ASM Tutorial Using PPSSPP
Get to this scene:
Save the state. In PPSSPP, F3 cycles through five save states and F2 saves the state. F4 is used to load the state.
Reference the RAM map for this game. You can find it where it says "internal data" at the bottom of this page; the same applies for other games on Data Crystal.
For this tutorial, we are interested in narrowing the font width. From the RAM map for this game, we see that 0x088A3858 is loading the x-spacing value. We're going to make it a lot narrower.
Open the debugger by pressing CTRL+D. Note that you can open the debugger with emulation paused too, if you want. Don't get too scared just yet.
Explaining the debug window. First the main parts.
On the left are registers. We can talk more about registers if you want in another tutorial. A register holds a value that is ready to be used by an instruction. In RISC like the PSP's R3000, values have to be in a register to be used by the program.
To the right of the registers is the program window. It shows a disassembly of the program.
On the bottom is the memory view window, and it has some tabs with other functions that we'll get to in another tutorial.
Now more advanced stuff.
If you click funcs above the register window, it will display a list of detected functions from the disassembly. You can double-click any function to jump the program window to the start of that function. Try that now (pick a random function).
Above the program window are function buttons that say stop/step into/step over/step out/next HLE, breakpoint. Stop stops emulation. When you click it, it will change to "Go" and click this will restart emulation. "Step into" steps through the program one instruction at a time. "Step over" is similar to "Step into" but for functions, instead of stepping into a function, it will execute the function and leave you where that function returns. "Step out" executes the program until the next return. I don't know what "Next HLE" does. "Set breakpoint" will mark a place in the program. Each time the program arrives at a breakpoint it will stop execution similar to pushing the "Stop" button.
Please go ahead and hit the "Stop" button now.
Now we need to go to the place in the program where it is loading x-width. Click on any instruction in the program window. Now push CTRL+G and copy and paste the address: 0x088A3858 and push enter. You will see that the instruction at the specified address has been jumped to and highlighted. Double-click on it to set a break point. Now click run.
You see that the execution is continuing without hitting our break point. This means that our break point is not being hit. That is, that instruction is not being executed during the current game loop.
Pick up the controller and advance the dialog by pushing O. You will see the execution halt.
Do you see the [08B28F68] = FFFE at the bottom? This is a lh "load halfword" instruction. It says to load the half word at the address in register s2 plus an offset of 0x8 and place the contents in register a3. Just as a side note the "a" registers a0, a1, a2 and a3 are often used by compilers for passing function arguments. Back to the tutorial. 0xFFFE corresponds to a value of negative 2.
We did not actually need to do anything there though, clear the break point by double-clicking it. Then click in the PPSSPP emulation window and press F4 to load the state you saved earlier.
Now we need to get ready to modify the program. Halt emulation by pushing the "Stop" button, then navigate to the key address by pressing CTRL+G and copy and paste the address: 0x088A3858. Now we need to modify the program. Right-click the highlighted instruction, then select "Assemble opcode." We are going to write our own assembly instruction on top of this one to modify the program. The instruction we want is li a3, -10. li is load immediate. Immediate means a value that we, the programmer, specify (i.e., not a value in memory). Load means we are going to place the value in a register. In the box, enter li a3, -10. I need to refer you to the MIPS manual for opcode formatting, but a space always goes after the opcode. A comma goes between all operands that are not offsets. The two operands for the li instruction are the target register and the value we want to load.
Now that we're done modifying the program, we need to now run it and observe the effect on the game. As we saw before, this instruction does not get hit when text is on the screen; it only gets hit when displaying new text. Click run, then push O on your controller to advance the dialogue to observe the results. All the characters on top of each other!
I don't want to conclude the tutorial just yet. If you like this, you can select a new save slot with F3 and then save the state. You can then restore the program to how it was earlier using F3 to select the previous state and then F4 to load. Advance the dialogue with O and observe how your changes have been undone. It's always a good idea to save your state when making changes because crashes will result from assembly code errors.
That concludes this tutorial. I hope you enjoyed it. Please feel free to edit this tutorial to provide clarifications or use the talk page for feedback. Thanks, flame
|Internal Data for Blaze Union|