|
pico9918-core 1.3.0
TMS9918A / F18A video display processor emulation in C99
|
The default build is the useful emulator library: multiple instances, the full PICO9918 renderer and GPU, runtime chip selection, the PRO line width and the debugger API. The examples, tests and Python module stay out until you ask for them.
docs targetThe library has no runtime dependencies beyond the platform C runtime. It builds static by default; a desktop build honours BUILD_SHARED_LIBS=ON. Pico firmware is always static.
That one build can create TMS9918, TMS9918A, F18A, PICO9918 and PICO9918 PRO instances. Call pico9918_set_chip() after creating one when the emulated machine needs a specific personality; a new instance otherwise starts at PICO9918_CHIP_MAX, which is PRO in the default wide build.
The 64KB map, enhanced renderer and GPU are always part of pico9918-core. If all you want is the smaller original chip, that is what vrEmuTms9918 is for. The emulator integration guide explains what each layer needs from the host once it is built.
The PICO9918 firmware supplies its own smaller policy when it adds this directory: both RP2040 and RP2350 builds turn runtime chip selection and the debug API off. RP2040 also turns the wide 80-column line off; RP2350 keeps it on.
The default produces a static library. Use CMake's standard switch for a shared one:
The pico9918::core target carries the right linkage definition to consumers. A static Windows consumer inherits PICO9918_STATIC; a shared library uses PICO9918_COMPILING_DLL privately while it is compiled, and its consumers get the dllimport declarations. Do not set any of those definitions yourself when linking the CMake target.
Vendored and installed builds use the same target name:
For the installed form:
test/package/ is a small working consumer. CI installs the library and builds that project separately, so it catches exports that only happened to work in-tree.
These are the settings an emulator integration is likely to care about. Pass them to CMake as -Dname=value when configuring the library, not as compiler definitions on the emulator target.
| option | default | what it changes |
|---|---|---|
PICO9918_SINGLE_INSTANCE | 0 | 1 puts one VDP at a fixed address and drops the instance argument from nearly every call. It is for firmware; leave it off in an emulator |
PICO9918_TEXT80_8BPP | ON | renders 80-column text at eight bits a pixel, which is what ECM, palette select and the bitmap layer need there. It doubles the widest line to 512 bytes |
PICO9918_RUNTIME_CHIP | ON | adds a per-instance TMS9918 / TMS9918A / F18A / PICO9918 / PRO selector. PRO also needs the wide 80-column line |
PICO9918_NO_SPLASH | OFF | drops the splash overlay and its image asset |
PICO9918_SPLASH_IMAGE | res/splash.png | chooses the PNG generated into the splash asset, relative to src/overlay/ |
PICO9918_DEBUG_API | ON | builds pico9918_debug.h: the memory map, span read and write, register store and GPU controls a debugger wants |
PICO9918_DIAG_GPU_FRAME_COUNTER | OFF | adds the optional GPU-frames row and its host-pushed counter to the diagnostics overlay |
PICO9918_EXAMPLES | OFF | builds the programs in examples/ against the same public target a consumer uses |
PICO9918_PYTHON_BINDING | OFF | builds the CPython extension and makes the static library position-independent |
PICO9918_SINGLE_INSTANCE=1 changes the calling convention of nearly every public function. Do not define it yourself when using an installed library. The generated pico9918_build_config.h records the choice the archive was built with and pico9918.h rejects a disagreement.
The line width, runtime-chip and debug choices are recorded there too. Size a line buffer with PICO9918_SCANLINE_BUFFER_SIZE and it will match the archive you actually linked.
These are mostly useful to the firmware and this repository itself:
| option | default | what it changes |
|---|---|---|
PICO9918_GPU_C_CORE | OFF | on a Pico build, uses the portable C TMS9900 core instead of the hand-written Thumb core. Desktop builds already use C, so the switch changes nothing there |
PICO9918_PORTABLE_CODEGEN | OFF | suppresses host-specific code generation (-march=native or /arch:AVX2). PICO9918_GOLDEN=ON turns it on automatically |
PICO9918_V9938_BASE | OFF | exposes the additive V9938 scaffold. This is not a finished V9938 implementation and is not an emulator personality to offer yet |
PICO9918_WERROR | OFF | asks GCC or Clang for -Wall -Wextra -Wpedantic -Werror. The MSVC build already uses /W4 /WX |
PICO9918_PICO_BUILD, PICO9918_BUILD_*, PICO9918_ASSET_PIXEL_SIZE and PICO9918_ASM_SUFFIX are derived by CMake. PICO9918_STATIC and PICO9918_COMPILING_DLL are selected from the target type. They appear in generated headers or compile commands, but they are not consumer settings and should not be supplied on the command line.
The source-level platform seam is separate again. A host compiling the library itself can provide PICO9918_HOST_OPS_HEADER, interrupt and critical-section operations, a clock, and the pixel/fill policy described in src/impl/platform.h. Those definitions must reach the library's translation units; adding them only to the emulator executable cannot change an archive that has already been compiled. Most desktop integrations do not need any of them.
These select the repository's own test programs. They are not library features:
| option | default | what it builds |
|---|---|---|
PICO9918_GOLDEN | OFF | the committed golden-frame regression harness; also enables portable code generation |
PICO9918_DEBUG_TEST | OFF | the debugger surface test; also enables PICO9918_DEBUG_API |
PICO9918_PIXEL_TEST | OFF | the post-palette pixel path and line-geometry test |
PICO9918_GPU_TEST | OFF | the library-paced GPU test |
PICO9918_TMS9900_TEST | OFF | the portable GPU core's instruction tests |
The ordinary CMake settings - BUILD_SHARED_LIBS, CMAKE_BUILD_TYPE, CMAKE_INSTALL_PREFIX, generator and toolchain selection - work normally and are not duplicated above.
The in-tree form is:
It produces a module named pico9918. The binding is one Python object per VDP, so it requires PICO9918_SINGLE_INSTANCE=0.
The binding can also be built on its own against an installed library:
In that form the installed static library must have been built as position-independent code. The top-level PICO9918_PYTHON_BINDING=ON route handles that for you.
If Doxygen was found while configuring a standalone build:
The HTML goes to doc/code. Binary packages can be made from the build directory with cpack -G TGZ or cpack -G ZIP; they contain whichever library type that build was configured for and are therefore platform-specific. Shared packages carry -shared in the filename so they can sit beside the default static ones.