1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150 |
# Fire ASM

Repository: [runawaydevil/fire-asm](https://github.com/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:
```asm
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:
```bat
nasm -f bin fire.asm -o FIRE.COM
```
Then run it inside DOSBox or DOSBox-X:
```bat
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:
```asm
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:
```asm
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:
```asm
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:
```asm
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.
|