The Next Registers
------------------
Author:     Victor Trucco with contributions from Kev Brady, Alvin
            Albrecht, Garry Lancaster and Phoebus Dokos
Maintainer: Alvin Albrecht
Editor:     Phoebus Dokos
Date:	    2020-04-27
License:    CC BY-NC-SA
Version:    2.1

Changelog
---------
2020-04-27: 2.0 Major update (previous versions discarded)
2020-04-30: 2.1 New NextREG 143 for memory mapping mode control

Introduction
------------
The ZX Spectrum Next stores its configuration state in a field of registers.
These registers are accessible via two io ports or via the special nextreg 
instructions.

Port 0x243B (9275) is used to select the register by number, listed below.
Port 0x253B (9531) is used to read or write the register value.

Some registers are accessible only during the initialization process.
Registers 0x80 and above are inaccessible to the copper.

Initial values are set during a hard or soft reset but may be modified by the 
operating system.
A hard reset is generated at power on, by the F1 key or via a write to nextreg 
0x02 with bit 1 set.
A soft reset is generated by a hard reset, the F4 key or via a write to nextreg 
0x02 with bit 0 set.

Special considerations regarding the use of the Expansion bus
-------------------------------------------------------------
There are two sets of 4 Next Registers that control how devices are enabled.
NextREG 130-133 (Internal Decoding control) and 
NextREG 134-137 (External Decoding control).

When the external decoding for a port is enabled, the corresponding internal
port is disabled and will remain so until the bus is disabled again in which
case the internal device will be reenabled.
Enabling/Disabling the internal devices from the Internal Decoding control
Register however applies until a hard reset is issued or until manually changed
by writing to the relevant register.

Effectively that means that if you want to plug a device such as say the 
ZX Printer, you only need to enable the external decoding of the relevant port
(in this case FBh) and turn on the bus. Once you turn off the bus then the 
internal device will be reenabled automatically.


Notes
-----
Registers that have been previously in use but are now deprecated are marked
by: //


NEXTREG REGISTER SPACE
----------------------
Generally a set bit indicates the property is asserted

0x00 (00) => Machine ID
(R)
  00000001 = DE1A
  00000010 = DE2A
  00000101 = FBLABS
  00000110 = VTRUCCO
  00000111 = WXEDA
  00001000 = EMULATORS *
  00001010 = ZX Spectrum Next *
  11101010 = ZX Spectrum Next on ZX-DOS FPGA platform *
  00001011 = Multicore
  11111010 = ZX Spectrum Next Anti-brick *
  * = Relevant for ZX Next machines & software

0x01 (01) => Core Version 
(R)
  bits 7:4 = Major version number
  bits 3:0 = Minor version number
  (see register 0x0E for sub minor version number)

0x02 (02) => Reset
(R)
  bit 7 = Indicates the reset signal to the expansion bus and esp is asserted
  bits 6:2 = Reserved
  bit 1 = Indicates the last reset was a hard reset
  bit 0 = Indicates the last reset was a soft reset
  * Only one of bits 1:0 will be set
(W)
  bit 7 = Assert and hold reset to the expansion bus and the esp wifi (hard reset = 0)
  bits 6:2 = Reserved, must be 0
  bit 1 = Generate a hard reset (reboot)
  bit 0 = Generate a soft reset
  * Hard reset has precedence
  
0x03 (03) => Machine Type
(R)
  bit 7 = nextreg 0x44 second byte indicator
  bits 6:4 = Display timing
  bit 3 = User lock on display timing applied
  bits 2-0 = Machine type
(W)
  A write to this register disables the bootrom in config mode
  bit 7 = 1 to allow changes to bits 6:4
  bits 6:4 = Selects display timing (VGA/RGB only)
    affects port decoding
    000 = Internal Use
    001 = ZX 48K display timing
    010 = ZX 128K/+2 display timing
    011 = ZX +2A/+2B/+3 display timing
    100 = Pentagon display timing 50 Hz only
  bit 3 = 1 to toggle user lock on display timing (hard reset = 0)
  bits 2:0 = Selects machine type (config mode only)
    determines roms loaded and multiface type
    000 = Configuration mode
    001 = ZX 48K
    010 = ZX 128K/+2
    011 = ZX +2A/+2B/+3
    100 = Pentagon

0x04 (04) => Config Mapping (config mode only, bootrom disabled)
(W)
   bits 7:5 = Reserved, must be 0
   bits 4:0 = 16K SRAM bank mapped to 0x0000-0x3FFF (first 1MB of sram) (hard reset = 0)

0x05 (05) => Peripheral 1 Setting
(R/W)
  bits 7:6 = Joystick 1 mode (LSB)
  bits 5:4 = Joystick 2 mode (LSB)
  bit 3 = Joystick 1 mode (MSB)
  bit 2 = 50/60 Hz mode (0 = 50Hz, 1 = 60Hz, Pentagon is always 50Hz)
  bit 1 = Joystick 2 mode (MSB)
  bit 0 = Enable scandoubler (1 = enabled)
Joystick modes:
  000 = Sinclair 2 (12345)
  001 = Kempston 1 (port 0x1F)
  010 = Cursor (56780)
  011 = Sinclair 1 (67890)
  100 = Kempston 2 (port 0x37)
  101 = MD 1 (3 or 6 button joystick port 0x1F)
  110 = MD 2 (3 or 6 button joystick port 0x37)
  111 = I/O Mode
