dockthepod posted on Jul 13 2006 at 12:58 AM said:
Yeah, I was wondering that as well. Is the GBA ARM (ARM7?) not compatible with the GP2X one (ARM9?)?
Also, how I read it... you translate to C as you actually play the game initially? Or did I read that wrong? Because... that makes no sense to me. I don't see how every code path could get exercised. You must be loading up the CODE portion of the rom and decompiling it.
Do a search for static recompilers. It is/was a yahoo groups thing. Graham Toal did a very nice writeup that summed up what a number of us were doing at the time on the subject.
The ARM in ARM mode is beautiful, one 32 bit word per instruction, no more, no less, easy to disassemble, easy to convert the disassembly to C.
Take any variable length ISA (instruction set architecture) and try to do that. You will find that you cannot, there is always going to be data embedded in the code, that data can fool you into thinking you have found another branch instruction which leads you to an address that you think has an opcode. You can only get so far with a simple disassembly approach (actually you get nowhere if you simply start at one end and disassemble).
Here is one thing I did on the 6502. Start with the reset vector, this gives you an address. Add that address to your list of addresses that contain opcodes. Make a pass on the rom dissassembling from every address in your list and stopping each instruction chain when it hits an unconditional branch. As you go through each instruction sequence make a note of all conditional branch destinations as valid opcodes. Repeat this over and over again until it cannot find any new branch destinations. What I found, at least with Asteroids, is that I would have an address in the list that pointed to a three byte instruction, but some other address in the list pointed to the the second or third byte in that instruction, which is impossible. It made sense once I figured out one/some of the sources of the bad addresses. I dont remember exactly what it was now, but if for example the compiler and or assembly programmer chose to preced a conditional branch with an instruction that would guarantee the branch, thus making the instruction pair an unconditional branch, then follow that with some data that when disassembled gets you out of sequence with the instructions that follow it, it goes down hill from there. If you are lucky you may end up with every single byte in the rom as an opcode even if the processor has no single byte instructions.
Eventually you figure out that disassembly (of a variable length ISA) cannot reach every execution path and have to search for another solution...Hmm, like executing in an emulator and making a note of every execution path.
You dont have to play test in the emulator to build an opcode list, but it will save you a considerable amount of time. I think you have to build your translation or test translations such that instruction sequences that dont end in a branch fall into a handler that halts execution and displays information about where the halt occured. This is actually pretty simple, once you have your opcode list, then disasseble the rom from the beginning to end. Any bytes that are not part of an instruction generate code that calls a handler passing in the rom address of that byte. Then you can manually examine the disassembly near and at that byte (had it been considered an instruction) and determine what to do.
On a variable instruction length architecture I argue you have do this process for every individual rom.
Anyway with the ARM, so long as you know there is no thumb in there, it is super easy.
Now here is a problem, we are talking about a platform (GBA) dominated by thumb mode. Thumb mode cannot stand on its own it will periodically have to switch to arm mode to do some things then back to thumb, nothing you can do about that. So even on this translation, you are dealing with a variable length ISA. So back to plan, A, play test the emulator some, capture some addresses, disassemble and translate some, play the translation some, back and forth.
Another thing here is that you have to go through and hand type C code for hundreds of opcodes (depending on the ISA), this is boring and error prone. Which means your translation is buggy. There are variations on this theme, but basically you have to run the emulator and translation along the same instructions and compare something, register contents and/or memory reads and writes, and/or condition registers, etc. When you get a mismatch you have to sort it out, fix the translation, start again. I chose to do it by running the emulator and logging all of this information to a file, Then running the translator and comparing the emulation output to the translated output. The solution I liked but didnt try myself was to run the emulation and translation at the same time in essense and compare cycle for cycle, this allows you to run infinitely. My solution started to fall apart as the files got into the gigabytes (Well I assume the magic 2gb to be exact).
I know at least during a 4kbyte gba coding competition many were trying to take advantage of the built in compression in the gba. Their program would start by decompressing the rest of the program into ram then branching to the decompressed program in ram. Try and disassemble that. Even playtesting that in an emulator will knock your socks off at first, wait the rom is here and this is executing there, what is going on!
Also it was not uncommon, at least in the developer groups. to talk about moving some code into the fast ram for performance, the heavily used or code that needed to execute fast. A pure disassembly of this code when it is sitting in the rom as data, before it is copied to ram to be executed, will disassemble wrong.
Any of the programs that are multiplayer require that the client version at least runs strictly out of on board ram. This entire program as it were would live somewhere in the rom at the wrong address, this will disasseble wrong, only executing in an emulator will sort this out (actually you might never sort this one out as you might have to simulate the master to slave transfer to figure out what gets transferred and where).
This project, at least from a translation standpoint, just keeps sounding harder and harder.