home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / source / chapter18 / lcomp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-18  |  12.3 KB  |  502 lines

  1. // LCOMP.C
  2. //
  3. // Life compiler, ver 1.3
  4. //
  5. // David Stafford
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include "life.h"
  10.  
  11.  
  12. #define LIST_LIMIT (46 * 138)   // when we need to use es:
  13.  
  14. int Old, New, Edge, Label;
  15. char Buf[ 20 ];
  16.  
  17.  
  18. void Next1( void )
  19.   {
  20.   char *Seg = "";
  21.  
  22.   if( WIDTH * HEIGHT > LIST_LIMIT )  Seg = "es:";
  23.  
  24.   printf( "mov  bp,%s[si]\n", Seg );
  25.   printf( "add  si,2\n" );
  26.   printf( "mov  dh,[bp+1]\n" );
  27.   printf( "and  dh,0FEh\n" );
  28.   printf( "jmp  dx\n" );
  29.   }
  30.  
  31.  
  32. void Next2( void )
  33.   {
  34.   printf( "mov  bp,es:[si]\n" );
  35.   printf( "add  si,2\n" );
  36.   printf( "mov  dh,[bp+1]\n" );
  37.   printf( "or   dh,1\n" );
  38.   printf( "jmp  dx\n" );
  39.   }
  40.  
  41.  
  42. void BuildMaps( void )
  43.   {
  44.   unsigned short i, j, Size, x = 0, y, N1, N2, N3, C1, C2, C3;
  45.  
  46.   printf( "_DATA segment 'DATA'\nalign 2\n" );
  47.   printf( "public _CellMap\n" );
  48.   printf( "_CellMap label word\n" );
  49.  
  50.   for( j = 0; j < HEIGHT; j++ )
  51.     {
  52.     for( i = 0; i < WIDTH; i++ )
  53.       {
  54.       if( i == 0 || i == WIDTH-1 || j == 0 || j == HEIGHT-1 )
  55.         {
  56.         printf( "dw 8000h\n" );
  57.         }
  58.       else
  59.         {
  60.         printf( "dw 0\n" );
  61.         }
  62.       }
  63.     }
  64.  
  65.   printf( "ChangeCell dw 0\n" );
  66.   printf( "_RowColMap label word\n" );
  67.  
  68.   for( j = 0; j < HEIGHT; j++ )
  69.     {
  70.     for( i = 0; i < WIDTH; i++ )
  71.       {
  72.       printf( "dw 0%02x%02xh\n", j, i * 3 );
  73.       }
  74.     }
  75.  
  76.   if( WIDTH * HEIGHT > LIST_LIMIT )
  77.     {
  78.     printf( "Change1 dw offset _CHANGE:_ChangeList1\n" );
  79.     printf( "Change2 dw offset _CHANGE:_ChangeList2\n" );
  80.     printf( "ends\n\n" );
  81.     printf( "_CHANGE segment para public 'FAR_DATA'\n" );
  82.     }
  83.   else
  84.     {
  85.     printf( "Change1 dw offset DGROUP:_ChangeList1\n" );
  86.     printf( "Change2 dw offset DGROUP:_ChangeList2\n" );
  87.     }
  88.  
  89.   Size = WIDTH * HEIGHT + 1;
  90.  
  91.   printf( "public _ChangeList1\n_ChangeList1 label word\n" );
  92.   printf( "dw %d dup (offset DGROUP:ChangeCell)\n", Size );
  93.   printf( "public _ChangeList2\n_ChangeList2 label word\n" );
  94.   printf( "dw %d dup (offset DGROUP:ChangeCell)\n", Size );
  95.   printf( "ends\n\n" );
  96.  
  97.   printf( "_LDMAP segment para public 'FAR_DATA'\n" );
  98.  
  99.   do
  100.     {
  101.     // Current cell states
  102.     C1 = (x & 0x0800) >> 11;
  103.     C2 = (x & 0x0400) >> 10;
  104.     C3 = (x & 0x0200) >> 9;
  105.  
  106.     // Neighbor counts
  107.     N1 = (x & 0x01C0) >> 6;
  108.     N2 = (x & 0x0038) >> 3;
  109.     N3 = (x & 0x0007);
  110.  
  111.     y = x & 0x8FFF;  // Preserve all but the next generation states
  112.  
  113.     if(  C1 && ((N1 + C2 == 2) || (N1 + C2 == 3)) )
  114.       {
  115.       y |= 0x4000;
  116.       }
  117.  
  118.     if( !C1 &&  (N1 + C2 == 3) )
  119.       {
  120.       y |= 0x4000;
  121.       }
  122.  
  123.     if(  C2 && ((N2 + C1 + C3 == 2) || (N2 + C1 + C3 == 3)) )
  124.       {
  125.       y |= 0x2000;
  126.       }
  127.  
  128.     if( !C2 &&  (N2 + C1 + C3 == 3) )
  129.       {
  130.       y |= 0x2000;
  131.       }
  132.  
  133.     if(  C3 && ((N3 + C2 == 2) || (N3 + C2 == 3)) )
  134.       {
  135.       y |= 0x1000;
  136.       }
  137.  
  138.     if( !C3 &&  (N3 + C2 == 3) )
  139.       {
  140.       y |= 0x1000;
  141.       }
  142.  
  143.     printf( "db 0%02xh\n", y >> 8 );
  144.     }
  145.   while( ++x != 0 );
  146.  
  147.   printf( "ends\n\n" );
  148.   }
  149.  
  150.  
  151. void GetUpAndDown( void )
  152.   {
  153.   printf( "mov  ax,[bp+_RowColMap-_CellMap]\n" );
  154.   printf( "or   ah,ah\n" );
  155.   printf( "mov  dx,%d\n", DOWN );
  156.   printf( "mov  cx,%d\n", WRAPUP );
  157.   printf( "jz   short D%d\n", Label );
  158.   printf( "cmp  ah,%d\n", HEIGHT - 1 );
  159.   printf( "mov  cx,%d\n", UP );
  160.   printf( "jb   short D%d\n", Label );
  161.   printf( "mov  dx,%d\n", WRAPDOWN );
  162.   printf( "D%d:\n", Label );
  163.   }
  164.  
  165.  
  166. void FirstPass( void )
  167.   {
  168.   char *Op;
  169.   unsigned short UpDown = 0;
  170.  
  171.   printf( "org 0%02x00h\n", (Edge << 7) + (New << 4) + (Old << 1) );
  172.  
  173.   // reset cell
  174.   printf( "xor  byte ptr [bp+1],0%02xh\n", (New ^ Old) << 1 );
  175.  
  176.   // get the screen address and update the display
  177.   #ifndef NODRAW
  178.   printf( "mov  al,160\n" );
  179.   printf( "mov  bx,[bp+_RowColMap-_CellMap]\n" );
  180.   printf( "mul  bh\n" );
  181.   printf( "add  ax,ax\n" );
  182.   printf( "mov  bh,0\n" );
  183.   printf( "add  bx,ax\n" );    // bx = screen offset
  184.  
  185.   if( ((New ^ Old) & 6) == 6 )
  186.     {
  187.     printf( "mov  word ptr fs:[bx],0%02x%02xh\n",
  188.             (New & 2) ? 15 : 0,
  189.             (New & 4) ? 15 : 0 );
  190.  
  191.     if( (New ^ Old) & 1 )
  192.       {
  193.       printf( "mov  byte ptr fs:[bx+2],%s\n",
  194.               (New & 1) ? "15" : "dl" );
  195.       }
  196.     }
  197.   else
  198.     {
  199.     if( ((New ^ Old) & 3) == 3 )
  200.       {
  201.       printf( "mov  word ptr fs:[bx+1],0%02x%02xh\n",
  202.               (New & 1) ? 15 : 0,
  203.               (New & 2) ? 15 : 0 );
  204.       }
  205.     else
  206.       {
  207.       if( (New ^ Old) & 2 )
  208.         {
  209.         printf( "mov  byte ptr fs:[bx+1],%s\n",
  210.                 (New & 2) ? "15" : "dl" );
  211.         }
  212.  
  213.       if( (New ^ Old) & 1 )
  214.         {
  215.         printf( "mov  byte ptr fs:[bx+2],%s\n",
  216.                 (New & 1) ? "15" : "dl" );
  217.         }
  218.       }
  219.  
  220.     if( (New ^ Old) & 4 )
  221.       {
  222.       printf( "mov  byte ptr fs:[bx],%s\n",
  223.               (New & 4) ? "15" : "dl" );
  224.       }
  225.     }
  226.   #endif
  227.  
  228.   if( (New ^ Old) & 4 )  UpDown += (New & 4) ? 0x48 : -0x48;
  229.   if( (New ^ Old) & 2 )  UpDown += (New & 2) ? 0x49 : -0x49;
  230.   if( (New ^ Old) & 1 )  UpDown += (New & 1) ? 0x09 : -0x09;
  231.  
  232.   if( Edge )
  233.     {
  234.     GetUpAndDown();  // ah = row, al = col, cx = up, dx = down
  235.  
  236.     if( (New ^ Old) & 4 )
  237.       {
  238.       printf( "mov  di,%d\n", WRAPLEFT );      // di = left
  239.       printf( "cmp  al,0\n" );
  240.       printf( "je   short L%d\n", Label );
  241.       printf( "mov  di,%d\n", LEFT );
  242.       printf( "L%d:\n", Label );
  243.  
  244.       if( New & 4 )  Op = "inc";
  245.       else           Op = "dec";
  246.  
  247.       printf( "%s  word ptr [bp+di]\n", Op );
  248.       printf( "add  di,cx\n" );
  249.       printf( "%s  word ptr [bp+di]\n", Op );
  250.       printf( "sub  di,cx\n" );
  251.       printf( "add  di,dx\n" );
  252.       printf( "%s  word ptr [bp+di]\n", Op );
  253.       }
  254.  
  255.     if( (New ^ Old) & 1 )
  256.       {
  257.       printf( "mov  di,%d\n", WRAPRIGHT );      // di = right
  258.       printf( "cmp  al,%d\n", (WIDTH - 1) * 3 );
  259.       printf( "je   short R%d\n", Label );
  260.       printf( "mov  di,%d\n", RIGHT );
  261.       printf( "R%d:\n", Label );
  262.  
  263.       if( New & 1 )  Op = "add";
  264.       else           Op = "sub";
  265.  
  266.       printf( "%s   word ptr [bp+di],40h\n", Op );
  267.       printf( "add  di,cx\n" );
  268.       printf( "%s   word ptr [bp+di],40h\n", Op );
  269.       printf( "sub  di,cx\n" );
  270.       printf( "add  di,dx\n" );
  271.       printf( "%s   word ptr [bp+di],40h\n", Op );
  272.       }
  273.  
  274.     printf( "mov  di,cx\n" );
  275.     printf( "add  word ptr [bp+di],%d\n", UpDown );
  276.     printf( "mov  di,dx\n" );
  277.     printf( "add  word ptr [bp+di],%d\n", UpDown );
  278.  
  279.     printf( "mov  dl,0\n" );
  280.     }
  281.   else
  282.     {
  283.     if( (New ^ Old) & 4 )
  284.       {
  285.       if( New & 4 )  Op = "inc";
  286.       else           Op = "dec";
  287.  
  288.       printf( "%s  byte ptr [bp+%d]\n", Op, LEFT );
  289.       printf( "%s  byte ptr [bp+%d]\n", Op, UPPERLEFT );
  290.       printf( "%s  byte ptr [bp+%d]\n", Op, LOWERLEFT );
  291.       }
  292.  
  293.     if( (New ^ Old) & 1 )
  294.       {
  295.       if( New & 1 )  Op = "add";
  296.       else           Op = "sub";
  297.  
  298.       printf( "%s  word ptr [bp+%d],40h\n", Op, RIGHT );
  299.       printf( "%s  word ptr [bp+%d],40h\n", Op, UPPERRIGHT );
  300.       printf( "%s  word ptr [bp+%d],40h\n", Op, LOWERRIGHT );
  301.       }
  302.  
  303.     if( abs( UpDown ) > 1 )
  304.       {
  305.       printf( "add  word ptr [bp+%d],%d\n", UP, UpDown );
  306.       printf( "add  word ptr [bp+%d],%d\n", DOWN, UpDown );
  307.       }
  308.     else
  309.       {
  310.       if( UpDown == 1 )  Op = "inc";
  311.       else               Op = "dec";
  312.  
  313.       printf( "%s  byte ptr [bp+%d]\n", Op, UP   );
  314.       printf( "%s  byte ptr [bp+%d]\n", Op, DOWN );
  315.       }
  316.     }
  317.  
  318.   Next1();
  319.   }
  320.  
  321.  
  322. void Test( char *Offset, char *Str )
  323.   {
  324.   printf( "mov  bx,[bp+%s]\n", Offset );
  325.   printf( "cmp  bh,[bx]\n" );
  326.   printf( "jnz  short FIX_%s%d\n", Str, Label );
  327.   printf( "%s%d:\n", Str, Label );
  328.   }
  329.  
  330.  
  331. void Fix( char *Offset, char *Str, int JumpBack )
  332.   {
  333.   printf( "FIX_%s%d:\n", Str, Label );
  334.   printf( "mov  bh,[bx]\n" );
  335.   printf( "mov  [bp+%s],bx\n", Offset );
  336.  
  337.   if( *Offset != '0' )  printf( "lea  ax,[bp+%s]\n", Offset );
  338.   else                  printf( "mov  ax,bp\n" );
  339.  
  340.   printf( "stosw\n" );
  341.  
  342.   if( JumpBack )  printf( "jmp  short %s%d\n", Str, Label );
  343.   }
  344.  
  345.  
  346. void SecondPass( void )
  347.   {
  348.   printf( "org 0%02x00h\n",
  349.           (Edge << 7) + (New << 4) + (Old << 1) + 1 );
  350.  
  351.   if( Edge )
  352.     {
  353.     // finished with second pass
  354.     if( New == 7 && Old == 0 )
  355.       {
  356.       printf( "cmp  bp,offset DGROUP:ChangeCell\n" );
  357.       printf( "jne  short NotEnd\n" );
  358.       printf( "mov  word ptr es:[di],offset DGROUP:ChangeCell\n" );
  359.       printf( "pop  di si bp ds\n" );
  360.       printf( "mov  ChangeCell,0\n" );
  361.       printf( "retf\n" );
  362.       printf( "NotEnd:\n" );
  363.       }
  364.  
  365.     GetUpAndDown();  // ah = row, al = col, cx = up, dx = down
  366.  
  367.     printf( "push si\n" );
  368.     printf( "mov  si,%d\n", WRAPLEFT );    // si = left
  369.     printf( "cmp  al,0\n" );
  370.     printf( "je   short L%d\n", Label );
  371.     printf( "mov  si,%d\n", LEFT );
  372.     printf( "L%d:\n", Label );
  373.  
  374.     Test( "si", "LEFT" );
  375.     printf( "add  si,cx\n" );
  376.     Test( "si", "UPPERLEFT" );
  377.     printf( "sub  si,cx\n" );
  378.     printf( "add  si,dx\n" );
  379.     Test( "si", "LOWERLEFT" );
  380.  
  381.     printf( "mov  si,cx\n" );
  382.     Test( "si", "UP" );
  383.     printf( "mov  si,dx\n" );
  384.     Test( "si", "DOWN" );
  385.  
  386.     printf( "cmp  byte ptr [bp+_RowColMap-_CellMap],%d\n",
  387.             (WIDTH - 1) * 3 );
  388.  
  389.     printf( "mov  si,%d\n", WRAPRIGHT );    // si = right
  390.     printf( "je   short R%d\n", Label );
  391.     printf( "mov  si,%d\n", RIGHT );
  392.     printf( "R%d:\n", Label );
  393.  
  394.     Test( "si", "RIGHT" );
  395.     printf( "add  si,cx\n" );
  396.     Test( "si", "UPPERRIGHT" );
  397.     printf( "sub  si,cx\n" );
  398.     printf( "add  si,dx\n" );
  399.     Test( "si", "LOWERRIGHT" );
  400.     }
  401.   else
  402.     {
  403.     Test( itoa( LEFT, Buf, 10 ), "LEFT" );
  404.     Test( itoa( UPPERLEFT, Buf, 10 ), "UPPERLEFT" );
  405.     Test( itoa( LOWERLEFT, Buf, 10 ), "LOWERLEFT" );
  406.     Test( itoa( UP, Buf, 10 ), "UP" );
  407.     Test( itoa( DOWN, Buf, 10 ), "DOWN" );
  408.     Test( itoa( RIGHT, Buf, 10 ), "RIGHT" );
  409.     Test( itoa( UPPERRIGHT, Buf, 10 ), "UPPERRIGHT" );
  410.     Test( itoa( LOWERRIGHT, Buf, 10 ), "LOWERRIGHT" );
  411.     }
  412.  
  413.   if( New == Old )  Test( "0", "CENTER" );
  414.  
  415.   if( Edge )  printf( "pop  si\n" "mov  dl,0\n" );
  416.  
  417.   Next2();
  418.  
  419.   if( Edge )
  420.     {
  421.     Fix( "si", "LEFT",       1 );
  422.     Fix( "si", "UPPERLEFT",  1 );
  423.     Fix( "si", "LOWERLEFT",  1 );
  424.     Fix( "si", "UP",         1 );
  425.     Fix( "si", "DOWN",       1 );
  426.     Fix( "si", "RIGHT",      1 );
  427.     Fix( "si", "UPPERRIGHT", 1 );
  428.     Fix( "si", "LOWERRIGHT", New == Old );
  429.     }
  430.   else
  431.     {
  432.     Fix( itoa( LEFT, Buf, 10 ),       "LEFT",       1 );
  433.     Fix( itoa( UPPERLEFT, Buf, 10 ),  "UPPERLEFT",  1 );
  434.     Fix( itoa( LOWERLEFT, Buf, 10 ),  "LOWERLEFT",  1 );
  435.     Fix( itoa( UP, Buf, 10 ),         "UP",         1 );
  436.     Fix( itoa( DOWN, Buf, 10 ),       "DOWN",       1 );
  437.     Fix( itoa( RIGHT, Buf, 10 ),      "RIGHT",      1 );
  438.     Fix( itoa( UPPERRIGHT, Buf, 10 ), "UPPERRIGHT", 1 );
  439.     Fix( itoa( LOWERRIGHT, Buf, 10 ), "LOWERRIGHT", New == Old );
  440.     }
  441.  
  442.   if( New == Old )  Fix( "0", "CENTER", 0 );
  443.  
  444.   if( Edge )  printf( "pop  si\n" "mov  dl,0\n" );
  445.  
  446.   Next2();
  447.   }
  448.  
  449.  
  450. void main( void )
  451.   {
  452.   char *Seg = "ds";
  453.  
  454.   BuildMaps();
  455.  
  456.   printf( "DGROUP group _DATA\n" );
  457.   printf( "LIFE segment 'CODE'\n" );
  458.   printf( "assume cs:LIFE,ds:DGROUP,ss:DGROUP,es:NOTHING\n" );
  459.   printf( ".386C\n" "public _NextGen\n\n" );
  460.  
  461.   for( Edge = 0; Edge <= 1; Edge++ )
  462.     {
  463.     for( New = 0; New < 8; New++ )
  464.       {
  465.       for( Old = 0; Old < 8; Old++ )
  466.         {
  467.         if( New != Old )  FirstPass();  Label++;
  468.         SecondPass();                   Label++;
  469.         }
  470.       }
  471.     }
  472.  
  473.   // finished with first pass
  474.   printf( "org  0\n" );
  475.   printf( "mov  si,Change1\n" );
  476.   printf( "mov  di,Change2\n" );
  477.   printf( "mov  Change1,di\n" );
  478.   printf( "mov  Change2,si\n" );
  479.   printf( "mov  ChangeCell,0F000h\n" );
  480.   printf( "mov  ax,seg _LDMAP\n" );
  481.   printf( "mov  ds,ax\n" );
  482.   Next2();
  483.  
  484.   // entry point
  485.   printf( "_NextGen: push ds bp si di\n" "cld\n" );
  486.  
  487.   if( WIDTH * HEIGHT > LIST_LIMIT )  Seg = "seg _CHANGE";
  488.  
  489.   printf( "mov  ax,%s\n", Seg );
  490.   printf( "mov  es,ax\n" );
  491.  
  492.   #ifndef NODRAW
  493.   printf( "mov  ax,0A000h\n" );
  494.   printf( "mov  fs,ax\n" );
  495.   #endif
  496.  
  497.   printf( "mov  si,Change1\n" );
  498.   printf( "mov  dl,0\n" );
  499.   Next1();
  500.  
  501.   printf( "LIFE ends\nend\n" );
  502.   }