Both joysticks are placed in I/O Mode if either is set to I/O Mode. The underlying
joystick type is not changed and reads of this register will continue to return
the last joystick type. Whether the joystick is in io mode or not is invisible
but this state can be cleared either through reset or by re-writing the register
with joystick type not equal to 111. Recovery time for a normal joystick read after
leaving I/O Mode is at most 64 scan lines.

0x06 (06) => Peripheral 2 Setting
(R/W)
  bit 7 = Enable F8 cpu speed hotkey (soft reset = 1)
  bit 6 = Divert BEEP only to internal speaker (hard reset = 0)
  bit 5 = Enable F3 50/60 Hz hotkey (soft reset = 1)
  bit 4 = Enable divmmc automap and divmmc nmi by DRIVE button (hard reset = 0)
  bit 3 = Enable multiface nmi by M1 button (hard reset = 0)
  bit 2 = PS/2 mode (0 = keyboard primary, 1 = mouse primary; config mode only)
  bits 1-0 = Audio chip mode (00 = YM, 01 = AY, 11 = Hold all AY in reset)

0x07 (07) => CPU Speed
(R)
  bits 7:6 = Reserved
  bits 5:4 = Current actual cpu speed
  bits 3:2 = Reserved
  bits 1:0 = Programmed cpu speed
(W)
  bits 7:2 = Reserved, must be 0
  bits 1:0 = Set cpu speed (soft reset = 00)
    00 = 3.5 MHz
    01 = 7 MHz
    10 = 14 MHz
    11 = 28 MHz

0x08 (08) => Peripheral 3 Setting
(R/W)
  bit 7 = Unlock port 0x7ffd (read 1 indicates port 0x7ffd is not locked)
  bit 6 = Disable ram and port contention (soft reset = 0)
  bit 5 = AY stereo mode (0 = ABC, 1 = ACB) (hard reset = 0)
  bit 4 = Enable internal speaker (hard reset = 1)
  bit 3 = Enable 8-bit DACs (A,B,C,D) (hard reset = 0)
  bit 2 = Enable port 0xff Timex video mode read (hides floating bus on 0xff) (hard reset = 0)
  bit 1 = Enable turbosound (currently selected AY is frozen when disabled) (hard reset = 0)
  bit 0 = Implement issue 2 keyboard (hard reset = 0)

0x09 (09) => Peripheral 4 Setting
(R/W)
  bit 7 = Place AY 2 in mono mode (hard reset = 0)
  bit 6 = Place AY 1 in mono mode (hard reset = 0)
  bit 5 = Place AY 0 in mono mode (hard reset = 0)
  bit 4 = Sprite id lockstep (nextreg 0x34 and port 0x303B are in lockstep) (soft reset = 0)
  bit 3 = Reset divmmc mapram bit (port 0xe3 bit 6) (read returns 0)
  bit 2 = 1 to silence hdmi audio (hard reset = 0)
  bits 1:0 = Scanline weight
    00 = scanlines off
    01 = scanlines 50%
    10 = scanlines 25%
    11 = scanlines 12.5%

0x0A (10) => Peripheral 5 Setting
  bits 7:3 = Reserved, must be zero
  bit 2 = 1 to reverse left and right mouse buttons (hard reset = 0)
  bits 1:0 = mouse dpi (hard reset = 01)
    00 = low dpi
    01 = default
    10 = medium dpi
    11 = high dpi

0x0E (14) => Core Version (sub minor number)
(R) (see register 0x01 for the major and minor version number)

0x10 (16) => Core Boot
(R)
  bits 7:2 = Reserved
  bit 1 = Button DRIVE (divmmc) is pressed
  bit 0 = Button M1 (multiface) is pressed
(W)
  bit 7 = Start selected core
  bits 6:5 = Reserved, must be 0
  bits 4:0 = Core ID 0-31 (config mode only)

0x11 (17) => Video Timing (writable in config mode only)
(R/W)
  bits 7:3 = Reserved, must be 0
  bits 2:0 = Mode (VGA = 0..6, HDMI = 7)
    000 = Base VGA timing, clk28 = 28000000
    001 = VGA setting 1, clk28 = 28571429
    010 = VGA setting 2, clk28 = 29464286
    011 = VGA setting 3, clk28 = 30000000
    100 = VGA setting 4, clk28 = 31000000
    101 = VGA setting 5, clk28 = 32000000
    110 = VGA setting 6, clk28 = 33000000
    111 = HDMI, clk28 = 27000000
    * 50/60Hz selection depends on bit 2 of nextreg 0x05

0x12 (18) => Layer 2 Active RAM bank
(R/W)
  bit 7 = Reserved, must be 0
  bits 6:0 = Starting 16K RAM bank (soft reset = 8)

0x13 (19) => Layer 2 Shadow RAM bank
(R/W)
  bit 7 = Reserved, must be 0
  bits 6:0 = Starting 16K RAM bank (soft reset = 11)

0x14 (20) => Global Transparency Colour
(R/W)
  bits 7:0 = Transparency colour value (soft reset = 0xe3)
  * Note: This value is 8-bit, so the transparency colour is compared against
      the MSB bits of the final 9-bit colour only.
  * Note: This colour only applies to Layer 2, ULA and LoRes.
      Sprites use nextreg 0x4B and the tilemap uses nextreg 0x4C for transparency.

