Difference between revisions of "Video Modes"

From SpecNext official Wiki
Jump to: navigation, search
(Added info on the 16 colour lores mode)
 
(29 intermediate revisions by 10 users not shown)
Line 1: Line 1:
The ULA is the Spectrum video and input chip. The enhanced ULA adds extra video modes and features to the standard Spectrum.
+
The ULA is the Spectrum video and input chip. The Enhanced ULA adds extra video modes and features to the standard Spectrum.
  
ULA stands for "Uncommitted Logic Array" and refers to the manufacturing process involved. The chip itself is a custom chip.
+
ULA stands for "Uncommitted Logic Array" and refers to the manufacturing process involved. It does not relate to the video behavior of the chip. The chip itself is a custom chip.
  
 
= Spectrum Video Mode =
 
= Spectrum Video Mode =
 
The standard Spectrum has only one video mode, with a resolution of 256x192 (not including the border) and 15 colours. This screen is further divided into 8x8 "attribute cells", so the attribute cell resolution is 32x24.
 
The standard Spectrum has only one video mode, with a resolution of 256x192 (not including the border) and 15 colours. This screen is further divided into 8x8 "attribute cells", so the attribute cell resolution is 32x24.
  
The ULA reads memory from [[Memory map|Bank 5]] or [[Memory map|Bank 7]] based on the setting at {{PortNo|$7FFD}}. If you haven't done any fancy messing about with the memory map, or you're using Spectrum 48k mode, then the screen memory will start at $4000.
+
The ULA reads memory from [[Memory map|16k-Bank 5]] or [[Memory map|16k-Bank 7]] based on the setting at {{PortNo|$7FFD}}. If you haven't done any fancy messing about with the memory map, or you're using Spectrum 48k mode, then the screen memory will start at $4000.
  
There is one bit per pixel, so each byte represents 8 pixels (ie, one line of an attribute cell). Each screen line is stored in straightforward left-to-right order, so the 32 bytes from $4000 onwards represent all the pixels on the first line of the screen.
+
There is one bit per pixel, so each byte represents 8 pixels (ie, one line of an attribute cell). Each screen line is stored in straightforward left-to-right order, so the 32 bytes from $4000 onwards represent all the pixels on the first line of the screen. Each 1 bit means the pixel is drawn in the "ink" color; a 0 bit means it is drawn in the "paper" color. Which colors these are is specified in the attribute blocks described below.
  
Unfortunately, while the columns of the screen are in straightforward order, the ''lines'' are not.
+
Unfortunately, while the columns of the screen are in straightforward order, the ''lines'' are not. The 192 line screen is vertically divided into thirds, with each third containing 64 lines (or 8 attribute cells). These three thirds are stored sequentially in memory, but ''within'' each third, the order is not what you'd expect. You'd expect it'd store the first line of the first cell, the second line of the first cell.. up to the eighth line of the first cell, then the first line of the second cell. Instead, the sorting is ''inverted''. So it stores the first line of the first cell, then the ''first line of the second cell'', then the first line of the third cell, and so on.. up to the first line of the eighth cell, which is then followed by the second line of the first cell!
  
The 192 line screen is vertically divided into thirds, with each third containing 64 lines (or 8 attribute cells). These three thirds are stored sequentially in memory, but ''within'' each third, the order is not what you'd expect. You'd expect it'd store the first line of the first cell, the second line of the first cell.. up to the eighth line of the first cell, then the first line of the second cell. Instead, the sorting is ''inverted''. So it stores the first line of the first cell, then the ''first line of the second cell'', then the first line of the third cell, and so on.. up to the first line of the eighth cell, which is then followed by the second line of the first cell!
+
This means that getting the address of the start of a given line can be a tricky business. The Spectrum Next provides the [[Extended Z80 instruction set|PIXELAD]] opcode to automatically perform the necessary transition. It can be done manually by breaking the line number (0-191) into bits as described below.
  
