News: 11 March 2016 - Forum Rules

Author Topic: Can fceux have breakpoints on read from ROM?  (Read 3190 times)

nesrocks

  • Hero Member
  • *****
  • Posts: 746
    • View Profile
    • nesrocks.com
Can fceux have breakpoints on read from ROM?
« on: April 17, 2016, 03:19:55 pm »
Is there a way to use breakpoints when reading from specific ROM addresses? How does that even work? On the debugger I only see references to things loaded in RAM, cpu memory and such. How does an assembly opcode read from ROM? Can anyone shed some light on this?

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: Can fceux have breakpoints on read from ROM?
« Reply #1 on: April 17, 2016, 03:52:15 pm »
Is there a way to use breakpoints when reading from specific ROM addresses? How does that even work? On the debugger I only see references to things loaded in RAM, cpu memory and such. How does an assembly opcode read from ROM? Can anyone shed some light on this?


One of the biggest pet peeves I have of FCEUX is that is calls "addressing space" RAM.  It is NOT RAM.

The NES has $10000 addresses.  This is "addressing space" and is what you see when you look at the "RAM Viewer" in FCEUX.  Some of this space is assigned to RAM.  Some is ROM.  Some is hardware registers.

The general layout is:

Code: [Select]
0000-07FF = System RAM
2000-2007 = PPU registers
4000-4017 = APU / controller / DMA registers
6000-7FFF = on-cartridge RAM (SRAM).  Not always available -- depends on mapper & game
8000-FFFF = on-cartridge PRG (ROM).  Exact placement depends on mapper & game


- other regions are either not mapped to anything or are mirrors

So if you want to set a breakpoint on a ROM read... odds are your breakpoint will fall in the $8000-FFFF range, since that is where ROM gets mapped to.

snarfblam

  • Submission Reviewer
  • Hero Member
  • *****
  • Posts: 595
  • CANT HACK METROID
    • View Profile
    • snarfblam
Re: Can fceux have breakpoints on read from ROM?
« Reply #2 on: April 17, 2016, 06:44:19 pm »
You need to know how the ROM is mapped into CPU address space. That depends on the mapper used by the game. For example, MMC1 (Zelda, Metroid, etc., etc.) divides the ROM into $4000-byte banks. The last bank is mapped to $C000-$FFFF, and any other bank can be mapped into $8000-$BFFF. So, suppose you're looking to break when the byte at 0x13056 is read.

First subtract $10 to account for the iNES header, giving you 0x13046. Divide that by $4000 to get the bank number, which gets you 4. Then, keep subtracting $4000 to get the location within the bank within question. Stop when you get a number that is less than $4000. (In other words, you want the modulus, i.e. remainder of the division we did.) In this case it will be 3046. Since bank 4 isn't the last bank, it will be mapped in the $8000 region, thus our address is $8000 + $3046 = $B046. If you create a breakpoint for reads on $B064, the emulator will break when you want. (It will also break if the same location is read in a different bank, but that usually doesn't create a problem.)

That might sound like a pretty big headache for every time you need to convert a ROM location to a CPU address, but with some practice you'll get to the point where you can do it in your head in a second. Again, this is just an example using MMC1. Different mappers will use different bank sizes in different configurations. You can look up detailed documentation on sites like NESDev for the various mappers.

How does an assembly opcode read from ROM? Can anyone shed some light on this?

The CPU doesn't know anything about mappers or banks. That's all handled by the cartridge. In effect, every time the CPU accesses the ROM, the cartridge does the above conversion.

nesrocks

  • Hero Member
  • *****
  • Posts: 746
    • View Profile
    • nesrocks.com
Re: Can fceux have breakpoints on read from ROM?
« Reply #3 on: April 17, 2016, 10:45:50 pm »
Amazing info from the legends, thanks! It's a lot to digest for such a newbie as me, so it'll take time and effort (both of which I'll invest). So thank you very much for taking your time to answer, I appreciate it.

Disch: Reverse engineering these games is no easy task and misinformation sure doesn't help, so having more accurate naming in the most popular NES debugger should be a concern indeed. Hoping its development hasn't halted.

The rom hack I'm working on is of a mapper 2 game, Super Pitfall. Why such a bad game? For starters it has sentimental value to me and to many people I know. But also because it being so bad means it's very improvable. I'm planning some distinct hacks for the game to be released modularly.

So, I've tried to disassemble it using disasm6 (indicating the prg starts at 0x0000 as I've read somewhere there's no chr in mapper 2), but it won't recompile using asm6. I have most certainly misinterpreted this... It throws some errors, so I'm doing my edits directly in hex and using fceux's debugger and looking for references of 6502 opcodes.

I guess I am kind of confused on how data and code are handled, but still managed to make lots of progress on the hack. For example I've changed the main menu to do something else instead of picking 1 / 2 players by changing some pointers! Pretty proud moment for me  :)

I've noticed there's map data starting at 0x004000 by using yy-chr prg editor. I've also since improved my "breakpointing skills" by using condition expressions. I still wish there was a way to backtrack executed code starting from a breakpoint, I feel like that'd be amazing.

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: Can fceux have breakpoints on read from ROM?
« Reply #4 on: April 18, 2016, 12:22:16 am »
The rom hack I'm working on is of a mapper 2 game, Super Pitfall.

Mapper 2!

- No SRAM ($6000-7FFF is empty/useless).
- $8000-FFFF swaps the same way snarfblam described in his post.


Quote
I still wish there was a way to backtrack executed code starting from a breakpoint, I feel like that'd be amazing.

There is.

1)  Save state just before the breakpoint triggers
2)  Set the breakpoint
3)  Debugger snaps when breakpoint is hit
4)  Start a tracelog
5)  Load state
6)  Run


When the breakpoint triggers, the trace window will fill with a couple ?thousand? lines that executed before the breakpoint hit.