External application to monitor gamestates
Moderator: ZSNES Mods
-
- New Member
- Posts: 5
- Joined: Sun Nov 07, 2004 6:50 am
External application to monitor gamestates
I saw what the Z-Net author did -- he made a dll that used a bunch of api calls to open the zsnes process and I guess watch some arbitrary memory location. This lets him get game stats in Mario Kart and provide a sort of live commentary on IRC.
Is there some magic trick to this? How would you go about finding the memory offsets for the various chunks of snes memory, like the registers, stack, and whatnot. It would be pretty neat if i could find a reasonable method to determine wins/losses in a few games. Then one of the online zsnes netplay matchmaking services could keep track of wins/losses for stuff like ladder matches. Obviously not foolproof against hacking, but seems like an interesting prospect nonetheless.
Is there some magic trick to this? How would you go about finding the memory offsets for the various chunks of snes memory, like the registers, stack, and whatnot. It would be pretty neat if i could find a reasonable method to determine wins/losses in a few games. Then one of the online zsnes netplay matchmaking services could keep track of wins/losses for stuff like ladder matches. Obviously not foolproof against hacking, but seems like an interesting prospect nonetheless.
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
Using ZSNES' memory searcher/cheat creator you would find which locations for the game under question contained the info you were looking for. Then you'd see how the SNES memory is located in ZSNES so you can pinpoint it.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
Not sure if you are referring to getting the actual SNES WRAM offset for a particular game, or the zsnes executable offset to the SNES WRAM. But since Nach already answered the former, I'll explain the latter process a bit.
Attach a debugger to zsnes. Something like visual studio would do. You can get the pointer from there with some trickery (scroll through the memory of zsnes and look for the SNES ram data, then search for a pointer to the top of the ram data. You may need to go up another pointer after that, repeat until you have a pointer >= 0x400000, as the rest are just pointers into allocated memory). Or if you prefer, you could compile zsnes yourself, and the obj files generated should give you the virtual address to where zsnes maps its snes wram to. I don't have any info on obj file formats, so I can't help you there. Since win32 apps are mapped to virtual memory, the offset will always be the same (again, only the top pointer. All the malloc'ed data will be random places in memory), but your offset will very likely be limited to one version of ZSNES. Once you have the offset, you can get the memory using ReadProcessMemory.
You will need to attach your own 'debugger' to zsnes, however. You don't actually have to add any real debugging stuff though. Or you could try using
DebugActiveProcess to get access to the processes memory, but I've never tried that before.
There's probably a way to read the memory from processes without
attaching a debugger, which is probably the best way to go about it, but I don't know it offhand.
It would honestly be easier to just compile zsnes yourself, and add a dll directly in to zsnes, that exports the SNES wram pointer for you. Set up a timer, and then you can just grab the memory at various intervals.
Attach a debugger to zsnes. Something like visual studio would do. You can get the pointer from there with some trickery (scroll through the memory of zsnes and look for the SNES ram data, then search for a pointer to the top of the ram data. You may need to go up another pointer after that, repeat until you have a pointer >= 0x400000, as the rest are just pointers into allocated memory). Or if you prefer, you could compile zsnes yourself, and the obj files generated should give you the virtual address to where zsnes maps its snes wram to. I don't have any info on obj file formats, so I can't help you there. Since win32 apps are mapped to virtual memory, the offset will always be the same (again, only the top pointer. All the malloc'ed data will be random places in memory), but your offset will very likely be limited to one version of ZSNES. Once you have the offset, you can get the memory using ReadProcessMemory.
You will need to attach your own 'debugger' to zsnes, however. You don't actually have to add any real debugging stuff though. Or you could try using
DebugActiveProcess to get access to the processes memory, but I've never tried that before.
There's probably a way to read the memory from processes without
attaching a debugger, which is probably the best way to go about it, but I don't know it offhand.
It would honestly be easier to just compile zsnes yourself, and add a dll directly in to zsnes, that exports the SNES wram pointer for you. Set up a timer, and then you can just grab the memory at various intervals.
-
- New Member
- Posts: 5
- Joined: Sun Nov 07, 2004 6:50 am
Good info guys, Thanks!
I'm wondering how effective watching the object files would be. I have to imagine the offsets would change on a compiler to compiler basis. What was the official 1.36 build built with anyway? My best bet is probably going to be a custom zsnes build or rev-eng the mem addr with a debugger...
I'm wondering how effective watching the object files would be. I have to imagine the offsets would change on a compiler to compiler basis. What was the official 1.36 build built with anyway? My best bet is probably going to be a custom zsnes build or rev-eng the mem addr with a debugger...
-
- Locksmith of Hyrule
- Posts: 3634
- Joined: Sun Aug 08, 2004 7:49 am
- Location: 255.255.255.255
- Contact:
If you're talking about the programming language used to make ZSnes, they used x86 assembly code for a majority (or maybe all?) of it.
<Nach> so why don't the two of you get your own room and leave us alone with this stupidity of yours?
NSRT here.
NSRT here.
-
- New Member
- Posts: 5
- Joined: Sun Nov 07, 2004 6:50 am
Parts of it are in C, other parts in ASM. On unix they I assume they use the usual stuff to compile it, nasm and gcc. But If the memory mapping of variables in the obj files are going to depend on the version of compiler used, I'd have to know what they used to build it on windows, as in what versions of nasm/gcc.
Then again, maybe i'm wrong and it doesn't matter from version to version...
Then again, maybe i'm wrong and it doesn't matter from version to version...
The obj data most definately would change. nasm may not, since it's all hardcoded assembly, I doubt the obj files would differ much. But gcc, yeah. Forget it.
I don't even know how well that would work. The only time I've ever hooked the memory from another app was when I attached a debugger and manually disabled IsDebuggerPresent and patched some font stuff.
If you're going to make your own build, you really should just build in a small routine into the emulator so that you can access the memory directly. If you really don't want to bundle whatever application you're making inside ZSNES, then add an option to export memory from the MessageLoop, and just have your app use SendMessage on zsnes to get updated memory info.
I don't even know how well that would work. The only time I've ever hooked the memory from another app was when I attached a debugger and manually disabled IsDebuggerPresent and patched some font stuff.
If you're going to make your own build, you really should just build in a small routine into the emulator so that you can access the memory directly. If you really don't want to bundle whatever application you're making inside ZSNES, then add an option to export memory from the MessageLoop, and just have your app use SendMessage on zsnes to get updated memory info.
-
- New Member
- Posts: 5
- Joined: Sun Nov 07, 2004 6:50 am
For this trick, i'd recompile zsnes to recieve a new custom message.
From what I understand (which isn't much, so correct me if i'm wrong), is that if I SendMessage between applications, the only return value the sending application can recieve from the recieving application is the return value (LRESULT) of the wndproc. I assume that memory addresses are going to be relative to the context of a specific proccess, so i can't just return a malloc()'d pointer full of wram data from zsnes to the other application.
So, I figure I can get a custom message to return either the memory address of wram, or the memory address of the pointer to wram (i assume that wramdata and wramdataa are the relevant symbols here, i have yet to narrow down exactly which is what). Using this relative memory address, I can open the process with the relevant api call, and read the wram memory from the addresses I recieved from the sendmessage call. Does this make sense? Do you think I'm going about it all wrong?
From what I understand (which isn't much, so correct me if i'm wrong), is that if I SendMessage between applications, the only return value the sending application can recieve from the recieving application is the return value (LRESULT) of the wndproc. I assume that memory addresses are going to be relative to the context of a specific proccess, so i can't just return a malloc()'d pointer full of wram data from zsnes to the other application.
So, I figure I can get a custom message to return either the memory address of wram, or the memory address of the pointer to wram (i assume that wramdata and wramdataa are the relevant symbols here, i have yet to narrow down exactly which is what). Using this relative memory address, I can open the process with the relevant api call, and read the wram memory from the addresses I recieved from the sendmessage call. Does this make sense? Do you think I'm going about it all wrong?
-
- Savestate Pimp
- Posts: 129
- Joined: Thu Jul 29, 2004 2:15 pm
- Contact:
http://msdn.microsoft.com/library/defau ... memory.aspfunkyass wrote:a piece of shared page
I've been thinking about using this for communicating between programs... but it's designed for exchanging data, not for exchanging messages... so a sub-standard would have to be developed.
"Other people can give you more suggestions as I just lost all my motivation to respond further to this post."
[i] - Nightcrawler[/i]
[url=http://www.geocities.com/illegal_eagle_2003/]vSNES v2.00[/url]: My SNES savestate viewer.
[i] - Nightcrawler[/i]
[url=http://www.geocities.com/illegal_eagle_2003/]vSNES v2.00[/url]: My SNES savestate viewer.
-
- New Member
- Posts: 5
- Joined: Sun Nov 07, 2004 6:50 am
-
- Romhacking God
- Posts: 922
- Joined: Wed Jul 28, 2004 11:27 pm
- Contact:
Anytime I want to communicate between programs, I use windows messages. I wouldn't think it would be very hard to add a few new messages that ZSNES handles. Of course, this would only work on the win32 port. I think this is the simplest way though.
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.