First post, by gregf
Hi all,
Recently I fell down a deep retro rabbit hole reliving my old DOS days. One of the things I really wanted to recreate was a classic demoscene VGA text mode rainbow and copper effect.
On machines like the Amiga, you have copper lists and precise raster interrupts that make splitting screens and cycling palettes effortless. On a standard IBM PC, however, we are normally locked into rigid frame-based updates, meaning you are either forced to burn CPU cycles polling status ports or guessing timing loops.
Not being entirely satisfied with software polling, I decided to hack DOSBox to solve the problem at the architectural level - emulating a hardware-based scanline interrupt generator.
How the Emulated Hardware Works
I designed a virtual interface modelled after a conceptual ISA expansion card. It listens on I/O port `0x62` using a simple three-byte command protocol:
1. Target scanline low byte
2. Target scanline high byte
3. Interrupt vector and commit byte (e.g. 0x60)
I patched both the VGA and EGA rendering pipelines in DOSBox Staging to track scanlines as they are drawn. When the emulated scanline counter matches the target set by the program, it flags a pending event and injects a hardware interrupt directly into the PIC queue.
Putting it to Work: TINYRAIN.ASM
To test the concept, I wrote an assembly program that hooks interrupt 0x60. On every incoming scanline interrupt, the Interrupt Service Routine calculates a scrolling lookup index and updates VGA DAC register 7 on the fly.
The result is a silky smooth, 400-line continuous vertical rainbow (RED -> YELLOW -> GREEN -> CYAN -> BLUE -> MAGENTA -> RED) that scrolls down the screen independently of the main application loop - all without locking up the CPU in a tight polling loop. You can package it as a standalone test, or bundle it into a TSR to paint background copper bars behind your favourite DOS text-mode applications.
Next Steps and Real-World Hardware
The patch touches src/hardware/video/vga.cpp, vga_draw.cpp, vga.h, dosbox.cpp, pic.c and pic.h to ensure the vector fires cleanly when CPU interrupt flags allow it.
I would love to hear thoughts from fellow retro enthusiasts, emulator developers, or anyone else interested in bringing custom display co-processors to standard IBM hardware. Next up on the workbench is taking this exact protocol and moving it to physical hardware - building an actual ISA card with an external microcontroller listening directly to VGA HSYNC and VSYNC signals and generating the interrupts directly.
Cheers,
Greg