mirror of
https://codeberg.org/virtualxt/virtualxt.git
synced 2026-10-19 14:04:45 +00:00
Bug fixes: - pic: honor auto-EOI mode (ICW4 bit 1); ISR bit now only set when auto-EOI is disabled (previously set unconditionally) - spec: correct port 0xB0-in polarity (0x00 = hard disk, 0xFF = floppy) to match both the Odin and C implementations - debug: gate cga_regs/cga_vram handlers on the video adapter actually being CGA (returned garbage when EGA/HGC was active) Dead code removal: - unused public APIs: vxt_cpu_flush_prefetch, vxt_bus_set_pic, vxt_uart_registers, vxt_uart_set_error, vxt_disk_bootstrap - write-only CPU instruction-stream fields + MAX_INSTRUCTION_SIZE - unused macros VXT_CPU_USE_PREFETCH, MBOX_TOTAL_SIZE - debug server: g_active_server, single_step, last_segments, SEG_TAG_* - UART iir field, always-false ega_config stub, empty destroy stubs (joystick, UART, mouse), exec_wait/exec_esc folded into exec_nop - frontend: BIOS_ROM_BASE/VXTX_ROM_BASE, mixer HOSTFS_DURATION/ HOSTFS_VOLUME/seek_volume, unreachable clamps, ini_parse return value - misc dead stores/clamps (hostfs, hgc), dangling comment (cpu.c) Makefile: drop 12 redundant pattern rules, replace dead check-circle test with a real compiler check, drop duplicated distclean line, complete .PHONY, collapse flag lists, develop honors LIBRETRO_OUT. STATUS.md: correct stale module test counts (110 -> 119).
303 lines
12 KiB
Makefile
303 lines
12 KiB
Makefile
# VirtualXT -- Makefile
|
|
#
|
|
# Core library, utils, modules, and frontend compile freestanding (no libc).
|
|
# The frontend depends only on libretro function pointers.
|
|
# Tests are hosted (use libc for stdio, malloc, etc.).
|
|
#
|
|
# Targets:
|
|
# develop (default) -- libretro core with debug server + test runners
|
|
# release -- libretro core without debug server
|
|
# object -- release-mode libretro object for packaging/web
|
|
# rpi -- cross-compile baremetal Raspberry Pi kernel
|
|
# web -- standalone Emscripten web frontend
|
|
# test -- run all tests (test-modules + test-cpu)
|
|
# testdata -- download 8088/V20 MOO CPU test data
|
|
# bios-data -- regenerate C headers from BIOS ROMs and disk image
|
|
# samples -- regenerate audio sample header
|
|
# vxtbios/vxtx/egabios-- assemble BIOS ROMs (requires nasm)
|
|
# run -- launch develop core in RetroArch
|
|
# clean/distclean -- remove build artifacts (+ test data)
|
|
|
|
CC ?= gcc
|
|
AR ?= ar
|
|
NASM ?= nasm
|
|
PYTHON ?= python3
|
|
BUILD_DATE := $(shell date +%m/%d/%Y)
|
|
VXT_VERSION := $(shell . tools/getversion/export.sh)
|
|
CFLAGS := -std=c11 -Wall -Wextra -Wpedantic -Isrc
|
|
LDFLAGS ?=
|
|
LIBRETRO_OUT ?= virtualxt_libretro.so
|
|
LIBRETRO_LINK_MODE ?= -shared
|
|
LIBRETRO_OBJECT_OUT ?= virtualxt_libretro.o
|
|
CIRCLEHOME ?= ../circle
|
|
|
|
# Cross-compiler prefix for Raspberry Pi.
|
|
# Read the toolchain prefix from Circle's Config.mk (set by ./configure).
|
|
# Falls back to the standard baremetal prefix if Circle is not yet configured.
|
|
CROSS_PREFIX ?= $(shell \
|
|
if [ -f "$(CIRCLEHOME)/Config.mk" ]; then \
|
|
grep '^PREFIX64' "$(CIRCLEHOME)/Config.mk" 2>/dev/null | sed 's/^PREFIX64[[:space:]]*=[[:space:]]*//' | sed 's/[[:space:]]*$$//'; \
|
|
fi)
|
|
ifeq ($(CROSS_PREFIX),)
|
|
CROSS_PREFIX := aarch64-none-elf-
|
|
endif
|
|
|
|
ifdef NO_RTC
|
|
CFLAGS += -DNO_RTC
|
|
endif
|
|
|
|
ifdef NO_DEFAULT_DISK
|
|
CFLAGS += -DNO_DEFAULT_DISK
|
|
endif
|
|
|
|
ifdef NO_SAMPLES
|
|
CFLAGS += -DNO_SAMPLES
|
|
endif
|
|
|
|
ifdef CRT_FILTER_EXTERNAL
|
|
CFLAGS += -DCRT_FILTER_EXTERNAL
|
|
endif
|
|
|
|
CORE_CFLAGS := $(CFLAGS) -ffreestanding -fPIC -O2
|
|
TEST_CFLAGS := $(CFLAGS) -O2 -DDEBUG_SERVER
|
|
FRONT_CFLAGS := $(CORE_CFLAGS) -Itools/libretro -DVXT_VERSION='"$(VXT_VERSION)"'
|
|
DEBUG_CFLAGS := $(TEST_CFLAGS) -fPIC
|
|
|
|
# ── Source lists ─────────────────────────────────────────────────────────
|
|
|
|
CORE_SRCS := src/utils/utils.c \
|
|
src/vxt/peripheral.c src/vxt/cpu.c src/vxt/alu.c \
|
|
src/vxt/div.c src/vxt/cpu_remap.c src/vxt/cpu_v20.c \
|
|
src/vxt/cpu_cycles.c src/vxt/machine.c \
|
|
src/modules/module_table.c \
|
|
src/modules/rom/rom.c \
|
|
src/modules/disk/disk.c \
|
|
src/modules/chipset/chipset.c src/modules/chipset/pic.c \
|
|
src/modules/chipset/pit.c src/modules/chipset/dma.c \
|
|
src/modules/chipset/ppi.c \
|
|
src/modules/cga/cga.c \
|
|
src/modules/ega/ega.c \
|
|
src/modules/hgc/hgc.c \
|
|
src/modules/uart/uart.c \
|
|
src/modules/mouse/mouse.c \
|
|
src/modules/joystick/joystick.c \
|
|
src/modules/hostfs/hostfs.c \
|
|
src/modules/ems/ems.c \
|
|
$(if $(NO_RTC),,src/modules/rtc/rtc.c)
|
|
|
|
TEST_SRCS := src/tests/moo.c src/tests/cpu_main.c
|
|
|
|
MODULE_SRCS := src/tests/module_main.c \
|
|
src/tests/test_bus.c src/tests/test_pic.c \
|
|
src/tests/test_pit.c src/tests/test_dma.c \
|
|
src/tests/test_rom.c src/tests/test_ppi.c \
|
|
src/tests/test_ems.c src/tests/test_rtc.c
|
|
|
|
# ── Object lists ─────────────────────────────────────────────────────────
|
|
|
|
CORE_OBJS := $(CORE_SRCS:.c=.o)
|
|
TEST_OBJS := $(TEST_SRCS:.c=.o)
|
|
MODULE_OBJS := $(MODULE_SRCS:.c=.o)
|
|
DEBUG_TEST_OBJS := src/tests/test_debug.o
|
|
DEBUG_SERVER_OBJS := src/modules/debug/debug_server.o
|
|
DEVELOP_FRONT_OBJS := src/frontend/core.develop.o src/frontend/ini.develop.o src/frontend/crt.develop.o src/frontend/audio_mixer.develop.o
|
|
RELEASE_FRONT_OBJS := src/frontend/core.release.o src/frontend/ini.release.o src/frontend/crt.release.o src/frontend/audio_mixer.release.o
|
|
|
|
# When NO_RTC=1, rtc.o is excluded from libvxt.a but test_rtc.c still needs it.
|
|
# Compile rtc.o separately for the module-runner link.
|
|
ifdef NO_RTC
|
|
MODULE_EXTRA_OBJS := src/modules/rtc/rtc.o
|
|
else
|
|
MODULE_EXTRA_OBJS :=
|
|
endif
|
|
|
|
# ── BIOS data generation ────────────────────────────────────────────────
|
|
|
|
BIOS_DATA := src/frontend/generated/vxtbios_bin.h \
|
|
src/frontend/generated/vxtx_bin.h \
|
|
src/frontend/generated/egabios_rom.h \
|
|
src/frontend/generated/freedos_hd_img.h
|
|
|
|
$(BIOS_DATA): bios/vxtbios.bin bios/vxtx.bin bios/egabios.bin boot/freedos_hd.img
|
|
$(PYTHON) tools/bios/gen_bios_data.py
|
|
|
|
# ── Sample data generation ──────────────────────────────────────────────
|
|
|
|
SAMPLES_DATA := src/frontend/generated/audio_samples.h
|
|
|
|
$(SAMPLES_DATA): samples/servo_seeks_eq.wav tools/samples/gen_samples.py
|
|
$(PYTHON) tools/samples/gen_samples.py
|
|
|
|
# ── Top-level targets ───────────────────────────────────────────────────
|
|
|
|
.PHONY: all develop release object web rpi check-circle clean distclean testdata test test-cpu test-cpu-8088 test-cpu-v20 test-modules run bios-data samples vxtbios vxtx egabios
|
|
|
|
.DEFAULT_GOAL := develop
|
|
|
|
all: develop
|
|
|
|
develop: libvxt.a test-runner module-runner $(DEVELOP_FRONT_OBJS) $(DEBUG_SERVER_OBJS)
|
|
mkdir -p $(dir $(LIBRETRO_OUT))
|
|
$(CC) $(LIBRETRO_LINK_MODE) -o $(LIBRETRO_OUT) $(LDFLAGS) $(DEVELOP_FRONT_OBJS) $(DEBUG_SERVER_OBJS) ./libvxt.a -lpthread
|
|
|
|
release: libvxt.a $(RELEASE_FRONT_OBJS)
|
|
mkdir -p $(dir $(LIBRETRO_OUT))
|
|
$(CC) $(LIBRETRO_LINK_MODE) -o $(LIBRETRO_OUT) $(RELEASE_FRONT_OBJS) ./libvxt.a
|
|
|
|
object: libvxt.a $(RELEASE_FRONT_OBJS)
|
|
mkdir -p $(dir $(LIBRETRO_OBJECT_OUT))
|
|
$(CC) -r $(LDFLAGS) -o $(LIBRETRO_OBJECT_OUT) $(RELEASE_FRONT_OBJS) ./libvxt.a
|
|
|
|
# Cross-compile the libretro core object for Raspberry Pi (AArch64 baremetal),
|
|
# then build the Circle kernel image that wraps it.
|
|
# The baremetal target excludes the default disk image and audio samples to
|
|
# reduce binary size; the user is expected to provide a custom machine setup.
|
|
rpi: check-circle
|
|
rm -f $(CORE_OBJS) $(RELEASE_FRONT_OBJS) libvxt.a $(LIBRETRO_OBJECT_OUT)
|
|
$(MAKE) CC=$(CROSS_PREFIX)gcc AR=$(CROSS_PREFIX)ar object NO_DEFAULT_DISK=1 NO_SAMPLES=1 CRT_FILTER_EXTERNAL=1
|
|
$(MAKE) -C tools/circle/kernel PREFIX64=$(CROSS_PREFIX)
|
|
|
|
# Build standalone web frontend with Emscripten.
|
|
web:
|
|
$(MAKE) -C tools/web
|
|
|
|
check-circle:
|
|
@command -v $(CROSS_PREFIX)gcc >/dev/null 2>&1 || { \
|
|
echo "Error: No AArch64 cross-compiler found ($(CROSS_PREFIX)gcc)."; \
|
|
echo "Please install aarch64-none-elf-gcc or aarch64-linux-gnu-gcc."; \
|
|
exit 1; \
|
|
}
|
|
@if [ ! -f "$(CIRCLEHOME)/lib/libcircle.a" ]; then \
|
|
echo "Error: Circle library not found at $(CIRCLEHOME)/lib/libcircle.a"; \
|
|
echo "Please build Circle first:"; \
|
|
echo " cd $(CIRCLEHOME) && ./configure -r 4 --multicore && makeall"; \
|
|
exit 1; \
|
|
fi
|
|
|
|
bios-data: $(BIOS_DATA)
|
|
samples: $(SAMPLES_DATA)
|
|
|
|
# ── BIOS assembly (manual, requires nasm) ───────────────────────────────
|
|
|
|
vxtbios: bios/vxtbios.bin
|
|
bios/vxtbios.bin: bios/vxtbios.asm
|
|
$(NASM) -f bin -o $@ -l bios/vxtbios.lst -dBUILD_DATE="'$(BUILD_DATE)'" $<
|
|
$(PYTHON) tools/checksum/update_bios_checksum.py $@
|
|
|
|
vxtx: bios/vxtx.bin
|
|
bios/vxtx.bin: bios/vxtx.asm
|
|
$(NASM) -f bin -o $@ -l bios/vxtx.lst $<
|
|
$(PYTHON) tools/checksum/update_bios_checksum.py $@
|
|
|
|
egabios: bios/egabios.bin
|
|
bios/egabios.bin: bios/egabios.asm
|
|
$(NASM) -f bin -o $@ -l bios/egabios.lst $<
|
|
$(PYTHON) tools/checksum/update_bios_checksum.py $@
|
|
|
|
# ── Libraries and binaries ──────────────────────────────────────────────
|
|
|
|
libvxt.a: $(CORE_OBJS)
|
|
$(AR) rcs $@ $^
|
|
|
|
test-runner: $(TEST_OBJS) libvxt.a
|
|
$(CC) $(TEST_CFLAGS) -o $@ $(TEST_OBJS) ./libvxt.a
|
|
|
|
module-runner: $(MODULE_OBJS) $(MODULE_EXTRA_OBJS) $(DEBUG_TEST_OBJS) $(DEBUG_SERVER_OBJS) libvxt.a
|
|
$(CC) $(TEST_CFLAGS) -o $@ $(MODULE_OBJS) $(MODULE_EXTRA_OBJS) $(DEBUG_TEST_OBJS) $(DEBUG_SERVER_OBJS) ./libvxt.a -lpthread
|
|
|
|
# ── Compilation rules ───────────────────────────────────────────────────
|
|
|
|
# Core: freestanding.
|
|
src/utils/%.o: src/utils/%.c; $(CC) $(CORE_CFLAGS) -c -o $@ $<
|
|
src/vxt/%.o: src/vxt/%.c; $(CC) $(CORE_CFLAGS) -c -o $@ $<
|
|
src/modules/%.o: src/modules/%.c; $(CC) $(CORE_CFLAGS) -c -o $@ $<
|
|
src/modules/debug/%.o: src/modules/debug/%.c; $(CC) $(DEBUG_CFLAGS) -c -o $@ $<
|
|
|
|
# Tests: hosted.
|
|
src/tests/%.o: src/tests/%.c
|
|
$(CC) $(TEST_CFLAGS) -c -o $@ $<
|
|
|
|
# Frontend: develop (with debug server) and release (without).
|
|
src/frontend/%.develop.o: src/frontend/%.c
|
|
$(CC) $(FRONT_CFLAGS) -DDEBUG_SERVER -c -o $@ $<
|
|
|
|
src/frontend/%.release.o: src/frontend/%.c
|
|
$(CC) $(FRONT_CFLAGS) -c -o $@ $<
|
|
|
|
# ── Test targets ────────────────────────────────────────────────────────
|
|
|
|
test: test-modules test-cpu
|
|
|
|
test-modules: module-runner
|
|
@./module-runner
|
|
|
|
test-cpu: test-cpu-8088 test-cpu-v20
|
|
|
|
test-cpu-8088: test-runner
|
|
@if [ ! -d src/tests/testdata ] || [ -z "$$(ls src/tests/testdata/*.MOO 2>/dev/null)" ]; then \
|
|
echo "No 8088 test data found. Run 'make testdata' first."; exit 1; \
|
|
fi; \
|
|
failed=0; passed=0; total=0; \
|
|
for f in src/tests/testdata/*.MOO; do \
|
|
[ -f "$$f" ] || continue; \
|
|
mask=213; \
|
|
if [ -f src/tests/testdata/masks.txt ]; then \
|
|
m=$$(grep "^$$(basename $$f) " src/tests/testdata/masks.txt | awk '{print $$2}'); \
|
|
[ -n "$$m" ] && mask=$$m; \
|
|
fi; \
|
|
total=$$((total + 1)); \
|
|
if ./test-runner "$$f" "$$mask"; then \
|
|
passed=$$((passed + 1)); \
|
|
else \
|
|
failed=$$((failed + 1)); \
|
|
fi; \
|
|
done; \
|
|
echo ""; \
|
|
echo "=== 8088 Results: $$passed passed, $$failed failed ($$total files) ==="; \
|
|
[ $$failed -eq 0 ]
|
|
|
|
test-cpu-v20: test-runner
|
|
@if [ ! -d src/tests/testdata/v20 ] || [ -z "$$(ls src/tests/testdata/v20/*.MOO 2>/dev/null)" ]; then \
|
|
echo "No V20 test data found. Run 'make testdata' first."; exit 1; \
|
|
fi; \
|
|
failed=0; passed=0; total=0; \
|
|
for f in src/tests/testdata/v20/*.MOO; do \
|
|
[ -f "$$f" ] || continue; \
|
|
mask=213; \
|
|
if [ -f src/tests/testdata/v20/masks.txt ]; then \
|
|
m=$$(grep "^$$(basename $$f) " src/tests/testdata/v20/masks.txt | awk '{print $$2}'); \
|
|
[ -n "$$m" ] && mask=$$m; \
|
|
fi; \
|
|
total=$$((total + 1)); \
|
|
if ./test-runner --v20 "$$f" "$$mask"; then \
|
|
passed=$$((passed + 1)); \
|
|
else \
|
|
failed=$$((failed + 1)); \
|
|
fi; \
|
|
done; \
|
|
echo ""; \
|
|
echo "=== V20 Results: $$passed passed, $$failed failed ($$total files) ==="; \
|
|
[ $$failed -eq 0 ]
|
|
|
|
testdata:
|
|
$(PYTHON) tools/testdata/fetch.py
|
|
|
|
# ── Run ─────────────────────────────────────────────────────────────────
|
|
|
|
run: develop
|
|
retroarch -v -L virtualxt_libretro.so
|
|
|
|
# ── Clean ───────────────────────────────────────────────────────────────
|
|
|
|
clean:
|
|
rm -f $(CORE_OBJS) $(TEST_OBJS) $(MODULE_OBJS) $(MODULE_EXTRA_OBJS) \
|
|
$(DEBUG_TEST_OBJS) $(DEBUG_SERVER_OBJS) \
|
|
$(DEVELOP_FRONT_OBJS) $(RELEASE_FRONT_OBJS) \
|
|
libvxt.a test-runner module-runner $(LIBRETRO_OUT) \
|
|
$(LIBRETRO_OBJECT_OUT)
|
|
-$(MAKE) -C tools/circle/kernel clean
|
|
-$(MAKE) -C tools/web clean
|
|
|
|
distclean: clean
|
|
rm -rf src/tests/testdata
|