0x15 (21) => Sprite and Layers System
(R/W)
  bit 7 = Enable lores mode (soft reset = 0)
  bit 6 = Sprite priority (1 = sprite 0 on top, 0 = sprite 127 on top) (soft reset = 0)
  bit 5 = Enable sprite clipping in over border mode (soft reset = 0)
  bits 4:2 = Set layer priority (eg SLU = sprites over layer 2 over ula) (soft reset = 000)
    000 - S L U
    001 - L S U
    010 - S U L
    011 - L U S
    100 - U S L
    101 - U L S
    110 - (U|T)S(T|U)(B+L) Blending layer and Layer 2 combined, colours clamped to [0,7]
    111 - (U|T)S(T|U)(B+L-5) Blending layer and Layer 2 combined, colours clamped to [0,7]
  bit 1 = Enable sprites over border (soft reset = 0)
  bit 0 = Enable sprites (soft reset = 0)

0x16 (22) => Layer2 X Scroll LSB
(R/W)
  bits 7:0 = X Offset (0-255) (soft reset = 0)

0x17 (23) => Layer2 Y Scroll
(R/W)
  bits 7:0 = Y Offset (limited to 0-191 when vertical resolution is 192 pixels) (soft reset = 0)

0x18 (24) => Clip Window Layer 2
(R/W)
  bits 7:0 = Clip window coordinate (inclusive)
  1st write - X1 position (soft reset = 0)
  2nd write - X2 position (soft reset = 255)
  3rd write - Y1 position (soft reset = 0)
  4rd write - Y2 position (soft reset = 191)
  Reads do not advance the clip position

0x19 (25) => Clip Window Sprites
(R/W)
  bits 7:0 = Clip window coordinate (inclusive)
  1st write - X1 position (soft reset  = 0)
  2nd write - X2 position (soft reset = 255)
  3rd write - Y1 position (soft reset = 0)
  4rd write - Y2 position (soft reset = 191)
  Reads do not advance the clip position
  When the clip window is enabled for sprites in "over border" mode,
  the X coords are internally doubled and the clip window origin is
  moved to the sprite origin inside the border.

0x1A (26) => Clip Window ULA (and LoRes, see note)
(R/W)
  bits 7:0 = Clip window coordinate (inclusive)
  1st write = X1 position (soft reset = 0)
  2nd write = X2 position (soft reset = 255)
  3rd write = Y1 position (soft reset = 0)
  4rd write = Y2 position (soft reset = 191)
  Reads do not advance the clip position
  LoRes may get a separate clip window in the future

0x1B (27) => Clip Window Tilemap
(R/W)
  bits 7:0 = Clip window coordinate (inclusive)
  1st write = X1 position (soft reset = 0)
  2nd write = X2 position (soft reset = 159)
  3rd write = Y1 position (soft reset = 0)
  4rd write = Y2 position (soft reset = 255)
  Reads do not advance the clip position
  The X coordinates are internally doubled.

0x1C (28) => Clip Window control
(R) (may change)
  bits 7:6 = Tilemap clip index
  bits 5:4 = ULA/Lores clip index
  bits 3:2 = Sprite clip index
  bits 1:0 = Layer 2 clip index
(W) (may change)
  bits 7:4 = Reserved, must be 0
  bit 3 = Reset the tilemap clip index
  bit 2 = Reset the ULA/LoRes clip index
  bit 1 = Reset the sprite clip index
  bit 0 = Reset the Layer 2 clip index

0x1E (30) => Active video line (MSB)
(R)
  bits 7:1 = Reserved
  bit 0 = Active line MSB

0x1F (31) => Active video line (LSB)
(R)
  bits 7:0 = Active line LSB

0x22 (34) => Line Interrupt control
(R/W)
  bit 7 = (R) Indicates if the ula is asserting an interrupt (even if disabled)
  bits 7:3 = Reserved, must be 0
  bit 2 = Disables ula interrupt (soft reset = 0)
  bit 1 = Enables line Interrupt (soft reset = 0)
  bit 0 = MSB of line interrupt value (soft reset = 0)

0x23 (35) => Line Interrupt Value LSB
(R/W)
  bits 7:0 = Line Interrupt value LSB (soft reset = 0)

0x26 (38) => ULA X Scroll
(R/W)
  bits 7:0 = X Offset (0-255) (soft reset = 0)

0x27 (39) => ULA Y Scroll
(R/W)
  bits 7:0 = Y Offset (0-191) (soft reset = 0)

0x28 (40) => PS/2 Keymap Address MSB
(R)
  bits 7:0 = Stored palette value from nextreg 0x44
(W)
  bits 7:1 = Reserved, must be 0
  bit 0 = MSB address

0x29 (41) => PS/2 Keymap Address LSB
(W)
  bits 7:0 = LSB adress

0x2A (42) => PS/2 Keymap Data MSB
(W)
  bits 7:1 = Reserved, must be 0
  bit 0 = MSB data

0x2B (43) => PS/2 Keymap Data LSB
(W) (write causes the data to be written and auto-increments the keymap address)
  bits 7:0 = LSB data

