26#define PICO9918_LINKAGE extern "C"
28#define PICO9918_LINKAGE extern
32#include <emscripten.h>
33#define PICO9918_DLLEXPORT EMSCRIPTEN_KEEPALIVE PICO9918_LINKAGE
34#define PICO9918_DLLEXPORT_CONST PICO9918_LINKAGE
35#elif PICO9918_COMPILING_DLL
36#define PICO9918_DLLEXPORT PICO9918_LINKAGE __declspec(dllexport)
37#elif defined WIN32 && !defined PICO9918_STATIC
38#define PICO9918_DLLEXPORT PICO9918_LINKAGE __declspec(dllimport)
41#define PICO9918_DLLEXPORT PICO9918_LINKAGE
44#ifndef PICO9918_DLLEXPORT_CONST
45#define PICO9918_DLLEXPORT_CONST PICO9918_DLLEXPORT
48#include "pico9918_build_config.h"
55#ifndef PICO9918_SINGLE_INSTANCE
56#define PICO9918_SINGLE_INSTANCE PICO9918_BUILD_SINGLE_INSTANCE
57#elif (PICO9918_SINGLE_INSTANCE != 0) != (PICO9918_BUILD_SINGLE_INSTANCE != 0)
58#error "PICO9918_SINGLE_INSTANCE disagrees with the archive - drop it and let pico9918_build_config.h supply it"
65#if PICO9918_SINGLE_INSTANCE
66#define PICO9918_INST_ARG
67#define PICO9918_INST_ONLY_ARG void
69#define PICO9918_INST_ONLY
71#define PICO9918_INST_ARG pico9918_t *tms9918,
72#define PICO9918_INST_ONLY_ARG pico9918_t* tms9918
73#define PICO9918_INST tms9918,
74#define PICO9918_INST_ONLY tms9918
96typedef void (*pico9918_config_applied_fn)(pico9918_t* tms9918,
void* userdata);
97typedef void (*pico9918_config_reload_fn)(pico9918_t* tms9918,
void* userdata);
98typedef void (*pico9918_gpu_flash_fn)(pico9918_t* tms9918,
void* userdata);
99typedef void (*pico9918_gpu_config_save_fn)(pico9918_t* tms9918, uint8_t* config, uint8_t key,
106 TMS_MODE_GRAPHICS_II,
110#ifdef PICO9918_V9938_BASE
120#if PICO9918_BUILD_RUNTIME_CHIP
167#if PICO9918_BUILD_TEXT80_8BPP
168#define PICO9918_CHIP_MAX PICO9918_CHIP_PICO9918_PRO
170#define PICO9918_CHIP_MAX PICO9918_CHIP_PICO9918
208 TMS_REG_NAME_TABLE = TMS_REG_2,
209 TMS_REG_COLOR_TABLE = TMS_REG_3,
210 TMS_REG_PATTERN_TABLE = TMS_REG_4,
211 TMS_REG_SPRITE_ATTR_TABLE = TMS_REG_5,
212 TMS_REG_SPRITE_PATT_TABLE = TMS_REG_6,
213 TMS_REG_FG_BG_COLOR = TMS_REG_7,
275#define PICO9918_SR0_INT 0x80
276#define PICO9918_SR0_5S 0x40
277#define PICO9918_SR0_COLLISION 0x20
278#define PICO9918_SR0_SPRITE_NUM 0x1f
281#define PICO9918_SR1_HF 0x01
282#define PICO9918_SR1_BLANK 0x02
286#define TMS_R0_MODE_GRAPHICS_I 0x00
287#define TMS_R0_MODE_GRAPHICS_II 0x02
288#define TMS_R0_MODE_MULTICOLOR 0x00
289#define TMS_R0_MODE_TEXT 0x00
290#define TMS_R0_MODE_TEXT_80 0x04
291#define TMS_R0_EXT_VDP_ENABLE 0x01
292#define TMS_R0_EXT_VDP_DISABLE 0x00
293#define TMS_R0_DOUBLE_ROWS 0x08
294#define TMS_R0_INT_SCANLINE 0x10
297#define TMS_R1_RAM_16K 0x80
298#define TMS_R1_RAM_4K 0x00
299#define TMS_R1_DISP_BLANK 0x00
300#define TMS_R1_DISP_ACTIVE 0x40
301#define TMS_R1_INT_ENABLE 0x20
302#define TMS_R1_INT_DISABLE 0x00
303#define TMS_R1_MODE_GRAPHICS_I 0x00
304#define TMS_R1_MODE_GRAPHICS_II 0x00
305#define TMS_R1_MODE_MULTICOLOR 0x08
306#define TMS_R1_MODE_TEXT 0x10
307#define TMS_R1_SPRITE_8 0x00
308#define TMS_R1_SPRITE_16 0x02
309#define TMS_R1_SPRITE_MAG1 0x00
310#define TMS_R1_SPRITE_MAG2 0x01
316#define PICO9918_R24_SPRITE_PS 0x30
317#define PICO9918_R24_TILE_PS 0x0f
318#define PICO9918_R24_TILE2_PS 0x0c
319#define PICO9918_R24_TILE1_PS 0x03
322#define PICO9918_R29_SPRITE_STRIDE 0xc0
323#define PICO9918_R29_PAGE2_HORZ 0x20
324#define PICO9918_R29_PAGE2_VERT 0x10
325#define PICO9918_R29_TILE_STRIDE 0x0c
326#define PICO9918_R29_PAGE1_HORZ 0x02
327#define PICO9918_R29_PAGE1_VERT 0x01
330#define PICO9918_R31_BML_ENABLE 0x80
331#define PICO9918_R31_BML_PRIORITY 0x40
332#define PICO9918_R31_BML_TRANSP 0x20
333#define PICO9918_R31_BML_FAT 0x10
334#define PICO9918_R31_BML_PS 0x0f
337#define PICO9918_R47_DATA_PORT 0x80
338#define PICO9918_R47_AUTO_INC 0x40
339#define PICO9918_R47_INDEX 0x3f
342#define PICO9918_R49_TILE2_ENABLE 0x80
343#define PICO9918_R49_ROW30 0x40
344#define PICO9918_R49_ECM_TILE 0x30
345#define PICO9918_R49_ECM_TILE_1 0x10
346#define PICO9918_R49_ECM_TILE_2 0x20
347#define PICO9918_R49_ECM_TILE_3 0x30
348#define PICO9918_R49_Y_REAL 0x08
349#define PICO9918_R49_ECM_SPRITE 0x03
350#define PICO9918_R49_ECM_SPRITE_1 0x01
351#define PICO9918_R49_ECM_SPRITE_2 0x02
352#define PICO9918_R49_ECM_SPRITE_3 0x03
355#define PICO9918_R50_RESET 0x80
356#define PICO9918_R50_GPU_HSYNC 0x40
357#define PICO9918_R50_GPU_VSYNC 0x20
358#define PICO9918_R50_TILE1_OFF 0x10
359#define PICO9918_R50_REPORT_MAX 0x08
360#define PICO9918_R50_VSCANLINES 0x04
361#define PICO9918_R50_POS_ATTR 0x02
362#define PICO9918_R50_T2_PRIORITY 0x01
365#define PICO9918_R56_GPU_RUN 0x01
368#define PICO9918_R57_UNLOCK 0x1c
371#define PICO9918_R15_COUNTER_RESET 0x40
372#define PICO9918_R15_COUNTER_SNAP 0x20
373#define PICO9918_R15_COUNTER_EN 0x10
374#define PICO9918_R15_STATUS_NUM 0x0f
376#define TMS9918_PIXELS_X 256
377#define TMS9918_PIXELS_Y 384
383#if PICO9918_SINGLE_INSTANCE
387void pico9918_init(
void);
414#if PICO9918_BUILD_RUNTIME_CHIP
508#define PICO9918_SCANLINE_BYTES_MAX \
509 (PICO9918_BUILD_TEXT80_8BPP ? TMS9918_PIXELS_X * 2 : TMS9918_PIXELS_X)
517#define PICO9918_SCANLINE_BUFFER_SIZE (PICO9918_SCANLINE_BYTES_MAX + 8)
uint8_t pico9918_peek_status(pico9918_t *tms9918)
read from the status register without resetting it
pico9918_color_t
the sixteen TMS9918 colours, in palette-index order
pico9918_t * pico9918_new(void)
create a new TMS9918
uint8_t pico9918_read_data(pico9918_t *tms9918)
read data (mode = 0) from the tms9918
pico9918_mode_t pico9918_display_mode(pico9918_t *tms9918)
the current display mode
bool pico9918_display_enabled(pico9918_t *tms9918)
check the BLANK flag
void pico9918_destroy(pico9918_t *tms9918)
destroy a TMS9918 and release everything it owns
void pico9918_write_addr(pico9918_t *tms9918, uint8_t data)
write an address (mode = 1) to the tms9918 - the data byte DB0 -> DB7
void pico9918_set_chip(pico9918_t *tms9918, pico9918_chip_t chip)
select which chip this instance answers as
const uint8_t * pico9918_line_source(pico9918_t *tms9918)
where the scanline just generated actually is - the arbitration buffer, or a tile layer's own buffer ...
uint8_t pico9918_read_data_no_inc(pico9918_t *tms9918)
read data (mode = 0) without incrementing the address pointer
#define PICO9918_INST_ARG
declare the instance ahead of other parameters
uint8_t pico9918_status_value(pico9918_t *tms9918, pico9918_status_register_t reg)
return a status register value, without the side effects of reading it
pico9918_chip_t pico9918_chip(pico9918_t *tms9918)
which chip this instance answers as
uint8_t pico9918_vram_value(pico9918_t *tms9918, uint16_t addr)
return a value from vram
void pico9918_interrupt_set(pico9918_t *tms9918)
set the interrupt flag
uint32_t pico9918_line_bytes(pico9918_t *tms9918)
how many bytes of the line the current mode fills: 256, or 512 for unlocked 80-column text on a board...
void pico9918_set_status(pico9918_t *tms9918, uint8_t status)
set the status flags
uint8_t pico9918_scan_line(pico9918_t *tms9918, uint16_t y)
generate a scanline
pico9918_register_t
the eight TMS9918 registers, by number and by what each one holds
@ PICO9918_REG_COLOR_TABLE2
tile layer 2 colour table base
@ PICO9918_REG_CONFIG_INDEX
PICO9918 only: which configuration byte R59 addresses.
@ PICO9918_REG_BML_X
bitmap layer left edge
@ PICO9918_REG_BML_BASE
bitmap layer base address, in 64-byte units
@ PICO9918_REG_VRAM_INC
signed VRAM address increment per access
@ PICO9918_REG_CONFIG_VALUE
PICO9918 only: the configuration byte R58 selected.
@ PICO9918_REG_NAME_TABLE2
tile layer 2 name table base
@ PICO9918_REG_ENHANCED1
tile layer 2, 30-row mode, ECM levels, real Y
@ PICO9918_REG_T1_VSCROLL
tile layer 1 vertical scroll
@ PICO9918_REG_GPU_PC_MSB
GPU program counter, high byte.
@ PICO9918_REG_STATUS_SELECT
which status register S1 reads back, and the counter controls
@ PICO9918_REG_ENHANCED2
GPU triggers, per-position attributes, layer priority.
@ PICO9918_REG_T2_HSCROLL
tile layer 2 horizontal scroll
@ PICO9918_REG_T2_VSCROLL
tile layer 2 vertical scroll
@ PICO9918_REG_PAGE_SIZE
scroll page sizes, and the ECM pattern plane stride
@ PICO9918_REG_UNLOCK
0x1c twice unlocks the F18A personality; any other value locks
@ PICO9918_REG_BML_WIDTH
bitmap layer width in pixels
@ PICO9918_REG_MAX_SCAN_SPRITES
sprites drawn per scanline before the limit bites
@ PICO9918_REG_HORZ_INT_LINE
scanline the horizontal interrupt fires on
@ PICO9918_REG_GPU_PC_LSB
GPU program counter, low byte - writing it also starts the GPU.
@ PICO9918_REG_BML_TOP_ROW
bitmap layer top row
@ PICO9918_REG_MAX_SPRITES
sprites processed per frame before the scan stops
@ PICO9918_REG_PALETTE_SELECT
sub-palette for sprites and each tile layer
@ PICO9918_REG_BML_CONTROL
bitmap layer enable, priority, transparency, fat pixels
@ PICO9918_REG_T1_HSCROLL
tile layer 1 horizontal scroll
@ PICO9918_REG_GPU_CONTROL
GPU load and trigger.
@ PICO9918_REG_FLASH_CONTROL
PICO9918 only: flash operation control.
@ PICO9918_REG_BML_HEIGHT
bitmap layer height in rows
@ PICO9918_REG_PALETTE_CONTROL
palette data port mode, auto-increment and index
pico9918_status_register_t
the status registers, by number and by what each one reports
@ PICO9918_SR_STATUS
the TMS9918A status: interrupt, 5th sprite, collision, sprite number
@ PICO9918_SR_MICROS_LSB
microsecond counter, low byte
@ PICO9918_SR_CONFIG_VALUE
PICO9918 only: the configuration byte R58 selected.
@ PICO9918_SR_REG_VALUE
the register value latched when the VRAM address was set
@ PICO9918_SR_MILLIS_LSB
millisecond counter, low byte
@ PICO9918_SR_NANOS_MSB
nanosecond counter, high bits.
@ PICO9918_SR_NANOS_LSB
nanosecond counter, low byte.
@ PICO9918_SR_SECONDS_LSB
second counter, low byte
@ PICO9918_SR_RASTER_LINE
the line currently being drawn
@ PICO9918_SR_MICROS_MSB
microsecond counter, high bits
@ PICO9918_SR_IDENT
chip identity, blanking, and the scanline interrupt flag
@ PICO9918_SR_TEMPERATURE
PICO9918 only: core temperature, as degrees C times four.
@ PICO9918_SR_MILLIS_MSB
millisecond counter, high bits
@ PICO9918_SR_VERSION
the F18A feature level, as major and minor nibbles
@ PICO9918_SR_SECONDS_MSB
second counter, high byte
@ PICO9918_SR_GPU
GPU running and its status byte.
void pico9918_reset(pico9918_t *tms9918)
reset the TMS9918
#define PICO9918_INST_ONLY_ARG
declare the instance as the only parameter
uint8_t pico9918_read_status(pico9918_t *tms9918)
read from the status register
uint16_t pico9918_default_palette(int index)
a default palette value, 0x0rgb
bool pico9918_interrupt_status(pico9918_t *tms9918)
true if both the INT status and the INT control bit are set
pico9918_chip_t
which chip an instance answers as
@ PICO9918_CHIP_PICO9918
an F18A plus the PICO9918's own extensions
@ PICO9918_CHIP_TMS9918
a pre-A TMS9918: a TMS9918A without Graphics II
@ PICO9918_CHIP_PICO9918_PRO
a PICO9918 PRO: 8bpp 80-column text, its own splash
@ PICO9918_CHIP_TMS9918A
a TMS9918A: locked, no GPU, no extensions
@ PICO9918_CHIP_F18A
an F18A: unlock, enhanced renderer, GPU
uint8_t pico9918_reg_value(pico9918_t *tms9918, pico9918_register_t reg)
return a register value
#define PICO9918_DLLEXPORT
the linkage every public entry point carries - see LINKAGE MODES above
void pico9918_write_data(pico9918_t *tms9918, uint8_t data)
write data (mode = 0) to the tms9918 - the data byte DB0 -> DB7
pico9918_mode_t
the display modes the VDP can be in, TMS9918A modes and F18A alike