RAMBO-1: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
(Move Disch's notes from iNES Mapper 064)
 
(28 intermediate revisions by 7 users not shown)
Line 1: Line 1:
[[Category:MMC3-like mappers]]
{{Infobox_iNES_mapper
The '''Tengen RAMBO-1''' is an [[:Category:ASIC mappers|ASIC]] [[MMC|mapper]], assigned to iNES mappers [[INES_Mapper_064|64]] and [[iNES Mapper 158|158]]. This mapper is basically Tengen's version of the [[MMC3]], but with some extra features.
|name=RAMBO-1
|company=Tengen
|mapper=64
|othermappers=[[iNES Mapper 158|158]]
|nescartdbgames=5
|complexity=ASIC
|boards=800032
|pinout=Tengen RAMBO-1 pinout
|prgmax=256K
|prgpage=3×8K + 8K fixed
|chrmax=256K
|chrpage=1Kx8 or 2Kx2 + 1Kx4
|mirroring=H or V, switchable
|busconflicts=No
|irq=Yes
}}
{{nesdbbox
|ines|64|iNES 064
|unif|TENGEN-800032|800032
}}:''For the mapper used in the game "Rambo", see [[UxROM]].''
[[Category:MMC3-like mappers]][[Category:Mappers with scanline IRQs]][[Category:Mappers with cycle IRQs]]
The '''Tengen RAMBO-1''' is an [[:Category:ASIC mappers|ASIC]] [[MMC|mapper]], canonically designated as '''mapper 64'''. This mapper is basically Tengen's version of the [[MMC3]], but with some extra features. The RAMBO-1 came as a [[Tengen RAMBO-1 pinout|40-pin PDIP]]. A variant with different mirroring control is [[iNES Mapper 158|mapper 158]].


== Overview ==
Example games:
* PRG ROM size: Up to 256 KB
* ''Klax''
* PRG ROM bank size: 8 KB
* ''Skull and Crossbones''
* PRG RAM: Unknown
* ''Shinobi''
* CHR capacity: Up to 256 KB ROM
* ''Rolling Thunder''
* CHR bank size: All 1 KB, or 2 2KB and 4 1KB
* ''Hard Drivin' (prototype)''
* Nametable [[mirroring]]: Controlled by mapper
* Subject to [[bus conflict]]s: No


== Banks ==
== Banks ==
* CPU $8000-$9FFF: 8 KB switchable PRG ROM bank
* CPU $8000-$9FFF: 8 KiB switchable PRG ROM bank
* CPU $A000-$BFFF: 8 KB switchable PRG ROM bank
* CPU $A000-$BFFF: 8 KiB switchable PRG ROM bank
* CPU $C000-$DFFF: 8 KB switchable PRG ROM bank
* CPU $C000-$DFFF: 8 KiB switchable PRG ROM bank
* CPU $E000-$FFFF: 8 KB PRG ROM bank, fixed to the last bank
* CPU $E000-$FFFF: 8 KiB PRG ROM bank, fixed to the last bank
* PPU -- Three selectable configurations:
* PPU -- Three selectable configurations:
*# 1 KB switchable CHR banks at $0000, $0400, $0800, $0C00, $1000, $1400, $1800, $1C00
*# 1 KiB switchable CHR banks at $0000, $0400, $0800, $0C00, $1000, $1400, $1800, $1C00
*# 2 KB switchable CHR banks at $0000, $0800; 1 KB switchable CHR banks at $1000, $1400, $1800, $1C00  
*# 2 KiB switchable CHR banks at $0000, $0800; 1 KiB switchable CHR banks at $1000, $1400, $1800, $1C00  
*# 2 KB switchable CHR banks at $1000, $1800; 1 KB switchable CHR banks at $0000, $0400, $0800, $0C00
*# 2 KiB switchable CHR banks at $1000, $1800; 1 KiB switchable CHR banks at $0000, $0400, $0800, $0C00


== Registers ==
== Registers ==


The RAMBO-1 has 4 pairs of registers at $8000-$9FFF, $A000-$BFFF, $C000-$DFFF, and $E000-$FFFF - even addresses ($8000, $8002, etc.) select the low register and odd addresses ($8001, $8003, etc.) select the high register in each pair.
The RAMBO-1 has four pairs of registers at $8000-$9FFF, $A000-$BFFF, $C000-$DFFF, and $E000-$FFFF - even addresses ($8000, $8002, etc.) select the low register and odd addresses ($8001, $8003, etc.) select the high register in each pair.


=== Bank select ($8000-$9FFE, even) ===
=== Bank select ($8000-$9FFE, even) ===
Line 31: Line 50:
  |||  ||||
  |||  ||||
  |||  ++++- Specify which bank register to update on next write to Bank Data register
  |||  ++++- Specify which bank register to update on next write to Bank Data register
  |||       0: Select 2 (K=0) or 1 (K=1) KB CHR bank at PPU $0000 (or $1000);
  |||         0000: R0: Select 2 (K=0) or 1 (K=1) KiB CHR bank at PPU $0000 (or $1000)
  |||       1: Select 2 (K=0) or 1 (K=1) KB CHR bank at PPU $0800 (or $1800);
  |||         0001: R1: Select 2 (K=0) or 1 (K=1) KiB CHR bank at PPU $0800 (or $1800)
  |||       2: Select 1 KB CHR bank at PPU $1000-$13FF (or $0000-$03FF);
  |||         0010: R2: Select 1 KiB CHR bank at PPU $1000-$13FF (or $0000-$03FF)
  |||       3: Select 1 KB CHR bank at PPU $1400-$17FF (or $0400-$07FF);
  |||         0011: R3: Select 1 KiB CHR bank at PPU $1400-$17FF (or $0400-$07FF)
  |||       4: Select 1 KB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF);
  |||         0100: R4: Select 1 KiB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF)
  |||       5: Select 1 KB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF);
  |||         0101: R5: Select 1 KiB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF)
  |||       6: Select 8 KB PRG ROM bank at $8000-$9FFF (or $A000-$BFFF);
  |||         0110: R6: Select 8 KiB PRG ROM bank at $8000-$9FFF (or $C000-$DFFF)
  |||       7: Select 8 KB PRG ROM bank at $A000-$BFFF (or $C000-$DFFF);
  |||         0111: R7: Select 8 KiB PRG ROM bank at $A000-$BFFF
  |||       8: If K=1, Select 1 KB CHR bank at PPU $0400 (or $1400);
  |||         1000: R8: If K=1, Select 1 KiB CHR bank at PPU $0400 (or $1400)
  |||       9: If K=1, Select 1 KB CHR bank at PPU $0C00 (or $1C00);
  |||         1001: R9: If K=1, Select 1 KiB CHR bank at PPU $0C00 (or $1C00)
  |||       F: Select 8 KB PRG ROM bank at $C000-$DFFF (or $8000-$9FFF);
  |||         1111: RF: Select 8 KiB PRG ROM bank at $C000-$DFFF (or $8000-$9FFF)
  ||+------- Full 1KB CHR bank mode (0: two 2KB banks at $0000-$0FFF (or $1000-$1FFF),
  ||+------- Full 1 KiB CHR bank mode 0: two 2 KiB banks at $0000-$0FFF (or $1000-$1FFF)
  ||                                 1: four 1KB banks at $0000-$0FFF (or $1000-$1FFF))
  ||                                   1: four 1 KiB banks at $0000-$0FFF (or $1000-$1FFF)
  |+-------- PRG ROM bank mode (0: $8000-$9FFF uses bank selected with R:6,
  |+-------- PRG ROM bank mode 0: $8000-$9FFF uses bank selected with R6
  |                                $A000-$BFFF uses bank selected with R:7,
  |                                $A000-$BFFF uses bank selected with R7
  |                                $C000-$DFFF uses bank selected with R:F;
  |                                $C000-$DFFF uses bank selected with RF
  |                            1: $8000-$9FFF uses bank selected with R:F,
  |                            1: $8000-$9FFF uses bank selected with RF
  |                                $A000-$BFFF uses bank selected with R:6, -- NOT 7
  |                                $A000-$BFFF uses bank selected with R7
  |                                $C000-$DFFF uses bank selected with R:7) -- NOT 6
  |                                $C000-$DFFF uses bank selected with R6
  +--------- CHR A12 inversion (0: two 2 KB banks (or four 1 KB banks) at $0000-$0FFF,
  +--------- CHR A12 inversion 0: two 2 KiB banks (or four 1 KiB banks) at $0000-$0FFF
                                   four 1 KB banks at $1000-$1FFF;
                                   four 1 KiB banks at $1000-$1FFF
                               1: two 2 KB banks (or four 1 KB banks) at $1000-$1FFF,
                               1: two 2 KiB banks (or four 1 KiB banks) at $1000-$1FFF
                                   four 1 KB banks at $0000-$0FFF)
                                   four 1 KiB banks at $0000-$0FFF