0x2C (44) => DAC B Mirror (left)
(R)
  bits 7:0 = MSB of current I2S (pi) left side sample
             the LSB is latched and can be read from nextreg 0x2D later
(W)
  bits 7:0 = 8-bit sample written to left side DAC B (soft reset = 0x80)

0x2D (45) => DAC A+D Mirror (mono)
(R)
  bits 7:0 = LSB of last I2S (pi) sample read from nextreg 0x2C or nextreg 0x2E
(W)
  bits 7:0 = 8-bit sample written to DACs A and D (soft reset = 0x80)

0x2E (46) => DAC C Mirror (right)
(R)
  bits 7:0 = MSB of current I2S (pi) right side sample
             the LSB is latched and can be read from nextreg 0x2D later
(W)
  bits 7:0 = 8-bit sample written to right side DAC C (soft reset = 0x80)

0x2F (47) => Tilemap X Scroll MSB
(R/W)
  bits 7:2 = Reserved, must be 0
  bits 1:0 = MSB X Offset (soft reset = 0)
  Meaningful Range is 0-319 in 40 char mode, 0-639 in 80 char mode

0x30 (48) => Tilemap X Scroll LSB
(R/W)
  bits 7:0 = LSB X Offset (soft reset = 0)
  Meaningful range is 0-319 in 40 char mode, 0-639 in 80 char mode

0x31 (49) => Tilemap Offset Y
(R/W)
  bits 7:0 = Y Offset (0-255) (soft reset = 0)

0x32 (50) => LoRes X Scroll
(R/W)
  bits 7:0 = X Offset (0-255) (soft reset = 0)
  LoRes scrolls in "half-pixels" at the same resolution and smoothness as Layer 2.

0x33 (51) => LoRes Y Scroll
(R/W)
  bits 7:0 = Y Offset (0-191) (soft reset = 0)
  LoRes scrolls in "half-pixels" at the same resolution and smoothness as Layer 2.

0x34 (52) => Sprite Number
(R/W)
  If the sprite number is in lockstep with port 0x303B (nextreg 0x09 bit 4 is set)
    bit 7 = Pattern address offset (add 128 to pattern address)
    bits 6:0 = Sprite number 0-127, Pattern number 0-63
    Selects which sprite has its attributes connected to the following registers.
    Effectively performs an out to port 0x303B with the same value
  Otherwise
    bit 7 = Ignored
    bits 6:0 = Sprite number 0-127
    Selects which sprite has its attributes connected to the following registers.
  Bit 7 always reads back as zero.

0x35 (53)  => Sprite Attribute 0
0x75 (117) => Sprite Attribute 0 with automatic post increment of Sprite Number
(W) See documentation at https://www.specnext.com/sprites/

0x36 (54)  => Sprite Attribute 1
0x76 (118) => Sprite Attribute 1 with automatic post increment of Sprite Number
(W) See documentation at https://www.specnext.com/sprites/

0x37 (55)  => Sprite Attribute 2
0x77 (119) => Sprite Attribute 2 with automatic post increment of Sprite Number
(W) See documentation at https://www.specnext.com/sprites/

0x38 (56)  => Sprite Attribute 3
0x78 (120) => Sprite Attribute 3 with automatic post increment of Sprite Number
(W) See documentation at https://www.specnext.com/sprites/

0x39 (57)  => Sprite Attribute 4
0x79 (121) => Sprite Attribute 4 with automatic post increment of Sprite Number
(W) See documentation at https://www.specnext.com/sprites/

0x40 (64) => Palette Index
(R/W)
  bits 7:0 = Select the palette index to change the associated colour. (soft reset = 0)
  For the ULA only, INKs are mapped to indices 0-7, Bright INKS to indices 8-15,
   PAPERs to indices 16-23 and Bright PAPERs to indices 24-31.
  In ULANext mode, INKs come from a subset of indices 0-127 and PAPERs come from
   a subset of indices 128-255.  The number of active indices depends on the number
   of attribute bits assigned to INK and PAPER out of the attribute byte.
  In ULA+ mode, the top 64 entries hold the ula+ palette.
  The ULA always takes border colour from paper for standard ULA and ULAnext.

0x41 (65) => Palette Value (8 bit colour)
(R/W)
  bits 7:0 = Colour for the palette index selected by nextreg 0x40. 
    The format is RRRGGGBB -  the lower blue bit of the 9-bit colour will be the logical
    OR of blue bits 1 and 0 of this 8-bit value.
    After the write, the palette index is auto-incremented to the next index if the
    auto-increment is enabled in nextreg 0x43.  Reads do not auto-increment.
    Any other bits associated with the index will be zeroed.

0x42 (66) => ULANext Attribute Byte Format
(R/W)
  bits 7:0 = Mask indicating which bits of an attribute byte are used to represent INK.
    Other bits represent PAPER. (soft reset = 0x07)
    The mask can only indicate a solid sequence of bits on the right side of an attribute
    byte (1, 3, 7, 15, 31, 63, 127 or 255).
    INKs are mapped to base index 0 in the palette and PAPERs and border are
    mapped to base index 128 in the palette.
    The 255 value enables the full ink colour mode making all the palette entries INK.
    In this case PAPER and border are both taken from the fallback colour in nextreg 0x4A.
    If the mask is not one of those listed above, the INK is taken as the logical AND of
    the mask with the attribute byte and the PAPER and border colour are again both taken
    from the fallback colour in nextreg 0x4A.

