last weekend I got in need to mod the minors a little, I just hated them being that important on low tech.
So I searched the forum a little and found this topic. First I didn't care about the jumping population, but at least wanted to lessen it alot. race.rst did the job, thx Gowron, but still the evolution level seemed to be too high for my preferred difficulty settings.
I thought of editing racetech.tec, didn't find much more about it than mentioned in this topic and started analysing it myself. Using UE to adjust all of them currently is a hell of a work and I just didn't realize it being in "Starting Conditions" tab. Cause I havn't found anything about it in the forum, I'll just post what I've figured and already was known.
A hex view width of 108 clarified the structure and having read about the bandi advancement bug I soon realized that on top of the file are just the addresses of all the contained entries stored. Having read about that already helped me alot!
With some analysing it came clear, that major races have 5 EvolutionLevel entries and minors have 10, like mentioned here by DCER as well.
Each entry has a length of 0x6C (=108 in dezimal as used for the view).
Relative to each entry, at position 0x00 comes the RaceID with length of 2bytes. The RaceID starts with value 0x00 and ends with 0x22, for all the 35 races. race.rst lists them in sequence without of the RaceID, but when searching for the corresponding line, race.rst will tell the race's name.
After the RaceID, the tech levels are following. Each research has a length of 8 bytes, the first two of them are for the actual level and the rest I dunno. Interestingly, they only matter for the initial buildings of the races, at least for the minors, cause I havn't tested the majors. I also realized that within my tests all minors initially have cardassian buildings and change them on first upgrade.
Next I searched for setting the succeeding upgrade levels and found out that they are read from the succeeding evolution level entry. They are stored at 0x47, relative to the entry start offset.
They really made me some headaches, cause it just didn't came clear to me how they are stored. I should have taken a look to the source of UE, cause UE already supports setting them. However, now I wonder why I didn't realize that earlier, but they are stored bitwise as flags.
First come the cardassian buildings, then the federation, the ferengi, the klingon and the romulan (obviously when having a look at the entries of these races).
For the buildings of each race there are 10 bits for the farms, 9 for the factories, 9 for the energy buildings, 9 for the intel buildings and 9 for the laboratories. This is causing the weird diagonal regularity and is why there are only letters of 0-8. It's hard to read but with knowing this, it should be comprehensible.
Farms have one flag more than the others, cause farms of type 0 are set with the tenth flag and other buildings just don't have a type 0.
Modifying these flags can cause downgrades as well. Setting more flag than one seems to result in the highest bit flag being recognized, setting just zeros causes no upgrading.
Then, cause this still didn't satisfy me. Especially with not having the mood to modify all these entries by hexeditng as well, I continued studying this thread. But I must say, UE currently doesn't simplify setting the technology achievements by much, for me it seems even more work than hexediting and it's less clear cause of having to scroll that much and the tech levels being accessed through a scroll down tab. sry
I would have prefferred ONE single page for each minor, listing all the EL entries in a table. Maybe two pages, one for the actual technology levels and one for the buildings. And buildings could be summed to just setting the level or disabling them cause a building can't have multiple tech levels at once. The energy buildings could have a third page cause, here setting all races at once seems to be a great future of UE cause you normally wouldn't want to have much differences.
A future to adjust multiple races would be great as well, but it'll be harder to implement this. Maybe by having a race selection scroll window on the left like it's available for the buildings in the building stats, but with multiple selection support.
Maybe you'll find time to improve it alittle, DCER.
I must say IDA free is a great tool, but it doesn't seem to support modifying or writing into the code at all. But I found OllyDbg that is free as well and supports editing the hexvalues as well as the asm code. Great tool, although the debugging crashes or freezes immediately after the intro on my vista laptop. Maybe I would just have to disable an automatic breakpoint, but with a frozen dx fullscreen window I can't get to see the debugger anyway. Havn't tested debugging with IDA, but DCER already mentioned it makes troubles on vista...
Anyway I can recommend OllyDbg, although I'm missing an option to save the code changes as well as the hex offsets. But OllyDbg automatically stores all modifications to an udd file, including added comments.
So I'm using OllyDbg for typing new asm commands plus writing comments, use IDA free for getting the hex position (cause every few times I miscalculate with doing it myself), and HxD for actually inserting the new hex values told by OllyDbg. If you have a better solution, please let me know.
So back to the topic.
I totally disliked the EL (evolution level) prediction function sub_451970 and completely removed it. It's only called on initialization at asm 43D26C so I just replaced it with five 'nop's 0x9090909090. The EL prediction value 0x5A2B2B being set by that function is being read at the single position 4530AA asm or 0x524AA hex only anyway. I replaced loading the value [A02B2B5A00] by a xor and some nops [30C0909090] so it always is zero.
There are two other references, writing to 0x5A2B2B. I dunno what they are about, but havn't encountered any issues on testing.
If level seems to be too low, it's still possible to adjust the racetech.tec entries, but remember there are just 10 entries for the minors, so it's great having some more to be used. I wanted to have less important minors anyway and prefer having more upgrade steps.
Of course it should be possible to create a new function for calculating the start EL, but space seems to be a problem, right...
(progressed analysing the functiones)
Not enough, having read this topic I wanted to try continuing where this topic has stopped. I'm not sure if it's a great idea to use this single function for upgrading AND population growth. But, unluckily, placing the growth somewhere else means that the buildings count won't get adjusted. This is whithin the building upgrade code portions.
However, to split it or fix the issues DCER encountered, first there is need to analyse the code some more. I've spent quite some time on it the last days and found out alot about. Hopefully some helpful stuff, cause I'm currently not about to finish this job.
I began with sub_4528A0 and labled it _updateMinorResearch. It takes the RaceID as argument compares it by 0x20 and splits the code sequence.
For races below 0x20 it loads address 5A2B50 and for races above it loads 5A2B54. It compares bitwise and returns if corresponding flag isn't set, so 0x5A2B50 and 0x5A2B54 must be the MinorPresenceTables. Didn't found anything about in the dyn key variable thread yet.
At 45291A asm I wondered about loading address 5B4330. It is added to the previous loaded DifficultyLevel and compared with the current race EL. If the race's EL is too high, it breaks and returns. Might it be the PlayerEL or something? dunno
However, at 45295C last check will take place for evolving. I think DCER already mentioned that some kind of remaining turn value is being used.
So at 4529D9 a function is called to actually evolve and upgrade the system. I labled it _evolveMinorSystem and it's again taking the RaceID as parameter, passing through the eax register.
Within that function, as Spocks-cuddly-tribble told, at 45237B another function gets called to build new ships. But let's go back to the top of this function.
In the beginning, again the presence of the minor get's checked by the MinorPresenceTables already mentioned. This test ends at 451F59. The compiler placed some code for RaceIDs > 0x20 at 452114 but let's ignore this.
After storing the new population number at 45207C asm, which has been figured by DCER, the minor planet terraforming gets adjusted with the function call at 452084. Not calling this function will cause minors increasing population above currently terraformed population capacity within their system!
(btw, DCER, did you figure the population numbers by debugging or was it long testing and a portion of luck? could need a working asm debugger as well
maybe I should try vc++, think it had an asm debugger included as well
Now, at 452090 asm, there begins the upgrading part. Here it becomes terrible cause of nested loops and a switch or something. Code that sometimes already get's hard to understand in high level language!
The first jump, the jge at 4520FD leads to a decision at 452143 that decides at 452157 weather upgrading of buildings is finished and it shall be progressed with ship building or weather the main loop, back at 452090 shall continue with new building type.
The second jump at 45210B instead tries to upgrade something.
It points to 4521B6, being part of a switch or a nested if/else construct.
In between, at 452104, there is a function call that determines the selected building's new tech level. It must be read out of racetech.rst within the called function.
At 4521C6 it decides if it's the right or the wrong type to upgrade and either jumps to the next case or breaks at 4521CA jumping to 452111 which is pointing back to 4520E4 cause there's nothing to upgrade, or calls function 452460 at 4521F7 to upgrade the farms and then going back to 4520E4. Placing nops at the farm upgrading function call causes them not to upgrade but doesn't affect anything else.
So if it hasn't been farms, it continues at 45220D, either jumping to 452241 if it's still the wrong building type or calling 452460 again but this time for upgrading the power plants and then jumping back to 4520E4.
In 452241, comes the research centers, being upgraded at 452279 by the call to function 452460. Interesingly, this time, it doesn't only get reffered to the next building type entry (at 45224A), but also, at 452269, it jumps to 4522BF.
But first to the last switch case 452284. This one is responsible for upgrading the factories by calling 452460 again at4522B4. I think we could call it the upgradeBuildingFunction. that function obviously must take the building type to upgrade as parameter.
Back to the interesting jump to 4522BF. I figured this to be the orbital building portion. At 4522F0 it actually calls function 445DF0 in a loop to build the orbitals. Placing nine nops can prevent this, BUT, that's not the only call to build orbitals! However, it is the main call to build orbitals.
Never would have figured in game that building orbitals is dependent on research facility upgrade for the minors.
When the building upgrade part is finished, going back to 45216C is another call to build ONE single orbital. Replacing it by nops as well as the looped call, totally prevents minors building additional orbitals!
It gets followed by a jump to 452173. This is the jump out of the main building upgrade loop. It gets us down to 452306, where the MinorPresenceTable get's controlled again. I'm not sure, but would think of it being checked for weather the race is a ship controlling race.
Anyhow, it get's followed by a call, testing for the number of ships to be build or something.
Then, finally, at 45237B the function to build ships gets invoked. It seems like it's taking register dx as parameter that reads in the RaceID that got stored somewhere in beginning. Havn't followed it further.
So that's my observations. I hope someone can use it and either seperate the population growth with adjusting building count or somehow fix the issues DCER encountered. I believe it wouldn't make troubles calling the building upgrading multiple times when moving the orbital upgrading out. It just seems to adjust to the current EL and population.
And depending the build of orbitals on research facility upgrades doesn't make much sense to me anyway.
BTW, I noticed some promising ASCII notes within the function responsible for turn progress, that also calls a function for updating research, that is calling the function I've labled _updateMinorResearch which is calling the labled _evolveMinorSystem function we've talked about. I labled it _makeTurn, it's to be found at 458260 and I'm sure you coders know about.
Just am surprised about all the notes like "AIProcessTurn", "LaborProcessTurn", "_turnResolveEconomyPhase", "_turnResolveMilitary", "MonsterProcessTurn", "GameSave", "IncidentReportTurn",...
Not having known about, that's just fantastic to see all these notes within the make turn function!
Oh, *hrm*, well, day over again.
Tomorrow I must program again, although I really enjoy all this modding stuff.
Edit: sry, OllyDbg showed me much empty space where is none. Got trapped by the asm to hex conversion.