In PRG ROM bank mode 1, the functions of registers 6 and 7 are ''backward'' compared to the corresponding mode of MMC3.
==== CHR Banks ====
{| class="wikitable"
! When $8000 & $80 !! is $00 !! is $80
|-
! PPU Bank !! colspan=2|Value of RAMBO-1 register
|-
| $0000-$03FF || R0 || R2
|-
| $0400-$07FF || K=0: R0<br/>K=1: R8 || R3
|-
| $0800-$0BFF || R1 || R4
|-
| $0C00-$0FFF || K=0: R1<br/>K=1: R9 || R5
|-
| $1000-$13FF || R2 || R0
|-
| $1400-$17FF || R3 || K=0: R0<br/>K=1: R8
|-
| $1800-$1BFF || R4 || R1
|-
| $1C00-$1FFF || R5 || K=0: R1<br/>K=1: R9
|}
With 2KiB banks (where K=0), only even-numbered CHR banks can be selected. The lowest bit in the register is ignored and instead passes PPU A10 directly through to CHR A10.
 
==== PRG Banks ====
Because the values in R6, R7, RF, and $8000 are unspecified at power on, the reset vector must point into $E000-$FFFF, and code must initialize these before jumping out of $E000-$FFFF.
 
{| class="wikitable"
! When $8000 & $40 !! is $00 !! is $40
|-
! CPU Bank !! colspan=2|Value of RAMBO-1 register
|-
| $8000-$9FFF || R6 || RF
|-
| $A000-$BFFF || R7 || R7
|-
| $C000-$DFFF || RF || R6
|-
| $E000-$FFFF || (-1) || (-1)
|}
* (-1) : the last bank


