;**************************** LIFE.ASM -- Life simulation, VERY FAST!

Ideal

Model Tiny
CodeSeg
P386
Org 100h

Proc        Prog

            mov ax,13h              ;Set mode 13h
            int 10h

            mov ds,ax               ;ES = 13h
            mov ebx,[033Ch]         ;Seed RNG
                                    
            mov ax,cs               ;DS, ES = virtual video
            add ax,1000h
            mov ds,ax
            mov es,ax

            xor di,di               ;Zero DI
            mov cx,32768            ;32K dwords
            xor ax,ax               ;Clear memory
            rep stosw

            push 0A000h             ;FS = video memory
            pop fs

            mov di,320              ;DI = 320
            mov cx,64000            ;64000 bytes

RandLoop:   imul ebx,015A4E35h      ;Generate random number
            inc ebx
            mov ax,bx
            shr ax,15
            stosb                   ;Store byte
            imul ax,15              ;Write to screen
            mov [fs:di-321],al
            loop RandLoop           ;Loop back

            mov di,320              ;DI = 320
            mov cx,64000            ;64000 bytes

InitLoop:   xor ah,ah               ;Get boundary count
            mov al,[di+1]
            and al,1
            add ah,al
            mov al,[di-1]
            and al,1
            add ah,al
            mov al,[di+319]
            and al,1
            add ah,al
            mov al,[di-319]
            and al,1
            add ah,al
            mov al,[di+320]
            and al,1
            add ah,al
            mov al,[di-320]
            and al,1
            add ah,al
            mov al,[di+321]
            and al,1
            add ah,al
            mov al,[di-321]
            and al,1
            add ah,al

            shl ah,1                ;Shift left 1
            and ah,0Fh
            or [di],ah              ;Set count

            inc di                  ;Loop back
            loop InitLoop

            mov di,321              ;Set up for loop
            mov cx,63998

SetupLoop:  mov al,[di]             ;Copy to high bits
            shl al,4
            or [di],al
            
            inc di                  ;Loop back
            loop SetupLoop

MainLoop:   mov di,320              ;Set up for LifeLoop
            mov cx,64000

LifeLoop:   mov al,[di]             ;Get cell value
            and al,0Fh              ;AL = boundary count
            jz LifeLB               ;Empty cell?
            shr al,1
            jnc LifeDead            ;Test current cell

            sub al,2                ;Alive, check boundary
            cmp al,2
            jb LifeLB

            mov al,-20h             ;Set to flip cell
            jmp LifeFlip

LifeDead:   cmp al,3                ;Dead, check boundary
            jne LifeLB

            mov al,20h              ;Set to flip cell

LifeFlip:   xor [byte di],10h       ;Flip the cell
            xor [byte fs:di-320],15

            add [di+1],al           ;Change boundary counts
            add [di-1],al
            add [di+319],al
            add [di-319],al
            add [di+320],al
            add [di-320],al
            add [di+321],al
            add [di-321],al

LifeLB:     inc di                  ;Loop back
            dec cx
            jnz LifeLoop

            mov di,320              ;Set up for CleanLoop
            mov cx,16000
            mov si,0F0F0h

CleanLoop:  mov ax,[di]             ;Get values
            mov dx,[di+2]
            and ax,si
            and dx,si

            mov bx,ax               ;Copy to both digits
            shr bx,4
            mov bp,dx
            shr bp,4
            or ax,bx
            or dx,bp

            mov [di],ax             ;Store values
            mov [di+2],dx

            add di,4                ;Loop back
            dec cx
            jnz CleanLoop

            mov ah,1                ;Check for key
            int 16h
            jz MainLoop             ;Loop if no key

            mov ax,3                ;Set text mode
            int 10h

            ret                     ;Return

EndP        Prog

End Prog
