byuu's message board

For discussion of projects related to www.byuu.org/


Cheat finder for higan; advice on address handling? 
Author Message
User avatar

Joined: Fri 07 Jun 2013, 06:52:39

Posts: 43
Location: Union of American Socialist Republics (U.A.S.R.)
Post Cheat finder for higan; advice on address handling?
I am writing an external program that reads the memory dumps made by higan when pressing the "Export Memory" hotkey and searches them to make cheat codes. Currently, it only supports the Super Famicom and can search for values in work RAM (7E:0000..7F:FFFF) that satisfy the following comparison types with an exact value: == (equal), != (not equal), < (less than), <= (less than or equal to), > (greater than), and >= (greater than or equal to). I still have not implemented comparisons with previous values.

I would like to extend my cheat finder to support expansion-chip-specific memory such as the SA-1's IRAM. I already made an addition to higan's code to make it dump expansion-chip-specific memory:

Code:
void Interface::exportMemory() {
  string pathname = {path(group(ID::ROM)), "debug/"};
  directory::create(pathname);

  file::write({pathname, "work.ram"}, cpu.wram, 128 * 1024);
  file::write({pathname, "video.ram"}, ppu.vram, 64 * 1024);
  file::write({pathname, "sprite.ram"}, ppu.oam, 544);
  file::write({pathname, "palette.ram"}, ppu.cgram, 512);
  file::write({pathname, "apu.ram"}, smp.apuram, 64 * 1024);
  if(cartridge.has_sa1())
    file::write({pathname, "sa1.internal.ram"}, sa1.iram.data(), sa1.iram.size());
  if(cartridge.has_armdsp())
    file::write({pathname, "st018.program.ram"}, armdsp.programRAM, sizeof(armdsp.programRAM));
  if(cartridge.has_hitachidsp())
    file::write({pathname, "cx4.data.ram"}, hitachidsp.ram.data(), hitachidsp.ram.size());
  if(cartridge.has_necdsp())
    file::write({pathname, "dsp.data.ram"}, necdsp.dataRAM, sizeof(necdsp.dataRAM));
}


However, while all 131072 addresses in WRAM are mapped exactly once (except for 00-3F,80-BF:0000-1FFF, which I ignore because bsnes remaps cheat codes in 7E:0000-1FFF to those areas automatically), this is not true of some of the expansion-chip-specific memories. Individual file addresses are mapped to multiple ROM addresses, and I have no way of predicting exactly which ones will be used on a game-by-game basis.

For example, Super Mario RPG's IRAM, which is 2048 (0x800) bytes long, is mapped to 00-3F,80-BF:3000-37FF. A total of 128 banks have mappings for IRAM, so 2048 * 128 == 262144 potential addresses that would need to be searched just for a file that is 2048 bytes long.

I cannot just choose which group of addresses to search, because what if I guess wrong and the game does not read from or write to those addresses at all?

So, is there any technique, anything at all, that can help optimize the workload?

I should note that I am using Ruby (the programming language by Matz, not the hardware abstraction layer in higan) to write this program because I initially intended the program for my private use and, while I do know some C++, I generally prefer Ruby for its relative ease of use. This means that my cheat finder runs on the command-line and may be user-unfriendly. If anyone still wants it knowing this, I will make a version that only searches WRAM and nothing else is now on mega.co.nz (it is too dependency-heavy to release as piecemealed [ code ] blocks, including a rewrite of nall/string/markup and code that is shared with a "de-purifying launcher" program for adding cartridge folder support to Project64, DeSmuME, Kega Fusion, etc.).

_________________
This signature has been censored by the United States government. You didn't see anything.


hex_usr


Sun 27 Jul 2014, 04:40:00

Joined: Fri 10 Apr 2009, 15:00:08

Posts: 13668
Post Re: Cheat finder for higan; advice on address handling?
You rewrote nall/string/markup? Interested in hearing more about that.

As to your question, copy the masking operation done for SNES RAM (in memory-inline.hpp IIRC) if you want to mirror for the SA-1.

You probably want BWRAM though, I don't think IRAM is really meant for storing RAM, but more for tight loops of code. Extremely high probability of false-positive matches there (due to RAM address reuse) with cheat codes.

> a "de-purifying launcher" program for adding cartridge folder support to Project64, DeSmuME, Kega Fusion, etc.

Neat! Sounds like something I'd make (ala header-magic) if I actually played games anymore.

Sun 27 Jul 2014, 04:46:02
User avatar

Joined: Fri 07 Jun 2013, 06:52:39

Posts: 43
Location: Union of American Socialist Republics (U.A.S.R.)
Post Re: Cheat finder for higan; advice on address handling?
It is not and should not be the cheat finder's responsibility to handle emulation behavior such as mirroring. I'll look through memory-inline.hpp, but I doubt it will help. The problem is that the same value is mirrored across hundreds of addresses, and I have no way of knowing which one is correct because I cannot guarantee that every game uses the same location for any given purpose. The HiROM games I observed, for example, seem to use 30:6000-7FFF for reading/writing SRAM despite it being available at 20-3F,A0-BF:6000-7FFF, but how do I know that every game puts SRAM at that exact same spot? Write to 30:6378, and the same value can be read from B7:6378, 25:6378, or A9:6378 (assuming a 0x2000 byte file).

With the Super Famicom's internal WRAM, I do not need to worry about 00-3F,80-BF:0000-1FFF because I have already seen the code that mirrors cheat codes in 7E:0000-1FFF to those areas (in sfc/cheat/cheat.cpp), so I can safely ignore them (in fact, I kind of suspect that making a cheat code for those areas will cause the cheat code to simply not work at all; change the bank to 7E to fix if that happens). I know of no such code for cartridge RAM, so that is why this is a concern.

While I don't doubt that IRAM is mainly used for tight loops of code, I already know it has been used as extra RAM in at least 1 case:

In Super Mario RPG, the addresses 00:3033-3037 store the current party as bytes representing each character's ID number.

0x00: Mario
0x01: Peach (Toadstool)
0x02: Bowser
0x03: Geno
0x04: Mallow

For example, I could use the following cheat code to swap out Mario and make Geno a permanent member that cannot be switched out with the menu:
003033/03+003036/00
It is recommended that you move Geno to slot 4 (the middle-right one) before attempting this; you do not want duplicate characters fighting in battle.

To the best of my knowledge, these locations never change. I looked them up a year or 2 before starting this project from giangurgolo's documents that he wrote when writing Lazy Shell (find them here and look for "the entire collection of SMRPG rom documents").

As for searching SRAM and BWRAM: Not only would it further amplify the problem even more (mirrored across 00-3F,80-BF:6000-7FFF and 40-4F:0000-FFFF for 2097152 addresses!), but it also involves reading "save.ram" which is not in the debug folder and will not be redumped by pressing "Export Memory". Searching it for cheats would require closing and reopening higan with a save state for each time, or modifying higan's exportMemory function to save SRAM the same way as when closing it or loading a different game.

I made my cheat finder and related programs available here. Feel free to post bug reports and constructive criticism.

_________________
This signature has been censored by the United States government. You didn't see anything.

Sun 27 Jul 2014, 08:05:31

Who is online

Users browsing this forum: No registered users and 0 guests

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum