updated at 2021-03-29 by wojtek at bitologia.org (index)
DOS Navigator (DN)
is a successor of NC,
devouring significantly less RAM (only 1056B) in comparison with other file managers
while offering the same general functionality.
DN is shipped with several screen savers (SS) and Tetris!
In fact the SS are just ordinary executable programs
launched when user's activity is idle.
It is enough to rename *.SS to *.EXE and run it to watch simple although attractive visual effects.
Three SS from DN are going to be disassembled. See also another masterpiece from 1993.
Why disassembling? For two reasons. First, if you cannot change something, you do not own it! Each of the presented codes carries something new or nonobvious and it is the perfect source of knowledge. Second, to... reduce the distribution of DN:
RGB.EXE 341 --> RGB.COM --> RGB.SS 286
GLEAM.EXE 1492 --> GLEAM.COM --> GLEAM.SS 919
FIRE.EXE 816 --> FIRE.COM --> FIRE.SS 306
--------------------------------------------
Σ=2649 Σ=1511
* Each software is named just to be easily distinguished.
The simplest one. Actually it is already in the COM format. In DEBUG one readily recognises three subroutines (procedures), main body and three arrays.
Here, and in the forthcoming examples, mouse handling was removed completely, so it responds only for k/b.
; 2021-02-27
; 2021-03-01
; wojtek[at]bitologia.org
; SS from DN
.model small
.code
org 100h
start: mov ax, 0b800h ; text mode only
mov es, ax
mov di, 1
mov cx, 07d0h
mov al, 7
cld
_012b: mov al, es:[di]
mov bl, al
and bl, 0fh
cmp bl, 1
jz _0158
cmp bl, 8
jz _0158
cmp bl, 6
jz _0158
mov bl, al
and bl, 0f0h
cmp bl, 10h
jz _015c
cmp bl, 80h
jz _015c
cmp bl, 60h
jz _015c
jmp short _015e
_0158: and al, 0f0h
jmp short _015e
_015c: and al, 0fh
_015e: and al, 0f7h
stosb
inc di
loop _012b
in al, 60h
mov cs:[_key], al
_0169: mov bx, offset _ah; 0234h
call _020f
mov bx, offset _bl; 023fh
call _020f
mov bx, offset _bh; 023ah
call _020f
xor di, di
call _0226
_0180: mov bx, offset _ah
call _01ed
mov bx, offset _bl
call _01ed
mov bx, offset _bh
call _01ed
mov dx, 03c8h
xor al, al
out dx, al
mov ah, cs:[_ah]; [0234]
mov bl, cs:[_bl]; [023f]
mov bh, cs:[_bh]; [024a]
mov dx, 03dah
_01a7: in al, dx
rcr al, 1
jnb _01a7
mov dx, 03c9h
mov al, ah
out dx, al
mov al, bl
out dx, al
mov al, bh
out dx, al
inc di
cmp di, 0198h
jnz _0180
in al, 60h
test al, 80h
jnz _0169
cmp al, cs:[_key]
jnz _01ec
jmp _0169
_01ec: ret ; ---> DOS
_01ed: xor ah, ah
mov al, [bx + 01]
mov dx, [bx + 03]
sub dx, di
cmp dx, +00
jge _0202
neg dx
cmp dx, ax
jg _020b
_0202: cmp dx, ax
jg _020b
sub al, dl
mov [bx], al
ret
_020b: mov byte ptr [bx], 00
ret
_020f: mov dx, [bx + 03]
add dx, [bx + 05]
cmp dx, [bx + 07]
jle _021f
cmp dx, [bx + 09]
jl _0222
_021f: neg word ptr [bx + 05]
_0222: mov [bx + 03], dx
ret
_0226: mov dx, 03dah
_0229: in al, dx
test al, 08
jz _0229
_022e: in al, dx
rcr al, 1
jb _022e
ret
_ah db 00h, 3fh, 1h, 0cch, 0h, 0ffh, 0ffh, 4ah, 0h, 4eh, 1h
_bl db 00h, 3fh, 1h, 0cch, 0h, 0feh, 0ffh, 4ah, 0h, 4eh, 1h
_bh db 00h, 3fh, 1h, 0cch, 0h, 0fdh, 0ffh, 4ah, 0h, 4eh, 1h
_key db ?
end start
It draws three dispersed horizontal stripes
moving up and down with individual speeds (fifth offset in _ah, _bl or _bh array)
in the background of the text mode. Yes, it is the text mode! Stripes are in red, green and blue
spreading over a distance and eventually fading to black. When overlapping (two or three of them), the colours
are being mixed, eg. r+b = violet or r+g+b = white; in particular one can see any rainbow spectrum for other possible combinations.
As it is drawn in the text mode, the best impression is achieved when the screen holds some printout.
The program is very hardware-sensitive as it utilises specific VGA properties. Thus, to be displayed properly, it requires either
$ dosbox <path> -machine vgaonly
or a genuine VGA (ISA-like) standard device. On other adapters the effect might be limited or even invisible.
A combination of sine waves called "gleam" due to the vivid colour blaze it uses. It is hard to describe the final effect verbally. Somebody might spot a resemblance to a phase image of pendulum which pulses periodically in two orthogonal directions.
EDIT@2022-03-15 – this should be called IRIS, as it allegedly originates from the old DEMO by the same name!
At the first glance, the code structure is slightly complicated because of stack pointers and several "creative" solutions. Anyway, after a while one gets the following listing:
; wojtek[at]bitologia.org
;
; 2021-03-01 disassembling GLEAM.EXE
; 2021-03-02 disassembling GLEAM.EXE
; 2021-03-03 disassembled! GLEAM.COM (919B)
.model small
.code
org 100h
start:
; original fragments with mouse handling:
;
; ....:0000 ...... mov dx, DS_SEGMENT
; mov ds, dx
; mov bx, ss
; sub bx, dx
; shl bx, 1
; shl bx, 1
; shl bx, 1
; shl bx, 1
; cli
; mov ss, dx
; add sp, bx
; sti
; xor ax, ax
; int 33
; or ax, ax
; jz 0033
; cs:
; mov word ptr [0015], 9090 ; NOP NOP
; mov ax, 0003
; int 33
; mov cs:[_cx], cx
; mov cs:[_dx], dx
; ....:0033 FC cld
_0033: cld
mov ax, 13h
int 10h
cli
mov dx, 03c4h
mov ax, 0604h
out dx, ax
mov ax, 0f02h
out dx, ax
mov dx, 03d4h
mov ax, 0014h
out dx, ax
mov ax, 0e317h
out dx, ax
mov al, 9
out dx, al
inc dx
in al, dx
and al, 0e0h
add al, 7
out dx, al
mov dx, 03c8h
mov al, 80h
out dx, al
inc dx
mov cx, 180h
lea si, palette
_0067: lodsb
out dx, al
loop _0067
mov ax, 0a000h
mov es, ax
lea si, sine
_0073: mov dx, 03dah
_0076: in al, dx
test al, 8
jz _0076
_007b: in al, dx
test al, 8
jnz _007b
xor di, di
mov ah, 32h
mov cl, cs:[_40a]
mov ch, cs:[_40b]
_008c: push ax
mov ah, 50h
mov dl, cs:[_408]
mov dh, cs:[_409]
xor bp, bp ; extra line
_0097: mov bx, bp
mov al, bl
xor bh, bh
mov bl, dl
add al, [bx + si]
mov bl, dh
add al, [bx + si]
mov bl, cl
add al, [bx + si]
mov bl, ch
add al, [bx + si]
or al, 80h
stosb
add dl, 1
add dh, 3
dec ah
jnz _0097
add cl, 2
add ch, 1
pop ax
dec ah
jnz _008c
dec bp
mov bx, bp
xor bl, bh
xor bl, [di - 1]
xor bl, cl
xor bl, dl
add bl, ch
add bl, dh
xor bh, bh
mov di, 0280h
test bl, 8
jnz _00eb
and bl, 3
cmp byte ptr [bx + di], 3
jg _00f5
inc byte ptr [bx + di]
jmp short _00f5
_00eb: and bl, 03
cmp byte ptr [bx + di], 0fdh
jl _00f5
_00f3: dec byte ptr [bx + di]
_00f5: mov dl, cs:[_280]
mov dh, cs:[_281]
mov cl, cs:[_282]
mov ch, cs:[_283]
add cs:[_408], dl
sub cs:[_409], dh
add cs:[_40a], cl
sub cs:[_40b], ch
; ....:0115 jmp 012c
; mov ax, 0003
; int 33
; or bx, bx
; jnz 0139
; cmp cx, cs:[_cx]
; jnz 0139
; cmp dx, cs:[_dx]
; jnz 0139
_012c: mov ah, 1
int 16h
jnz _0135
jmp _0073
_0135: xor ah, ah
int 16h
_0139: mov ax, 3
int 10h
xor bh, bh
mov dx, 1700h
mov ah, 2
int 10h
mov ah, 4ch
int 21h
_280 db 2 ; magic constants
_281 db 1
_282 db 3
_283 db 4
_408 db ?; 0a7h ; other magic constants
_409 db ?; 080h
_40a db ?; 03eh
_40b db ?; 018h
include GLEAM_S.inc
include GLEAM_P.inc
end start
and two auxiliary arrays in separate files, one with discretised sine values:
sine db 64,64,64,64,64,64,64,64,63,63,63,63,63,62,62,62
db 62,61,61,61,60,60,59,59,59,58,58,57,57,56,56,55
db 55,54,53,53,52,52,51,50,50,49,48,48,47,46,46,45
db 44,44,43,42,41,41,40,39,38,37,37,36,35,34,34,33
db 32,31,30,30,29,28,27,27,26,25,24,23,23,22,21,20
db 20,19,18,18,17,16,16,15,14,14,13,12,12,11,11,10
db 09,09,08,08,07,07,06,06,05,05,05,04,04,03,03,03
db 02,02,02,02,01,01,01,01,01,00,00,00,00,00,00,00
db 00,00,00,00,00,00,00,00,01,01,01,01,01,02,02,02
db 02,03,03,03,04,04,05,05,05,06,06,07,07,08,08,09
db 09,10,11,11,12,12,13,14,14,15,16,16,17,18,18,19
db 20,20,21,22,23,23,24,25,26,27,27,28,29,30,30,31
db 32,33,34,34,35,36,37,37,38,39,40,41,41,42,43,44
db 44,45,46,46,47,48,48,49,50,50,51,52,52,53,53,54
db 55,55,56,56,57,57,58,58,59,59,59,60,60,61,61,61
db 62,62,62,62,63,63,63,63,63,64,64,64,64,64,64,64
and another one with a custom palette:
palette db 63,00,63,63,02,61,63,04,59,63,06,57,63,08,55,63
db 10,53,63,12,51,63,14,49,63,16,47,63,18,45,63,20
db 43,63,22,41,63,24,39,63,26,37,63,28,35,63,30,33
db 63,32,31,63,34,29,63,36,27,63,38,25,63,40,23,63
db 42,21,63,44,19,63,46,17,63,48,15,63,50,13,63,52
db 11,63,54,09,63,56,07,63,58,05,63,60,03,63,62,01
db 63,63,00,61,63,02,59,63,04,57,63,06,55,63,08,53
db 63,10,51,63,12,49,63,14,47,63,16,45,63,18,43,63
db 20,41,63,22,39,63,24,37,63,25,35,63,28,33,63,30
db 31,63,32,29,63,34,27,63,36,25,63,38,23,63,40,21
db 63,42,19,63,44,17,63,46,15,63,48,13,63,50,11,63
db 52,09,63,54,07,63,56,05,63,58,03,63,60,01,63,62
db 00,63,63,00,61,63,00,59,63,00,57,63,00,55,63,00
db 53,63,00,51,63,00,49,63,00,47,63,00,45,63,00,43
db 63,00,41,63,00,39,63,00,37,63,00,35,63,00,33,63
db 00,31,63,00,29,63,00,27,63,00,25,63,00,23,63,00
db 21,63,00,19,63,00,17,63,00,15,63,00,13,63,00,11
db 63,00,09,63,00,07,63,00,05,63,00,03,63,00,01,63
db 00,00,63,02,00,63,04,00,63,06,00,63,08,00,63,10
db 00,63,12,00,63,14,00,63,16,00,63,18,00,63,20,00
db 63,22,00,63,24,00,63,26,00,63,28,00,63,30,00,63
db 32,00,63,34,00,63,36,00,63,38,00,63,40,00,63,42
db 00,63,44,00,63,46,00,63,48,00,63,50,00,63,52,00
db 63,54,00,63,56,00,63,58,00,63,60,00,63,62,00,63
Again, it is strongly recommended to run it on a genuine VGA, otherwise one gets ugly glitches.
The most obfuscated code. It took me a while of digging to decipher (almost) all subtleties of this one. It looks like it was prepared in a high-level language and then "optimized" by a compiler. There are still some tiny obscured fragments, however they do not affect the entirety of the final form. The original executable 816 (0x330) bytes (including header) read:
| +0 | +1 | +2 | +3 | +4 | +5 | +6 | +7 | +8 | +9 | +a | +b | +c | +d | +e | +f | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 | 4d 5a MZ | 30 | 01 | 02 | 00 | 06 | 00 | 04 | 00 | fc | 0c | fc | ac | 2b | 09 | |
| 0010 | 00 | 40 | 00 | 00 | b7 | 00 | 00 | 00 | 1c | 00 | 00 | 00 | 08 | 00 | 00 | 00 |
| 0020 | 63 | 00 | 00 | 00 | ba | 00 | 00 | 00 | c4 | 00 | 00 | 00 | c9 | 01 | 00 | 00 |
| 0030 | 01 | 00 | 1d | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
| 0040 | 55 @0000: | 89 e5 | 31 c0 | 9a 00 00 1d 00 | a1 02 00 | 8b 1e 04 | ||||||||||
| 0050 | 00 | 89 c1 | 2e f7 26 06 00 cs: ... | d1 e1 | d1 e1 | d1 e1 | 00 cd | |||||||||
| 0060 | 01 ca | 01 da | d1 e3 | d1 e3 | 01 da | 00 de | b1 05 | d3 e3 | ||||||||
| 0070 | 00 de | 05 01 00 | 83 d2 00 | a3 02 00 | 89 16 04 00 | 89 | ||||||||||
| 0080 | e3 | 89 d1 | 36 f7 67 04 ss: .... | 89 c8 | 89 d1 | 36 f7 67 04 ss: .... | 01 | |||||||||
| 0090 | c8 | 83 d2 00 | 89 d0 | c9 leave | c2 02 00 ret 0002 | 55 @005a: | 89 e5 | b8 02 00 | ||||||||
| 00a0 | 9a 00 00 1d 00 | 83 ec 02 | b0 00 | ba c8 03 | ee | 31 c0 | ||||||||||
| 00b0 | 89 46 fe | eb 03 | ff 46 fe | 86 46 fe | 99 | b9 02 00 | f7 | |||||||||
| 00c0 | f9 | ba c9 03 | ee | 6b 46 fe 16 imul ax, [bp - 02], +16 | 99 | b9 80 00 | f7 f9 | ba | ||||||||
| 00d0 | c9 03 | ee | 83 7e fe 08 | 7d 0f | 8b 46 fe | 99 | b9 02 00 | |||||||||
| 00e0 | f7 f9 | ba c9 03 | ee | eb 06 | b0 00 | ba c9 03 | ee | 81 7e | ||||||||
| 00f0 | fe 80 00 | 75 c0 | c9 leave | c3 ret | 9a 00 00 1d 00 [entry point]: call .... | 55 | 89 e5 | 31 | ||||||||
| 0100 | c0 | 9a 00 00 1d 00 call .... | 1e | 07 | bf f2 00 | b9 e0 47 | b8 00 | |||||||||
| 0110 | 00 | fc | f3 | ab | b8 13 00 | cd 10 | 31 c0 | cd 33 | a3 b2 90 | |||||||
| 0120 | 3d ff ff | 75 11 | 68 03 00 mouse ... | cd 33 mouse ... | 89 1e b8 90 mouse ... | 89 0e mouse ... | ||||||||||
| 0130 | b4 90 | 89 16 b6 90 mouse ... | b4 2c | cd 21 | 89 0e 02 00 | 89 16 | ||||||||||
| 0140 | 04 00 | e8 55 ff call 005a | b9 3f 01 | 51 | 6a 04 push +04 | e8 f2 fe call 0000 | 59 | 75 | ||||||||
| 0150 | 1a | 51 | 6a 04 push +04 | e8 e9 fe call 0000 | 59 | bb ff 00 | f7 eb | bb 80 00 | ||||||||
| 0160 | f7 fb | bf 80 8e | 01 cf | 88 95 f2 00 | e2 db | b9 00 46 | ||||||||||
| 0170 | b8 f2 00 | 50 | 89 c6 | bb 72 00 | d1 e3 | 8b 87 0a 00 | 01 | |||||||||
| 0180 | c6 | 4e | 30 e4 | 30 ff | 8a 9c 3f 01 | 02 9c 40 01 | 8a 84 | |||||||||
| 0190 | 41 01 | 02 04 | 01 c3 | c1 eb 02 shr bx, 02 | 74 01 | 4b | 88 1c | 4e | e2 | |||||||
| 01a0 | e5 | bb 38 00 | d1 e3 | 8b 87 0a 00 | 89 c2 | 5e | b8 00 a0 | |||||||||
| 01b0 | 8e c0 | bf 40 6a | 01 d6 | bb 00 00 | d1 e3 | 8b 87 0a 00 | ||||||||||
| 01c0 | 01 c7 | b8 38 00 | b9 a0 00 | f3 a5 | b9 a0 00 | 81 ee 40 | ||||||||||
| 01d0 | 01 | f3 a5 | 48 | 75 ef | 81 3e b2 90 ff ff cmp word ptr [09b2], 0ffffh | 75 17 | b8 03 mouse ... | |||||||||
| 01e0 | 00 | cd 33 mouse ... | 3b 1e b8 90 mouse ... | 75 15 mouse ... | 3b 0e b4 90 mouse ... | 75 0f mouse ... | 3b | |||||||||
| 01f0 | 16 b6 90 mouse ... | 75 09 mouse ... | b4 01 | cd 16 | 75 03 | e9 47 ff | b8 03 | |||||||||
| 0200 | 00 | cd 10 | c9 leave | 31 c0 | 9a 10 00 1d 00 | 00 | 00 | 00 | 00 | 00 | ||||||
| 0210 | ba 1f 00 | 8e da | 8c 06 bc 90 | a0 f0 00 | a2 ba 90 | cb retf | ||||||||||
| 0220 | b8 00 4c mov ax, 4c00h | cd 21 int 21h | cb retf | .. .. | .. .. | .. .. | .. .. | .. .. | ||||||||
| 0230 | .. .. | .. .. | .. .. | 05 84 | .. .. | .. .. ds:[000a] | 40 01 | 80 02 | ||||||||
| 0240 | c0 03 | .. 05 | 40 06 | 80 07 | c0 08 | .. 0a | 40 0b | 80 0c | ||||||||
| 0250 | c0 0d | .. 0f | 40 10 | 80 11 | c0 12 | .. 14 | 40 15 | 80 16 | ||||||||
| 0260 | c0 17 | .. 19 | 40 1a | 80 1b | c0 1c | .. 1e | 40 1f | 80 20 | ||||||||
| 0270 | c0 21 | .. 23 | 40 24 | 80 25 | c0 26 | .. 28 | 40 29 | 80 2a | ||||||||
| 0280 | c0 2b | .. 2d | 40 2e | 80 2f | c0 30 | .. 32 | 40 33 | 80 34 | ||||||||
| 0290 | c0 35 | .. 37 | 40 38 | 80 39 | c0 3a | .. 3c | 40 3d | 80 3e | ||||||||
| 02a0 | c0 3f | .. 41 | 40 42 | 80 43 | c0 44 | .. 46 ds:[007a] | 40 47 | 80 48 | ||||||||
| 02b0 | c0 49 | .. 4b | 40 4c | 80 4d | c0 4e | .. 50 | 40 51 | 80 52 | ||||||||
| 02c0 | c0 53 | .. 55 | 40 56 | 80 57 | c0 58 | .. 5a | 40 5b | 80 5c | ||||||||
| 02d0 | c0 5d | .. 5f | 40 60 | 80 61 | c0 62 | .. 64 | 40 65 | 80 66 | ||||||||
| 02e0 | c0 67 | .. 69 | 40 6a | 80 6b | c0 6c | .. 6e | 40 6f | 80 70 | ||||||||
| 02f0 | c0 71 | .. 73 | 40 74 | 80 75 | c0 76 | .. 78 | 40 79 | 80 7a | ||||||||
| 0300 | c0 7b | .. 7d | 40 7e | 80 7f | c0 80 | .. 82 | 40 83 | 80 84 | ||||||||
| 0310 | c0 85 | .. 87 | 40 88 | 80 89 | c0 8a | .. 8c | 40 8d | 80 8e ds:[00ee] | ||||||||
| 0320 | .. .. | .. .. | .. .. | .. .. | .. .. | .. .. | .. .. | .. .. | ||||||||
To guide the eye, assembly codes are framed and some of them (the crucial ones) are captioned or somehow emphasised (double dots at the end represent double zero words, for simplicity).
There is a little problem with proper interpretation of particular fragments. For some reason original
DEBUG fails at some points and cannot decode everything, eg. 6b 46 fe 16 or c9 c3 or
c1 eb 02. Mixing together
DEBUG, Enhanced DEBUG,
hview 5.13, and step-by-step analysis, makes it possible to rebuild
the whole logical structure.
In order to get pure executable binary format, several things must be done in a different way. The main refactorization concernes the process of all stack references being reorganized:
: push bp mov sp, bp : : leave ≡ mov sp, bp pop bp : : push +04 : ... ss:[bp - 02] : leave ret 0002 :
Then, in three places a "heavy calculation" on bx
is being performed just to lift three "magic constants" out:
: mov bx, 0072h shl bx, 1 mov ax, ds:[bx + 0ah] ; 8e80h at bx=00ah : mov bx, 0038h shl bx, 1 mov ax, ds:[bx + 0ah] ; 4600h at bx=07ah : mov bx, 0000h shl bx, 1 mov ax, ds:[bx + 0ah] ; 0000h at bx=0eeh :
This can be replaced with immediate loading: mov ax, ....h and even further simplfied - see the source below.
These constants are not really so magic, because they are somehow related to the array at the end of the file.
Actually, this array is the only unexplained thing, and most likely it has something to do with initialization of fire seeds.
The constants are just offsets of memory blocks being adequatly rearranged to mimic the process of combustion.
The original flames flow on the screen periodically leftward (once reach the left edge they reappear on the right side).
After disassembling this is no longer the case, as the array is not engaged into calculations anymore.
However, the final effect cannot be simple distinguished from the original one, if at all, and on every run it starts with a diffrent pattern of flames.
; 2021-03-05
; 2021-03-08
; 2021-03-10 disassembled
; 2021-03-11 fixed and simplified
;
; wojtek[at]bitologia.org
.model tiny
.code
.286
org 100h
start:
_00b7: cld
xor ax, ax
mov di, 46f2h
mov cx, 56*320
repz stosw
mov di, 6a40h
mov cx, 56*320
repz stosw
mov ax, 0a000h
mov es, ax
mov ax, 13h
int 10h
_00f6: mov ah, 2ch
int 21h
mov [_0002], cx
mov [_0004], dx
call _005a
_0105: mov cx, 013fh
_0108: push cx
call _0000
pop cx
jnz _012b
push cx
call _0000
pop cx
mov bx, 00ffh
imul bx
mov bx, 0080h
idiv bx
mov di, 8e80h
add di, cx
mov [di + 00f2h], dl
_012b: loop _0108
mov cx, 4600h + 0280h ; + 280h(640d) hide artifacts in two upper lines
mov si, 00f2h + 8e80h - 1
xor ah, ah
xor bh, bh
_0146: mov bl, [si + 013fh]
add bl, [si + 0140h]
mov al, [si + 0141h]
add al, [si]
add bx, ax
shr bx, 2
jz _015c
dec bx
_015c: mov [si], bl
dec si
loop _0146
mov di, 6a40h + 320*3 ; fill three bottom lines
mov si, 00f2h + 4600h
mov ax, 0038h
; (si) 46f2h + (38h x 140h) = 8cf2h
; (di) 6a40h + (38h x 140h) x 2 = f640h
_0185: mov cx, 00a0h
repz movsw
mov cx, 00a0h
sub si, 0140h
repz movsw
dec ax
jnz _0185
_01b5: mov ah, 01
int 16h
jnz _01be
jmp short _0105
_01be: mov ax, 0003
int 10h
ret
;mov ah, 4ch
;int 21h ; ret
_0000: ; fire seeds (sparks)
mov ax, [_0002]
mov bx, [_0004]
mov cx, ax
; mul word ptr ds:[0006]
shl cx, 1
shl cx, 1
shl cx, 1
add ch, cl
add dx, cx
add dx, bx
shl bx, 1
shl bx, 1
add dx, bx
add dh, bl
mov cl, 05
shl bx, cl
add dh, bl
inc ax
adc dx, +00
mov [_0002], ax
mov [_0004], dx
mov cx, dx
mov bx, 0004
mul bx
mov ax, cx
mov cx, dx
mul bx
add ax, cx
adc dx, +00
mov ax, dx
ret
_005a: ; set palette
xor al, al
mov dx, 03c8h
out dx, al
xor ax, ax
mov [index], ax
jmp short _0078
_0075: inc word ptr [index]
_0078: mov ax, [index]
cwd
mov cx, 0002
idiv cx
mov dx, 03c9h
out dx, al
imul ax, [index], +16h
cwd
mov cx, 00ffh ; color of fire
; 0080 = orange (original)
; 00ff = red
; 002a = green
idiv cx
mov dx, 03c9h
out dx, al
cmp word ptr [index], +08
jge _00a8
mov ax, [index]
cwd
mov cx, 0002
idiv cx
mov dx, 03c9h
out dx, al
jmp short _00ae
_00a8: mov al, 00
mov dx, 03c9h
out dx, al
_00ae: cmp word ptr [index], 0080h
jnz _0075
ret
_0002 dw ? ; clock data (for "randomness")
_0004 dw ? ; clock data
_0006 db ?
index dw ?
end start
All codes have been successfully compiled and tested on: DOSBOX and real 80286, 80386, 80486, P133-S, P166MMX and K6-2/350 machines equipped with different standard VGA cards. When run on DOSBOX remember to emulate real VGA:
$ DOSBOX . -machine vgaonly
See also MARS.EXE.