;--------------------------------------------------------------------
; Hi-res mode Life simulator (640x480) - Tenie Remmel
;--------------------------------------------------------------------
Ideal
Model Tiny
P386
CodeSeg
Org 100h
Start: jmp Main
;----------------------------------------------------------
NoMem$ db 'Out of memory (need 256K)',13,10,'$'
Table$ db 'Generating tables . . .',13,10,'$'
VID_MODE = 12h
X_SIZE = 640
Y_SIZE = 480
X_BYTES = X_SIZE / 8
SEG_START = X_BYTES * 2
;----------------------------------------------------------
DataSeg1 dw ?
DataSeg2 dw ?
TableSeg dw ?
;----------------------------------------------------------
Proc Main
mov ah,4Ah ;Resize memory block
mov bx,1000h
int 21h
jc m_nomem
mov ah,48h ;Allocate 3 segments
mov bx,3000h
int 21h
jnc m_cont1
m_nomem: mov ah,9 ;Out of memory...
mov dx,offset NoMem$
int 21h
mov ax,4C01h
int 21h
m_cont1: mov [DataSeg1],ax ;Save segments
add ax,1000h
mov [DataSeg2],ax
add ax,1000h
mov [TableSeg],ax
mov ah,9 ;'Generating...'
mov dx,offset Table$
int 21h
mov es,[TableSeg] ;Generate the table
call GenTable
mov ax,VID_MODE ;Set video mode
int 10h
;----------------------------------------------------------
push 0 ;Seed RNG with clock
pop es
mov ebx,[es:046Ch]
mov es,[cs:DataSeg2] ;ES = second data seg.
xor di,di
xor eax,eax ;Clear the segment
mov cx,16384
rep stosd
mov es,[cs:DataSeg1] ;ES = first data seg.
mov cx,16384 ;Clear the segment
rep stosd
mov di,SEG_START ;DI = start segment
mov cx,X_BYTES * Y_SIZE / 2 ;CX = word count
m_rloop: imul ebx,015A4E35h ;Generate random number
inc ebx
mov eax,ebx ;AX = 16 bit number
shr eax,8
stosw ;Write value
dec cx ;Loop back
jnz m_rloop
;----------------------------------------------------------
mov fs,[cs:TableSeg] ;FS = table seg.
m_loop: mov ds,[cs:DataSeg1] ;Calculate 1 --> 2
mov es,[cs:DataSeg2]
call CalcLife
mov ds,[cs:DataSeg2] ;Display buffer 2
call DispScreen
mov ds,[cs:DataSeg2] ;Calculate 2 --> 1
mov es,[cs:DataSeg1]
call CalcLife
mov ds,[cs:DataSeg1] ;Display buffer 1
call DispScreen
mov ah,1 ;Loop if no key
int 16h
jz m_loop
;----------------------------------------------------------
mov ax,3 ;Set normal video mode
int 10h
mov ah,49h ;Free the memory
mov es,[cs:DataSeg1]
int 21h
mov ax,4C00h ;Return
int 21h
EndP Main
;----------------------------------------------------------
Proc GenTable ;ES = segment
pusha ;Save all registers
xor di,di ;Zero counter
gt_loop: xor ax,ax ;Zero AX
mov bx,di ;BX = UL bits
and bx,0EAE0h
call gt_count ;Count bits
cmp cl,3
sete ah
cmp cl,2
jne gt_test2
test di,0400h
setnz ah
gt_test2: shl ah,3 ;Add in bit
or al,ah
mov bx,di ;BX = UR bits
and bx,07570h
call gt_count ;Count bits
cmp cl,3
sete ah
cmp cl,2
jne gt_test3
test di,0200h
setnz ah
gt_test3: shl ah,2 ;Add in bit
or al,ah
mov bx,di ;BX = LL bits
and bx,00EAEh
call gt_count ;Count bits
cmp cl,3
sete ah
cmp cl,2
jne gt_test4
test di,0040h
setnz ah
gt_test4: add ah,ah ;Add in bit
or al,ah
mov bx,di ;BX = LR bits
and bx,00757h
call gt_count ;Count bits
cmp cl,3
sete ah
cmp cl,2
jne gt_lback
test di,0020h
setnz ah
gt_lback: or al,ah ;Add in bit
stosb ;Store value
test di,di ;Loop back
jnz gt_loop
popa ;Restore registers
ret ;Return
gt_count: mov cx,bx ;Collect bit pairs
shr bx,1
and cx,5555h
and bx,5555h
add bx,cx
mov cx,bx ;Collect nibbles
shr bx,2
and cx,3333h
and bx,3333h
add bx,cx
mov cx,bx ;Collect bytes
shr bx,4
and cx,0F0Fh
and bx,0F0Fh
add cx,bx
add cl,ch ;CL = result
ret ;Return
EndP GenTable
;----------------------------------------------------------
Proc CalcLife ;DS = source, ES = dest.
pusha ;Save all registers
mov si,SEG_START ;SI = start of data
mov bp,Y_SIZE / 2 ;BP = Y counter
cl_oloop: mov cx,X_BYTES ;CX = X bytes
cl_loop: push cx bp ;Save registers
mov bx,[si-1-X_BYTES] ;Get values for all lines
mov cx,[si-1]
mov dx,[si-1+X_BYTES]
mov di,[si-1+X_BYTES*2]
and bx,0E001h ;Mask and shift them
ror bx,1
and cx,0E001h
ror cx,5
and dx,0E001h
rol dx,7
and di,0E001h
rol di,3
or bx,cx ;OR them into BX and DI
or di,dx
mov al,[fs:bx+di] ;Look up new value
mov ah,al ;Shift and mask
and ax,030Ch
shl al,4
shl ah,6
mov cx,ax ;CX = AX
mov bh,[si-X_BYTES] ;Get values for all lines
mov dh,[si]
mov bl,[si+X_BYTES]
mov dl,[si+X_BYTES*2]
push bx dx ;Save values
and bx,7878h ;Add in all four lines
add bx,bx
and dx,7878h
shr dx,3
or bx,dx
mov al,[fs:bx] ;Look up new value
mov ah,al ;Shift and mask
and ax,030Ch
shl al,2
shl ah,4
or cx,ax ;OR in values
pop dx bx ;Get values (same as last time)
and bx,1E1Eh ;Add in all four lines
shl bx,3
and dx,1E1Eh
shr dx,1
or bx,dx
mov ah,[fs:bx] ;Look up new value
mov al,ah ;Shift and mask
and ax,030Ch
shl ah,2
or cx,ax ;OR in values
mov ax,[si-X_BYTES] ;Get values for all lines
mov bx,[si]
mov dx,[si+X_BYTES]
mov di,[si+X_BYTES*2]
and ax,8007h ;Mask and shift them
ror ax,3
and bx,8007h
ror bx,7
and dx,8007h
rol dx,5
and di,8007h
rol di,1
or bx,ax ;OR them into BX and DI
or di,dx
mov al,[fs:bx+di] ;Look up new value
mov ah,al ;Shift and mask
and ax,030Ch
shr al,2
or ax,cx ;AX = result
mov [es:si],al ;Write new data
mov [es:si+X_BYTES],ah
pop bp cx ;Restore registers
inc si ;Next byte
dec cx ;Loop back
jnz cl_loop
add si,X_BYTES ;Next 2 rows
dec bp ;Loop back
jnz cl_oloop
popa ;Restore registers
ret ;Return
EndP CalcLife
;----------------------------------------------------------
Proc DispScreen ;DS = source
pusha ;Save all registers
push es
push 0A000h ;ES = video memory
pop es
mov si,SEG_START ;Copy to screen
xor di,di
mov cx,X_BYTES * Y_SIZE / 4
rep movsd
pop es ;Restore registers
popa
ret ;Return
EndP DispScreen
;----------------------------------------------------------
End Start