Display: Difference between revisions

From WSdev Wiki
Jump to navigationJump to search
No edit summary
(→‎LCD Final Line ($16): I'd suspect row inversion)
 
(25 intermediate revisions by one other user not shown)
Line 12: Line 12:
=== Tiles ===
=== Tiles ===


The "mono" WonderSwan can display up to 512 tiles stored in a planar format, with two bits total per pixel.
The WonderSwan can display up to 512 distinct tiles at a time, with two bits of palette index information for every pixel.


The planes are interleaved with each other; that is, two consecutive bytes form a full 8x1 row of the tile:
The WonderSwan Color expands this to 1024 distinct tiles for background (with 512 remaining the limit for sprites), while also introducing modes with four bits of palette index information for every pixel.
 
==== 2 bits per pixel, planar ====
 
The tiles are stored in an interleaved planar format, with two bits total for every pixel. Odd bytes store the first plane (bit 0 of each pixel), while even bytes store the second plane (bit 1 of each pixel).


<pre>
<pre>
  plane 0     plane 1
            tile data (16 bytes)
byte N      byte N+1
01 7C 01 FC 00 C0 18 D8 18 D8 00 C0 00 00 C0 00
7  bit  0   7  bit  0     full tile
 
---- ----   ---- ----
                      ||
.... ...1   .222 22..      .22222.1
                      \/
.... ...1   2222 22..      222222.1
 
.... ....   22.. ....      22......
  plane 0         plane 1
...1 1...   22.2 2...  --\  22.33...
7  bit  0       7  bit  0           full tile
...1 1...   22.2 2...  --/  22.33...
---- ----       ---- ----
.... ....   22.. ....      22......
.... ...1 = 01  .222 22.. = 7C       .22222.1
.... ....   .... ....      ........
.... ...1 = 01  2222 22.. = FC       222222.1
11.. ....   .... ....      11......
.... .... = 00  22.. .... = C0       22......
...1 1... = 18  22.2 2... = D8 --\  22.33...
...1 1... = 18  22.2 2... = D8 --/  22.33...
.... .... = 00  22.. .... = C0       22......
.... .... = 00  .... .... = 00       ........
11.. .... = C0  .... .... = 00       11......
</pre>
</pre>


The WonderSwan Color extends this with an additional 512 tiles (available for screens only, not sprites) and support for three new modes.
This matches the format used by the Game Boy.


* The first new mode is another two bit per pixel mode, but using color palettes instead of monochrome shades.
==== 4 bits per pixel, planar ====


The latter two modes extend tiles to four bits per pixel.
This mode is stored in a manner similar to the 2 bits per pixel mode, but with an additional two planes for bit 2 and bit 3 of each pixel's palette index, expanding the tile data to 32 bytes.


* The first among them is the planar mode, which works similarly to the two bit per pixel mode:


<pre>
<pre>
  plane 0     plane 1     plane 2     plane 3
                                      tile data (32 bytes)
byte N      byte N+1    byte N+2    byte N+3
54 32 01 00 54 32 F1 00 54 32 01 F0 54 32 F1 F0 04 02 01 00 F8 04 02 01 00 F8 04 02 00 00 F8 04
7  bit  0   7  bit  0   7  bit  0   7  bit  0     full rows
 
---- ----   ---- ----   ---- ----   ---- ----
                                              ||
1.1. 1.1.   22.. 22..   4444 ....   .... ....  --\  7654321.
                                              \/
.1.1 .1.1    ..22 ..22    .... 4444    8888 8888 --/  89ABCDEF
 
  plane 0         plane 1         plane 2         plane 3
7  bit  0       7  bit  0       7  bit  0       7  bit  0           full tile
---- ----       ---- ----       ---- ----       ---- ----
.1.1 .1.. = 54  ..22 ..2. = 32  .... ...4 = 01  .... .... = 00      .123.124
.1.1 .1.. = 54  ..22 ..2. = 32  4444 ...4 = F1  .... .... = 00      4567.124
.1.1 .1.. = 54  ..22 ..2. = 32  .... ...4 = 01  8888 .... = F0      89AB.124
.1.1 .1.. = 54  ..22 ..2. = 32  4444 ...4 = F1  8888 .... = F0 --\  CDEF.124
.... .1.. = 04  .... ..2. = 02  .... ...4 = 01  .... .... = 00 --/  .....124
1111 1... = F8  .... .2.. = 04  .... ..4. = 02  .... ...8 = 01      11111248
.... .... = 00  2222 2... = F8  .... .4.. = 04  .... ..8. = 02      2222248.
.... .... = 00  .... .... = 00  4444 4... = F8  .... .8.. = 04      444448..
</pre>
</pre>


* The second is the chunky (packed) mode, which instead stores each plane as consecutive bits, with each byte responsible for two of the eight pixels:
This format matches the one used by the Sega Master System and Game Gear family of consoles.
 
==== 4 bits per pixel, packed ====
 
Unlike the previous two formats, in the packed format each byte stores the complete palette index of two pixels - the high four bits store the left pixel, while the low four bits store the right pixel. Four such bytes make up a row of eight pixels from left to right.


<pre>
<pre>
  byte N      byte N+1     byte N+2     byte N+3
                                      tile data (32 bytes)
pxl0 pxl1    pxl2 pxl3    pxl4 pxl5    pxl6 pxl7
01 23 01 24 45 67 01 24 89 AB 01 24 CD EF 01 24 00 00 01 24 11 11 12 48 22 22 24 80 44 44 48 00
7 bit 0   7 bit  0    7 bit  0    7  bit 0      full rows
 
---- ----    ---- ----    ---- ----    ---- ----
                                              ||
.421 .42.   .4.1 .4..   ..21 ..2.   ...1 .... --\ 7654321.
                                              \/
8... 8..1   8.2. 8.21    84.. 84.1    842. 8421  --/  89ABCDEF
 
  byte     0            1         2         3
  bits 7-4 3-0     7-4 3-0    7-4 3-0    7-4 3-0
  pixel 0   1        2  3      4  5     6  7          full tile
      --- ---     --- ---    --- ---    --- ---
        . 1 = 01    2 3 = 23  . 1 = 01  2 4 = 24      .123.124 = 01 23 01 24
        4 5 = 45    6 7 = 67  . 1 = 01  2 4 = 24      4567.124 = 45 67 01 24
        8 9 = 89    A B = AB  . 1 = 01  2 4 = 24      89AB.124 = 89 AB 01 24
        C D = CD    E F = EF  . 1 = 01  2 4 = 24  --\  CDEF.124 = CD EF 01 24
        . . = 00    . . = 00  . 1 = 01  2 4 = 24 --/ .....124 = 00 00 01 24
        1 1 = 11    1 1 = 11  1 2 = 12  4 8 = 48      11111248 = 11 11 12 48
        2 2 = 22    2 2 = 22  2 4 = 24  8 . = 80      2222248. = 22 22 24 80
        4 4 = 44    4 4 = 44  4 8 = 48  . . = 00      444448.. = 44 44 48 00
</pre>
</pre>


=== Colors, Shades ===
This format matches the one used by the Mega Drive console.


The "mono" WonderSwan uses eight value indices, which are converted by a global look-up table to eight of the sixteen shades the LCD can display:
=== Palettes ===
 
The display system provides sixteen different palettes that can be used to color or shade tiles.
 
* Palettes 0-7 can be used for the two screens only;
* Palettes 8-15 can be used for both screens and sprites.
 
==== Mono ====
 
In ''mono'' modes, palettes are stored in I/O ports 0x20 through 0x3F. Each palette contains four three-bit entries, which are pointers into a global, four-bit shade lookup table:


<pre>
<pre>
Line 68: Line 112:
  ^  (0, 2, 4, 6) ^ (1, 3, 5, 7, 9, 11, 13, 15) ^
  ^  (0, 2, 4, 6) ^ (1, 3, 5, 7, 9, 11, 13, 15) ^
  |              |                            |
  |              |                            |
Tile pixel      Value                       Displayed shade
Palette index  Value                         Displayed shade
</pre>
</pre>


In "color" mode, the WonderSwan instead loads RGB444 color values from a table in the console's internal RAM:
The shade value corresponds to the darkness of the pixel: shade 0 is the brightest, while shade 15 is the darkest.
 
==== Color ====
 
In ''color'' modes, palettes are stored as 16-bit words in memory addresses 0xFE00 through 0xFFFF, without additional lookup tables:


<pre>
<pre>
      Address
15  bit  8  7  bit  0
---- ----  ---- ----
1111 111p  pppi iii.
        |  |||| |||
        |  |||+-+++-- Index in palette (0-15)
        +--+++------- Palette number (0-15)
        Data
15  bit  8  7  bit  0
15  bit  8  7  bit  0
  ---- ----  ---- ----
  ---- ----  ---- ----
Line 83: Line 140:
</pre>
</pre>


No further processing or look-up tables are applied.
In 2 bits per pixel color modes, palette entries 4 through 15 are not used.


=== Palettes ===
==== Transparency ====
 
In two bit per pixel modes:
 
* Palettes 0-3 and 8-11 are ''opaque''. For these, index zero is treated as opaque.
* Palettes 4-7 and 12-15 are ''translucent''. For these, index zero is treated as transparent. This means that the color/shade value set to it is ignored, and only three distinct colors/shades can be used for tiles.


The WonderSwan provides sixteen different palettes. All sixteen can be used for screens only, while the latter eight can be used for screens and sprites. In addition, the background color (for areas where no opaque pixel is drawn) can be selected arbitrarily from the color palette or from the shade LUT.
In four bit per pixel modes, all palettes are ''translucent''. Index zero is always treated as transparent, and fifteen different colors/shades can be used for tiles.


In two bit per pixel modes, palettes 0 - 3 and 8 - 11 are ''opaque'' (color zero is opaque, four distinct colors are usable), while palettes 4 - 7 and 12 - 15 are ''translucent'' (color zero is transparent, three distinct colors are usable). This applies in both mono and color modes.
=== Background color ===


In four bit per pixel modes, every palette is ''translucent'' (color zero is transparent, fifteen distinct colors are usable). The first entry of each palette can be used only for the background color.
The background color is displayed if no ''opaque'' pixel from screens or sprites is drawn. This color is set in I/O port ''0x01'':


Palettes 8-15 are also referred to as sprite palettes 0-7.
* In mono modes, it is set to an entry in the shade lookup table (0-7),
* In color modes, it is set to an entry in the color palette (0-255). Note that this allows you to use the first color (color zero) of any palette, which is normally ignored and assumed to be ''transparent''.


=== Screens ===
=== Screens ===


The WonderSwan can display up to two distinct 32x32 screens. These consist of 1024 two-byte cells:
A screen is a layout of tiles. Each cell in a screen controls one 8x8 tile.
 
The display system can show two distinct screens simultaneously. It also supports hardware flipping of tiles, both horizontally and vertically.
 
The size of each screen is fixed at 32x32 cells or 256x256 pixels, while each cell is stored as a two-byte word:


<pre>
<pre>
      Address
15  bit  8  7  bit  0
---- ----  ---- ----
0bbb byyy  yyxx xxx.
  ||| ||||  |||| |||
  ||| ||||  ||++-+++-- X coordinate (0-31)
  ||| |+++--++-------- Y coordinate (0-31)
  +++-+--------------- Base address (from I/O port)
        Data
15  bit  8  7  bit  0
15  bit  8  7  bit  0
  ---- ----  ---- ----
  ---- ----  ---- ----
Line 110: Line 187:
  +-------------------- Vertical flip
  +-------------------- Vertical flip
</pre>
</pre>
In ''color'' modes, the tile bank selects between tiles 0-511 and 512-1023.


=== Sprites ===
=== Sprites ===


The WonderSwan can display up to 128 sprites at once. These are stored in a sprite table in RAM, which consists of up to 128 four-byte entries:
The display system can show up to 128 sprites at once.
 
Sprites are always drawn in front of Screen 1, but they can be drawn in front of or behind Screen 2.
 
Sprites are stored in a sprite table in the console's internal RAM. It consists of up to 128 four-byte entries, of which any sequential slice can be displayed:


<pre>
<pre>
Line 121: Line 204:
  vhPi pppt  tttt tttt
  vhPi pppt  tttt tttt
  |||| ||||  |||| ||||
  |||| ||||  |||| ||||
  |||| |||+--++++-++++- Tile index (0-511) - only bank 0
  |||| |||+--++++-++++- Tile index (0-511) - only tile bank 0
  |||| +++------------- Palette (0-7) - mapped to screen palettes 8-15
  |||| +++------------- Palette (0-7) - mapped to screen palettes 8-15
  |||+----------------- Window location - 0 = inside, 1 = outside
  |||+----------------- Window location - 0 = inside, 1 = outside
Line 143: Line 226:
</pre>
</pre>


For each row, the first 32 sprites for that row will be drawn - including sprites obscured by windows or outside of the visible range; only the Y coordinate determines this. The earlier among those sprites will be on top of the later ones.
There is a sprite limit of 32 per scanline. This means that for each scanline, only the first 32 sprites will be drawn. Note that this includes sprites obscured by windows or outside of visible X coordinates; this list is determined solely by the Y coordinate. Between sprites themselves, earlier sprites in the list are always drawn on top of later sprites in the list.
 
The sprite table is copied from the console's RAM to a SoC-internal buffer every frame on line <tt>144</tt>; one word for every clock of the line, totaling 256 words (512 bytes) for 256 clocks. This internal buffer is then used for reading sprite data on the next frame.


=== Visibility priority ===
=== Visibility priority ===
Line 159: Line 244:
=== Windows ===
=== Windows ===


Screen 2 and the sprite layer can optionally be restricted to a specific window.
Screen 2 and sprites can optionally have their drawing restricted within or outside of their specific rectangular windows.


In addition, one can control if a given element is rendered inside or outside that window. For Screen 2, this is controlled globally; for sprites, this is controlled per-sprite.
Note that for sprites, the window is enabled globally (for all sprites), but each sprite can individually decide if it's rendered inside or outside of it.


=== Icons ===
=== Icons ===


Finally, the WonderSwan features six LCD segment icons which are displayed to the right<sup>(color)</sup> or below<sup>(mono)</sup> the main display. These are, as follows:
The WonderSwan features six LCD segment icons which are displayed to the right<sup>(color)</sup> or below<sup>(mono)</sup> the main display. These are, as follows:


* Aux 3 - large circle,
* Aux 3 - large circle,
Line 191: Line 276:
7  bit  0
7  bit  0
---- ----
---- ----
..ow Ws21
..wo Ws21
   || ||||
   || ||||
   || |||+- Enable Screen 1 layer
   || |||+- Enable Screen 1 layer
Line 197: Line 282:
   || |+--- Enable Sprite layer
   || |+--- Enable Sprite layer
   || +---- Enable Sprite window
   || +---- Enable Sprite window
   |+------ Enable Screen 2 window
   |+------ Screen 2 tiles are drawn (if window enabled):
   +------- Screen 2 window location:
  |        0 = inside window,
          0 = inside, 1 = outside
  |        1 = outside window.
   +------- Enable Screen 2 window
</pre>
</pre>


{{Anchor|Display Background}}
{{Anchor|Display Background}}
=== Display Background Color ($01) ===
=== Display Background Color ($01) ===


Line 280: Line 367:
=== Screen 2 Window Right ($0A) ===
=== Screen 2 Window Right ($0A) ===
=== Screen 2 Window Bottom ($0B) ===
=== Screen 2 Window Bottom ($0B) ===
The X and Y coordinates of the Screen 2 window.
Note that all coordinates are inclusive; for example, for a 200x100 window in the top-left corner, the values should be set as follows:
* Left - 0,
* Top - 0,
* Right - 199,
* Bottom - 99.


{{Anchor|Sprite Window}}
{{Anchor|Sprite Window}}
=== Sprite Window Left ($0C) ===
=== Sprite Window Left ($0C) ===
=== Sprite Window Top ($0D) ===
=== Sprite Window Top ($0D) ===
=== Sprite Window Right ($0E) ===
=== Sprite Window Right ($0E) ===
=== Sprite Window Bottom ($0F) ===
=== Sprite Window Bottom ($0F) ===
The X and Y coordinates of the Sprite window.
Note that all coordinates are inclusive.


{{Anchor|Screen Scroll}}
{{Anchor|Screen Scroll}}
=== Screen 1 Scroll X ($10) ===
=== Screen 1 Scroll X ($10) ===
=== Screen 1 Scroll Y ($11) ===
=== Screen 1 Scroll Y ($11) ===
The X and Y coordinates that Screen 1 is scrolled by.
For example, setting Scroll X to 24 and Scroll Y to 8 will omit, in 8x8 tile units, the first three rows and the first two columns of the 32x32 screen.
=== Screen 2 Scroll X ($12) ===
=== Screen 2 Scroll X ($12) ===
=== Screen 2 Scroll Y ($13) ===
=== Screen 2 Scroll Y ($13) ===
The X and Y coordinates that Screen 2 is scrolled by.


{{Anchor|LCD Control}}
{{Anchor|LCD Control}}
=== LCD Control ($14) ===
=== LCD Control ($14) ===


Line 301: Line 411:
.... ..Ce
.... ..Ce
       ||
       ||
       |+- LCD Enable: 0 = sleep, 1 = enabled
       |+- LCD enable: 0 = sleep, 1 = enabled
       +-- Contrast (WSC): 0 = low, 1 = high
       +-- Contrast (WSC): 0 = low, 1 = high
</pre>
</pre>
The LCD enable bit controls whether or not the LCD screen is displaying graphics; if sleeping, it displays nothing (all white). Note that segments continue displaying regardless of this configuration.
Note that port $1A also provides an LCD sleep bit; the display will be disabled in the same way if any of those bits are set to "sleep".


{{Anchor|LCD Icon Control}}
{{Anchor|LCD Icon Control}}
=== LCD Icon Control ($15) ===
=== LCD Icon Control ($15) ===


Line 356: Line 471:
=== LCD Final Line ($16) ===
=== LCD Final Line ($16) ===


The final line preceding line counter restart. By default, this should be set to 158.
The final line preceding line counter restart and the beginning of active display. By default, this is set to 158, which equals 159 total lines per frame.


It is said setting this register to an odd value on SwanCrystal has an adverse effect to the LCD panel<ref>[http://daifukkat.su/docs/wsman/#REG_LCD_VSYNC REG_LCD_VSYNC - WSMan]</ref>, but the exact mechanism is unknown.
It is said setting this register to an odd value on SwanCrystal has an adverse effect to the LCD panel,<ref>[http://daifukkat.su/docs/wsman/#REG_LCD_VTOTAL REG_LCD_VTOTAL - WSMan]</ref> but the exact mechanism is unknown. A starting point for research is that an even value, or odd total line count, is needed to balance positive and negative charges on the LCD.<ref>W.A. Steer. "[http://www.techmind.org/lcd/ LCD monitor technology and tests]". Techmind, 2011-12-03. Accessed 2024-11-19.</ref>


{{Anchor|LCD Back Porch Line}}
{{Anchor|LCD Back Porch Line}}
=== LCD Back Porch Line ($17, WSC only) ===
=== LCD Back Porch Line ($17, WSC only) ===


Line 369: Line 485:
The vertical back porch of the LCD is assumed to be 4 lines by some hardware, including IPS mods, as well as the official "TV Swan" capture device. Given that the first visible line is sent to the LCD on the display's line 1, this should be generally set to <code>LCD Final Line - 3</code>.
The vertical back porch of the LCD is assumed to be 4 lines by some hardware, including IPS mods, as well as the official "TV Swan" capture device. Given that the first visible line is sent to the LCD on the display's line 1, this should be generally set to <code>LCD Final Line - 3</code>.


Conversely, it is said moving this value closer to vertical blank improves LCD visibility<ref>[http://daifukkat.su/docs/wsman/#REG_LCD_VTOTAL REG_LCD_VTOTAL - WSMan]</ref>, but the exact mechanism is unknown.
Conversely, it is said moving this value closer to vertical blank improves LCD visibility<ref>[http://daifukkat.su/docs/wsman/#REG_LCD_VSYNC REG_LCD_VSYNC - WSMan]</ref>, but the exact mechanism is unknown.


{{Anchor|LCD Status}}
{{Anchor|LCD Status}}
Line 377: Line 493:
7  bit  0
7  bit  0
---- ----
---- ----
...v vv.s
...v vvhs
   | || |
   | ||||
   | || +- LCD sleep: 0 = no, 1 = sleep
   | |||+- LCD sleep: 0 = no, 1 = sleep
  | ||+-- Headphone segment
   | ||
   | ||
   | ||    Volume segments:
   | ||    Volume segments:
   | |+--- Volume B (medium, high)
   | |+--- - Volume B (medium, high)
   | +---- Volume A (low, high)
   | +---- - Volume A (low, high)
   +------ Speaker
   +------ - Speaker
</pre>
</pre>
The LCD sleep bit is writable. The remaining bits are read-only.
The volume and headphone segments are enabled when pressing the SOUND button, according to this algorithm:
* If headphones are plugged in, enable the Headphone segment.
* If headphones are not plugged in, enable the Speaker segment and the following Volume segments:
** Volume level 0: None
** Volume level 1: A
** Volume level 2: B
** Volume level 3: A, B
* Hide all visible segments after 128 frames from the last press.
TODO: This documents the WonderSwan Color. The specifics probably work differently on the mono WonderSwan.


=== TFT LCD Configuration ($70, $71, $72, $73, $74, $75, $76, $77 SwanCrystal only) ===
=== TFT LCD Configuration ($70, $71, $72, $73, $74, $75, $76, $77 SwanCrystal only) ===

Latest revision as of 02:28, 20 November 2024

The WonderSwan's display functionality generally consists of:

  • a 224x144 display clocked at ~75.47 Hz by default, capable of displaying:
    • up to sixteen distinct shades of gray
    • 12-bit RGB444 color(color)
  • two 32x32 background layers ("screens"), capable of displaying up to 512 (1024(color)) distinct tiles,
  • a sprite layer, capable of displaying up to 128 8x8 sprites (up to 32 per line),
  • six LCD icons to the bottom or right of the display, usable as additional indicators.

Components

Tiles

The WonderSwan can display up to 512 distinct tiles at a time, with two bits of palette index information for every pixel.

The WonderSwan Color expands this to 1024 distinct tiles for background (with 512 remaining the limit for sprites), while also introducing modes with four bits of palette index information for every pixel.

2 bits per pixel, planar

The tiles are stored in an interleaved planar format, with two bits total for every pixel. Odd bytes store the first plane (bit 0 of each pixel), while even bytes store the second plane (bit 1 of each pixel).

             tile data (16 bytes)
01 7C 01 FC 00 C0 18 D8 18 D8 00 C0 00 00 C0 00

                      ||
                      \/

 plane 0          plane 1
7  bit  0        7  bit  0            full tile
---- ----        ---- ----
.... ...1 = 01   .222 22.. = 7C       .22222.1
.... ...1 = 01   2222 22.. = FC       222222.1
.... .... = 00   22.. .... = C0       22......
...1 1... = 18   22.2 2... = D8  --\  22.33...
...1 1... = 18   22.2 2... = D8  --/  22.33...
.... .... = 00   22.. .... = C0       22......
.... .... = 00   .... .... = 00       ........
11.. .... = C0   .... .... = 00       11......

This matches the format used by the Game Boy.

4 bits per pixel, planar

This mode is stored in a manner similar to the 2 bits per pixel mode, but with an additional two planes for bit 2 and bit 3 of each pixel's palette index, expanding the tile data to 32 bytes.


                                      tile data (32 bytes)
54 32 01 00 54 32 F1 00 54 32 01 F0 54 32 F1 F0 04 02 01 00 F8 04 02 01 00 F8 04 02 00 00 F8 04

                                               ||
                                               \/

 plane 0          plane 1          plane 2          plane 3
7  bit  0        7  bit  0        7  bit  0        7  bit  0            full tile
---- ----        ---- ----        ---- ----        ---- ----
.1.1 .1.. = 54   ..22 ..2. = 32   .... ...4 = 01   .... .... = 00       .123.124
.1.1 .1.. = 54   ..22 ..2. = 32   4444 ...4 = F1   .... .... = 00       4567.124
.1.1 .1.. = 54   ..22 ..2. = 32   .... ...4 = 01   8888 .... = F0       89AB.124
.1.1 .1.. = 54   ..22 ..2. = 32   4444 ...4 = F1   8888 .... = F0  --\  CDEF.124
.... .1.. = 04   .... ..2. = 02   .... ...4 = 01   .... .... = 00  --/  .....124
1111 1... = F8   .... .2.. = 04   .... ..4. = 02   .... ...8 = 01       11111248
.... .... = 00   2222 2... = F8   .... .4.. = 04   .... ..8. = 02       2222248.
.... .... = 00   .... .... = 00   4444 4... = F8   .... .8.. = 04       444448..

This format matches the one used by the Sega Master System and Game Gear family of consoles.

4 bits per pixel, packed

Unlike the previous two formats, in the packed format each byte stores the complete palette index of two pixels - the high four bits store the left pixel, while the low four bits store the right pixel. Four such bytes make up a row of eight pixels from left to right.

                                      tile data (32 bytes)
01 23 01 24 45 67 01 24 89 AB 01 24 CD EF 01 24 00 00 01 24 11 11 12 48 22 22 24 80 44 44 48 00

                                               ||
                                               \/

 byte     0            1          2          3
 bits  7-4 3-0      7-4 3-0    7-4 3-0    7-4 3-0
 pixel  0   1        2  3       4   5      6   7           full tile
       --- ---      --- ---    --- ---    --- ---
         . 1 = 01     2 3 = 23   . 1 = 01   2 4 = 24       .123.124 = 01 23 01 24
         4 5 = 45     6 7 = 67   . 1 = 01   2 4 = 24       4567.124 = 45 67 01 24
         8 9 = 89     A B = AB   . 1 = 01   2 4 = 24       89AB.124 = 89 AB 01 24
         C D = CD     E F = EF   . 1 = 01   2 4 = 24  --\  CDEF.124 = CD EF 01 24
         . . = 00     . . = 00   . 1 = 01   2 4 = 24  --/  .....124 = 00 00 01 24
         1 1 = 11     1 1 = 11   1 2 = 12   4 8 = 48       11111248 = 11 11 12 48
         2 2 = 22     2 2 = 22   2 4 = 24   8 . = 80       2222248. = 22 22 24 80
         4 4 = 44     4 4 = 44   4 8 = 48   . . = 00       444448.. = 44 44 48 00

This format matches the one used by the Mega Drive console.

Palettes

The display system provides sixteen different palettes that can be used to color or shade tiles.

  • Palettes 0-7 can be used for the two screens only;
  • Palettes 8-15 can be used for both screens and sprites.

Mono

In mono modes, palettes are stored in I/O ports 0x20 through 0x3F. Each palette contains four three-bit entries, which are pointers into a global, four-bit shade lookup table:

      Palette            Global shade LUT
 1  ===========> 2 ==========================> 5
 ^  (0, 2, 4, 6) ^ (1, 3, 5, 7, 9, 11, 13, 15) ^
 |               |                             |
Palette index   Value                         Displayed shade

The shade value corresponds to the darkness of the pixel: shade 0 is the brightest, while shade 15 is the darkest.

Color

In color modes, palettes are stored as 16-bit words in memory addresses 0xFE00 through 0xFFFF, without additional lookup tables:

       Address
15  bit  8  7  bit  0
 ---- ----  ---- ----
 1111 111p  pppi iii.
         |  |||| |||
         |  |||+-+++-- Index in palette (0-15)
         +--+++------- Palette number (0-15)

         Data
15  bit  8  7  bit  0
 ---- ----  ---- ----
 .... rrrr  gggg bbbb
      ||||  |||| ||||
      ||||  |||| ++++- Blue (0-15)
      ||||  ++++------ Green (0-15)
      ++++------------ Red (0-15)

In 2 bits per pixel color modes, palette entries 4 through 15 are not used.

Transparency

In two bit per pixel modes:

  • Palettes 0-3 and 8-11 are opaque. For these, index zero is treated as opaque.
  • Palettes 4-7 and 12-15 are translucent. For these, index zero is treated as transparent. This means that the color/shade value set to it is ignored, and only three distinct colors/shades can be used for tiles.

In four bit per pixel modes, all palettes are translucent. Index zero is always treated as transparent, and fifteen different colors/shades can be used for tiles.

Background color

The background color is displayed if no opaque pixel from screens or sprites is drawn. This color is set in I/O port 0x01:

  • In mono modes, it is set to an entry in the shade lookup table (0-7),
  • In color modes, it is set to an entry in the color palette (0-255). Note that this allows you to use the first color (color zero) of any palette, which is normally ignored and assumed to be transparent.

Screens

A screen is a layout of tiles. Each cell in a screen controls one 8x8 tile.

The display system can show two distinct screens simultaneously. It also supports hardware flipping of tiles, both horizontally and vertically.

The size of each screen is fixed at 32x32 cells or 256x256 pixels, while each cell is stored as a two-byte word:

       Address
15  bit  8  7  bit  0
 ---- ----  ---- ----
 0bbb byyy  yyxx xxx.
  ||| ||||  |||| |||
  ||| ||||  ||++-+++-- X coordinate (0-31)
  ||| |+++--++-------- Y coordinate (0-31)
  +++-+--------------- Base address (from I/O port)

         Data
15  bit  8  7  bit  0
 ---- ----  ---- ----
 vhbp pppt  tttt tttt
 |||| ||||  |||| ||||
 |||| |||+--++++-++++- Tile index (0-511)
 |||+-+++------------- Palette (0-15)
 ||+------------------ Tile bank (0-1) - color only
 |+------------------- Horizontal flip
 +-------------------- Vertical flip

In color modes, the tile bank selects between tiles 0-511 and 512-1023.

Sprites

The display system can show up to 128 sprites at once.

Sprites are always drawn in front of Screen 1, but they can be drawn in front of or behind Screen 2.

Sprites are stored in a sprite table in the console's internal RAM. It consists of up to 128 four-byte entries, of which any sequential slice can be displayed:

 (Byte 1)   (Byte 0)
15  bit  8  7  bit  0
 ---- ----  ---- ----
 vhPi pppt  tttt tttt
 |||| ||||  |||| ||||
 |||| |||+--++++-++++- Tile index (0-511) - only tile bank 0
 |||| +++------------- Palette (0-7) - mapped to screen palettes 8-15
 |||+----------------- Window location - 0 = inside, 1 = outside
 ||+------------------ Priority - 0 = behind Screen 2, 1 = in front of Screen 2
 |+------------------- Horizontal flip
 +-------------------- Vertical flip

 (Byte 2)
 7  bit  0
 ---- ----
 yyyy yyyy
 |||| ||||
 ++++-++++- Y coordinate

 (Byte 3)
 7  bit  0
 ---- ----
 xxxx xxxx
 |||| ||||
 ++++-++++- X coordinate

There is a sprite limit of 32 per scanline. This means that for each scanline, only the first 32 sprites will be drawn. Note that this includes sprites obscured by windows or outside of visible X coordinates; this list is determined solely by the Y coordinate. Between sprites themselves, earlier sprites in the list are always drawn on top of later sprites in the list.

The sprite table is copied from the console's RAM to a SoC-internal buffer every frame on line 144; one word for every clock of the line, totaling 256 words (512 bytes) for 256 clocks. This internal buffer is then used for reading sprite data on the next frame.

Visibility priority

For display components, the visibility priority is as follows:

  • Sprite 0, high priority
  • Sprite 127, high priority
  • Screen 2
  • Sprite 0, low priority
  • Sprite 127, low priority
  • Screen 1
  • Background color

Windows

Screen 2 and sprites can optionally have their drawing restricted within or outside of their specific rectangular windows.

Note that for sprites, the window is enabled globally (for all sprites), but each sprite can individually decide if it's rendered inside or outside of it.

Icons

The WonderSwan features six LCD segment icons which are displayed to the right(color) or below(mono) the main display. These are, as follows:

  • Aux 3 - large circle,
  • Aux 2 - medium circle,
  • Aux 1 - small circle,
  • Horizontal orientation,
  • Vertical orientation,
  • Sleep.

Interrupts

The display circuit generates two interrupts of its own:

  • Display Interrupt Line Match - when Display Current Line == Display Interrupt Line, at the beginning of said line.
  • Display Vertical Blank - when Display Current Line == 144, at the beginning of said line.

It also provides a timing source for the two Horizontal and Vertical Blank Timers, which provide their own respective interrupts.

I/O ports

Display Control ($00)

7  bit  0
---- ----
..wo Ws21
  || ||||
  || |||+- Enable Screen 1 layer
  || ||+-- Enable Screen 2 layer
  || |+--- Enable Sprite layer
  || +---- Enable Sprite window
  |+------ Screen 2 tiles are drawn (if window enabled):
  |        0 = inside window,
  |        1 = outside window.
  +------- Enable Screen 2 window

Display Background Color ($01)

  (mono)             (color)
7  bit  0           7  bit  0
---- ----           ---- ----
.... .sss           pppp iiii
      |||           |||| ||||
      +++- Value    |||| ++++- Index in palette (0-15)
           (0-7)    ++++------ Color palette (0-15)

Display Current Line ($02 read)

The current line being drawn by the display.

Note that lines are sent to the display with a one-line delay. This matters for color palette or shade LUT manipulation; changing these values when current line == 1 will actually affect line 0.

Display Interrupt Line ($03)

The line to emit an interrupt on.

Sprite Table Address ($04)

7  bit  0
---- ----
..Aa aaaa
  || ||||
  |+-++++- Address (bits 9-13)
  +------- Address (bit 14) - color only

Sprite Table First ($05)

7  bit  0
---- ----
.iii iiii
 ||| ||||
 +++-++++- Index of first sprite entry to draw (0-127)

Sprite Table Count ($06)

7  bit  0
---- ----
cccc cccc
|||| ||||
++++-++++- Count of sprite entries to draw (1-128)

Screen Address ($07)

7  bit  0
---- ----
2222 1111
|||| ||||
|||| |+++- Screen 1 address (bits 11-13)
|||| +---- Screen 1 address (bit 14) - color only
|+++------ Screen 2 address (bits 11-13)
+--------- Screen 2 address (bit 14) - color only

Screen 2 Window Left ($08)

Screen 2 Window Top ($09)

Screen 2 Window Right ($0A)

Screen 2 Window Bottom ($0B)

The X and Y coordinates of the Screen 2 window.

Note that all coordinates are inclusive; for example, for a 200x100 window in the top-left corner, the values should be set as follows:

  • Left - 0,
  • Top - 0,
  • Right - 199,
  • Bottom - 99.

Sprite Window Left ($0C)

Sprite Window Top ($0D)

Sprite Window Right ($0E)

Sprite Window Bottom ($0F)

The X and Y coordinates of the Sprite window.

Note that all coordinates are inclusive.

Screen 1 Scroll X ($10)

Screen 1 Scroll Y ($11)

The X and Y coordinates that Screen 1 is scrolled by.

For example, setting Scroll X to 24 and Scroll Y to 8 will omit, in 8x8 tile units, the first three rows and the first two columns of the 32x32 screen.

Screen 2 Scroll X ($12)

Screen 2 Scroll Y ($13)

The X and Y coordinates that Screen 2 is scrolled by.

LCD Control ($14)

7  bit  0
---- ----
.... ..Ce
       ||
       |+- LCD enable: 0 = sleep, 1 = enabled
       +-- Contrast (WSC): 0 = low, 1 = high

The LCD enable bit controls whether or not the LCD screen is displaying graphics; if sleeping, it displays nothing (all white). Note that segments continue displaying regardless of this configuration.

Note that port $1A also provides an LCD sleep bit; the display will be disabled in the same way if any of those bits are set to "sleep".

LCD Icon Control ($15)

7  bit  0
---- ----
..32 1hvs
  || ||||
  || |||+- Sleep
  || ||+-- Vertical orientation
  || |+--- Horizontal orientation
  || +---- Aux 1
  |+------ Aux 2
  +------- Aux 3


LCD Mono Shade LUT ($1C-$1F)

   $1C         $1D         $1E         $1F
7  bit  0   7  bit  0   7  bit  0   7  bit  0
---- ----   ---- ----   ---- ----   ---- ----
1111 0000   3333 2222   5555 4444   7777 6666

LCD Mono Palette 0..15 ($20, $21 .. $3E, $3F)

The monochrome palette is laid out as sixteen words:

    N+1         N
15  bit  8  7  bit  0
 ---- ----  ---- ----
 .333 .222  .111 .000
  |||  |||   |||  |||
  |||  |||   |||  +++- Shade LUT index for color 0
  |||  |||   +++------ Shade LUT index for color 1
  |||  +++------------ Shade LUT index for color 2
  +++----------------- Shade LUT index for color 3

Internal I/O ports

These I/O ports are said to be internal and not intended for use by commercial games.

LCD Final Line ($16)

The final line preceding line counter restart and the beginning of active display. By default, this is set to 158, which equals 159 total lines per frame.

It is said setting this register to an odd value on SwanCrystal has an adverse effect to the LCD panel,[1] but the exact mechanism is unknown. A starting point for research is that an even value, or odd total line count, is needed to balance positive and negative charges on the LCD.[2]

LCD Back Porch Line ($17, WSC only)

This port is available on the WonderSwan Color only - not the SwanCrystal!

The final line preceding the vertical back porch; by default, this should be set to 155.

The vertical back porch of the LCD is assumed to be 4 lines by some hardware, including IPS mods, as well as the official "TV Swan" capture device. Given that the first visible line is sent to the LCD on the display's line 1, this should be generally set to LCD Final Line - 3.

Conversely, it is said moving this value closer to vertical blank improves LCD visibility[3], but the exact mechanism is unknown.

LCD Status ($1A)

7  bit  0
---- ----
...v vvhs
   | ||||
   | |||+- LCD sleep: 0 = no, 1 = sleep
   | ||+-- Headphone segment
   | ||
   | ||    Volume segments:
   | |+--- - Volume B (medium, high)
   | +---- - Volume A (low, high)
   +------ - Speaker

The LCD sleep bit is writable. The remaining bits are read-only.

The volume and headphone segments are enabled when pressing the SOUND button, according to this algorithm:

  • If headphones are plugged in, enable the Headphone segment.
  • If headphones are not plugged in, enable the Speaker segment and the following Volume segments:
    • Volume level 0: None
    • Volume level 1: A
    • Volume level 2: B
    • Volume level 3: A, B
  • Hide all visible segments after 128 frames from the last press.

TODO: This documents the WonderSwan Color. The specifics probably work differently on the mono WonderSwan.

TFT LCD Configuration ($70, $71, $72, $73, $74, $75, $76, $77 SwanCrystal only)

These eight bytes are read from internal EEPROM and configure unknown aspects of the console's TFT LCD panel.

They are only writable while the Boot ROM is unlocked - locking has the side effect of making them read-only.

Notes

  1. REG_LCD_VTOTAL - WSMan
  2. W.A. Steer. "LCD monitor technology and tests". Techmind, 2011-12-03. Accessed 2024-11-19.
  3. REG_LCD_VSYNC - WSMan