0x43 (67) => Palette Control
(R/W)
  bit 7 = Disable palette write auto-increment (soft reset = 0)
  bits 6-4 = Select palette for reading or writing (soft reset = 000)
    000 = ULA first palette
    100 = ULA second palette
    001 = Layer 2 first palette
    101 = Layer 2 second palette
    010 = Sprites first palette 
    110 = Sprites second palette
    011 = Tilemap first palette
    111 = Tilemap second palette
  bit 3 = Select Sprites palette (0 = first palette, 1 = second palette) (soft reset = 0)
  bit 2 = Select Layer 2 palette (0 = first palette, 1 = second palette) (soft reset = 0)
  bit 1 = Select ULA palette (0 = first palette, 1 = second palette) (soft reset = 0)
  bit 0 = Enabe ULANext mode (soft reset = 0)

0x44 (68) => Palette Value (9 bit colour)
(R/W)
  Two consecutive writes are needed to write the 9 bit colour
  1st write:
    bits 7:0 = RRRGGGBB
  2nd write:
    bits 7:1 = Reserved, must be 0
    bit 0 = lsb B
    If writing to an L2 palette
    bit 7 = 1 for L2 priority colour, 0 for normal.
      An L2 priority colour moves L2 above all layers.  If you need the same
      colour in both priority and normal modes, you will need to have two
      different entries with the same colour one with and one without priority.
  After two consecutive writes the palette index is auto-incremented if
  auto-increment is enabled in nextreg 0x43.
  Reads only return the 2nd byte and do not auto-increment.

0x4A (74) => Fallback Colour
(R/W)
  bits 7:0 = 8-bit colour used if all layers are transparent (soft reset = 0xe3)

0x4B (75) => Sprite Transparency Index
(R/W)
  bits 7:0 = Sprite colour index treated as transparent (soft reset = 0xe3)
  For 4-bit sprites only the bottom 4-bits are used

0x4C (76) => Tilemap Transparency Index
(R/W)
  bits 7-4 = Reserved, must be 0
  bits 3-0 = Tilemap colour index treated as transparent (soft reset = 0xf)

0x50 (80) => MMU slot 0
(R/W)
  bits 7:0 = 8K RAM page occupying address 0x0000 - 0x1FFF (soft reset = 255)
  Pages range from 0 to 223 on a fully expanded Next. 
  A 255 value causes the ROM to become visible.

0x51 (81) => MMU slot 1
(R/W)
  bits 7:0 = 8K RAM page occupying address 0x2000 - 0x3FFF (soft reset = 255)
  Pages range from 0 to 223 on a fully expanded Next. 
  A 255 value causes the ROM to become visible.

0x52 (82) => MMU slot 2
(R/W)
  bits 7:0 = 8K RAM page occupying address 0x4000 - 0x5FFF (soft reset = 10)
  Pages range from 0 to 223 on a fully expanded Next.

0x53 (83) => MMU slot 3
(R/W)
  bits 7:0 = 8K RAM page occupying address 0x6000 - 0x7FFF (soft reset = 11)
  Pages range from 0 to 223 on a fully expanded Next.

0x54 (84) => MMU slot 4
(R/W)
  bits 7:0 = 8K RAM page occupying address 0x8000 - 0x9FFF (soft reset = 4)
  Pages range from 0 to 223 on a fully expanded Next.

0x55 (85) => MMU slot 5
(R/W)
  bits 7:0 = 8K RAM page occupying address 0xA000 - 0xBFFF (soft reset = 5)
  Pages range from 0 to 223 on a fully expanded Next.

0x56 (86) => MMU slot 6
(R/W)
  bits 7:0 = 8K RAM page occupying address 0xC000 - 0xDFFF (soft reset = 0)
  Pages range from 0 to 223 on a fully expanded Next.

0x57 (87) => MMU slot 7
(R/W)
  bits 7:0 = 8K RAM page occupying address 0xE000 - 0xFFFF (soft reset = 1)
  Pages range from 0 to 223 on a fully expanded Next.

0x60 (96) => Copper Data 8-bit Write
(W)
  bits 7:0 = Byte to write to copper instruction memory
  Note that each copper instruction is two bytes long
  After a write, the copper address is auto-incremented to the next memory position

0x61 (97) => Copper Address LSB
(R/W)
  bits 7:0 = Copper instruction memory address LSB (soft reset = 0)
  (Copper addresses range over 0 - 0x7FF = 2K)

0x62 (98) => Copper Control
(R/W)
  bits 7:6 = Start control (soft reset = 00)
    00 = Copper fully stopped
    01 = Copper start, execute the list from index 0, and loop to the start
    10 = Copper start, execute the list from last point, and loop to the start
    11 = Copper start, execute the list from index 0, and restart the list 
         when the raster reaches position (0,0)
  bits 2:0 = Copper instruction memory address MSB (soft reset = 0)
  (Copper addresses range over 0 - 0x7FF = 2K)
  Writing the same start control value does not reset the copper

0x63 (99) => Copper Data 16-bit Write
(W)
  The 16-bit value is written in pairs.  The first 8-bits are the MSB and
  are destined for an even copper instruction address.  The second 8-bits are
  the LSB and are destined for an odd copper instruction address.
  After each write, the copper address is auto-incremented to the next memory position
  After a write to an odd address, the entire 16-bits is written to copper memory at once