This means that getting the address of the start of a given line can be a tricky business. Fortunately, since the numbers involved are all powers of 2, it can be done by breaking the line number (0-191) into its bits.
+
[[File:Ktclash.png|200px|thumb|left|Color clash in a classic spectrum game. The corners of the knight's helmet appear green and red because they are in the same attribute cell as the plant and table respectively.]]
 +
Pixel data is stored with 1-bit color in the pixel data memory. However, it is possible for the color to vary across the screen. The snag is that you can set only two colours within a single ''attribute cell'' - that is, an 8x8 area. Because you can have only one color value per 8x8 cell, some older games exhibited "color clash" in which an object or part of an object would appear the wrong color because it needed to be drawn inside an 8x8 cell with another object of a different color.
 +
 
 +
Color data is stored at $5800 onwards. Unlike the pixel data, it's stored in straightforward reading order, with one byte per attribute cell, for a total of 768 bytes. The byte represents:
 +
 
 +
{|class="wikitable"
 +
! Bit !! Function
 +
|-
 +
| 0-2 || "Ink" color (color of 1 bits). From 0-7: black, blue, red, magenta, green, cyan, yellow, white.
 +
|-
 +
| 3-5 || "Paper" color (color of 0 bits).
 +
|-
 +
| 6 || Bright flag (toggles brighter version of both colors).
 +
|-
 +
| 7 || Flash flag (toggles regular alternation of ink and paper colors)
 +
|}
 +
 
 +
If Enhanced ULA is enabled, then this no longer applies; see below.
 +
 
 +
== Calculating line addresses in interleaved video modes ==
 +
 
 +
The line number can be broken down into bits as follows:
  
 
{| class=wikitable
 
{| class=wikitable
Line 24: Line 45:
 
Each 3rd is 64 lines, so the top two bits of the line number indicate which 3rd we're in, with the highest being %10 for 128 (%11 would be 192, off the bottom of the screen). Then, each cell is 8 lines, so bits 3-5 of the line number give the cell address, and the remaining bits give the line within that cell.
 
Each 3rd is 64 lines, so the top two bits of the line number indicate which 3rd we're in, with the highest being %10 for 128 (%11 would be 192, off the bottom of the screen). Then, each cell is 8 lines, so bits 3-5 of the line number give the cell address, and the remaining bits give the line within that cell.
  
The thirds are stored in sequential order; each third contains 64 lines; and storing a line takes 32 bytes, meaning that the 3rd number is multiplied by 2048. Add $4000 for the start of the screen and that'll give the address of the start of the target third. Now, to get to the block for the correct line number. To store the top line of a single row of cells takes 32 bytes; but since all the top lines for 8 cells are stored together, there's actually 256 bytes (32*8) between lines. So the offset must be multiplied by 256 and added to the address. Then, to select the correct cell within that block, the cell number needs to be multiplied by 32. So the final 16-bit address is:
+
The thirds are stored in sequential order; each third contains 64 lines; and storing a line takes 32 bytes. This means each 3rd takes 2048 bytes, so the "which 3rd" number is multiplied by 2048. Add $4000 for the start of the screen and that'll give the address of the start of the target third. Now we need to get to the block for the correct line number. To store the top line of a single row of cells takes 32 bytes; but since all the top lines for 8 cells are stored together, there's actually 256 bytes (32*8) between lines. So the line number must be multiplied by 256 and added to the address. Then, to select the correct cell within that block, the cell number needs to be multiplied by 32 (because each line takes 32 bytes). So the final 16-bit address is:
  
 
{| class=wikitable
 
{| class=wikitable
Line 33: Line 54:
  
 
The five lowest bits of this value are then used to select between the 32 horizontal cells on that line, which is simply done by dividing the pixel address by 8.
 
The five lowest bits of this value are then used to select between the 32 horizontal cells on that line, which is simply done by dividing the pixel address by 8.
 
As you can see from the above, pixel data is stored with 1-bit color in the pixel data memory. However, it is possible for the color to vary across the screen. The snag is that you can set only two colours within a single ''attribute cell'' - that is, an 8x8 area.
 
 
Color data is stored at $5800 onwards. Unlike the pixel data, it's stored in straightforward reading order, with one byte per attribute cell, for a total of 768 bytes. The byte represents:
 
 
{|class="wikitable"
 
! Bit !! Function
 
|-
 
| 0-2 || "Ink" color (color of 1 bits). From 0-7: black, blue, red, magenta, green, cyan, yellow, white. Note that ULAPlus (see below) allows these colors to be redefined.
 
|-
 
| 3-5 || "Paper" color (color of 0 bits).
 
|-
 
| 6 || Bright flag (toggles brighter version of both colors). If ULAPlus is enabled, bits 6-7 instead select between the 4 available palettes.
 
|-
 
| 7 || Flash flag (toggles regular alternation of ink and paper colors)
 
|}
 
 
[[File:Ktclash.png|200px|thumb|left|Color clash in a classic spectrum game. The corners of the knight's helmet appear green and red because they are in the same attribute cell as the plant and table respectively.]]
 
Because you can have only one color value per 8x8 cell, some older games exhibited "color clash" in which an object or part of an object would appear the wrong color because it needed to be drawn inside an 8x8 cell with another object of a different color.
 
 
<div style="clear:{{{1|both}}};"></div>
 
  
 
= Enhanced video modes =
 
= Enhanced video modes =
 
The Next adds a number of additional video modes to the standard ULA.
 
The Next adds a number of additional video modes to the standard ULA.
  
== Timex Sinclar Double Buffering ==
+
== Timex Sinclair Double Buffering ==
Writing %001 to the lower 3 bits of {{PortNo|$xxFF}} will change the accessed base screen address to $6000 instead of $4000. Writing %000 restores the normal base screen address. This allows this area of memory to be used for a "double buffer" for smooth frame transitions. Note however that the Spectrum 128k's bank switching also allows double buffering (see [[Memory Map]]) which can be combined with this.
+
Writing %001 to the lower 3 bits of {{PortNo|$xxFF}} will change the accessed base screen address to $6000 instead of $4000 (or otherwise add $2000 to the accessed true address, moving it into the second half of the appropriate 16k-bank or the next 8k-bank). Writing %000 restores the normal base screen address. This allows this area of memory to be used for a "double buffer" for smooth frame transitions. Note however that the Spectrum 128k's bank switching also allows double buffering (using Bank 7, see [[Memory map]]), but only first half of bank 7 is mirrored inside the FPGA in the fast BRAM region. The Layer 2 can be used in parallel only when ULA layer data are coming from BRAM memory in the FPGA (the mirror of first half of Bank 7 is new feature of latest cores 3.0.x, in 2.0 cores using the ZX128 shadow screen caused the Layer 2 to switch off).
  
 
== Timex Sinclair Hi-Res Mode ==
 
== Timex Sinclair Hi-Res Mode ==
Writing %110 to the lower 3 bits of {{PortNo|$xxFF}} will change the screen resolution to 512x192, doubling the X resolution. This still uses the Double Buffer structure of one set of screen data at $4000 and another at $6000, but now columns are alternately read from the two buffers to account for the higher resolution. In addition, attributes are disabled: this mode supports only two colors. Which they are can be set by writing bits 3-5 of {{PortNo|$xxFF}}.
+
Writing %110 to the lower 3 bits of {{PortNo|$xxFF}} will change the screen resolution to 512x192, doubling the X resolution. This still uses the Double Buffer structure of one set of screen data at $4000 and another at $6000, but now columns (one column = one byte = 8 pixels) are alternately read from the two buffers to account for the higher resolution. In addition, attributes are disabled: this mode supports only two colors. Which they are can be set by writing bits 3-5 of {{PortNo|$xxFF}}.
  
 
== Timex Sinclair Hi-Color Mode ==
 
== Timex Sinclair Hi-Color Mode ==
 
Writing %010 to the lower 3 bits of {{PortNo|$xxFF}} will disable the standard attribute area. Instead, the attribute area is set to begin at $6000 and to have the same interleaved structure as the pixel data. Each attribute byte is now applied to only one ''line'' of each cell, rather than the whole cell. The storage structure matches that of the pixel data (including the weird interleaving). This means that the areas of color clash are now limited to 8x1 blocks instead of 8x8 blocks.
 
Writing %010 to the lower 3 bits of {{PortNo|$xxFF}} will disable the standard attribute area. Instead, the attribute area is set to begin at $6000 and to have the same interleaved structure as the pixel data. Each attribute byte is now applied to only one ''line'' of each cell, rather than the whole cell. The storage structure matches that of the pixel data (including the weird interleaving). This means that the areas of color clash are now limited to 8x1 blocks instead of 8x8 blocks.
 
   
 
   
== Radastanian/Radastan Mode ==
+
== LoRes Layer/Radasjimian Mode ==
Radastanian Mode, named after its implementor's username, is from the ZXUno system. It allows 16 colors, selected from 256, anywhere on the screen - at the cost of halving the standard screen resolution to 128x96. Each pixel is assigned 4 bits instead of 1.
+
LoRes Layer is a mode similar to the "Radastanian Mode" on the ZXUno, in that it offers reduced resolution in exchange for more colors. LoRes Layer has two submodes allowing any of either 16 or 256 colors anywhere on the screen, but lowers the resolution in both dimensions to 128x96.
 +
 
 +
LoRes layer is enabled by setting bit 7 in {{NextRegNo|$15}}. The number of available colours is selected by bit 5 in {{NextRegNo|$6A}} with 0 selecting 256 colours and 1 selecting 16 colours.
 +
 
 +
In 256 colour mode each pixel is assigned one byte, in reading order (without interleaving). The first 48 lines are stored between $4000 and $5800 (16K bank 5 $0000-$1800), and the second 48 between $6000 and $7800 (16k bank 5 $2000-$3800). Each byte is an index into the ULA palette.
 +
 
 +
In 16 colour mode a byte corresponds to a pair of pixels with the most significant nybble corresponding to the left pixel and the least significant to the right pixel. Pixels are arranged in memory in reading order (without interleaving). The image is stored in one of two locations either $4000-$5800 (16K bank 5 $0000-$1800) or $6000-$7800 (16K bank 5 $2000-$3800). The location is determined by the xor of bit 4 of {{NextRegNo|$6A}} and bit 0 of {{PortNo|$xxFF}}. The colour of each pixel combines the value of its corresponding nybble with the Radistan palette offset in bits 3-0 of {{NextRegNo|$6A}}.
 +
 
 +
== Enhanced ULA ==
  
Operation of Radastanian mode and the ZX-Uno configuration on the Next is not yet clear.
+
The Spectrum Next comes with Enhanced ULA which allows the standard Spectrum graphics to display 256 colours on the screen at once. It uses the system [[Palettes]] in the same way as [[Sprites]] and [[Layer 2]].
  
= ULAPlus =
+
Setting bit 0 of {{NextRegNo|$43}} enables the Enhanced ULA mode. In this mode, the breakdown of Ink/Paper/FLASH/BRIGHT bits in the attribute cells given above is ignored. Instead, the bit value written to {{NextRegNo|$42}} is used as a bitmask to determine which bits are used for the ink color palette index (it must mask off a number of bits on the LSB side, eg %00111111, so not %01010101 or anything silly like that!) and the remaining bits, with 128 added, are used for the paper color palette index. The mask %11111111, to treat ''all'' bits as ink, is legal; if used the paper color in every cell will be {{NextRegNo|$4A}} (since core 3.0, it was color index 128 in 2.0 core). The mask %00000000 to treat all bits as paper is not legal.
ULAPlus allows 64 colors on screen at once via re-purposing the FLASH and BRIGHT bits as extra color bits. It also allows these colors to be selected from a palette of 256. It is controlled via {{PortNo|$BF3B}} and {{PortNo|$FF3B}}.
 
  
 
= Additional features =
 
= Additional features =
In addition to the Enhanced ULA, the Spectrum Next adds [[Sprites]] and [[Layer 2]] which are not ULA controlled.
+
In addition to the Enhanced ULA, the Spectrum Next adds [[Sprites]], [[Layer 2]] and a [[Tilemap]] which are not ULA controlled.

Latest revision as of 14:42, 19 November 2020

The ULA is the Spectrum video and input chip. The Enhanced ULA adds extra video modes and features to the standard Spectrum.

ULA stands for "Uncommitted Logic Array" and refers to the manufacturing process involved. It does not relate to the video behavior of the chip. The chip itself is a custom chip.

Spectrum Video Mode

The standard Spectrum has only one video mode, with a resolution of 256x192 (not including the border) and 15 colours. This screen is further divided into 8x8 "attribute cells", so the attribute cell resolution is 32x24.

The ULA reads memory from 16k-Bank 5 or 16k-Bank 7 based on the setting at Memory Paging Control ($7FFD / 32765). If you haven't done any fancy messing about with the memory map, or you're using Spectrum 48k mode, then the screen memory will start at $4000.

There is one bit per pixel, so each byte represents 8 pixels (ie, one line of an attribute cell). Each screen line is stored in straightforward left-to-right order, so the 32 bytes from $4000 onwards represent all the pixels on the first line of the screen. Each 1 bit means the pixel is drawn in the "ink" color; a 0 bit means it is drawn in the "paper" color. Which colors these are is specified in the attribute blocks described below.

Unfortunately, while the columns of the screen are in straightforward order, the lines are not. The 192 line screen is vertically divided into thirds, with each third containing 64 lines (or 8 attribute cells). These three thirds are stored sequentially in memory, but within each third, the order is not what you'd expect. You'd expect it'd store the first line of the first cell, the second line of the first cell.. up to the eighth line of the first cell, then the first line of the second cell. Instead, the sorting is inverted. So it stores the first line of the first cell, then the first line of the second cell, then the first line of the third cell, and so on.. up to the first line of the eighth cell, which is then followed by the second line of the first cell!

This means that getting the address of the start of a given line can be a tricky business. The Spectrum Next provides the PIXELAD opcode to automatically perform the necessary transition. It can be done manually by breaking the line number (0-191) into bits as described below.

Color clash in a classic spectrum game. The corners of the knight's helmet appear green and red because they are in the same attribute cell as the plant and table respectively.

Pixel data is stored with 1-bit color in the pixel data memory. However, it is possible for the color to vary across the screen. The snag is that you can set only two colours within a single attribute cell - that is, an 8x8 area. Because you can have only one color value per 8x8 cell, some older games exhibited "color clash" in which an object or part of an object would appear the wrong color because it needed to be drawn inside an 8x8 cell with another object of a different color.

Color data is stored at $5800 onwards. Unlike the pixel data, it's stored in straightforward reading order, with one byte per attribute cell, for a total of 768 bytes. The byte represents:

Bit Function
0-2 "Ink" color (color of 1 bits). From 0-7: black, blue, red, magenta, green, cyan, yellow, white.
3-5 "Paper" color (color of 0 bits).
6 Bright flag (toggles brighter version of both colors).
7 Flash flag (toggles regular alternation of ink and paper colors)

If Enhanced ULA is enabled, then this no longer applies; see below.

Calculating line addresses in interleaved video modes

The line number can be broken down into bits as follows:

128 64 32 16 8 4 2 1
3rd 3rd V-Cell V-Cell V-Cell Offset Offset Offset

Each 3rd is 64 lines, so the top two bits of the line number indicate which 3rd we're in, with the highest being %10 for 128 (%11 would be 192, off the bottom of the screen). Then, each cell is 8 lines, so bits 3-5 of the line number give the cell address, and the remaining bits give the line within that cell.

The thirds are stored in sequential order; each third contains 64 lines; and storing a line takes 32 bytes. This means each 3rd takes 2048 bytes, so the "which 3rd" number is multiplied by 2048. Add $4000 for the start of the screen and that'll give the address of the start of the target third. Now we need to get to the block for the correct line number. To store the top line of a single row of cells takes 32 bytes; but since all the top lines for 8 cells are stored together, there's actually 256 bytes (32*8) between lines. So the line number must be multiplied by 256 and added to the address. Then, to select the correct cell within that block, the cell number needs to be multiplied by 32 (because each line takes 32 bytes). So the final 16-bit address is:

32768 16384 8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1
0 1 0 3rd 3rd Offset Offset Offset V-Cell V-Cell V-Cell 0 0 0 0 0

The five lowest bits of this value are then used to select between the 32 horizontal cells on that line, which is simply done by dividing the pixel address by 8.

Enhanced video modes

The Next adds a number of additional video modes to the standard ULA.

Timex Sinclair Double Buffering

Writing %001 to the lower 3 bits of Timex Sinclair Video Mode Control ($xxFF / 255) will change the accessed base screen address to $6000 instead of $4000 (or otherwise add $2000 to the accessed true address, moving it into the second half of the appropriate 16k-bank or the next 8k-bank). Writing %000 restores the normal base screen address. This allows this area of memory to be used for a "double buffer" for smooth frame transitions. Note however that the Spectrum 128k's bank switching also allows double buffering (using Bank 7, see Memory map), but only first half of bank 7 is mirrored inside the FPGA in the fast BRAM region. The Layer 2 can be used in parallel only when ULA layer data are coming from BRAM memory in the FPGA (the mirror of first half of Bank 7 is new feature of latest cores 3.0.x, in 2.0 cores using the ZX128 shadow screen caused the Layer 2 to switch off).

Timex Sinclair Hi-Res Mode

Writing %110 to the lower 3 bits of Timex Sinclair Video Mode Control ($xxFF / 255) will change the screen resolution to 512x192, doubling the X resolution. This still uses the Double Buffer structure of one set of screen data at $4000 and another at $6000, but now columns (one column = one byte = 8 pixels) are alternately read from the two buffers to account for the higher resolution. In addition, attributes are disabled: this mode supports only two colors. Which they are can be set by writing bits 3-5 of Timex Sinclair Video Mode Control ($xxFF / 255).

Timex Sinclair Hi-Color Mode

Writing %010 to the lower 3 bits of Timex Sinclair Video Mode Control ($xxFF / 255) will disable the standard attribute area. Instead, the attribute area is set to begin at $6000 and to have the same interleaved structure as the pixel data. Each attribute byte is now applied to only one line of each cell, rather than the whole cell. The storage structure matches that of the pixel data (including the weird interleaving). This means that the areas of color clash are now limited to 8x1 blocks instead of 8x8 blocks.

LoRes Layer/Radasjimian Mode

LoRes Layer is a mode similar to the "Radastanian Mode" on the ZXUno, in that it offers reduced resolution in exchange for more colors. LoRes Layer has two submodes allowing any of either 16 or 256 colors anywhere on the screen, but lowers the resolution in both dimensions to 128x96.

LoRes layer is enabled by setting bit 7 in Sprite and Layers System Register ($15). The number of available colours is selected by bit 5 in LoRes Control Register ($6A) with 0 selecting 256 colours and 1 selecting 16 colours.

In 256 colour mode each pixel is assigned one byte, in reading order (without interleaving). The first 48 lines are stored between $4000 and $5800 (16K bank 5 $0000-$1800), and the second 48 between $6000 and $7800 (16k bank 5 $2000-$3800). Each byte is an index into the ULA palette.

In 16 colour mode a byte corresponds to a pair of pixels with the most significant nybble corresponding to the left pixel and the least significant to the right pixel. Pixels are arranged in memory in reading order (without interleaving). The image is stored in one of two locations either $4000-$5800 (16K bank 5 $0000-$1800) or $6000-$7800 (16K bank 5 $2000-$3800). The location is determined by the xor of bit 4 of LoRes Control Register ($6A) and bit 0 of Timex Sinclair Video Mode Control ($xxFF / 255). The colour of each pixel combines the value of its corresponding nybble with the Radistan palette offset in bits 3-0 of LoRes Control Register ($6A).

Enhanced ULA

The Spectrum Next comes with Enhanced ULA which allows the standard Spectrum graphics to display 256 colours on the screen at once. It uses the system Palettes in the same way as Sprites and Layer 2.

Setting bit 0 of Enhanced ULA Control Register ($43) enables the Enhanced ULA mode. In this mode, the breakdown of Ink/Paper/FLASH/BRIGHT bits in the attribute cells given above is ignored. Instead, the bit value written to Enhanced ULA Ink Color Mask ($42) is used as a bitmask to determine which bits are used for the ink color palette index (it must mask off a number of bits on the LSB side, eg %00111111, so not %01010101 or anything silly like that!) and the remaining bits, with 128 added, are used for the paper color palette index. The mask %11111111, to treat all bits as ink, is legal; if used the paper color in every cell will be Transparency colour fallback Register ($4A) (since core 3.0, it was color index 128 in 2.0 core). The mask %00000000 to treat all bits as paper is not legal.

Additional features

In addition to the Enhanced ULA, the Spectrum Next adds Sprites, Layer 2 and a Tilemap which are not ULA controlled.