Previous | Table of Contents | Next |
LISTING 18.1 BUILD.BAT
bcc -v -D%1=%2;%2=%3;%3=%4;%4=%5;%5=%6;%6=%7;%7=%8;%8 lcomp.c lcomp > qlife.asm tasmx /mx /kh30000 qlife bcc -v -D%1=%2;%2=%3;%3=%4;%4=%5;%5=%6;%6=%7;%7=%8;%8 qlife.obj main.c video.c
LISTING 18.2 LCOMP.C
// LCOMP.C // // Life compiler, ver 1.3 // // David Stafford // #include <stdio.h> #include <stdlib.h> #include life.h #define LIST_LIMIT (46 * 138) // when we need to use es: int Old, New, Edge, Label; char Buf[ 20 ]; void Next1( void ) { char *Seg = ; if( WIDTH * HEIGHT > LIST_LIMIT ) Seg = es:; printf( mov bp,%s[si]\n, Seg ); printf( add si,2\n ); printf( mov dh,[bp+1]\n ); printf( and dh,0FEh\n ); printf( jmp dx\n ); } void Next2( void ) { printf( mov bp,es:[si]\n ); printf( add si,2\n ); printf( mov dh,[bp+1]\n ); printf( or dh,1\n ); printf( jmp dx\n ); } void BuildMaps( void ) { unsigned short i, j, Size, x = 0, y, N1, N2, N3, C1, C2, C3; printf( _DATA segment DATA\nalign 2\n ); printf( public _CellMap\n ); printf( _CellMap label word\n ); for( j = 0; j < HEIGHT; j++ ) { for( i = 0; i < WIDTH; i++ ) { if( i == 0 || i == WIDTH-1 || j == 0 || j == HEIGHT-1 ) { printf( dw 8000h\n ); } else { printf( dw 0\n ); } } } printf( ChangeCell dw 0\n ); printf( _RowColMap label word\n ); for( j = 0; j < HEIGHT; j++ ) { for( i = 0; i < WIDTH; i++ ) { printf( dw 0%02x%02xh\n, j, i * 3 ); } } if( WIDTH * HEIGHT > LIST_LIMIT ) { printf( Change1 dw offset _CHANGE:_ChangeList1\n ); printf( Change2 dw offset _CHANGE:_ChangeList2\n ); printf( ends\n\n ); printf( _CHANGE segment para public FAR_DATA\n ); } else { printf( Change1 dw offset DGROUP:_ChangeList1\n ); printf( Change2 dw offset DGROUP:_ChangeList2\n ); } Size = WIDTH * HEIGHT + 1; printf( public _ChangeList1\n_ChangeList1 label word\n ); printf( dw %d dup (offset DGROUP:ChangeCell)\n, Size ); printf( public _ChangeList2\n_ChangeList2 label word\n ); printf( dw %d dup (offset DGROUP:ChangeCell)\n, Size ); printf( ends\n\n ); printf( _LDMAP segment para public FAR_DATA\n ); do { // Current cell states C1 = (x & 0x0800) >> 11; C2 = (x & 0x0400) >> 10; C3 = (x & 0x0200) >> 9; // Neighbor counts N1 = (x & 0x01C0) >> 6; N2 = (x & 0x0038) >> 3; N3 = (x & 0x0007); y = x & 0x8FFF; // Preserve all but the next generation states if( C1 && ((N1 + C2 == 2) || (N1 + C2 == 3)) ) { y |= 0x4000; } if( !C1 && (N1 + C2 == 3) ) { y |= 0x4000; } if( C2 && ((N2 + C1 + C3 == 2) || (N2 + C1 + C3 == 3)) ) { y |= 0x2000; } if( !C2 && (N2 + C1 + C3 == 3) ) { y |= 0x2000; } if( C3 && ((N3 + C2 == 2) || (N3 + C2 == 3)) ) { y |= 0x1000; } if( !C3 && (N3 + C2 == 3) ) { y |= 0x1000; } printf( db 0%02xh\n, y >> 8 ); } while( ++x != 0 ); printf( ends\n\n ); } void GetUpAndDown( void ) { printf( mov ax,[bp+_RowColMap-_CellMap]\n ); printf( or ah,ah\n ); printf( mov dx,%d\n, DOWN ); printf( mov cx,%d\n, WRAPUP ); printf( jz short D%d\n, Label ); printf( cmp ah,%d\n, HEIGHT - 1 ); printf( mov cx,%d\n, UP ); printf( jb short D%d\n, Label ); printf( mov dx,%d\n, WRAPDOWN ); printf( D%d:\n, Label ); } void FirstPass( void ) { char *Op; unsigned short UpDown = 0; printf( org 0%02x00h\n, (Edge << 7) + (New << 4) + (Old << 1) ); // reset cell printf( xor byte ptr [bp+1],0%02xh\n, (New ^ Old) << 1 ); // get the screen address and update the display #ifndef NODRAW printf( mov al,160\n ); printf( mov bx,[bp+_RowColMap-_CellMap]\n ); printf( mul bh\n ); printf( add ax,ax\n ); printf( mov bh,0\n ); printf( add bx,ax\n ); // bx = screen offset if( ((New ^ Old) & 6) == 6 ) { printf( mov word ptr fs:[bx],0%02x%02xh\n, (New & 2) ? 15 : 0, (New & 4) ? 15 : 0 ); if( (New ^ Old) & 1 ) { printf( mov byte ptr fs:[bx+2],%s\n, (New & 1) ? 15 : dl ); } } else { if( ((New ^ Old) & 3) == 3 ) { printf( mov word ptr fs:[bx+1],0%02x%02xh\n, (New & 1) ? 15 : 0, (New & 2) ? 15 : 0 ); } else { if( (New ^ Old) & 2 ) { printf( mov byte ptr fs:[bx+1],%s\n, (New & 2) ? 15 : dl ); } if( (New ^ Old) & 1 ) { printf( mov byte ptr fs:[bx+2],%s\n, (New & 1) ? 15 : dl ); } } if( (New ^ Old) & 4 ) { printf( mov byte ptr fs:[bx],%s\n, (New & 4) ? 15 : dl ); } } #endif if( (New ^ Old) & 4 ) UpDown += (New & 4) ? 0x48 : -0x48; if( (New ^ Old) & 2 ) UpDown += (New & 2) ? 0x49 : -0x49; if( (New ^ Old) & 1 ) UpDown += (New & 1) ? 0x09 : -0x09; if( Edge ) { GetUpAndDown(); // ah = row, al = col, cx = up, dx = down if( (New ^ Old) & 4 ) { printf( mov di,%d\n, WRAPLEFT ); // di = left printf( cmp al,0\n ); printf( je short L%d\n, Label ); printf( mov di,%d\n, LEFT ); printf( L%d:\n, Label ); if( New & 4 ) Op = inc; else Op = dec; printf( %s word ptr [bp+di]\n, Op ); printf( add di,cx\n ); printf( %s word ptr [bp+di]\n, Op ); printf( sub di,cx\n ); printf( add di,dx\n ); printf( %s word ptr [bp+di]\n, Op ); } if( (New ^ Old) & 1 ) { printf( mov di,%d\n, WRAPRIGHT ); // di = right printf( cmp al,%d\n, (WIDTH - 1) * 3 ); printf( je short R%d\n, Label ); printf( mov di,%d\n, RIGHT ); printf( R%d:\n, Label ); if( New & 1 ) Op = add; else Op = sub; printf( %s word ptr [bp+di],40h\n, Op ); printf( add di,cx\n ); printf( %s word ptr [bp+di],40h\n, Op ); printf( sub di,cx\n ); printf( add di,dx\n ); printf( %s word ptr [bp+di],40h\n, Op ); } printf( mov di,cx\n ); printf( add word ptr [bp+di],%d\n, UpDown ); printf( mov di,dx\n ); printf( add word ptr [bp+di],%d\n, UpDown ); printf( mov dl,0\n ); } else { if( (New ^ Old) & 4 ) { if( New & 4 ) Op = inc; else Op = dec; printf( %s byte ptr [bp+%d]\n, Op, LEFT ); printf( %s byte ptr [bp+%d]\n, Op, UPPERLEFT ); printf( %s byte ptr [bp+%d]\n, Op, LOWERLEFT ); } if( (New ^ Old) & 1 ) { if( New & 1 ) Op = add; else Op = sub; printf( %s word ptr [bp+%d],40h\n, Op, RIGHT ); printf( %s word ptr [bp+%d],40h\n, Op, UPPERRIGHT ); printf( %s word ptr [bp+%d],40h\n, Op, LOWERRIGHT ); } if( abs( UpDown ) > 1 ) { printf( add word ptr [bp+%d],%d\n, UP, UpDown ); printf( add word ptr [bp+%d],%d\n, DOWN, UpDown ); } else { if( UpDown == 1 ) Op = inc; else Op = dec; printf( %s byte ptr [bp+%d]\n, Op, UP ); printf( %s byte ptr [bp+%d]\n, Op, DOWN ); } } Next1(); } void Test( char *Offset, char *Str ) { printf( mov bx,[bp+%s]\n, Offset ); printf( cmp bh,[bx]\n ); printf( jnz short FIX_%s%d\n, Str, Label ); printf( %s%d:\n, Str, Label ); } void Fix( char *Offset, char *Str, int JumpBack ) { printf( FIX_%s%d:\n, Str, Label ); printf( mov bh,[bx]\n ); printf( mov [bp+%s],bx\n, Offset ); if( *Offset != 0 ) printf( lea ax,[bp+%s]\n, Offset ); else printf( mov ax,bp\n ); printf( stosw\n ); if( JumpBack ) printf( jmp short %s%d\n, Str, Label ); } void SecondPass( void ) { printf( org 0%02x00h\n, (Edge << 7) + (New << 4) + (Old << 1) + 1 ); if( Edge ) { // finished with second pass if( New == 7 && Old == 0 ) { printf( cmp bp,offset DGROUP:ChangeCell\n ); printf( jne short NotEnd\n ); printf( mov word ptr es:[di],offset DGROUP:ChangeCell\n ); printf( pop di si bp ds\n ); printf( mov ChangeCell,0\n ); printf( retf\n ); printf( NotEnd:\n ); } GetUpAndDown(); // ah = row, al = col, cx = up, dx = down printf( push si\n ); printf( mov si,%d\n, WRAPLEFT ); // si = left printf( cmp al,0\n ); printf( je short L%d\n, Label ); printf( mov si,%d\n, LEFT ); printf( L%d:\n, Label ); Test( si, LEFT ); printf( add si,cx\n ); Test( si, UPPERLEFT ); printf( sub si,cx\n ); printf( add si,dx\n ); Test( si, LOWERLEFT ); printf( mov si,cx\n ); Test( si, UP ); printf( mov si,dx\n ); Test( si, DOWN ); printf( cmp byte ptr [bp+_RowColMap-_CellMap],%d\n, (WIDTH - 1) * 3 ); printf( mov si,%d\n, WRAPRIGHT ); // si = right printf( je short R%d\n, Label ); printf( mov si,%d\n, RIGHT ); printf( R%d:\n, Label ); Test( si, RIGHT ); printf( add si,cx\n ); Test( si, UPPERRIGHT ); printf( sub si,cx\n ); printf( add si,dx\n ); Test( si, LOWERRIGHT ); } else { Test( itoa( LEFT, Buf, 10 ), LEFT ); Test( itoa( UPPERLEFT, Buf, 10 ), UPPERLEFT ); Test( itoa( LOWERLEFT, Buf, 10 ), LOWERLEFT ); Test( itoa( UP, Buf, 10 ), UP ); Test( itoa( DOWN, Buf, 10 ), DOWN ); Test( itoa( RIGHT, Buf, 10 ), RIGHT ); Test( itoa( UPPERRIGHT, Buf, 10 ), UPPERRIGHT ); Test( itoa( LOWERRIGHT, Buf, 10 ), LOWERRIGHT ); } if( New == Old ) Test( 0, CENTER ); if( Edge ) printf( pop si\n mov dl,0\n ); Next2(); if( Edge ) { Fix( si, LEFT, 1 ); Fix( si, UPPERLEFT, 1 ); Fix( si, LOWERLEFT, 1 ); Fix( si, UP, 1 ); Fix( si, DOWN, 1 ); Fix( si, RIGHT, 1 ); Fix( si, UPPERRIGHT, 1 ); Fix( si, LOWERRIGHT, New == Old ); } else { Fix( itoa( LEFT, Buf, 10 ), LEFT, 1 ); Fix( itoa( UPPERLEFT, Buf, 10 ), UPPERLEFT, 1 ); Fix( itoa( LOWERLEFT, Buf, 10 ), LOWERLEFT, 1 ); Fix( itoa( UP, Buf, 10 ), UP, 1 ); Fix( itoa( DOWN, Buf, 10 ), DOWN, 1 ); Fix( itoa( RIGHT, Buf, 10 ), RIGHT, 1 ); Fix( itoa( UPPERRIGHT, Buf, 10 ), UPPERRIGHT, 1 ); Fix( itoa( LOWERRIGHT, Buf, 10 ), LOWERRIGHT, New == Old ); } if( New == Old ) Fix( 0, CENTER, 0 ); if( Edge ) printf( pop si\n mov dl,0\n ); Next2(); } void main( void ) { char *Seg = ds; BuildMaps(); printf( DGROUP group _DATA\n ); printf( LIFE segment CODE\n ); printf( assume cs:LIFE,ds:DGROUP,ss:DGROUP,es:NOTHING\n ); printf( .386C\n public _NextGen\n\n ); for( Edge = 0; Edge <= 1; Edge++ ) { for( New = 0; New < 8; New++ ) { for( Old = 0; Old < 8; Old++ ) { if( New != Old ) FirstPass(); Label++; SecondPass(); Label++; } } } // finished with first pass printf( org 0\n ); printf( mov si,Change1\n ); printf( mov di,Change2\n ); printf( mov Change1,di\n ); printf( mov Change2,si\n ); printf( mov ChangeCell,0F000h\n ); printf( mov ax,seg _LDMAP\n ); printf( mov ds,ax\n ); Next2(); // entry point printf( _NextGen: push ds bp si di\n cld\n ); if( WIDTH * HEIGHT > LIST_LIMIT ) Seg = seg _CHANGE; printf( mov ax,%s\n, Seg ); printf( mov es,ax\n ); #ifndef NODRAW printf( mov ax,0A000h\n ); printf( mov fs,ax\n ); #endif printf( mov si,Change1\n ); printf( mov dl,0\n ); Next1(); printf( LIFE ends\nend\n ); }
Previous | Table of Contents | Next |