=== Bank data ($8001-$9FFF, odd) ===
=== Bank data ($8001-$9FFF, odd) ===
7  bit  0
All eight bits are used for a new value for the bank based on last value written to Bank select register (as mentioned above)
---- ----
DDDD DDDD
|||| ||||
++++-++++- New bank value, based on last value written to Bank select register (mentioned above)


=== Mirroring ($A000-$BFFE, even) ===
=== Mirroring ($A000-$BFFE, even) ===
Line 71: Line 126:
         +- [[Mirroring]] (0: vertical; 1: horizontal)
         +- [[Mirroring]] (0: vertical; 1: horizontal)


This applies to mapper 64 only (see Variants below).
This applies to '''mapper 64''' only (see [[#Variants|Variants]] below).
 
=== Unknown ($A001-$BFFF, odd) ===
This register is either not implemented or has undiscovered functionality on RAMBO-1.  The MMC3/MMC6 equivalent of this register controls external and internal PRG-RAM access.  There is not presently any reason to believe that RAMBO-1 has any support for PRG-RAM.
 
== IRQ registers ==


=== IRQ latch ($C000-$DFFE, even) ===
=== IRQ latch ($C000-$DFFE, even) ===
7  bit  0
All eight bits of this register specifies the IRQ counter reload value. When the IRQ counter is zero (or a reload is requested through $C001), this value will be copied into the IRQ counter at the end of the current scanline.
---- ----
DDDD DDDD
|||| ||||
++++-++++- IRQ latch value
 
This register specifies the IRQ counter reload value. When the IRQ counter is zero (or a reload is requested through $C001), this value will be copied into the IRQ counter at the end of the current scanline.


=== IRQ mode select / reload ($C001-$DFFF, odd) ===
=== IRQ mode select / reload ($C001-$DFFF, odd) ===
Line 92: Line 146:


=== IRQ acknowledge / disable ($E000-$FFFE, even) ===
=== IRQ acknowledge / disable ($E000-$FFFE, even) ===
7  bit  0
---- ----
xxxx xxxx
Writing any value to this register will disable counter interrupts AND acknowledge any pending interrupts.
Writing any value to this register will disable counter interrupts AND acknowledge any pending interrupts.


=== IRQ enable ($E001-$FFFF, odd) ===
=== IRQ enable ($E001-$FFFF, odd) ===
7  bit  0
Writing any value to this register will enable counter interrupts.  Note that writing to this register does not acknowledge the IRQ if already set.
---- ----
xxxx xxxx
 
Writing any value to this register will enable counter interrupts.


== IRQ counter operation ==
== IRQ counter operation ==
The counter can be set to either scanline mode or cpu cycle mode.
There are two IRQ modes: PPU A12 mode (also known as ''scanline mode'') and CPU cycle mode.


In scanline mode, the counter is clocked using the same method the [[MMC3]] uses, and follows the same restrictions. However, the actual interrupt seems to trigger 5 pixels later, compared to the [[MMC3]].
In ''scanline mode'', the counter is clocked using a very similar method to that used by the [[MMC3]] and follows the same restrictions. In comparison to the [[MMC3]], the actual interrupt triggers slightly later. Specifically, it is delayed until [http://forums.nesdev.org/viewtopic.php?p=117323#p117323 M2 falls twice after the PPU A12 rise] that would have triggered the MMC3 interrupt.


In CPU cycle mode, the counter is clocked every 4 CPU cycles. Again, the actual interrupt seems to trigger 5 pixels later than when they're fired.
In ''CPU cycle mode'', the counter is clocked every 4 CPU cycles. The actual interrupt triggers [http://forums.nesdev.org/viewtopic.php?p=117461#p117461 one M2 cycle later] than one would naively expect.


Whichever method is being used, the counter behaves the following way:
Whichever IRQ mode is being used, the counter behaves the following way:


* '''IF''' $C001 was written to after previous clock
'''When the IRQ is clocked by ''scanline'' or ''CPU cycle'' modes:'''
** reload IRQ counter with IRQ Reload value '''PLUS ONE''' (see note)
* '''IF''' $C001 was written to after previous clock:
* '''ELSE IF''' IRQ counter is 0
** reload IRQ counter with IRQ reload value; if non zero, this value is '''ORed with 1''' (see notes).
** reload IRQ counter with IRQ Reload value
* '''ELSE IF''' IRQ counter is 0:
** reload IRQ counter with IRQ reload value.
* '''ELSE'''
* '''ELSE'''
** Decrement IRQ counter by 1
** Decrement IRQ counter by 1.
** '''IF''' IRQ counter is now 0 '''AND''' IRQs are enabled
* If IRQ counter is now 0 '''AND''' IRQs are enabled:
*** trigger IRQ (which takes effect 5 pixels later)
** trigger IRQ after 4 CPU cycles.
 
'''Notes:'''
* It's still unknown how the extra kick works. ''Klax'' still requires '''+1''' to run perfectly.
* Most emulators run ''Skull & Crossbones'' with a glitched scanline on the "Continue" screen OR during the game (score bar).
 
Following these rules in scanline counter mode has demonstrated accurate behavior, but this needs to be refined and merged with the description above:


'''Note:''' When $C001 is written to, it's unknown as to whether reload+1 is written to the counter, or if the counter just takes an extra clock to start counting.
On M2 falling edge:
    If PA12 = 0:
        If 4-bit counter < 16: 4-bit counter++.
        else keep the same value.
    If PA12 = 1:
        If 4-bit counter = 16: Clock the 8-bit counter.
        Always reset 4-bit counter to 0.
On 8-bit counter clock:
    If value = 0:
        If IRQ is enabled, trigger IRQ (wait 1 more cycle before doing that though, regardless of PA12 next cycle...)
        Always reload counter with value in $C000.
    Else value--.
On Write to $C001 (reset):
    Reload 8-bit counter with value in $C000
    Set 4-bit counter to 17.


== Variants ==
== Variants ==
Mapper 64 has mirroring like mapper 4, as described above.
[[iNES Mapper 158|Mapper 158]], used for ''Alien Syndrome'', has mirroring like [[iNES Mapper 118|mapper 118]] ([[TLSROM]]), where CIRAM A10 is connected to CHR A17, and bit 7 of each CHR bank mapped into PPU $0000-$0FFF controls which page of CIRAM is used for the corresponding nametable in $2000-$2FFF.
Mapper 158, used for ''Alien Syndrome'', has mirroring like [[iNES Mapper 118|mapper 118]] (TLSROM), where CIRAM A10 is connected to CHR A17, and bit 7 of each CHR bank mapped into PPU $0000-$0FFF controls which page of CIRAM is used for the corresponding nametable in $2000-$2FFF.


== Disch's Notes ==
== See also ==
  Here are Disch's original notes: 
*[http://www.romhacking.net/documents/362/ NES Mapper List] by Disch
  ========================
*[http://nesdev.org/mappers.zip Comprehensive NES Mapper Document] by \Firebug\, information about mapper's initial state is inaccurate.
  =  Mapper 064          =
  ========================
 
 
  aka
  --------------------------
  Tengen RAMBO-1
 
 
 
  Example Games:
  --------------------------
  Klax
  Skull and Crossbones
  Shinobi
 
 
  Notes:
  --------------------------
  This mapper is very similar to MMC3.  It uses a similar swapping system, but adds a little functionality.
 
  IRQs are set up similar as well... but have some major differences.
 
  This is one of those mappers that is a big pain to implement in an emu -- especially since so few games use
  it.  And the games that use it really blow hard.
 
 
  Registers:
  --------------------------
 
  Range,Mask:  $8000-FFFF, $E001
 
    $8000:  [CPK. AAAA]
      C = CHR mode select
      P = PRG mode select
      K = full 1k CHR mode select (see CHR setup)
      A = Address for use with $8001
 
    $8001:  [DDDD DDDD]  Data port
      R:0 ->  CHR reg 0
      R:1 ->  CHR reg 1
      R:2 ->  CHR reg 2
      R:3 ->  CHR reg 3
      R:4 ->  CHR reg 4
      R:5 ->  CHR reg 5
      R:6 ->  PRG reg 0
      R:7 ->  PRG reg 1
      R:8 ->  CHR reg 6
      R:9 ->  CHR reg 7
        R:A - R:E not used
      R:F ->  PRG reg 2
 
    $A000:  [.... ...M]   Mirroring
      0 = Vert
      1 = Horz
 
 
 
    $C000:  [IIII IIII]  IRQ Reload value
    $C001: [.... ...M]  IRQ Mode select and reset
      0 = Scanline (A12) mode
      1 = Cycle mode
 
    $E000:  [.... ....]  IRQ Acknowledge/Disable
    $E001:  [.... ....]  IRQ Enable
 
 
  PRG Setup:
  ---------------------------
 
  PRG mode is selected via $8000.6
 
                $8000  $A000  $C000  $E000 
              +-------+-------+-------+-------+
  PRG Mode 0:  |  R:6  |  R:7  |  R:F  | { -1} |
              +-------+-------+-------+-------+
  PRG Mode 1:  |  R:F  |  R:6  |  R:7  | { -1} |
              +-------+-------+-------+-------+
 
 
  CHR Setup:
  ---------------------------
 
  $8000 has 2 bits to configure CHR modes.  Therefore there are effectively 4 CHR modes.
 
    $8000:  [CPK. AAAA]   <---  C and K bits relevant to CHR
 
 
                $0000  $0400  $0800  $0C00  $1000  $1400  $1800  $1C00
              +---------------+---------------+-------+-------+-------+-------+
  C=0, K=0    |    <R:0>    |    <R:1>    |  R:2  |  R:3  |  R:4  |  R:5  |
              +---------------+---------------+-------+-------+-------+-------+
  C=0, K=1    |  R:0  |  R:8  |  R:1  |  R:9  |  R:2  |  R:3  |  R:4  |  R:5  |
              +-------+-------+-------+-------+---------------+---------------+
  C=1, K=0    |  R:2  |  R:3  |  R:4  |  R:5  |    <R:0>    |    <R:1>    |
              +-------+-------+-------+-------+---------------+---------------+
  C=1, K=1    |  R:2  |  R:3  |  R:4  |  R:5  |  R:0  |  R:8  |  R:1  |  R:9  |
              +-------+-------+-------+-------+-------+-------+-------+-------+
 
 
 
  IRQs:
  ---------------------------
 
  There are two separate IRQ modes.  One uses A12 to count scanlines in a manner just like MMC3 does (see
  mapper 004 for details on how scanlines are counted and the restrictions involved).  The other mode uses CPU
  cycles with a 4-step prescaler (so the IRQ counter gets clocked every 4 CPU cycles).
 
  Regardless of the mode used to clock the counter... every time the counter is clocked, the following actions
  occur:
 
  - If Reset reg ($C001) was written to after previous clock...
      a)  reload IRQ counter with IRQ Reload value **PLUS ONE**
 
  - Otherwise... If IRQ Counter is 0...
      a)  reload IRQ counter with IRQ Reload value
 
  - Otherwise...
      a)  Decrement IRQ counter by 1
      b)  If IRQ counter is now 0 and IRQs are enabled, trigger IRQ
 
 
  Just like with MMC3, the counter is clocked and updated even when IRQs are disabled -- however IRQs will only
  be triggered when enabled.
 
  Note about the plus one:  I'm not sure if 1 is really added or if there's simply an additional 1 clock delay
  before the IRQ counter is updated.  From a software standpoint, it doesn't really matter -- adding the
  additional 1 works without any side-effects.
 
 
  Registers involved with IRQs:
  ---------------------------
 
    $C000:  [IIII IIII] - IRQ Reload value
 
    $C001:  [.... ...M] - IRQ Reset reg, mode select
      0 = Scanline mode (A12)
      1 = CPU Cycle mode (with prescaler)
 
      Any write to this register will make it so that the IRQ counter will reload with the reload value +1 on
  its next clock.  Whether or not writing to this register clears the IRQ counter like it does with MMC3 isn't
  known... and doesn't matter, since it's reloaded later anyway.
 
      Also, any write to this register will reset the CPU cycle prescaler (so that it will be 4 CPU cycles
  until the next clock).
 
    $E000:  [.... ....] - IRQ Acknowledge/Disable
      Any write to this register will acknowledge the pending IRQ, and disable IRQs
 
    $E001:  [.... ....] - IRQ Enable
      Any write to this register will enable IRQs
 
 
 
  A note about IRQs:
  ------------------
 
    Scanline IRQs seem to trip a little later than they do on the MMC3.  It looks like about a 5 dot delay
  from the normal MMC3 IRQ time (265 instead of 260).  Failure to put in this delay results in shaking and
  other graphical quirks in some games... notably Klax.  This delay also seems to exist for CPU cycle driven
  IRQs (Skull & Crossbones will suffer without it).  Perhaps the RAMBO-1's IRQ generating hardware is a little
  slower than usual?
 
    Apart from that timing difference, A12 clocks RAMBO-1's IRQ counter just exactly like it does MMC3, so all
  the notes about A12, $2006/7, etc from the mapper 004 documentation apply to this mapper as well.

Latest revision as of 13:48, 7 March 2021

RAMBO-1
Company Tengen
Games 5 in NesCartDB
Complexity ASIC
Boards 800032
Pinout Tengen RAMBO-1 pinout
PRG ROM capacity 256K
PRG ROM window 3×8K + 8K fixed
PRG RAM capacity None
CHR capacity 256K
CHR window 1Kx8 or 2Kx2 + 1Kx4
Nametable mirroring H or V, switchable
Bus conflicts No
IRQ Yes
Audio No
iNES mappers 064, 158
NESCartDB
iNES 064
800032
For the mapper used in the game "Rambo", see UxROM.

The Tengen RAMBO-1 is an ASIC mapper, canonically designated as mapper 64. This mapper is basically Tengen's version of the MMC3, but with some extra features. The RAMBO-1 came as a 40-pin PDIP. A variant with different mirroring control is mapper 158.

Example games:

  • Klax
  • Skull and Crossbones
  • Shinobi
  • Rolling Thunder
  • Hard Drivin' (prototype)

Banks

  • CPU $8000-$9FFF: 8 KiB switchable PRG ROM bank
  • CPU $A000-$BFFF: 8 KiB switchable PRG ROM bank
  • CPU $C000-$DFFF: 8 KiB switchable PRG ROM bank
  • CPU $E000-$FFFF: 8 KiB PRG ROM bank, fixed to the last bank
  • PPU -- Three selectable configurations:
    1. 1 KiB switchable CHR banks at $0000, $0400, $0800, $0C00, $1000, $1400, $1800, $1C00
    2. 2 KiB switchable CHR banks at $0000, $0800; 1 KiB switchable CHR banks at $1000, $1400, $1800, $1C00
    3. 2 KiB switchable CHR banks at $1000, $1800; 1 KiB switchable CHR banks at $0000, $0400, $0800, $0C00

Registers

The RAMBO-1 has four pairs of registers at $8000-$9FFF, $A000-$BFFF, $C000-$DFFF, and $E000-$FFFF - even addresses ($8000, $8002, etc.) select the low register and odd addresses ($8001, $8003, etc.) select the high register in each pair.

Bank select ($8000-$9FFE, even)

7  bit  0
---- ----
CPKx RRRR
|||  ||||
|||  ++++- Specify which bank register to update on next write to Bank Data register
|||          0000: R0: Select 2 (K=0) or 1 (K=1) KiB CHR bank at PPU $0000 (or $1000)
|||          0001: R1: Select 2 (K=0) or 1 (K=1) KiB CHR bank at PPU $0800 (or $1800)
|||          0010: R2: Select 1 KiB CHR bank at PPU $1000-$13FF (or $0000-$03FF)
|||          0011: R3: Select 1 KiB CHR bank at PPU $1400-$17FF (or $0400-$07FF)
|||          0100: R4: Select 1 KiB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF)
|||          0101: R5: Select 1 KiB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF)
|||          0110: R6: Select 8 KiB PRG ROM bank at $8000-$9FFF (or $C000-$DFFF)
|||          0111: R7: Select 8 KiB PRG ROM bank at $A000-$BFFF
|||          1000: R8: If K=1, Select 1 KiB CHR bank at PPU $0400 (or $1400)
|||          1001: R9: If K=1, Select 1 KiB CHR bank at PPU $0C00 (or $1C00)
|||          1111: RF: Select 8 KiB PRG ROM bank at $C000-$DFFF (or $8000-$9FFF)
||+------- Full 1 KiB CHR bank mode  0: two 2 KiB banks at $0000-$0FFF (or $1000-$1FFF)
||                                   1: four 1 KiB banks at $0000-$0FFF (or $1000-$1FFF)
|+-------- PRG ROM bank mode  0: $8000-$9FFF uses bank selected with R6
|                                $A000-$BFFF uses bank selected with R7
|                                $C000-$DFFF uses bank selected with RF
|                             1: $8000-$9FFF uses bank selected with RF
|                                $A000-$BFFF uses bank selected with R7
|                                $C000-$DFFF uses bank selected with R6
+--------- CHR A12 inversion  0: two 2 KiB banks (or four 1 KiB banks) at $0000-$0FFF
                                 four 1 KiB banks at $1000-$1FFF
                              1: two 2 KiB banks (or four 1 KiB banks) at $1000-$1FFF
                                 four 1 KiB banks at $0000-$0FFF

CHR Banks

When $8000 & $80 is $00 is $80
PPU Bank Value of RAMBO-1 register
$0000-$03FF R0 R2
$0400-$07FF K=0: R0
K=1: R8
R3
$0800-$0BFF R1 R4
$0C00-$0FFF K=0: R1
K=1: R9
R5
$1000-$13FF R2 R0
$1400-$17FF R3 K=0: R0
K=1: R8
$1800-$1BFF R4 R1
$1C00-$1FFF R5 K=0: R1
K=1: R9

With 2KiB banks (where K=0), only even-numbered CHR banks can be selected. The lowest bit in the register is ignored and instead passes PPU A10 directly through to CHR A10.

PRG Banks

Because the values in R6, R7, RF, and $8000 are unspecified at power on, the reset vector must point into $E000-$FFFF, and code must initialize these before jumping out of $E000-$FFFF.

When $8000 & $40 is $00 is $40
CPU Bank Value of RAMBO-1 register
$8000-$9FFF R6 RF
$A000-$BFFF R7 R7
$C000-$DFFF RF R6
$E000-$FFFF (-1) (-1)
  • (-1) : the last bank

Bank data ($8001-$9FFF, odd)

All eight bits are used for a new value for the bank based on last value written to Bank select register (as mentioned above)

Mirroring ($A000-$BFFE, even)

7  bit  0
---- ----
xxxx xxxM
        |
        +- Mirroring (0: vertical; 1: horizontal)

This applies to mapper 64 only (see Variants below).

Unknown ($A001-$BFFF, odd)

This register is either not implemented or has undiscovered functionality on RAMBO-1. The MMC3/MMC6 equivalent of this register controls external and internal PRG-RAM access. There is not presently any reason to believe that RAMBO-1 has any support for PRG-RAM.

IRQ registers

IRQ latch ($C000-$DFFE, even)

All eight bits of this register specifies the IRQ counter reload value. When the IRQ counter is zero (or a reload is requested through $C001), this value will be copied into the IRQ counter at the end of the current scanline.

IRQ mode select / reload ($C001-$DFFF, odd)

7  bit  0
---- ----
xxxx xxxM
        |
        +- IRQ mode select (0: Scanline Mode, 1: CPU Cycle Mode)

Writing to this register also clears the IRQ counter so that it will be reloaded at next clock, or the next scanline, depending on the selected mode. This also resets the prescaler in cycle mode, so the next clock will occur 4 cycles later.

IRQ acknowledge / disable ($E000-$FFFE, even)

Writing any value to this register will disable counter interrupts AND acknowledge any pending interrupts.

IRQ enable ($E001-$FFFF, odd)

Writing any value to this register will enable counter interrupts. Note that writing to this register does not acknowledge the IRQ if already set.

IRQ counter operation

There are two IRQ modes: PPU A12 mode (also known as scanline mode) and CPU cycle mode.

In scanline mode, the counter is clocked using a very similar method to that used by the MMC3 and follows the same restrictions. In comparison to the MMC3, the actual interrupt triggers slightly later. Specifically, it is delayed until M2 falls twice after the PPU A12 rise that would have triggered the MMC3 interrupt.

In CPU cycle mode, the counter is clocked every 4 CPU cycles. The actual interrupt triggers one M2 cycle later than one would naively expect.

Whichever IRQ mode is being used, the counter behaves the following way:

When the IRQ is clocked by scanline or CPU cycle modes:

  • IF $C001 was written to after previous clock:
    • reload IRQ counter with IRQ reload value; if non zero, this value is ORed with 1 (see notes).
  • ELSE IF IRQ counter is 0:
    • reload IRQ counter with IRQ reload value.
  • ELSE
    • Decrement IRQ counter by 1.
  • If IRQ counter is now 0 AND IRQs are enabled:
    • trigger IRQ after 4 CPU cycles.

Notes:

  • It's still unknown how the extra kick works. Klax still requires +1 to run perfectly.
  • Most emulators run Skull & Crossbones with a glitched scanline on the "Continue" screen OR during the game (score bar).

Following these rules in scanline counter mode has demonstrated accurate behavior, but this needs to be refined and merged with the description above:

On M2 falling edge:
   If PA12 = 0:
       If 4-bit counter < 16: 4-bit counter++.
       else keep the same value.
   If PA12 = 1:
       If 4-bit counter = 16: Clock the 8-bit counter.
       Always reset 4-bit counter to 0.

On 8-bit counter clock:
   If value = 0:
       If IRQ is enabled, trigger IRQ (wait 1 more cycle before doing that though, regardless of PA12 next cycle...)
       Always reload counter with value in $C000.
   Else value--.

On Write to $C001 (reset):
   Reload 8-bit counter with value in $C000
   Set 4-bit counter to 17.

Variants

Mapper 158, used for Alien Syndrome, has mirroring like mapper 118 (TLSROM), where CIRAM A10 is connected to CHR A17, and bit 7 of each CHR bank mapped into PPU $0000-$0FFF controls which page of CIRAM is used for the corresponding nametable in $2000-$2FFF.

See also