+  RHDN Forum Archive
|-+  Romhacking
| |-+  ROM Hacking Discussion
| | |-+  Mega Man 2 Graphics Swap?
Pages: [1]
Author Topic: Mega Man 2 Graphics Swap?  (Read 2 times)
Rockman
Guest
« on: August 13, 2008, 11:51:07 am »

Does anyone know how Mega Man 2 writes to the Pattern Table, exactly? The game has no CHR-ROM, only PRG, and I have been searching for a couple of days, and haven't had any luck. It is possible that address $F7 has something to do with it, but I don't know how. I will keep looking, but if somebody already has information about this, I would appreciate it. It is the last part I need to complete the new game engine I coded.  I need to know how it writes to the Pattern Table, because I want to swap Mega Man's graphics in/out.
KingMike
Guest
« Reply #1 on: August 13, 2008, 11:59:00 am »

You'd need to know ASM and find a routine that writes to VRAM. Use a tracing emulator and trace when the address of the data you need is changed.
NES games write the 2-byte VRAM address to $2006 (first the high byte, then the low byte) and then write data to $2007.
Disch
Guest
« Reply #2 on: August 13, 2008, 12:06:01 pm »

Quote from: Rockman on August 13, 2008, 11:51:07 am
Does anyone know how Mega Man 2 writes to the Pattern Table, exactly? The game has no CHR-ROM, only PRG, and I have been searching for a couple of days, and haven't had any luck.

I didn't look at this game specifically, but most CHR-RAM games I've seen have a sort of table that indicates which tiles to draw where and how much.  For example... if a game wanted to write $618 bytes of tile data taken from pointer $8000, and wants to draw them to PPU address $1234, you might see "34 12 00 80 18 06" in the ROM somewhere.  Of course this can be harder to find if you don't know exactly what values to look for.

Odds are, MM's graphics are copied in full, so figure out how many tiles make up all of MM and multiply that number by $10 to get the number of bytes.

To find the PPU address, you can use FCEUXD to get the tile number.  Just multiply the tile number by $10 for the PPU address -- and also add $1000 if MM is on the right-hand side of the pattern tables

To find the CPU pointer, find the offset of the start of MMs graphics in the ROM with a tile viewer, subtract $10 for the header, AND with $3FFF, then add $8000.  Example:  if graphics are at offset 0x05780, subtract $10 for 0x5780, AND with $3FFF for 0x1780, and add $8000 to get $9780.

Searching for one of more of those values in the ROM may turn up the table you're looking for.


