Post subject: Finding pointers to enemy locations that respawn
Joined: 5/4/2005
Posts: 502
Location: Onett, Eagleland
I was playing Cadash on Mame-rr (Always loved this game on TG16, which was a superior compared to the genesis version) and I found some enemy X/Y locations. In cadash, you can walk away from the enemy spawn point just a little bit, and then walk back and the enemy will respawn, however the memory address for that enemy is somewhere else, even though the spawn point was the same, the enemy can also be a different type, but still come from the same spawn point. I'm pretty sure the game uses a pointer (possibly multi-level) to point to the address of the enemy that is on the screne, I wrote a lua script to display them, but say there is an enemy later on in the stage, if I have the luascript monitoring that memory address, it returns a null value. I think people who do side scrolling shoot-em-ups have experience with this sort of issue. So how do I go about finding the pointer that displays what memory address is being looked at for enemy x/y coordinates, and how do I make it only display IF there is an enemy on the screen. I hope this makes sense and if it doesn't please clarify where you're confused and I'll do my best to elaborate, thanks!
I think.....therefore I am not Barry Burton
Joined: 10/20/2006
Posts: 1248
Every enemy always needs to have a certain memory space reserved for it, where its x/y coordinates and also much more than that will usually be stored. Usually, each enemy will take up a fixed space per game (maybe about a 0x0100 range in address space). For older systems, there'll usually be a maximum enemy count and the game would have space reserved for the space one enemy needs multiplied by that count. Let's say all enemy info is stored from 0xC000 to 0xD000, then there'd be space for 16 enemies in the memory max (because 0x0100 * 16 = 0x1000). Now, there's multiple ways in which the game could determine if there currently are active enemies on screen: a) The information if an enemy is active is stored inside that 0x0100 wide range in the form of a certain value (a flag) that'll change depending on that. b) The information if it's active is not stored inside that 0x0100 wide range, but you can find a pointer/offset to where it's actually stored somewhere inside that range. (This is unlikely in your case. A system like that would typically be used to permanently mark an enemy as dead, without it ever respawning again) c) The information if it's active is stored somewhere totally else in the memory, in the form of several pointers/offsets to the 0xC000 - 0xD000 range. Invalid values could then mean that the enemy is not active. If it's a pointer to enemy number 3, it'd read 0xC200 (or 0x00C2) in our example, if offsets are used, you'd have to search for 0x0200 or 0x0002, depending on how they are implemented. You'd probably find a combination of these methods, or even something totally different. So, to find out how your game handles it, I recommend locating an easily findable variable, like x position of at least 3 enemies at first (should be three different addresses). The difference between the most distant ones should give you a minimal address range of the space that's reserved for enemies in the memory, the third one should give you a hint at the space each enemy takes up. From that point on, I recommend trying to understand what each of the variables in that space do. More than likely, you're eventually going to come across a variable that'll determine whether the enemy is active or to a pointer/offset to another memory location. If you don't, then it's probably case c. Let's say, you find the x-position of one enemy at 0xC644 and another one at 0xC244, then 0xC600 and 0xC200 or 0x0600 and 0x0200 are the values you should be looking for, as the pointer won't directly point to the x-position, but to the beginning of the memory range that's reserved for each respective enemy. If the addresses you find the x position at are totally random, then the game uses a form of dynamic memory allocation. In that case you'd have to go search for a pointer as in case c exclusively. This case can be tricky though because you have no way to find out at which distance from the pointer you're looking for the x-position is stored other than looking at raw memory data. My guess is that you'll find a combination of a and c. I hope this made any sense at all.
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
Depending on how the game manages memory, the location of the enemy data might in fact change every time it spawns. In very old consoles with a very limited amount of RAM this might be very limited (probably even often to the point that the data for a specific enemy will always appear in the exact same memory location, even if that enemy is killed and it respawns), but the newer the console and the more advanced the game, the chances that the data is at a random location in RAM increases.
Joined: 5/4/2005
Posts: 502
Location: Onett, Eagleland
Ok, so it's as I suspected then. The only trouble I was having, is that the memory addresses do appear static. That is, as someone mentioned, they are equal increments from each other (e.g. enemy 1 is +0x10C from enemy 2). My problem is this, enemy 1 is for example 0x80000000, enemy 1 dies, I move to the right, and to the left to respawn it. Now the enemy's address at that exact same spawn location and same type of enemy is now located at 0x8000010C. My question was, how can I tell which memory address is being looked at, at that current time so I don't read a wrong address in Lua, how can I tell if 2 or more enemy addresses are being written to? This would most likely be a situation where there is a pointer for enemy 1, enemy 2 etc...and I'd just need to find the pointers correct?. I have a 2nd question as well. How do I make the coordinates I received from in game values, relative to the emulator, e.g., I have the enemy's x/y position, but they are 100,10. How do I draw the coordinates exactly above the enemy's sprite? I've seen this done before for keeping track of enemy life, and I'm curious how it's done. Thank you all for your help.
I think.....therefore I am not Barry Burton
Banned User
Joined: 3/10/2004
Posts: 7698
Location: Finland
As you point out, the pointer to the enemy data ought to be stored in a variable (iow. a memory location). This variable might have a fixed location on memory (again, depending on how advanced the system and the program is). See if you can find the address of the enemy data somewhere else, and see if that address changes accordingly when the enemy respawns and its new data changes location. (OTOH the address might not be directly stored in any variable because it could well be a base address and an offset which are stored in two variables. Finding them could prove to be more difficult, but not impossible.)
Joined: 2/19/2007
Posts: 424
Location: UK
If everything else fails, and if your emulator supports it, you could try to trace the processor execution. From a state where you know that an enemy is just about to be generated at a given address, start tracing the execution, step 1 frame or so forward, and stop tracing. You will now have a disassembly of everything the processor did during that frame. Search for the address in the dump, and then work your way meticulously backwards until you find out how the processor arrived at that location. This way of doing things is a last resort, though, since it requires assembly knowledge and huge amounts of patience. I used it to find the loading zone triggers, treasure chest locations and event triggers in final fantasy VI, but it took many days, and I don't recommend it unless you are interested in the inner workings of games.
Joined: 10/20/2006
Posts: 1248
You'd ideally just need to find the enemy active flag somewhere in that 0x10C wide range. Just look at the whole surrounding memory range and try modifying some values to see what they do. Your goal is to find out the lower bound of where one enemy's data starts and another enemy's data ends. Then, if you have to find pointers, you need to search for that address in memory or convert it to an offset and try searching for that (searching for an offset is only possible once you know the absolutely lowest address an enemy's data could start at in memory). But you might not even have to find that pointer. If you succeed at finding an enemy active flag, then you can just read the entire range of where you know enemies could be stored and only draw the values for the active ones. This is only possible if you find consistent addresses, so if you find a value at 0x80000110 and 0x80000004, then you know it's never going to be at 0x80000100 (even after reboot), but always in fixed intervals starting from a certain address. If you find that not to be the case, then you'd just have to find a pointer/offset to the lower bound of that range somehow. And like I said, you may also have tough luck at finding such a flag in that 0x10C wide range if it's case b or c. To draw them, you just find the X and Y coordinates in that 0x10C wide range and then try finding a formula that let's you draw the values you want to draw below the actual enemies. Here's an example for such a function: gui.text((enemy.x-camera_x)/1-127-message.len(message)*2,(enemy.y-camera_y)/1-133,message,"#FFF00FF","black");
Joined: 5/4/2005
Posts: 502
Location: Onett, Eagleland
amaurea wrote:
If everything else fails, and if your emulator supports it, you could try to trace the processor execution. From a state where you know that an enemy is just about to be generated at a given address, start tracing the execution, step 1 frame or so forward, and stop tracing. You will now have a disassembly of everything the processor did during that frame. Search for the address in the dump, and then work your way meticulously backwards until you find out how the processor arrived at that location. This way of doing things is a last resort, though, since it requires assembly knowledge and huge amounts of patience. I used it to find the loading zone triggers, treasure chest locations and event triggers in final fantasy VI, but it took many days, and I don't recommend it unless you are interested in the inner workings of games.
Ya, I've done this to find (at least some what), how damage is calculated in SSF2T. I have a sort of off topic question for you, what debugger did you use for SNES? I can't find one.
Kuwaga wrote:
You'd ideally just need to find the enemy active flag somewhere in that 0x10C wide range. Just look at the whole surrounding memory range and try modifying some values to see what they do. Your goal is to find out the lower bound of where one enemy's data starts and another enemy's data ends. Then, if you have to find pointers, you need to search for that address in memory or convert it to an offset and try searching for that (searching for an offset is only possible once you know the absolutely lowest address an enemy's data could start at in memory). But you might not even have to find that pointer. If you succeed at finding an enemy active flag, then you can just read the entire range of where you know enemies could be stored and only draw the values for the active ones. This is only possible if you find consistent addresses, so if you find a value at 0x80000110 and 0x80000004, then you know it's never going to be at 0x80000100 (even after reboot), but always in fixed intervals starting from a certain address. If you find that not to be the case, then you'd just have to find a pointer/offset to the lower bound of that range somehow. And like I said, you may also have tough luck at finding such a flag in that 0x10C wide range if it's case b or c. To draw them, you just find the X and Y coordinates in that 0x10C wide range and then try finding a formula that let's you draw the values you want to draw below the actual enemies. Here's an example for such a function: gui.text((enemy.x-camera_x)/1-127-message.len(message)*2,(enemy.y-camera_y)/1-133,message,"#FFF00FF","black");
Interesting, I never thought if this. This sounds ideal if this is how it works, just check all the active flag locations, and if one is active just check for whatever values I want within that enemies structure. Any tips on finding hit boxes by using x/y coordinates of enemy/player values? Thanks for all the help guys.
I think.....therefore I am not Barry Burton