0x64 (100) => Vertical Line Count Offset
(R/W)
  bits 7:0 = Offset added to the vertical line counter affects copper, line interrupt and active line count.
  Normally the ula's pixel row 0 aligns with vertical line count 0.  With a non-zero
  offset, the ula's pixel row 0 will align with the vertical line offset.  Eg, if the offset is 32
  then vertical line 32 will correspond to the first pixel row in the ula and vertical line 0
  will align with the first pixel row of the tilemap and sprites.
  * Since a change in offset takes effect when the ula reaches row 0, the change can take up to
  one frame to occur.

0x68 (104) => ULA Control
(R/W)
  bit 7 = Disable ULA output (soft reset = 0)
  bits 6:5 = Blending in SLU modes 6 & 7 (soft reset = 0)
           = 00 for ula as blend colour
           = 10 for ula/tilemap mix result as blend colour
           = 11 for tilemap as blend colour
           = 01 for no blending
  bit 4 = Cancel entries in 8x5 matrix for extended keys
  bit 3 = ULA+ enable (soft reset = 0)
  bit 2 = ULA half pixel scroll (may change) (soft reset = 0)
  bit 1 = Reserved, must be 0
  bit 0 = Enable stencil mode when both the ULA and tilemap are enabled (soft reset = 0)
  (if either are transparent the result is transparent otherwise the result is a logical AND of both colours)

0x69 (105) => Display Control 1
(R/W)
  bit 7 = Enable layer 2 (alias port 0x123B bit 1)
  bit 6 = Enable ULA shadow display (alias port 0x7FFD bit 3)
  bits 5:0 = Port 0xFF bits 5:0 alias (Timex display modes)

0x6A (106) => LoRes Control
(R/W)
  bits 7-6 = Reserved, must be 0
  bit 5 = LoRes is Radastan mode (128x96x4, 6144 bytes) (soft reset = 0)
  bit 4 = LoRes Radastan timex display file xor (soft reset = 0)
  bits 3:0 = LoRes palette offset (bits 1:0 apply in ula+ mode) (soft reset = 0)

0x6B (107) => Tilemap Control
(R/W)
  bit 7 = 1 Enable the tilemap (soft reset = 0)
  bit 6 = 0 for 40x32, 1 for 80x32 (soft reset = 0)
  bit 5 = Eliminate the attribute entry in the tilemap (soft reset = 0)
  bit 4 = Palette select (soft reset = 0)
  bit 3 = Select textmode (soft reset = 0)
  bit 2 = Reserved, must be 0
  bit 1 = Activate 512 tile mode (soft reset = 0)
  bit 0 = Force tilemap on top of ULA (soft reset = 0)

0x6C (108) => Default Tilemap Attribute
(R/W)
  Active if nextreg 0x6B bit 5 is set
  bits 7:4 = Palette offset (soft reset = 0)
  bit 3 = X mirror (soft reset = 0)
  bit 2 = Y mirror (soft reset = 0)
  bit 1 = Rotate (soft reset = 0)
  bit 0 = ULA over tilemap (soft reset = 0)
          (or bit 8 of the tile number if 512 tile mode is enabled)

0x6E (110) => Tilemap Base Address
(R/W) (soft reset = 0x6c00)
  bits 7:6 = Read back as zero, write values ignored
  bits 5:0 = MSB of address of the tilemap in Bank 5
  The value written is an offset into Bank 5 allowing the tilemap to be placed
  at any multiple of 256 bytes.
  Writing a physical MSB address in 0x40-0x7f or 0xc0-0xff range is permitted.
  The value read back should be treated as having a fully significant 8-bit value.

0x6F (111) => Tile Definitions Base Address
(R/W) (soft reset = 0x4c00)
  bits 7:6 = Read back as zero, write values ignored
  bits 5:0 = MSB of address of tile definitions in Bank 5
  The value written is an offset into Bank 5 allowing tile definitions to be placed
  at any multiple of 256 bytes.
  Writing a physical MSB address in 0x40-0x7f or 0xc0-0xff range is permitted.
  The value read back should be treated as having a fully significant 8-bit value.

0x70 (112) => Layer 2 Control
(R/W)
  bits 7:6 = Reserved, must be 0
  bits 5:4 = Layer 2 resolution (soft reset = 0)
    00 = 256x192x8
    01 = 320x256x8
    10 = 640x256x4
  bits 3:0 = Palette offset (soft reset = 0)

0x71 (113) => Layer 2 X Scroll MSB
(R/W)
   bits 7:1 = Reserved, must be 0
   bit 0 = MSB of scroll amount

0x75 (117) => Sprite Attribute 0 with automatic post increment of Sprite Number
(W) see nextreg 0x35

0x76 (118) => Sprite Attribute 1 with automatic post increment of Sprite Number
(W) see nextreg 0x36

0x77 (119) => Sprite Attribute 2 with automatic post increment of Sprite Number
(W) see nextreg 0x37

0x78 (120) => Sprite Attribute 3 with automatic post increment of Sprite Number
(W) see nextreg 0x38

0x79 (121) => Sprite Attribute 4 with automatic post increment of Sprite Number
(W) see nextreg 0x39

