RAMBO-1
The Tengen RAMBO-1 is an ASIC mapper, assigned to iNES mapper 64. This mapper is basically Tengen's version of the MMC3, but with some extra features.
Overview
- PRG ROM size: Up to 256 KB
- PRG ROM bank size: 8 KB
- PRG RAM: Unknown
- CHR capacity: Up to 256 KB ROM
- CHR bank size: All 1 KB, or 2 2KB and 4 1KB
- Nametable mirroring: Controlled by mapper
- Subject to bus conflicts: No
Banks
- CPU $8000-$9FFF: 8 KB switchable PRG ROM bank
- CPU $A000-$BFFF: 8 KB switchable PRG ROM bank
- CPU $C000-$DFFF: 8 KB switchable PRG ROM bank
- CPU $E000-$FFFF: 8 KB PRG ROM bank, fixed to the last bank
- PPU -- Three selectable configurations:
- 1 KB 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 KB switchable CHR banks at $1000, $1800; 1 KB switchable CHR banks at $0000, $0400, $0800, $0C00
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.
Bank select ($8000-$9FFE, even)
7 bit 0 ---- ---- CPKx RRRR ||| |||| ||| ++++- 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); ||| 1: Select 2 (K=0) or 1 (K=1) KB CHR bank at PPU $0800 (or $1800); ||| 2: Select 1 KB CHR bank at PPU $1000-$13FF (or $0000-$03FF); ||| 3: Select 1 KB CHR bank at PPU $1400-$17FF (or $0400-$07FF); ||| 4: Select 1 KB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF); ||| 5: Select 1 KB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF); ||| 6: Select 8 KB PRG bank at $8000-$9FFF (or $A000-$BFFF); ||| 7: Select 8 KB PRG bank at $A000-$BFFF (or $C000-$DFFF); ||| 8: If K=1, Select 1 KB CHR bank at PPU $0400 (or $1400); ||| 9: If K=1, Select 1 KB CHR bank at PPU $0C00 (or $1C00); ||| F: Select 8 KB PRG bank at $C000-$DFFF (or $8000-$9FFF); ||+------- Full 1KB CHR ROM bank mode (0: two 2KB banks at $0000-$0FFF (or $1000-$1FFF), || 1: four 1KB banks at $0000-$0FFF (or $1000-$1FFF)) |+-------- PRG ROM bank configuration (0: $8000-$9FFF uses bank selected with R:6, | $A000-$BFFF uses bank selected with R:7, | $C000-$DFFF uses bank selected with R:F; | 1: $8000-$9FFF uses bank selected with R:F, | $A000-$BFFF uses bank selected with R:6, -- NOT 7 | $C000-$DFFF uses bank selected with R:7) -- NOT 6 +--------- CHR ROM bank configuration (0: two 2 KB banks (or four 1 KB banks) at $0000-$0FFF, four 1 KB banks at $1000-$1FFF; 1: two 2 KB banks (or four 1 KB banks) at $1000-$1FFF, four 1 KB banks at $0000-$0FFF)
Bank data ($8001-$9FFF, odd)
7 bit 0 ---- ---- DDDD DDDD |||| |||| ++++-++++- New bank value, based on last value written to Bank select register (mentioned above)
Mirroring ($A000-$BFFE, even)
7 bit 0 ---- ---- xxxx xxxM | +- Mirroring (0: vertical; 1: horizontal)
IRQ latch ($C000-$DFFE, even)
7 bit 0 ---- ---- 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)
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)
7 bit 0 ---- ---- xxxx xxxx
Writing any value to this register will disable counter interrupts AND acknowledge any pending interrupts.
IRQ enable ($E001-$FFFF, odd)
7 bit 0 ---- ---- xxxx xxxx
Writing any value to this register will enable counter interrupts.
IRQ Counter Operation
The counter can be set to either scanline mode or 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 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.
Whichever method is being used, the counter behaves the following way:
- IF $C001 was written to after previous clock
- reload IRQ counter with IRQ Reload value PLUS ONE (see note)
- 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 (which takes effect 5 pixels later)
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.