updated at 2021-03-29 by wojtek at bitologia.org (index)


legacy stuff of DN (SS)

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

1. RGB*

* 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.

Fig. 1. Static example #1.
Fig. 2. Static example #2.
Fig. 3. Static example #3.

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.


2. gleam

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.

Fig. 4. Gleam sinusoidal effect.

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.


3. fire

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
00004d 5a
MZ
3001020006000400fc0cfcac2b09
001000400000b70000001c00000008000000
002063000000ba000000c4000000c9010000
003001001d00000000000000000000000000
004055
@0000:
89 e531 c09a 00 00 1d 00a1 02 008b 1e 04
00500089 c12e f7 26 06 00
cs: ...
d1 e1d1 e1d1 e100 cd
006001 ca01 dad1 e3d1 e301 da00 deb1 05d3 e3
007000 de05 01 0083 d2 00a3 02 0089 16 04 0089
0080e389 d136 f7 67 04
ss: ....
89 c889 d136 f7 67 04
ss: ....
01
0090c883 d2 0089 d0c9
leave
c2 02 00
ret 0002
55
@005a:
89 e5b8 02 00
00a09a 00 00 1d 0083 ec 02b0 00ba c8 03ee31 c0
00b089 46 feeb 03ff 46 fe86 46 fe99b9 02 00f7
00c0f9ba c9 03ee6b 46 fe 16
imul ax, [bp - 02], +16
99b9 80 00f7 f9ba
00d0c9 03ee83 7e fe 087d 0f8b 46 fe99b9 02 00
00e0f7 f9ba c9 03eeeb 06b0 00ba c9 03ee81 7e
00f0fe 80 0075 c0c9
leave
c3
ret
9a 00 00 1d 00
[entry point]: call ....
5589 e531
0100c09a 00 00 1d 00
call ....
1e07bf f2 00b9 e0 47b8 00
011000fcf3abb8 13 00cd 1031 c0cd 33a3 b2 90
01203d ff ff75 1168 03 00
mouse ...
cd 33
mouse ...
89 1e b8 90
mouse ...
89 0e
mouse ...
0130b4 9089 16 b6 90
mouse ...
b4 2ccd 2189 0e 02 0089 16
014004 00e8 55 ff
call 005a
b9 3f 01516a 04
push +04
e8 f2 fe
call 0000
5975
01501a516a 04
push +04
e8 e9 fe
call 0000
59bb ff 00f7 ebbb 80 00
0160f7 fbbf 80 8e01 cf88 95 f2 00e2 db
b9 00 46
0170b8 f2 005089 c6bb 72 00d1 e38b 87 0a 0001
0180c64e30 e430 ff8a 9c 3f 0102 9c 40 018a 84
019041 0102 0401 c3c1 eb 02
shr bx, 02
74 014b88 1c4ee2
01a0e5bb 38 00d1 e38b 87 0a 0089 c25eb8 00 a0
01b08e c0bf 40 6a01 d6bb 00 00d1 e38b 87 0a 00
01c001 c7b8 38 00b9 a0 00f3 a5b9 a0 0081 ee 40
01d001f3 a54875 ef81 3e b2 90 ff ff
cmp word ptr [09b2], 0ffffh
75 17b8 03
mouse ...
01e000cd 33
mouse ...
3b 1e b8 90
mouse ...
75 15
mouse ...
3b 0e b4 90
mouse ...
75 0f
mouse ...
3b
01f016 b6 90
mouse ...
75 09
mouse ...
b4 01cd 1675 03e9 47 ffb8 03
020000cd 10c9
leave
31 c09a 10 00 1d 000000000000
0210ba 1f 008e da8c 06 bc 90a0 f0 00a2 ba 90cb
retf
0220b8 00 4c
mov ax, 4c00h
cd 21
int 21h
cb
retf
.. .... .... .... .... ..
0230.. .... .... ..05 84.. .... ..
ds:[000a]
40 0180 02
0240c0 03.. 0540 0680 07c0 08.. 0a40 0b80 0c
0250c0 0d.. 0f40 1080 11c0 12.. 1440 1580 16
0260c0 17.. 1940 1a80 1bc0 1c.. 1e40 1f80 20
0270c0 21.. 2340 2480 25c0 26.. 2840 2980 2a
0280c0 2b.. 2d40 2e80 2fc0 30.. 3240 3380 34
0290c0 35.. 3740 3880 39c0 3a.. 3c40 3d80 3e
02a0c0 3f.. 4140 4280 43c0 44.. 46
ds:[007a]
40 4780 48
02b0c0 49.. 4b40 4c80 4dc0 4e.. 5040 5180 52
02c0c0 53.. 5540 5680 57c0 58.. 5a40 5b80 5c
02d0c0 5d.. 5f40 6080 61c0 62.. 6440 6580 66
02e0c0 67.. 6940 6a80 6bc0 6c.. 6e40 6f80 70
02f0c0 71.. 7340 7480 75c0 76.. 7840 7980 7a
0300c0 7b.. 7d40 7e80 7fc0 80.. 8240 8380 84
0310c0 85.. 8740 8880 89c0 8a.. 8c40 8d80 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.

Fig. 5. Fire.

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.