|
|
(9 intermediate revisions by 5 users not shown) |
Line 1: |
Line 1: |
| [[iNES Mapper 001]] is used to designate the [[SxROM]] boardset, all of which use the [[Nintendo MMC1]]. | | #REDIRECT [[MMC1]] |
| | | {{DEFAULTSORT:001}}[[Category:iNES Mappers]][[Category:in NesCartDB]][[Category:Nintendo licensed mappers]][[Category:NES 2.0 mappers with submappers]] |
| This has proven to be problematic for boards (such as SOROM, SUROM and SXROM) which use the upper CHR bank select lines to select additional PRG ROM or PRG RAM data; games which use SOROM or SXROM often must be handled individually based on the ROM checksum.
| |
| | |
| In the absence of data beyond basic [[iNES]] header data, the following procedure developed by [[User:Bregalad]] may work to guess a board type useful for emulation:
| |
| | |
| # CHR ROM present on cartridge : MMC1 registers acts "normal".
| |
| # CHR ROM not-present on cartridge : MMC1 CHR's registers bankswitches SRAM banks. If the battery bit is present, only banks which are accessed are saved to the disk when the game is quit. When loading a game with the battery bit set, if a 8KB .sav file is present, it is repeated equally across all banks. This will lead to data being saved when it wasn't supposed to for SOROM games, but 8KB of hard disk space isn't a problem.
| |
| # PRG ROM size equal to 512 KiB: Higher CHR line switches 256 KB banks.
| |
| # PRG ROM size equal to 256 KiB or less and CHR-ROM not present on the cartidge : Higher CHR line disables SRAM.
| |
| | |
| <pre>
| |
| ========================
| |
| = Mapper 001 =
| |
| ========================
| |
| | |
| aka
| |
| --------------------------
| |
| MMC1
| |
| SxROM
| |
| | |
| | |
| Example Games:
| |
| --------------------------
| |
| Final Fantasy
| |
| Mega Man 2
| |
| Blaster Master
| |
| Metroid
| |
| Kid Icarus
| |
| Zelda
| |
| Zelda 2
| |
| Castlevania 2
| |
| | |
| | |
| Notes:
| |
| ---------------------------
| |
| MMC1 is unique in that not only must the registers be written to *one bit at a time*, but also you cannot
| |
| write to the registers directly.
| |
| | |
| Internal registers are 5 bits wide. Meaning to complete a "full" write, games must write to a register 5
| |
| times (low bit first). This is usually accomplished with something like the following:
| |
| | |
| LDA value_to_write
| |
| STA $9FFF ; 1st bit written
| |
| LSR A
| |
| STA $9FFF ; 2nd bit written
| |
| LSR A
| |
| STA $9FFF ; 3rd bit written
| |
| LSR A
| |
| STA $9FFF ; 4th bit written
| |
| LSR A
| |
| STA $9FFF ; final 5th bit written -- full write is complete
| |
| | |
| Writing to anywhere in $8000-FFFF will do -- however the address you write to on the last of the 5 writes
| |
| will determine which internal register gets filled. The address written to for the first 4 writes *does not
| |
| matter at all*... though games generally write to the same address anyway (like in the above example).
| |
| | |
| To illustrate this:
| |
| | |
| LDA #$00 ; we want to write 0 to a reg
| |
| STA $8000
| |
| STA $8000
| |
| STA $8000
| |
| STA $8000 ; first 4 writes go to $8000
| |
| STA $E000 ; 5th write goes to $E000
| |
| | |
| The above code will affects reg $E000 only!!! Despite $8000 being written to several times, reg $8000
| |
| remains totally unchanged!
| |
| | |
| How this works is that when the game writes to $8000-FFFF, it goes to a hidden temporary register. That
| |
| register records the bits being written. Only after all 5 bits are written does the final 5-bit value move
| |
| to the desired *actual* register.
| |
| | |
| Only bits 7 and 0 are significant when writing to a register:
| |
| | |
| Temporary reg port ($8000-FFFF):
| |
| [r... ...d]
| |
| r = reset flag
| |
| d = data bit
| |
| | |
| When 'r' is set:
| |
| - 'd' is ignored
| |
| - hidden temporary reg is reset (so that the next write is the "first" write)
| |
| - bits 2,3 of reg $8000 are set (16k PRG mode, $8000 swappable)
| |
| - other bits of $8000 (and other regs) are unchanged
| |
| | |
| When 'r' is clear:
| |
| - 'd' proceeds as the next bit written in the 5-bit sequence
| |
| - If this completes the 5-bit sequence:
| |
| - temporary reg is copied to actual internal reg (which reg depends on the last address written to)
| |
| - temporary reg is reset (so that next write is the "first" write)
| |
| | |
| | |
| Confusing? Yeah it looks confusing, but isn't really. For an example:
| |
| | |
| LDA #$00
| |
| STA $8000 ; 1st write ('r' bit is clear)
| |
| STA $8000 ; 2nd write
| |
| | |
| LDA #$80
| |
| STA $8000 ; reset ('r' bit is set)
| |
| | |
| LDA #$00
| |
| STA $8000 ; 1st write (not 3rd!)
| |
| | |
| | |
| | |
| Variants:
| |
| --------------------------
| |
| There are also a slew of board variations which are assigned to mapper 001 as well. See the sections at the
| |
| bottom for details. Determining which variant a game uses is difficult -- likely you'll need to fall back
| |
| to a CRC or hask check.
| |
| | |
| | |
| | |
| Registers:
| |
| --------------------------
| |
| | |
| Note again, these registers are internal and are not accessed directly! Read notes above.
| |
| | |
| | |
| $8000-9FFF: [...C PSMM]
| |
| C = CHR Mode (0=8k mode, 1=4k mode)
| |
| P = PRG Size (0=32k mode, 1=16k mode)
| |
| S = Slot select:
| |
| 0 = $C000 swappable, $8000 fixed to page $00 (mode A)
| |
| 1 = $8000 swappable, $C000 fixed to page $0F (mode B)
| |
| This bit is ignored when 'P' is clear (32k mode)
| |
| M = Mirroring control:
| |
| %00 = 1ScA
| |
| %01 = 1ScB
| |
| %10 = Vert
| |
| %11 = Horz
| |
| | |
| | |
| $A000-BFFF: [...C CCCC]
| |
| CHR Reg 0
| |
| | |
| $C000-DFFF: [...C CCCC]
| |
| CHR Reg 1
| |
| | |
| $E000-FFFF: [...W PPPP]
| |
| W = WRAM Disable (0=enabled, 1=disabled)
| |
| P = PRG Reg
| |
| | |
| | |
| Disabled WRAM cannot be read or written. Earlier MMC1 versions apparently do not have this bit implimented.
| |
| Later ones do.
| |
| | |
| | |
| | |
| CHR Setup:
| |
| --------------------------
| |
| There are 2 CHR regs and 2 CHR modes.
| |
| | |
| $0000 $0400 $0800 $0C00 $1000 $1400 $1800 $1C00
| |
| +---------------------------------------------------------------+
| |
| C=0: | <$A000> |
| |
| +---------------------------------------------------------------+
| |
| C=1: | $A000 | $C000 |
| |
| +-------------------------------+-------------------------------+
| |
| | |
| | |
| | |
| PRG Setup:
| |
| --------------------------
| |
| There is 1 PRG reg and 3 PRG modes.
| |
| | |
| $8000 $A000 $C000 $E000
| |
| +-------------------------------+
| |
| P=0: | <$E000> |
| |
| +-------------------------------+
| |
| P=1, S=0: | { 0 } | $E000 |
| |
| +---------------+---------------+
| |
| P=1, S=1: | $E000 | {$0F} |
| |
| +---------------+---------------+
| |
| | |
| | |
| On Powerup:
| |
| ----------------------------
| |
| | |
| This varies from version to version. Earlier MMC1 versions have no determined startup state. Later ones do.
| |
| | |
| - bits 2,3 of $8000 are set (16k PRG mode, $8000 swappable)
| |
| | |
| WRAM Disable varies wildly from version to version. Some versions don't have it at all, other versions have
| |
| it cleared initially, others have it set initially, and others have it random. To be "safe", when
| |
| homebrewing, assume it's disabled (and have your game explicitly enable it before accessing WRAM), and when
| |
| emudeving, assume it's enabled at startup (or else some early MMC1 games will break in your emu).
| |
| | |
| | |
| | |
| | |
| Additional Notes:
| |
| ----------------------------
| |
| | |
| Consecutive writes that are too close together are apparently ignored. One game where this is significant
| |
| is Bill & Ted's Excellent Video Game Adventure. That game does the following HORRIBLY SLOPPY code to reset
| |
| the mapper:
| |
| | |
| INC $FFFF (where $FFFF contains $FF when read)
| |
| | |
| For those of you who really know your 6502... you know that this will read $FFFF (getting $FF), write that
| |
| value ($FF) back to $FFFF, increment it by one, then write the new value ($00) to $FFFF. This results in
| |
| two register writes: $FF, then $00.
| |
| | |
| Normally, such writes would reset the mapper, then write a single data bit. However if your emu does it
| |
| like that, the game will crash, as the game expects the next write to be the 1st in a 5-bit sequence (and
| |
| your emu will treat it like the 2nd).
| |
| | |
| However these writes are performed on consecutive CPU cycles -- which apparently are too close to each other.
| |
| As such, only the first write (of $FF) is acknowledged and performed, and the second write (of $00) is
| |
| ignored. Emulating in this manner results in a fully functioning game.
| |
| | |
| So while it is unsure exactly how far apart the writes must be, you can assume that the distance between
| |
| them must be at least 2 CPU cycles. Such that Read/Modify/Write instructions (like INC) will only
| |
| acknowledge the first write, but two consecutive write instructions (like 2 side-by-side STA's) will work
| |
| normally.
| |
| | |
| | |
| -----------------------------------------
| |
| -----------------------------------------
| |
| | |
| | |
| Special Variant -- SUROM:
| |
| --------------------------
| |
| | |
| Example Games:
| |
| Dragon Warrior 4
| |
| Dragon Quest 4
| |
| | |
| | |
| The MMC1 PRG reg is only 4 bits wide. This means that normally, page $0F is the highest page number you can
| |
| access. With 16k pages... this limits typical MMC1 to 256k PRG ($10 pages * $4000 per page). SUROM
| |
| "hijacks" one of the bits from the CHR registers and uses it as an additional PRG bit. This allows for
| |
| access to $1F pages, allowing 512k PRG.
| |
| | |
| $A000-BFFF: [...C CCCC] CHR reg 0
| |
| [...P ....] hijacked PRG bit
| |
| | |
| $C000-DFFF: [...C CCCC] CHR reg 1
| |
| [...P ....] hijacked PRG bit
| |
| | |
| When in 4k CHR mode, 'P' in both $A000 and $C000 *must* be set to the same value, or else pages will
| |
| constantly be swapped as graphics render! In 8k CHR mode (which is what DQ4 uses), $C000 is irrelevent
| |
| since it is ignored, and $A000 is used exclusively.
| |
| | |
| The hijacked PRG bit selects which 256k block is used for *ALL* PRG... *including* fixed pages. Meaning
| |
| fixed page $0F @ $C000 can swap between page $0F and $1F.
| |
| | |
| | |
| | |
| Special Variant -- SOROM:
| |
| --------------------------
| |
| | |
| Example Games:
| |
| Nobunaga's Ambition
| |
| Romance of the Three Kingdoms
| |
| Genghis Khan
| |
| | |
| | |
| SOROM has 16k PRG-RAM (instead of the typical 8k), and hijacks unused bits from the CHR regs in order to
| |
| select which 8k PRG-RAM page is at $6000-7FFF. The first 8k of PRG-RAM (page 0) is not battery backed --
| |
| but the second 8k is.
| |
| | |
| When in 4k CHR Mode:
| |
| | |
| $A000-BFFF: [...R ...C]
| |
| R = PRG-RAM page select
| |
| C = CHR reg 0
| |
| | |
| $C000-DFFF: [...R ...C]
| |
| R = PRG-RAM page select
| |
| C = CHR reg 1
| |
| | |
| In 4k CHR mode, above 'R' bits MUST be set to the same value or else PRG-RAM will automatically swap as
| |
| the PPU fetches tiles to render!
| |
| | |
| | |
| When in 8k mode:
| |
| | |
| $A000-BFFF: [.... R...] PRG-RAM page select
| |
| $C000-DFFF: [.... ....] Unused
| |
| | |
| | |
| | |
| Special Variant -- SXROM:
| |
| --------------------------
| |
| | |
| Example Games:
| |
| Final Fantasy 1 & 2 (the combo cart, not the individual games)
| |
| Best Play Pro Yakyuu Special
| |
| | |
| | |
| SXROM is sort of like a combination of SUROM and SOROM. It uses bits from CHR regs to have an additional
| |
| PRG bit, and also to have swappable PRG-RAM. SXROM has a whopping 32k PRG-RAM (all of which can be battery
| |
| backed).
| |
| | |
| | |
| When in 8k CHR mode:
| |
| | |
| $A000-BFFF: [...P RR..]
| |
| P = PRG-ROM 256k block select (just like on SUROM)
| |
| R = PRG-RAM page select (selects 8k @ $6000-7FFF, just like SOROM)
| |
| | |
| | |
| I'm uncertain of behavior when in 4k CHR mode. I suspect it is similar to SUROM, in that the registers must
| |
| be identical or else undesired swapping will occur as the PPU renders.
| |
| </pre>
| |
| | |
| [[Category:iNES Mappers]]
| |