Lousy map/texture generator.

TAD/Hugi

Introduction

This was originally written for and sent to Wilby diskmag (along with a few more articles) but unfortunately none of them have appeared or are likely to appear in the near future. All seems quiet in the Wilby part of the globe and with no response to say that the articles ever had arrived, I have decided to publish them here. You (un)lucky people. ;)

The code itself.

Here is the entire program which should be assembled as a .COM (tiny model) program.

    .model tiny
    .code
    .286
     org  256
go:  mov  al,13h                ; [1]
     int  10h
     mov  ax,0A000h
     mov  DS,ax                 ; [2]
     mov  dx,3C8h
     out  dx,al
     inc  dx
rgb: ror  ax,2                  ; [3]
     out  dx,al
     rol  ax,1                  ; [4]
     out  dx,al
     rol  ax,1                  ; [5]
     out  dx,al
     inc  ax                    ; [6]
     loop rgb                   ; [7]

gen: mov  [bx],al               ; [8]
     add  ax,bx                 ; \
     aad  13                    ;   [9]
     inc  bx                    ; /
     jnz  gen                   ; [10]

     mov  cl,30                 ; [11]
arc: mov  al,[bx]
     adc  al,[bx+1]
     shr  al,1
     adc  al,[bx+320]
     shr  al,1
     mov  [bx],al               ; [12]
     inc  bx                    ; \
     jnz  arc                   ; / [13]
     loop arc                   ; [14]
     int  16h                   ; [15]
     mov  ax,3
     int  10h
     ret                        ; [16]
     end go  

"Groovy"

First of all, because it is intended to be a .COM program I have assumed that some registers will be set to certain values upon start up. These values are:-

        ax = 00xx
        bx = 0000
        cx = 00FF 

The AH register is assumed to be 00h, this saves 1 byte over a normal MOV AX,0013h instruction.

go:  mov  al,13h                ; [1] 

The DS segment register is loaded with the paragraph address of the video memory. Because AX=A000 hex we can use the AL=00 to set the PEL index register without needing to perform a MOV AL,00 instruction saving 2 bytes.

     mov  DS,ax                 ; [2]
     mov  dx,3C8h
     out  dx,al 

The palette is set up using a red=n DIV 4, green=n DIV 2 and blue=n loop. Bits 15 and 14 of the AX register are used as temporary storage for the DIV 4 and DIV 2 steps.

rgb: ror  ax,2                  ; [3] n DIV 4
     out  dx,al
     rol  ax,1                  ; [4] n DIV 2
     out  dx,al
     rol  ax,1                  ; [5] n
     out  dx,al 

The palette generation loop assumes that the CX register is 00FF hex. This saves 3 bytes (MOV CX,xxxx) but means only the first 255 colours are set.

     loop rgb                   ; [7] 

The map/texture generation loop is next. It's only 9 bytes and does a okay (ish) job at filling the entire 64kb with random values. It assumes the BX=0000 on entry and will exit with BX=0000. In fact all the following loops uses this BX=0000..FFFF wrap to avoid having to reinit the BX register.

gen: mov  [bx],al               ; [8] write AL to the buffer
     add  ax,bx                 ; \
     aad  13                    ;   [9] the 5 byte 'random' generator
     inc  bx                    ; /
     jnz  gen                   ; [10] 

Okay, so it doesn't look much like a map/texture at the present time, more like a ROM dump to the screen, or perhaps a rainbow coloured snow scene. ;) It has no local cohesion, it needs some kinda shaping function in order to make neighbouring pixels look like they contribute something to the overall image.

This is where the smoothing operation comes in. It helps to give the 'random snow' some apparent purpose. Instead of chaos we end up with a nice cloud/map-like image. The following smooth loop takes the pixel to the right, the pixel below and the current pixel then performs a dodgy average on them. I've used ADC to introduce a little bit more random-ness into the smooth operation. The smooth operation repeats 30 times in order to help push the random spikes of the map outwards into the neighbouring pixels. You can of course experiment with different repeat values to create very smooth or spiky maps.

     mov  cl,30                 ; [11]
arc: mov  al,[bx]
     adc  al,[bx+1]
     shr  al,1
     adc  al,[bx+320]
     shr  al,1
     mov  [bx],al               ; [12] write new the 'averaged' pixel
     inc  bx                    ; \
     jnz  arc                   ; / [13]
     loop arc                   ; [14] repeat CX times

Because AX=00xx from the AAD 13 instruction at step [9], we don't need to use MOV AH,00 for the key-wait INT 16h below. That AAD instruction always gives AH=00 (and also helps to randomise things too ;).

     int  16h                   ; [15] 

The normal text-mode switch and exit then occurs.

     mov  ax,3
     int  10h
     ret                        ; [16] 

Final words

So it ain't going to win any prizes for texture generation, but it might be good enough (or perhaps some part(s) of it) for a small 256, 512 or 1kb intro. In fact the palette generation might be good enough to be used in a voxel landscape or similiar effect.

Happy mapping...

TAD/Hugi