Настроение: | accomplished |
Entry tags: | computing |
Today's Decompilation Progress
Began work on the STRONG.DAT dumping utility.
That is not a normal archive file, but more of an asset stash.
At least that is what the error handling code calls it.
It does have a table of contents, but it just associates ids with entries.
For example, during the grab phase, *.voc files were preprocessed for DIGPAK,
The lbms were broken into animation frames, these frames RLE encoded.
The entire grab process, including number of frames, was hardcoded into the executable.
That is an efficient way to do it.
For example when drawing text, one doesn't have have to load or parse entire font.
Just the required letters.
The game also uses a ring buffer, which gets garbage collected, after each operation.
The proper dump will require first relating data with the source files.
One funny thing: the game appears to be using 0xA000 graphics area for temporary storage of loaded font letters.
All in all, I got through the init_game() routine.
void init_game() {
_OvrInitExt(0,0);
_OvrInitEms(0,0,0);
init_base();
init_paths();
init_cfg();
clrscr();
srand8(*BDA_DailyTimeCounter);
stshAlloc(0xfa0f); //0xfa0f = special stash init value
if (!strcmp(GExeArg,"debug")) GDebug = 1;
if (!strcmp(GExeArg,"grab")) {
GDebug = 1;
process_strong_dat(true);
} else {
process_strong_dat(false);
}
stshInit();
StrongDat = stshOpen(0); // 0 = STRONG.DAT
sfxInit();
musInit();
gfxInitRand();
miceInit();
biosVideoCall(0x0,0x13); // Ask bios for 320x200x8bpp
init_min_palette();
init_palettes();
init_buffers();
clean_ring_buffer();
heapInit();
play_sfx(0x53,0); // play 33.voc
return;
}
Unfortunately the process_strong_dat() there will need some python script to parse.
I already had to write a simple script to dump the filenames.
# For each of the 544 seg:ofs far pointers at the current address,
print associated 0-ended C-string:
def getCstr(addr):
s = []
while True:
try:
c = getByte(addr)
if c == 0: break
s.append(chr(c))
addr = addr.add(1)
except MemoryAccessException:
break
return ''.join(s)
adr = getState().getCurrentAddress()
for i in range(544):
sadr = toAddr((getShort(adr.add(i*4 + 2)) << 4) + getShort(adr.add(i*4)))
print(getCstr(sadr))
but scripting Ghidra is easier than using Java.