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


MARS.EXE

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

toc


[enhanced] DEBUG

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.


code:

        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

data:

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


algorithm

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

conversion to MARS.COM

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.

MARS.COM

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.