updated at 2021-03-28 by wojtek at bitologia.org (index)
A comprehensive study of the outstanding code example from 1993 - the martian landscape renderer by Tim J. Clarke.
Original code has been disassembled, rewritten and reduced from 5649 bytes to... 1517 bytes! :)
Tim, if you read this, please contact me! I was trying to reach you, but I couldn't...
get raw data with [enhanced] DEBUG:
-u06ca:0000 ; confirm beginning of the code (might be different segment:offset)
-n mars.asm ; file name
-rcx
-ffff ; file size - here entire segment for simplicity
-w0000 ; save data
and then decode binaries with, eg. HVIEW.EXE, but be careful, not all instructions are properly understood!
Actually, it is better to operate in DEBUG all the time.
0000: b8d607 mov ax, 07d6 ; ALL NUMBERS ARE IN BASE-16!
0003: 8ed8 mov dx, ax ; PREFIX 'h' IS INTENTIONALLY SKIPPED
0005: 8ec0 mov es, ax
0007: fc cld
0008: 32e4 xor ah, ah
000a: cd1a int 1a
000c: 80e67f and dh, 7f
000f: 89165d03 mov [035d], dx
0013: b81300 mov ax, 0013
0016: cd10 int 10
0018: 33c0 xor ax, ax
001a: cd33 int 33
001c: 3dffff cmp ax, ffff
001f: 0f94065b03 setz [035b]
0024: be0a02 mov si, 020a
0027: fa cli
0028: bac803 mov dx, 03c8
002b: 32c0 xor al, al
002d: ee out dx, al
002e: 42 inc dx
002f: b90003 mov cx, 0300
0032: f36e rep outsb
0034: fb sti
0035: 8e263d03 mov fs, [033d]
0039: 64c606fff960 mov byte ptr fs:[f9ff], 60 ; ### ### ###
003f: 64c606fef960 mov byte ptr fs:[f9fe], 60 ; # # #
0045: 64c606fdf960 mov byte ptr fs:[f9fd], 60 ; # ## ###
004b: 64c606bdf860 mov byte ptr fs:[f8bd], 60
0051: 64c6067df760 mov byte ptr fs:[f77d], 60
0057: 64c6067ef760 mov byte ptr fs:[f77e], 60
005d: 64c6067ff760 mov byte ptr fs:[f77f], 60
0063: 64c6067bf760 mov byte ptr fs:[f77b], 60
0069: 64c6067af760 mov byte ptr fs:[f77a], 60
006f: 64c60679f760 mov byte ptr fs:[f779], 60
0075: 64c606baf860 mov byte ptr fs:[f8ba], 60
007b: 64c606faf960 mov byte ptr fs:[f9fa], 60
0081: 64c606f9f960 mov byte ptr fs:[f9f9], 60
0087: 64c60677f760 mov byte ptr fs:[f777], 60
008d: 64c60676f760 mov byte ptr fs:[f776], 60
0093: 64c60675f760 mov byte ptr fs:[f775], 60
0099: 64c606b6f860 mov byte ptr fs:[f8b6], 60
009f: 64c606f6f960 mov byte ptr fs:[f9f6], 60
00a5: e84b00 call 00f3
00a8: e8a800 call 0153
00ab: c6065f0300 mov byte ptr [035f], 00
00b0: c7065103e803 mov word ptr [0351], 03e8
00b6: c7065303e803 mov word ptr [0353], 03e8
00bc: e84903 call 0408
00bf: e89703 call 0459
00c2: e85a09 call 0a1f
00c5: beaa07 mov si 07aa
00c8: 8e063d03 mov es, [033d]
00cc: bf2000 mov di, 0020
00cf: b3c8 mov bl, c8
00d1: b94000 mov cx, 0040
00d4: f366a5 rep movsd
00d7: 83c740 add di, 40
00da: fecb dec bl
00dc: 75f3 jne 00d1
00de: 8e064503 mov es, [0345]
00e2: 803e5f0300 cmp byte ptr [035f], 00
00e7: 74d3 je 00bc ; MAIN LOOP
00e9: b80300 mov ax, 0003
00ec: cd10 int 10
00ee: b8004c mov ax, 4c00
00f1: cd21 int 21
================================================================================
00f3: 8e064b03 mov es, [034b]
00f7: 33ff xor di, di
00f9: 66b8ffffffff mov eax, ffffffff
00ff: b90040 mov cx, 4000
0102: f366ab rep stosd
0105: b8ab00 mov ax, 00ab
0108: f7265d03 mul word ptr [035d]
010c: 05cd2b add ax, 2bcd
010f: 83d200 adc dx, 00
0112: f7364d03 div word ptr [034d]
0116: 89165d03 mov [035d], dx
011a: 8bf2 mov si, dx
011c: 26c606000000 mov byte ptr es:[0000], 00
0122: 26c6068000fe mov byte ptr es:[0080], fe
0128: 26c6060080fe mov byte ptr es:[8000], fe
012e: 26c606808000 mov byte ptr es:[8080], 00
0134: 6a00 push 00
0136: 680001 push 0100
0139: e8dd00 call 0219
013c: 83c404 add sp, 04
013f: 33ff xor di, di
0141: 268a05 mov al, es:[di]
0144: c0e803 shr al, 03
0147: 0440 add al, 0040
0149: aa stosb
014a: 0bff or di, di
014c: 75f3 jne 0141
014e: 8e064503 mov es, [0345]
0152: c3 ret ; called from one place
--------------------------------------------------------------------------------
0153: 8e064703 mov es:[0347]
0157: 8e264903 mov fs,[0349]
015b: 33ff xor di, di
015d: 66b8ffffffff mov eax, ffffffff
0163: b90040 mov cx, 4000
0166: f366ab rep stosd
0169: b8ab00 mov ax, 00ab
016c: f7265d03 mul word ptr [035d]
0170: 05cd2b add ax, 2bcd
0173: 83d200 adc dx, 00
0176: f7364d03 div word ptr [034d]
017a: 89165d03 mov [035d], dx
017e: 8bf2 mov si, dx
0180: 26c606000080 mov byte ptr, es:[0000], 0080
0186: 6a00 push 00
0188: 680001 push 0100
018b: e88b00 call 0219
018e: 83c404 add sp, 04
0191: 33f6 xor si, si
0193: 8b3e4f03 mov di, [034f]
0197: c1e704 shl di, 04
019a: 8b9d1f03 mov bx, [di + 031f]
019e: 268a00 mov al, es:[bx + si]
01a1: 32e4 xor ah, ah
01a3: 8b9d2103 mov bx, [di + 0321]
01a7: 260200 add al, es:[bx + si]
01aa: 80d400 adc ah, 00
01ad: 8b9d2303 mov bx, [di + 0323]
01b1: 260200 add al, es:[bx + si]
01b4: 80d400 adc ah, 00
01b7: 8b9d2503 mov bx, [di + 0325]
01bb: 260200 add al, es:[bx + si]
01be: 80d400 adc ah, 00
01c1: c1e802 shr ax, 02
01c4: 268804 mov es:[si], al
01c7: 46 inc si
01c8: 75d0 jne 019a
01ca: 33f6 xor si, si
01cc: 268a04 mov al, es:[si]
01cf: 32e4 xor ah, ah
01d1: 262a4403 sub al, es:[si + 03]
01d5: 80dc00 sbb ah, 00
01d8: 052000 add ax, 0020
01db: 7902 jns 01df
01dd: 33c0 xor ax, ax
01df: 3d3f00 cmp ax, 003f
01e2: 7603 jbe 01e7
01e4: b83f00 mov ax, 003f
01e7: 648804 mov fs:[si], al
01ea: 46 inc si
01eb: 75df jne 01cc
01ed: 33f6 xor si, si
01ef: 268a04 mov al, es:[si]
01f2: 32e4 xor ah, ah
01f4: 26024401 add al, es:[si + 0001]
01f8: 80d400 adc ah, 00
01fb: 2602840001 add al, es:[si + 0100]
0200: 80d400 adc ah, 00
0203: 2602840101 add al, es:[si + 0101]
0208: 80d400 adc ah, 00
020b: c1e802 shr ax, 02
020e: 268804 mov es:[si], al
0211: 46 inc si
0212: 75db jne 01ef
0214: 8e064503 mov es, [0345]
0218: c3 ret ; called from one place
--------------------------------------------------------------------------------
0219: 8bec mov bp, sp ; plasma algorithm
021b: 8b5e04 mov bx, [bp + 04]
021e: 8b4e02 mov cx, [bp + 02]
0221: d1e9 shr cx, 01
0223: 268a17 mov dl, es:[bx]
0226: 02d9 add bl, cl
0228: 8bfb mov di, bx
022a: 02d9 add bl, cl
022c: 26803dff cmp byte ptr es:[di], ff
0230: 7544 jnz 0276
0232: 32f6 xor dh, dh
0234: 260217 add dl, es:[bx]
0237: 80d600 adc dh, 00
023a: d1ea shr dx, 01
023c: 8aea mov ch, dl
023e: b8ab00 mov ax, 00ab
0241: f7e6 mul si
0243: 05cd2b add ax, 2bcd
0246: 83d200 adc dx, 00
0249: f7364d03 div word ptr [034d]
024d: 8bf2 mov si, dx
024f: 81eac267 sub dx, 67c2
0253: 8ac1 mov al, cl
0255: 32e4 xor ah, ah
0257: f7ea imul dx
0259: 8ac4 mov al, ah
025b: 8ae2 mov ah, dl
025d: c1f805 sar ax, 05
0260: 98 cbw
0261: 02c5 add al, ch
0263: 80d400 adc ah, 00
0266: 7809 js 0271
0268: 3dfe00 cmp ax 00fe
026b: 7606 jbe 0273
026d: b0fe mov al, fe
026f: eb02 jmp 0273
0271: 32c0 xor al, al
0273: 268805 mov es:[di], al
0276: 268a17 mov dl, es:[bx]
0279: 02f9 add bh, cl
027b: 8bfb mov di, bx
027d: 02f9 add bh, cl
027f: 26803dff cmp byte ptr, es:[di], 0ff
0283: 7544 jne 02c9
0285: 32f6 xor dh, dh
0287: 260217 add dl, es:[bx]
028a: 80d600 adc dh, 00
028d: d1ea shr dx, 01
028f: 8aea mov ch, dl
0291: b8ab00 mov ax, 00ab
0294: f7e6 mul si
0296: 05cd2b add ax, 2bcd
0299: 83d200 adc dx, 00
029c: f7364d03 div word ptr, [034d]
02a0: 8bf2 mov si, dx
02a2: 81eac267 sub dx, 67c2
02a6: 8ac1 mov al, cl
02a8: 32e4 xor ah, ah
02aa: f7ea imul dx
02ac: 8ac4 mov al, ah
02ae: 8ae2 mov ah, dl
02b0: c1f805 sar ax, 05
02b3: 98 cbw
02b4: 02c5 add al, ch
02b6: 80d400 adc ah, 00
02b9: 7809 js 02c4
02bb: 3dfe00 cmp ax, 00fe
02be: 7606 jbe 02c6
02c0: b0fe mov al, 0fe
02c2: eb02 jmp 02c6
02c4: 32c0 xor al, al
02c6: 268805 mov es:[di], al
02c9: 268a17 mov dl, es:[bx]
02cc: 2ad9 sub bl, cl
02ce: 8bfb mov di, bx
02d0: 2ad9 sub bl, cl
02d2: 26803dff cmp byte ptr es:[di], ff
02d6: 7544 jnz 031c
02d8: 32f6 xor dh, dh
02da: 260217 add dl, es:[bx]
02dd: 80d600 adc dh, 00
02e0: d1ea shr dx, 1
02e2: 8aea mov ch, dl
02e4: b8ab00 mov ax, 00ab
02e7: f7e6 mul si
02e9: 05cd2b add ax, 2bcd
02ec: 83d200 adc dx, 00
02ef: f7364d03 div word ptr [034d]
02f3: 8bf2 mov si, dx
02f5: 81eac267 sub dx, 67c2
02f9: 8ac1 mov al, cl
02fb: 32e4 xor ah, ah
02fd: f7ea imul dx
02ff: 8ac4 mov al, ah
0301: 8ae2 mov ah, dl
0303: c1f805 sar ax, 05
0306: 98 cbw
0307: 02c5 add al, ch
0309: 80d400 adc ah, 00
030c: 7809 js 0317
030e: 3dfe00 cmp ax, 00fe
0311: 7606 jbe 0319
0313: b0fe mov al, fe
0315: eb02 jmp 0319
0317: 32c0 xor al, al
0319: 268805 mov es:[di], al
031c: 268a17 mov dl, es:[bx]
031f: 2af9 sub bh, cl
0321: 8bfb mov di, bx
0323: 2af9 sub bh, cl
0325: 26803dff cmp byte ptr es:[di], ff
0329: 7544 jnz 036f
032b: 32f6 xor dh, dh
032d: 260217 add dl, es:[bx]
0330: 80d600 adc dh, 00
0333: d1ea shr dx, 01
0335: 8aea mov ch, dl
0337: b8ab00 mov ax, 00ab
033a: f7e6 mul si
033c: 05cd2b add ax, 2bcd
033f: 83d200 adc dx, 00
0342: f7364d03 div word ptr [034d]
0346: 8bf2 mov si, dx
0348: 81eac267 sub dx, 67c2
034c: 8ac1 mov al, cl
034e: 32e4 xor ah, ah
0350: f7ea imul dx
0352: 8ac4 mov al, ah
0354: 8ae2 mov ah, dl
0356: c1f805 sar ax, 05
0359: 98 cbw
035a: 02c5 add al, ch
035c: 80d400 adc ah, 00
035f: 7809 js 036a
0361: 3dfe00 cmp ax, 00fe
0364: 7606 jbe 036c
0366: b0fe mov al, fe
0368: eb02 jmp 036c
036a: 32c0 xor al, al
036c: 268805 mov es:[di], al
036f: 268a17 mov dl, es:[bx]
0372: 32f6 xor dh, dh
0374: 02d9 add bl, cl
0376: 02d9 add bl, cl
0378: 260217 add dl, es:[bx]
037b: 80d600 adc dh, 00
037e: 02f9 add bh, cl
0380: 02f9 add bh, cl
0382: 260217 add dl, es:[bx]
0385: 80d600 adc dh, 00
0388: 2ad9 sub bl, cl
038a: 2ad9 sub bl, cl
038c: 260217 add dl, es:[bx]
038f: 80d600 adc dh, 00
0392: c1ea02 shr dx, 02
0395: 8aea mov ch, dl
0397: b8ab00 mov ax, 00ab
039a: f7e6 mul si
039c: 05cd2b add ax, 2bcd
039f: 83d200 adc dx, 00
03a2: f7364d03 div word ptr [034d]
03a6: 8bf2 mov si, dx
03a8: 81eac267 sub dx, 67c2
03ac: 8ac1 mov al, cl
03ae: 32e4 xor ah, ah
03b0: f7ea imul dx
03b2: 8ac4 mov al, ah
03b4: 8ae2 mov ah, dl
03b6: c1f805 sar ax, 05
03b9: 98 cbw
03ba: 02c5 add al, ch
03bc: 80d400 adc ah, 00
03bf: 7809 js 03ca
03c1: d3fe00 cmp ax, 00fe
03c4: 7606 jbe 03cc
03c6: b0fe mov al, fe
03c8: eb02 jmp 03cc
03ca: 32c0 xor al, al
03cc: 02d9 add bl, cl
03ce: 2af9 sub bh, cl
03d0: 268807 mov es:[bx], al
03d3: 80f901 cmp cl, 01
03d6: 742f jz 0407
03d8: 32ed xor ch, ch
03da: 2ad9 sub bl, cl
03dc: 2af9 sub bh, cl
03de: 53 push bx
03df: 51 push cx
03e0: e836fe call 0219 ; self call
03e3: 8bec mov bp, sp
03e5: 8a4e00 mov cl, [bp + 00]
03e8: 004e02 add [bp + 02], cl
03eb: e82bfe call 0219 ; self call
03ee: 8bec mov bp, sp
03f0: 8a4e00 mov cl, [bp + 00]
03f3: 004e03 add [bp + 03], cl
03f6: e820fe call 0219 ; self call
03f9: 8bec mov bp, sp
03fb: 8a4e00 mov cl, [bp + 00]
03fe: 284e02 sub [bp + 02], cl
0401: e815fe call 0219 ; self call
0404: 83c404 add sp, 04 ; stack adjustment
0407: c3 ret ; called from many places including itself (recursion)
--------------------------------------------------------------------------------
0408: 33c9 xor cx, cx
040a: 33d2 xor dx, dx
040c: 33c0 xor ax, ax
040e: 803e5b0300 cmp byte ptr [035b], 00
0413: 740e jz 0423
0415: b80b00 mov ax, 000b
0418: cd33 int 33
041a: 51 push cx
041b: 52 push dx
041c: b80500 mov ax, 0005
041f: cd33 int 33
0421: 5a pop dx
0422: 59 pop cx
0423: 010e5103 add [0351], cx
0427: 29165303 sub [0353], dx
042b: 8b0e5103 mov cx, [0351]
042f: 8b165303 mov dx, [0353]
0433: 890e5503 mov [0355], cx
0437: 89165703 mov [0357], dx
043b: e81e0c call 105c
043e: 80c419 add ah, 19
0441: 7303 jae 0446
0443: b8ffff mov ax, ffff
0446: a35903 mov [0359], ax
0449: b401 mov ah, 01
044b: cd16 int 16
044d: 7409 jz 0458
044f: c6065f0301 mov byte ptr [035f], 01
0454: 32e4 xor ah, ah
0456: cd16 int 16
0458: c3 ret ; called from one place
--------------------------------------------------------------------------------
0459: bfaa07 mov di, 07aa
045c: 66b963000000 mov ecx, 00000063
0462: 6633c0 xor eax, eax
0465: a15903 mov ax, [0359]
0468: f7d8 neg ax
046a: c1e803 shr ax, 03
046d: 050040 add ax, 4000
0470: 66c1e00d shl eax, 0d
0474: 66a36003 mov [0360], eax
0478: 6633c0 xor eax, eax
047b: a15503 mov ax, [0355]
047e: 66c1e009 shl eax, 09
0482: 66a36403 mov [0364], eax
0486: 6633c0 xor eax, eax
0489: a15703 mov ax, [0357]
048c: 66c1e009 shl eax, 09
0490: 66a36803 mov [0368], eax
0494: 1e push ds
0495: 8e2e4503 mov gs, [0345]
0499: 8e1e4b03 mov dx, [034b]
049d: 6665a16003 mov eax, gs:[0360]
04a2: 6633d2 xor edx, edx
04a5: 66f7f1 div ecx
04a8: 66658b366403 mov esi, gs:[0364]
04ae: 66658b2e6803 mov ebp, gs:[0368]
04b4: 662bf0 sub esi, eax
04b7: 6603e8 add ebp, eax
04ba: 66c1e807 shr eax, 07
04be: 8bde mov bx, si
04c0: 66c1ee10 shr esi, 10
04c4: 81e6ff00 and si, 00ff
04c8: 66c1ed08 shr ebp, 08
04cc: 81e500ff and bp, ff00
04d0: 0bf5 or si, bp
04d2: 668be8 mov ebp, eax
04d5: 66c1ed10 shr ebp, 10
04d9: 4d dec bp
04da: a4 movsb ; #0001
04db: 03d8 add bx, ax
04dd: 13f5 adc si, bp
04df: a4 movsb ; #0002
04e0: 03d8 add bx, ax
04e2: 13f5 adc si, bp
:
:
:
09d0: a4 movsb ; #00ff
09d1: 03d8 add bx, ax
09d3: 13f5 adc si, bp
09d5: a4 movsb ; #0100
09d6: fec9 dec cl
09d8: 0f85c1fa jnz 049d
09dc: 1f pop ds
09dd: 66b850505050 mov eax, 50505050
09e3: b94000 mov cx, 0040
09e6: f366ab rep stosd
09e9: 8b365903 mov si, [0359]
09ed: d1ee shr si, 01
09ef: 83c60a add si, 0a
09f2: bb0400 mov bx, 0004
09f5: 8bc6 mov ax, si
09f7: 33d2 xor dx, dx
09f9: f7f3 div bx
09fb: c1e807 shr ax, 07
09fe: 3d3f00 cmp ax, 003f
0a01: 7602 jbe 0a05
0a03: b03f mov al, 3f
0a05: 8ae0 mov ah, al
0a07: 8ad0 mov dl, al
0a09: 66c1e010 shl eax, 10
0a0d: 8ac2 mov al, dl
0a0f: 8ae0 mov ah, al
0a11: b94000 mov cx, 0040
0a15: f366ab rep stosd
0a17: fec3 inc bl
0a19: 80fb2c cmp bl, 2c
0a1c: 75d7 jnz 09f5
0a1e: c3 ret ; called from one place
--------------------------------------------------------------------------------
0a1f: 8e264703 mov fs, [0347]
0a23: 8e2e4903 mov gs, [0349]
0a27: 66b8007d007d mov eax, 7d007d00
0a2d: bfaa03 mov di, 03aa
0a30: b98000 mov cx, 0080
0a33: f366ab rep stosd
0a36: 6633c0 xor eax, eax
0a39: bfaa05 mov di, 05aa
0a3c: b98000 mov cx, 0080
0a3f: f366ab rep stosd
0a42: c706a0037800 mov word ptr [03a0], 0078
0a48: 8b36a003 mov si, [03a0]
0a4c: 8bb49001 mov si, [si + 0190]
0a50: c1e604 shl si, 04
0a53: a15703 mov ax, [0357]
0a56: 250f00 and ax, 000f
0a59: 340f xor al, 0f
0a5b: 03f0 add si, ax
0a5d: a15903 mov ax, [0359]
0a60: 33d2 xor dx, dx
0a62: f7f6 div si
0a64: 056400 add ax, 0064
0a67: a3a203 mov [03a2], ax
0a6a: 6633c0 xor eax, eax
0a6d: 8bc6 mov ax, si
0a6f: 66c1e006 shl eax, 06
0a73: 66a3a603 mov [03a6], eax
0a77: 833ea00302 cmp word ptr [03a0], 02
0a7c: 750e jne 0a8c
0a7e: c706a203007d mov word ptr [03a2], 7d00
0a84: c706a4030000 mov word ptr [03a4], 0000
0a8a: eb0a jmp 0a96
0a8c: 33c0 xor ax, ax
0a8e: ba0100 mov dx, 0001
0a91: f7f6 div si
0a93: a3a403 mov [03a4], ax
0a96: 6633c9 xor ecx, ecx
0a99: 8b0e5503 mov cx, [0355]
0a9d: 66c1e10c shl ecx, 0ch
0aa1: 66a1a603 mov eax, [03a6]
0aa5: 66c1e007 shl eax, 07
0aa9: 662bc8 sub ecx, eax
0aac: 8b165703 mov dx, [0357]
0ab0: c1e204 shl dx, 04
0ab3: 668bd9 mov ebx, ecx
0ab6: 66c1eb10 shr ebx, 10h
0aba: 8afe mov bh, dh
0abc: 8bc6 mov ax, si
0abe: c1e804 shr ax, 04
0ac1: 02f8 add bh, al
0ac3: d1e9 shr cx, 01
0ac5: befe01 mov si, 01fe
0ac8: c7066403aa07 mov word ptr [0364], 07aa
0ace: d1e1 shl cx, 01
0ad0: 030ea603 add cx, [03a6]
0ad4: 121ea803 adc bl, [03a8]
0ad8: d1e9 shr cx, 01
0ada: 648a4701 mov al, fs:[bx + 01]
0ade: 32e4 xor ah, ah
0ae0: 642a07 sub al, fs:[bx]
0ae3: 80dc00 sbb ah, 00
0ae6: f7e9 imul cx
0ae8: 0facd007 shrd ax, dx, 07
0aec: 640227 add ah, fs:[bx]
0aef: f726a403 mul word ptr [03a4]
0af3: 8b3ea203 mov di, [03a2]
0af7: 2bfa sub di, dx
0af9: 7903 jns 0afe
0afb: bfffff mov di, ffff
0afe: 81ffc800 cmp di, 00c8
0b02: 7c03 jl 0b07
0b04: bfc700 mov di, 00c7
0b07: 8bacaa03 mov bp, [si + 03aa]
0b0b: 89bcaa03 mov [si + 03aa], di
0b0f: 2bef sub bp, di
0b11: 0f890505 jns 101a
0b15: c1e708 shl di, 08
0b18: 033e6403 add di, [0364]
0b1c: 658a4701 mov al, gs:[bx + 01]
0b20: 652a07 sub al, gs:[bx]
0b23: f6ed imul ch
0b25: d1e0 shl ax, 01
0b27: 650227 add ah, gs:[bx]
0b2a: 8bd0 mov dx, ax
0b2c: 8784aa05 xchg ax, [si + 05aa]
0b30: 50 push ax
0b31: 2bc2 sub ax, dx
0b33: 99 cwd
0b34: f7fd idiv bp
0b36: 5a pop dx
0b37: d1e5 shl bp, 1
0b39: 3effa69001 jmp word ptr ds:[bp + 0190]
0b3e: 88b50039 mov [di + 03900h], dh
0b42: 03d0 add dx, ax
0b44: 88b5003a mov [di + 03a00h], dh
0b48: 03d0 add dx, ax
:
:
:
0f86: 03d0 add dx, ax
0f88: 88b500f0 mov [di + 0f000h], dh
0f8c: 03d0 add dx, ax
0f8e: 88b500f1 mov [di + 0f100h], dh
0f92: 03d0 add dx, ax
0f94: 88b500f2 mov [di + 0f200h], dh
0f98: 03d0 add dx, ax
0f9a: 88b500f3 mov [di + 0f300h], dh
0f9e: 03d0 add dx, ax
0fa0: 88b500f4 mov [di + 0f400h], dh
0fa4: 03d0 add dx, ax
0fa6: 88b500f5 mov [di + 0f500h], dh
0faa: 03d0 add dx, ax
0fac: 88b500f6 mov [di + 0f600h], dh
0fb0: 03d0 add dx, ax
0fb2: 88b500f7 mov [di + 0f700h], dh
0fb6: 03d0 add dx, ax
0fb8: 88b500f8 mov [di + 0f800h], dh
0fbc: 03d0 add dx, ax
0fbe: 88b500f9 mov [di + 0f900h], dh
0fc2: 03d0 add dx, ax
0fc4: 88b500fa mov [di + 0fa00h], dh
0fc8: 03d0 add dx, ax
0fca: 88b500fb mov [di + 0fb00h], dh
0fce: 03d0 add dx, ax
0fd0: 88b500fc mov [di + 0fc00h], dh
0fd4: 03d0 add dx, ax
0fd6: 88b500fd mov [di + 0fd00h], dh
0fda: 03d0 add dx, ax
0fdc: 88b500fe mov [di + 0fe00h], dh
0fe0: 03d0 add dx, ax
0fe2: 88b500ff mov [di + 0ff00h], dh
0fe6: 03d0 add dx, ax
0fe8: 8835 mov [di], dh
0fea: ff066403 inc word ptr [0364]
0fee: 83ee02 sub si, 02
0ff1: 0f89d9fa jns 0ace
0ff5: 832ea00302 sub word ptr [03a0], 02
0ffa: 8b36a003 mov si, [03a0]
0ffe: 8bb49001 mov si, [si + 0190]
1002: f7c60300 test si, 0003
1006: 7508 jnz 1010
1008: c1ee02 shr si, 02
100b: 83fe0f cmp si, 0fh
100e: 7700 ja 1010
1010: 833ea00300 cmp word ptr [03a0], 00
1015: 0f852ffa jnz 0a48
1019: c3 ret ; called from one place
--------------------------------------------------------------------------------
101a: 658a4701 mov al, gs:[bx + 01]
101e: 652a07 sub al, gs:[bx]
1021: f6ed imul ch
1023: d1e0 shl ax, 01
1025: 650227 add ah, gs:[bx]
1028: 8984aa05 mov [si + 05aa], ax
102c: ff066403 inc word ptr [0364]
1030: 83ee02 sub si, 02
1033: 0f8997fa jns 0ace
1037: 832ea00302 sub word ptr [03a0], 02
103c: 8b36a003 mov si, [03a0]
1040: 8bb49001 mov si, [si + 0190]
1044: f7c60300 test si, 0003
1048: 7508 jnz 1052
104a: c1ee02 shr si, 02
104d: 83fe0f cmp si, 0f
1050: 7700 ja 1052
1052: 833ea00300 cmp word ptr [03a0], 00
1057: 0f85edf9 jnz 0a48
105b: c3 ret ; called from one place
--------------------------------------------------------------------------------
105c: 8e264703 mov fs, [0347]
1060: c1c904 ror cx, 04
1063: c1ca04 ror dx, 04
1066: 8ad9 mov bl, cl
1068: 8afa mov bh, dl
106a: c1e90c shr cx, 0c
106d: c1ea0c shr dx, 0c
1070: fec3 inc bl
1072: 648a07 mov al, fs:[bx]
1075: 32e4 xor ah, ah
1077: fecb dec bl
1079: 642a07 sub al, fs:[bx]
107c: 80dc00 sbb ah, 00
107f: 52 push dx
1080: f7e9 imul cx
1082: 648a17 mov dl, fs:[bx]
1085: 32f6 xor dh, dh
1087: c1e204 shl dx, 04
108a: 03c2 add ax, dx
108c: 5a pop dx
108d: 8bf0 mov si, ax
108f: fec7 inc bh
1091: fec3 inc bl
1093: 648a07 mov al, fs:[bx]
1096: 32e4 xor ah, ah
1098: fecb dec bl
109a: 642a07 sub al, fs:[bx]
109d: 80dc00 sbb ah, 00
10a0: 52 push dx
10a1: f7e9 imul cx
10a3: 648a17 mov dl, fs:[bx]
10a6: 32f6 xor dh, dh
10a8: c1e204 shl dx, 04
10ab: 03c2 add ax, dx
10ad: 5a pop dx
10ae: 8bf8 mov di, ax
10b0: 8bc7 mov ax, di
10b2: 2bc6 sub ax, si
10b4: f7ea imul dx
10b6: c1e604 shl si, 04
10b9: 03c6 add ax, si
10bb: c3 ret ; called from one place
+0 +1 +2 +3 +4 +5 +6 +7|+8 +9 +a +b +c +d +e +f
-----------------------------+-----------------------
07d6:0000: 3e 0b 44 0b 4a 0b 50 0b|56 0b 5c 0b 62 0b 68 0b : "jump" offsets #1 (Δ = 6)
: 0010: 6e 0b 74 0b 7a 0b 80 0b|86 0b 8c 0b 92 0b 98 0b
0020: 9e 0b a4 0b aa 0b b0 0b|b6 0b bc 0b c2 0b c8 0b
0030: ce 0b d4 0b da 0b e0 0b|e6 0b ec 0b f2 0b f8 0b
0040: fe 0b 04 0c 0a 0c 10 0c|16 0c 1c 0c 22 0c 28 0c
0050: 2e 0c 34 0c 3a 0c 40 0c|46 0c 4c 0c 52 0c 58 0c
0060: 5e 0c 64 0c 6a 0c 70 0c|76 0c 7c 0c 82 0c 88 0c
0070: 8e 0c 94 0c 9a 0c a0 0c|a6 0c ac 0c b2 0c b8 0c
0080: be 0c c4 0c ca 0c d0 0c|d6 0c dc 0c e2 0c e8 0c
0090: ee 0c f4 0c fa 0c 00 0d|06 0d 0c 0d 12 0d 18 0d
00a0: 1e 0d 24 0d 2a 0d 30 0d|36 0d 3c 0d 42 0d 48 0d
00b0: 4e 0d 54 0d 5a 0d 60 0d|66 0d 6c 0d 72 0d 78 0d
00c0: 7e 0d 84 0d 8a 0d 90 0d|96 0d 9c 0d a2 0d a8 0d
00d0: ae 0d b4 0d ba 0d c0 0d|c6 0d cc 0d d2 0d d8 0d
00e0: de 0d e4 0d ea 0d f0 0d|f6 0d fc 0d 02 0e 08 0e
00f0: 0e 0e 14 0e 1a 0e 20 0e|26 0e 2c 0e 32 0e 38 0e
0100: 3e 0e 44 0e 4a 0e 50 0e|56 0e 5c 0e 62 0e 68 0e
0110: 6e 0e 74 0e 7a 0e 80 0e|86 0e 8c 0e 92 0e 98 0e
0120: 9e 0e a4 0e aa 0e b0 0e|b6 0e bc 0e c2 0e c8 0e
0130: ce 0e d4 0e da 0e e0 0e|e6 0e ec 0e f2 0e f8 0e
0140: fe 0e 04 0f 0a 0f 10 0f|16 0f 1c 0f 22 0f 28 0f
0150: 2e 0f 34 0f 3a 0f 40 0f|46 0f 4c 0f 52 0f 58 0f
0160: 5e 0f 64 0f 6a 0f 70 0f|76 0f 7c 0f 82 0f 88 0f
0170: 8e 0f 94 0f 9a 0f a0 0f|a6 0f ac 0f b2 0f b7 0f
0180: be 0f c4 0f ca 0f d0 0f|d6 0f dc 0f e2 0f e8 0f
: -- -- -- -- -- -- -- --|-- -- -- -- -- -- -- --
07d6:0190: 00 00 01 00 02 00 03 00|04 00 05 00 06 00 07 00 : "jump" offsets #2
: 01a0: 08 00 09 00 0a 00 0b 00|0c 00 0d 00 0e 00 0f 00
01b0: 10 00 11 00 12 00 13 00|14 00 15 00 16 00 17 00
01c0: 18 00 19 00 1a 00 1b 00|1c 00 1d 00 1e 00 1f 00
01d0: 20 00 21 00 22 00 23 00|24 00 25 00 26 00 27 00
01e0: 28 00 2a 00 2c 00 2e 00|30 00 32 00 34 00 36 00
01f0: 38 00 3a 00 3c 00 40 00|44 00 48 00 4c 00 50 00
: 0200: 54 00 58 00 5c 00 60 00|64 00 -- -- -- -- -- --
07d6:020a: -- -- -- -- -- -- -- --|-- -- 00 00 00 01 00 00 : palette
: 0210: 02 00 00 03 00 00 03 01|00 04 00 00 05 00 00 06 ; <------ 01?!
0220: 00 00 07 00 00 08 00 00|09 00 00 0a 00 00 0b 00
0230: 00 0c 00 00 0d 00 00 0e|00 00 0f 00 00 10 00 00
0240: 11 00 00 12 00 00 13 00|00 14 00 00 15 00 00 16
0250: 00 00 17 00 00 18 00 00|19 00 00 1a 00 00 1b 00
0260: 00 1c 00 00 1d 01 00 1e|02 00 1f 03 00 20 04 00
0270: 21 05 00 22 06 00 23 07|01 24 08 02 25 09 03 26
0280: 0a 04 27 0b 05 28 0c 06|29 0d 07 2a 0e 08 2b 0f
0290: 09 2c 10 0a 2d 11 0b 2e|12 0c 2f 13 0d 30 14 0e
02a0: 31 15 0f 32 16 10 33 17|11 34 18 12 35 19 13 36
02b0: 1a 14 37 1b 15 38 1c 16|39 1d 17 3a 1e 18 3b 1f
02c0: 19 3c 20 1a 3d 21 1b 3e|22 1c 32 0a 0a 32 0b 0b
02d0: 32 0c 0c 32 0d 0d 32 0e|0e 32 0f 0f 32 10 10 32
02e0: 11 11 32 12 12 32 13 13|32 14 14 32 15 15 32 16
02f0: 16 32 17 17 32 18 18 32|19 19 32 1a 1a 32 1b 1b
0300: 32 1c 1c 32 1d 1d 32 1e|1e 32 1f 1f 32 20 20 32
0310: 21 21 32 22 22 32 23 23|32 24 24 32 25 25 32 26
0320: 26 32 27 27 32 28 28 32|29 29 -- -- -- -- -- --
: 032a -- -- -- -- -- -- -- --|-- -- 3f 3f 3f 9d 30 00 : data
07d6:0330: 00 04 00 02 02 ff fe 00|00 00 00 00 00 00 a0 00
07d6:0340: 00 40 00 ca 06 d6 07 d1|14 d1 24 d1 34 85 cf 01
07d6:0350: 00 e8 03 e8 03 e8 03 e8|03 00 00 01 00 27 b7 00
07d6:0360: 00 00 d4 0a aa 08 07 00|00 d0 07 00 00 00 00 00
07d6:0370: | : these
07d6:0380: | : three
07d6:0390: | : paragraphs are apparently unused...
07d6:03a0: ** ** ** ** ** ** ** **|** ** -- -- -- -- -- --
07d6:03aa: -- -- -- -- -- -- -- --|-- -- ** ** ** ** ** ** : data
: : |
07d6:05aa: -- -- -- -- -- -- -- --|-- -- ** ** ** ** ** ** : data
: : |
07d6:07aa: -- -- -- -- -- -- -- --|-- -- ** ** ** ** ** ** : data
: : |
in particular (little endian)
ds:[032f/w] = 0000 ; constant value
ds:[0331/w] = 0004 ; constant value
ds:[0333/w] = 0202 ; constant value
ds:[0335/w] = feff ; constant value
ds:[034f/w] = 0001 ; constant value
ds:[033d/w] = a000 ; constant VGA address
ds:[0345/w] = 07d6 ; offset of generated landscape view
ds:[0347/w] = 14d1 ; offset of aux. map
ds:[0349/w] = 24d1 ; offset of terra - lower half of the view
ds:[034b/w] = 34d1 ; offset of cloudy sky - upper half of the view
ds:[034d/w] = cf85 ; constant value
this parameter is roughly responsible for the camera elevation
ds:[035d/w] = .... ; random value from "int 1a"
ds:[0355/w] = .... ; mouse state
ds:[035f/b] = .... ; k/b state
ds:[0360/d] = .... ; address recalculation variables
ds:[0364/d] = ....
ds:[0368/d] = ....
ds:[03a0/d] = .... ; address recalculation variables
ds:[03a2/d] = ....
ds:[03a4/d] = ....
ds:[03a6/d] = ds:[03a6/w] + ds:[03a8/w]
and some others which are not so crucial. It seems, only seven cells hold constant values:
[032f-0335], [034f], [033d/w] and [034d/w], others
are run-time dependent.
Offsets at 03aa, 05aa and 07aa are of special use, see the code.
The flow is quite easy and well organised. There are five main procedures. Two initial:
00a5: e84b00 call 00f3 ; prepare cloudy sky
00a8: e8a800 call 0153 ; prepare martian terrain
and three others in the main loop:
00bc: e84903 call 0408 ; mouse handling
00bf: e89703 call 0459 ; refresh (recalculate) sky (background)
00c2: e85a09 call 0a1f ; refresh (recalculate) terra
The following snippet
-a00ab ....:00AB mov es, [033d] ....:00AF mov ds, [034b] ....:00B3 xor di, di ....:00B5 mov si, 07aa ....:00B8 mov cx, 0100 ....:00BB rep movsb ....:00BD add di, 40 ....:00C0 cmp di, fe00 ....:00C4 jbe 00b8 ....:00C6 in al, 60 ....:00C8 cmp al, 1 ....:00CA jne 00c6 ....:00CC mov ax,03 ....:00CF int 10 ....:00D1 mov ah, 4c ....:00D3 int 21 ....:00D5 -g
injected after the second call, here at 00AB, retrieves the sky;
(the image is not centered)
If the address [034b] in the second line (at 00AF)
is replaced by [0349], another familiar picture appears:
Recall, that [034b] and
[0349] are offsets for the sky and terra, respectively.
By the way, this is the original colour's gamut:
Once there was a blue sky... :)
Now, all the "magic" is to divide the window 256 × 200 onto two parts. The upper one for the projection of the sky and the lower one for the 3-D-like simulation of the terra by means of voxel graphics. Using mouse, one can wander on the Martian mountains under the reddish sky.
Tim Clarke, whose 18-pixels-initials TJC can be seen in the original screen at the bottom-right corner, describes
the project in his words:
Martian terrain renderer
------------------------
Here is a small demo to draw fractal voxel-based terrains in real time...
If you have a 386 or better with VGA graphics, run mars and use the mouse to
move around the landscape. Press any key to quit. A different map is calculated
each time the program is run. This code may form the basis of a forthcoming
game...
taken from: http://archive.gamedev.net/archive/reference/articles/article655.html at 2021-03-24
Voxel landscapes and How I did it
---------------------------------
This document describes the method I used in my demo of a Martian terrain,
which can be found at garbo.uwasa.fi:/pc/demo/mars10.zip.
It's similar to a floating horizon hidden line removal algorithm, so you'll
find discussion of the salient points in many computer graphics books. The
difference is the vertical line interpolation.
First, some general points:
---------------------------
The map is a 256x256 grid of points, each having and 8-bit integer height
and a colour. The map wraps round such that, calling w(u,v) the height at
(u,v), then w(0,0)=w(256,0)=w(0,256)=w(256,256). w(1,1)=w(257,257), etc.
Map co-ords: (u,v) co-ordinates that describe a position on the map. The
map can be thought of as a height function w=f(u,v) sampled discretely.
Screen co-ords: (x,y) co-ordinates for a pixel on the screen.
To generate the map:
--------------------
This is a recursive subdivision, or plasma, fractal. You start of with
a random height at (0,0) and therefore also at (256,0), (0,256), (256,256).
Call a routine that takes as input the size and position of a square, in the
first case the entire map.
This routine get the heights from the corners of the square it gets given.
Across each edge (if the map has not been written to at the point halfway
along that edge), it takes the average of the heights of the 2 corners on that
edge, applies some noise proportional to the length of the edge, and writes
the result into the map at a position halfway along the edge. The centre of
the square is the average of the four corners+noise.
The routine then calls itself recursively, splitting each square into four
quadrants, calling itself for each quadrant until the length of the side is
2 pixels.
This is probably old-hat to many people, but the map is made more realistic
by blurring:
w(u,v)=k1*w(u,v)+k2*w(u+3,v-2)+k3*w(u-2,v+4) or something.
Choose k1,k2,k3 such that k1+k2+k3=1. The points at which the map is sampled
for the blurring filter do not really matter - they give different effects,
and you don't need any theoretical reason to choose one lot as long as it
looks good. Of course do everything in fixed point integer arithmetic.
The colours are done so that the sun is on the horizon to the East:
Colour=A*[ w(u+1,v)-w(u,v) ]+B
with A and B chosen so that the full range of the palette is used.
The sky is a similar fractal but without the colour transformation.
How to draw each frame
----------------------
First, draw the sky, and blank off about 50 or so scan lines below the
horizon since the routine may not write to all of them (eg. if you are on top
of a high mountain looking onto a flat plane, the plane will not go to the
horizon).
Now, down to business. The screen is as follows:
---------------------------
# #
# #
# Sky #
# #
# #
#a------------------------# Horizon
# #
# # Point (a)=screen co-ords (0,0)
# Ground # x increases horizontally
# # y increases downwards
# #
---------------------------
Imagine the viewpoint is at a position (p,q,r) where (p,q) are the (u,v)
map co-ordinates and r is the altitude. Now, for each horizontal (constant v)
line of map from v=r+100 (say) down to v=r, do this:
1. Calculate the y co-ordinate of map co-ord (p,v,0) (perspective transform)
2. Calculate scale factor f which is how many screen pixels high a mountain
of constant height would be if at distance v from q. Therefore, f is small
for map co-ords far away (v>>r) and gets bigger as v comes down towards r.
3. Work out the map u co-ord corresponding to (0,y). v is constant along
each line.
4. Starting at the calculated (u,v), traverse the screen, incrementing the
x co-ordinate and adding on a constant, c, to u such that (u+c,v) are the map
co-ords corresponding to the screen co-ords (1,y). You then have 256 map
co-ords along a line of constant v. Get the height, w, at each map co-ord and
draw a spot at (x,y-w*f) for all x.
Sorry, but that probably doesn't make much sense. Here's an example:
Imagine sometime in the middle of drawing the frame, everything behind a
point (say v=q+50) will have been drawn:
---------------------------
# #
# #
# #
# **** #
# ********* # <- A mountain half-drawn.
#-----**************------#
#*************************#
#********* *********#
#****** ******#
#.........................# <- The row of dots is at screen co-ord y
# # corresponding to an altitude of 0 for that
--------------------------- particular distance v.
Now the screen-scanning routine will get called for v=q+50. It draws in a
point for every x corresponding to heights at map positions (u,v) where u
goes from p-something to p+something, v constant. The routine would put points
at these positions: (ignoring what was there before)
---------------------------
# #
# #
# #
# #
# #
#-------------------------#
# ***** #
# *** *** #
#******* *******#
#.........................#
# #
---------------------------
So, you can see that the screen gets drawn from the back, one vertical
section after another. In fact, there's more to it than drawing one pixel
at every x during the scan - you need to draw a vertical line between
(x,y old) to (x,y new), so you have to have a buffer containing the y values
for every x that were calculated in the previous pass. You interpolate
along this line (Gouraud style) from the old colour to the new colour also,
so you have to keep a buffer of the colours done in the last pass.
Only draw the vertical lines if they are visible (ie. going down,
y new>y old). The screen is drawn from the back so that objects can be drawn
inbetween drawing each vertical section at the appropriate time.
[...]
Tim Clarke, tjc1005 at hermes.cam.ac.uk
Note that there are: eax, ecx, shrd,
fs:, gs:, ... instructions in the original code
which means it was designed only for .386+. This is in accordance
with what author says: "If you have a 386 or better with VGA graphics, run [MARS.EXE] and use the mouse to
move around the landscape.". This architecture is going to be preserved in the next steps.
1. I'd like to have a MARS.COM
file with all segments equalized to one.
To this end I introduce four blocks of 64k (ffffh) for each image:
cs:[_0345] = 241d0 for the landscape
cs:[_0347] = 341d0 for the auxiliary map
cs:[_0349] = 441d0 for the terrain
cs:[_034b] = 541d0 for the sky
and another one at 641d0 for the stack ss:sp which is extensively used
during the recursive plasma-like algorithm for the sky and terra generation;
see 0219.
2. Eighteen commands from 0039 to 009f drawing the TJC
signature are to be removed (for a moment). For I'd like to reach the smallest possible volume!
3. Some (not all) block operations eg. movsd, stosd, ... on 32-bits e-registers
can be rewritten to 16-bits version.
This slightly slows down the performance, but also reduces the file volume. A trade-off must be chosen.
4. Mouse button is completely unused here, so the lines between 0418
and 0423 shall be dropped immediately.
5. Five constants at [032f-0335/w] and [034f/w] are just hardcoded
for some reason (code obfuscation, or remnants of some general structure from the higher-level code),
so the fragment between
0191 and 01bb can be significantly reduced and optimized.
6. Between 04da and 09d5 there is a long sequence of (256) commands
responsible for the "sky mechanics":
:
movsb
add bx, ax
adc si, bp
:
which can be compressed into a single loop:
:
push cx
mov cx, 00ff
_04df: add bx, ax
adc si, bp
movsb ; caution here! proper values of ds and es must be set!
loop _04df
pop cx
:
7. The last huge improvement is between 0b39
and 0fe8. Without much explanation, one can replace it with:
:
push bx
push ax
push dx
xor dx, dx
mov ax, word ptr ds:[bp + 0190] ; again, watch ds here...
sub ax, 0b3e
mov bx, 0006
div bx
shl ax, 8
add ax, 3900
mov bx, ax
pop dx
pop ax
fill_hills:
mov ds:[di + bx], dh ; ...and here!
add dx, ax
add bx, 0100
cmp bx, 0100 ; actually we must stop at fe00, but we let it overflow to avoid glitches
jne fill_hills
pop bx
:
together with a dynamically generated array of offsets at 0000 and 0190.
Let it be a simple exercise for the reader, what is going on at ds:[0190] and before... :) OK, roughly
speaking, this part of the code performs smooth filling of the hilly martian surface in the lower part of the picture. One
observes that the consecutive addresses:
0b3e ; = j .... 0b44 ; btw, these values can be fished out of "jmp word ptr ds:[bp + 0190]" .... 0b4a ; one readily sees that Δ(bp) = 2 while Δ([bp + 0190]) = 6 :) .... :
correspond to an increasing sequence of offsets:
3900 3a00 3b00 :
that can be expressed in a single and compact formula:
f(j) = offset = 3900 + 0100 * (j - 0b32) / 6
8. I decided to remove original palette and, instead, I generate it dynamically to save additional space. Colours have changed a bit, though, nevertheless it still resembles Mars:
9. There are some other minor optimizations including removal of empty conditions, trivial jumps and code repetition. They are not mentioned here.
Finally, after recalculation of new segments and offsets one obtains:
;
; wojtek[at]bitologia.org
;
; *************************************************
; * MARS.EXE from 1993 by Tim J. Clarke REVISITED *
; *************************************************
;
; -----------------------------------------------------------------------------
; 2021-03-14 playing with MARS_WWP.EXE from the old resources (1995-05-09)
; WWP is an executable files packer
; by Piotr Warężak and Rafał Wierzbicki
; https://www.wwpack32.venti.pl
; -----------------------------------------------------------------------------
; 2021-03-16 1st serious attempt to disassembling original MARS.EXE
; it is also possible to disassemble MARS_WWP, although
; this is really exhausting job
; -----------------------------------------------------------------------------
; 2021-03-19 disassembling MARS.EXE
; 2021-03-20 disassembling MARS.EXE
; 2021-03-21 disassembling MARS.EXE
; 2021-03-22 sky and terra are now correctly generated in 2-D
; problems with the "ladder" before 0fe8h
; sky is smoothly moving when the 5th call (@0a1fh) is off
; -----------------------------------------------------------------------------
; 2021-03-23 to avoid a big mess segments are realigned
; to four 65535 blocks at 24d1, 34d1, 44d1, 54d1
; and one extra for ss at 64d1 (eventually abandoned)
; of course I do not care about RAM allocation
; --> "640K ought to be enough for anybody"
; -----------------------------------------------------------------------------
; 2021-03-24 recovering "missing" data in the "ds" segment
; contour of hills is being drawn
; 2021-03-24 almost done - hills are filled
; althouhgh there are some artifacts in the vicinity of 0b3eh :/
; -----------------------------------------------------------------------------
; 2021-03-25 1st final fix:
; _03a6 dd ?
; _03a8 db ? ; for "adc bl, ..."
; the issue was in "adc" of the lower part of "double-word" variable
; now it is taken directly from the run-time memory
; but there is still a little glitch when drawing highest hills...
; 2021-03-25 2nd final fix:
; no glitches at all! DONE AGAIN AFTER 28 YEARS :)
; (well, the original algorithm is not so perfect either, sometimes
; one can see little anomalies...)
; remember, when under DOSBOX, always use
; $ DOSBOX . -machine vgaonly
; -----------------------------------------------------------------------------
; 2021-03-26 clean code
; data compression
; MARS.COM has 2126 bytes and still can be reduced far below 2.0kB!
; -----------------------------------------------------------------------------
; 2021-03-27 palette compression
; MARS.COM has 1828 bytes and still can be reduced far below 1.5kB!
; 2021-03-27 plasma algorithm compression and other repetitions removed
; MARS.COM has 1517 bytes and still can be reduced below 1.5kB!
; -----------------------------------------------------------------------------
; references:
; https://hornet.org/cgi-bin/scene-search.cgi?search=Tim%20Clarke
; https://www.youtube.com/watch?v=_zSjpIyMt0k
; https://www.shadertoy.com/view/XdsGWH
; helpful links:
; http://www.os2museum.com/wp/who-needs-the-address-wraparound-anyway/
; https://en.wikipedia.org/wiki/X86_memory_segmentation
; https://www.aldeid.com/wiki/X86-assembly/Instructions/or
; https://www.calculator.net/hex-calculator.html?b2dnumber1=20&calctype=b2d&x=0&y=0#hex2decimal
; https://www.csie.ntu.edu.tw/~acpang/course/asm_2004/slides/chapt_07_PartISolve.pdf
; https://stanislavs.org/helppc/int_33-5.html
; https://8086assembly.blogspot.com/2017/11/logical-instructions-and-or-xor-not.html
;
; pictorial ASCII table:
; http://maettig.com/media/dos/system-tools/basic-snippets-power-test-ascii-table.png
;
;
; ------------------------------------------------------------------------------
.model tiny
.code
.386
org 100h
start: ; mov ax, 064d1h ; without stack relocation...
; mov ss, ax
; mov sp, 0400h
mov es, cs:[_0345]
xor di, di
mov ax, 0b3eh ; load data to [_0345]:0000
mov cx, 00c8h ; from 0b3e to 0fe8
_load1: stosw ; see _fill below...
add ax, 0006
loop _load1
xor ax, ax
mov cl, 0029h
_load2: stosw
inc ax
loop _load2
inc ax ; ax = 029h
inc ax ; ax = 02ah
mov cl, 000ah
_load3: stosw
inc ax
inc ax
loop _load3
mov al, 0040h
mov cl, 000ah
_load4: stosw
add al, 04
loop _load4
; cld
xor ah, ah
int 1ah
and dh, 7fh
mov cs:[_035d], dx
mov ax, 0013h
int 10h
xor ax, ax
int 33h
cmp ax, 0ffffh
setz byte ptr cs:[mouse]
; lea si, cs:[palette] ; try -1 or +1 to get green or blue shades
cli
; mov dx, 03c8h ; original palette
; xor al, al
; out dx, al
; inc dx
; mov cx, 0300h
; rep outsb ; [ds:si++] ---> [dx] (cx--)
xor bx, bx ; new shades of terra
xor ax, ax
p1: push ax
mov cl, 0040h
p2: mov dx, 03c8h
out dx, al
inc dx
push ax
mov al, bl
out dx, al
inc bl
mov al, bh
out dx, al
out dx, al
pop ax
inc al
loop p2
pop ax
add bx, 941eh ; new shades of sky
add al, 40h
cmp al, 80h
jne p1
sti
call _00f3 ; prepare cloudy sky
call _0153 ; prepare terrain
mov byte ptr cs:[key_pressed], 00
mov word ptr cs:[_0351], 03e8h
mov word ptr cs:[_0353], 03e8h
_00bc: mov es, cs:[_0345]
call _0408
call _0459
call _0a1f
mov si, 07aah
mov ax, 0a000h
mov es, ax
mov di, 0020h
mov bl, 0c8h
push ds
mov ds, cs:[_0345]
_00d1: mov cx, 0040h
rep movsd
add di, 40h
dec bl
jne short _00d1
pop ds
cmp byte ptr cs:[key_pressed], 00
je short _00bc
mov ax, 0003
int 10h
mov ah, 4ch
int 21h
;-------------------------------------------------------------------------------
_00f3: mov es, cs:[_034b]
xor di, di
mov ax, 0ffffh ; clear the sky
mov cx, 8000h
rep stosw
mov ax, 00abh
mul word ptr cs:[_035d]
add ax, 2bcdh
adc dx, +00
div word ptr cs:[_034d]
mov cs:[_035d], dx
mov si, dx
mov byte ptr es:[0000h], 0
mov byte ptr es:[0080h], 0feh
mov byte ptr es:[8000h], 0feh
mov byte ptr es:[8080h], 0
push +00
push 0100h
call _0219
add sp, +04
xor di, di
_0141: mov al, es:[di]
shr al, 03
add al, 40h
stosb ; ax ---> [es:di++] (cx--)
or di, di ; ZF | SF | result
; 0 | 0 | di > 0
; 1 | 0 | di = 0
; 0 | 1 | di < 0
jnz short _0141
ret
;-------------------------------------------------------------------------------
_0153: mov es, cs:[_0347]
mov fs, cs:[_0349]
xor di, di
mov ax, 0ffffh
mov cx, 8000h
rep stosw
mov ax, 00abh
mul word ptr cs:[_035d]
add ax, 2bcdh
adc dx, +00
div word ptr cs:[_034d]
mov cs:[_035d], dx
mov si, dx
mov byte ptr es:[0000], 0080h
push +00
push 0100h
call _0219
add sp, +04
xor si, si
_019a: mov al, es:[si]
xor ah, ah
add al, es:[si+4]
adc ah, 00
add al, es:[si+0202h]
adc ah, 00
add al, es:[si+0feffh]
adc ah, 00
shr ax, 02
mov es:[si], al
inc si
jnz _019a
xor si, si
_01cc: mov al, es:[si]
xor ah, ah
sub al, es:[si + 03]
sbb ah, 00
add ax, 0020h
jns short _01df
xor ax, ax
_01df: cmp ax, 003fh
jbe short _01e7
mov ax, 003fh
_01e7: mov fs:[si], al
inc si
jnz short _01cc
xor si, si
_01ef: mov al, es:[si]
xor ah, ah
add al, es:[si + 01]
adc ah, 00
add al, es:[si + 0100h]
adc ah, 00
add al, es:[si + 0101h]
adc ah, 00
shr ax, 02
mov es:[si], al
inc si
jnz short _01ef
ret
;-------------------------------------------------------------------------------
_0219: mov bp, sp
mov bx, ss:[bp + 04]
mov cx, ss:[bp + 02]
shr cx, 1
mov dl, es:[bx]
add bl, cl
mov di, bx
add bl, cl
call _cr03
add bh, cl
mov di, bx
add bh, cl
call _cr03
sub bl, cl
mov di, bx
sub bl, cl
call _cr03
sub bh, cl
mov di, bx
sub bh, cl
call _cr03
xor dh, dh
add bl, cl
add bl, cl
add dl, es:[bx]
adc dh, 00
add bh, cl
add bh, cl
add dl, es:[bx]
adc dh, 00
sub bl, cl
sub bl, cl
add dl, es:[bx]
adc dh, 00
shr dx, 02
call _cr05
js short _03ca
cmp ax, 00feh
jbe short _03cc
mov al, 0feh
jmp short _03cc
_03ca: xor al, al
_03cc: add bl, cl
sub bh, cl
mov es:[bx], al
cmp cl, 01
jz short _0407
xor ch, ch
sub bl, cl
sub bh, cl
push bx
push cx
call _0219
mov bp, sp
mov cl, ss:[bp + 00]
add ss:[bp + 02], cl
call _0219
mov bp, sp
mov cl, ss:[bp + 00]
add ss:[bp + 03], cl
call _0219
mov bp, sp
mov cl, ss:[bp + 00]
sub ss:[bp + 02], cl
call _0219
add sp, +04
_0407: ret
_cr03: cmp byte ptr es:[di], 0ffh
jnz short _0276
xor dh, dh
add dl, es:[bx]
adc dh, 00
shr dx, 1
call _cr05
js short _0271
cmp ax, 00feh
jbe short _0273
mov al, 0feh
jmp short _0273
_0271: xor al, al
_0273: mov es:[di], al
_0276: mov dl, es:[bx]
ret
_cr05: mov ch, dl
mov ax, 00abh
mul si
add ax, 2bcdh
adc dx, +00
div word ptr cs:[_034d]
mov si, dx
sub dx, 67c2h
mov al, cl
xor ah, ah
imul dx
mov al, ah
mov ah, dl
sar ax, 05
cbw
add al, ch
adc ah, 00
ret
;-------------------------------------------------------------------------------
_0408: cmp byte ptr cs:[mouse], 00
jz short _0423
mov ax, 000bh
int 33h
_0423: add cs:[_0351], cx
sub cs:[_0353], dx
mov cx, cs:[_0351]
mov dx, cs:[_0353]
mov cs:[_0355], cx
mov cs:[_0357], dx
call _105c
add ah, 19h
jae short _0446
mov ax, 0ffffh
_0446: mov cs:[_0359], ax
mov ah, 01
int 16h
jz short _0458
mov byte ptr cs:[key_pressed], 01
xor ah, ah
int 16h
_0458: ret
;-------------------------------------------------------------------------------
_105c: mov fs, cs:[_0347]
ror cx, 04
ror dx, 04
mov bl, cl
mov bh, dl
shr cx, 0ch
shr dx, 0ch
inc bl
mov al, fs:[bx]
xor ah, ah
dec bl
sub al, fs:[bx]
sbb ah, 00
push dx
imul cx
mov dl, fs:[bx]
xor dh, dh
shl dx, 04
add ax, dx
pop dx
mov si, ax
inc bh
inc bl
mov al, fs:[bx]
xor ah, ah
dec bl
sub al, fs:[bx]
sbb ah, 00
push dx
imul cx
mov dl, fs:[bx]
xor dh, dh
shl dx, 04
add ax, dx
pop dx
mov di, ax
mov ax, di
sub ax, si
imul dx
shl si, 04
add ax, si
ret
;-------------------------------------------------------------------------------
_0459: mov di, 07aah
mov ecx, 00000063h
xor eax, eax
mov ax, cs:[_0359]
neg ax
shr ax, 03
add ax, 4000h
shl eax, 0dh
mov cs:[_0360], eax
xor eax, eax
mov ax, cs:[_0355]
shl eax, 09
mov cs:[_0364], eax
xor eax, eax
mov ax, cs:[_0357]
shl eax, 09
mov cs:[_0368], eax
push ds
mov ds, cs:[_034b]
_049d: mov eax, cs:[_0360]
xor edx, edx
div ecx
mov esi, cs:[_0364]
mov ebp, cs:[_0368]
sub esi, eax
add ebp, eax
shr eax, 07
mov bx, si
shr esi, 10h
and si, 00ffh
shr ebp, 08
and bp, 0ff00h
or si, bp
mov ebp, eax
shr ebp, 10h
dec bp
movsb
push cx
mov cx, 00ffh
_04df: add bx, ax
adc si, bp
movsb
loop _04df
pop cx
dec cl
jnz _049d
pop ds
mov ax, 5050h ; this is horizon :)
mov cx, 0080h
rep stosw
mov si, cs:[_0359]
shr si, 1
add si, +0ah
mov bx, 0004
_09f5: mov ax, si
xor dx, dx
div bx
shr ax, 07
cmp ax, 003fh
jbe short _0a05
mov al, 3fh
_0a05: mov ah, al
mov dl, al
shl ax, 10h
mov al, dl
mov ah, al
mov cx, 80h
rep stosw
inc bl
cmp bl, 2ch
jnz _09f5
ret
;-------------------------------------------------------------------------------
_0a1f: mov fs, cs:[_0347]
mov gs, cs:[_0349]
mov eax, 7d007d00h
mov di, 03aah
mov cx, 0080h
rep stosd
xor eax, eax
mov di, 05aah
mov cx, 0080h
rep stosd
mov word ptr cs:[_03a0], 0078h
_0a48: mov si, cs:[_03a0]
mov ds, cs:[_0345]
mov si, ds:[si + 0190h]
shl si, 04
mov ax, cs:[_0357]
and ax, 000fh
xor al, 0fh
add si, ax
mov ax, cs:[_0359]
xor dx, dx
div si
add ax, 0064h
mov cs:[_03a2], ax
xor eax, eax
mov ax, si
shl eax, 06
mov ds:[03a6h], eax
cmp word ptr cs:[_03a0], +02
jnz short _0a8c
mov word ptr cs:[_03a2], 7d00h
mov word ptr cs:[_03a4], 0000
jmp short _0a96
_0a8c: xor ax, ax
mov dx, 0001
div si
mov cs:[_03a4], ax
_0a96: xor ecx, ecx
mov cx, cs:[_0355]
shl ecx, 0ch
mov eax, ds:[03a6h]
shl eax, 07
sub ecx, eax
mov dx, cs:[_0357]
shl dx, 04
mov ebx, ecx
shr ebx, 10h
mov bh, dh
mov ax, si
shr ax, 04
add bh, al
shr cx, 1
mov si, 01feh
mov word ptr cs:[_0364], 07aah
_0ace: shl cx, 1
add cx, ds:[03a6h]
adc bl, ds:[03a8h]
shr cx, 1
mov al, fs:[bx + 01]
xor ah, ah
sub al, fs:[bx]
sbb ah, 00
imul cx
shrd ax, dx, 07
add ah, fs:[bx]
mul word ptr cs:[_03a4]
mov di, cs:[_03a2]
sub di, dx
jns short _0afe
mov di, 0ffffh
_0afe: cmp di, 00c8h
jl short _0b07
mov di, 00c7h
_0b07: mov bp, ds:[si + 03aah]
mov ds:[si + 03aah], di
sub bp, di
jns short _101a
shl di, 08
add di, word ptr cs:[_0364]
call _cr02
mov dx, ax
xchg ax, ds:[si + 05aah]
push ax
sub ax, dx
cwd
idiv bp
pop dx
shl bp, 1
comment #
_0b39: jmp word ptr ds:[bp + 0190h]
_0b3e: mov [di + 03900h], dh
#
push bx
push ax
push dx
xor dx, dx
mov ax, word ptr ds:[bp + 0190h]
sub ax, 0b3eh
mov bx, 0006
div bx
shl ax, 8
add ax, 3900h
mov bx, ax
pop dx
pop ax
_fill: mov ds:[di + bx], dh
add dx, ax
add bx, 0100h
cmp bx, 0100h
jne _fill
pop bx
_0fe8: mov ds:[di], dh
_cr01: inc word ptr cs:[_0364]
sub si,+02
jns _0ace
sub word ptr cs:[_03a0],+02
mov si, cs:[_03a0]
mov si, ds:[si + 0190h]
test si, 0003
jnz short _1010
shr si, 02
_1010: cmp word ptr cs:[_03a0], +00
jnz _0a48
ret
_101a: call _cr02
mov ds:[si + 05aah], ax
jmp short _cr01
_cr02: mov al, gs:[bx + 01]
sub al, gs:[bx]
imul ch
shl ax, 1
add ah, gs:[bx]
ret
;===============================================================================
_0345 dw 024d1h ; offset of landscape
_0347 dw 034d1h ; offset of aux. array
_0349 dw 044d1h ; offset of terra
_034b dw 054d1h ; offset of sky
_034d dw 0cf85h
_0351 dw ?
_0353 dw ?
_0355 dw ?
_0357 dw ?
_0359 dw ?
_035d dw ?
_0360 dd ?
_0364 dd ?
_0368 dd ?
_03a0 dw ?
_03a2 dw ?
_03a4 dw ?
key_pressed db ?
mouse dw ?
comment #
palette db 00h, 00h, 00h ; 1st part
db 01h, 00h, 00h
db 02h, 00h, 00h
db 03h, 00h, 00h
db 03h, 00h, 00h ; 03 _01_ 00 in the original data
db 04h, 00h, 00h
db 05h, 00h, 00h
db 06h, 00h, 00h
db 07h, 00h, 00h
db 08h, 00h, 00h ; 10
db 09h, 00h, 00h
db 0ah, 00h, 00h
db 0bh, 00h, 00h
db 0ch, 00h, 00h
db 0dh, 00h, 00h
db 0eh, 00h, 00h
db 0fh, 00h, 00h
db 10h, 00h, 00h
db 11h, 00h, 00h
db 12h, 00h, 00h ; 20
db 13h, 00h, 00h
db 14h, 00h, 00h
db 15h, 00h, 00h
db 16h, 00h, 00h
db 17h, 00h, 00h
db 18h, 00h, 00h
db 19h, 00h, 00h
db 1ah, 00h, 00h
db 1bh, 00h, 00h
db 1ch, 00h, 00h ; 30
db 1dh, 01h, 00h
db 1eh, 02h, 00h
db 1fh, 03h, 00h
db 20h, 04h, 00h
db 21h, 05h, 00h
db 22h, 06h, 00h
db 23h, 07h, 01h
db 24h, 08h, 02h
db 25h, 09h, 03h
db 26h, 0ah, 04h ; 40
db 27h, 0bh, 05h
db 28h, 0ch, 06h
db 29h, 0dh, 07h
db 2ah, 0eh, 08h
db 2bh, 0fh, 09h
db 2ch, 10h, 0ah
db 2dh, 11h, 0bh
db 2eh, 12h, 0ch
db 2fh, 13h, 0dh
db 30h, 14h, 0eh ; 50
db 31h, 15h, 0fh
db 32h, 16h, 10h
db 33h, 17h, 11h
db 34h, 18h, 12h
db 35h, 19h, 13h
db 36h, 1ah, 14h
db 37h, 1bh, 15h
db 38h, 1ch, 16h
db 39h, 1dh, 17h
db 3ah, 1eh, 18h ; 60
db 3bh, 1fh, 19h
db 3ch, 20h, 1ah
db 3dh, 21h, 1bh
db 3eh, 22h, 1ch
db 32h, 0ah, 0ah ; 2nd part
db 32h, 0bh, 0bh
db 32h, 0ch, 0ch
db 32h, 0dh, 0dh
db 32h, 0eh, 0eh
db 32h, 0fh, 0fh ; 70
db 32h, 10h, 10h
db 32h, 11h, 11h
db 32h, 12h, 12h
db 32h, 13h, 13h
db 32h, 14h, 14h
db 32h, 15h, 15h
db 32h, 16h, 16h
db 32h, 17h, 17h
db 32h, 18h, 18h
db 32h, 19h, 19h ; 80
db 32h, 1ah, 1ah
db 32h, 1bh, 1bh
db 32h, 1ch, 1ch
db 32h, 1dh, 1dh
db 32h, 1eh, 1eh
db 32h, 1fh, 1fh
db 32h, 20h, 20h
db 32h, 21h, 21h
db 32h, 22h, 22h
db 32h, 23h, 23h ; 90
db 32h, 24h, 24h
db 32h, 25h, 25h
db 32h, 26h, 26h
db 32h, 27h, 27h
db 32h, 28h, 28h
db 32h, 29h, 29h
#
end start
which perfectly compiles using TASM (2.0) and TLINK under DOSBOX and on real 386+ machines!
The output COM-file weights only ≈1.5kB which is incredibly small number in comparison with the final effect.