Joined: 2/24/2010
Posts: 22
Location: Turku, Finland
I've been searching for RAM addresses in a couple of games and it seems really awkward at times.
For example, when I try to find enemy health during a hit in some games I cannot get a single value that is logically reduced in +-3 frames. I've tried searching with unsigned and signed values, so I'm wondering what's next. Can the health be scattered through various addresses and if so, how can I effectively find them? Or maybe there's an address that tells the enemy's max hp and another address that counts the inflicted total damage? Anyway, any tips would help a lot... And oh, I've been only searching for addresses in NES and SG games so far.
The only game I've seen that had really wonky hitpoint storage was Darius Twin. The game used some kind of pointer scheme, presumably because of how enemies stream in and out in large waves without necessarily being deleted at any given moment. You couldn't track the HP of any one enemy for more than a few seconds, because they all kept shifting around in some arbitrary looking way that I never uncovered.
Solar Jetman stored the lo and hibyte of a few 16-bit values in two non-consecutive addresses. They might be offset by 32 bytes, or some non-rounded, non-power-of-two number. If you're dealing with a number greater than 255, that's something to look out for on NES games.
Rock and Roll Racing had the quirk of storing the amount of bonus money the player had picked up off the race track using the last 4 bits of one byte, and the first 4 bits of the byte following it. If you can roughly infer the amount of HP your search target has, you might be able to test for such a scheme.
Practically speaking, you might try generalizing the search to simply use inequality, rather than risk being misled by any assumption.
One other piece of advice, which tends to be too advanced (or at any rate, too daunting) to be of practical use to a layman is to automate (or at least accelerate) RAM searching using Lua scripting. If you're a programmer or CS student, it might be worth looking into. I can give you some starting-off code if you're interested.
I or someone else here may even have tinkered with the games you're working on, so you could mention them by name.
I guess I should also disclaim the accuracy of all the trivia I've described. It's old information that I used once and let lapse. I just didn't want to put "IIRC" in every goddamn sentence.
Joined: 2/24/2010
Posts: 22
Location: Turku, Finland
Thanks for the enlightening reply. I'm currently working on Ghostbusters on SG as my first full TAS, so my questions emerge mainly from that game at the moment.
That may be the case since the enemy in this case shakes numerous leaves out of its body that all seem to have an individual HP. Hitting the leaves seems to also damage the enemy's total HP but I can't tell for sure. A room before encountering this leaf-enemy the player faces a miniboss that has a separate HP for head and body but those two parts have constant addresses for health points, so the game's HP tracking in different bosses is either varying or then I didn't search deep enough.
There's also another similar enemy in the game in a room filled with flying flesh-eating plants that work in a similar way to the leaves in the boss mentioned above. I couldn't read the HP of the main enemy in that room either.
Cool. Thanks for these priceless advices. I'll implement those methods into the search process.
Yeah. Inequality has worked fine until these latest efforts so Lua scripting seems to be inevitable (or at least a huge help) in some cases. I'm a programmer so scripting shouldn't be a problem. I haven't gotten into Lua yet though for I'm new to this environment, so any example scripts would be great to begin with!
Awesome. I'm going to show you two scripts. The first is a library of functions for doing RAM searches, and the second is an example that uses the library... sort of. In retrospect, I'm not pleased with my abstraction. But hey, it got the job done. ;)
The library defines a few functions: "makemem", "scanmem" and "display". makemem returns the complete RAM, which you store in a Lua table. The nice thing about this is that you can have as many of these tables as you want— the standard cheat search tools only let you have one search active, so far as I know.
Again, looking back, I wish I'd added these functions to the existing table of "memory" functions. That would have made so much more sense. :(
Anyway, scanmem implements the standard search operators. You can, of course, extend it to search by any kind of logic.
Lastly, display describes how the found addresses should be shown to the user— hopefully in a way that doesn't draw out of bounds or anything crazy like that.
The second script I linked defines the keys to do the searches, and a toggle key to display or hide the results. I haven't used it in months, but it seems to still work. Both scripts were written for FCEUX, but changing them to work with GENS shouldn't require anything more than changing the max memory range and hotkey mappings.
Using the functions built into the emulator, you can also automate the process of searching— there are functions for frame-advancing, sending gamepad input to the emulator, as well as savestate handling. There should be a complete reference of emulator functions packaged with GENS.
I think that covers everything... except the basics. There should be some more example scripts included with the emulator, which will hopefully make everything clear.
Joined: 2/24/2010
Posts: 22
Location: Turku, Finland
It seems that my journey into the world of TAS is only in the very beginning. Thanks for all the helpful info since now I'm even more excited about this. I'll return to you or the corresponding forums once I've studied enough and need more tips.
Joined: 2/24/2010
Posts: 22
Location: Turku, Finland
I was able to read the stage boss health in Ghostbusters and it didn't eventually need any scripting. I was distracted before because the middle bosses can be damaged at every frame but the stage bosses seem to normally take damage at only every 11 frames. So, thanks to inequality this case is solved.