Before trying to design homebrew - be it a game, a demo or a tool - for a platform, it is a good idea to be aware of its general features and constraints.
Note that technical documentation is provided as part of the WSdev Wiki - this serves as a high-level overview of the hardware only.
The WonderSwan is a handheld console released by Bandai in March 1999, with an enhanced Color model released in December 2000.
The CPU is an NEC V30MZ CPU, clocked at 3.072 MHz. This CPU is compatible with the Intel 80186, an expanded version of the 16-bit 8086 CPU whose distant grandchildren power PCs to this day. However, note that the CPU has little to do with the older NEC V20/V30 - most of the extensions and quirks specific to that architecture are missing in the V30MZ.
The timing characteristics of the CPU are very different - in a good way! - to those of the early 80s chips. The V30MZ was designed in the 1990s, and features significantly better IPC (instructions per clock) than the original Intel part. Of particular note to prior 8-bit developers is the presence of a reasonably fast 32/16 divider (23-25 cycles), 16/8 divider (16-18 cycles) and 16/16 multiplier (3-4 cycles). Conversely, a prior 8086 developer should note that using look-up tables with the XLAT opcode (5 cycles) can often be slower than some simple operations, such as multiplication or shifting.
Note that while NEC provides their own opcode and register names, the Wonderful toolchain uses the Intel names. As such, you are better off using tutorials and guides targetting the 8086/80186.
While banking is common on many retro consoles, memory segmentation implemented in the 16-bit 8086 architecture is fairly unique - and the WonderSwan does banking *on top* of that. As such, it's a good idea to look at it closer.
The CPU exposes a 20-bit memory bus. This means it's capable of directly addressing 1 megabyte of memory. However, it's also a 16-bit CPU - the instruction pointer, data offsets and other registers are all, at most, sixteen bits in width. How does it address more memory?
The answer is segmentation. In addition to general registers, the CPU provides four *segment* registers:
MOVSB
and STOSW
, use it as an additional data segment.
A segment covers the top 16 bits of the 20-bit address (referred to as a “linear address”); that is, adding 1
to a segment register is equivalent to adding 16
to the address. Therefore, any memory access is done by multiplying the segment value by 16
and adding it to the 16-bit offset: segment * 16 + offset
. For example, if the data segment is set to 0x3108
, while the data offset is set to 0x4240
, the linear address resolved will be 0x352c0
:
This means that programming for the 8086 distinguishes between near
(16-bit, containing only the offset) and far
(32-bit, containing the segment and the offset) pointers.
However, because banking is performed on top of segmentation, a linear address in the cartridge ROM's space may not always point to the same physical location in the ROM! This is further discussed in the Cartridge section below.
As the naming can get confusing, the following convention has been established on this wiki:
The WonderSwan features 16 kilobytes of internal memory. The WonderSwan Color bumps that to a total of 64 kilobytes. The address space is divided so that CPU addresses 0x00000
- 0x0FFFF
point to internal memory, while addresses `0x10000` - 0xFFFFF
are redirected to the cartridge.
Unlike many other 8/16-bit platforms, the WonderSwan has a unified memory architecture - CPU, video and audio data are all stored in the same internal memory at different locations.
The WonderSwan Color also adds general DMA, capable of efficiently copying data from the internal or cartridge memory to the internal memory.
The WonderSwan features a 224×144 display, capable of simultaneously 1) displaying up to 8 out of 16 shades of gray, or 241 out of 4096 colors on the WonderSwan Color through:
Unusually, the display is clocked at 75.47 Hz.
The default mode for tile storage is to use 2-bit-per-pixel data plus one of sixteen palettes to select the shades or colors. The palettes are configured as follows:
The WonderSwan Color augments this with two additional modes, which allow displaying 4-bit-per-pixel tile data, albeit with color “zero” always transparent.
In addition to the display, there are also six user-controlled segments to the right or bottom of the console, which can be used as indicators.
Additional hardware features include:
The WonderSwan features four channels of audio. Each of them is capable of playing 32 x 4-bit wavetable samples with a specified frequency and separate left/right volume control. Some channels, however, have additional modes:
The WonderSwan Color further augments this with:
The WonderSwan features eleven keypad inputs: the two directional diamonds on the left (Y1-Y4, X1-X4), as well as the A, B and Start buttons.
Notably, the arrangement of the directional diamonds allows an alternate layout, where the WonderSwan is held vertically.
The cartridge is capable of anything, depending on the mapper chip. For the purposes of this guide, we're going to discuss the features of the official Bandai mapper chips - the 2001 and 2003.
The Bandai 2001 allows up to 16 megabytes of ROM data, while the 2003 allows up to 64 megabytes. Note that even though the theoretical limit of Bandai's chips is 64 MB, there are no commercial games larger than 16 MB, and no broadly available flash cartridges capable of playing games larger than 8 MB. Caveat emptor.
Memory banking is provided by splitting the cartridge's part of the linear address space into four areas:
0x10000
- 0x1FFFF
- SRAM0x20000
- 0x2FFFF
- ROM, bank 00x30000
- 0x3FFFF
- ROM, bank 10x40000
- 0xFFFFF
- ROM, “linear” bank 2Banks 0 and 1 can be moved at runtime, as to point to any 64KB part of the ROM. Conversely, bank 2 can point to any 1 MB part of the ROM, but only its top 2) 768 KB is exposed.
Let's look at a more practical example. Suppose that bank 0
is set to point to the 0x680000
- 0x68FFFF
portion of the ROM's address space (“physical address”); as with the previous example in the Segmentation section, the data segment is set to `0x3108`, while the data offset is set to `0x4240`:
Optionally, a cartridge can provide:
Additional hardware features include: