Stage 0: the emulator carries the ROM, so a disk is enough

./SplitBit --disk system.img
  stage two
  CosmOS
  >

No boot image named. The emulator shadows its built in stage one into
Program Memory - boot vector included - and the CPU then does exactly what
it has always done: reads the boot vector and starts where it points.
NOTHING ABOUT THE CPU CHANGED to make a machine that starts itself, which
is what picking shadowing over a mapped ROM bought.

The ROM is generated from Programs/Boot/stage1.asm by the makefile rather
than committed beside it, because a copy of a program kept next to the
program is a copy that goes stale. That makes the assembler a real
dependency of the emulator, which it always sort of was and now says so.
od and awk rather than xxd, which is not everywhere, or python, which the
README does not ask anybody to install in order to build this.

loadROM is loadFile given bytes instead of a path: both go through one
reader over an fmemopen stream, because a ROM is a boot image and there is
no reason for the machine to have two ways of understanding one.

Naming an image still works and is what every other test here does. That
path is not a shortcut to apologise for - placing memory from outside is a
real thing real machines allow, and it is a debugger. The help says so now.
No image and no disk is the one case with nothing to run, and it says that
rather than printing a usage message about a missing file.

run.sh gained a "rom" mode which hands the emulator a disk and nothing
else. The source column still names stage1.asm, because that is what is IN
the ROM: assembling it there says the thing the emulator carries is a thing
that still assembles.
This commit is contained in:
Anachronaut
2026-08-27 14:41:33 -04:00
parent c312853f8e
commit 54ff7196c9
11 changed files with 177 additions and 16 deletions
+32 -1
View File
@@ -33,7 +33,7 @@ SRC_DIR_LINT = Source/Linter
OBJ_DIR = Object
# Source files
EMU_SRCS = emulator.c io.c controller.c utility.c cpu.c bootstrap.c assembly.c
EMU_SRCS = emulator.c io.c controller.c utility.c cpu.c bootstrap.c assembly.c rom.c
ASM_SRCS = Assembler.c assembly.c firstPass.c Assm-util.c secondPass.c
DSK_SRCS = SplitDisk.c
LINT_SRCS = Linter.c
@@ -52,6 +52,36 @@ LINT_TARGET = SplitLint
# Default target: build the emulator and its three host-side tools.
all: $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET) $(LINT_TARGET)
# ---- The ROM the machine wakes up in ----
#
# Generated from the assembly rather than committed, because a copy of a program kept
# beside the program is a copy that goes stale. It needs the assembler, which is built
# first; that is a real dependency and saying so is better than hiding it.
#
# od and awk rather than xxd, which is not everywhere, and rather than python, which the
# README does not ask anybody to install to build this.
$(SRC_DIR_EMU)/rom.c: Programs/Boot/stage1.asm $(ASM_TARGET)
@mkdir -p $(OBJ_DIR)
@./$(ASM_TARGET) Programs/Boot/stage1.asm -o $(OBJ_DIR)/stage1.bin > /dev/null
@{ \
echo '// rom.c'; \
echo '// GENERATED from Programs/Boot/stage1.asm by the makefile. Do not edit.'; \
echo '//'; \
echo '// The first thing the machine runs, and the only part of it that is not on'; \
echo '// the disk. On hardware this is a chip; here it is an array, placed into'; \
echo '// Program Memory at reset the way a shadowed ROM is.'; \
echo ''; \
echo '#include "rom.h"'; \
echo ''; \
echo 'const unsigned char bootROM[] = {'; \
od -v -An -tu1 $(OBJ_DIR)/stage1.bin | awk '{ printf " "; for (i = 1; i <= NF; i++) printf " %s,", $$i; print "" }'; \
echo '};'; \
echo ''; \
echo 'const unsigned long bootROMBytes = sizeof(bootROM);'; \
} > $@
$(OBJ_DIR)/rom.o: $(SRC_DIR_EMU)/rom.c $(SRC_DIR_EMU)/rom.h
# Emulator binary
$(EMU_TARGET): $(EMU_OBJS)
$(CC) $(CFLAGS) -o $(EMU_TARGET) $(EMU_OBJS)
@@ -172,6 +202,7 @@ bless: $(EMU_TARGET) $(ASM_TARGET)
clean:
rm -rf $(OBJ_DIR)
rm -rf Tests/build
rm -f $(SRC_DIR_EMU)/rom.c
rm -f $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET) $(LINT_TARGET)
# Install compiled binaries