code.pablomurad.com

fire-asm

Tiny 16-bit DOS fire demo in x86 assembly

git clone https://code.pablomurad.com/fire-asm.git

Recent commits

  1. 37364e6
    Initial commit
    
    Add the DOS fire demo source, screenshot, and project documentation as the initial repository state.
    
    Made-with: Cursor
    

Full log →

Readme

Fire ASM

FIRE running in DOSBox-X

Repository: runawaydevil/fire-asm

This is a tiny 16-bit real mode DOS fire demo written in x86 assembly.

No engine, no runtime, no framework. Just BIOS calls, VGA mode 13h, a hand-built palette, a scratch buffer, and a loop that keeps pushing heat upward until you press a key.

The Language

The source is NASM-style x86 assembly. It is built as a .COM program, which is about as bare-metal as DOS application code gets:

  • execution starts at offset 0x100
  • code and data live in the same segment
  • there is no executable header
  • DOS loads the program and jumps straight in
  • BIOS and DOS interrupts are used directly

The first line says it plainly:

org 0x100

That tells the assembler to lay out addresses for a DOS .COM file. There is also a commented org 0x7c00 path in the file, plus the commented boot signature at the bottom, because the same kind of code can be pushed toward an MBR-style boot sector with the right constraints.

Building It

Use NASM to build a flat binary:

nasm -f bin fire.asm -o FIRE.COM

Then run it inside DOSBox or DOSBox-X:

FIRE.COM

Press any key to leave the demo. The program restores text mode before exiting.

What It Does

The demo enters VGA mode 13h:

mov ax, 0x13
int 0x10

Mode 13h gives you a 320x200 framebuffer with one byte per pixel. The video memory starts at A000:0000, so drawing is just writing color indexes into a 64,000 byte linear buffer.

After switching video modes, the program writes the text pablomurad.com using BIOS interrupt 10h, function 13h. Then it builds the VGA palette by talking directly to the DAC ports:

  • 0x3c8: DAC address write register
  • 0x3c9: DAC data register

The palette starts dark, ramps through red and yellow, then fills the rest with white heat. Old school VGA palette tricks make the simulation cheap: the fire buffer stores only byte-sized intensity values, and the hardware palette turns those values into color.

The Fire Loop

The bottom row is seeded with pseudo-random heat:

imul ax, 181
add ax, 359

That is a small linear congruential generator. It is not cryptography, it is not pretty, but it is fast and good enough to shake the flame.

Each frame, the code walks backward through the buffer. For every pixel, it looks at nearby pixels below it:

  • directly below
  • below-left
  • below-right
  • two rows below

It adds those values, scales the sum by 15 / 64, and writes the cooled result above:

imul ax, 15
shr ax, 6

That tiny average-and-cool step is the whole fire effect. Heat is born at the bottom, smeared upward by neighboring pixels, and slowly loses energy as it rises.

Buffers And Video Memory

The program does not render directly into the visible framebuffer all the time. It copies the initial screen into a scratch buffer at a segment offset from the program segment, then computes frames there.

At the end of each loop it copies the scratch buffer back to VGA memory:

push 0xa000
pop es
rep movsw

The copy uses word moves for speed. This is the kind of code where ds, es, si, di, and the direction flag matter. There is no abstraction layer between the program and the machine.

Text Reflection

The text is part of the trick. The program mirrors some lower fire rows onto the area where the text lives, but only where destination pixels are already non-zero. That keeps the logo shape while borrowing color and motion from the flame below.

In other words: the text is a mask, the fire is the texture, and the CPU is doing the compositing one byte at a time.

Timing And Exit

Frame pacing uses BIOS interrupt 1Ah, waiting for the system timer tick. That tick runs at about 18.2 Hz on a classic PC.

Keyboard polling uses BIOS interrupt 16h. When a key is waiting, the program consumes it, restores text mode with int 10h, and exits through DOS interrupt 21h.

Files

  • fire.asm: the NASM source.
  • fire.png: screenshot of the demo running in DOSBox-X.
  • FIRE.COM: generated binary, if you build it locally.