0x7F (127) => User Register 0
(R/W)
  bits 7:0 = Unused storage available to the user (soft reset = 0xff)

NEXTREG 0x80 AND HIGHER ARE INACCESSIBLE TO THE COPPER

0x80 (128) => Expansion Bus Enable
(R/W) (hard reset = 0)
IMMEDIATE
bit 7 = 1 to enable the expansion bus
bit 6 = 1 to enable romcs rom replacement from divmmc banks 14/15
bit 5 = 1 to disable i/o cycles & ignore iorqula
bit 4 = 1 to disable memory cycles & ignore romcs
AFTER SOFT RESET (copied into bits 7-4)
bit 3 = 1 to enable the expansion bus
bit 2 = 1 to enable romcs rom replacement from divmmc banks 14/15
bit 1 = 1 to disable i/o cycles & ignore iorqula
bit 0 = 1 to disable memory cycles & ignore romcs

0x81 (129) => Expansion Bus Control
(R/W) (hard reset = 0)
bit 7 = 1 if ROMCS is asserted on the expansion bus (read only)
bit 4 = 1 to propagate the max cpu clock at all times including when the expansion bus is off
bits 1-0 = max cpu speed when the expansion bus is on (currently fixed at 00 = 3.5MHz)

0x85,0x84,0x83,0x82 (133-130) => Internal Port Decoding Enables (0x85 is MSB) (soft reset if bit 31 = 1, hard reset if bit 31 = 0 : all 1)
0x89,0x88,0x87,0x86 (137-134) => Expansion Bus Decoding Enables (0x89 is MSB) (soft reset if bit 31 = 0, hard reset if bit 31 = 1 : all 1)
(R/W)
  bit 0 = port ff
  bit 1 = port 7ffd
  bit 2 = port dffd
  bit 3 = port 1ffd
  bit 4 = +3 floating bus
  bit 5 = port 6b zxn dma
  bit 6 = port 1f kempston / md1
  bit 7 = port 37 kempston 2 / md2 / joystick control
  -----
  bit 8 = port e3 divmmc control
  bit 9 = multiface (two variable ports)
  bit 10 = port 103b,113b i2c
  bit 11 = port e7,eb spi
  bit 12 = port 133b,143b,153b uart
  bit 13 = port fadf,fbdf,ffdf mouse
  bit 14 = port 57,5b,303b sprites
  bit 15 = port 123b layer2
  -----
  bit 16 = port fffd,bffd ay
  bit 17 = port 0f,1f,4f,5f dac soundrive mode 1
  bit 18 = port f1,f3,f9,fb dac soundrive mode 2
  bit 19 = port 3f,5f dac stereo profi covox
  bit 20 = port 0f,4f dac stereo covox
  bit 21 = port fb dac mono pentagon/atm (sd mode 2 off)
  bit 22 = port b3 dac mono gs covox
  bit 23 = port df dac mono specdrum
  -----
  bit 24 = port bf3b, ff3b ula+
  bit 25 = port 0b z80 dma
  ...
  bit 31 = register reset mode (soft or hard reset selection)
  -----
  The internal port decoding enables always apply.
  When the expansion bus is on, the expansion port decoding enables are logically ANDed with the internal enables.
  A zero bit indicates the internal device is disabled.  If the expansion bus is on, this allows io cycles for
  disabled ports to propagate to the expansion bus, otherwise corresponding io cycles to the expansion bus are filtered.

0x8A (138) => Expansion Bus IO Propagate
(R/W)
  bits 7:5 = Reserved, must be 0
  bit 4 = Propagate port 0xff io cycles (hard reset  = 0)
  bit 3 = Propagate port 0x1ffd io cycles (hard reset = 0)
  bit 2 = Propagate port 0xdffd io cycles (hard reset = 0)
  bit 1 = Propagate port 0x7ffd io cycles (hard reset = 0)
  bit 0 = Propagare port 0xfe io cycles (hard reset = 0)
  If any of the bits are set, io cycles for the corresponding ports are propagated to the expansion bus when
  the expansion bus is on.  If the internal port decode is still active, any response sent by devices on the
  expansion bus will be ignored.  The purpose here is to allow external peripherals to monitor changes in state
  inside the zx next.
  Port 0xfe is treated specially so that external keyboards can be attached.  When its propagate bit is set,
  the value read from the bus will be mixed into keyboard reads on port 0xfe.

0x8C (140) => Alternate ROM 
(R/W) (hard reset = 0)
IMMEDIATE
  bit 7 = 1 to enable alt rom
  bit 6 = 1 to make alt rom visible only during writes, otherwise replaces rom during reads
  bit 5 = 1 to lock ROM1 (48K rom)
  bit 4 = 1 to lock ROM0 (128K rom)
AFTER SOFT RESET (copied into bits 7-4)
  bit 3 = 1 to enable alt rom
  bit 2 = 1 to make alt rom visible only during writes, otherwise replaces rom during reads
  bit 1 = 1 to lock ROM1 (48K rom)
  bit 0 = 1 to lock ROM0 (128K rom)
The locking mechanism also applies if the alt rom is not enabled. For the +3 and zx next, if the two lock bits are not
zero, then the corresponding rom page is locked in place. Other models use the bits to preferentially lock the corresponding
48K rom or the 128K rom.

