# Setting up MSXgl on macOS MSXgl ships its build toolchain as **Windows and Linux x86 binaries only**. On a Mac (Apple Silicon or Intel) those bundled binaries cannot run, which is why a fresh checkout fails to build out of the box. This guide explains the one-time setup that makes it work, and documents exactly which samples build and which don't. Tested on: macOS (Apple Silicon, arm64), Node v24, SDCC 4.6, openMSX 21. --- ## 1. Install the prerequisites (Homebrew) ```bash brew install sdcc openmsx node ``` - **sdcc** — the Z80 C compiler / assembler / linker (`sdcc`, `sdasz80`, `sdar`). MSXgl was written against SDCC 4.2; Homebrew currently ships 4.6. Almost everything compiles, but a couple of samples don't (see *Known issues* below). - **openmsx** — the emulator used to run the built programs. - **node** — the build system is a set of Node.js scripts. (A system Node works fine; the `node` binary bundled in `tools/build/Node/` is Windows/Linux only.) Verify: ```bash sdcc -v # should print 4.x openmsx -v node -v ``` --- ## 2. How the project was adapted for macOS These changes are already applied in this checkout. They make the build prefer the **system** (Homebrew) toolchain on macOS/Linux while leaving Windows behavior unchanged. If you ever start from a clean MSXgl download, you'll need to redo them. | File | Change | |------|--------| | `engine/script/js/setup_global.js` | On non-Windows, use `sdcc`/`sdasz80`/`sdar` from `PATH` and derive the SDCC lib path from where `sdcc` is installed. | | `engine/script/js/default_config.js` | The hardcoded SDCC tool paths are guarded with `if (process.platform === "win32")` so they no longer override the system toolchain. `Emulator` auto-detects `openmsx` from `PATH`. | | `projects/default_config.js` | Same two changes. **This file is an auto-generated copy** of the engine template and loads *after* it — if you delete it, it regenerates from the (now-fixed) template. | | `tools/build/msxtar/msxtar` | Rebuilt as a native macOS binary from `tools/build/msxtar/src/main.cc` (the bundled one is Linux-only). Needed for all disk/tape image generation. The Linux original is kept as `msxtar.linux.bak`. | | `engine/src/vdp.h` | The struct-based `VDP_SetSpriteData` inline is now restricted to MSX1 (`#if (MSX_VERSION < MSX_2)`), removing a name clash with the MSX2 `const u8*` version that newer SDCC rejects. | | `engine/src/rom_mapper.h` | The `TARGET_DOS2_MAPPER` branch now `#include`s `dos_mapper.h`, so `DOSMapper_SetPage`/`GetPage` are declared (they were implicitly declared before, which newer SDCC rejects). | | `engine/script/js/setup_emulator.js` + both `default_config.js` | Added an `EmulMachineName` config option: when set, the openMSX runner uses that machine (e.g. a real MSX with a Disk BIOS) instead of C-BIOS. Needed to *run* disk/DOS targets — see section 4. | The MSX toolkit helpers in `tools/MSXtk/bin/` (`MSXhex`, `MSXbin`, `MSXmath`, `MSXzip`) were also rebuilt as native macOS arm64 binaries. The Windows `.exe` versions sit alongside them and are ignored on macOS. To rebuild `msxtar` yourself: `cd tools/build/msxtar/src && g++ main.cc -w -o ../msxtar` (harmless deprecation warnings; `-w` silences them). > **Note:** this directory is **not a git repository**, so the edits above are not > tracked. Keep a backup if you plan to update MSXgl from upstream. --- ## 3. Build and run a sample ```bash cd projects/samples ./build.sh s_bios # compile + link + package -> out/s_bios.rom ./build.sh s_bios run # same, then launch it in openMSX ``` - Built ROMs land in `projects/samples/out/` and are copied to `projects/samples/emul/rom/`. - Swap `s_bios` for any other sample name (the part before `.c` / `.js`), e.g. `s_print`, `s_psg`, `s_game`, `s_scroll`, `s_math`. - Common extra flags: `run` (launch emulator), `clean` (remove intermediates). Targets/machine are set per sample in its `s_*.js` and in `project_config.js`. To build your own project, copy `projects/template/` and use its `build.sh` the same way. --- ## 4. Running disk / DOS programs (extra setup) ROM and tape targets run on **C-BIOS**, the free BIOS openMSX bundles — no extra setup. But **C-BIOS cannot boot a disk**: it only autostarts cartridge ROMs (its boot screen literally says *"This version of C-BIOS can only start cartridges"*). So disk and MSX-DOS targets (`DOS0/1/2`, `BIN_DISK`, `_MAPPER`-to-disk, etc.) need a **real MSX machine** config, which requires that machine's **system ROMs** (copyrighted — supply them from a machine you own). **Setup:** 1. Put the system ROMs where openMSX looks for them — either `~/.openMSX/share/systemroms/` or `~/.openMSX/share/machines/` (both are searched recursively). openMSX matches ROMs by **SHA-1**, so filenames don't matter, but the dumps must be exact (an unextracted `.zip` or a bad dump is silently ignored). 2. Confirm a disk-capable machine resolves, e.g.: ```bash openmsx -machine Philips_NMS_8250 -diska projects/samples/emul/dsk/DOS1_s_dos.dsk ``` Good disk-equipped machines: `Philips_NMS_8250`, `Sony_HB-F1XD`, `Panasonic_FS-A1ST` (turboR), `National_FS-4500`. 3. Tell MSXgl's runner to use that machine by setting **`EmulMachineName`** in `projects/default_config.js` (already wired up and set to `Philips_NMS_8250` in this checkout): ```js EmulMachineName = "Philips_NMS_8250"; ``` It applies **only to disk/DOS/tape targets** (the ones C-BIOS can't boot). Plain **cartridge ROM** targets ignore it and keep using the version-correct C-BIOS machine — so an MSX2+ ROM still runs on `C-BIOS_MSX2+`, not on the (MSX2) machine set here. Leave it `""` to use C-BIOS for everything. Verified: - `./build.sh s_dos run` → boots MSX-DOS on `Philips_NMS_8250` and runs `s_dos` from the generated `.dsk`. - `projects/mazegame` (MSX2+ Konami-SCC ROM) → `./build.sh run` launches on `C-BIOS_MSX2+_EU` automatically. --- ## What works ✅ **All 55 samples build cleanly** (verified: 55 pass, 0 fail), across every output format — plain/mapped ROM, BASIC binary, tape, and MSX-DOS 0/1/2 disk images. This includes graphics/VDP, input, every audio replayer, the MegaROM mappers, and the disk/tape samples. Running any of them in openMSX (`./build.sh run`) works. This required the native `msxtar` and the two small source fixes listed in section 2. Without those, 8 samples fail — see below for what they were, in case you start from a clean MSXgl checkout and hit them again. ## Previously-failing samples (now fixed) ⚠️ On a clean MSXgl download these 8 fail. They are fixed in this checkout; the notes below say how, so you can reapply after an upstream update. ### A. Disk / tape formats — bundled `msxtar` is Linux-only (6 samples) `s_dos`, `s_dos0`, `s_dos2`, `s_lvgm`, `s_usr`, `s_zip` They **compile and link fine** but fail at the final disk-image (`.dsk`) step with `/bin/sh: ./msxtar: cannot execute binary file`, because the shipped `tools/build/msxtar/msxtar` is a Linux x86-64 ELF binary. The same blocks any `BIN_DISK`, `BIN_TAPE`, `DOS0/1/2`, or `_MAPPER`-to-disk target you configure yourself. **Fix (applied):** rebuilt `msxtar` natively from its bundled source — `cd tools/build/msxtar/src && g++ main.cc -w -o ../msxtar`. ### B. SDCC 4.6 source incompatibilities (2 samples) The code was written for SDCC 4.2; SDCC 4.6 has a stricter front-end. These would fail the same way on Linux/Windows with SDCC 4.6 — they are **not** macOS-specific. | Sample | Original error | Fix (applied) | |--------|----------------|---------------| | `s_sprite` | `vdp.h:1217: error 20: Undefined identifier 'data'/'index'` — name clash: on MSX2 `VDP_SetSpriteData` was declared both as a struct-based inline and as the real `const u8*` function. | Restricted the struct-based inline to MSX1 with `#if (MSX_VERSION < MSX_2)`. | | `s_dosmap` | `rom_mapper.h:275/282: error 101: too many parameters` — `DOSMapper_SetPage`/`GetPage` were implicitly declared. | Added `#include "dos_mapper.h"` to the `TARGET_DOS2_MAPPER` branch. | (Alternative to the source fixes: install **SDCC 4.2** and point the build at it via `Compiler`/`Assembler`/`Linker`/`SDCCPath` in `projects/default_config.js`.) --- ## Quick reference ```bash # one-time brew install sdcc openmsx node # build a ROM and run it cd projects/samples ./build.sh s_bios run # rebuild everything to see current pass/fail for p in $(ls s_*.js | sed 's/\.js$//'); do ./build.sh "$p" >/dev/null 2>&1 \ && echo "PASS $p" || echo "FAIL $p"; done ``` **Bottom line:** with SDCC and openMSX installed and the fixes in this checkout, MSXgl development works fully on macOS — all 55 samples build across every output format (ROM, BASIC binary, tape, and MSX-DOS disk). ROM/tape samples run on free C-BIOS out of the box; disk/DOS samples run too, but require real MSX system ROMs and an `EmulMachineName` (see section 4).