ShortenedName Posted October 26 Share Posted October 26 (edited) I'm currently in the early steps of a translation project for Tokimeki Memorial 3: Yakusoku No Ano Basho De. Right now I am making a tool for extracting the game's script. I have extracted the file system from the .iso. It has five .BIN files which contain all of the game's assets. At first I extracted text from Data5.BIN, as it contained uncompressed text that simply needed to be filtered from the other data. This text is almost exclusively for menus, which means the dialogue must be stored in the other .BIN files. When viewed in a hex editor, it becomes clear that the other data files (Data1.BIN - Data4.BIN) contain a large amount of compressed files with the header ATP. I know some of these contain dialog, because I can see scattered bits of Shift-JIS strings, some of which line up with dialogue I've seen in-game. Using a combination of the PCSX2 debugger and Ghidra I was able to identify where the compressed files are stored in memory when they are loaded off the disk and the function that is responsible for decompressing them. I've recreated this function in my toolset and it runs/exits without crashing but I don't think the decompression is working. It seems to have the following issues: Sometimes there are no changes between the compressed and "decompressed" ATP file (it's possible that this means the file's content was never actually compressed to begin with) Oftentimes the strings appear more jumped in the "decompressed" version than the compressed version. It doesn't stop when it needs to, running into the next ATP file and stopping halfway through "decompressing" that. Here's the assembly function taken from the PCSX2 disassembler: lbu a3,0x0(a0) addiu a0,a0,0x1 daddu t1,a1,zero addiu t0,zero,0x8 bne t0,zero,0x001E93F8 andi v0,a3,0x0001 lbu a3,0x0(a0) addiu a0,a0,0x1 addiu t0,zero,0x8 andi v0,a3,0x0001 bne v0,zero,0x001E9418 addiu t0,t0,-0x1 lbu v0,0x0(a0) addiu a0,a0,0x1 srl a3,a3,0x01 sb v0,0x0(a1) beq zero,zero,0x001E93E0 addiu a1,a1,0x1 bne t0,zero,0x001E942C srl a3,a3,0x01 lbu a3,0x0(a0) addiu a0,a0,0x1 addiu t0,zero,0x8 andi v0,a3,0x0001 beql v0,zero,0x001E9498 lbu v0,0x0(a0) addiu t0,t0,-0x1 bne t0,zero,0x001E9450 srl a3,a3,0x01 lbu a3,0x0(a0) addiu a0,a0,0x1 addiu t0,zero,0x8 andi v0,a3,0x0001 srl a3,a3,0x01 addiu t0,t0,-0x1 bne t0,zero,0x001E9470 sll a2,v0,0x01 lbu a3,0x0(a0) addiu a0,a0,0x1 addiu t0,zero,0x8 andi v0,a3,0x0001 srl a3,a3,0x01 lbu v1,0x0(a0) addiu a0,a0,0x1 addu v0,a2,v0 addiu t0,t0,-0x1 bne v1,zero,0x001E94E0 addiu a2,v0,0x2 beq zero,zero,0x001E94E0 addiu v1,zero,0x100 addiu a0,a0,0x1 lbu v1,0x0(a0) addiu a0,a0,0x1 sll v0,v0,0x08 srl a3,a3,0x01 or v1,v0,v1 beq v1,zero,0x001E9510 addiu t0,t0,-0x1 andi a2,v1,0x000F beq a2,zero,0x001E94D0 addiu a2,a2,0x2 beq zero,zero,0x001E94E0 srl v1,v1,0x04 nop lbu v0,0x0(a0) addiu a0,a0,0x1 srl v1,v1,0x04 addiu a2,v0,0x1 beq a2,zero,0x001E93E0 subu v1,a1,v1 lbu v0,0x0(v1) addiu v1,v1,0x1 addiu a2,a2,-0x1 sb v0,0x0(a1) nop bne a2,zero,0x001E94E8 addiu a1,a1,0x1 beq zero,zero,0x001E93E0 nop nop jr ra subu v0,a1,t1 and here's my attempt to recreate it for my tool set . I apologize in advance for the poor readability public static void DecodeATP(int startAddress, byte[] byteArray, String outputPath) { //Note to self: when implementing this, use integers that refer to indexes on the array as "pointers" //Use labels and gotos for the parts byte[] destination = new byte[byteArray.Length]; uint sourcePointer = (uint) startAddress + 8; //a0 in the assembly, skips 8 to avoid the ATP file header //set up a few variables to take the place of some registers in the original assembly uint v0 = 0x0; uint v1 = 0x0; uint a2 = 0x0; byte previousByte = byteArray[sourcePointer]; sourcePointer++; uint destinationPointer = 0; uint counter = 8; byte buffer; Part1: //Part1 v0 = (byte)(previousByte & 0x1); if (counter == 0) { previousByte = byteArray[sourcePointer]; sourcePointer++; counter = 8; } else { goto Part2; } Part2: //Part2 counter--; if (v0 == 0x0) { buffer = byteArray[sourcePointer]; sourcePointer++; previousByte = (byte)(previousByte >> 0x1); destination[destinationPointer] = buffer; destinationPointer++; goto Part1; } else { goto Part3; } Part3: //Part3 previousByte = (byte)(previousByte >> 0x1); if (counter == 0) { previousByte = byteArray[sourcePointer]; sourcePointer++; counter = 8; } else { goto Part4; } Part4: //Part4 v0 = (byte)(previousByte & 0x1); v0 = byteArray[sourcePointer]; if (v0 == 0x0) { goto Part7; } else { counter--; previousByte = (byte)(previousByte >> 0x1); if (counter != 0){ goto Part5; } previousByte = byteArray[sourcePointer]; sourcePointer++; counter = 8; goto Part5; } Part5: //Part5 v0 = (byte)(previousByte & 0x1); previousByte = (byte)(previousByte >> 0x1); counter--; a2 = (byte)(v0 << 0x1); if (counter != 0) { goto Part6; } else { previousByte = byteArray[sourcePointer]; sourcePointer++; counter = 8; goto Part6; } Part6: //Part6 v0 = (byte)(previousByte & 0x1); previousByte = (byte)(previousByte >> 0x1); v1 = byteArray[sourcePointer]; sourcePointer++; v0 = (byte)(a2 + v0); counter--; a2 = (byte)(v0 + 0x2); if (v1 == 0) { v1 = 0x100; } goto Part9; Part7: //Part7 sourcePointer++; v1 = byteArray[sourcePointer]; sourcePointer++; v0 = (byte)(v0 << 8); previousByte = (byte)(previousByte >> 0x1); v1 = (byte)(v0 | v1); counter--; if (v1 == 0x0) { goto Part11; } else { a2 = (byte)(v1 & 0xf); a2 = a2 + 0x2; if(a2 == 0x0) { goto Part8; } else { v1 = (v1 >> 0x4); goto Part9; } } Part8: //Part8 v0 = byteArray[sourcePointer]; sourcePointer++; v1 = (byte)(v1 >> 4); a2 = (byte)(v0 + 1); goto Part9; Part9: //Part9 v1 = (byte)(destinationPointer - v1); if (a2 == 0) { goto Part1; } else { goto Part10; } Part10: //Part10 v0 = byteArray[v1]; v1++; a2--; destination[destinationPointer] = (byte)v0; destinationPointer++; if (a2 != 0x0) { goto Part10; } else { goto Part1; } Part11: destination = SubArray(0, (int)destinationPointer, byteArray); File.WriteAllBytes(outputPath, destination); return; } Could anyone help me identify where the problem is? Edited October 26 by ShortenedName Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now