# HDGL Commodore 64 — COMPLETE package

A real, functioning Commodore 64 as a face of the substrate, running through the
universal translator, booting on real hardware with a working (polled) keyboard.

A real 6502 core executes the real KERNAL/BASIC ROMs; the substrate observes the
machine's screen and projects it as the face; typed keys flow through the
translator into the real KERNAL and BASIC executes them. Verified on metal
(Quadro NVS 295) with BIOS "USB Legacy / port 60/64" enabled.

## Boot (Windows / Rufus)

1. Rufus -> SELECT `iso/hdgl-c64.iso` -> **DD Image mode** -> START (erases USB).
2. In BIOS/UEFI setup:
   - Enable **Legacy/CSM boot**, disable **Secure Boot** (this is a BIOS multiboot image).
   - Enable **USB Legacy Support / USB Keyboard Support / Port 60/64 Emulation**
     (REQUIRED for the keyboard on a USB-keyboard machine).
3. Boot from USB, pick a GRUB entry. After the blue screen, wait a few seconds:
   - **interactive**: `READY.`; type `PRINT 3+4` <Return> -> `7`
   - **self-test**: auto-runs `PRINT 3+4` -> `7` (no typing)

Under QEMU: `qemu-system-i386 -cdrom iso/hdgl-c64.iso -boot d -m 256`

## The full fix history (all found by testing, close to metal)

1. **GDT segment limit 64MB -> 4GB** (`src/gdt.cpp`). Real GPUs expose the
   framebuffer at a high physical address (your NVS 295: $F9000000). The old
   64MB segment limit made writes there a GP fault -> triple fault -> reboot.
   THE "flash blue then reboot" bug. Invisible in QEMU (low framebuffer addr).
2. **Framebuffer from GRUB** (`src/kernel.cpp`) + `gfxpayload` in grub.cfg, so
   the kernel uses the real linear framebuffer GRUB set up, not a QEMU address.
3. **Fast boot**: 6502 step batch raised so BASIC comes up in ~3-4s not ~16s.
4. **Keyboard doubling fix** (`src/c64/io.cpp`): suppressed the CIA key-matrix
   path when the face is active, so the translator's buffer injection is the
   sole delivery (was `AABBCDDEE`, now clean; real double-letters preserved).
5. **Universal polled keyboard** (`src/c64/c64.cpp`, `src/drivers/keyboard.cpp`):
   the scancode ring is fed by POLLING port 0x60 every tick, IRQ-independent, so
   it works via BIOS USB-Legacy emulation even when IRQ1 never fires. This is
   what makes the keyboard work on your USB-keyboard metal.
6. **Low-latency input**: the guest runs in small chunks with the keyboard
   polled between each (20x/frame), and the screen only redraws when it changed
   -- cutting the input lag.

## Known limits (honest)

- **Keyboard needs BIOS port-60/64 (USB Legacy) emulation.** If a machine's BIOS
  delivers nothing to port 0x60 after boot (pure USB, no legacy), a real USB HID
  driver would be required -- OS64 has none. Proven: QEMU `-device usb-kbd` with
  no legacy delivers nothing to 0x60.
- **Some residual input lag** remains vs a cycle-exact machine; the polled path
  is responsive but the emulator loop is not real-time tuned.
- **Timing is not cycle-exact** (fine for BASIC/editor; not tight raster demos).
- **`.hdgl` is not canonical** -- the glyph files express the architecture.

## Contents

```
iso/hdgl-c64.iso            bootable image for Rufus (all fixes)
kernels/                    os64_c64_interactive.bin / .flat, os64_c64_selftest.bin
glyph/                      hdgl_universal_face.hdgl (the universal translator),
                            hdgl_c64_node.hdgl, hdgl_console.hdgl
analogcontainer1/           vector_container.h (the container-boundary primitive)
roms/                       real C64 KERNAL + BASIC (already baked into the kernel)
screenshots/                BASIC computing 3+4 = 7
OS64-master/                the COMPLETE source tree (verified: rebuilds clean)
README.md                   this file
FIXES/                      the per-issue write-ups (GDT, metal, keyboard, lag)
```

## Rebuild (Linux + gcc-multilib, nasm, grub-mkrescue)

```sh
cd OS64-master
make os64kernel.bin
objcopy -O binary os64kernel.bin os64kernel.flat
# self-test build: recompile face_node.o with -DFACE_SELFTEST, then relink.
# ISO:
mkdir -p iso/boot/grub
cp os64kernel.bin iso/boot/os64_c64.bin
printf 'set timeout=5\ninsmod all_video\nset gfxpayload=800x600x16,auto\nmenuentry "HDGL C64" { multiboot /boot/os64_c64.bin; boot }\n' > iso/boot/grub/grub.cfg
grub-mkrescue -o hdgl-c64.iso iso
```

## Architecture (universal translator)

The substrate does not re-implement any OS's hardware; it TRANSLATES the small
set of hardware-contract vectors an OS uses (console-out, keyboard, IRQ) into
substrate operations. One operator (`face_realize`/`face_tick`/`face_key`) drives
any OS; adding one means writing only its translation table. The C64 proves it:
we translate CHROUT ($FFD2->$0326) and the keyboard buffer ($0277/$C6), and
observe screen RAM ($0400) into the face. Input is a universal polled observer
feeding the scancode ring; the ring is the input boundary, source-agnostic.

Key files: `include/c64/face_node.h`, `src/c64/face_node.cpp` (operator + C64
translation table), `src/c64/f6502/` (real 6502 core + memory bridge),
`src/c64/c64.cpp` (the loop: polled input, chunked stepping, observe/project),
`src/gdt.cpp` (4GB fix), `src/kernel.cpp` (framebuffer), `src/drivers/keyboard.cpp`.
