Timex Sinclair Video Mode Control

From SpecNext official Wiki
Jump to: navigation, search
Number $xxFF
Decimal 255
Short desc. Controls Timex Sinclair video modes and colours in hi-res mode.
Bit Mask
Readable No
Writable Yes
Subsystem Enhanced ULA

This port is also readable when Peripheral 3 Register ($08) bit 2 is set to one (otherwise "floating bus" values are read at port $FF) (soft reset = 0).

Bit Function
0-2 000=Screen 0. 001=Screen 1. 010=Hi-colour. 110=Hi-res.
3-5 Sets screen color combination for hi-res mode.

The bit pattern does set INK colour, PAPER+BORDER colour is deducted as complement value, both colours are of BRIGHT variant. I.e. only some combinations are possible, like White/Black, Yellow/Blue, ..

6 Disables interrupts. Does the same as DI, but cannot be turned on again with EI. Use with caution!
7 Used for memory paging on the Timex Sinclair, not relevant on the Next.

The hi-res mode (and some parts also about other Timex modes) HW implementation details:

In classic ULA mode the border colour is identical to paper (including the brightness!) - the hi-res mode overrides port 254 border colour.

The Next display pipeline starts at reading the pixel data from "bank 5", which resides in BRAM of FPGA, and is mapped to $4000 and $6000 in default memory mapping (the display data are read from the BRAM, so mapping different ram into $4000..$8000 Z80 address space does not modify the screen output, to modify screen output you have to map "bank 5" to some memory and write there). These pixel data are half of input for "ULA", other half is attribute byte, which is composed as "01pppiii" value, where "iii" are the bits 3-5 from (this) $FF port, and "ppp" are complement of "iii".

For example for bits set as %100 the ULA does accompany every pixel byte with attribute byte %01011100, i.e. "INK 4, PAPER 3, BRIGHT 1".

If Enhanced ULA mode is enabled (bit 0 in Enhanced ULA Control Register ($43)), this attribute byte is decomposed by ink-mask (Enhanced ULA Ink Color Mask ($42)) into ink-index and paper-index, border-index is (paper-index AND %111), then the selected ULA palette is used to fetch particular colours (the constant 128 is added to paper and border index), so in the example above with attribute byte %01011100 and ink-mask 7 the resulting colour will be current-ULA-palette[4] for filled-pixels, current-ULA-palette[128+11] for paper (empty pixel) and current-ULA-palette[128+3] for border (with ink-mask 15 the indices will be 12 for ink and 128+5 for paper+border).

(the default ink-mask of Enhanced ULA did change from 15 to 7, since one of 3.0 cores, can't recall precise version)

If the colour in palette is a match with Global Transparency Register ($14), the colour is treated as transparent, and the final output will display non-transparent pixel belonging to other layer (Layer2 or Sprites) - if there is some non-transparent pixel in other layers, or Transparency colour fallback Register ($4A) colour (of course if the layer priorities put Layer2/Sprites above ULA layer, and there's non-transparent pixel already there, it is displayed over hi-res pixels).

I.e. the "pipeline" is like: hi-res VRAM data (or "empty" for border area) + attribute composed from port $FF -> ULANext palette conversion -> transparency check -> Next layers mixer -> final output to display.

The various mixing modes and results can be seen for example in "LayersMixingHiRes" test of ZXSpectrumNextTests project, the resulting image (the cyan pixels are drawn by Timex hi-res layer, green are part of Layer2 and yellow are from Sprites) (colours are selected by Next ULA palette, allowing any two ink/paper colours combination from the total 512-colour space even for hi-res mode): 400px