<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://wiki.specnext.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Varmfskii</id>
	<title>SpecNext Wiki - User contributions [en-gb]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.specnext.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Varmfskii"/>
	<link rel="alternate" type="text/html" href="https://wiki.specnext.dev/Special:Contributions/Varmfskii"/>
	<updated>2026-05-23T08:06:40Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://wiki.specnext.dev/index.php?title=Layer_2&amp;diff=11609</id>
		<title>Layer 2</title>
		<link rel="alternate" type="text/html" href="https://wiki.specnext.dev/index.php?title=Layer_2&amp;diff=11609"/>
		<updated>2020-11-19T20:03:15Z</updated>

		<summary type="html">&lt;p&gt;Varmfskii: size of hidden memory&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Layer 2 provides an additional screen layer at 256x192 256 colours, 320x256 256 colours or 640x256 16 colours in which every pixel is individually coloured. Layer 2 may appear in place of, behind, or above the ULA-generated/Tilemap layer.&lt;br /&gt;
&lt;br /&gt;
The Layer 2 screen occupies 48kiB or 80kiB, which is stored in 3 (or 5) consecutive [[Memory map|banks]]. By NextZXOS/NextBASIC default, banks 9-11 are used for the visible and &amp;quot;shadow&amp;quot; Layer 2 screen (the HW after power-on defaults to 8-10 for displayed and 11-13 for shadow screen, but that gets modified by NextZXOS booting up). These can be set using {{NextRegNo|$12}} and {{NextRegNo|$13}} (avoid banks 5, 7 and 8 to be used as Layer 2 screen, unless you are familiar with SRAM and BRAM of the board and how the ULA screen memory has special treatment in Next&#039;s FPGA).&lt;br /&gt;
&lt;br /&gt;
Each pixel of Layer 2 is assigned 1 byte of video memory (in 8bpp modes). This means Layer 2 consumes a total of 48kiB (256x192) or 80kiB (320x256). Since the Spectrum banks are 16kiB, Layer 2 256x192 mode is divided horizontally into 3 banks of 64 lines each, each of which is exactly 16kiB. The mode 320x256 (and 640x256) is divided vertically into 5 banks of 64 (128) columns each.&lt;br /&gt;
&lt;br /&gt;
Layer 2 is controlled via {{PortNo|$123B}} and {{NextRegNo|$70}}, the port is bit mapped as follows:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 7-6 || Video RAM bank select (write/read paging)&lt;br /&gt;
|-&lt;br /&gt;
| 5-4 || Reserved, write 0&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Use Shadow Layer 2 for paging - {{NextRegNo|$13}}&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Enable Layer 2 read-only paging&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Layer 2 visible - {{NextRegNo|$12}}&lt;br /&gt;
Since core 3.0 this bit has mirror in {{NextRegNo|$69}}&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Enable Layer 2 write-only paging&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When bit 0 of $123B is set to 1, the appropriate area of Layer 2 video memory (as set by bits 6-7) is accessed by &#039;&#039;&#039;writes&#039;&#039;&#039; into slot 1, ie memory area $0000-$3fff (see [[Memory map]]). This prevents any conflict since this area would normally be ROM and thus useless to write to. However, you &#039;&#039;&#039;cannot READ the contents of Layer 2 via this mapping!&#039;&#039;&#039; Reading addresses in this range will read the values from the ROM page (or RAM bank if in AllRam mode) that would be mapped there normally if Layer 2 paging was disabled.&lt;br /&gt;
&lt;br /&gt;
When bit 2 of $123B is set to 1 (new feature of core 3.0), the same area $0000-$3fff is remapped for read, allowing read access into Layer 2 bank selected by bits 3,6 and 7 (while write will still go into the regular ROM/RAM page).&lt;br /&gt;
&lt;br /&gt;
With both bits 0 and 2 set you are creating alternative read+write mapping of RAM (technically identical to mapping done by MM0+MMU1 registers).&lt;br /&gt;
&lt;br /&gt;
Bank 5 and first half of Bank 7, when being accessed by regular means (MMU paging, default memory mapping, DMA), are overshadowed by fast BRAM memory inside the FPGA chip, which is then used to generate ULA screen and [[Tilemap]] graphics (aka &amp;quot;Layer 3&amp;quot;) - not using the SRAM memory chip in that particular area. This Layer 2 (mapping and visible data) is the only exception, circumventing this mechanism and accessing the Bank 5 and Bank 7 in the main memory SRAM chip (giving you extra 16+8kiB of &amp;quot;secret&amp;quot; memory and further headache to emulators&#039; authors). If you are not sure what this means, just avoid using bank 5 and 7 for Layer 2, use values greater/equal to 8 (and avoid also Bank 8, unless you want to destroy NextBASIC warm-restart/soft-reset variables).&lt;br /&gt;
&lt;br /&gt;
Bits 6 and 7 contain the number which third of Layer 2 should be mapped (0..2), or (new feature of core 3.0) when value 3 is set, whole 48kiB of Layer 2 is mapped into area $0000-$bfff (make sure your code, stack and interrupts will cope well with such new mapping).&lt;br /&gt;
&lt;br /&gt;
There is one more new functionality in latest 3.x cores, allowing to set bank-offset variable from 0 to 7. This offset is further applied to the bank selected for write/read (by writing value 0..7 to the port with bit4 set (so it&#039;s value 16..23). If you did set for example 16kiB write mapping of first bank, the first bank is 9, and use value 21 for bank-offset setup (+5 offset), the bank mapped into $0000..$3FFF address area will be 14 (9+5). This way you can map full 80kiB of pixel data into the bottom 16kiB window (or bottom 48kiB window), using different offsets.&lt;br /&gt;
&lt;br /&gt;
Use {{NextRegNo|$70}} to select particular Layer2 mode, and to modify palette offset (added to top four bits of each pixel). Don&#039;t forget to set up Layer 2 clip window correctly for each mode ({{NextRegNo|$18}}).&lt;br /&gt;
&lt;br /&gt;
You can still use also the regular [[Memory map|banking]] ports to switch in one of the Layer 2 banks in slot for at $C000 (or use the ZX Next MMU registers to map that RAM in other regions). This will allow you to read and write the memory as usual. The ability to write to Layer 2 via writes into slot 1 is provided for convenience and to allow graphics data to be easily copied from extended RAM banks.&lt;br /&gt;
&lt;br /&gt;
Pixels are drawn to Layer 2 by writing to the appropriate area of RAM. Layer 2 pixels in 256x192 mode are in English reading order with no ULA-style interlacing. Since there are 256 pixels per line, and when using access via slot 1 the memory port starts at $0000, the upper byte of the address exactly equals the Y coordinate (within the selected third of the screen) and the lower byte exactly equals the X coordinate.&lt;br /&gt;
&lt;br /&gt;
In mode 320x256 (8bpp) the pixels are stored in memory going from top to bottom and left to right (second byte is first pixel on second line, 256th byte is second pixel on first line). Since there are 256 pixels per column, the upper byte of address could represent the X coordinate (only specific range of them, as whole 0..319 range does not fit into 8 bits), and the lower byte of address is Y coordinate. The total pixel memory is 80kiB (five 16kiB banks), and could be mapped into memory either by MMU or by bank-offset feature of {{PortNo|$123B}}.&lt;br /&gt;
&lt;br /&gt;
In mode 640x256 (4bpp) the pixels are stored identically to 320x256 mode, but every byte contains two pixels. The top nibble (top four bits) form &amp;quot;left&amp;quot; pixel, and the bottom nibble form &amp;quot;right&amp;quot; pixel, so first 256 bytes will display as two columns on screen, not one.&lt;br /&gt;
&lt;br /&gt;
Note that you will need to manually clear the Layer 2 screen before drawing on it, as it may contain random data when the machine starts up.&lt;br /&gt;
&lt;br /&gt;
System registers {{NextRegNo|$16}}, {{NextRegNo|$71}} and {{NextRegNo|$17}} apply a pixel shift to all content in Layer &lt;br /&gt;
2, allowing scrolling effects to be created.&lt;br /&gt;
&lt;br /&gt;
Since core 3.0 the visibility of Layer 2 is not affected by usage of ZX128 ULA-shadow (Bank 7) screen.&lt;br /&gt;
&lt;br /&gt;
Obsolete info for core 2.x (limitation was lifted in core 3.0): &amp;lt;del&amp;gt;the visible Layer 2 will cause the slow down of CPU to 7MHz.&amp;lt;/del&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To use double-buffered scheme for Layer 2, think about {{NextRegNo|$12}} being display related (i.e. has to be changed to display new Layer 2, when the new image is already prepared) (or it may be modified also during frame to compose final image from various memory areas), while {{NextRegNo|$13}} is related only to write-over-ROM paging functionality ({{PortNo|$123B}}).&lt;/div&gt;</summary>
		<author><name>Varmfskii</name></author>
	</entry>
	<entry>
		<id>https://wiki.specnext.dev/index.php?title=Video_Modes&amp;diff=11607</id>
		<title>Video Modes</title>
		<link rel="alternate" type="text/html" href="https://wiki.specnext.dev/index.php?title=Video_Modes&amp;diff=11607"/>
		<updated>2020-11-19T14:42:30Z</updated>

		<summary type="html">&lt;p&gt;Varmfskii: Added info on the 16 colour  lores mode&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The ULA is the Spectrum video and input chip. The Enhanced ULA adds extra video modes and features to the standard Spectrum.&lt;br /&gt;
&lt;br /&gt;
ULA stands for &amp;quot;Uncommitted Logic Array&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
= Spectrum Video Mode =&lt;br /&gt;
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 &amp;quot;attribute cells&amp;quot;, so the attribute cell resolution is 32x24.&lt;br /&gt;
&lt;br /&gt;
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&#039;t done any fancy messing about with the memory map, or you&#039;re using Spectrum 48k mode, then the screen memory will start at $4000.&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;ink&amp;quot; color; a 0 bit means it is drawn in the &amp;quot;paper&amp;quot; color. Which colors these are is specified in the attribute blocks described below.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, while the columns of the screen are in straightforward order, the &#039;&#039;lines&#039;&#039; 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 &#039;&#039;within&#039;&#039; each third, the order is not what you&#039;d expect. You&#039;d expect it&#039;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 &#039;&#039;inverted&#039;&#039;. So it stores the first line of the first cell, then the &#039;&#039;first line of the second cell&#039;&#039;, 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!&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
[[File:Ktclash.png|200px|thumb|left|Color clash in a classic spectrum game. The corners of the knight&#039;s helmet appear green and red because they are in the same attribute cell as the plant and table respectively.]]&lt;br /&gt;
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 &#039;&#039;attribute cell&#039;&#039; - that is, an 8x8 area. Because you can have only one color value per 8x8 cell, some older games exhibited &amp;quot;color clash&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
Color data is stored at $5800 onwards. Unlike the pixel data, it&#039;s stored in straightforward reading order, with one byte per attribute cell, for a total of 768 bytes. The byte represents:&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bit !! Function&lt;br /&gt;
|-&lt;br /&gt;
| 0-2 || &amp;quot;Ink&amp;quot; color (color of 1 bits). From 0-7: black, blue, red, magenta, green, cyan, yellow, white. &lt;br /&gt;
|-&lt;br /&gt;
| 3-5 || &amp;quot;Paper&amp;quot; color (color of 0 bits).&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Bright flag (toggles brighter version of both colors). &lt;br /&gt;
|-&lt;br /&gt;
| 7 || Flash flag (toggles regular alternation of ink and paper colors)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If Enhanced ULA is enabled, then this no longer applies; see below.&lt;br /&gt;
&lt;br /&gt;
== Calculating line addresses in interleaved video modes ==&lt;br /&gt;
&lt;br /&gt;
The line number can be broken down into bits as follows:&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! 128 !! 64 !! 32 !! 16 !! 8 !! 4 !! 2 !! 1&lt;br /&gt;
|-&lt;br /&gt;
| 3rd || 3rd || V-Cell || V-Cell || V-Cell || Offset || Offset || Offset&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each 3rd is 64 lines, so the top two bits of the line number indicate which 3rd we&#039;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.&lt;br /&gt;
&lt;br /&gt;
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 &amp;quot;which 3rd&amp;quot; number is multiplied by 2048. Add $4000 for the start of the screen and that&#039;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&#039;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:&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! 32768 !! 16384 !! 8192 !! 4096 !! 2048 !! 1024   !! 512    !! 256    !! 128 !! 64 !! 32 !! 16 !! 8 !! 4 !! 2 !! 1&lt;br /&gt;
|-&lt;br /&gt;
| 0     || 1     ||    0 || 3rd  || 3rd  || Offset || Offset || Offset || V-Cell || V-Cell || V-Cell || 0 || 0 || 0 || 0 || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Enhanced video modes =&lt;br /&gt;
The Next adds a number of additional video modes to the standard ULA.&lt;br /&gt;
&lt;br /&gt;
== Timex Sinclair Double Buffering ==&lt;br /&gt;
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 &amp;quot;double buffer&amp;quot; for smooth frame transitions. Note however that the Spectrum 128k&#039;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).&lt;br /&gt;
&lt;br /&gt;
== Timex Sinclair Hi-Res Mode ==&lt;br /&gt;
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}}.&lt;br /&gt;
&lt;br /&gt;
== Timex Sinclair Hi-Color Mode ==&lt;br /&gt;
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 &#039;&#039;line&#039;&#039; 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.&lt;br /&gt;
 &lt;br /&gt;
== LoRes Layer/Radasjimian Mode ==&lt;br /&gt;
LoRes Layer is a mode similar to the &amp;quot;Radastanian Mode&amp;quot; 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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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}}.  &lt;br /&gt;
&lt;br /&gt;
== Enhanced ULA ==&lt;br /&gt;
&lt;br /&gt;
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]].&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;all&#039;&#039; 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.&lt;br /&gt;
&lt;br /&gt;
= Additional features =&lt;br /&gt;
In addition to the Enhanced ULA, the Spectrum Next adds [[Sprites]], [[Layer 2]] and a [[Tilemap]] which are not ULA controlled.&lt;/div&gt;</summary>
		<author><name>Varmfskii</name></author>
	</entry>
</feed>