EarthWeb   
   datamation.com Brought to you by EarthWeb

HomeSubscribeSearchFAQSitemapContact Us
     

   

  Search Tips
  Advanced Search
   
  

  
Go to ITKnowledge Enterprise

Michael Abrash's Graphics Programming Black Book, Special Edition Michael Abrash's Graphics Programming Black Book, Special Edition
by Michael Abrash
The Coriolis Group
ISBN: 1576101746   Pub Date: 07/01/97

Search this book:
 
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

homesubscribesearchfaqsitemapcontactus
Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.