Show whole topic Oct 05, 2008 9:59 pm
Artlav Offline
Approved Member
Registered since: Jul 16, 2008
Location: Moscow


Subject: Re: resource stripper help
Quote by shaktazuki:
My next step is to also output the amounts. This will take significant effort.
Why should it?

Quote by shaktazuki:
I wrote the bmp writer and I still didn't know exactly how it works.
You wrote a BMP writer without knowing about how it works?
Nicely done, considering that it seem to work well.

Quote by shaktazuki:
I only knew the resource masks / amounts / offset. I wish I knew the rest - if you have a description of the savegame format, I'd like to get it.
The whole format description does not exist yet.
I've decoded a big deal of it, but there are still lots of blind spots.

At the start, a word of version - 0x0046 for 1.04, 0x0045 for 1.56.
Then, a header:
DownloadSource code (Text):
  1. struct header104 {
  2.  game_type:byte;                        //0 - Singleplayer, 2 - Campaing, 3 - Multiplayer, 5 - Demo
  3.  game_name:array [0..29] of char;       //Game name
  4.  map_id_1:byte;                         //Map ID, first entry. Some entries are duplicated, can only speculate why.
  5.  level_num:word;                                //Campaign number, or something like that              
  6.  
  7.  //Player names
  8.  red_name,green_name,blue_name,gray_name:array[0..29]of char;
  9.  
  10.  //Player types: 0 - Absent, 1 - Human, 2 - Computer
  11.  red_type,green_type,blue_type,gray_type,alien_type:byte;
  12.  
  13.  unk104:array[0..4]of byte;             //Unknown array, only in 1.04
  14.  creation_time:dword;                   //Timestamp
  15.  cpuiq1:byte;                           //CPU level, first entry
  16.  
  17.  //Times of turn and end of turn, first enries
  18.  time_of_turn_1,time_of_end_turn_1:word;
  19.  
  20.  turn_mode_1:byte;                      //Turn mode: 0 - 'Turn Based, 1 - Simultaneous
  21.  map_id_2:dword;                        //Map id, second entry
  22.  time_of_turn_2:dword;          //Time of turn, second entry
  23.  time_of_end_turn_2:dword;              //Time of end turn, second entry
  24.  sgold:dword;                           //Starting gold
  25.  turn_mode_2:dword;                     //Turn mode, second entry
  26.  type_of_end:dword;                     //End condition: 0 - Turns, 1 - Score
  27.  amt_to_end:dword;                      //End condition amount
  28.  cpuiq2:dword;                          //CPU level, second entry
  29.  start_raw:dword;                       //Starting raw
  30.  start_fuel:dword;                      //... fuel
  31.  start_gold:dword;                      //... gold
  32.  start_alien:dword;                     //... aliens
  33. }
(Not exactly C++ syntax, but the structure is preserved)

After that, pass map - one byte per cell passability, then resource map as described above.
After the maps - player information: red, green, blue, gray one after another:
Here the blind spots become more obvious
DownloadSource code (Text):
  1. struct playerinfo{
  2.  FF1:array[0..39]of byte;               //Filled with 0xFF, no idea about meaning
  3.  plr_type:byte;                         //Player type, same as in header
  4.  unk0:byte;                             //Blind spot 1
  5.  clan:byte;                                     //Clan ID: 0 thru 7, sequenced as in the game.
  6.  
  7.  research:array[0..7]of resinfo;        //Research info, 12 bytes per type, with types going from top to bottom
  8.  //first dword - now researched, second dword - unknown, third dword - labs allocated
  9.  
  10.  score:dword;                           //Score
  11.  unk2:word;                             //Blind spot 2
  12.  unkarr1:array[0..92]of byte;           //Unknown again
  13.  FF2:array[0..11]of byte;               //Filled with 0xFF, no reason why known
  14.  unk1r:array[0..97]of byte;             //And another unknown
  15.  unk3:word;                             //Followed by one more unknown
  16.  selunit:word;                          //Selected unit id
  17.  zoom,xoff,yoff:word;                   //Zoom and offsets of the visible area
  18.  buttons:array[0..10]of byte;           //UT button states
  19.  unk4,unk5,unk6,unk7:word;              //Some more unknown values
  20.  loses:array[0..175]of byte;            //Loses of the player, one byte per unit
  21.  unk2r:array[0..9]of byte;              //Something...
  22.  goldused:word;                         //Gold used during the game
  23. }

That ends the static part, the stuff downrange from here goes somewhat cryptic.
There are unit updates tables, unit objects, updates objects, construction objects, all without an obvious structure i can cleanly define, the most common being - a word for object id, object type, object record. But there are also size-like intermittents in the stream, i can't find out the sequence of, only ignore.
It can be read nicely enough to do basic conversion to MGA in about 90% of times, but a lot is being lost and not known yet.

After the units part, there are scan maps and message log of some sort.

The current state of my save-game reader.
This one comes with both 1.04 and 1.56 version support, unlike the above one, that only worked on 1.56.
http://www.rumaxclub.ru/etc/maxse_081005_all.zip

.
Artyom Litvinovich
This post has been edited 1 times. Last edit on Oct 05, 2008 10:01 pm by Artlav.