FBA-rr 0.0.7 implements some new Lua functions:
memory.registerexec | trigger a function when a given code is executed |
memory.registerread |
trigger a function when given memory is accessed |
memory.registerwrite |
|
memory.getregister |
read from and write to the CPU registers |
memory.setregister |
This effectively makes breakpoints and watchpoints available from within Lua. You can thank mz for these developments.
Most of the scripts have been updated to use these functions where applicable. In particular, if you want to see the CPS2 and Marvel throwboxes without messing around with MAME-rr, now you can.
In fact, the old method of piggybacking on the MAME-rr debugger has been removed, because I oppose writing to memory when the script is supposed to be read-only. So you have to use FBA for the bp/wp functionality now, but MAME still works for everything else.
The exceptions are garou-hitboxes.lua, since FBA's Lua can't control the NeoGeo's bank switching, and cps3-hitboxes.lua, since the new functions don't support the SH2 processor, although it's only one breakpoint at stake there. (It may be possible to get garou working in FBA by getting to script to read the box parameters exactly when the game's program does, which would obviate bank switching.)
The overhaul process was unexpectedly painstaking:
missing boxes
The most enigmatic problem was the way throwboxes would randomly fail to be displayed. I confirmed that the breakpoints were getting triggered properly, and besides this happened even in cases that don't rely on breakpoints. I never found the cause, but the solution was to set up a special throwbuffer, separate from the framebuffer. Throwboxes are stored there by the emu.registerafter
routine and read from there by the gui.register
routine. Rather than incrementing the progression of time with each execution of registerafter
, every throwbox is keyed with a spawn time determined by emu.framecount
and cleared from the buffer when the spawn time falls behind the current framecount.
feedback loop
registerread
and registerwrite
can be triggered by memwatch or Lua actions rather than just the emulated system's own operation. Besides getting a lot of unwanted callbacks, that tends to cause stack overflows. In fact, the MAME-rr debugger's watchpoints have the same problem. Put a watchpoint on a memwatched address and you'll get a seemingly nonsensical break on every frame. Avoidable but annoying.
write delay
When you put a watchpoint on a memory address, the contents don't actually get updated until one opcode after registerwrite
triggers. If the callback function needs to read from said address, it's getting data that immediately becomes obsolete.
A workaround: if the data is coming from a known register or place in memory, read from that source instead. This script for sfa3 demonstrates the discrepancy by printing out the contents of the relevant memory address and its source register whenever P1 attempts a throw: The memread only gives the correct result if you do the same throw successively.
Another workaround is to find another address that gets read from or written to immediately after the address of interest changes. This is situation-specific and not always available. I found such addresses for the sf2 and kof scripts, although nothing analogous was available for World Warrior, and the user has to do the same throw at least twice to get the box to look right.
The final solution is to simply not use registerwrite
, using registerexec
instead. This exposes me to either the inelegance of making the code clone-specific or the aggravation of finding offsets for every clone. I wanted to avoid this.
vsav corrections
Command throws in vsav, vhunt2 & vsav2 won't come out unless you are already in range when they are input. The throw is first simulated at input time and, if the check is successful, it doesn't happen for real until after the startup. In the previous script version, the simulation routine was triggering the same as a real attempt and causing false boxes.
This has been corrected, but to make it easier to see them, another breakpoint has been added to allow attempts to come out at any range. This was kind of difficult because the same range check is used to determine if actual attacks and throws connect. The callback has to look at the stack pointer to ensure it only interferes in the right situation.
A similar but unrelated problem is the normal throws of some characters like Jedah and Q-bee don't get attempted unless you input them from real close. To get around this you can use a cheat code to force the word at 0xFF8530 and 0xFF8930 to zero.
Wow. You know what it was with the "missing boxes"?
Try running this simple script with any game:
gui.register(function()
emu.message(emu.framecount())
end)
If Audio > Plugin options is set to disabled, it increments twice per frame advance, which screws up my measuring stick. I had retuned the scripts to work with muted audio, and now they act funny with the audio on. Dammit.
Posted by: dammit | 11/13/2011 at 10:01 PM
I just realized I forgot to give you the stand locations since Jojo's on a technical level is a 2v2 game.
0x020350CC, Player 1 stand.
0x020354EC, Player 2 stand.
Posted by: Jedpossum | 11/14/2011 at 10:02 AM
And a correction to Jojo's Venture Locations
0x02030448 - Player 1
0x02030868 - Player 2
0x02030C88 - Player 1 Stand
0x020310A8 - Player 2 Stand
Posted by: Jedpossum | 11/14/2011 at 01:26 PM
Thanks again for all of your hard work! I would follow but I don't have a facebook account so it won't let me follow >_>
You're doing great! Keep up the good work!
Posted by: Miloyoyo | 11/14/2011 at 02:14 PM
Last thing i'm going to post.
http://i.imgur.com/Yf0il.png
http://i.imgur.com/7mf0a.png
Posted by: Jedpossum | 11/14/2011 at 05:08 PM
Hey there dammit, I was wondering, have you ever thought about making a fighting game?
I kinda wonder what you do as a job
Posted by: CWheezy | 11/21/2011 at 10:47 PM
Well, my real interests aren't with games, even less so with selling them.
I do this stuff because it's the most challenging thing I can get my hands on given the availability and low cost, and this challenge is intended to be proof that I'm worth something to the field I want to get into. (It's not working. Life hasn't been good, let's leave it at that.)
Posted by: dammit | 12/19/2011 at 01:24 AM
Now I'm a little curious what field you're trying to get into.
Posted by: Rufus | 12/22/2011 at 10:55 AM
I'd rather not get into that.
Posted by: dammit | 01/02/2012 at 12:55 AM