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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191 |
org 0x100 ; For .com file.
;org 0x7c00 ; For MBR.
section .text
start:
; Enter mode 13h: 320x200, 1 byte (256 colors) per pixel.
mov ax, 0x13
int 0x10
; Make sure es and ds point to our segment (cs).
push cs
push cs
pop ds
pop es
; Write string.
mov ax, 0x1300 ; ah=13h, al=write mode
mov bx, 0xf ; bh=page number (0), bl=attribute (white)
mov cx, (msg_end - msg) ; cx=length
mov dx, ((10 << 8) + (40 / 2 - (msg_end - msg) / 2)) ; dh=row, cl=column
mov bp, msg ; es:bp=string address
int 0x10
; Set up the palette.
; Jare's original FirePal:
cli ; No interrupts while we do this, please.
mov dx, 0x3c8 ; DAC Address Write Mode Register
xor al, al
out dx, al ; Start setting DAC register 0
inc dx ; DAC Data Register
mov cx, (firepal_end - firepal)
mov si, firepal
setpal1:
lodsb
out dx, al ; Set DAC register (3 byte writes per register)
loop setpal1
mov al, 63
mov cx, (256 * 3 - (firepal_end - firepal))
setpal2:
out dx, al ; Set remaining registers to "white heat".
loop setpal2
sti ; Re-enable interrupts.
; A buffer at offset 0x1000 from our segment will be used for preparing
; the frames. Copy the current framebuffer (the text) there.
push 0xa000
pop ds
push cs
pop ax
add ax, 0x1000
mov es, ax
xor si, si
xor di, di
mov cx, (320 * 200 / 2)
cld
rep movsw ; Copy two bytes at a time.
push es
pop ds
mainloop:
; On entry to the loop, es and ds should point to the scratch buffer.
; Since we'll be working "backwards" through the framebuffer, set the
; direction flag, meaning stosb etc. will decrement the index registers.
std
; Let di point to the pixel to be written.
mov di, (320 * 200 - 1)
; Write random values to the bottom row.
; For random numbers, use "x = 181 * x + 359" from
; Tom Dickens "Random Number Generator for Microcontrollers"
; http://home.earthlink.net/~tdickens/68hc11/random/68hc11random.html
mov cx, 320
xchg bp, ax ; Fetch the seed from bp.
bottomrow:
imul ax, 181
add ax, 359
xchg al, ah ; It's the high 8 bits that are random.
stosb
xchg ah, al
loop bottomrow
xchg ax, bp ; Store the seed in bp for next time.
; For the next 50 rows, propagate the fire upwards.
mov cx, (320 * 50)
mov si, di
add si, 320 ; si points at the pixel below di.
propagate:
; Add the pixel below, below-left, below-right and two steps below.
xor ax, ax
mov al, [si]
add al, [si - 1]
adc ah, 0
add al, [si + 1]
adc ah, 0
add al, [si + 320]
adc ah, 0
imul ax, 15
shr ax, 6 ; Compute floor(sum * 15 / 64), averaging and cooling.
stosb
dec si
loop propagate
; Mirror some of the fire onto the text.
mov dx, 15 ; Loop count, decrementing.
mov di, (90 * 320) ; Destination pixel.
mov si, (178 * 320) ; Source pixel.
mirrorouter:
mov cx, 320 ; Loop over each pixel in the row.
mirrorinner:
mov al, [di] ; Load destination pixel.
test al, al ; Check if its zero.
lodsb ; Load the source pixel into al.
jnz mirrorwrite ; For non-zero destination pixel, don't zero al.
xor al, al
mirrorwrite:
stosb ; Write al to the destination pixel.
loop mirrorinner
add si, 640 ; Bump si to the row below the one just processed.
dec dx
jnz mirrorouter
; Sleep for one system clock tick (about 1/18.2 s).
xor ax, ax
int 0x1a ; Returns nbr of clock ticks in cx:dx.
mov bx, dx
sleeploop:
xor ax, ax
int 0x1a
cmp dx, bx
je sleeploop
; Copy from the scratch buffer to the framebuffer.
cld
push 0xa000
pop es
mov cx, (320 * (200 - 3) / 2)
xor si, si
mov di, (320 * 3) ; Scroll down three rows to avoid noisy pixels.
rep movsw
; Restore es to point to the scratch buffer.
push ds
pop es
; Check for key press.
mov ah, 1
int 0x16
jz mainloop
done:
; Fetch key from buffer.
xor ah, ah
int 0x16
; Return to mode 3.
mov ax, 0x3
int 0x10
; Exit with code 0.
mov ax, 0x4c00
int 0x21
; Data.
msg: db 'pablomurad.com'
msg_end:
firepal:
db 0, 0, 0, 0, 1, 1, 0, 4, 5, 0, 7, 9
db 0, 8, 11, 0, 9, 12, 15, 6, 8, 25, 4, 4
db 33, 3, 3, 40, 2, 2, 48, 2, 2, 55, 1, 1
db 63, 0, 0, 63, 0, 0, 63, 3, 0, 63, 7, 0
db 63, 10, 0, 63, 13, 0, 63, 16, 0, 63, 20, 0
db 63, 23, 0, 63, 26, 0, 63, 29, 0, 63, 33, 0
db 63, 36, 0, 63, 39, 0, 63, 39, 0, 63, 40, 0
db 63, 40, 0, 63, 41, 0, 63, 42, 0, 63, 42, 0
db 63, 43, 0, 63, 44, 0, 63, 44, 0, 63, 45, 0
db 63, 45, 0, 63, 46, 0, 63, 47, 0, 63, 47, 0
db 63, 48, 0, 63, 49, 0, 63, 49, 0, 63, 50, 0
db 63, 51, 0, 63, 51, 0, 63, 52, 0, 63, 53, 0
db 63, 53, 0, 63, 54, 0, 63, 55, 0, 63, 55, 0
db 63, 56, 0, 63, 57, 0, 63, 57, 0, 63, 58, 0
db 63, 58, 0, 63, 59, 0, 63, 60, 0, 63, 60, 0
db 63, 61, 0, 63, 62, 0, 63, 62, 0, 63, 63, 0
firepal_end:
; For MBR:
;times (510 - ($ - $$)) db 0 ; Pad to 510 bytes
;db 0x55 ; MBR boot signature.
;db 0xaa
|