Next Registers
The Next’s machine state is in a bank of registers reached through two ports, not through the Z80’s I/O space directly. Write the register number to $243B, then read or write its value at $253B. The NEXTREG instructions do both in one instruction; see Z80N Instructions.
nextreg $07,3 ; CPU speed: 28 MHzA read returns the write format with reserved and one-shot bits forced to zero, unless an entry below says otherwise.
The page describes the hardware, as the FPGA design defines it. The examples are Z80N assembly.
Machine configuration
These registers reconfigure the whole machine.
$02 Reset
| Bit | Meaning |
|---|---|
| 7 | bus / expansion reset |
| 4 | the I/O trap fired (read); see Sound and miscellaneous |
| 3 | generate a Multiface NMI, gated by $06 bit 3 |
| 2 | generate a DivMMC NMI, gated by $06 bit 4 |
| 1 | hard reset |
| 0 | soft reset |
⚠ Bits 2 and 3 are as shown. The design documentation and the wiki label them bit 3 DivMMC and bit 4 Multiface, which is wrong.
nextreg $02,%00000001 ; soft reset$03 Machine type and display timing
Bits[2:0] select the machine type: 111 enters config mode, 001 to 100 select a machine and leave config mode, and 000 changes neither. Bits[6:4] select the machine timing: 000 or 001 48K, 010 128K, 011 +3, and 1xx Pentagon. Bit 3 toggles the user lock on display timing. A read returns the palette sub-index in bit 7, then the machine timing, the lock bit and the machine type.
Config mode is not in the read-back, so a program cannot read whether it is in config mode. The machine type changes only in config mode; entering config mode does not require it, so a running program can re-enter config mode.
The timing bits select the ULA timing, the contention pattern and which banks are contended, as well as the frame length; see Machine Timing. Any write to $03 also disables the boot ROM.
A read of $32 means +3 timing (011) and the 128K machine type (010).
$05 Peripheral 1
| Bits | Meaning |
|---|---|
| 7–6 | left joystick mode, low bits |
| 5–4 | right joystick mode, low bits |
| 3 | left joystick mode, high bit |
| 2 | 60 Hz (1) or 50 Hz (0) |
| 1 | right joystick mode, high bit |
| 0 | scandouble |
The 50/60 Hz bit changes the vertical timing, so it changes the frame length, the interrupt line and the raster counter together. The joystick bits select what ports $1F and $37 present.
The 50/60 Hz and scandouble bits read back as the value latched at the last frame, so a read straight after a write can return the old value.
A value of $04 selects 60 Hz, with both joysticks in mode 0.
$06 Peripheral 2
| Bit | Meaning |
|---|---|
| 7 | CPU speed hotkey enable |
| 6 | internal speaker beep |
| 5 | 50/60 Hz hotkey enable |
| 4 | DivMMC NMI button enable, gating $02 bit 2 |
| 3 | Multiface NMI button enable, gating $02 bit 3 |
| 2 | PS/2 mode |
| 1–0 | PSG mode: 00 YM, 01 AY, 1x off |
The PSG mode selects the envelope behaviour and the volume curve. The Next starts in YM mode, a different timbre from an AY-3-8910.
nextreg $06,%10110001 ; both hotkeys, the DivMMC NMI button, AY mode$07 CPU speed
Bits[1:0] select 3.5, 7, 14 or 28 MHz. A read returns the actual speed in bits[5:4] and the programmed one in bits[1:0]. Enabling the expansion bus holds the actual speed at 3.5 MHz whatever is programmed. Machine Timing covers the 28 MHz wait state.
With the CPU running at 28 MHz after nextreg $07,3, a read returns $33.
$08 Peripheral 3
| Bit | Meaning |
|---|---|
| 7 | write 1 to unlock $7FFD paging |
| 6 | disable contention |
| 5 | PSG stereo mode, ABC or ACB: swaps the centre channel B with C |
| 4 | internal speaker enable |
| 3 | DAC enable, gating every DAC port |
| 2 | port $FF read enable |
| 1 | Turbosound enable |
| 0 | keyboard issue 2 |
nextreg $08,%00011010 ; speaker, DAC and Turbosound on$09 Peripheral 4
Bits[7:6] are the per-chip PSG mono bits, then the sprite-id lockstep, bit 4 the HDMI audio disable, bit 3 a one-shot that clears the DivMMC MAPRAM, and bits[1:0] the scanline weight. Bit 3 is the only way to clear MAPRAM short of a hard reset.
The scanline bits are cycled by the F7 hotkey, which is not gated by $06.
nextreg $09,%00001000 ; clear MAPRAM; scanlines off$0A Peripheral 5
| Bits | Meaning |
|---|---|
| 7–6 | Multiface type: 00 MF+3, 11 MF48, otherwise MF128. It changes the ports the Multiface answers on |
| 5 | SD card swap |
| 4 | DivMMC automap enable |
| 3 | mouse button reverse |
| 1–0 | mouse DPI |
The Multiface type and SD swap fields change only in config mode; the automap enable, button reverse and DPI change at any time. Clearing bit 4 resets the whole automap, the $0066 NMI entries included.
The DPI field scales each mouse packet in the mouse’s receiver, before the counters at ports $FBDF and $FFDF:
$0A bits 1–0 | Movement |
|---|---|
00 low | ×2 |
01 default | ×1 |
10 medium | ÷2 |
11 high | ÷4 |
A higher setting divides more, since a higher-resolution mouse sends more counts for the same movement. The scaling is applied to each packet, at 80 packets a second, and the results are summed, so slow movement at a high divisor produces no movement at all.
nextreg $0A,%00010010 ; automap on, mouse DPI medium$0B Joystick I/O mode
Bit 7 enables I/O mode, and bits[5:4] select it. Bit 4 also picks the joystick port, left or right. Bit 0 picks the UART for the serial modes: 0 the ESP (UART 0), 1 the Pi (UART 1).
| Bits 5–4 | Joystick pin 7 carries |
|---|---|
00 | bit 0, as a static level |
01 | a level toggled by CTC channel 3’s zero count. With bit 0 clear it toggles once, giving a single rising edge; with bit 0 set it toggles on every zero count, dividing by two |
10, 11 | the selected UART’s transmit line, on the left (10) or right (11) port |
In the serial modes the UART also takes its receive line from the pad’s C button pin and its CTS from the B button pin, both inverted, in place of the module connector, which is held off. CTS is live only when that UART uses hardware flow control.
$0B does not stop the joystick ports being read. $1F and $37 read the same pins the serial lines use. Pin 7 has no read-back path, so a program cannot read what it drove.
nextreg $0B,%10100000 ; the ESP's UART on the left joystick port$11 Video timing
Bits[2:0] select the display-timing profile. A write reprograms the clock generator, so every derived clock, the CPU’s included, moves together: a frame is the same number of cycles in every profile and only the wall-clock rate changes.
$11 | System clock, nominal (Hz) | System clock, achieved (Hz) |
|---|---|---|
| 0 | 28 000 000 | 28 000 000 |
| 1 | 28 571 429 | 28 583 333 |
| 2 | 29 464 286 | 29 437 500 |
| 3 | 30 000 000 | 30 000 000 |
| 4 | 31 000 000 | 31 000 000 |
| 5 | 32 000 000 | 32 000 000 |
| 6 | 33 000 000 | 33 000 000 |
Modes 1 and 2 do not reach their nominal rate; a rate derived from the profile uses the achieved column.
There is no mode 7. A write of 111 stores 000. On an issue 2 board only modes 0 and 1 exist, and a write keeps bit 0 alone. The register changes only in config mode.
The UART prescaler counts cycles of this clock, so a baud rate programmed as clock ÷ rate holds in every profile: 115200 baud in mode 3 is a prescaler of 30 000 000 ÷ 115 200 = 260.
Identity
| Reg | Meaning |
|---|---|
$00 / $01 | machine id / core version |
$0E / $0F | sub-version / board issue |
$10 | anti-brick, core id and the board buttons on read |
$7F | user scratch register |
Bizmuth emulates the KS3 board, whose machine id in $00 is $0A.
Video
Layer 2 and global
| Reg | Meaning |
|---|---|
$12 / $13 | Layer 2 active bank / shadow bank |
$14 | global transparent colour |
$15 | bit 7 LoRes enable, bit 6 sprite priority, bit 5 sprite border clip, bits[4:2] layer priority and blend, bit 1 sprites over border, bit 0 sprites enable |
$16 / $17 / $71 | Layer 2 scroll X low, scroll Y, scroll X msb |
$18 | Layer 2 clip window: four writes, auto-advancing |
$70 | Layer 2 resolution and palette offset |
⚠ $15 bit 6 is 0 at reset, which puts the highest-numbered sprite on top. A program assuming the opposite draws its sprites in the wrong order.
nextreg $15,%00000011 ; sprites on, and over the borderULA, clipping and scrolling
| Reg | Meaning |
|---|---|
$1A | ULA clip window: four writes |
$1C | a write resets the Layer 2, sprite, ULA and tilemap clip indices; a read returns all four |
$26 / $27 | ULA hardware scroll X / Y. X honours the $68 bit 2 fine-scroll enable |
$42 | ULANext attribute format mask |
$43 | palette write select, active palette selects, ULANext enable; bit 7 disables palette auto-increment |
$68 | bit 7 ULA disable, bits[6:5] blend operand, bit 4 cancel extended keys, bit 3 ULA+ enable, bit 2 ULA fine scroll X enable, bit 0 ULA stencil |
$69 | a mirror: bit 7 drives port $123B Layer 2 enable, bit 6 the $7FFD shadow bit, bits[5:0] the port $FF Timex mode |
$69 is not a register of its own: writing it changes state that also lives in ports.
Setting the ULA clip window to the central 128 × 96 pixels:
nextreg $1C,%00000100 ; reset the ULA clip index
nextreg $1A,64 ; x1
nextreg $1A,191 ; x2
nextreg $1A,48 ; y1
nextreg $1A,143 ; y2Sprites, tilemap and LoRes
| Reg | Meaning |
|---|---|
$19 | sprite clip window: four writes |
$1B | tilemap clip window: four writes |
$2F / $30 | tilemap scroll X, msb and low (10-bit) |
$31 | tilemap scroll Y |
$32 / $33 | LoRes scroll X / Y |
$34 | sprite mirror id (read); $35–$39 write the attributes and auto-advance |
$4B / $4C | sprite / tilemap transparent index |
$6A | LoRes Radastan mode, XOR, and palette offset |
$6B / $6C | tilemap control / default attribute |
$6E / $6F | tilemap map base / tile definitions base, in bank 5 or 7 |
nextreg $31,8 ; tilemap scrolled up 8 pixelsPalette
| Reg | Meaning |
|---|---|
$40 | palette index |
$41 | palette data, 8-bit RRRGGGBB, auto-incrementing unless $43 bit 7 is set |
$44 | palette data, 9-bit plus priority, in two writes |
$28 | stored palette value read-back |
$4A | fallback colour, shown where every layer is transparent |
Writing $40 or $43 restarts the two-byte sequence $44 is part way through, so an interrupted upload resumes on the wrong half unless the index is written again.
nextreg $40,16 ; palette entry 16
nextreg $41,%11100000 ; bright redMemory and paging
MMU
$50–$57 hold one 8K page number per slot, and a read returns the live mapping. Pages run 0 to 223 on a machine with all its memory fitted. A page number from $E0 to $FF in slot 0 or 1 maps the ROM there, and in slots 2 to 7 maps nothing. Reset sets slots 0 and 1 to $FF.
MMU page P is physical 8K bank P + 32. Physical banks 0 to 31 have no page number and are reachable only through config mode.
nextreg $56,20 ; page 20 at $C000Paging and expansion
| Reg | Meaning |
|---|---|
$80 / $81 | expansion bus enable and control |
$82–$85 | internal_port_enable: which internal port groups decode at all |
$86–$8A | bus_port_enable and propagate, for expansion-bus port decode |
$8C | alternate ROM: bit 7 enable, bit 6 write, and the lock bits |
$8E | paging shortcut for $7FFD / $1FFD / $DFFD; the read reconstructs live state |
$8F | memory mapping mode, standard or Pentagon |
An internal port group that is not enabled in $82–$85 does not decode, so a port that appears dead is checked there first. The bit map is on the ports page.
$8C loads a replacement ROM without config mode. With bits 7 and 6 both set, writes to the ROM region land in the alternate ROM while reads still come from the real ROM; clearing bit 6 then makes the alternate ROM live. The alternate ROM is physical banks 12 to 15: one 16K image for the 128K ROM slot and one for the 48K.
nextreg $8C,%11000000 ; writes to $0000-$3FFF fill the alternate ROMCopper
| Reg | Meaning |
|---|---|
$60 | copper instruction / data write |
$61 / $62 | list index low / mode in bits[7:6] plus index msb |
$63 | copper data pair write |
$64 | copper and line-interrupt vertical offset |
nextreg $61,0
nextreg $62,0 ; copper stopped, list index 0Extended keys
$B0–$B2 are read-only, and a set bit means the key is pressed.
| Reg | Bit 7 → bit 0 |
|---|---|
$B0 | ; " , . UP DOWN LEFT RIGHT |
$B1 | DELETE EDIT BREAK INV TRUE GRAPH CAPS LOCK EXTEND |
$B2 | the extended joystick buttons, right pad then left pad |
With only the up arrow held, $B0 reads $08.
$68 bit 4 does not hide a key from $B0 or $B1. It stops an extended key also pressing its CAPS SHIFT combination in the $FE keyboard rows, so an arrow key no longer reads as CAPS SHIFT + 7 there; $B0 still reports it.
DivMMC automap entry points
Which addresses page DivMMC in, on what condition, and with what timing. Bit n of $B8–$BA refers to the RST entry at address n × 8.
| Reg | Meaning |
|---|---|
$B8 | RST entry enable. Reset $83 enables $0000, $0008 and $0038 |
$B9 | per-entry condition: 1 fires always; 0 fires only while the 128K ROM 3 is paged. Reset $01 |
$BA | per-entry timing: 1 maps DivMMC for this fetch; 0 from the next instruction fetch. Reset $00 |
$BB | the other entries: bit 0 $0066 NMI delayed, bit 1 $0066 NMI instant, bit 2 $04C6, bit 3 $0562, bit 4 $04D7, bit 5 $056A, bit 6 $1FF8–$1FFF unmap, bit 7 $3Dxx instant. Reset $CD |
The $BB bits 2 to 5 entries and the $3Dxx entry fire only while ROM 3 is paged, whatever $B9 holds. The $0066 entries fire only on a DivMMC NMI, so ordinary code running at $0066 does not map DivMMC in.
DivMMC outranks everything a program can page. An automap that fires wins over Layer 2, the alternate ROM and RAM the MMU put at $0000. But mapping RAM into slot 0 or 1 disables every entry conditional on ROM 3, so with the reset settings only $0000 still maps DivMMC in.
nextreg $B8,%10000001 ; automap on RST $00 and RST $38 onlyInterrupts
| Reg | Meaning |
|---|---|
$C0 | bits[7:5] IM2 vector base, bit 3 stackless NMI, bits[2:1] the CPU’s live interrupt mode (read only), bit 0 hardware IM2 mode |
$C2 / $C3 | return address low / high for the stackless NMI |
$C4 | interrupt enables: ULA, line, expansion bus |
$C5 | CTC interrupt enable mask |
$C6 | UART interrupt enables: bits 6 and 2 transmit empty, 5 and 1 receive near full, 4 and 0 receive available, for UART 1 and UART 0 |
$C8–$CA | interrupt status: line, ULA, CTC, UART, expansion bus; writing a 1 clears a bit |
$CC–$CE | which interrupt triggers the DMA |
A UART’s receive near-full and receive-available conditions share one interrupt per channel: the enables select which raises it, and near-full wins when both are set. A device whose interrupt is disabled still sets its status bit, so it can be polled.
The interrupt priority, highest first: the line interrupt, UART 0 receive, UART 1 receive, CTC channels 0 to 7, the ULA, UART 0 transmit, UART 1 transmit. Receive outranks every CTC channel and the ULA; transmit ranks below all of them.
nextreg $C0,%10100001 ; vectors from $A0, hardware IM2 mode onSound and miscellaneous
$2C, $2D and $2E are a DAC write alias of the Soundrive channels: $2C left to channel B, $2D mono to channels A and D, $2E right to channel C, all gated by $08 bit 3. A read returns the Pi’s I2S input sample instead, a different signal. The copper can write $2D once per scanline to stream digital audio.
nextreg $2D,$80 ; mono DAC sample at the midpoint$D8–$DA are the I/O trap: enable, the written byte, and the cause. A write to $2xFD or $3xFD with the trap enabled raises a Multiface NMI. $90–$93, $98–$9B and $A0 upward are Pi GPIO. $F0 and $F8–$FA are the xdev command and the FPGA’s own temperature and voltage sensing.
Unemulated hardware
These registers exist and store values, with nothing behind them:
- Expansion bus devices: nothing is attached, so
$81and$86–$8Agate nothing. Enabling the bus with$80still holds the CPU at 3.5 MHz. - Pi GPIO and I2S:
$90–$93,$98–$9B,$A0upward, and the read side of$2C/$2D/$2E. - FPGA hardware sensing:
$F0,$F8–$FA.
See also
- I/O Ports: the ports these registers gate and mirror.
- Machine Timing: what
$03,$05,$07and$08do to the frame.