Programming UNROM: Difference between revisions
MetalSlime (talk | contribs) |
(Merged with Programming UOROM. I don't think we need two nearly identical pages for this.) |
||
Line 1: | Line 1: | ||
'''UNROM''' is the common name for a discrete mapper found on the UNROM board as well as the less common '''UOROM''' board. UNROM has 64 KB or 128 KB PRG-ROM (divided into 8 16k banks) and CHR-RAM. The UOROM board works the same way and can take PRG-ROM up to 256 KB. It is very easy to use. | |||
== iNES Header == | == iNES Header == | ||
Here is an iNES header for the | Here is an iNES header for the UNROM mapper. | ||
UNROM, 64 KB: | |||
.segment "HEADER" | |||
.byte "NES", $1A | |||
.byte $04 ;UNROM has 4 16k banks | |||
.byte $00 ;UNROM uses CHR RAM, so no CHR ROM | |||
.byte $20, $00 ;UNROM is Mapper 2 | |||
.byte $00 ;UNROM has no PRG RAM, though [[PRG RAM circuit|clone boards might]] | |||
UNROM, 128 KB (most common): | |||
.segment "HEADER" | .segment "HEADER" | ||
.byte "NES", $1A | .byte "NES", $1A | ||
Line 10: | Line 19: | ||
.byte $00 ;UNROM uses CHR RAM, so no CHR ROM | .byte $00 ;UNROM uses CHR RAM, so no CHR ROM | ||
.byte $20, $00 ;UNROM is Mapper 2 | .byte $20, $00 ;UNROM is Mapper 2 | ||
.byte $00 ;UNROM has no PRG RAM | .byte $00 ;UNROM has no PRG RAM, though clone boards might | ||
UOROM, 256 KB: | |||
.segment "HEADER" | |||
.byte "NES", $1A | |||
.byte $10 ;UOROM has 16 16k banks | |||
.byte $00 ;UOROM uses CHR RAM, so no CHR ROM | |||
.byte $20, $00 ;UOROM is Mapper 2 | |||
.byte $00 ;UOROM has no PRG RAM, though clone boards might | |||
== Bankswitching == | == Bankswitching == | ||
UNROM has four or eight banks 16 KB in size; UOROM has 16 banks. The last of these banks is fixed at $C000-$FFFF. The rest (numbered 0-2, 0-6, or 0-14) are switchable at $8000-$BFFF. | |||
Switching banks requires a write to $8000-$FFFF. | Switching banks requires a write to $8000-$FFFF. In UNROM, bits 0-2 of the byte written to $8000-$FFFF will select the bank; UOROM uses bits 0-3. When writing to $8000-$FFFF, the value you are writing must match the value located at the destination address in ROM (see [[Bus conflict]]). One way to ensure this is to have a bankswitch lookup table. You can read from this table and then immediately write that value back to the table. | ||
.segment "BANKTABLE" | .segment "BANKTABLE" | ||
banktable: | banktable: | ||
.byte $00, $01, $02, $03, $04, $05, $06 | .byte $00, $01, $02, $03, $04, $05, $06 ;Write to this table to switch banks. | ||
.byte $07, $08, $09, $0A, $0B, $0C, $0D, $0E | |||
; UNROM needs only the first line of this table (0-6) | |||
; but UOROM needs both lines (0-14). | |||
.segment "ZP": zeropage | .segment "ZP": zeropage | ||
current_bank: .res 1 | current_bank: .res 1 | ||
Line 32: | Line 51: | ||
rts | rts | ||
The lookup table and the bankswitching subroutine should be located in the fixed bank, so that they are always available. It is common to stick the lookup table | The lookup table and the bankswitching subroutine should be located in the fixed bank, so that they are always available. It is common to stick the lookup table somewhere in $FF00-$FFF9, close to the nmi/reset/irq vectors (at $FFFA-FFFF). | ||
With the lookup table and bankswitching subroutine in place, switching banks is as easy as this: | With the lookup table and bankswitching subroutine in place, switching banks is as easy as this: | ||
Line 42: | Line 61: | ||
* [[UxROM|UxROM technical reference]] | * [[UxROM|UxROM technical reference]] | ||
Revision as of 22:55, 27 July 2009
UNROM is the common name for a discrete mapper found on the UNROM board as well as the less common UOROM board. UNROM has 64 KB or 128 KB PRG-ROM (divided into 8 16k banks) and CHR-RAM. The UOROM board works the same way and can take PRG-ROM up to 256 KB. It is very easy to use.
iNES Header
Here is an iNES header for the UNROM mapper.
UNROM, 64 KB:
.segment "HEADER" .byte "NES", $1A .byte $04 ;UNROM has 4 16k banks .byte $00 ;UNROM uses CHR RAM, so no CHR ROM .byte $20, $00 ;UNROM is Mapper 2 .byte $00 ;UNROM has no PRG RAM, though clone boards might
UNROM, 128 KB (most common):
.segment "HEADER" .byte "NES", $1A .byte $08 ;UNROM has 8 16k banks .byte $00 ;UNROM uses CHR RAM, so no CHR ROM .byte $20, $00 ;UNROM is Mapper 2 .byte $00 ;UNROM has no PRG RAM, though clone boards might
UOROM, 256 KB:
.segment "HEADER" .byte "NES", $1A .byte $10 ;UOROM has 16 16k banks .byte $00 ;UOROM uses CHR RAM, so no CHR ROM .byte $20, $00 ;UOROM is Mapper 2 .byte $00 ;UOROM has no PRG RAM, though clone boards might
Bankswitching
UNROM has four or eight banks 16 KB in size; UOROM has 16 banks. The last of these banks is fixed at $C000-$FFFF. The rest (numbered 0-2, 0-6, or 0-14) are switchable at $8000-$BFFF.
Switching banks requires a write to $8000-$FFFF. In UNROM, bits 0-2 of the byte written to $8000-$FFFF will select the bank; UOROM uses bits 0-3. When writing to $8000-$FFFF, the value you are writing must match the value located at the destination address in ROM (see Bus conflict). One way to ensure this is to have a bankswitch lookup table. You can read from this table and then immediately write that value back to the table.
.segment "BANKTABLE" banktable: .byte $00, $01, $02, $03, $04, $05, $06 ;Write to this table to switch banks. .byte $07, $08, $09, $0A, $0B, $0C, $0D, $0E ; UNROM needs only the first line of this table (0-6) ; but UOROM needs both lines (0-14). .segment "ZP": zeropage current_bank: .res 1
.segment "CODE" bankswitch: lda banktable, y ;read a byte from the banktable sta banktable, y ;and write it back, switching banks sta current_bank ;store the current bank in RAM rts
The lookup table and the bankswitching subroutine should be located in the fixed bank, so that they are always available. It is common to stick the lookup table somewhere in $FF00-$FFF9, close to the nmi/reset/irq vectors (at $FFFA-FFFF).
With the lookup table and bankswitching subroutine in place, switching banks is as easy as this:
ldy #$02 jsr bankswitch ;switch to bank 2