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 of such 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.