The 13-bit address bus
The 6507 has address lines A0 to A12, so every address is taken modulo 8 KiB: $F000 and $1000 are the same
place. Three chips decode the bus:
| Address (13 bits) | What | How it is decoded |
|---|---|---|
$0000-$007F | TIA registers | A12 low and A7 low; only A0-A5 are used, so $40-$7F repeats $00-$3F |
$0080-$00FF | RIOT RAM, 128 bytes | A12 low, A9 low, A7 high. The zero page, and the stack at $0180-$01FF is the same RAM |
$0280-$029F | RIOT I/O and timer | A12 low, A9 high, A7 high; the registers repeat in the range |
$1000-$1FFF | Cartridge ROM | A12 high. Bank-switching hotspots are decoded here (and a few below) |
The mirrors of the TIA and the RAM are real and used by some programs; the explorer names only the addresses listed below, so an access through a mirror shows as a plain number.
Vectors
Three 16-bit little-endian addresses at the top of the 6502’s memory: NMI at $FFFA, RESET at $FFFC and IRQ/BRK at
$FFFE. With 13 address lines they are read from $1FFA-$1FFF, the last six bytes of the bank that is in the window. The 6507
has no interrupt pins, so a 2600 program uses only RESET (and BRK, which many programs use as a second entry). The values are usually
written for $F000, such as $F000 in both starfield.bin and flapping.bin, and the explorer shows the code at the
address you choose in the options bar ($F000 by default).
Banked ROMs have vectors in every bank. On real hardware the console does not know which bank is selected at power-up, so a good ROM has a reset vector in every bank that leads to the same code. The explorer reads the vectors of the bank chosen in the options bar (the scheme’s usual start bank by default) and tabulates the vectors of every bank.
TIA registers
The names are those of the standard “stella” register file. Reading and writing the same address reach different registers; a name with a slash is write / read. The explorer cannot tell a read from a write, so it shows both names.
| Address | Name | What |
|---|---|---|
| $00 | VSYNC/CXM0P | Write: vertical sync (bit 1). Read: collision of missile 0 with players |
| $01 | VBLANK/CXM1P | Write: vertical blank, input latch, paddle dump. Read: collision of missile 1 with players |
| $02 | WSYNC/CXP0FB | Write: halt the CPU until the next line. Read: player 0 with playfield and ball |
| $03 | RSYNC/CXP1FB | Write: reset the horizontal sync counter. Read: player 1 with playfield and ball |
| $04 | NUSIZ0/CXM0FB | Write: number and size of player and missile 0. Read: missile 0 with playfield and ball |
| $05 | NUSIZ1/CXM1FB | Write: number and size of player and missile 1. Read: missile 1 with playfield and ball |
| $06 | COLUP0/CXBLPF | Write: colour of player and missile 0. Read: ball with playfield |
| $07 | COLUP1/CXPPMM | Write: colour of player and missile 1. Read: players with players, missiles with missiles |
| $08 | COLUPF/INPT0 | Write: colour of playfield and ball. Read: paddle input 0 |
| $09 | COLUBK/INPT1 | Write: colour of the background. Read: paddle input 1 |
| $0A | CTRLPF/INPT2 | Write: playfield control and ball size. Read: paddle input 2 |
| $0B | REFP0/INPT3 | Write: reflect player 0. Read: paddle input 3 |
| $0C | REFP1/INPT4 | Write: reflect player 1. Read: fire button of joystick 0 |
| $0D | PF0/INPT5 | Write: playfield graphics, first part. Read: fire button of joystick 1 |
| $0E | PF1 | Playfield graphics, second part |
| $0F | PF2 | Playfield graphics, third part |
| $10 | RESP0 | Reset the position of player 0 |
| $11 | RESP1 | Reset the position of player 1 |
| $12 | RESM0 | Reset the position of missile 0 |
| $13 | RESM1 | Reset the position of missile 1 |
| $14 | RESBL | Reset the position of the ball |
| $15 | AUDC0 | Audio control of channel 0 |
| $16 | AUDC1 | Audio control of channel 1 |
| $17 | AUDF0 | Audio frequency of channel 0 |
| $18 | AUDF1 | Audio frequency of channel 1 |
| $19 | AUDV0 | Audio volume of channel 0 |
| $1A | AUDV1 | Audio volume of channel 1 |
| $1B | GRP0 | Graphics of player 0 |
| $1C | GRP1 | Graphics of player 1 |
| $1D | ENAM0 | Enable missile 0 |
| $1E | ENAM1 | Enable missile 1 |
| $1F | ENABL | Enable the ball |
| $20 | HMP0 | Horizontal motion of player 0 |
| $21 | HMP1 | Horizontal motion of player 1 |
| $22 | HMM0 | Horizontal motion of missile 0 |
| $23 | HMM1 | Horizontal motion of missile 1 |
| $24 | HMBL | Horizontal motion of the ball |
| $25 | VDELP0 | Vertical delay of player 0 |
| $26 | VDELP1 | Vertical delay of player 1 |
| $27 | VDELBL | Vertical delay of the ball |
| $28 | RESMP0 | Reset missile 0 to player 0 |
| $29 | RESMP1 | Reset missile 1 to player 1 |
| $2A | HMOVE | Apply the horizontal motion registers |
| $2B | HMCLR | Clear the horizontal motion registers |
| $2C | CXCLR | Clear the collision latches |
RIOT registers
The 6532 RIOT has 128 bytes of RAM at $80-$FF (not named in the disassembly) and these registers. The same addresses and names were
checked against the register numbers js7800 uses for the 7800’s RIOT, which is the same chip at the same addresses.
| Address | Name | What |
|---|---|---|
| $280 | SWCHA | Port A data: the joysticks |
| $281 | SWACNT | Port A data direction |
| $282 | SWCHB | Port B data: the console switches |
| $283 | SWBCNT | Port B data direction |
| $284 | INTIM | Read: the timer |
| $285 | INSTAT | Read: timer interrupt flags |
| $294 | TIM1T | Set the timer, one count per cycle |
| $295 | TIM8T | Set the timer, one count per 8 cycles |
| $296 | TIM64T | Set the timer, one count per 64 cycles |
| $297 | T1024T | Set the timer, one count per 1024 cycles |
Not described
Known, not yet covered
- Viewer: the TIA and RAM mirrors are not named in the disassembly.
Unknown
- Reference: the register descriptions are summaries; the TIA register bits are not described one by one. No Stella source or manual was available to compare the names beyond the TIA audio and RIOT addresses that js7800 shares.