Of course.... if you know 6502 (which I'm assuming you must, if you coded a new engine!), you can also just do some simple tracing.  Set a write breakpoint on the PPU address that has MM's graphics, fire up the trace logger, and get the game to load MM's graphics.  Once the debugger snaps, simply follow the tracelogger back to where it loads the pointers from, and you found your table.


I might look into this later if I'm bored and you can't find it on your own.

Quote
I need to know how it writes to the Pattern Table, because I want to swap Mega Man's graphics in/out.

Be warned that CHR-RAM writing is SLOW.  It's the big disadvantage to using CHR-RAM over CHR-ROM... games can't "swap" per se... rather they have to redraw each tile one byte at a time.  These loops suck up lots of CPU time and aren't instantaneous like CHR-ROM swapping.  You'll be able to swap out graphics between scenes.. but you probably won't be able to swap many/any out during any in-game action.

EDIT

well... maybe I'm being pessimistic.  You should be able to copy a small bit of tiles every VBlank (maybe 4 or 8 or something like that).  So you could swap out large chunks if you spread it across several frames.
Dan
Guest
« Reply #3 on: August 13, 2008, 04:46:33 pm »

If you're looking to manipulate what the pattern tables are loaded for mega man, the data is stored for each level individually.  There's a table for Fireman's stage at $3C10 (you can add $4000 to get the other stages).  From my editor source, here's a rough guide to the data:

  Format is as follows:

  Byte #00 - Number of Entries

  Entries are three bytes in size.

  Entry Byte #00 - Memory Address (Multiply by 1000)
  Entry Byte #01 - Number of PPU Rows
  Entry Byte #02 - Bank ?
Rockman
Guest
« Reply #4 on: August 16, 2008, 01:47:06 am »

Disch, I wouldn't mind your help if you are up for it.  Tonight I tried to see if I could code it, but I wasn't having any luck.  I even tried using the game's original code to swap graphics, but that wasn't going well either.  I have a picture here, with some information.



What I think might be part of the problem, is what you said, with this being too much to write to at once during gameplay.  Do you think you could help me come up with some clever code I could use to accomplish this task?
tomaitheous
Guest
« Reply #5 on: August 16, 2008, 03:11:19 am »

Does the update need to happen instantly? Would a slight pause still work? If it's something you can switch back and forth to, maybe you could put the megaman sprite in "transition" mode (like when you pause and unpause the game), until the graphics are updated - then transition back into the standing frame, etc.
Rockman
Guest
« Reply #6 on: August 16, 2008, 10:34:50 am »

Yeah I'm sure a slight pause would be fine.  I wouldn't mind if Mega Man does that "squeak" animation he does, when he returns from the inventory menu.  Maybe I could JSR to the code that returns from the invertory menu, and then put my code in there?  I would have to check to see if he is Mega Man or not, and then carry out the to swap the graphics.  But there is still $8FF of data there.  I tried using the game's way of processing that, but it hasn't really worked well.  Should I still try to see if I can get it to work, or should I use my own code to swap the graphics?
Disch
Guest
« Reply #7 on: August 16, 2008, 10:50:37 am »

Quote from: Rockman on August 16, 2008, 01:47:06 am
What I think might be part of the problem, is what you said, with this being too much to write to at once during gameplay.

That many tiles is definately too much.  Way too much to accomplish in one VBlank.  The NES just isn't fast enough.

You'll notice, however, that many of those tiles are identical.  You could get away with trimming that (for example...that whole last row is the same for both except for the last tile).  That way rather than trying to update one huge block, you'd be updating several smaller blocks (which could be done a bit faster if it removes enough tiles).

Quote
Do you think you could help me come up with some clever code I could use to accomplish this task?

I don't think anything super-fancy is required to make this work.  Since the game is already set up so that you have to go in and out of the pause menu to change graphics, the game is already paused when you need to make the swap.  All you'll have to do is stop the pause menu from exiting for a few frames (maybe 8 or so -- enough to get the drawing done... but the end user would hardly notice a 8-frame pause at all.. I mean that's only like 0.13 seconds)

I would probably approach this with the following:

1)  Find the code that triggers when the user exits the pause menu (preferably the code before the weapon select window is erased).  This code probably sets some flag in RAM that gets checked in the game's NMI code.  When the game sees that the flag is set, it will start erasing the weapon select screen in VBlank (it won't start erasing it in the routine you're looking for, simply because this routine probably won't be run in VBlank, where all drawing needs to be done).  Your first edit would be to stop the game from setting this paticular flag, and have it set your own custom flag instead.

2)  In the NMI routine (which is called at the start of every VBlank), check for your custom flag being set.  If it's set start replacing a small chunk of tiles at a time.  You have $800 bytes there (less if you trim duplicates).  Maybe copy over $100 bytes a frame.  You can do this by having a counter increment every NMI and copying a different chunk based on the value of said counter.

3)  After you've copied over all of it, set the game's normal flag to erase the weapon screen.  If all goes according to plan, the new graphics will be swapped in, and the game's original code will kick in, erase the weapon screen, and the program will continue as normal.


If $100 bytes is too much to get done in VBlank (I think it'll be fine... but you never know), you can reduce the number... but you'll have to pause for more frames.  The way you can tell if it's too much is there will be on-screen graphics corruption and/or the scroll will get all screwed up.
Pages: [1]  


Powered by SMF 1.1.4 | SMF © 2006-2007, Simple Machines LLC