+  RHDN Forum Archive
|-+  Romhacking
| |-+  General Romhacking
| | |-+  Quick SMB1 Question
Pages: [1]
Author Topic: Quick SMB1 Question  (Read 606 times)
Dr. Floppy
Guest
« on: February 19, 2007, 12:15:28 am »

I've noticed that the SMB1 ROM ends around $9FDA. And yet, I'm told NES ROMs are capable of reading from $0000-$FFFF.

Does this mean that one could (at least theoretically) use the space after $9FDA to write new data, to which relevant portions of the existing ROM could be redirected?

Thatisall.
tomaitheous
Guest
« Reply #1 on: February 19, 2007, 03:40:00 am »


SMB 1 PRG data is only 32k, so anything $8000 (minus header ofcourse) and after is CHR data. Are you trying to add game code or additional CHR banks?

~Rich
Disch
Guest
« Reply #2 on: February 19, 2007, 01:14:22 pm »

Quote from: Dr. Floppy on February 19, 2007, 12:15:28 am
I've noticed that the SMB1 ROM ends around $9FDA.

I smell a bad dump

If your ROM is not exactly $A010 bytes, it is a bad dump  (of course, having the right size doesn't necessarily make it a good dump).


Quote
And yet, I'm told NES ROMs are capable of reading from $0000-$FFFF.

ROM offsets do not translate directly to NES addressing space.  SMB1 has 32k of PRG (from offset 0x00010 - 0x0800F in the .nes file).  This 32k is put at $8000-$FFFF.. so when the game reads from $8000, it's really reading offset 0x00010 in the file.  $0000-7FFF is generally used for other things on the system, such as RAM, and PPU/CPU/APU registers.  $2007, for example, is not ROM, but rather is the PPU I/O port, which the game will write to in order to draw things to the screen.

SMB1 is the "maximum" size allowed for a mapper 0 game (32k PRG + 8k CHR).  Games can be larger only with the addition of a mapper which would allow for PRG/CHR swapping.


Quote
Does this mean that one could (at least theoretically) use the space after $9FDA to write new data, to which relevant portions of the existing ROM could be redirected?

NES ROM expansion is a bit more complicated than just tacking things on the end.  So the short answer to this is "no".  However it IS very possible to expand the game to virtually any size... it just takes more work than what you might think.
Dr. Floppy
Guest
« Reply #3 on: February 19, 2007, 07:36:53 pm »

<< I smell a bad dump. If your ROM is not exactly $A010 bytes, it is a bad dump.   >>

It's $A010, I just discounted the last three lines of straight FF's. My bad.

(By the way, am I alone in thinking whoever came up with the terminology for this needs a major lesson in aesthetics?) 


<< SMB1 is the "maximum" size allowed for a mapper 0 game (32k PRG + 8k CHR).  Games can be larger only with the addition of a mapper which would allow for PRG/CHR swapping. It IS very possible to expand the game to virtually any size... it just takes more work than what you might think. >>

I'm game. What is the general procedure for adding a new mapper to expand/swap the PRG section?
Disch
Guest
« Reply #4 on: February 19, 2007, 08:40:55 pm »

Quote from: Dr. Floppy on February 19, 2007, 07:36:53 pm
(By the way, am I alone in thinking whoever came up with the terminology for this needs a major lesson in aesthetics?)

Hahahaha

Quote
I'm game. What is the general procedure for adding a new mapper to expand/swap the PRG section?

I've been meaning to write an actual comprehensive doc on the subject... but I never got around to it.  Plus I'm lazy.  It will require shifting around code and writing custom routines -- so if you're not comfortable with 6502, this might not be a good beginner project.

Anyway...

*cracks knuckles*

To understand how to change a mapper you must first know what a mapper does.  The cartridge is able to map anything on the cart to the $4020-FFFF range.  Everything lower than that is used by the actual NES and maps to system RAM, system registers, or whatnot.  The "standard" way to map this range is:

$4020-5FFF = nothing (open bus)
$6000-7FFF = on-cartridge RAM (aka, SRAM when battery backed) ** only when present (not all carts have RAM)
$8000-FFFF = PRG ROM (the actual game code+data)

As you can see, this only allows for 32k of PRG to be "visible" at once... which is why mapper 0 (no mapper) is maxed out at 32k.  That's not a whole lot of space.

Mappers get around this by employing something called "PRG swapping" (though the name is somewhat misleading).  This breaks the $8000-FFFF range into smaller blocks, and assigns a flexible page number to each block... so that instead of mapping directly to a "hardwired" area in ROM, the address range is indexed by a page number.

One of the more common methods of PRG swapping is what is done by mapper 2.  It splits PRG space into two 16k blocks ($8000-BFFF and $C000-FFFF).  $C000 is "fixed" to the last 16k of PRG in the .nes file, but $8000 is "swappable".  That is, the game can assign a page number to it, and when it reads from that range, the current page number selects where in the .nes file to read from.

For example... if a game reads from $9130, it could be reading from any of the following .nes offsets:

0x01140  (if page 0 "swapped in")
0x05140  (if page 1)
0x09140  (if page 2)
etc

There are, of course, lots of other swapping schemes, and different mappers all do it a little differently.  Although they are all conceptually the same idea.

How you select a page depends on the mapper you're using.  Usually it involves one or more writes to the $8000-FFFF area.


-----------------------
So how do you add a mapper?  Adding a mapper to a mapper 0 game isn't really that hard.  In fact... depending on the game, it might be as easy as just changing the mapper number in the header.  However there's one big catch that most people don't realize...

On system startup, mapper registers (ie:  what page is swapped in) are unprepped!  Many people (and even some docs) claim that registers are set to certain values on startup... however 99% of the time they are not.  This means that to start up "safely", you must have the reset vector point to somewhere in the hardwired bank, and specifically select desired PRG pages before accessing any PRG in swappable areas.

For SMB1, this becomes a problem, as the Reset vector points to $8000, which is swappable on pretty much every mapper out there.  So depending on which mapper you change to, you'll have to free up some space in $E000-FFFF or whatever is hardwired, run some custom code to prep the mapper (swap in desired startup pages) then jump to the game's normal startup code.  SMB1 is notoriously tight on space, so freeing up this space is quite a task, and may involve shifting routines around and jumping through all sorts of hoops.


----------------
What about expanding?

Once you have a mapper in... expanding is as easy as adding more PRG in (as long as you keep the PRG a power-of-2 size).  Just make sure you keep the hardwired pages where they need to be (ie:  if the last 16k is hardwired... you'll need that 16k to stay at the end of the PRG .. so you'll want to add pages before it, rather than after it).  Nothing really hard at all.

Using the space you gain from expanding is something else.  To use the new space, you'll have to swap in the desired page, jump to it / read from it, then swap back to the page that was originally there.  This isn't so horrible for quick custom routines... but when you're working around existing game routines (like say, you want to use the extra space for more levels or more text), you might have to gut and rewrite large portions of the game's routines in order to get it working the way you want.
KingMike
Guest
« Reply #5 on: April 03, 2007, 11:58:58 am »

Quote from: Disch on February 19, 2007, 08:40:55 pm
So how do you add a mapper?  Adding a mapper to a mapper 0 game isn't really that hard.  In fact... depending on the game, it might be as easy as just changing the mapper number in the header.  However there's one big catch that most people don't realize...

On system startup, mapper registers (ie:  what page is swapped in) are unprepped!  Many people (and even some docs) claim that registers are set to certain values on startup... however 99% of the time they are not.  This means that to start up "safely", you must have the reset vector point to somewhere in the hardwired bank, and specifically select desired PRG pages before accessing any PRG in swappable areas.

For SMB1, this becomes a problem, as the Reset vector points to $8000, which is swappable on pretty much every mapper out there.  So depending on which mapper you change to, you'll have to free up some space in $E000-FFFF or whatever is hardwired, run some custom code to prep the mapper (swap in desired startup pages) then jump to the game's normal startup code.  SMB1 is notoriously tight on space, so freeing up this space is quite a task, and may involve shifting routines around and jumping through all sorts of hoops.
I wonder if this is related to why Paris-Dakar Rally Special crashes with a blue screen on startup in FCEUltra?
(uses mapper 66 (GNROM), which has (4x) 32KB PRG banks and (4x) 8KB CHR banks)
Well, at least it works in Nesten, so at least it's still a possibility.
(looks like a weird racing/RPG/platformer?Huh)
hap
Guest
« Reply #6 on: April 03, 2007, 12:14:40 pm »

I think the reason Paris-Dakar Rally Special crashes is due to an unwanted IRQ that shouldn't happen on a NES during this obscure code:

CLI
RTI
doppelganger
Guest
« Reply #7 on: April 04, 2007, 05:19:51 pm »

I can't believe how many bad dumps there are of this game.  That title-less pirate ROM is the most conspicuous of them all.
Pages: [1]  


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