### Initialize and Configure TMS9918 Emulator Source: https://github.com/visrealm/vremutms9918/blob/main/README.md Demonstrates the basic setup of the TMS9918 emulator, including setting VRAM addresses and display modes. This is a starting point for interacting with the VDP. ```c #include "vrEmuTms9918.h" #include "vrEmuTms9918Util.h" #define TMS_VRAM_NAME_ADDRESS 0x3800 #define TMS_VRAM_COLOR_ADDRESS 0x0000 #define TMS_VRAM_PATT_ADDRESS 0x2000 #define TMS_VRAM_SPRITE_ATTR_ADDRESS 0x3B00 #define TMS_VRAM_SPRITE_PATT_ADDRESS 0x1800 // program entry point int main() { // create a new tms9918 VrEmuTms9918 *tms9918 = vrEmuTms9918New(); // Here, we're using the helper functions provided by vrEmuTms9918Util.h // // In a full system emulator, the only functions required (connected to the system bus) would be: // // * vrEmuTms9918WriteAddr() // * vrEmuTms9918WriteData() // * vrEmuTms9918ReadStatus() // * vrEmuTms9918ReadData() // // The helper functions below wrap the above functions and are not required. // vrEmuTms9918Util.h/c can be omitted if you're not using them. // // For a full example, see https://github.com/visrealm/hbc-56/blob/master/emulator/src/devices/tms9918_device.c // set up the VDP write-only registers vrEmuTms9918WriteRegisterValue(tms9918, TMS_REG_0, TMS_R0_MODE_GRAPHICS_I); vrEmuTms9918WriteRegisterValue(tms9918, TMS_REG_1, TMS_R1_MODE_GRAPHICS_I | TMS_R1_RAM_16K); vrEmuTms9918SetNameTableAddr(tms9918, TMS_VRAM_NAME_ADDRESS); vrEmuTms9918SetColorTableAddr(tms9918, TMS_VRAM_COLOR_ADDRESS); vrEmuTms9918SetPatternTableAddr(tms9918, TMS_VRAM_PATT_ADDRESS); vrEmuTms9918SetSpriteAttrTableAddr(tms9918, TMS_VRAM_SPRITE_ATTR_ADDRESS); vrEmuTms9918SetSpritePattTableAddr(tms9918, TMS_VRAM_SPRITE_PATT_ADDRESS); vrEmuTms9918SetFgBgColor(tms9918, TMS_BLACK, TMS_CYAN); // send it some data (a pattern) vrEmuTms9918SetAddressWrite(tms9918, TMS_VRAM_PATT_ADDRESS); // update pattern #0 char smile[] = {0b00111100, 0b01000010, 0b10000001, 0b10100101, 0b10000001, 0b10011001, 0b01000010, 0b00111100}; vrEmuTms9918WriteBytes(tms9918, smile, sizeof(smile)); // update fg/bg color for first 8 characters vrEmuTms9918SetAddressWrite(tms9918, TMS_VRAM_COLOR_ADDRESS) vrEmuTms9918WriteData(tms9918, vrEmuTms9918FgBgColor(TMS_BLACK, TMS_LT_YELLOW)); // output smile pattern to screen vrEmuTms9918SetAddressWrite(tms9918, TMS_VRAM_NAME_ADDRESS); // a few smiles vrEmuTms9918WriteData(tms9918, 0x00); vrEmuTms9918WriteData(tms9918, 0x00); vrEmuTms9918WriteData(tms9918, 0x00); // render the display char scanline[TMS9918A_PIXELS_X]; // scanline buffer // an example output (a framebuffer for an SDL texture) uint32_t frameBuffer[TMS9918A_PIXELS_X * TMS9918A_PIXELS_Y]; // generate all scanlines and render to framebuffer uint32_t *pixPtr = frameBuffer; for (int y = 0; y < TMS9918A_PIXELS_Y; ++y) { // get the scanline pixels vrEmuTms9918ScanLine(tms9918, y, scanline); for (int x = 0; x < TMS9918A_PIXELS_X; ++x) { // values returned from vrEmuTms9918ScanLine() are palette indexes // use the vrEmuTms9918Palette array to convert to an RGBA value *pixPtr++ = vrEmuTms9918Palette[scanline[x]]; } } // output the buffer... ... // clean up vrEmuTms9918Destroy(tms9918); tms9918 = NULL; return 0; } ``` -------------------------------- ### Setup Build Directory Source: https://github.com/visrealm/vremutms9918/blob/main/README.md Create a build directory and navigate into it to prepare for the CMake configuration. ```bash mkdir build cd build cmake .. ``` -------------------------------- ### vrEmuTms9918InitialiseGfxI / vrEmuTms9918InitialiseGfxII Source: https://context7.com/visrealm/vremutms9918/llms.txt These functions provide a one-call setup for initializing the VDP for Graphics I or Graphics II modes. They set all necessary registers, configure default table addresses, clear VRAM, and for Graphics II, fill the name table with sequential tile indices. ```APIDOC ### `vrEmuTms9918InitialiseGfxI` / `vrEmuTms9918InitialiseGfxII` — One-call mode setup Fully initializes the VDP for Graphics I or Graphics II mode: sets all registers, configures default table addresses, clears VRAM, and (for Graphics II) fills the name table with sequential tile indices. ```c #include "vrEmuTms9918Util.h" VrEmuTms9918 *tms = vrEmuTms9918New(); /* Graphics I — general-purpose tiled display with sprites */ vrEmuTms9918InitialiseGfxI(tms); /* ---or --- /* Graphics II — full-screen bitmap with per-cell color control */ vrEmuTms9918InitialiseGfxII(tms); /* Both calls leave tms ready to render immediately */ uint8_t scanline[TMS9918_PIXELS_X]; vrEmuTms9918ScanLine(tms, 0, scanline); ``` ``` -------------------------------- ### Initialize VDP for Graphics I or Graphics II mode Source: https://context7.com/visrealm/vremutms9918/llms.txt One-call setup functions for initializing the VDP. They set all registers, configure default table addresses, clear VRAM, and optionally fill the name table for Graphics II. Both functions prepare the VDP for immediate rendering. ```c #include "vrEmuTms9918Util.h" VrEmuTms9918 *tms = vrEmuTms9918New(); /* Graphics I — general-purpose tiled display with sprites */ vrEmuTms9918InitialiseGfxI(tms); /* --- or --- */ /* Graphics II — full-screen bitmap with per-cell color control */ vrEmuTms9918InitialiseGfxII(tms); /* Both calls leave tms ready to render immediately */ uint8_t scanline[TMS9918_PIXELS_X]; vrEmuTms9918ScanLine(tms, 0, scanline); ``` -------------------------------- ### Query VDP display status and mode Source: https://context7.com/visrealm/vremutms9918/llms.txt Use `vrEmuTms9918DisplayEnabled` to check if the display is active (BLANK flag) and `vrEmuTms9918DisplayMode` to get the current VDP mode. ```c if (vrEmuTms9918DisplayEnabled(tms)) { switch (vrEmuTms9918DisplayMode(tms)) { case TMS_MODE_GRAPHICS_I: puts("Graphics I"); break; case TMS_MODE_GRAPHICS_II: puts("Graphics II"); break; case TMS_MODE_TEXT: puts("Text"); break; case TMS_MODE_MULTICOLOR: puts("Multicolor"); break; } } ``` -------------------------------- ### Bulk VRAM write from byte array Source: https://context7.com/visrealm/vremutms9918/llms.txt The `vrEmuTms9918WriteBytes` function efficiently writes multiple bytes from a buffer to VRAM starting at the current address pointer. The address pointer is auto-incremented after each byte. ```c static const uint8_t checkerboard[8] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }; vrEmuTms9918SetAddressWrite(tms, 0x2008); /* pattern slot 1 */ vrEmuTms9918WriteBytes(tms, checkerboard, sizeof(checkerboard)); ``` -------------------------------- ### `vrEmuTms9918WriteBytes` — Bulk VRAM write from a byte array Source: https://context7.com/visrealm/vremutms9918/llms.txt Writes a specified number of bytes from a byte array into VRAM starting at the current address pointer. The address pointer is automatically incremented after each byte is written. ```APIDOC ## `vrEmuTms9918WriteBytes` — Bulk VRAM write from a byte array ### Description Writes a specified number of bytes from a byte array into VRAM starting at the current address pointer. The address pointer is automatically incremented after each byte is written. ### Method ```c static const uint8_t checkerboard[8] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }; vxEmuTms9918SetAddressWrite(tms, 0x2008); /* pattern slot 1 */ vxEmuTms9918WriteBytes(tms, checkerboard, sizeof(checkerboard)); ``` ``` -------------------------------- ### `vrEmuTms9918WriteString` / `vrEmuTms9918WriteStringOffset` — Write ASCII text to VRAM Source: https://context7.com/visrealm/vremutms9918/llms.txt Writes a C string to VRAM as a sequence of byte values. `vrEmuTms9918WriteStringOffset` allows for an offset to be added to each character's value, useful for fonts not starting at ASCII 0. ```APIDOC ## `vrEmuTms9918WriteString` / `vrEmuTms9918WriteStringOffset` — Write ASCII text to VRAM ### Description Writes a C string to VRAM as a sequence of byte values. `vrEmuTms9918WriteStringOffset` allows for an offset to be added to each character's value, useful for fonts not starting at ASCII 0. ### Method ```c /* Write "HELLO" to name table starting at row 0, col 0 */ vxEmuTms9918SetAddressWrite(tms, 0x3800); vxEmuTms9918WriteString(tms, "HELLO"); /* Write "WORLD" with offset 32 (e.g., font mapped from pattern 32 upward) */ vxEmuTms9918SetAddressWrite(tms, 0x3820); vxEmuTms9918WriteStringOffset(tms, "WORLD", 32); ``` ``` -------------------------------- ### Build vrEmuTms9918 Source: https://github.com/visrealm/vremutms9918/blob/main/README.md Execute this command to compile the emulator after setting up the build environment. ```bash cmake --build . ``` -------------------------------- ### Run Tests Source: https://github.com/visrealm/vremutms9918/blob/main/README.md Execute this command to run the test suite for the emulator. ```bash ctest ``` -------------------------------- ### Create a new TMS9918 emulator instance Source: https://context7.com/visrealm/vremutms9918/llms.txt Allocates and initializes a new VrEmuTms9918 object. Must be called before any other function. Returns a pointer to the opaque emulator state; ownership belongs to the caller and must be released with vrEmuTms9918Destroy. ```c #include "vrEmuTms9918.h" int main(void) { VrEmuTms9918 *tms = vrEmuTms9918New(); if (!tms) { fprintf(stderr, "Failed to create TMS9918 instance\n"); return 1; } /* ... use tms ... */ vrEmuTms9918Destroy(tms); return 0; } ``` -------------------------------- ### vrEmuTms9918New Source: https://context7.com/visrealm/vremutms9918/llms.txt Allocates and initializes a new TMS9918 emulator instance. This function must be called before any other emulator functions. It returns a pointer to the emulator's state, which should be managed and eventually freed by the caller. ```APIDOC ## vrEmuTms9918New ### Description Allocates and initializes a new `VrEmuTms9918` object. Must be called before any other function. Returns a pointer to the opaque emulator state; ownership belongs to the caller and must be released with `vrEmuTms9918Destroy`. ### Method `VrEmuTms9918 *vrEmuTms9918New(void);` ### Returns - `VrEmuTms9918 *`: A pointer to the newly created emulator instance, or `NULL` if allocation fails. ### Example ```c #include "vrEmuTms9918.h" int main(void) { VrEmuTms9918 *tms = vrEmuTms9918New(); if (!tms) { fprintf(stderr, "Failed to create TMS9918 instance\n"); return 1; } /* ... use tms ... */ vrEmuTms9918Destroy(tms); return 0; } ``` ``` -------------------------------- ### Clone vrEmuTms9918 Repository Source: https://github.com/visrealm/vremutms9918/blob/main/README.md Use this command to download the source code of the emulator. ```bash git clone https://github.com/visrealm/vrEmuTms9918.git cd vrEmuTms9918 ``` -------------------------------- ### Set Interface Include Directories Source: https://github.com/visrealm/vremutms9918/blob/main/src/CMakeLists.txt Configures the include directories for the vrEmuTms9918 library. This ensures that header files are found during compilation. ```cmake target_include_directories (vrEmuTms9918 INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) ``` -------------------------------- ### Add vrEmuTms9918 Library Source: https://github.com/visrealm/vremutms9918/blob/main/src/CMakeLists.txt Defines a static library for the vrEmuTms9918 module. This is a fundamental step in building the project. ```cmake add_library(vrEmuTms9918 vrEmuTms9918.c) ``` -------------------------------- ### Add vrEmuTms9918Util Library Source: https://github.com/visrealm/vremutms9918/blob/main/src/CMakeLists.txt Defines a static library for utility functions related to vrEmuTms9918. This library depends on the main vrEmuTms9918 library. ```cmake add_library(vrEmuTms9918Util vrEmuTms9918Util.c) ``` -------------------------------- ### Pack foreground and background colors into one byte Source: https://context7.com/visrealm/vremutms9918/llms.txt Combines foreground and background color values into a single byte. The high nibble represents the foreground color and the low nibble represents the background color. This packed byte is used for the color table or REG7. ```c /* Dark red on cyan */ uint8_t colorByte = vrEmuTms9918FgBgColor(TMS_DK_RED, TMS_CYAN); /* colorByte = 0x67 */ vrEmuTms9918SetAddressWrite(tms, 0x0000); /* color table */ vrEmuTms9918WriteData(tms, colorByte); ``` -------------------------------- ### Table address helpers Source: https://context7.com/visrealm/vremutms9918/llms.txt A set of six inline functions used to configure the six VDP table registers (name, color, pattern, sprite attribute, sprite pattern, fg/bg). Each function takes a 16-bit VRAM address and encodes it into the appropriate register value. ```APIDOC ### Table address helpers — Set VRAM table locations Six inline functions configure the six VDP table registers (name, color, pattern, sprite attribute, sprite pattern, fg/bg). Each accepts a raw 16-bit VRAM address and encodes the appropriate register value. ```c /* Standard Graphics I layout */ vrEmuTms9918SetNameTableAddr (tms, 0x3800); vrEmuTms9918SetColorTableAddr (tms, 0x0000); vrEmuTms9918SetPatternTableAddr (tms, 0x2000); vrEmuTms9918SetSpriteAttrTableAddr(tms, 0x3B00); vrEmuTms9918SetSpritePattTableAddr(tms, 0x1800); ``` ``` -------------------------------- ### Render a single scanline with vrEmuTms9918ScanLine Source: https://context7.com/visrealm/vremutms9918/llms.txt The `vrEmuTms9918ScanLine` function renders a single scanline into a provided buffer. Call this for each scanline to generate a full frame. Ensure `vrEmuTms9918Palette` is populated with color data. ```c #include "vrEmuTms9918.h" #define W TMS9918_PIXELS_X /* 256 */ #define H TMS9918_PIXELS_Y /* 192 */ uint32_t framebuffer[W * H]; uint8_t scanline[W]; for (int y = 0; y < H; ++y) { vrEmuTms9918ScanLine(tms, (uint8_t)y, scanline); for (int x = 0; x < W; ++x) { /* vrEmuTms9918Palette entries are 0xRRGGBBAA */ framebuffer[y * W + x] = vrEmuTms9918Palette[scanline[x]]; } } /* framebuffer now contains the full RGBA frame */ ``` -------------------------------- ### Python Tms9918 class for VRAM and screen manipulation Source: https://context7.com/visrealm/vremutms9918/llms.txt A high-level Python interface using pybind11 that wraps the C library. It allows setting registers, VRAM, and retrieving the screen buffer as a flat list of RGB bytes. ```python from tms9918 import Tms9918 from PIL import Image # Load a raw TMS9918 state dump (16 KB VRAM + 8 register bytes) with open("image.bin", "rb") as f: data = f.read() vram = list(data[:16 * 1024]) # first 16 384 bytes = VRAM regs = list(data[16 * 1024:]) # remaining bytes = register values tms = Tms9918() tms.setRegs(regs) # write all 8 registers at once tms.setVram(0, vram) # bulk-write VRAM starting at address 0 # getScreen() returns flat RGB bytes: [R0,G0,B0, R1,G1,B1, ...] screen = tms.getScreen() img = Image.frombytes('RGB', (256, 192), bytes(screen)) img.show() # Expected: renders the TMS9918 screen captured in image.bin ``` -------------------------------- ### vrEmuTms9918ReadData Source: https://context7.com/visrealm/vremutms9918/llms.txt Simulates reading a data byte from VRAM (CSR, MODE=0). The emulator increments the VRAM address pointer after each read, consistent with the real hardware. ```APIDOC ## vrEmuTms9918ReadData ### Description Reads one byte from the current VRAM address and auto-increments the pointer. ### Method `uint8_t vrEmuTms9918ReadData(VrEmuTms9918 *tms); ` ### Parameters - **tms** (`VrEmuTms9918 *`): Pointer to the TMS9918 emulator instance. ### Returns - `uint8_t`: The data byte read from VRAM. ### Example ```c /* Read back 8 bytes from pattern table address 0x2000 */ vrEmuTms9918WriteAddr(tms, 0x00); vrEmuTms9918WriteAddr(tms, 0x20); /* read mode (no 0x40 flag) */ for (int i = 0; i < 8; ++i) { uint8_t byte = vrEmuTms9918ReadData(tms); printf("Pattern byte %d: 0x%02X\n", i, byte); } ``` ``` -------------------------------- ### vrEmuTms9918FgBgColor Source: https://context7.com/visrealm/vremutms9918/llms.txt Packs foreground and background colors into a single byte. The high nibble represents the foreground color and the low nibble represents the background color. This is useful for setting colors in the color table or the REG7 register. ```APIDOC ## `vrEmuTms9918FgBgColor` — Pack foreground and background colors into one byte Returns a single byte with foreground in the high nibble and background in the low nibble, for use with the color table or REG7. ```c /* Dark red on cyan */ uint8_t colorByte = vrEmuTms9918FgBgColor(TMS_DK_RED, TMS_CYAN); /* colorByte = 0x67 */ vrEmuTms9918SetAddressWrite(tms, 0x0000); /* color table */ vrEmuTms9918WriteData(tms, colorByte); ``` ``` -------------------------------- ### Write data to VRAM (CSW, MODE=0) Source: https://context7.com/visrealm/vremutms9918/llms.txt Writes a single byte to the current VRAM address and auto-increments the internal address pointer, exactly as on real hardware. ```c /* Write the byte pattern for a smiley face into pattern slot 0 */ static const uint8_t smile[8] = { 0b00111100, 0b01000010, 0b10000001, 0b10100101, 0b10000001, 0b10011001, 0b01000010, 0b00111100 }; /* Set write address to start of pattern table */ vrEmuTms9918WriteAddr(tms, 0x00); vrEmuTms9918WriteAddr(tms, 0x40 | 0x20); /* 0x2000 in write mode */ for (int i = 0; i < 8; ++i) vrEmuTms9918WriteData(tms, smile[i]); ``` -------------------------------- ### Configure VDP table registers Source: https://context7.com/visrealm/vremutms9918/llms.txt Inline functions to configure the six VDP table registers (name, color, pattern, sprite attribute, sprite pattern, fg/bg). Each function accepts a raw 16-bit VRAM address and encodes the appropriate register value. ```c /* Standard Graphics I layout */ vrEmuTms9918SetNameTableAddr (tms, 0x3800); vrEmuTms9918SetColorTableAddr (tms, 0x0000); vrEmuTms9918SetPatternTableAddr (tms, 0x2000); vrEmuTms9918SetSpriteAttrTableAddr(tms, 0x3B00); vrEmuTms9918SetSpritePattTableAddr(tms, 0x1800); ``` -------------------------------- ### Link vrEmuTms9918Util to vrEmuTms9918 Source: https://github.com/visrealm/vremutms9918/blob/main/src/CMakeLists.txt Establishes a public link dependency for vrEmuTms9918Util on vrEmuTms9918. This ensures that the vrEmuTms9918 library is available when linking vrEmuTms9918Util. ```cmake target_link_libraries(vrEmuTms9918Util PUBLIC vrEmuTms9918) ``` -------------------------------- ### Write to the address/control port (CSW, MODE=1) Source: https://context7.com/visrealm/vremutms9918/llms.txt Simulates a write on the TMS9918 address bus (MODE pin high). Two consecutive calls set a VRAM address or write to a register, matching the real chip's latch behavior. ```c /* Write register: first byte is value, second is 0x80 | reg number */ vrEmuTms9918WriteAddr(tms, 0xC0); /* value = 0xC0 */ vrEmuTms9918WriteAddr(tms, 0x80 | 0x01); /* write to register 1 */ /* Set VRAM address for reading at 0x1800 */ vrEmuTms9918WriteAddr(tms, 0x00); /* low byte of 0x1800 */ vrEmuTms9918WriteAddr(tms, 0x18); /* high byte (no 0x40 flag = read mode) */ /* Set VRAM address for writing at 0x3800 */ vrEmuTms9918WriteAddr(tms, 0x00); /* low byte */ vrEmuTms9918WriteAddr(tms, 0x40 | 0x38); /* high byte | 0x40 = write mode */ ``` -------------------------------- ### Direct VDP register read/write Source: https://context7.com/visrealm/vremutms9918/llms.txt Use `vrEmuTms9918RegValue` and `vrEmuTms9918WriteRegValue` for direct register access, bypassing the standard latch protocol. These are intended for debugging or state management, not bus-accurate emulation. ```c /* Read current value of register 1 */ uint8_t r1 = vrEmuTms9918RegValue(tms, TMS_REG_1); printf("REG1 = 0x%02X\n", r1); /* Directly enable display (set BLANK bit) */ vrEmuTms9918WriteRegValue(tms, TMS_REG_1, r1 | 0x40); ``` -------------------------------- ### vrEmuTms9918WriteData Source: https://context7.com/visrealm/vremutms9918/llms.txt Simulates writing a data byte to VRAM (CSW, MODE=0). The emulator automatically increments the VRAM address pointer after each write, consistent with the real hardware's behavior. ```APIDOC ## vrEmuTms9918WriteData ### Description Writes a single byte to the current VRAM address and auto-increments the internal address pointer, exactly as on real hardware. ### Method `void vrEmuTms9918WriteData(VrEmuTms9918 *tms, uint8_t value); ` ### Parameters - **tms** (`VrEmuTms9918 *`): Pointer to the TMS9918 emulator instance. - **value** (`uint8_t`): The data byte to write to VRAM. ### Example ```c /* Write the byte pattern for a smiley face into pattern slot 0 */ static const uint8_t smile[8] = { 0b00111100, 0b01000010, 0b10000001, 0b10100101, 0b10000001, 0b10011001, 0b01000010, 0b00111100 }; /* Set write address to start of pattern table */ vrEmuTms9918WriteAddr(tms, 0x00); vrEmuTms9918WriteAddr(tms, 0x40 | 0x20); /* 0x2000 in write mode */ for (int i = 0; i < 8; ++i) vrEmuTms9918WriteData(tms, smile[i]); ``` ``` -------------------------------- ### Set REG7 foreground/background color Source: https://context7.com/visrealm/vremutms9918/llms.txt A convenience function to set the foreground and background color using REG7. It calls `vrEmuTms9918WriteRegisterValue` with the packed color byte. ```c vrEmuTms9918SetFgBgColor(tms, TMS_WHITE, TMS_DK_BLUE); /* Text-mode characters will render as white-on-dark-blue */ ``` -------------------------------- ### Repeat a byte write to VRAM Source: https://context7.com/visrealm/vremutms9918/llms.txt Use `vrEmuTms9918WriteByteRpt` to write the same byte value multiple times to VRAM. This is efficient for clearing large regions of memory. ```c /* Clear 16 KB of VRAM to zero */ vrEmuTms9918SetAddressWrite(tms, 0x0000); vrEmuTms9918WriteByteRpt(tms, 0x00, 0x4000); ``` -------------------------------- ### Read data byte from VRAM (CSR, MODE=0) Source: https://context7.com/visrealm/vremutms9918/llms.txt Reads one byte from the current VRAM address and auto-increments the pointer. ```c /* Read back 8 bytes from pattern table address 0x2000 */ vrEmuTms9918WriteAddr(tms, 0x00); vrEmuTms9918WriteAddr(tms, 0x20); /* read mode (no 0x40 flag) */ for (int i = 0; i < 8; ++i) { uint8_t byte = vrEmuTms9918ReadData(tms); printf("Pattern byte %d: 0x%02X\n", i, byte); } ``` -------------------------------- ### Tms9918 Python class Source: https://context7.com/visrealm/vremutms9918/llms.txt The `Tms9918` Python class, exposed via pybind11, offers a high-level interface to the C library. It includes methods for setting registers (`setReg`, `setRegs`), VRAM (`setVram`), and retrieving the screen buffer (`getScreen`). The `getScreen` method returns a flat list of RGB bytes representing the TMS9918 display. ```APIDOC ## `Tms9918` Python class — High-level Python interface The pybind11 module exposes a `Tms9918` class wrapping the C library. It provides `setReg`, `setRegs`, `setVram`, and `getScreen` methods. `getScreen` returns a flat `list[int]` of RGB bytes (256×192×3 = 147,456 bytes). ```python from tms9918 import Tms9918 from PIL import Image # Load a raw TMS9918 state dump (16 KB VRAM + 8 register bytes) with open("image.bin", "rb") as f: data = f.read() vram = list(data[:16 * 1024]) # first 16 384 bytes = VRAM regs = list(data[16 * 1024:]) # remaining bytes = register values tms = Tms9918() tms.setRegs(regs) # write all 8 registers at once tms.setVram(0, vram) # bulk-write VRAM starting at address 0 # getScreen() returns flat RGB bytes: [R0,G0,B0, R1,G1,B1, ...] screen = tms.getScreen() img = Image.frombytes('RGB', (256, 192), bytes(screen)) img.show() # Expected: renders the TMS9918 screen captured in image.bin ``` ``` -------------------------------- ### Write ASCII strings to VRAM Source: https://context7.com/visrealm/vremutms9918/llms.txt Write C strings to VRAM using `vrEmuTms9918WriteString` or `vrEmuTms9918WriteStringOffset`. The latter allows for an offset to be added to each character's value, useful for custom font mappings. ```c /* Write "HELLO" to name table starting at row 0, col 0 */ vrEmuTms9918SetAddressWrite(tms, 0x3800); vrEmuTms9918WriteString(tms, "HELLO"); /* Write "WORLD" with offset 32 (e.g., font mapped from pattern 32 upward) */ vrEmuTms9918SetAddressWrite(tms, 0x3820); vrEmuTms9918WriteStringOffset(tms, "WORLD", 32); ``` -------------------------------- ### vrEmuTms9918WriteAddr Source: https://context7.com/visrealm/vremutms9918/llms.txt Simulates writing to the TMS9918 address/control port (CSW, MODE=1). Two consecutive calls are required to set a VRAM address or write to a register, mimicking the chip's latching behavior. ```APIDOC ## vrEmuTms9918WriteAddr ### Description Simulates a write on the TMS9918 address bus (MODE pin high). Two consecutive calls set a VRAM address or write to a register, matching the real chip's latch behavior. ### Method `void vrEmuTms9918WriteAddr(VrEmuTms9918 *tms, uint8_t value); ` ### Parameters - **tms** (`VrEmuTms9918 *`): Pointer to the TMS9918 emulator instance. - **value** (`uint8_t`): The byte value to write to the address/control port. ### Usage Notes - To write to a register: Call twice. The first call provides the value, the second provides `0x80 | register_number`. - To set VRAM address for reading: Call twice. The first call provides the low byte of the address, the second provides the high byte (without the `0x40` write flag). - To set VRAM address for writing: Call twice. The first call provides the low byte of the address, the second provides the high byte with the `0x40` write flag set. ### Example ```c /* Write register: first byte is value, second is 0x80 | reg number */ vrEmuTms9918WriteAddr(tms, 0xC0); /* value = 0xC0 */ vrEmuTms9918WriteAddr(tms, 0x80 | 0x01); /* write to register 1 */ /* Set VRAM address for reading at 0x1800 */ vrEmuTms9918WriteAddr(tms, 0x00); /* low byte of 0x1800 */ vrEmuTms9918WriteAddr(tms, 0x18); /* high byte (no 0x40 flag = read mode) */ /* Set VRAM address for writing at 0x3800 */ vrEmuTms9918WriteAddr(tms, 0x00); /* low byte */ vrEmuTms9918WriteAddr(tms, 0x40 | 0x38); /* high byte | 0x40 = write mode */ ``` ``` -------------------------------- ### Conditional Compilation for Windows DLL Source: https://github.com/visrealm/vremutms9918/blob/main/src/CMakeLists.txt Adds a preprocessor definition for compiling a DLL on Windows. This is used when building shared libraries on the Windows platform. ```cmake if (WIN32) if (BUILD_SHARED_LIBS) add_definitions(-DVR_TMS9918_EMU_COMPILING_DLL) endif() endif() ``` -------------------------------- ### Write VDP register via latch protocol Source: https://context7.com/visrealm/vremutms9918/llms.txt The `vrEmuTms9918WriteRegisterValue` helper simplifies writing to VDP registers by handling the two-byte address-port sequence. Include `vrEmuTms9918Util.h` to use this function. ```c #include "vrEmuTms9918Util.h" /* Enable 16K RAM, activate display, enable interrupts, Graphics I mode */ vrEmuTms9918WriteRegisterValue(tms, TMS_REG_0, TMS_R0_MODE_GRAPHICS_I); vrEmuTms9918WriteRegisterValue(tms, TMS_REG_1, TMS_R1_RAM_16K | TMS_R1_DISP_ACTIVE | TMS_R1_INT_ENABLE | TMS_R1_MODE_GRAPHICS_I); ``` -------------------------------- ### Set VRAM address for read/write operations Source: https://context7.com/visrealm/vremutms9918/llms.txt Use `vrEmuTms9918SetAddressRead` and `vrEmuTms9918SetAddressWrite` to set the VRAM address pointer before performing sequential reads or writes. These functions abstract the two-byte latch sequence. ```c /* Prepare to read from color table at 0x0000 */ vrEmuTms9918SetAddressRead(tms, 0x0000); uint8_t color0 = vrEmuTms9918ReadData(tms); /* Prepare to write into name table at 0x3800 */ vrEmuTms9918SetAddressWrite(tms, 0x3800); vrEmuTms9918WriteData(tms, 0x01); /* place tile #1 at (0,0) */ ``` -------------------------------- ### vrEmuTms9918Reset Source: https://context7.com/visrealm/vremutms9918/llms.txt Resets the TMS9918 emulator to its initial power-on state. This function is useful for simulating system reset signals without deallocating the emulator instance. ```APIDOC ## vrEmuTms9918Reset ### Description Resets all internal registers and state without freeing the object. Useful when emulating a system reset signal. ### Method `void vrEmuTms9918Reset(VrEmuTms9918 *tms);` ### Parameters - **tms** (`VrEmuTms9918 *`): Pointer to the TMS9918 emulator instance to reset. ### Example ```c VrEmuTms9918 *tms = vrEmuTms9918New(); /* run emulation ... then reset */ vrEmuTms9918Reset(tms); /* tms is now in a clean power-on state */ ``` ``` -------------------------------- ### Read VDP status register (CSR, MODE=1) Source: https://context7.com/visrealm/vremutms9918/llms.txt Returns the status byte and clears the interrupt flag, exactly as on real hardware. Bits: `F`(VSYNC) | `5S`(5th sprite) | `C`(sprite collision) | sprite number. ```c uint8_t status = vrEmuTms9918ReadStatus(tms); if (status & 0x80) printf("VSYNC interrupt pending\n"); if (status & 0x40) printf("5th sprite detected, sprite #%d\n", status & 0x1F); if (status & 0x20) printf("Sprite collision detected\n"); ``` -------------------------------- ### `vrEmuTms9918DisplayEnabled` / `vrEmuTms9918DisplayMode` — State queries Source: https://context7.com/visrealm/vremutms9918/llms.txt Queries the current state of the TMS9918 display. `vrEmuTms9918DisplayEnabled` checks if the display is active, and `vrEmuTms9918DisplayMode` returns the current operational mode. ```APIDOC ## `vrEmuTms9918DisplayEnabled` / `vrEmuTms9918DisplayMode` — State queries ### Description Queries the current state of the TMS9918 display. `vrEmuTms9918DisplayEnabled` checks if the display is active, and `vrEmuTms9918DisplayMode` returns the current operational mode. ### Method ```c if (vrEmuTms9918DisplayEnabled(tms)) { switch (vrEmuTms9918DisplayMode(tms)) { case TMS_MODE_GRAPHICS_I: puts("Graphics I"); break; case TMS_MODE_GRAPHICS_II: puts("Graphics II"); break; case TMS_MODE_TEXT: puts("Text"); break; case TMS_MODE_MULTICOLOR: puts("Multicolor"); break; } } ``` ``` -------------------------------- ### Read VRAM without advancing address pointer Source: https://context7.com/visrealm/vremutms9918/llms.txt Use `vrEmuTms9918ReadDataNoInc` to peek at VRAM content without modifying the internal address pointer. This is useful for debugging or inspecting VRAM without side effects. ```c uint8_t val = vrEmuTms9918ReadDataNoInc(tms); /* subsequent calls return the same byte */ ``` -------------------------------- ### vrEmuTms9918SetFgBgColor Source: https://context7.com/visrealm/vremutms9918/llms.txt A convenience wrapper function that sets the foreground and background colors for text mode. It calls `vrEmuTms9918WriteRegisterValue` to write the packed color byte to the `TMS_REG_FG_BG_COLOR` register. ```APIDOC ## `vrEmuTms9918SetFgBgColor` — Set REG7 foreground/background color Convenience wrapper that calls `vrEmuTms9918WriteRegisterValue` for `TMS_REG_FG_BG_COLOR` with the packed color byte. ```c vrEmuTms9918SetFgBgColor(tms, TMS_WHITE, TMS_DK_BLUE); /* Text-mode characters will render as white-on-dark-blue */ ``` ``` -------------------------------- ### `vrEmuTms9918ScanLine` — Render a single scanline Source: https://context7.com/visrealm/vremutms9918/llms.txt Renders a single scanline of the TMS9918 display. This function populates a provided buffer with color palette indices for the specified scanline, which can then be used to construct the full frame. ```APIDOC ## `vrEmuTms9918ScanLine` — Render a single scanline ### Description Renders a single scanline of the TMS9918 display. This function populates a provided buffer with color palette indices for the specified scanline, which can then be used to construct the full frame. ### Method ```c #include "vrEmuTms9918.h" #define W TMS9918_PIXELS_X /* 256 */ #define H TMS9918_PIXELS_Y /* 192 */ uint32_t framebuffer[W * H]; uint8_t scanline[W]; for (int y = 0; y < H; ++y) { vrEmuTms9918ScanLine(tms, (uint8_t)y, scanline); for (int x = 0; x < W; ++x) { /* vrEmuTms9918Palette entries are 0xRRGGBBAA */ framebuffer[y * W + x] = vrEmuTms9918Palette[scanline[x]]; } } /* framebuffer now contains the full RGBA frame */ ``` ``` -------------------------------- ### Direct VRAM read by address Source: https://context7.com/visrealm/vremutms9918/llms.txt The `vrEmuTms9918VramValue` function allows reading a byte from VRAM at a specific address without altering the internal address pointer. This is useful for debuggers and unit tests. ```c /* Inspect name table entry at row 2, col 5 */ uint16_t name_addr = 0x3800 + (2 * 32) + 5; uint8_t tile_idx = vrEmuTms9918VramValue(tms, name_addr); printf("Name table [2][5] = pattern #%d\n", tile_idx); ``` -------------------------------- ### `vrEmuTms9918WriteRegisterValue` — Write a register via the latch protocol Source: https://context7.com/visrealm/vremutms9918/llms.txt Writes a value to a TMS9918 register using the standard two-byte address-port sequence. This is the recommended method for register writes during normal emulation. ```APIDOC ## `vrEmuTms9918WriteRegisterValue` — Write a register via the latch protocol ### Description Writes a value to a TMS9918 register using the standard two-byte address-port sequence. This is the recommended method for register writes during normal emulation. ### Method ```c #include "vrEmuTms9918Util.h" /* Enable 16K RAM, activate display, enable interrupts, Graphics I mode */ vrEmuTms9918WriteRegisterValue(tms, TMS_REG_0, TMS_R0_MODE_GRAPHICS_I); vrEmuTms9918WriteRegisterValue(tms, TMS_REG_1, TMS_R1_RAM_16K | TMS_R1_DISP_ACTIVE | TMS_R1_INT_ENABLE | TMS_R1_MODE_GRAPHICS_I); ``` ``` -------------------------------- ### `vrEmuTms9918WriteByteRpt` — Write a repeated byte to VRAM Source: https://context7.com/visrealm/vremutms9918/llms.txt Writes a single byte value repeatedly to VRAM for a specified number of times. This is efficient for clearing large regions of VRAM to a uniform value. ```APIDOC ## `vrEmuTms9918WriteByteRpt` — Write a repeated byte to VRAM ### Description Writes a single byte value repeatedly to VRAM for a specified number of times. This is efficient for clearing large regions of VRAM to a uniform value. ### Method ```c /* Clear 16 KB of VRAM to zero */ vxEmuTms9918SetAddressWrite(tms, 0x0000); vxEmuTms9918WriteByteRpt(tms, 0x00, 0x4000); ``` ``` -------------------------------- ### `vrEmuTms9918ReadDataNoInc` — Read VRAM without advancing the address pointer Source: https://context7.com/visrealm/vremutms9918/llms.txt Reads a byte from VRAM at the current internal address pointer without incrementing the pointer. This is useful for inspecting VRAM contents without altering the state for subsequent operations. ```APIDOC ## `vrEmuTms9918ReadDataNoInc` — Read VRAM without advancing the address pointer ### Description Reads a byte from VRAM at the current internal address pointer without incrementing the pointer. This is useful for inspecting VRAM contents without altering the state for subsequent operations. ### Method ```c uint8_t val = vrEmuTms9918ReadDataNoInc(tms); /* subsequent calls return the same byte */ ``` ``` -------------------------------- ### Destroy a TMS9918 instance Source: https://context7.com/visrealm/vremutms9918/llms.txt Frees all memory associated with the emulator object. Always call this when the instance is no longer needed. ```c VrEmuTms9918 *tms = vrEmuTms9918New(); /* ... */ vrEmuTms9918Destroy(tms); tms = NULL; /* good practice to avoid dangling pointer */ ``` -------------------------------- ### vrEmuTms9918Destroy Source: https://context7.com/visrealm/vremutms9918/llms.txt Frees all memory associated with a TMS9918 emulator instance. This function should always be called when the emulator is no longer needed to prevent memory leaks. ```APIDOC ## vrEmuTms9918Destroy ### Description Frees all memory associated with the emulator object. Always call this when the instance is no longer needed. ### Method `void vrEmuTms9918Destroy(VrEmuTms9918 *tms); ` ### Parameters - **tms** (`VrEmuTms9918 *`): Pointer to the TMS9918 emulator instance to destroy. ### Example ```c VrEmuTms9918 *tms = vrEmuTms9918New(); /* ... */ vrEmuTms9918Destroy(tms); tms = NULL; /* good practice to avoid dangling pointer */ ``` ```