0x8E (142) => Spectrum Memory Mapping
(R/W)
  bit 7 = port 0xdffd bit 0         \  RAM
  bits 6:4 = port 0x7ffd bits 2:0   /  bank 0-15
R bit 3 = 1
W bit 3 = 1 to change RAM bank, 0 = no change to mmu6 / mmu7 / RAM bank in ports 0x7ffd, 0xdffd
  bit 2 = port 0x1ffd bit 0            paging mode
If bit 2 = paging mode = 0 (normal)
  bit 1 = port 0x1ffd bit 2         \  ROM
  bit 0 = port 0x7ffd bit 4         /  select
If bit 2 = paging mode = 1 (special allRAM)
  bit 1 = port 0x1ffd bit 2         \  all
  bit 0 = port 0x1ffd bit 1         /  RAM
Writes can affect all ports 0x7ffd, 0xdffd, 0x1ffd
Writes always change the ROM / allRAM mapping
Writes immediately change the current mmu mapping as if by port write

0x8F (143) => Memory Mapping Mode
(R/W) (hard reset = 0)
  bits 7:2 = Reserved, must be zero
  bits 1:0 = Mapping mode applied
    00 = Standard ZX 128k +3
    01 = Profi 1024K
    10 = Pentagon 512K
    11 = Pentagon 1024K
00: Standard ZX 128K +3 = ports 0x7ffd, 0xdffd, 0x1ffd
01: Profi 1024K = ports 0x7ffd, 0xdffd
10: Pentagon 512K = port 0x7ffd
11: Pentagon 1024K = port 0x7ffd, 0xdffd, 0xeff7

0x93,0x92,0x91,0x90 (144-147) => PI GPIO Output Enable (0x93 is MSB)
(R/W)
  bits 27:0 Set bits enable GPIO output on the corresponding GPIO pin (soft reset = all 0)
  (GPIO pins 1:0 cannot be enabled)

0x9B,0x9A,0x99,0x98 (155-152) => PI GPIO (0x9B is MSB)
(R/W)
  bits 27:0 Read / Write the GPIO pin state (soft reset = 0x00001ff)
  (writes only propagate when the corresponding pin has its output enabled)

0xA0 (160) => PI Peripheral Enable
(R/W)
  bits 7:6 = Reserved, must be 0
  bit 5 = Enable UART on GPIO 14,15 (overrides gpio) (soft reset = 0)
  bit 4 = 0 to connect Rx to GPIO 15, Tx to GPIO 14 (for comm with pi hats) (soft reset = 0)
        = 1 to connect Rx to GPIO 14, Tx to GPIO 15 (for comm with pi)
  bit 3 = Enable I2C on GPIO 2,3 (override gpio) (soft reset = 0)
  bits 2:1 = Reserved, must be 0
  bit 0 = Enable SPI on GPIO 7,8,9,10,11 (overrides gpio) (soft reset = 0)

0xA2 (162) => PI I2S Audio Control
(R/W)
  bits 7:6 = I2S enable (soft reset = 00)
    00 = i2s off
    01 = i2s is mono source right
    10 = i2s is mono source left
    11 = i2s is stereo
  bit 5 = Reserved, must be 0
  bit 4 = 0 PCM_DOUT to pi, PCM_DIN from pi (hats) (soft reset = 0)
        = 1 PCM_DOUT from pi, PCM_DIN to pi (pi)
  bit 3 = Mute left side (soft reset = 0)
  bit 2 = Mute right side (soft reset = 0)
//bit 1 = Slave mode (PCM_CLK, PCM_FS supplied externally) (soft reset = 0)
  bit 1 = Reserved must be 1
  bit 0 = Direct i2s audio to EAR on port 0xFE (soft reset = 0)

// 0xA3 (163) => PI I2S Clock Divide (Master Mode)
// (R/W)
//   bits 7:0 = Clock divide sets sample rate when in master mode (soft reset = 11)
//     clock divider = 538461 / SampleRateHz - 1

0xA8 (168) => ESP Wifi GPIO Output Enable
(R/W) (soft reset = 0)
  bit 2 = GPIO2 output enable (fixed at 0, GPIO2 is read-only)
  bit 0 = GPIO0 output enable

0xA9 (169) => ESP Wifi GPIO
(R/W)
  bit 2 = Read / Write ESP GPIO2 (soft reset = 1)
  bit 0 = Read / Write ESP GPIO0 (soft reset = 1)

0xB0 (176) => EXTENDED KEYS 0
  bit 7 = 1 if ; pressed
  bit 6 = 1 if " pressed
  bit 5 = 1 if , pressed
  bit 4 = 1 if . pressed
  bit 3 = 1 if UP pressed
  bit 2 = 1 if DOWN pressed
  bit 1 = 1 if LEFT pressed
  bit 0 = 1 if RIGHT pressed

0xB1 (177) => EXTENDED KEYS 1
  bit 7 = 1 if DELETE pressed
  bit 6 = 1 if EDIT pressed
  bit 5 = 1 if BREAK pressed
  bit 4 = 1 if INV VIDEO pressed
  bit 3 = 1 if TRUE VIDEO pressed
  bit 2 = 1 if GRAPH pressed
  bit 1 = 1 if CAPS LOCK pressed
  bit 0 = 1 if EXTEND pressed

0xFF (255) => Reserved for internal use