/*
 * This work was originally done by Fred Taft (fred@hp-pcd.cv.hp.com).
 * Please forward any comments, corrections or additions back to Fred.
 *
 * Berzerk
 *
 ******************************************************************************
 *
 * The following are possible bugs discovered in this code:
 *
 *    DisplayBonusString
 *            When checking to see if the bonus strings should be displayed,
 *            the 'ble' command really should be a 'blt'!!  This explains why
 *            when a player clears a maze containing 10 robots, the bonus
 *            string was not displayed.  In this case the bonus string is
 *            "   100", and this fails the above check!
 *
 *    DisplayLives
 *            There is no check to see if the C8D8 buffer is overrun (this
 *            is the buffer used to display the number of lives a player has);
 *            what is the intended size of this buffer?
 *
 *    FireBullet
 *            There seems to be the potential to overwrite the stack when
 *            firing bullets.  The array of bullet entries can grow very
 *            quickly as a player gets better, since robots can fire more
 *            bullets (and fire them more quickly).  The end of the array
 *            only gets moved back when the last bullet hits something and
 *            becomes inactive.  It would be better to modify FireBullet()
 *            to only allow a certain number of bullets (or to do a better
 *            job of compacting the array).
 *
 ******************************************************************************
 *
 * The following is the memory map for Berzerk RAM usage:
 *
 * C880-C881     Points to player structure for the current player.
 *
 * C882          Number of players: 0 = 1 player, 1 = 2 players
 *
 * C883          Controls maximum number of bullets a robot can fire in a
 *               burst; takes a big jump when user's score surpasses 10,000
 *               points.
 *
 * C884          Velocity factor used when firing robot's bullets.
 *
 * C885          Work memory and loop counter.
 *
 * C886          Flag; don't draw player if set < 0
 *
 * C88F-C890     Player's position
 *
 * C891          Work memory
 *
 * C892          Work memory
 *
 * C893-C894     Otto's position (y,x)
 *
 * C895-C896     Player's position (starting position); used to seed Otto's
 *               initial position.
 *
 * C897          Counter; controls bouncing offset for Otto's 'y' position
 *
 * C898          Otto's movement velocity
 *
 * C899          After a point is mapped into a quadrant number, this contains
 *               the bitmask describing which walls are present in that
 *               quadrant:
 *
 *                      ---------------------------------
 *                      | 0 | 0 | 0 | 0 | B | T | R | L |
 *                      ---------------------------------
 *           Quadrant has Bottom Wall-----^
 *           Quadrant has Top Wall------------^
 *           Quadrant has Right Wall--------------^
 *           Quadrant has Left Wall-------------------^
 *
 * C89A          Quadrant into which a point falls:
 *
 *                   -100 -60 -20 +20 +60 +100
 *                     +---+---+---+---+---+ +96
 *                     | 0 | 1 | 2 | 3 | 4 |
 *                     +---o---o---o---o---+ +32
 *                     | 5 | 6 | 7 | 8 | 9 |
 *                     +---o---o---o---o---+ -32
 *                     |10 |11 |12 |13 |14 |
 *                     +---+---+---+---+---+ -96
 *
 * C89B-C89C     After a point is mapped into a quadrant number, this contains
 *               the point as a relative offset from the lower left corner
 *               of the quadrant.
 *
 * C89D          Work memory/counter
 *
 * C89E-C89F     During game, work memory; usually contains a position (y,x).
 *               After a game, C89F is a semaphore causing author's initials
 *               to be displayed;also used as a counter
 *
 * C8A1          Work memory and loop counter.
 *
 * C8A2          Work memory and loop counter.
 *
 * C8A7          Delay (placed in the robot's structure) between how often
 *               a robot is updated (moved, fire, etc); 0 = no delay.
 *
 * C8A8          Used while populating a level with robots; if the random
 *               number is < C8A8, then a robot is placed in the maze.
 *
 * C8A9          Used during robot processing.
 *
 * C8AA          Used during robot processing.
 *
 * C8AB-C8B2     Array of byte-long offsets, telling which walls are to be
 *               drawn from each of the 8 possible starting points within
 *               the maze (0=up, 2=down, 4=to right, 6=to left).  The 8
 *               possible starting points are shown below:
 *
 *                   -100 -60 -20 +20 +60 +100
 *                     +---+---+---+---+---+ +96
 *                     |                   |
 *                     +   o   o   o   o   + +32
 *                     |                   |
 *                     +   o   o   o   o   + -32
 *                     |                   |
 *                     +---+---+---+---+---+ -96
 *
 * C8B5-C8C3     Array of masks (1 per quadrant) indicating which walls are
 *               present in the quadrant.  The mask values are:
 *
 *                     0x01 = left wall
 *                     0x02 = right wall
 *                     0x04 = top wall
 *                     0x08 = bottom wall
 *
 *               C8B5 refers to quadrant 0, C8B6 to quadrant 1, etc.
 *
 * C8C5          Jump table index based on the player's current state:
 *
 *                     0 = player is alive
 *                     2 = player has left the maze
 *                     4 = player has died
 *
 * C8C6          Indicates if one of the maze doors should be closed off:
 *
 *                       ---------------------------------
 *                       | 0 | 0 | 0 | T | B | L | R | 0 |
 *                       ---------------------------------
 *                     Block Top Door--^
 *                     Block Bottom Door---^
 *                     Block Left Door---------^
 *                     Block Right Door------------^
 *
 * C8C7          Number of robots initially seeded into the maze
 *
 * C8C8          Number of robots still alive
 *
 * C8C9-C8CA     Indirect jump pointer
 *
 * C8CB          Intensity value used by DrawWithPossibleScrolling()
 *
 * C8CC          Index of the last bullet in use
 *
 * C8CD          Cleared in one place, then never again used.
 *
 * C8CE          Indicates state of player's legs:
 *
 *                     0 = player is standing still
 *                     2 = player is running right (wide legs)
 *                     4 = player is running right (close legs)
 *                     6 = player is running left (close legs)
 *                     8 = player is running left (wide legs)
 *
 * C8CF          Indicates the state of the player's arms:
 *
 *                  When player is running:
 *                     0x00 = arms moving to the right
 *                     0x02 = arms moving to the left
 *
 *                  When player is standing still:
 *                     0x00 = arms neutral
 *                     0x02 = arms shooting left
 *                     0x04 = arms shooting right
 *                     0x06 = arms shooting up
 *                     0x08 = arms shooting 45 degrees upper left
 *                     0x0A = arms shooting 45 degrees upper right
 *                     0x0C = arms shooting down
 *                     0x0E = arms shooting 45 degrees lower left
 *                     0x10 = arms shooting 45 degrees lower right
 *
 * C8D0          Intensity used when drawing a 'fried' player
 *
 * C8D1-C8D7     Bonus score string buffer
 *
 * C8D8-????     Buffer used when displaying number of lives a player has.
 *
 * C8DE          'y' delta between 2 points, as determined by
 *               DetermineDirectionToMove()
 *
 * C8DF          'x' delta between 2 points, as determined by
 *               DetermineDirectionToMove()
 *
 * C8E0          Used during scrolling; used to calculate 'y' delta
 *
 * C8E1          Used during scrolling; used to calculate 'x' delta
 *
 * C8E2-C8E3     Used during scrolling; delta added to 'y' drawing point
 *
 * C8E4-C8E5     Used during scrolling; delta added to 'x' drawing point
 *
 * C8E6          Used during scrolling; 0 if scrolling in a + direction (right
 *               or up), 0x80 if scrolling in a - direction (down or left)
 *
 * C8E7-C8E8     Work memory (used by DetermineDirectionToMove)
 *
 * C8E9          Loop counter
 *
 * C8EA          Mask showing joystick position and fire button state:
 *
 *                       ---------------------------------
 *                       | 0 | 0 | B | L | D | U | R | L |
 *                       ---------------------------------
 *                 Button Pressed--^
 *                 Joystick Left-------^---------------^
 *                 Joystick Down-----------^
 *                 Joystick Up-----------------^
 *                 Joystick Right------------------^
 *
 * C8EB          Direction current object is traveling (work memory):
 *
 *                       ---------------------------------
 *                       | 0 | 0 | 0 | L | D | U | R | L |
 *                       ---------------------------------
 *                 Joystick Left-------^---------------^
 *                 Joystick Down-----------^
 *                 Joystick Up-----------------^
 *                 Joystick Right------------------^
 *
 * C900-C90D     Player 1 structure
 * C90E-C91B     Player 2 structure
 *
 *               byte    meaning
 *               ----    -------
 *               0-6     player's score
 *               7       unused
 *               8       number of lives
 *               9       Flag specifying if 5000 point bonus was given
 *               10      player's y position
 *               11      player's x position
 *               12-13   unused
 *
 * C91C-C973     Array of robot structures (11 entries)
 *
 *               byte    meaning
 *               ----    -------
 *               0       robot's y position.
 *               1       robot's x position.
 *               2       flag: 0x80 = alive, 0 = gone, 0x0F = just killed
 *               3       direction of travel(0-10); indexes into extremities tbl
 *               4       Eye box to draw (0, 2, 4, 6)
 *               5       Delay before robot starts shooting (0-7)
 *               6       # of bullets robot can fire in a burst
 *               7       Delay between processing a robot (moving, firing, etc)
 *
 * C974-????     Array of bullet structures
 *
 *               byte    meaning
 *               ----    -------
 *               0       y position of bullet's tail
 *               1       x position of bullet's tail
 *               2       y delta between bullet's head and tail
 *               3       x delta between bullet's head and tail
 *               4       y position of bullet's head
 *               5       x position of bullet's head
 *               6       velocity factor
 *               7       direction of travel; anded w/ 0xF0 when hits something
 *
 ******************************************************************************
 */

                        .org 0x0000;
0000   67               .string "g GCE 1982",0x80;

000B   FD1D             .word #berzerk_music_block;

000D   F8               .byte 0xF8; /* height */
000E   50               .byte 0x50; /* width */
000F   20               .byte 0x20; /* rel y */
0010   D0               .byte 0xD0; /* rel x */
0011   42               .string "BERZERK",0x80,0x00;

                 /*
                  * Get the number of players: 1 or 2.
                  * C882 will be set to 0 for 1 player, and 1 for 2 players.
                  */
001A   CC0200    start: ldd   #0x0200;
001D   BDF7A9           jsr   $get_players_game;
0020   9679             lda   0x79;
0022   47               asra;
0023   9782             sta   0x82;

                 /*
                  * Disable 2 of the 4 joystick mask registers; the other
                  * 2 are enabled automatically by the ExecRom.
                  */
0025   0F21             clr   0x21;
0027   0F22             clr   0x22;
0029   BDF533           jsr   $init_music_buf;
002C   0F67             clr   0x67;

                 /*
                  * Initialize the 2 player's structures.
                  * Player 1 is C900-C90D, player 2 is C90E-C91B.
                  * The player's scores will be initialized, their
                  * number of lives set (3), and their initial positions
                  * set.
                  */
                 RestartBerzerk:
002E   BDF1AF           jsr   $dptoC8;
0031   0F9D             clr   0x9D;
0033   0C9D             inc   0x9D;
0035   8EC900           ldx   #0xC900;
0038   9F80             stx   0x80;
003A   8603      P003A: lda   #0x03;
003C   A708             sta   8,x;             /* Set number of lives */
003E   6F09             clr   9,x;             /* Clear 'bonus given' flag */
0040   BDF84F    P0040: jsr   $set_dft_score;  /* Set default score */
0043   8EC90E           ldx   #0xC90E;
0046   0A9D             dec   0x9D;
0048   2AF0             bpl   P003A;
004A   8EC900           ldx   #0xC900;
004D   CC00A5           ldd   #0x00A5;
0050   ED0A             std   10,x;            /* Set starting position */
0052   8EC90E           ldx   #0xC90E;
0055   CC005B           ldd   #0x005B;
0058   ED0A             std   10,x;            /* Set starting position */

                 /* Set initial robot attributes */
005A   86A0             lda   #0xA0;
005C   97A8             sta   0xA8;            /* Robot seeding threshold */
005E   8606             lda   #0x06;
0060   97A7      P0060: sta   0xA7;            /* Set robot processing delay */
0062   8601             lda   #0x01;           /* Start robot bullets with */
0064   9784             sta   0x84;            /* a low velocity factor */

                 /*
                  * This block takes care of setting up for the next turn,
                  * after a player has died.  It determines how the maze
                  * will look, displays the maze, the scores and the number
                  * of lives, and then does some music mucking.
                  */
                 StartNewTurn:
0066   863F             lda   #0x3F;         /* Set loop counter */
0068   9785             sta   0x85;
006A   8EC8C5           ldx   #0xC8C5;       /* Initialize game RAM */
006D   C626             ldb   #0x26;
006F   BDF53F           jsr   $clear_blockxb;
0072   BD0EF6           jsr   $DetermineMazeWalls;
0075   8EC8D1           ldx   #0xC8D1;       /* Initialize the bonus string */
0078   BDF84F           jsr   $set_dft_score;
007B   9E80             ldx   0x80;          /* Save the player's position */
007D   EC0A             ldd   10,x;
007F   DD8F             std   0x8F;
0081   A608             lda   8,x;           /* Display # of lives left */
0083   BD0315           jsr   $DisplayLives;

                 /*
                  * Display the maze, but not the player or the robots,
                  * and do some sound mucking; loop here for a while,
                  * before proceeding.
                  */
                 LoopWhileDisplayingMaze:
0086   0F86             clr   0x86;
0088   BD0D41           jsr   $DoUnknownSoundMucking;
008B   BDF687           jsr   $init_sound;
008E   9626             lda   0x26;
0090   8510             bita  #0x10;
0092   2602             bne   P0096;
0094   0A86             dec   0x86;
0096   BDF192    P0096: jsr   $waitrecal;
0099   BD0486           jsr   $DrawMaze;
009C   BDF289           jsr   $do_sound;
009F   BDF1AF           jsr   $dptoC8;
00A2   0A85             dec   0x85;
00A4   26E0             bne   LoopWhileDisplayingMaze;

                 /*
                  * Remove one of the player's lives, to take into account
                  * the life he is using now.
                  */
00A6   9E80             ldx   0x80;       /* Points to active player struct */
00A8   6A08             dec   8,x;
00AA   BDF533           jsr   $init_music_buf;
00AD   2006             bra   P00B5;

                 EnterNextMaze:
00AF   BDF1AF           jsr   $dptoC8;
00B2   BD0EF6           jsr   $DetermineMazeWalls;

00B5   862A      P00B5: lda   #0x2A;
00B7   9786             sta   0x86;
00B9   DE80             ldu   0x80;
00BB   EC4A             ldd   10,u;
00BD   DD8F             std   0x8F;      /* Save the player's position */
00BF   DD95             std   0x95;
00C1   8EC8E0           ldx   #0xC8E0;
00C4   C605             ldb   #0x05;
00C6   BDF53F           jsr   $clear_blockxb;
00C9   0F83             clr   0x83;
00CB   0A83             dec   0x83;

                 /*
                  * Based on the player's score, set the level of difficulty.
                  * If the score >= 10,000, then bump the difficulty by alot.
                  * After that, compare the 'thousands' portion of the score
                  * against the cutoff values in the table, and further bump
                  * for each cutoff value surpassed.
                  */
00CD   A641             lda   1,u;      /* Check if score >= 10,000 */
00CF   8120             cmpa  #0x20;
00D1   2704             beq   P00D7;
00D3   8606             lda   #0x06;    /* It is, so increase difficulty */
00D5   9783             sta   0x83;
00D7   EC42      P00D7: ldd   2,u;      /* Check the cutoff values */
00D9   8E0A2D           ldx   #SkillLevelCutoffs;
00DC   0C83      P00DC: inc   0x83;
00DE   6D84             tst   ,x;
00E0   2B05             bmi   P00E7;
00E2   10A381           cmpd  ,x++;
00E5   2CF5             bge   P00DC;

                 /*
                  * Initialize the bonus score string.
                  */
00E7   8EC8D1    P00E7: ldx   #0xC8D1;
00EA   BDF84F           jsr   $set_dft_score;

                 /*
                  * Do some processing based on the difficulty value calculated
                  * earlier (set the robot's bullet velocity and the robot
                  * processing delay).  Lastly, clear out the bullet structure.
                  */
00ED   9683             lda   0x83;         /* Max # of robot bullets */
00EF   8106             cmpa  #0x06;
00F1   2D02             blt   P00F5;
00F3   0C84             inc   0x84;         /* Robot bullet velocity factor */
00F5   47        P00F5: asra;
00F6   8006             suba  #0x06;
00F8   40               nega;
00F9   2A01             bpl   P00FC;
00FB   4F               clra;
00FC   97A7      P00FC: sta   0xA7;         /* Robot processing delay */
00FE   8EC974           ldx   #0xC974;      /* Init the bullet structure */
0101   BDF545           jsr   $clear_256_bytes;

                 /*
                  * This seeds the robot structure array.  It attempts to
                  * 'activate' a random number of robots.  If it fails to
                  * seed any robots, then it tries over again.
                  * The robot array is an array of structures, located
                  * at C91C-C973; there are 11 entries, each 8 bytes long.
                  * C8C7 keeps track of the number of robots initially
                  * seeded; C8C8 keeps track of the number of robots still
                  * alive.  A robot is seeded only if the generated random
                  * number is less than a pre-calculated threshold value.
                  */
0104   0FC7      P0104: clr   0xC7;
0106   C60B             ldb   #0x0B;
0108   8E0CE6           ldx   #RobotStartingPositionTable;
010B   CEC91C           ldu   #0xC91C;
010E   BDF517    P010E: jsr   $get_random_a;
0111   91A8             cmpa  0xA8;          /* Should we seed this robot? */
0113   2237             bhi   P014C;
0115   0CC7             inc   0xC7;          /* Bump the robot count */
0117   8680             lda   #0x80;
0119   A742             sta   2,u;           /* Flag the robot as alive */
011B   BDF517           jsr   $get_random_a;
011E   841F             anda  #0x1F;
0120   979D      P0120: sta   0x9D;
0122   8010             suba  #0x10;
0124   AB84             adda  ,x;
0126   A7C4             sta   ,u;            /* Set the y starting position */
0128   BDF517           jsr   $get_random_a;
012B   840F             anda  #0x0F;
012D   8008             suba  #0x08;
012F   AB01             adda  1,x;
0131   A741             sta   1,u;           /* Set the x starting position */
0133   6F43             clr   3,u;
0135   6F44             clr   4,u;
0137   BDF517           jsr   $get_random_a;
013A   8407             anda  #0x07;
013C   A745             sta   5,u;
013E   9683             lda   0x83;
0140   8106             cmpa  #0x06;
0142   2D02             blt   P0146;
0144   8006             suba  #0x06;
0146   A746      P0146: sta   6,u;
0148   6F47             clr   7,u;
014A   3348             leau  8,u;           /* Change ptr to the next robot */
014C   3002      P014C: leax  2,x;
014E   5A               decb;
014F   26BD             bne   P010E;
0151   96C7             lda   0xC7;
0153   27AF             beq   P0104;
0155   97C8             sta   0xC8;

                 /* Set value used during robot seeding */
0157   1F30             tfr   u,d;
0159   83C924           subd  #0xC924;
015C   D7AA             stb   0xAA;

                 /* Initialize Otto information */
015E   DC95             ldd   0x95;
0160   DD91             std   0x91;         /* Set Otto's initial position */
0162   DD93             std   0x93;         /* Set Otto's initial position */
0164   8605             lda   #0x05;
0166   9730             sta   0x30;
0168   8620             lda   #0x20;
016A   9797             sta   0x97;         /* Set Otto's sound loop counter */
016C   8601             lda   #0x01;
016E   9798             sta   0x98;         /* Set Otto's initial velocity */

                 /* Set up some counters */
0170   96C7             lda   0xC7;
0172   C650             ldb   #0x50;
0174   3D               mul;
0175   4D               tsta;
0176   2603             bne   P017B;
0178   8602             lda   #0x02;
017A   5F               clrb;
017B   DD2E      P017B: std   0x2E;

                 /* Main processing loop */
017D   0FC5             clr   0xC5;  /* Set jump idx to 'player is alive' */
017F   BDF192    P017F: jsr   $waitrecal;
0182   BDF1F8           jsr   $read_jstick;
0185   BDF1BA           jsr   $read_switches2;
0188   BDF289           jsr   $do_sound;
018B   BD0486           jsr   $DrawMaze;
018E   BDF1AF           jsr   $dptoC8;
0191   8E0198           ldx   #MainJumpTable;
0194   96C5             lda   0xC5;
0196   6E96             jmp   [a,x];    /* (UNKNOWN JUMP) */

                 MainJumpTable:
0198   01               .word PlayerIsAlive;
019A   09               .word PlayerHasLeftMaze;
019C   03               .word PlayerHasDied;

                 MakeSoundThenGotoMainLoop:
019E   0D56             tst   0x56;
01A0   2702             beq   P01A4;
01A2   0F67             clr   0x67;
01A4   BDF687    P01A4: jsr   $init_sound;
01A7   BD0D41           jsr   $DoUnknownSoundMucking;
01AA   9E2E             ldx   0x2E;
01AC   2702             beq   P01B0;
01AE   301F             leax  -1,x;
01B0   9F2E      P01B0: stx   0x2E;
01B2   20CB             bra   P017F;

                 /*
                  * This is one of the 'indirect jump' functions.  It is the
                  * active jump function while the player is alive.  It uses
                  * the state of the buttons and the joystick to decide how
                  * to draw the player.  It also attempts to detect whenever
                  * the player leaves a quadrant, to determine if the player
                  * has left the maze, or run into a wall.
                 PlayerIsAlive:
01B4   8EC88F           ldx   #0xC88F;
01B7   96E9             lda   0xE9;
01B9   2704             beq   ProcessJoystickAndButtons;
01BB   0AE9             dec   0xE9;
01BD   2053             bra   DoNotUpdatePlayerMovement;

                 /*
                  * Based on the joystick and button values, the 'b' register
                  * is set to the following mask:
                  *
                  *         ---------------------------------
                  *         | 0 | 0 | B | L | D | U | R | L |
                  *         ---------------------------------
                  *   Button Pressed--^
                  *   Joystick Left-------^---------------^
                  *   Joystick Down-----------^
                  *   Joystick Up-----------------^
                  *   Joystick Right------------------^
                  */
                 ProcessJoystickAndButtons:
01BF   5F               clrb;
01C0   961C             lda   0x1C;    /* Get joystick up/down setting */
01C2   2A04             bpl   P01C8;   /* 0=u/d neutral, -=down, +=up */
01C4   CB08             addb  #0x08;   /* Down */
01C6   2004             bra   P01CC;
01C8   2702      P01C8: beq   P01CC;
01CA   CB04             addb  #0x04;   /* Up */
01CC   961B      P01CC: lda   0x1B;    /* Get joystick left/right setting */
01CE   2A04             bpl   P01D4;   /* 0=l/r neutral, -=left, +=right)
01D0   CB11             addb  #0x11;   /* Left */
01D2   2004             bra   P01D8;
01D4   2702      P01D4: beq   P01D8;
01D6   CB02             addb  #0x02;   /* Right */
01D8   960F      P01D8: lda   0x0F;    /* Load button states */
01DA   2727             beq   NoBtnsPressed;
01DC   CA20             orb   #0x20;   /* Button pressed, but if joystick is */
01DE   C50F             bitb  #0x0F;   /* neutral, then do nothing. */
01E0   2730             beq   DoNotUpdatePlayerMovement;

                 /*
                  * The joystick is not in the neutral position, and a button
                  * is pressed, so the player is firing.
                  */
01E2   D7EA             stb   0xEA;    /* Save the joystick/button mask */
01E4   8608             lda   #0x08;
01E6   97E9             sta   0xE9;
01E8   C40F             andb  #0x0F;
01EA   D7EB             stb   0xEB;    /* Save just the joystick mask */
01EC   8606             lda   #0x06;
01EE   BD0939           jsr   $CalculateUpdatedPosition;
01F1   DD9E             std   0x9E;
01F3   8EC89E           ldx   #0xC89E;
01F6   C603             ldb   #0x03;
01F8   BD0333           jsr   $FireBullet;
01FB   8601             lda   #0x01;
01FD   9A67             ora   0x67;
01FF   9767             sta   0x67;
0201   200F             bra   DoNotUpdatePlayerMovement;

                 NoBtnsPressed:
0203   D7EA             stb   0xEA;   /* Save the joystick/button mask */
0205   9626             lda   0x26;
0207   8502             bita  #0x02;
0209   2607             bne   DoNotUpdatePlayerMovement;
020B   8601             lda   #0x01;
020D   BD0939           jsr   $CalculateUpdatedPosition;
0210   ED84             std   ,x;

                 /*
                  * If none of the buttons are pressed, and if the joystick
                  * is in neutral, then reset the players arms and legs to
                  * the 'neutral' position.
                  */
                 DoNotUpdatePlayerMovement:
0212   96EA             lda   0xEA;
0214   2606             bne   CheckIfFiring;
0216   0FCE             clr   0xCE;
0218   0FCF             clr   0xCF;
021A   2027             bra   CheckForPlayerLeavingQuadrant;

                 /*
                  * If a button was pressed, then we know the player was
                  * firing, so we can force his legs to the neutral position,
                  * and can set his arms to be shooting in the appropriate
                  * direction.
                  */
                 CheckIfFiring:
021C   8520             bita  #0x20;
021E   270D             beq   NotFiringButMoving;
0220   0FCE             clr   0xCE;   /* Force player to stand still */
0222   CE0A3C           ldu   #ArmsShootingIndicesTable;
0225   840F             anda  #0x0F;
0227   E6C6             ldb   a,u;
0229   D7CF             stb   0xCF;   /* Set player's arms accordingly */
022B   2016             bra   CheckForPlayerLeavingQuadrant;

                 /*
                  * We know that the player is on the move.  We will therefore
                  * make his arms swing left and right, and we will draw his
                  * legs so it appears he is running in the desired direction.
                  * The timing for changing the arms and legs is controlled by
                  * bit 0x08 of C826, which is a counter controlled by the
                  * Exec Rom.
                  *
                  * For the arms:
                  *
                  *        0 = 'arms to the right'
                  *        2 = 'arms to the left'
                  *
                  * For the legs:
                  *
                  *        2 = 'running right with wide legs'
                  *        4 = 'running right with close legs'
                  *        6 = 'running left with wide legs'
                  *        8 = 'running left with close legs'
                  */
                 NotFiringButMoving:
022D   8410             anda  #0x10;   /* a = joystick/button mask */
022F   3402             pshs  a;
0231   9626             lda   0x26;
0233   8408             anda  #0x08;
0235   1F89             tfr   a,b;     /* Get a value of 0 or 2, to control */
0237   57               asrb;          /* which arms get drawn.             */
0238   57               asrb;
0239   D7CF             stb   0xCF;
023B   AAE0             ora   ,s+;     /* Get a value of 2, 4, 6 or 8, to */
023D   47               asra;          /* control which legs get drawn.   */
023E   47               asra;
023F   8B02             adda  #0x02;
0241   97CE             sta   0xCE;

                 /*
                  * Take the player's position, and map it into:
                  *
                  *   1) the quadrant the player is in (C89A),
                  *   2) the relative position within that quadrant (C89B-C89C)
                  *   3) the bitmask indicating which walls are present for
                  *      the quadrant (C899).
                  *
                  * If it is determined that there was contact with a wall,
                  * then do some special checks to see if the wall was really
                  * a door; if it was a door, and the door was not blocked off,
                  * then exit to the next maze.
                  */
                 CheckForPlayerLeavingQuadrant:
0243   DC8F             ldd   0x8F;
0245   BD0F98           jsr   $MapPointToQuadrantAndMakeRelative;
0248   8E0EEA           ldx   #PlayerThresholds;
024B   BD0EC7           jsr   $CheckForQuadrantEdgeCrossing;
024E   D599             bitb  0x99;
0250   2756             beq   NoContactWithWalls;

                  /* Check for passing out the top door */
0252   969A             lda   0x9A;
0254   8102             cmpa  #0x02;   /* If quad 2, check for up door */
0256   260C             bne   P0264;
0258   96C6             lda   0xC6;    /* Check if door is blocked */
025A   8510             bita  #0x10;
025C   263D             bne   PlayerHitWall;
025E   C404             andb  #0x04;   /* Top wall (door) passed thru? */
0260   2739             beq   PlayerHitWall;
0262   202E             bra   ExitMaze;

                 /* Check for passing out the left door */
0264   8105      P0264: cmpa  #0x05;   /* If quad 5, check for left door */
0266   260C             bne   P0274;
0268   96C6             lda   0xC6;
026A   8504             bita  #0x04;   /* Check if door is blocked */
026C   262D             bne   PlayerHitWall;
026E   C401             andb  #0x01;   /* Left wall (door) passed thru ? */
0270   2729             beq   PlayerHitWall;
0272   201E             bra   ExitMaze;

                 /* Check for passing out the right door */
0274   8109      P0274: cmpa  #0x09;   /* If quad 9, check for right door */
0276   260C             bne   P0284;
0278   96C6             lda   0xC6;
027A   8502             bita  #0x02;   /* Check if door is blocked */
027C   261D             bne   PlayerHitWall;
027E   C402             andb  #0x02;   /* Right wall (door) passed thru ? */
0280   2719             beq   PlayerHitWall;
0282   200E             bra   ExitMaze;

                 /* Check for passing out the bottom door */
0284   810C      P0284: cmpa  #0x0C;   /* If quad 12, check for bottom door */
0286   2613             bne   PlayerHitWall;
0288   96C6             lda   0xC6;
028A   8508             bita  #0x08;   /* Check if door is blocked */
028C   260D             bne   PlayerHitWall;
028E   C408             andb  #0x08;   /* Bottom wall (door) passed thru ? */
0290   2709             beq   PlayerHitWall;

                 /*
                  * The player has successfully exited from the maze; change
                  * the jump index so that the code is called which scrolls
                  * the maze off the display.
                  */
                 ExitMaze:
0292   D7EA             stb   0xEA;
0294   C602             ldb   #0x02;
0296   D7C5             stb   0xC5;
0298   7E019E           jmp   $MakeSoundThenGotoMainLoop;

                 /*
                  * The player died by walking into a wall; change the
                  * jump index so that the code which shows the player being
                  * fried, is called.
                  */
                 PlayerHitWall:
029B   8608             lda   #0x08;
029D   9A67             ora   0x67;
029F   9767             sta   0x67;
02A1   C604             ldb   #0x04;
02A3   D7C5             stb   0xC5;
02A5   7E019E           jmp   $MakeSoundThenGotoMainLoop;

                 /*
                  * The player did not make contact with any walls, so all
                  * is well.  Starting at the end of the bullet array, work
                  * back until we find an active bullet, then update the
                  * bullet counter in C8CC.
                  */
                 NoContactWithWalls:
02A8   BD0825           jsr   $ProcessAndUpdateBullets;
02AB   BD064A           jsr   $ProcessAndUpdateRobots;
02AE   D6CC             ldb   0xCC;
02B0   271A             beq   CheckForExtraLifeBonus;
02B2   5A               decb;
02B3   8608             lda   #0x08;
02B5   3D               mul;
02B6   8EC974           ldx   #0xC974;  /* Start at the end of the bullet */
02B9   3A               abx;            /* array. */
02BA   A607      P02BA: lda   7,x;
02BC   850F             bita  #0x0F;
02BE   260C             bne   CheckForExtraLifeBonus;
02C0   8580             bita  #0x80;
02C2   2700             beq   P02C4;
02C4   0ACC      P02C4: dec   0xCC;
02C6   2704             beq   CheckForExtraLifeBonus;
02C8   3018             leax  -8,x;
02CA   20EE             bra   P02BA;

                 /*
                  * Display the number lives the player has, and then check
                  * to see if the player has earned an extra life (awarded
                  * for each 5000 points); if so, then award the extra life,
                  * and play a little tune.  The bonus check happens by
                  * comparing the thousands digit of the score to ascii '5'.
                  */
                 CheckForExtraLifeBonus:
02CC   9E80             ldx   0x80;
02CE   A608             lda   8,x;
02D0   8D43             bsr   $DisplayLives;
02D2   6D09             tst   9,x;      /* Semaphore; only do once */
02D4   2610             bne   CheckForClearedLevelBonus;
02D6   8635             lda   #0x35; /* "5" */
02D8   A102             cmpa  2,x;
02DA   2E0A             bgt   CheckForClearedLevelBonus;
02DC   6C08             inc   8,x;      /* Award the extra life */
02DE   6C09             inc   9,x;      /* Set the semaphore */
02E0   CEFF44           ldu   #0xFF44;  /* Play a tune */
02E3   BDF68D           jsr   $init_sound2;

                 /*
                  * Check to see if the player has cleared out all of
                  * the robots; if so, then award a bonus, and display
                  * the bonus string.  Some fancy manipulation is done
                  * to convert the integer into a BCD string value.
                  */
                 CheckForClearedLevelBonus:
02E6   0DC8             tst   0xC8;    /* Any robots left? */
02E8   2628             bne   P0312;
02EA   8602             lda   #0x02;   /* All robots have been cleared out */
02EC   9598             bita  0x98;
02EE   2622             bne   P0312;
02F0   0C98             inc   0x98;    /* Increment Otto's velocity */
02F2   4F               clra;
02F3   D6C7             ldb   0xC7;    /* Get the starting count of robots */
02F5   C10A             cmpb  #0x0A;
02F7   2D04             blt   P02FD;
02F9   C00A             subb  #0x0A;   /* Handle counts >= 10 specially */
02FB   CA10             orb   #0x10;
02FD   58        P02FD: aslb;          /* Convert to BCD string value */
02FE   49               rola;
02FF   58               aslb;
0300   49        P0300: rola;
0301   58               aslb;
0302   49               rola;
0303   58               aslb;
0304   49               rola;
0305   3406             pshs  a,b;     /* Add bonus to player's score */
0307   BDF87C           jsr   $add_d_to_x_in_bcd;
030A   3506             puls  a,b;
030C   8EC8D1           ldx   #0xC8D1;  /* Place value into the bonus string */
030F   BDF87C           jsr   $add_d_to_x_in_bcd;
0312   7E019E    P0312: jmp   $MakeSoundThenGotoMainLoop;

                 /*
                  * DisplayLives()
                  *
                  * Entry:
                  *   a = number of lives
                  *
                  * Displays a string of 'little men', one for each live
                  * the user has.  The buffer into which the string is
                  * placed starts at C8D8.
                  *
                  *  BUG ALERT: there is no check to see if the C8D8 buffer
                  *             is overrun; what is the intended size of this
                  *             buffer?
                  */
                 DisplayLives:
0315   5F               clrb;
0316   CEC8D8           ldu   #0xC8D8;     /* String buffer */
0319   979D             sta   0x9D;
031B   2709             beq   P0326;
031D   8669             lda   #0x69;       /* 'little man' icon */
031F   A7C5      P031F: sta   b,u;
0321   5C               incb;
0322   D19D             cmpb  0x9D;
0324   2DF9             blt   P031F;
0326   8620      P0326: lda   #0x20;
0328   A7C5             sta   b,u;         /* Terminate string with 2 spaces */
032A   5C               incb;              /* and 0x80.                      */
032B   A7C5             sta   b,u;
032D   5C               incb;
032E   8680             lda   #0x80;
0330   A7C5             sta   b,u;
0332   39               rts;

                 /*
                  * FireBullet()
                  *
                  * This function attempts to fire a bullet from the indicated
                  * position, using the specified velocity.  However, if the
                  * bullet would immediately hit a wall, then it is not fired.
                  *
                  * Entry:
                  *    b = bullet's velocity factor (a value indicating how
                  *        often the bullet's position is updated for each
                  *        pass).
                  *    x = Bullet's starting position.
                  *    C8EB = direction of travel for the bullet.
                  */
                 FireBullet:
0333   D79D             stb   0x9D;
0335   3450             pshs  x,u;
0337   EC84             ldd   ,x;
0339   BD0F98           jsr   $MapPointToQuadrantAndMakeRelative;
033C   8E0EEE           ldx   #BulletThresholds;
033F   BD0EC7           jsr   $CheckForQuadrantEdgeCrossing;
0342   3510             puls  x;        /* Don't fire if bullet will */
0344   D599             bitb  0x99;     /* immediately hit a wall.   */
0346   2621             bne   P0369;
0348   D6CC             ldb   0xCC;     /* Point to the next available bullet */
034A   8608             lda   #0x08;
034C   3D               mul;
034D   CEC974           ldu   #0xC974;
0350   33C5             leau  b,u;
0352   96EB             lda   0xEB;
0354   A747             sta   7,u;      /* Store bullet's direction */
0356   969D             lda   0x9D;
0358   A746             sta   6,u;      /* Store velocity factor */
035A   EC84             ldd   ,x;
035C   EDC4             std   ,u;       /* Set bullet's tail position */
035E   D6EB             ldb   0xEB;
0360   8602             lda   #0x02;
0362   BD0939           jsr   $CalculateUpdatedPosition;
0365   ED44             std   4,u;      /* Set bullet's head position */
0367   0CCC             inc   0xCC;     /* Increment the bullet count */
0369   35C0      P0369: puls  u,pc;

                 /*
                  * This is one of the 'indirect jump' functions.  It is the
                  * active jump function when the player gets killed.  It
                  * will cause the player to be drawn with a variety of
                  * intensities (simulating electrocution), and will update
                  * the current high score, if necessary.  It then resets
                  * the starting positions for the players, and tries to
                  * determine whose turn it is next.  If there are two
                  * players, then it tries to switch to the other player,
                  * unless that player has 0 lives left; in that case, it
                  * will stick with the current player, unless he, too, has
                  * 0 lives left, at which point the game ends, and it
                  * waits for either the user to press a button to restart
                  * the game, or a timeout to elapse (to cold start the
                  * system).
                  */
                 PlayerHasDied:
036B   0FEA             clr   0xEA;
036D   0FCD             clr   0xCD;
036F   BD064A           jsr   $ProcessAndUpdateRobots;
0372   BD0825           jsr   $ProcessAndUpdateBullets;
0375   9686             lda   0x86;
0377   840F             anda  #0x0F;
0379   CE0D0B           ldu   #PlayerFriedIntensities;
037C   E6C6             ldb   a,u;
037E   D7D0             stb   0xD0;    /* Save off next intensity value */
0380   0A86             dec   0x86;
0382   102AFE18         lbpl  MakeSoundThenGotoMainLoop;
0386   86A0             lda   #0xA0;
0388   97A8             sta   0xA8;
038A   9E80             ldx   0x80;    /* Check for new high score */
038C   CECBEB           ldu   #0xCBEB;
038F   BDF8D8           jsr   $check_4_new_hi_score;

                 /* Loop, doing some music mucking */
0392   8650             lda   #0x50;
0394   9785             sta   0x85;
0396   0F86             clr   0x86;
0398   0A86             dec   0x86;
039A   BD0774    P039A: jsr   $CheckForOttoStart;
039D   BD0D41           jsr   $DoUnknownSoundMucking;
03A0   BDF192           jsr   $waitrecal;
03A3   BD0486           jsr   $DrawMaze;
03A6   BDF289           jsr   $do_sound;
03A9   BDF1AF           jsr   $dptoC8;
03AC   0A85             dec   0x85;
03AE   26EA             bne   P039A;

                  /* Reset player's starting positions */
03B0   8EC900           ldx   #0xC900;   /* Player 1 */
03B3   CC00A5           ldd   #0x00A5;
03B6   ED0A             std   10,x;
03B8   8EC90E           ldx   #0xC90E;   /* Player 2 */
03BB   CC005B           ldd   #0x005B;
03BE   ED0A             std   10,x;

                  /* Determine whose turn it is */
03C0   0FC6             clr   0xC6;    /* Start with no door blocked */
03C2   0D82             tst   0x82;    /* Two player game? */
03C4   2713             beq   P03D9;
03C6   8EC900           ldx   #0xC900; /* Yes */
03C9   0D81             tst   0x81;    /* Is player 2 the active player? */
03CB   2603             bne   P03D0;
03CD   8EC90E           ldx   #0xC90E; /* No, so change to player 2 */
03D0   6D08      P03D0: tst   8,x;     /* Does this player have any lives? */
03D2   2705             beq   P03D9;
03D4   9F80             stx   0x80;    /* Yep; so let this player play */
03D6   7E0066           jmp   $StartNewTurn
03D9   9E80      P03D9: ldx   0x80;    /* Nope; so see if original player */
03DB   6D08             tst   8,x;     /* had any lives left.             */
03DD   1026FC85         lbne  $StartNewTurn

                 /* The game is over; loop waiting for next game  */
03E1   0F9F             clr   0x9F;      /* Clear the Easter Egg semaphore */
03E3   8E0C00           ldx   #0x0C00;   /* How long to wait for restart */

                 LoopWaitingForRestart:
03E6   9F9D             stx   0x9D;
03E8   BD0D41           jsr   $DoUnknownSoundMucking;
03EB   BDF192           jsr   $waitrecal;
03EE   BDF2A5           jsr   $intensity_to_5F;
03F1   BDF289           jsr   $do_sound;
03F4   7DC89F           tst   $C89F;
03F7   2706             beq   $DisplayHighScore;

                 /* Display the Easter Egg */
03F9   CE0CDE           ldu   #AuthorsInitials;
03FC   BDF373           jsr   $print_1_string;

                 /*
                  * Display the current high score, along with the scores
                  * for players 1 and 2.
                  */
                 DisplayHighScore:
03FF   CE046D           ldu   #HighScoreString;
0402   BDF373           jsr   $print_1_string;
0405   CECBEB           ldu   #0xCBEB;          /* height & width */
0408   CC60E0           ldd   #0x60E0;          /* rel y & rel x */
040B   BDF37A           jsr   $print_at_d;
040E   BD0632           jsr   $DisplayBothPlayersScore;

                 /*
                  * Display "Got You Humanoid" 4 times.
                  */
0411   108E047C         ldy   #HumanoidStringPositions;
0415   ECA1             ldd   ,y++;
0417   FDC82A           std   $C82A;
041A   ECA1             ldd   ,y++;
041C   CE045C           ldu   #HumanoidString;
041F   3440             pshs  u;
0421   BDF37A           jsr   $print_at_d;
0424   3540             puls  u;
0426   ECA1             ldd   ,y++;
0428   BDF37A           jsr   $print_at_d;
042B   3440             pshs  u;
042D   ECA1             ldd   ,y++;
042F   BDF37A           jsr   $print_at_d;
0432   ECA1             ldd   ,y++;
0434   3540             puls  u;
0436   BDF37A           jsr   $print_at_d;

                 /*
                  * If only buttons 1, 3 and 4 are pressed, toggle the
                  * flag (C89F) which will cause the author's initials
                  * to be displayed (Easter Egg).  Otherwise, if any buttons
                  * are pressed, then restart the game.  If no buttons are
                  * pressed, then eventually (after a predetermined
                  * amount of time), jump back to the start of the
                  * Exec Rom.  Note that if the Easter Egg gets enabled,
                  * then pressing buttons will not restart a new game;
                  * you must wait for the timeout to expire.
                  */
0439   BDF1BA           jsr   $read_switches2;
043C   BDF1AF           jsr   $dptoC8;
043F   0D9F             tst   0x9F;          /* Bypass if Easter Egg active */
0441   2610             bne   P0453;
0443   960F             lda   0x0F;          /* Button states */
0445   880D             eora  #0x0D;         /* Mask for buttons 1, 3 and 4 */
0447   2604             bne   P044D;
0449   0C9F             inc   0x9F;          /* Turn on the Easter egg */
044B   2006             bra   P0453;
044D   960F      P044D: lda   0x0F;          /* Button states */
044F   1026FBDB         lbne  RestartBerzerk;
0453   9E9D      P0453: ldx   0x9D;          /* Decrement timer */
0455   301F             leax  -1,x;
0457   268D             bne   LoopWaitingForRestart;
0459   7EF000           jmp   $start_of_OS_ROM;

                 HumanoidString:
045C   47               .string "GOT YOU HUMANOID",0xFF;

                 HighScoreString:
046D   F8               .byte 0xF8; /* height */
046E   38               .byte 0x38; /* width */
046F   70               .byte 0x70; /* rel y */
0470   D8               .byte 0xD8; /* rel x */
0471   48               .string "HIGH SCORE ";

                 HumanoidStringPositions:
047C   F2               .byte 0xF2; /* rel y */
047D   4A               .byte 0x4A; /* rel x */
047E   22               .byte 0x22; /* rel y */
047F   D8               .byte 0xD8; /* rel x */
0480   20               .byte 0x20; /* rel y */
0481   D8               .byte 0xD8; /* rel x */
0482   00               .byte 0x00; /* rel y */
0483   CF               .byte 0xCF; /* rel x */
0484   FE               .byte 0xFE; /* rel y */
0485   CF               .byte 0xCF; /* rel x */

                 /*
                  * Draw the outer and inner maze walls, and if necessary,
                  * block off one of the maze doors.
                  */
                 DrawMaze:
0486   7CC824           inc   $C824;
0489   BDF2A5           jsr   $intensity_to_5F;
048C   8EF3DD           ldx   #draw_VL_with_count1;
048F   BFC8C9           stx   $C8C9;        /* Indirect jump pointer */
0492   867F             lda   #0x7F;
0494   B7C8CB           sta   $C8CB;        /* Drawing intensity */

                 /* Draw 4 sets of vectors making up outer maze walls */
0497   C604             ldb   #0x04;
0499   E771             stb   -15,s;        /* Loop counter */
049B   CE0B0B           ldu   #OutsideMazeWallData;
049E   8601      P049E: lda   #0x01;        /* Vector count - 1 */
04A0   B7C823           sta   $C823;
04A3   AE42             ldx   2,u;          /* Pointer to vector table */
04A5   BD08C7           jsr   $DrawWithPossibleScrolling;
04A8   3344             leau  4,u;          /* Process to next wall */
04AA   6A71             dec   -15,s;
04AC   26F0             bne   P049E;

                 /* Draw the 8 inner walls */
04AE   7FC823           clr   $C823;
04B1   8608             lda   #0x08;
04B3   A771             sta   -15,s;        /* Loop counter */
04B5   108EC8AB         ldy   #0xC8AB;      /* Array of wall indicies */
04B9   CE0B1B           ldu   #InnerWallPositionTable;
04BC   E6A0      P04BC: ldb   ,y+;
04BE   8E0B3B           ldx   #InnerWallVectorTable;
04C1   3A               abx;
04C2   BD08C7           jsr   $DrawWithPossibleScrolling;
04C5   3342             leau  2,u;          /* Process next segment */
04C7   6A71             dec   -15,s;
04C9   26F1             bne   P04BC;

                 /* Block off one door, if signaled to do so */
04CB   CE0AE9           ldu   #BlockedDoorVectorTable;
04CE   B6C8C6           lda   $C8C6;        /* Door to block, if any */
04D1   2708             beq   DisplayBonusString;
04D3   EEC6             ldu   a,u;
04D5   3042             leax  2,u;
04D7   4F               clra;
04D8   BD08C7           jsr   $DrawWithPossibleScrolling;

                 /*
                  * If the player killed all of the robots, then display
                  * a message telling them they got a bonus.  We can tell
                  * if we need to display the bonus string, by checking to
                  * to see if the second digit in the bonus string is not '0'
                  * ("    x0" is the default, where 'x' is initially set to
                  * a space, but will be a digit when the bonus string has
                  * been assigned a value).
                  *
                  * BUG ALERT: when the above check occurs, the 'ble' command
                  *            really should be a 'blt'!!  This explains why
                  *            when a player clears a maze containing 10
                  *            robots, the bonus string was not displayed.
                  *            In this case the bonus string is "   100",
                  *            and this fails the above check!
                  */
                 DisplayBonusString:
04DB   CCF838           ldd   #0xF838;
04DE   FDC82A           std   $C82A;          /* Set height & width */
04E1   B6C8D5           lda   $C8D5;
04E4   8130             cmpa  #0x30;
04E6   2F0F             ble   DrawActivePieces;
04E8   CE0AE1           ldu   #BonusString;
04EB   BDF378           jsr   $print_with_dft_hw;
04EE   CC70F0           ldd   #0x70F0;        /* rel y & rel x */
04F1   CEC8D1           ldu   #0xC8D1;        /* Bonus score buffer */
04F4   BDF37A           jsr   $print_at_d;

                 /*
                  * Display both player's scores, and depending upon the
                  * active player, display the number of lives for that
                  * player.
                  */
                 DrawActivePieces:
04F7   BD0632           jsr   $DisplayBothPlayersScore;
04FA   CCF820           ldd   #0xF820;        /* Set height & width */
04FD   FDC82A           std   $C82A;
0500   CEC8D8           ldu   #0xC8D8;        /* Display # of lives */
0503   7DC881           tst   $C881;
0506   2708             beq   P0510;
0508   CC9840           ldd   #0x9840;        /* Player 2 rel y & rel x */
050B   BDF37A           jsr   $print_at_d;
050E   2006             bra   DrawActiveBullets;
0510   CC98A0    P0510: ldd   #0x98A0;        /* Player 1 rel y & rel x */
0513   BDF37A           jsr   $print_at_d;

                 /* Draw all active bullets */
                 DrawActiveBullets:
0516   CEC974           ldu   #0xC974;        /* Bullet array */
0519   B6C8CC           lda   $C8CC;          /* Bullet count */
051C   2714      P051C: beq   DrawAliveRobots;
051E   A771             sta   -15,s;
0520   E647             ldb   7,u;
0522   C40F             andb  #0x0F;
0524   2705             beq   P052B;
0526   3042             leax  2,u;            /* Ptr to vector list */
0528   BD08C7           jsr   $DrawWithPossibleScrolling;
052B   3348      P052B: leau  8,u;
052D   A671             lda   -15,s;
052F   4A               deca;
0530   20EA             bra   P051C;

                 /*
                  * Draw All robots.  When drawing the robot, it is drawn
                  * in two halves; first the right half, and then the left
                  * half.  When each half is drawn, that half of the body
                  * outline is drawn, and then the extremities are drawn
                  * (legs and feet).  The extremities are dependent upon
                  * whether the robot is moving or standing still (searching
                  * for the player).  The last thing drawn is the robot's
                  * eye box; this, too, is dependent upon whether the robot
                  * moving or standing still.  When moving, the eye box is
                  * aimed in the direction of movement (exception is down,
                  * in which case no eye box is displayed).  When the robot
                  * is searching for the player, the eye box will shuffle
                  * through all of the available positions.
                  */
                 DrawAliveRobots:
0532   B6C8C7           lda   $C8C7;         /* Number of robots */
0535   102700AE         lbeq  DrawThePlayer;
0539   A771             sta   -15,s;
053B   CEC91C           ldu   #0xC91C;       /* Robot structure */
053E   6D47      P053E: tst   7,u;
0540   2702             beq   P0544;
0542   6A47             dec   7,u;
0544   A642      P0544: lda   2,u;
0546   10270074         lbeq  P05BE;
054A   2A4D             bpl   DrawRobotDisappearing;
054C   7FC824           clr   $C824;
054F   8604             lda   #0x04;
0551   B7C8CB           sta   $C8CB;       /* Set drawing intensity */
0554   108E0A67         ldy   #RobotExtremitiesVectorTable;
0558   A643             lda   3,u;
055A   48               asla;
055B   10AEA6           ldy   a,y;         /* Get correct robot extremities */
055E   8E0619           ldx   #DrawRobotRightHalf;
0561   BFC8C9           stx   $C8C9;       /* Set drawing function */
0564   BD08C7           jsr   $DrawWithPossibleScrolling;
0567   3126             leay  6,y;         /* Get correct robot extremities */
0569   8E0614           ldx   #DrawRobotLeftHalf;
056C   BFC8C9           stx   $C8C9;       /* Set drawing function */
056F   BD08C7           jsr   $DrawWithPossibleScrolling;
0572   3126             leay  6,y;
0574   7CC824           inc   $C824;
0577   8EF3BC           ldx   #move_then_draw_VL_with_count5;
057A   BFC8C9           stx   $C8C9;       /* Set drawing function */
057D   8604             lda   #0x04;       /* Vector count - 1 */
057F   B7C823           sta   $C823;
0582   A644             lda   4,u;         /* Get correct eye box to draw */
0584   8406             anda  #0x06;
0586   AEA6             ldx   a,y;
0588   EC84             ldd   ,x;
058A   2703             beq   P058F;
058C   BD08C7           jsr   $DrawWithPossibleScrolling;  /* Draw eye box */
058F   3348      P058F: leau  8,u;
0591   6A71             dec   -15,s;
0593   1026FFA7         lbne  P053E;
0597   202D             bra   P05C6;

                 /*
                  * When a robot is killed, it is replaced by a cloud of
                  * random dots.
                  */
                 DrawRobotDisappearing:
0599   BDF517           jsr   $get_random_a;
059C   1F89             tfr   a,b;
059E   4F               clra;
059F   1F01             tfr   d,x;
05A1   8606             lda   #0x06;
05A3   A779             sta   -7,s;
05A5   ECC4      P05A5: ldd   ,u;           /* Get the robot's position */
05A7   BDF2FC           jsr   $move_pen7F_to_d;
05AA   E680             ldb   ,x+;
05AC   C407             andb  #0x07;
05AE   A680             lda   ,x+;
05B0   8407             anda  #0x07;
05B2   BDF2C3           jsr   $dot_at_d;    /* Draw random dot */
05B5   BDF354           jsr   $reset0ref;
05B8   6A79             dec   -7,s;
05BA   26E9             bne   P05A5;
05BC   6A42             dec   2,u;          /* Prepare for next pass */

                 /* Process next robot structure */
05BE   3348      P05BE: leau  8,u;
05C0   6A71             dec   -15,s;
05C2   1026FF78         lbne  P053E;

                 /*
                  * If the player has been in the maze for a certain amount
                  * of time, then it's time to bring out 'Otto'!
                  */
05C6   7DC82E    P05C6: tst   $C82E;
05C9   261C             bne   DrawThePlayer;
05CB   7DC82F           tst   $C82F;
05CE   2617             bne   DrawThePlayer;
05D0   7CC824           inc   $C824;
05D3   8614             lda   #0x14;
05D5   B7C8CB           sta   $C8CB;       /* Drawing intensity */
05D8   8EF410           ldx   #next_pt;
05DB   BFC8C9           stx   $C8C9;       /* Drawing function */
05DE   8E0B99           ldx   #OttoVectors;
05E1   CEC893           ldu   #0xC893;     /* Otto's position */
05E4   BD08C7           jsr   $DrawWithPossibleScrolling;

                 /*
                  * Unless C886 < 0, draw the player.  If the player is in
                  * the middle of getting fried, then redraw the player again,
                  * using a higher intensity.
                  */
                 DrawThePlayer:
05E7   7DC886           tst   $C886;       /* Should player be drawn? */
05EA   2B27             bmi   P0613;
05EC   8E09EF           ldx   #DrawPlayerFunction;
05EF   BFC8C9           stx   $C8C9;       /* Drawing function */
05F2   8609             lda   #0x09;
05F4   B7C8CB           sta   $C8CB;       /* Drawin intensity */
05F7   CEC88F           ldu   #0xC88F;     /* Player's position */
05FA   BD08C7           jsr   $DrawWithPossibleScrolling; /* Draw the player */
05FD   BDF354           jsr   $reset0ref;
0600   B6C8C5           lda   $C8C5;       /* See if player is being fried */
0603   8104             cmpa  #0x04;
0605   260C             bne   P0613;
0607   B6C8D0           lda   $C8D0;       /* Being fried */
060A   B7C8CB           sta   $C8CB;       /* Set higher drawing intensity */
060D   BD08C7           jsr   $DrawWithPossibleScrolling; /* Draw player again*/
0610   BDF354           jsr   $reset0ref;
0613   39        P0613: rts;

                 /*
                  * DrawRobotLeftHalf()
                  * DrawRobotRightHalf()
                  *
                  * These functions draw the indicated half of a robot.
                  *
                  * Entry:
                  *    y = Ptr to robot extremity table
                  *    u = Ptr to robot structure
                  */

                 DrawRobotLeftHalf:
0614   8E0B5E           ldx   #RobotLeftHalf;
0617   2003             bra   P061C;

                 DrawRobotRightHalf:
0619   8E0B43           ldx   #RobotRightHalf;
061C   BDF3AD    P061C: jsr   $move_then_draw_VL_with_count1;
061F   A644             lda   4,u;
0621   8402             anda  #0x02;
0623   AEA6             ldx   a,y;             /* Robot legs */
0625   8601             lda   #0x01;           /* Vector count - 1 */
0627   BDF3DA           jsr   $draw_VL_with_count5;
062A   AE24             ldx   4,y;             /* Robot foot */
062C   BDF3DD           jsr   $draw_VL_with_count1;
062F   7EF354           jmp   $reset0ref;

                 /*
                  * DisplayBothPlayersScore()
                  *
                  * This displays player 1's score, and if 2 players are
                  * playing, then player 2's score also.
                  */
                 DisplayBothPlayersScore:
0632   CC7086           ldd   #0x7086;        /* rel y & rel x */
0635   CEC900           ldu   #0xC900;        /* player 1 structure */
0638   BDF37A           jsr   $print_at_d;
063B   7DC882           tst   $C882;          /* 2 players? */
063E   2709             beq   P0649;
0640   CC7024           ldd   #0x7024;        /* rel y & rel x */
0643   CEC90E           ldu   #0xC90E;        /* player 2 structue */
0646   BDF37A           jsr   $print_at_d;
0649   39        P0649: rts;

                 /*
                  * ProcessAndUpdateRobots()
                  *
                  * This function loops through each of the robots, and
                  * determines where the robot is relative to the player,
                  * and will alter the robot's position (based on some
                  * criteria), and will determine if it is safe to fire
                  * at the player.  It also checks to see if the robot has
                  * hit a wall, collided with another robot or collided with
                  * the player.  Lastly, it updates Otto's position, if
                  * necessary, and checks to see if Otto has collided with
                  * the player.
                  *
                  * The robot will only fire if either it is 90 degrees or
                  * 45 degrees from the player; 45 degrees occurs when
                  * |x delta| == |y delta|.
                  *
                  * As the robot is moving, if it is in a different quad
                  * from the player, then it will only update it's position
                  * (in an attempt to avoid running into walls) when it is
                  * not in the center of the quadrant.
                  */
                 ProcessAndUpdateRobots:
064A   96C8             lda   0xC8;      /* Check if any robots are left */
064C   10270124         lbeq  CheckForOttoStart;
0650   0F9D             clr   0x9D;
0652   96A9             lda   0xA9;
0654   CEC91C    P0654: ldu   #0xC91C;   /* Ptr to robot array */
0657   33C6             leau  a,u;
0659   8B08             adda  #0x08;
065B   91AA             cmpa  0xAA;
065D   230A             bls   P0669;
065F   0D9D             tst   0x9D;
0661   2703             beq   P0666;
0663   7E0774           jmp   $CheckForOttoStart;
0666   0C9D      P0666: inc   0x9D;
0668   4F               clra;
0669   97A9      P0669: sta   0xA9;
066B   6D42             tst   2,u;      /* Skip this robot if he is dead or */
066D   2AE5             bpl   P0654;    /* not displayed.                   */
066F   6D47             tst   7,u;
0671   102600FF         lbne  CheckForOttoStart; /* Check processing delay */
0675   96A7             lda   0xA7;
0677   A747             sta   7,u;      /* Reset the processing delay value */
0679   A645             lda   5,u;      /* See if the robot can now start */
067B   2702             beq   P067F;    /* shooting.                      */
067D   6A45             dec   5,u;
067F   6C44      P067F: inc   4,u;      /* Update to display next eye box */
0681   ECC4             ldd   ,u;       /* Where is robot relative to player? */
0683   BD0F65           jsr   $DetermineDirectionToMove;
0686   C520             bitb  #0x20;    /* Do they line up in at least 1 dim? */
0688   260B             bne   PrepareToFire;  /* Yes */
068A   96DE             lda   0xDE;     /* No, so see if the x and y deltas */
068C   91DF             cmpa  0xDF;     /* are the same; i.e. 45 degrees.   */
068E   2705             beq   PrepareToFire;
0690   40               nega;
0691   91DF             cmpa  0xDF;
0693   2631             bne   RobotMoving;

                 /*
                  * Only fire if the robot's delay counter has decremented
                  * to 0.  Once all bullets have been spent, reset the counter
                  * and the bullet count.  Robots have a delay, which controls
                  * how often they can fire, along with a bullet counter, which
                  * controls how many bullets they can fire in a burst.
                  */
                 PrepareToFire:
0695   A645             lda   5,u;      /* Check if shooting delay expired */
0697   262D             bne   RobotMoving; /* Nope */
0699   6A46             dec   6,u;      /* Dec robot's bullet burst counter */
069B   2A0A             bpl   RobotFiring;
069D   9683             lda   0x83;     /* Fired all we can for now. */
069F   A746             sta   6,u;      /* Reset bullet burst counter */
06A1   8603             lda   #0x03;
06A3   A745             sta   5,u;      /* Reset shooting delay */
06A5   201F             bra   RobotMoving;

                 /*
                  * The robot is firing.  Determine the starting position for
                  * the bullet, the direction and the velocity.  Lastly, make
                  * a sound.
                  */
                 RobotFiring:
06A7   CA80             orb   #0x80;
06A9   C40F             andb  #0x0F;
06AB   D7EB             stb   0xEB;     /* Save direction to fire bullet */
06AD   30C4             leax  ,u;       /* Determine starting position for */
06AF   8607             lda   #0x07;    /* bullet; a little away from robot */
06B1   BD0939           jsr   $CalculateUpdatedPosition;
06B4   DD9E             std   0x9E;
06B6   8EC89E           ldx   #0xC89E;  /* Starting position */
06B9   D684             ldb   0x84;     /* Velocity factor */
06BB   BD0333           jsr   $FireBullet;
06BE   8602             lda   #0x02;    /* Make a sound */
06C0   9A67             ora   0x67;
06C2   9767             sta   0x67;
06C4   2046             bra   CheckForRobotContactWithWall;

                 /*
                  * The robot is moving, and not firing.  Update the robot's
                  * extremities, based upon the direction of movement.  If
                  * the robot is in a different quadrant than the player,
                  * then attempt to avoid walls in the quadrant, only if the
                  * robot is not in the center of the quadrant.  Usually, the
                  * robot's direction of travel is determined by trying to
                  * avoid walls in the quadrant.
                  */
                 RobotMoving:
06C6   C40F             andb  #0x0F;
06C8   E743             stb   3,u;    /* Set robot's extremities */
06CA   DC8F             ldd   0x8F;   /* Get player's quadrant */
06CC   BD0F98           jsr   $MapPointToQuadrantAndMakeRelative;
06CF   969A             lda   0x9A;
06D1   3402             pshs  a;
06D3   ECC4             ldd   ,u;     /* Get robot's quadrant */
06D5   BD0F98           jsr   $MapPointToQuadrantAndMakeRelative;
06D8   3502             puls  a;
06DA   919A             cmpa  0x9A;   /* In same quadrant? */
06DC   2721             beq   MoveInCurrentDirection;  /* yes */
06DE   969B             lda   0x9B;   /* In different quadrants */
06E0   8112             cmpa  #0x12;  /* Avoid walls, if not in quad center */
06E2   2D10             blt   AttemptToAvoidWalls;
06E4   812E             cmpa  #0x2E;
06E6   2E0C             bgt   AttemptToAvoidWalls;
06E8   969C             lda   0x9C;
06EA   8112             cmpa  #0x12;
06EC   2D06             blt   AttemptToAvoidWalls;
06EE   8116             cmpa  #0x16;
06F0   2E02             bgt   AttemptToAvoidWalls;
06F2   200B             bra   MoveInCurrentDirection;

                 /*
                  * Take the mask indicating which walls are present in this
                  * quadrant, and complement it, to determine the direction
                  * to move to avoid the walls.  If the resulting direction
                  * is 0, then the robot is completely enclosed.
                  */
                 AttemptToAvoidWalls:
06F4   9699             lda   0x99;     /* Wall mask for quadrant */
06F6   43               coma;
06F7   840F             anda  #0x0F;
06F9   A443             anda  3,u;      /* Update robot's direction of travel */
06FB   A743             sta   3,u;
06FD   270D             beq   CheckForRobotContactWithWall; /* Enclosed room */

                 /*
                  * Don't update the robot's direction of travel, but
                  * instead, just keep moving it in its current direction.
                  */
                 MoveInCurrentDirection:
06FF   30C4             leax  ,u;       /* Get current position */
0701   8601             lda   #0x01;    /* Set velocity factor */
0703   E643             ldb   3,u;      /* Get current direction */
0705   BD0939           jsr   $CalculateUpdatedPosition;
0708   EDC4             std   ,u;       /* Update robot's position */
070A   6C44             inc   4,u;      /* Update eye box index */

                 /* See if the robot has run into a wall */
                 CheckForRobotContactWithWall:
070C   6D42             tst   2,u;    /* Skip if the robot is already dead */
070E   2A14             bpl   CheckForRobotCollision;
0710   ECC4             ldd   ,u;     /* Robot's position */
0712   BD0F98           jsr   $MapPointToQuadrantAndMakeRelative;
0715   8E0EE6           ldx   #RobotThresholds;
0718   BD0EC7           jsr   $CheckForQuadrantEdgeCrossing;
071B   D599             bitb  0x99;   /* Contact? */
071D   2705             beq   CheckForRobotCollision;
071F   1F31             tfr   u,x;
0721   BD080F           jsr   $CreditPlayerWithDeadRobot;

                 /* See if the robot has run into another robot. */
                 CheckForRobotCollision:
0724   8EC91C           ldx   #0xC91C;
0727   96C7             lda   0xC7;
0729   979D             sta   0x9D;
072B   ECC4      P072B: ldd   ,u;
072D   10A384           cmpd  ,x;       /* Don't compare against yourself */
0730   271B             beq   GetNextRobotPtr;
0732   6D02             tst   2,x;      /* Skip if next robot is dead */
0734   2A17             bpl   GetNextRobotPtr;
0736   6D42             tst   2,u;      /* Skip if current robot is now dead */
0738   2A13             bpl   GetNextRobotPtr;
073A   108E0D35         ldy   #RobotContactBounds;
073E   BD0D1B           jsr   $CheckForContact;
0741   240A             bhs   GetNextRobotPtr;    /* Contact? */
0743   BD080F           jsr   $CreditPlayerWithDeadRobot;
0746   1E13             exg   x,u;
0748   BD080F           jsr   $CreditPlayerWithDeadRobot;
074B   1E13             exg   x,u;
                 GetNextRobotPtr:
074D   3008             leax  8,x;      /* Get pointer to next robot */
074F   0A9D             dec   0x9D;
0751   26D8             bne   P072B;

                 /* See if robot collided with the player */
0753   A642             lda   2,u;
0755   2A1D             bpl   CheckForOttoStart;  /* Skip if robot is dead */
0757   ECC4             ldd   ,u;
0759   8EC88F           ldx   #0xC88F;
075C   108E0D39         ldy   #PlayerContactBounds;
0760   BD0D1B           jsr   $CheckForContact;
0763   240F             bhs   CheckForOttoStart;
0765   1F31             tfr   u,x;
0767   BD080F           jsr   $CreditPlayerWithDeadRobot;
076A   8604             lda   #0x04;      /* Tag player as dead */
076C   97C5             sta   0xC5;
076E   8608             lda   #0x08;
0770   9A67             ora   0x67;
0772   9767             sta   0x67;   /* Make some sound */

                 /* Wait for counters to expire, before starting Otto */
                 CheckForOttoStart:
0774   0D2E             tst   0x2E;
0776   2675             bne   P07ED;
0778   0D2F             tst   0x2F;
077A   2671             bne   P07ED;
077C   9626             lda   0x26;
077E   8503             bita  #0x03;
0780   2619             bne   P079B;

                 /*
                  * Determine Otto's position and direction, do some
                  * occassional sound mucking, and then see if Otto collided
                  * with the player.
                  */
0782   DC91             ldd   0x91;     /* Determine Otto's travel direction */
0784   BD0F65           jsr   $DetermineDirectionToMove;
0787   8EC891           ldx   #0xC891;  /* Otto's position */
078A   9698             lda   0x98;     /* Otto's velocity */
078C   BD0939           jsr   $CalculateUpdatedPosition;
078F   DD91             std   0x91;     /* Update Otto's position */
0791   D697             ldb   0x97;     /* Since Otto bounces up and down, */
0793   D098             subb  0x98;     /* determine how to offset his 'y' */
0795   2A02             bpl   P0799;    /* position.                       */
0797   C620             ldb   #0x20;
0799   D797      P0799: stb   0x97;
079B   D697      P079B: ldb   0x97;
079D   C11A             cmpb  #0x1A;
079F   2606             bne   P07A7;
07A1   8601             lda   #0x01;
07A3   9A76             ora   0x76;     /* Make some sound */
07A5   9776             sta   0x76;
07A7   9691      P07A7: lda   0x91;     /* Make Otto bounce up and down */
07A9   CE07EE           ldu   #OttoBounceOffsets;
07AC   ABC5             adda  b,u;
07AE   D692             ldb   0x92;
07B0   DD93             std   0x93;     /* Update Otto's position */
07B2   0DC5             tst   0xC5;     /* Is player still alive? */
07B4   2618             bne   $CheckForRobotHitByOtto;
07B6   8EC88F           ldx   #0xC88F;  /* Otto and player collide? */
07B9   108E0D39         ldy   #PlayerContactBounds;
07BD   BD0D1B           jsr   $CheckForContact;
07C0   240C             bhs   $CheckForRobotHitByOtto;
07C2   0C98             inc   0x98;     /* Increment Otto's velocity */
07C4   8608             lda   #0x08;
07C6   9A67             ora   0x67;
07C8   9767             sta   0x67;     /* Make a sound */
07CA   8604             lda   #0x04;
07CC   97C5             sta   0xC5;     /* Tag player as dead */

                 /* Kill off any robots which collide with Otto */
                 CheckForRobotHitByOtto:
07CE   8EC91C           ldx   #0xC91C;     /* Addr of robot array */
07D1   96C7             lda   0xC7;        /* Number of array entries */
07D3   979D             sta   0x9D;        /* Loop counter */
07D5   108E0D35         ldy   #RobotContactBounds;     /* 'Accuracy' table */
07D9   6D02      P07D9: tst   2,x;         /* Make sure robot is alive */
07DB   2A0A             bpl   P07E7;
07DD   DC93             ldd   0x93;        /* Get Otto's position */
07DF   BD0D1B           jsr   $CheckForContact;
07E2   2403             bhs   P07E7;
07E4   BD080F           jsr   $CreditPlayerWithDeadRobot;
07E7   3008      P07E7: leax  8,x;
07E9   0A9D             dec   0x9D;
07EB   26EC             bne   P07D9;
07ED   39        P07ED: rts;

                 OttoBounceOffsets:
07EE   00               .byte 0x00;
07EF   08               .byte 0x08;
07F0   0C               .byte 0x0C;
07F1   0E               .byte 0x0E;
07F2   10               .byte 0x10;
07F3   12               .byte 0x12;
07F4   12               .byte 0x12;
07F5   12               .byte 0x12;
07F6   14               .byte 0x14;
07F7   16               .byte 0x16;
07F8   16               .byte 0x16;
07F9   16               .byte 0x16;
07FA   16               .byte 0x16;
07FB   16               .byte 0x16;
07FC   14               .byte 0x14;
07FD   12               .byte 0x12;
07FE   12               .byte 0x12;
07FF   12               .byte 0x12;
0800   10               .byte 0x10;
0801   0E               .byte 0x0E;
0802   0C               .byte 0x0C;
0803   08               .byte 0x08;
0804   00               .byte 0x00;
0805   FC               .byte 0xFC;
0806   F8               .byte 0xF8;
0807   F4               .byte 0xF4;
0808   EE               .byte 0xEE;
0809   EA               .byte 0xEA;
080A   EE               .byte 0xEE;
080B   F4               .byte 0xF4;
080C   F8               .byte 0xF8;
080D   FC               .byte 0xFC;
080E   00               .byte 0x00;

                 /*
                  * CreditPlayerWithDeadRobot()
                  *
                  * This function decrements the number of active robots
                  * (C8C8), marks the robot as dead, and credits the player
                  * with 50 points.
                  *
                  * Entry:
                  *    x = pointer to dead robot structure.
                  */
                 CreditPlayerWithDeadRobot:
080F   0AC8             dec   0xC8;
0811   860F             lda   #0x0F;
0813   A702             sta   2,x;
0815   8604             lda   #0x04;
0817   9767             sta   0x67;
0819   3410             pshs  x;
081B   9E80             ldx   0x80;
081D   CC0050           ldd   #0x0050;
0820   BDF87C           jsr   $add_d_to_x_in_bcd;
0823   3590             puls  x,pc;

                 /*
                  * ProcessAndUpdateBullets()
                  *
                  * This function updates the head and tail of each bullet,
                  * and checks to see if a bullet has run into a wall,
                  * hit a robot, or hit the player.  A bullet's position
                  * is updated multiple times, based on its velocity setting;
                  * a higher velocity setting causes a bullet to be updated
                  * more often.  A bullet is a short vector made up of a
                  * head and a tail.
                  */
                 ProcessAndUpdateBullets:
0825   96CC             lda   0xCC;      /* Number of bullets */
0827   1027009B         lbeq  P08C6;
082B   97A2             sta   0xA2;      /* Set loop counter */
082D   CEC974           ldu   #0xC974;
0830   E647      P0830: ldb   7,u;
0832   C40F             andb  #0x0F;     /* Skip if bullet is not active */
0834   1027007E         lbeq  P08B6;
0838   D7EB             stb   0xEB;      /* Get the direction of travel */
083A   A646             lda   6,u;
083C   97A1             sta   0xA1;      /* Use velocity as loop counter */
083E   D6EB      P083E: ldb   0xEB;      /* Direction of travel */
0840   8601             lda   #0x01;     /* Velocity */
0842   30C4             leax  ,u;        /* Current tail position */
0844   BD0939           jsr   $CalculateUpdatedPosition;
0847   EDC4             std   ,u;        /* Update bullet's tail position */
0849   D6EB             ldb   0xEB;      /* Direction of travel */
084B   8601             lda   #0x01;     /* Velocity */
084D   3044             leax  4,u;       /* Current head position */
084F   BD0939           jsr   $CalculateUpdatedPosition;
0852   ED44             std   4,u;       /* Update bullet's head position */

                 /* See if bullet collided with a wall */
0854   EC44             ldd   4,u;       /* Bullet's head position */
0856   BD0F98           jsr   $MapPointToQuadrantAndMakeRelative;
0859   0D9A             tst   0x9A;
085B   2B06             bmi   P0863;
085D   8E0EF2           ldx   #BulletToWallThresholds;
0860   BD0EC7           jsr   $CheckForQuadrantEdgeCrossing;
0863   D599      P0863: bitb  0x99;      /* Contact with wall? */
0865   2706             beq   P086D;
0867   C6F0             ldb   #0xF0;
0869   E447             andb  7,u;
086B   E747             stb   7,u;       /* Flag bullet as hitting something */

                 /* See if bullet hit any of the robots */
086D   8EC91C    P086D: ldx   #0xC91C;
0870   96C7             lda   0xC7;
0872   979D             sta   0x9D;
0874   A602      P0874: lda   2,x;       /* Skip robot if already dead */
0876   2A14             bpl   P088C;
0878   108E0D35         ldy   #RobotContactBounds;
087C   EC44             ldd   4,u;       /* Position of bullet's head */
087E   BD0D1B           jsr   $CheckForContact;
0881   2409             bhs   P088C;
0883   BD080F           jsr   $CreditPlayerWithDeadRobot;
0886   C6F0             ldb   #0xF0;     /* Flag bullet as hitting something */
0888   E447             andb  7,u;
088A   E747             stb   7,u;
088C   3008      P088C: leax  8,x;
088E   0A9D             dec   0x9D;
0890   26E2             bne   P0874;

                 /* See if bullet hit the player */
0892   EC44             ldd   4,u;       /* Position of bullet's head */
0894   8EC88F           ldx   #0xC88F;   /* Check for contact with player ? */
0897   108E0D3D         ldy   #PlayerContactBounds2;
089B   BD0D1B           jsr   $CheckForContact;
089E   2412             bhs   P08B2;
08A0   0DC5             tst   0xC5;      /* Do nothing if player is already */
08A2   260E             bne   P08B2;     /* dead or has left the maze.      */
08A4   8608             lda   #0x08;
08A6   9767             sta   0x67;      /* Make a sound */
08A8   8604             lda   #0x04;
08AA   97C5             sta   0xC5;      /* Flag player as dead */
08AC   C6F0             ldb   #0xF0;
08AE   E447             andb  7,u;       /* Flag bullet as hitting something */
08B0   E747             stb   7,u;

                 /* Keep processing this bullet, based on its velocity */
08B2   0AA1      P08B2: dec   0xA1;
08B4   2688             bne   P083E;

                 /* Update the delta between the head and tail of bullet */
08B6   EC44      P08B6: ldd   4,u;
08B8   A0C4             suba  ,u;
08BA   E041             subb  1,u;
08BC   ED42             std   2,u;

                 /* Loop until all bullets have been processed */
08BE   3348             leau  8,u;
08C0   0AA2             dec   0xA2;
08C2   1026FF6A         lbne  P0830;
08C6   39        P08C6: rts;

                 /*
                  * DrawWithPossibleScrolling()
                  *
                  * This function draws an object at its scrolled position,
                  * until the starting point for the object being drawn
                  * scrolls off, at which point, the object is no longer
                  * drawn.  The scrolling offsets are incremented each time
                  * PlayerHasLeftMaze() is called.  Most of the code below
                  * is trying to determine if the starting point has
                  * scrolled off in the expected direction.
                  *
                  * Entry:
                  *   x = ptr to vector list (for generic draw functions)
                  *   u = ptr to drawing position
                  *   C8C9 = drawing function to call
                  */
                 DrawWithPossibleScrolling:
08C7   BDF1AF           jsr   $dptoC8;
08CA   E6C4             ldb   ,u;
08CC   1D               sex;
08CD   D3E2             addd  0xE2;
08CF   D79D             stb   0x9D;   /* starting y pos + scrolling offset */
08D1   2A13             bpl   P08E6;
08D3   43               coma;
08D4   2660             bne   DoNoDrawing;
08D6   0DE6             tst   0xE6;
08D8   2B1D             bmi   P08F7;
08DA   6DC4             tst   ,u;
08DC   2A58             bpl   DoNoDrawing;
08DE   863F             lda   #0x3F;
08E0   91E0             cmpa  0xE0;
08E2   2D52             blt   DoNoDrawing;
08E4   2011             bra   P08F7;
08E6   4D        P08E6: tsta;
08E7   264D             bne   DoNoDrawing;
08E9   0DE6             tst   0xE6;
08EB   2A0A             bpl   P08F7;
08ED   6DC4             tst   ,u;
08EF   2B45             bmi   DoNoDrawing;
08F1   86C1             lda   #0xC1;
08F3   91E0             cmpa  0xE0;
08F5   2C3F             bge   DoNoDrawing;
08F7   E641      P08F7: ldb   1,u;
08F9   1D               sex;
08FA   D3E4             addd  0xE4;
08FC   D79E             stb   0x9E;  /* starting x pos + scrolling offset */
08FE   2A13             bpl   P0913;
0900   43               coma;
0901   2633             bne   DoNoDrawing;
0903   0DE6             tst   0xE6;
0905   2B1D             bmi   P0924;
0907   6D41             tst   1,u;
0909   2A2B             bpl   DoNoDrawing;
090B   863F             lda   #0x3F;
090D   91E1             cmpa  0xE1;
090F   2D25             blt   DoNoDrawing;
0911   2011             bra   P0924;
0913   4D        P0913: tsta;
0914   2620             bne   DoNoDrawing;
0916   0DE6             tst   0xE6;
0918   2A0A             bpl   P0924;
091A   6D41             tst   1,u;
091C   2B18             bmi   DoNoDrawing;
091E   86C1             lda   #0xC1;
0920   91E1             cmpa  0xE1;
0922   2C12             bge   DoNoDrawing;
0924   BDF1AA    P0924: jsr   $dptoD0;
0927   FCC89D           ldd   $C89D;        /* Goto modified drawing origin */
092A   BDF2FC           jsr   $move_pen7F_to_d;
092D   B6C8CB           lda   $C8CB;        /* Set drawing intensity */
0930   9704             sta   0x04;
0932   AD9FC8C9         jsr   [0xC8C9];     /* Jump to drawing function*/

                 DoNoDrawing:
0936   7EF1AA           jmp   $dptoD0;

                 /*
                  * CalculateUpdatedPosition()
                  *
                  * This function updates a position, based upon a direction
                  * of travel, and a velocity setting.  The velocity is
                  * broken up into a rise and a run value, and added to the
                  * incoming position.
                  *
                  * Entry:
                  *   b = direction of travel
                  *   a = velocity setting
                  *   x = pointer to a position
                  *
                  * Exit:
                  *   d = updated position (y,x)
                  */
                 CalculateUpdatedPosition:
0939   C503             bitb  #0x03;
093B   2715             beq   AddVelocityToEndpoints;
093D   C50C             bitb  #0x0C;
093F   2711             beq   AddVelocityToEndpoints;

                 /* Break up velocity into rise and run components */
0941   3404             pshs  b;
0943   C603             ldb   #0x03;
0945   3D               mul;
0946   57               asrb;
0947   2401             bhs   P094A;
0949   5C               incb;
094A   57        P094A: asrb;
094B   2401             bhs   P094E;
094D   5C               incb;
094E   1F98      P094E: tfr   b,a;
0950   3504             puls  b;

                 AddVelocityToEndpoints:
0952   979D             sta   0x9D;   /* Save adjusted velocity */
0954   C511             bitb  #0x11;
0956   2703             beq   P095B;
0958   40               nega;         /* Going left; - velocity */
0959   2005             bra   P0960;
095B   C502      P095B: bitb  #0x02;
095D   2601             bne   P0960;  /* Going right; + velocity */
095F   4F               clra          /* No movement in x direction */
0960   AB01      P0960: adda  1,x;    /* Update the x position */
0962   3402             pshs  a;
0964   969D             lda   0x9D;   /* Reload adjusted velocity */
0966   C508             bitb  #0x08;
0968   2703             beq   P096D;
096A   40               nega;         /* Going down; - velocity */
096B   2005             bra   P0972;
096D   C504      P096D: bitb  #0x04;
096F   2601             bne   P0972;  /* Going up; + velocity */
0971   4F               clra;         /* No movement in y direction */
0972   AB84      P0972: adda  ,x;     /* Update the y position */
0974   3584             puls  b,pc;

                 /*
                  * This is one of the 'indirect jump' functions.  It is the
                  * active jump function when the player successfully leaves
                  * a maze.  When the player exits from a door in the maze,
                  * the maze will then scroll off in the opposite direction;
                  * i.e. If the player exits through the left door, the maze
                  * will scroll off to the right.  Each time this function
                  * is called, it will bump the scrolling deltas; this
                  * continues until scrolling is complete.  It also sets
                  * the player's starting position in the next maze; if the
                  * player exited from the left, then he will start at the
                  * right edge of the next maze, and the door through which
                  * he exited will be blocked.
                  */
                 PlayerHasLeftMaze:
0976   C680             ldb   #0x80;
0978   D7E6             stb   0xE6;
097A   D6EA             ldb   0xEA;   /* Determine door player exited thru */
097C   C501             bitb  #0x01;
097E   2706             beq   P0986;
0980   0FE6             clr   0xE6;   /* Left door, so scroll right */
0982   0CE1             inc   0xE1;
0984   202C             bra   P09B2;
0986   C502      P0986: bitb  #0x02;
0988   2704             beq   P098E;
098A   0AE1             dec   0xE1;   /* Right door, so scroll left */
098C   2012             bra   P09A0;
098E   C504      P098E: bitb  #0x04;
0990   2704             beq   P0996;
0992   0AE0             dec   0xE0;   /* Top door, so scroll down */
0994   200A             bra   P09A0;
0996   C508      P0996: bitb  #0x08;
0998   2706             beq   P09A0;
099A   0FE6             clr   0xE6;   /* Bottom door, so scroll up */
099C   0CE0             inc   0xE0;
099E   2012             bra   P09B2;

                 /*
                  * This block checks to see if we have finished scrolling,
                  * and if so, prepares us for entering the next maze.
                  * It will also set the player's starting position in the
                  * next maze.
                  */
09A0   2B3C      P09A0: bmi   SaveScrollingDeltas;
09A2   C502             bitb  #0x02;
09A4   2706             beq   P09AC;   /* Exited thru right door? */
09A6   968F             lda   0x8F;
09A8   C6A5             ldb   #0xA5;   /* Yes; start at left edge */
09AA   2016             bra   P09C2;
09AC   86B0      P09AC: lda   #0xB0;   /* Exited thru top door */
09AE   D690             ldb   0x90;    /* Start at bottom */
09B0   2010             bra   P09C2;
09B2   2A2A      P09B2: bpl   SaveScrollingDeltas;
09B4   C508             bitb  #0x08;   /* Exited thru bottom door? */
09B6   2706             beq   P09BE;
09B8   8654             lda   #0x54;   /* Yes; start at top edge */
09BA   D690             ldb   0x90;
09BC   2004             bra   P09C2;
09BE   968F      P09BE: lda   0x8F;    /* Exited thru left door */
09C0   C65B             ldb   #0x5B;   /* Start at right edge */
09C2   9E80      P09C2: ldx   0x80;
09C4   ED0A             std   10,x;    /* Update player's position */
09C6   96EA             lda   0xEA;    /* This tells the exit door */
09C8   840F             anda  #0x0F;
09CA   48               asla;
09CB   97C6             sta   0xC6;    /* Block door player exited thru */
09CD   863F             lda   #0x3F;
09CF   9785             sta   0x85;    /* Set a loop counter */
09D1   86A0             lda   #0xA0;   /* Reset the threshold used to       */
09D3   0DD1             tst   0xD1;    /* determine if a robot is placed in */
09D5   2602             bne   P09D9;   /* the maze.                         */
09D7   8650             lda   #0x50;
09D9   97A8      P09D9: sta   0xA8;
09DB   7E00AF           jmp   $EnterNextMaze;

                 /*
                  * This block saves the x and y delta values, which are
                  * then used by the drawing function, to offset all
                  * drawing origins.
                  */
                 SaveScrollingDeltas:
09DE   D6E0             ldb   0xE0;
09E0   1D               sex;
09E1   58               aslb;
09E2   49               rola;
09E3   DDE2             std   0xE2;   /* Save 16-bit y delta */
09E5   D6E1             ldb   0xE1;
09E7   1D               sex;
09E8   58               aslb;
09E9   49               rola;
09EA   DDE4             std   0xE4;   /* Save 16-bit x delta */
09EC   7E019E           jmp   $MakeSoundThenGotoMainLoop;

                 /*
                  * DrawPlayerFunction()
                  *
                  * This function draws the player's body, and then the
                  * arms and legs; the types of arms and legs is dependent
                  * upon whether the player is standing still, running
                  * or shooting.  (C8CE) is the index indicating movement,
                  * while (C8CF) is the index indicating arm position
                  * (running, standing still or shooting).
                  */
                 DrawPlayerFunction:
09EF   7FC824           clr   $C824;
09F2   860A             lda   #0x0A;           /* Draw the player's body */
09F4   8E0BCD           ldx   #PlayersBody;
09F7   BDF3DA           jsr   $draw_VL_with_count5;
09FA   F6C8CE           ldb   $C8CE;           /* Running or standing still? */
09FD   2716             beq   PlayerStandingStill;
09FF   8E0A47           ldx   #PlayerLegsVectorTable;
0A02   AE85             ldx   b,x;
0A04   BDF410           jsr   $next_pt;
0A07   8E0A51           ldx   #PlayerMovingArmsVectorTable;
0A0A   F6C8CF           ldb   $C8CF;
0A0D   AE85             ldx   b,x;
0A0F   7CC824           inc   $C824;
0A12   7EF410           jmp   $next_pt;

                 PlayerStandingStill:
0A15   8E0C5B           ldx   #StationaryLegs;   /* Draw legs standing still */
0A18   BDF3AD           jsr   $move_then_draw_VL_with_count1;
0A1B   8E0A55           ldx   #PlayerArmsVectorTable;
0A1E   F6C8CF           ldb   $C8CF;
0A21   2705             beq   PlayerNotShooting;
0A23   AE85             ldx   b,x;            /* Player is shooting */
0A25   7EF3AD           jmp   $move_then_draw_VL_with_count1;

                 PlayerNotShooting:
0A28   AE84             ldx   ,x;             /* Draw arms at side */
0A2A   7EF410           jmp   $next_pt;

                 /*
                  * Whenever the player's score passes certain cutoff level,
                  * the game becomes more challenging.  The cutoff levels are:
                  * 3000, 15000, 30000, 45000, 50000, 60000 and 75000
                  */
                 SkillLevelCutoffs:
0A2D   20               .word 0x2033; /* " 3" */
0A2F   31               .word 0x3135; /* "15" */
0A31   33               .word 0x3330; /* "30" */
0A33   34               .word 0x3435; /* "45" */
0A35   35               .word 0x3530; /* "50" */
0A37   36               .word 0x3630; /* "60" */
0A39   37               .word 0x3735; /* "75" */
0A3B   80               .byte 0x80;

                 /*
                  * This table is used to fill in the player's arm
                  * movement value (C8CF), when standing still.  The
                  * value is obtained from this array, by indexing into
                  * it using the joystick state:
                  *
                  *         ---------------------------------
                  *         | 0 | 0 | B | L | D | U | R | L |
                  *         ---------------------------------
                  *   Button Pressed--^
                  *   Joystick Left-------^---------------^
                  *   Joystick Down-----------^
                  *   Joystick Up-----------------^
                  *   Joystick Right------------------^
                  */
                 ArmsShootingIndicesTable:
0A3C   80               .byte 0x80;     /* idx = 0x00; Invalid setting */
0A3D   02               .byte 0x02;     /* idx = 0x01; shooting left */
0A3E   04               .byte 0x04;     /* idx = 0x02; shooting right */
0A3F   80               .byte 0x80;     /* idx = 0x03; Invalid setting */
0A40   06               .byte 0x06;     /* idx = 0x04; shooting up */
0A41   08               .byte 0x08;     /* idx = 0x05; shooting upper left */
0A42   0A               .byte 0x0A;     /* idx = 0x06; shooting upper right */
0A43   80               .byte 0x80;     /* idx = 0x07; Invalid setting */
0A44   0C               .byte 0x0C;     /* idx = 0x08; shooting down */
0A45   0E               .byte 0x0E;     /* idx = 0x09; shooting lower left */
0A46   10               .byte 0x10;     /* idx = 0x0A; shooting lower right */

                 /*
                  * As the player runs, the legs either move in a left or
                  * right direction.  The value in C8CE is used to index
                  * into this table.
                  */
                 PlayerLegsVectorTable:
0A47   0C               .word StationaryLegs;
0A49   0B               .word LegsRunningRight1;
0A4B   0B               .word LegsRunningRight2;
0A4D   0C               .word LegsRunningLeft1;
0A4F   0C               .word LegsRunningLeft2;

                 /*
                  * As the player moves, his arms swing back and forth.
                  * The value in C8CF is used to index into this table.
                  */
                 PlayerMovingArmsVectorTable:
0A51   0C               .word MovingArms1;
0A53   0C               .word MovingArms2;

                 /*
                  * When a player is standing still, they are either shooting
                  * or not shooting.  The value in C8CF is used to index into
                  * this table.
                  */
                 PlayerArmsVectorTable:
0A55   0C               .word NeutralArms;
0A57   0C               .word ShootingLeft;
0A59   0C               .word ShootingRight;
0A5B   0C               .word ShootingUp;
0A5D   0C               .word ShootingUpperLeft;
0A5F   0C               .word ShootingUpperRight;
0A61   0C               .word ShootingDown;
0A63   0C               .word ShootingLowerLeft;
0A65   0C               .word ShootingLowerRight;

                 /*
                  * Depending upon what a robot is doing, his extremities
                  * (legs and eye boxes) may be drawn differently.  Each
                  * entry in this table points to another structure, which
                  * defines how the extremities should be drawn.  Each robot
                  * structure has a field which is used to index into this
                  * table.
                  */
                 RobotExtremitiesVectorTable:
0A67   0A               .word RobotStandingStill;
0A69   0A               .word RobotMovingLeft;
0A6B   0A               .word RobotMovingRight;
0A6D   0A               .word RobotStandingStill;
0A6F   0A               .word RobotMovingUp;
0A71   0A               .word RobotMovingLeft;
0A73   0A               .word RobotMovingRight;
0A75   0A               .word RobotStandingStill;
0A77   0A               .word RobotMovingDown;
0A79   0A               .word RobotMovingLeft;
0A7B   0A               .word RobotMovingRight;

                 /*
                  * Each of the following 5 structures describe how the
                  * extremities should be drawn for a robot, while in a
                  * particular state.  The structure is defined as follows:
                  *
                  *   {
                  *       ptr to first right leg vector list
                  *       ptr to second right leg vector list
                  *       ptr to right foot vector list
                  *       ptr to first left leg vector list
                  *       ptr to second left leg vector list
                  *       ptr to left foot vector list
                  *       ptr to eye box 1 vector list
                  *       ptr to eye box 2 vector list
                  *       ptr to eye box 3 vector list
                  *       ptr to eye box 4 vector list
                  *   }
                  *
                  * As the robot is drawn, it will cycle through the 2
                  * right leg and 2 left leg vector list; it will also
                  * cycle through the 4 eye box vector lists.  In some
                  * cases, values will be the same; this implies that no
                  * motion is occurring (i.e. if the robot is not moving,
                  * then the legs shouldn't be moving either).
                  *
                  * When a robot is moving left, the eye box and both feet
                  * point to the left.  When the robot is moving right, then
                  * the eye box and both feed point right.  When the robot
                  * is moving up, then the eye box points up.  When the robot
                  * moves down, no eye box is displayed.  When the robot is
                  * standing still, the eye box will appear to rotate.
                  */
                 RobotStandingStill:
0A7D   0B               .word RobotRightLeg1;
0A7F   0B               .word RobotRightLeg1;
0A81   0B               .word RobotRightFoot;
0A83   0B               .word RobotLeftLeg1;
0A85   0B               .word RobotLeftLeg1;
0A87   0B               .word RobotLeftFoot;
0A89   0B               .word RobotEyeBoxCentered;
0A8B   0B               .word RobotEyeBoxRight;
0A8D   0B               .word RobotEyeBoxInvisible;
0A8F   0B               .word RobotEyeBoxLeft;

                 RobotMovingRight:
0A91   0B               .word RobotRightLeg1;
0A93   0B               .word RobotRightLeg2;
0A95   0B               .word RobotRightFoot;
0A97   0B               .word RobotLeftLeg1;
0A99   0B               .word RobotLeftLeg2;
0A9B   0B               .word RobotRightFoot;
0A9D   0B               .word RobotEyeBoxRight;
0A9F   0B               .word RobotEyeBoxRight;
0AA1   0B               .word RobotEyeBoxRight;
0AA3   0B               .word RobotEyeBoxRight;

                 RobotMovingLeft:
0AA5   0B               .word RobotRightLeg1;
0AA7   0B               .word RobotRightLeg2;
0AA9   0B               .word RobotLeftFoot;
0AAB   0B               .word RobotLeftLeg1;
0AAD   0B               .word RobotLeftLeg2;
0AAF   0B               .word RobotLeftFoot;
0AB1   0B               .word RobotEyeBoxLeft;
0AB3   0B               .word RobotEyeBoxLeft;
0AB5   0B               .word RobotEyeBoxLeft;
0AB7   0B               .word RobotEyeBoxLeft;

                 RobotMovingUp:
0AB9   0B               .word RobotRightLeg1;
0ABB   0B               .word RobotRightLeg3;
0ABD   0B               .word RobotRightFoot;
0ABF   0B               .word RobotLeftLeg3;
0AC1   0B               .word RobotLeftLeg1;
0AC3   0B               .word RobotLeftFoot;
0AC5   0B               .word RobotEyeBoxCentered;
0AC7   0B               .word RobotEyeBoxCentered;
0AC9   0B               .word RobotEyeBoxCentered;
0ACB   0B               .word RobotEyeBoxCentered;

                 RobotMovingDown:
0ACD   0B               .word RobotRightLeg1;
0ACF   0B               .word RobotRightLeg3;
0AD1   0B               .word RobotRightFoot;
0AD3   0B               .word RobotLeftLeg3;
0AD5   0B               .word RobotLeftLeg1;
0AD7   0B               .word RobotLeftFoot;
0AD9   0B               .word RobotEyeBoxInvisible;
0ADB   0B               .word RobotEyeBoxInvisible;
0ADD   0B               .word RobotEyeBoxInvisible;
0ADF   0B               .word RobotEyeBoxInvisible;

                 BonusString:
0AE1   70               .byte 0x70; /* rel y */
0AE2   DA               .byte 0xDA; /* rel x */
0AE3   42               .string "BONUS",0xFF;

                 /*
                  * As the player gets better, the game will start to
                  * block off one of the maze doors.  The value in C8C6
                  * is used to index into this array, when the value > 0.
                  * The value in C8C6 has the following format:
                  *
                  *         ---------------------------------
                  *         | 0 | 0 | 0 | T | B | L | R | 0 |
                  *         ---------------------------------
                  *   Block Top Door------^
                  *   Block Bottom Door-------^
                  *   Block Left Door-------------^
                  *   Block Right Door----------------^
                  */
                 BlockedDoorVectorTable:
0AE9   0A               .word BlockedDoorVectorTable;  /* idx = 0; Invalid */
0AEB   0A               .word RightDoorVectors;        /* idx = 2 */
0AED   0A               .word LeftDoorVectors;         /* idx = 4 */
0AEF   0A               .word BlockedDoorVectorTable;  /* idx = 6; Invalid */
0AF1   0B               .word BottomDoorVectors;       /* idx = 8 */
0AF3   0A               .word BlockedDoorVectorTable;  /* idx = 10; Invalid */
0AF5   0A               .word BlockedDoorVectorTable;  /* idx = 12; Invalid */
0AF7   0A               .word BlockedDoorVectorTable;  /* idx = 14; Invalid */
0AF9   0B               .word TopDoorVectors;          /* idx = 16 */

                 /*
                  * Each of the following tables contain the relative (y,x)
                  * point to move to, followed by the (y,x) point to draw to.
                  */
                 RightDoorVectors:
0AFB   E0               .byte 0xE0;   /* move to absolute y */
0AFC   64               .byte 0x64;   /* move to absolute x */
0AFD   40               .byte 0x40;   /* vector rel y */
0AFE   00               .byte 0x00;   /* vector rel x */

                 LeftDoorVectors:
0AFF   E0               .byte 0xE0;   /* move to absolute y */
0B00   9C               .byte 0x9C;   /* move to absolute x */
0B01   40               .byte 0x40;   /* vector rel y */
0B02   00               .byte 0x00;   /* vector rel x */

                 TopDoorVectors:
0B03   60               .byte 0x60;   /* move to absolute y */
0B04   EC               .byte 0xEC;   /* move to absolute x */
0B05   00               .byte 0x00;   /* vector rel y */
0B06   28               .byte 0x28;   /* vector rel x */

                 BottomDoorVectors:
0B07   A0               .byte 0xA0;   /* move to absolute y */
0B08   EC               .byte 0xEC;   /* move to absolute x */
0B09   00               .byte 0x00;   /* vector rel y */
0B0A   28               .byte 0x28;   /* vector rel x */

                 /*
                  * This structure contains 4 entries; 1 for each of the
                  * sections of outer wall which must be drawn.  Each
                  * entry contains an absolute (y,x) position, to which
                  * the pen should be moved before doing any drawing, and
                  * a pointer to the appropriate vector list.
                  */
                 OutsideMazeWallData:
0B0B   60               .byte 0x60;  /* absolute y */
0B0C   EC               .byte 0xEC;  /* absolute x */
0B0D   0B               .word UpperLeftWall;
0B0F   A0               .byte 0xA0;  /* absolute y */
0B10   EC               .byte 0xEC;  /* absolute x */
0B11   0B               .word LowerLeftWall;
0B13   A0               .byte 0xA0;  /* absolute y */
0B14   14               .byte 0x14;  /* absolute x */
0B15   0B               .word LowerRightWall;
0B17   60               .byte 0x60;  /* absolute y */
0B18   14               .byte 0x14;  /* absolute x */
0B19   0B               .word UpperRightWall;

                 /*
                  * The following is a table of 8 (y,x) points, which
                  * represent the starting points for all interior maze
                  * walls.  The maze is divided into 15 quadrants, and
                  * these points represent the points where 4 quadrants
                  * meet (as indicated by the '+' character:
                  *
                  *     -100 -60 -20 +20 +60 +100
                  *       --------------------- +96
                  *       | 0 | 1 | 2 | 3 | 4 |
                  *       ----+---+---+---+---- +32
                  *       | 5 | 6 | 7 | 8 | 9 |
                  *       ----+---+---+---+---- -32
                  *       |10 |11 |12 |13 |14 |
                  *       --------------------- -96
                  */
                 InnerWallPositionTable:
0B1B   20               .byte 0x20;
0B1C   C4               .byte 0xC4;
0B1D   20               .byte 0x20;
0B1E   EC               .byte 0xEC;
0B1F   20               .byte 0x20;
0B20   14               .byte 0x14;
0B21   20               .byte 0x20;
0B22   3C               .byte 0x3C;
0B23   E0               .byte 0xE0;
0B24   C4               .byte 0xC4;
0B25   E0               .byte 0xE0;
0B26   EC               .byte 0xEC;
0B27   E0               .byte 0xE0;
0B28   14               .byte 0x14;
0B29   E0               .byte 0xE0;
0B2A   3C               .byte 0x3C;

                 /*
                  * The following 4 structures contain the (y,x) points
                  * needed to draw 2 of the outer maze walls.
                  */
                 UpperLeftWall:
0B2B   00               .byte 0x00;
0B2C   B0               .byte 0xB0;
0B2D   C0               .byte 0xC0;
0B2E   00               .byte 0x00;

                 LowerLeftWall:
0B2F   00               .byte 0x00;
0B30   B0               .byte 0xB0;
0B31   40               .byte 0x40;
0B32   00               .byte 0x00;

                 LowerRightWall:
0B33   00               .byte 0x00;
0B34   50               .byte 0x50;
0B35   40               .byte 0x40;
0B36   00               .byte 0x00;

                 UpperRightWall:
0B37   00               .byte 0x00;
0B38   50               .byte 0x50;
0B39   C0               .byte 0xC0;
0B3A   00               .byte 0x00;

                 /*
                  * The following is a table of 4 single vectors, each
                  * representing a posible vector which might be drawn
                  * as an inner wall.  From any one of the inner points,
                  * a wall could be drawn:
                  *
                  *   1) upward
                  *   2) downward
                  *   3) to the right
                  *   4) to the left
                  *
                  * When drawing the maze, the 8 byte array C8AB-C8B2
                  * (which contains one entry for each of the 8 possible
                  * inner wall positions) indicates which of the segments
                  * should be drawn; the index is either 0, 2, 4 or 6.
                  */
                 InnerWallVectorTable:
0B3B   40               .byte 0x40; /* Draw upward from point */
0B3C   00               .byte 0x00;
0B3D   C0               .byte 0xC0; /* Draw downward from point */
0B3E   00               .byte 0x00;
0B3F   00               .byte 0x00; /* Draw right from point */
0B40   28               .byte 0x28;
0B41   00               .byte 0x00; /* Draw left from point */
0B42   D8               .byte 0xD8;

                 /*
                  * Vector list comprising right half of the robot's body.
                  */
                 RobotRightHalf:
0B43   05               .byte 0x05; /* vector count - 1 */
0B44   64               .byte 0x64; /* rel y */
0B45   00               .byte 0x00; /* rel x */
0B46   00               .byte 0x00;
0B47   28               .byte 0x28;
0B48   E8               .byte 0xE8;
0B49   28               .byte 0x28;
0B4A   84               .byte 0x84;
0B4B   00               .byte 0x00;
0B4C   00               .byte 0x00;
0B4D   EC               .byte 0xEC;
0B4E   30               .byte 0x30;
0B4F   00               .byte 0x00;

                 RobotRightLeg1:
0B50   00               .byte 0x00;
0B51   E4               .byte 0xE4;
0B52   9C               .byte 0x9C;
0B53   00               .byte 0x00;

                 RobotRightLeg2:
0B54   00               .byte 0x00;
0B55   D0               .byte 0xD0;
0B56   9C               .byte 0x9C;
0B57   00               .byte 0x00;

                 RobotRightLeg3:
0B58   00               .byte 0x00;
0B59   E4               .byte 0xE4;
0B5A   8D               .byte 0x8D;
0B5B   00               .byte 0x00;

                 RobotRightFoot:
0B5C   00               .byte 0x00;
0B5D   1C               .byte 0x1C;

                 /*
                  * Vector list comprising left half of the robot's body.
                  */
                 RobotLeftHalf:
0B5E   05               .byte 0x05; /* vector count - 1 */
0B5F   64               .byte 0x64; /* rel y */
0B60   00               .byte 0x00; /* rel x */
0B61   00               .byte 0x00;
0B62   D8               .byte 0xD8;
0B63   E8               .byte 0xE8;
0B64   D8               .byte 0xD8;
0B65   84               .byte 0x84;
0B66   00               .byte 0x00;
0B67   00               .byte 0x00;
0B68   14               .byte 0x14;
0B69   30               .byte 0x30;
0B6A   00               .byte 0x00;

                 RobotLeftLeg1:
0B6B   00               .byte 0x00;
0B6C   1C               .byte 0x1C;
0B6D   9C               .byte 0x9C;
0B6E   00               .byte 0x00;

                 RobotLeftLeg2:
0B6F   00               .byte 0x00;
0B70   30               .byte 0x30;
0B71   9C               .byte 0x9C;
0B72   00               .byte 0x00;

                 RobotLeftLeg3:
0B73   00               .byte 0x00;
0B74   1C               .byte 0x1C;
0B75   8D               .byte 0x8D;
0B76   00               .byte 0x00;

                 RobotLeftFoot:
0B77   00               .byte 0x00;
0B78   E4               .byte 0xE4;

                 RobotEyeBoxCentered:
0B79   30               .byte 0x30;
0B7A   28               .byte 0x28;
0B7B   1C               .byte 0x1C;
0B7C   00               .byte 0x00;
0B7D   00               .byte 0x00;
0B7E   B0               .byte 0xB0;
0B7F   E4               .byte 0xE4;
0B80   00               .byte 0x00;
0B81   00               .byte 0x00;
0B82   50               .byte 0x50;

                 RobotEyeBoxRight:
0B83   30               .byte 0x30;
0B84   14               .byte 0x14;
0B85   00               .byte 0x00;
0B86   3C               .byte 0x3C;
0B87   1C               .byte 0x1C;
0B88   00               .byte 0x00;
0B89   00               .byte 0x00;
0B8A   C4               .byte 0xC4;
0B8B   E4               .byte 0xE4;
0B8C   00               .byte 0x00;

                 RobotEyeBoxLeft:
0B8D   30               .byte 0x30;
0B8E   EC               .byte 0xEC;
0B8F   1C               .byte 0x1C;
0B90   00               .byte 0x00;
0B91   00               .byte 0x00;
0B92   C4               .byte 0xC4;
0B93   E4               .byte 0xE4;
0B94   00               .byte 0x00;
0B95   00               .byte 0x00;
0B96   3C               .byte 0x3C;

                 RobotEyeBoxInvisible:
0B97   00               .byte 0x00;
0B98   00               .byte 0x00;

                 OttoVectors:
0B99   00               .byte 0x00;
0B9A   18               .byte 0x18;
0B9B   0A               .byte 0x0A;
0B9C   FF               .byte 0xFF;
0B9D   F2               .byte 0xF2;
0B9E   0E               .byte 0x0E;
0B9F   FF               .byte 0xFF;
0BA0   EC               .byte 0xEC;
0BA1   00               .byte 0x00;
0BA2   FF               .byte 0xFF;
0BA3   F2               .byte 0xF2;
0BA4   F2               .byte 0xF2;
0BA5   FF               .byte 0xFF;
0BA6   00               .byte 0x00;
0BA7   EC               .byte 0xEC;
0BA8   FF               .byte 0xFF;
0BA9   0E               .byte 0x0E;
0BAA   F2               .byte 0xF2;
0BAB   FF               .byte 0xFF;
0BAC   14               .byte 0x14;
0BAD   00               .byte 0x00;
0BAE   FF               .byte 0xFF;
0BAF   0E               .byte 0x0E;
0BB0   0E               .byte 0x0E;
0BB1   FF               .byte 0xFF;
0BB2   00               .byte 0x00;
0BB3   14               .byte 0x14;
0BB4   00               .byte 0x00;
0BB5   F4               .byte 0xF4;
0BB6   03               .byte 0x03;
0BB7   FF               .byte 0xFF;
0BB8   FD               .byte 0xFD;
0BB9   FB               .byte 0xFB;
0BBA   00               .byte 0x00;
0BBB   00               .byte 0x00;
0BBC   F2               .byte 0xF2;
0BBD   FF               .byte 0xFF;
0BBE   03               .byte 0x03;
0BBF   FB               .byte 0xFB;
0BC0   00               .byte 0x00;
0BC1   EC               .byte 0xEC;
0BC2   00               .byte 0x00;
0BC3   FF               .byte 0xFF;
0BC4   FD               .byte 0xFD;
0BC5   05               .byte 0x05;
0BC6   FF               .byte 0xFF;
0BC7   00               .byte 0x00;
0BC8   0E               .byte 0x0E;
0BC9   FF               .byte 0xFF;
0BCA   03               .byte 0x03;
0BCB   05               .byte 0x05;
0BCC   01               .byte 0x01;

                 PlayersBody:
0BCD   00               .byte 0x00;
0BCE   14               .byte 0x14;
0BCF   C4               .byte 0xC4;
0BD0   00               .byte 0x00;
0BD1   00               .byte 0x00;
0BD2   D8               .byte 0xD8;
0BD3   3C               .byte 0x3C;
0BD4   00               .byte 0x00;
0BD5   00               .byte 0x00;
0BD6   14               .byte 0x14;
0BD7   0F               .byte 0x0F;
0BD8   14               .byte 0x14;
0BD9   0A               .byte 0x0A;
0BDA   00               .byte 0x00;
0BDB   0A               .byte 0x0A;
0BDC   EC               .byte 0xEC;
0BDD   F6               .byte 0xF6;
0BDE   EC               .byte 0xEC;
0BDF   F6               .byte 0xF6;
0BE0   00               .byte 0x00;
0BE1   F1               .byte 0xF1;
0BE2   14               .byte 0x14;
0BE3   01               .byte 0x01;

                 LegsRunningRight1:
0BE4   00               .byte 0x00;
0BE5   C4               .byte 0xC4;
0BE6   0C               .byte 0x0C;
0BE7   FF               .byte 0xFF;
0BE8   E0               .byte 0xE0;
0BE9   16               .byte 0x16;
0BEA   FF               .byte 0xFF;
0BEB   EA               .byte 0xEA;
0BEC   06               .byte 0x06;
0BED   FF               .byte 0xFF;
0BEE   FE               .byte 0xFE;
0BEF   08               .byte 0x08;
0BF0   00               .byte 0x00;
0BF1   10               .byte 0x10;
0BF2   98               .byte 0x98;
0BF3   FF               .byte 0xFF;
0BF4   0A               .byte 0x0A;
0BF5   04               .byte 0x04;
0BF6   FF               .byte 0xFF;
0BF7   08               .byte 0x08;
0BF8   20               .byte 0x20;
0BF9   FF               .byte 0xFF;
0BFA   16               .byte 0x16;
0BFB   08               .byte 0x08;
0BFC   01               .byte 0x01;

                 LegsRunningRight2:
0BFD   00               .byte 0x00;
0BFE   C4               .byte 0xC4;
0BFF   08               .byte 0x08;
0C00   FF               .byte 0xFF;
0C01   E0               .byte 0xE0;
0C02   0A               .byte 0x0A;
0C03   FF               .byte 0xFF;
0C04   E6               .byte 0xE6;
0C05   F8               .byte 0xF8;
0C06   FF               .byte 0xFF;
0C07   00               .byte 0x00;
0C08   08               .byte 0x08;
0C09   00               .byte 0x00;
0C0A   00               .byte 0x00;
0C0B   DC               .byte 0xDC;
0C0C   FF               .byte 0xFF;
0C0D   02               .byte 0x02;
0C0E   F8               .byte 0xF8;
0C0F   FF               .byte 0xFF;
0C10   1A               .byte 0x1A;
0C11   08               .byte 0x08;
0C12   FF               .byte 0xFF;
0C13   1E               .byte 0x1E;
0C14   02               .byte 0x02;
0C15   01               .byte 0x01;

                 LegsRunningLeft1:
0C16   00               .byte 0x00;
0C17   C4               .byte 0xC4;
0C18   08               .byte 0x08;
0C19   FF               .byte 0xFF;
0C1A   E2               .byte 0xE2;
0C1B   FE               .byte 0xFE;
0C1C   FF               .byte 0xFF;
0C1D   E6               .byte 0xE6;
0C1E   0E               .byte 0x0E;
0C1F   FF               .byte 0xFF;
0C20   FE               .byte 0xFE;
0C21   FC               .byte 0xFC;
0C22   00               .byte 0x00;
0C23   00               .byte 0x00;
0C24   DC               .byte 0xDC;
0C25   FF               .byte 0xFF;
0C26   00               .byte 0x00;
0C27   08               .byte 0x08;
0C28   FF               .byte 0xFF;
0C29   1A               .byte 0x1A;
0C2A   FA               .byte 0xFA;
0C2B   FF               .byte 0xFF;
0C2C   20               .byte 0x20;
0C2D   0A               .byte 0x0A;
0C2E   01               .byte 0x01;

                 LegsRunningLeft2:
0C2F   00               .byte 0x00;
0C30   C4               .byte 0xC4;
0C31   08               .byte 0x08;
0C32   FF               .byte 0xFF;
0C33   EA               .byte 0xEA;
0C34   08               .byte 0x08;
0C35   FF               .byte 0xFF;
0C36   F8               .byte 0xF8;
0C37   20               .byte 0x20;
0C38   FF               .byte 0xFF;
0C39   F6               .byte 0xF6;
0C3A   04               .byte 0x04;
0C3B   00               .byte 0x00;
0C3C   F0               .byte 0xF0;
0C3D   9C               .byte 0x9C;
0C3E   FF               .byte 0xFF;
0C3F   02               .byte 0x02;
0C40   08               .byte 0x08;
0C41   FF               .byte 0xFF;
0C42   16               .byte 0x16;
0C43   06               .byte 0x06;
0C44   FF               .byte 0xFF;
0C45   20               .byte 0x20;
0C46   16               .byte 0x16;
0C47   01               .byte 0x01;

                 NeutralArms:
0C48   00               .byte 0x00;
0C49   32               .byte 0x32;
0C4A   1E               .byte 0x1E;
0C4B   FF               .byte 0xFF;
0C4C   F6               .byte 0xF6;
0C4D   14               .byte 0x14;
0C4E   FF               .byte 0xFF;
0C4F   E6               .byte 0xE6;
0C50   00               .byte 0x00;
0C51   00               .byte 0x00;
0C52   24               .byte 0x24;
0C53   C4               .byte 0xC4;
0C54   FF               .byte 0xFF;
0C55   F6               .byte 0xF6;
0C56   EC               .byte 0xEC;
0C57   FF               .byte 0xFF;
0C58   E6               .byte 0xE6;
0C59   00               .byte 0x00;
0C5A   01               .byte 0x01;

                 StationaryLegs:
0C5B   05               .byte 0x05;
0C5C   C4               .byte 0xC4;
0C5D   0A               .byte 0x0A;
0C5E   D8               .byte 0xD8;
0C5F   00               .byte 0x00;
0C60   FC               .byte 0xFC;
0C61   0A               .byte 0x0A;
0C62   FC               .byte 0xFC;
0C63   F6               .byte 0xF6;
0C64   00               .byte 0x00;
0C65   EC               .byte 0xEC;
0C66   30               .byte 0x30;
0C67   00               .byte 0x00;

                 ShootingRight:
0C68   03               .byte 0x03;
0C69   32               .byte 0x32;
0C6A   1E               .byte 0x1E;
0C6B   00               .byte 0x00;
0C6C   28               .byte 0x28;
0C6D   F0               .byte 0xF0;
0C6E   C0               .byte 0xC0;
0C6F   10               .byte 0x10;
0C70   F0               .byte 0xF0;

               ShootingLeft:
0C71   03               .byte 0x03;
0C72   32               .byte 0x32;
0C73   1E               .byte 0x1E;
0C74   F0               .byte 0xF0;
0C75   F0               .byte 0xF0;
0C76   10               .byte 0x10;
0C77   C0               .byte 0xC0;
0C78   00               .byte 0x00;
0C79   28               .byte 0x28;

               ShootingUp:
0C7A   04               .byte 0x04;
0C7B   32               .byte 0x32;
0C7C   1E               .byte 0x1E;
0C7D   0A               .byte 0x0A;
0C7E   14               .byte 0x14;
0C7F   24               .byte 0x24;
0C80   00               .byte 0x00;
0C81   C4               .byte 0xC4;
0C82   E2               .byte 0xE2;
0C83   0E               .byte 0x0E;
0C84   E2               .byte 0xE2;

                ShootingDown:
0C85   04               .byte 0x04;
0C86   32               .byte 0x32;
0C87   1E               .byte 0x1E;
0C88   EC               .byte 0xEC;
0C89   D0               .byte 0xD0;
0C8A   E4               .byte 0xE4;
0C8B   F4               .byte 0xF4;
0C8C   24               .byte 0x24;
0C8D   00               .byte 0x00;
0C8E   0A               .byte 0x0A;
0C8F   14               .byte 0x14;

                ShootingUpperLeft:
0C90   04               .byte 0x04;
0C91   32               .byte 0x32;
0C92   1E               .byte 0x1E;
0C93   F0               .byte 0xF0;
0C94   F0               .byte 0xF0;
0C95   30               .byte 0x30;
0C96   C0               .byte 0xC0;
0C97   D0               .byte 0xD0;
0C98   18               .byte 0x18;
0C99   10               .byte 0x10;
0C9A   10               .byte 0x10;

                ShootingLowerLeft:
0C9B   03               .byte 0x03;
0C9C   32               .byte 0x32;
0C9D   1E               .byte 0x1E;
0C9E   E8               .byte 0xE8;
0C9F   10               .byte 0x10;
0CA0   E0               .byte 0xE0;
0CA1   D0               .byte 0xD0;
0CA2   3A               .byte 0x3A;
0CA3   1A               .byte 0x1A;

                ShootingUpperRight:
0CA4   04               .byte 0x04;
0CA5   32               .byte 0x32;
0CA6   1E               .byte 0x1E;
0CA7   F0               .byte 0xF0;
0CA8   10               .byte 0x10;
0CA9   30               .byte 0x30;
0CAA   18               .byte 0x18;
0CAB   D0               .byte 0xD0;
0CAC   C0               .byte 0xC0;
0CAD   10               .byte 0x10;
0CAE   F0               .byte 0xF0;

                ShootingLowerRight:
0CAF   03               .byte 0x03;
0CB0   32               .byte 0x32;
0CB1   1E               .byte 0x1E;
0CB2   C4               .byte 0xC4;
0CB3   18               .byte 0x18;
0CB4   20               .byte 0x20;
0CB5   D0               .byte 0xD0;
0CB6   18               .byte 0x18;
0CB7   F0               .byte 0xF0;

                MovingArms1:
0CB8   00               .byte 0x00;
0CB9   32               .byte 0x32;
0CBA   1E               .byte 0x1E;
0CBB   FF               .byte 0xFF;
0CBC   F0               .byte 0xF0;
0CBD   10               .byte 0x10;
0CBE   FF               .byte 0xFF;
0CBF   EA               .byte 0xEA;
0CC0   F8               .byte 0xF8;
0CC1   00               .byte 0x00;
0CC2   04               .byte 0x04;
0CC3   BC               .byte 0xBC;
0CC4   FF               .byte 0xFF;
0CC5   18               .byte 0x18;
0CC6   00               .byte 0x00;
0CC7   FF               .byte 0xFF;
0CC8   06               .byte 0x06;
0CC9   14               .byte 0x14;
0CCA   01               .byte 0x01;

                MovingArms2:
0CCB   00               .byte 0x00;
0CCC   32               .byte 0x32;
0CCD   22               .byte 0x22;
0CCE   FF               .byte 0xFF;
0CCF   FA               .byte 0xFA;
0CD0   14               .byte 0x14;
0CD1   FF               .byte 0xFF;
0CD2   E4               .byte 0xE4;
0CD3   00               .byte 0x00;
0CD4   00               .byte 0x00;
0CD5   FC               .byte 0xFC;
0CD6   BC               .byte 0xBC;
0CD7   FF               .byte 0xFF;
0CD8   16               .byte 0x16;
0CD9   F8               .byte 0xF8;
0CDA   FF               .byte 0xFF;
0CDB   10               .byte 0x10;
0CDC   10               .byte 0x10;
0CDD   01               .byte 0x01;

                 AuthorsInitials:
0CDE   F8               .byte 0xF8; /* height */
0CDF   30               .byte 0x30; /* width */
0CE0   A0               .byte 0xA0; /* y */
0CE1   30               .byte 0x30; /* x */
0CE2   43               .string "CMK",0x80;

                 /*
                  * This contains the starting positions for
                  * robots; a random number is used to index into this
                  * table.  It is formated as (y, x) pairs.
                  */
                 RobotStartingPositionTable:
0CE6   40               .byte 0x40;
0CE7   B0               .byte 0xB0;
0CE8   C0               .byte 0xC0;
0CE9   B0               .byte 0xB0;
0CEA   40               .byte 0x40;
0CEB   D8               .byte 0xD8;
0CEC   00               .byte 0x00;
0CED   D8               .byte 0xD8;
0CEE   C0               .byte 0xC0;
0CEF   D8               .byte 0xD8;
0CF0   00               .byte 0x00;
0CF1   00               .byte 0x00;
0CF2   40               .byte 0x40;
0CF3   28               .byte 0x28;
0CF4   00               .byte 0x00;
0CF5   28               .byte 0x28;
0CF6   C0               .byte 0xC0;
0CF7   28               .byte 0x28;
0CF8   40               .byte 0x40;
0CF9   50               .byte 0x50;
0CFA   C0               .byte 0xC0;
0CFB   50               .byte 0x50;

                 /*
                  * By default, certain quadrants within the maze *always*
                  * have certain walls present; i.e. any of the outside
                  * quadrants.  This maze contains the default 'wall mask'
                  * values, which are used to seed the array C8B5-C8C3.
                  * That array is then further modified as the interior
                  * walls are added.  The mask values have the following
                  * meaning:
                  *
                  *              ---------------------------------
                  *              | 0 | 0 | 0 | 0 | B | T | R | L |
                  *              ---------------------------------
                  *   Quadrant has Bottom Wall-----^
                  *   Quadrant has Top Wall------------^
                  *   Quadrant has Right Wall--------------^
                  *   Quadrant has Left Wall-------------------^
                  *
                  * The quadrants are defined as follows:
                  *
                  *       ---------------------
                  *       | 0 | 1 | 2 | 3 | 4 |
                  *       ----+---+---+---+----
                  *       | 5 | 6 | 7 | 8 | 9 |
                  *       ----+---+---+---+----
                  *       |10 |11 |12 |13 |14 |
                  *       ---------------------
                  */
                 DefaultMazeWallsPerQuadrant:
0CFC   05               .byte 0x05;   /* left and top walls */
0CFD   04               .byte 0x04;   /* top wall */
0CFE   04               .byte 0x04;   /* top wall */
0CFF   04               .byte 0x04;   /* top wall */
0D00   06               .byte 0x06;   /* top and right walls */
0D01   01               .byte 0x01;   /* left wall */
0D02   00               .byte 0x00;   /* no walls */
0D03   00               .byte 0x00;   /* no walls */
0D04   00               .byte 0x00;   /* no walls */
0D05   02               .byte 0x02;   /* right wall */
0D06   09               .byte 0x09;   /* bottom and left wall */
0D07   08               .byte 0x08;   /* bottom wall */
0D08   08               .byte 0x08;   /* bottom wall */
0D09   08               .byte 0x08;   /* bottom wall */
0D0A   0A               .byte 0x0A;   /* bottom and right walls */

                 PlayerFriedIntensities:
0D0B   08               .byte 0x08;
0D0C   07               .byte 0x07;
0D0D   06               .byte 0x06;
0D0E   05               .byte 0x05;
0D0F   05               .byte 0x05;
0D10   05               .byte 0x05;
0D11   06               .byte 0x06;
0D12   07               .byte 0x07;
0D13   08               .byte 0x08;
0D14   09               .byte 0x09;
0D15   08               .byte 0x08;
0D16   07               .byte 0x07;
0D17   06               .byte 0x06;
0D18   05               .byte 0x05;
0D19   06               .byte 0x06;
0D1A   07               .byte 0x07;

                 /*
                  * CheckForContact()
                  *
                  * This function checks to see if two objects have come
                  * into contact (such as a bullet and a robot, a bullet
                  * and the player, or a robot and the player.  The 2
                  * objects do not need to come into exact contact, but
                  * rather, they only need to come within a prespecified
                  * distance.
                  *
                  * Entry:
                  *   x = ptr to object to which contact is being checked.
                  *   a = y position to check for contact with object.
                  *   b = x position to check for contact with object.
                  *   y = ptr to table telling how close contact must be.
                  *
                  * Exit:
                  *   The carry bit will be set if contact was made.
                  */
                 CheckForContact:
0D1B   A084             suba  ,x;
0D1D   E001             subb  1,x;
0D1F   A1A4             cmpa  ,y;
0D21   2E0F             bgt   P0D32;
0D23   A121             cmpa  1,y;
0D25   2D0B             blt   P0D32;
0D27   E122             cmpb  2,y;
0D29   2E07             bgt   P0D32;
0D2B   E123             cmpb  3,y;
0D2D   2D03             blt   P0D32;
0D2F   1A01             orcc  #0x01;
0D31   39               rts;
0D32   1CFE      P0D32: andcc #0xFE;
0D34   39               rts;

                 /*
                  * The following 3 tables define the bounding box around
                  * some figure (robot, player).  It is used to determine
                  * when something has hit the figure.  Each table contains
                  * the following values:
                  *
                  *     + y delta
                  *     - y delta
                  *     + x delta
                  *     - x delta
                  */
                 RobotContactBounds:
0D35   06               .byte 0x06;
0D36   FA               .byte 0xFA;
0D37   06               .byte 0x06;
0D38   FA               .byte 0xFA;

                 PlayerContactBounds:
0D39   05               .byte 0x05;
0D3A   F7               .byte 0xF7;
0D3B   05               .byte 0x05;
0D3C   FB               .byte 0xFB;

                 PlayerContactBounds2:
0D3D   05               .byte 0x05;
0D3E   FB               .byte 0xFB;
0D3F   05               .byte 0x05;
0D40   FB               .byte 0xFB;

                 /*
                  * This function appears to do some random mucking relating
                  * to sound.
                  */
                 DoUnknownSoundMucking:
0D41   0C77             inc   0x77;
0D43   860E             lda   #0x0E;
0D45   9744             sta   0x44;
0D47   9743             sta   0x43;
0D49   9742             sta   0x42;
0D4B   9667             lda   0x67;
0D4D   8580             bita  #0x80;
0D4F   2703             beq   P0D54;
0D51   7E0DF2           jmp   $P0DF2;
0D54   8508      P0D54: bita  #0x08;
0D56   270A      P0D56: beq   P0D62;
0D58   CC0080           ldd   #0x0080;
0D5B   9777             sta   0x77;
0D5D   D767             stb   0x67;
0D5F   7E0DEB           jmp   $P0DEB;
0D62   8540      P0D62: bita  #0x40;
0D64   2703             beq   P0D69;
0D66   7E0E32           jmp   $P0E32;
0D69   8504      P0D69: bita  #0x04;
0D6B   270A             beq   P0D77;
0D6D   CC0040           ldd   #0x0040;
0D70   9777             sta   0x77;
0D72   D767             stb   0x67;
0D74   7E0E22           jmp   $P0E22;
0D77   8502      P0D77: bita  #0x02;
0D79   270A             beq   P0D85;
0D7B   CC0020           ldd   #0x0020;
0D7E   9777             sta   0x77;
0D80   D767             stb   0x67;
0D82   7E0DB2           jmp   $P0DB2;
0D85   8520      P0D85: bita  #0x20;
0D87   2703             beq   P0D8C;
0D89   7E0DC3           jmp   $P0DC3;
0D8C   8501      P0D8C: bita  #0x01;
0D8E   270A             beq   P0D9A;
0D90   CC0010           ldd   #0x0010;
0D93   9777             sta   0x77;
0D95   D767             stb   0x67;
0D97   7E0E56           jmp   $DoUnknownSoundMucking3;
0D9A   8510      P0D9A: bita  #0x10;
0D9C   2703             beq   P0DA1;
0D9E   7E0E6A           jmp   $DoUnknownSoundMucking4;
0DA1   9676      P0DA1: lda   0x76;
0DA3   8510             bita  #0x10;
0DA5   2703             beq   P0DAA;
0DA7   7E0EAB           jmp   $P0EAB;
0DAA   8501      P0DAA: bita  #0x01;
0DAC   2703             beq   P0DB1;
0DAE   7E0E99           jmp   $P0E99;
0DB1   39        P0DB1: rts;
0DB2   CC0039    P0DB2: ldd   #0x0039;
0DB5   DD4B             std   0x4B;
0DB7   CC0030           ldd   #0x0030;
0DBA   DD49             std   0x49;
0DBC   CC0100           ldd   #0x0100;
0DBF   DD47             std   0x47;
0DC1   2015             bra   P0DD8;
0DC3   DC4B      P0DC3: ldd   0x4B;
0DC5   C30014           addd  #0x0014;
0DC8   DD4B             std   0x4B;
0DCA   DC49             ldd   0x49;
0DCC   C30024           addd  #0x0024;
0DCF   DD49             std   0x49;
0DD1   DC47             ldd   0x47;
0DD3   C30060           addd  #0x0060;
0DD6   DD47             std   0x47;
0DD8   8624      P0DD8: lda   #0x24;
0DDA   9177      P0DDA: cmpa  0x77;
0DDC   2304             bls   P0DE2;
0DDE   8638             lda   #0x38;
0DE0   2006             bra   P0DE8;
0DE2   863F      P0DE2: lda   #0x3F;
0DE4   0F67             clr   0x67;
0DE6   0F76             clr   0x76;
0DE8   9745      P0DE8: sta   0x45;
0DEA   39               rts;
0DEB   CC00C0    P0DEB: ldd   #0x00C0;
0DEE   DD4B             std   0x4B;
0DF0   0F6A             clr   0x6A;
0DF2   9677      P0DF2: lda   0x77;
0DF4   8501             bita  #0x01;
0DF6   2707             beq   P0DFF;
0DF8   DC4B             ldd   0x4B;
0DFA   C30010           addd  #0x0010;
0DFD   2005             bra   P0E04;
0DFF   DC4B      P0DFF: ldd   0x4B;
0E01   830013           subd  #0x0013;
0E04   DD4B      P0E04: std   0x4B;
0E06   D66A             ldb   0x6A;
0E08   5C               incb;
0E09   C108             cmpb  #0x08;
0E0B   2302             bls   P0E0F;
0E0D   C606             ldb   #0x06;
0E0F   D76A      P0E0F: stb   0x6A;
0E11   8650             lda   #0x50;
0E13   3D               mul;
0E14   DD49             std   0x49;
0E16   D66A             ldb   0x6A;
0E18   8631             lda   #0x31;
0E1A   3D               mul;
0E1B   DD47             std   0x47;
0E1D   862C             lda   #0x2C;
0E1F   7E0DDA           jmp   $P0DDA;
0E22   CC0030    P0E22: ldd   #0x0030;
0E25   DD4B             std   0x4B;
0E27   CC0000           ldd   #0x0000;
0E2A   DD49             std   0x49;
0E2C   CC0120           ldd   #0x0120;
0E2F   DD47             std   0x47;
0E31   39               rts;
0E32   8EC84B    P0E32: ldx   #0xC84B;
0E35   8D0A             bsr   DoUnknownSoundMucking2;
0E37   8EC849           ldx   #0xC849;
0E3A   8D05             bsr   DoUnknownSoundMucking2;
0E3C   8618             lda   #0x18;
0E3E   7E0DDA           jmp   $P0DDA;

                 /*
                  * This function appears to do some random mucking relating
                  * to sound.
                  */
                 DoUnknownSoundMucking2:
0E41   9677             lda   0x77;
0E43   8501             bita  #0x01;
0E45   2707             beq   P0E4E;
0E47   EC84             ldd   ,x;
0E49   C30023           addd  #0x0023;
0E4C   2005             bra   P0E53;
0E4E   EC84      P0E4E: ldd   ,x;
0E50   830010           subd  #0x0010;
0E53   ED84      P0E53: std   ,x;
0E55   39               rts;

                 /*
                  * This function appears to do some random mucking relating
                  * to sound.
                  */
                 DoUnknownSoundMucking3:
0E56   8603             lda   #0x03;
0E58   976A             sta   0x6A;
0E5A   CC0039           ldd   #0x0039;
0E5D   DD4B             std   0x4B;
0E5F   CC0030           ldd   #0x0030;
0E62   DD49             std   0x49;
0E64   CC0040           ldd   #0x0040;
0E67   DD47             std   0x47;
0E69   39               rts;

                 /*
                  * This function appears to do some random mucking relating
                  * to sound.
                  */
                 DoUnknownSoundMucking4:
0E6A   966A             lda   0x6A;
0E6C   2B11             bmi   P0E7F;
0E6E   D677             ldb   0x77;
0E70   C104             cmpb  #0x04;
0E72   230B             bls   P0E7F;
0E74   0F77             clr   0x77;
0E76   0A6A             dec   0x6A;
0E78   CC0039           ldd   #0x0039;
0E7B   DD4B             std   0x4B;
0E7D   2007             bra   P0E86;
0E7F   DC4B      P0E7F: ldd   0x4B;
0E81   C3001A           addd  #0x001A;
0E84   DD4B             std   0x4B;
0E86   DC49      P0E86: ldd   0x49;
0E88   C30024           addd  #0x0024;
0E8B   DD49             std   0x49;
0E8D   DC47             ldd   0x47;
0E8F   C30024           addd  #0x0024;
0E92   DD47             std   0x47;
0E94   861C             lda   #0x1C;
0E96   7E0DDA           jmp   $P0DDA;
0E99   8610      P0E99: lda   #0x10;
0E9B   0F67             clr   0x67;
0E9D   0F77             clr   0x77;
0E9F   9776             sta   0x76;
0EA1   CC0000           ldd   #0x0000;
0EA4   DD47             std   0x47;
0EA6   CC0300           ldd   #0x0300;
0EA9   DD4B             std   0x4B;
0EAB   9677      P0EAB: lda   0x77;
0EAD   8106             cmpa  #0x06;
0EAF   230B             bls   P0EBC;
0EB1   810C             cmpa  #0x0C;
0EB3   2207             bhi   P0EBC;
0EB5   DC4B             ldd   0x4B;
0EB7   830040           subd  #0x0040;
0EBA   DD4B             std   0x4B;
0EBC   DC4B      P0EBC: ldd   0x4B;
0EBE   44               lsra;
0EBF   56               rorb;
0EC0   DD49             std   0x49;
0EC2   8618             lda   #0x18;
0EC4   7E0DDA           jmp   $P0DDA;

                 /*
                  * CheckForQuadrantEdgeCrossing()
                  *
                  * This function determines whether an object has crossed
                  * over the edge of a quadrant; this helps to determine
                  * when a player runs into a wall, or exits through an
                  * open door.  It returns a mask, which indicates which
                  * edge (or edges) have been crossed.
                  *
                  * Entry:
                  *   d = a point in the quadrant, relative to the lower left
                  *       corner of the quadrant.
                  *   x = pointer to a table of boundary conditions, which
                  *       tell how close the point must be to the actual
                  *       edge, to consider an edge crossing as having
                  *       occurred (these offsets are relative to the lower
                  *       left corner of the quadrant).  The values in this
                  *       table are:
                  *
                  *             yLeft, yRight, xLeft, xRight
                  *
                  * Exit:
                  *   b = mask (having the following meaning):
                  *
                  *         ---------------------------------
                  *         | 0 | 0 | 0 | 0 | B | T | R | L |
                  *         ---------------------------------
                  *
                  *   Bottom Edge Crossing----^
                  *   Top Edge Crossing-----------^
                  *   Right Edge Crossing-------------^
                  *   Left Edge Crossing------------------^
                  */
                 CheckForQuadrantEdgeCrossing:
0EC7   5F               clrb;
0EC8   A184             cmpa  ,x;
0ECA   2C04             bge   P0ED0;
0ECC   CA08             orb   #0x08;
0ECE   2006             bra   P0ED6;
0ED0   A101      P0ED0: cmpa  1,x;
0ED2   2F02             ble   P0ED6;
0ED4   CA04             orb   #0x04;
0ED6   969C      P0ED6: lda   0x9C;
0ED8   A102             cmpa  2,x;
0EDA   2F03             ble   P0EDF;
0EDC   CA02             orb   #0x02;
0EDE   39               rts;
0EDF   A103      P0EDF: cmpa  3,x;
0EE1   2C02             bge   P0EE5;
0EE3   CA01             orb   #0x01;
0EE5   39        P0EE5: rts;


                 /*
                  * The following are all threshold tables, used when
                  * calling CheckForQuadrantEdgeContact(); a different
                  * table is used, depending upon what object is represented
                  * by the point (a robot, the player, a bullet, etc).
                  * Quadrants are all 40 wide x 64 high.
                  * Each of the tables is composed of the following values:
                  *
                  *     y left threshold
                  *     y right threshold
                  *     x left threshold
                  *     x right threshold
                  */
                 RobotThresholds:
0EE6   08               .byte 0x08;
0EE7   38               .byte 0x38;
0EE8   20               .byte 0x20;
0EE9   08               .byte 0x08;

                 PlayerThresholds:
0EEA   0A               .byte 0x0A;
0EEB   3C               .byte 0x3C;
0EEC   24               .byte 0x24;
0EED   04               .byte 0x04;

                 BulletThresholds:
0EEE   04               .byte 0x04;
0EEF   3C               .byte 0x3C;
0EF0   24               .byte 0x24;
0EF1   04               .byte 0x04;

                 BulletToWallThresholds:
0EF2   01               .byte 0x01;
0EF3   3F               .byte 0x3F;
0EF4   27               .byte 0x27;
0EF5   01               .byte 0x01;

                 /*
                  * DetermineMazeWalls()
                  *
                  * This function calculates the 8 walls (and the optional
                  * door) which are present in a maze.  The maze has 8
                  * internal points from which a wall can start, and fromright
                  * each point, the wall can go either upwards, downwards,
                  * to the right or to the left.  The array at C8AB will be
                  * filled with an integer index telling which walls are to
                  * be drawn (0=up, 2=down, 4=to right, 6=to left).  The
                  * array at C8B5 is a collection of bitmasks, indicating
                  * which walls are present for each quadrant (there is one
                  * entry in the array per quadrant).  The mask has the
                  * following format:
                  *
                  *              ---------------------------------
                  *              | 0 | 0 | 0 | 0 | B | T | R | L |
                  *              ---------------------------------
                  *   Quadrant has Bottom Wall-----^
                  *   Quadrant has Top Wall------------^
                  *   Quadrant has Right Wall--------------^
                  *   Quadrant has Left Wall-------------------^
                  */
                 DetermineMazeWalls:
0EF6   860F             lda   #0x0F;
0EF8   CE0CFC           ldu   #DefaultMazeWallsPerQuadrant;
0EFB   8EC8B5           ldx   #0xC8B5;
0EFE   3184             leay  ,x;
0F00   BDF683           jsr   $move_block2;
0F03   30A4             leax  ,y;
0F05   C608             ldb   #0x08;
0F07   D79F             stb   0x9F;
0F09   CEC8AB           ldu   #0xC8AB;
0F0C   BDF517    P0F0C: jsr   $get_random_a;
0F0F   8403             anda  #0x03;
0F11   8103             cmpa  #0x03;
0F13   2D0E             blt   P0F23;
0F15   E684             ldb   ,x;       /* Draw to the left from point */
0F17   CA08             orb   #0x08;    /* This quad has a bottom wall, and */
0F19   E784             stb   ,x;
0F1B   E605             ldb   5,x;
0F1D   CA04             orb   #0x04;    /* the quad below it has a top wall */
0F1F   E705             stb   5,x;
0F21   2030             bra   P0F53;
0F23   8102      P0F23: cmpa  #0x02;
0F25   2D0E             blt   P0F35;
0F27   E601             ldb   1,x;     /* Draw to the right from point */
0F29   CA08             orb   #0x08;   /* Next quad has a bottom wall, and */
0F2B   E701             stb   1,x;
0F2D   E606             ldb   6,x;
0F2F   CA04             orb   #0x04;   /* Quad below it has a top wall */
0F31   E706             stb   6,x;
0F33   201E             bra   P0F53;
0F35   8101      P0F35: cmpa  #0x01;
0F37   2D0E             blt   P0F47;
0F39   E605             ldb   5,x;     /* Draw downwards from point */
0F3B   CA02             orb   #0x02;   /* Quad below has a right wall, and */
0F3D   E705             stb   5,x;
0F3F   E606             ldb   6,x;
0F41   CA01             orb   #0x01;   /* quad next to it has a left wall */
0F43   E706             stb   6,x;
0F45   200C             bra   P0F53;
0F47   E684      P0F47: ldb   ,x;      /* Draw upwards from point */
0F49   CA02             orb   #0x02;   /* This quad has a right wall, and */
0F4B   E784             stb   ,x;
0F4D   E601             ldb   1,x;
0F4F   CA01             orb   #0x01;   /* quad next to it has a left wall */
0F51   E701             stb   1,x;
0F53   48        P0F53: asla;
0F54   A7C0             sta   ,u+;     /* Save the wall index */
0F56   C605             ldb   #0x05;
0F58   D19F             cmpb  0x9F;
0F5A   2602             bne   P0F5E;
0F5C   3001             leax  1,x;
0F5E   3001      P0F5E: leax  1,x;
0F60   0A9F             dec   0x9F;
0F62   26A8             bne   P0F0C;
0F64   39               rts;

                 /*
                  * DetermineDirectionToMove()
                  *
                  * This function takes a point, and returns a mask
                  * indicating the direction the point must travel, in
                  * in order to reach the player.  It also returns the
                  * distance (rise and run) describing how far away the
                  * point is from the player.
                  *
                  * Entry:
                  *   a = y position
                  *   b = x position
                  *
                  * Exit:
                  *   C8DE: y distance between point and player.
                  *   C8DF: x distance between point and player.
                  *   b = mask, indicating desired direction of travel
                  *
                  *              ---------------------------------
                  *              | 0 | 0 | x | 0 | x | x | x | x |
                  *              ---------------------------------
                  *   x and/or y is same --^
                  *   Down ------------------------^
                  *   Up ------------------------------^
                  *   Right -------------------------------^
                  *   Left ------------------------------------^
                  */
                 DetermineDirectionToMove:
0F65   8B80             adda  #0x80;
0F67   CB80             addb  #0x80;
0F69   DDE7             std   0xE7;
0F6B   968F             lda   0x8F;
0F6D   8B80             adda  #0x80;
0F6F   5F               clrb;
0F70   90E7             suba  0xE7;
0F72   2706             beq   P0F7A;
0F74   2508             blo   P0F7E;
0F76   CA04             orb   #0x04;
0F78   2006             bra   P0F80;
0F7A   CA20      P0F7A: orb   #0x20;
0F7C   2002             bra   P0F80;
0F7E   CA08      P0F7E: orb   #0x08;
0F80   40        P0F80: nega;
0F81   97DE             sta   0xDE;
0F83   9690             lda   0x90;
0F85   8B80             adda  #0x80;
0F87   90E8             suba  0xE8;
0F89   97DF             sta   0xDF;
0F8B   2705             beq   P0F92;
0F8D   2506             blo   P0F95;
0F8F   CA02             orb   #0x02;
0F91   39               rts;
0F92   CA20      P0F92: orb   #0x20;
0F94   39               rts;
0F95   CA01      P0F95: orb   #0x01;
0F97   39               rts;


                 /*
                  * MapPointToQuadrantAndMakeRelative()
                  *
                  * This function takes a point, and determines which of
                  * 15 quadrants it falls into.  It also maps the point
                  * so that it is relative to the lower left corner of the
                  * quadrant, and returns the bitmask indicating which walls
                  * are defined for this quadrant.
                  *
                  * Entry:
                  *   d = (y,x) position
                  *
                  * Exit:
                  *   C89A = quadrant (0 - 15)
                  *   C899 = wall bitmask
                  *   C89B-C89C = point, relative to lower left quad corner
                  *   d = point, relative to lower left quad corner
                  *
                  * where the bitmask has the following format:
                  *
                  *              ---------------------------------
                  *              | 0 | 0 | 0 | 0 | B | T | R | L |
                  *              ---------------------------------
                  *   Quadrant has Bottom Wall-----^
                  *   Quadrant has Top Wall------------^
                  *   Quadrant has Right Wall--------------^
                  *   Quadrant has Left Wall-------------------^
                  *
                  * and the quadrants are defined as follows:
                  *
                  *     -100 -60 -20 +20 +60 +100
                  *       --------------------- +96
                  *       | 0 | 1 | 2 | 3 | 4 |
                  *       ----+---+---+---+---- +32
                  *       | 5 | 6 | 7 | 8 | 9 |
                  *       ----+---+---+---+---- -32
                  *       |10 |11 |12 |13 |14 |
                  *       --------------------- -96
                  */
                 MapPointToQuadrantAndMakeRelative:
0F98   DD9B             std   0x9B;
0F9A   5F               clrb;
0F9B   81E0             cmpa  #0xE0;  /* -32 */
0F9D   2E04             bgt   P0FA3;
0F9F   CB0A             addb  #0x0A;
0FA1   2006             bra   P0FA9;
0FA3   8120      P0FA3: cmpa  #0x20;  /* 32 */
0FA5   2E02             bgt   P0FA9;
0FA7   CB05             addb  #0x05;
0FA9   969C      P0FA9: lda   0x9C;
0FAB   81C4             cmpa  #0xC4;  /* -60 */
0FAD   2F10             ble   P0FBF;
0FAF   5C               incb;
0FB0   81EC             cmpa  #0xEC;  /* -20 */
0FB2   2F0B             ble   P0FBF;
0FB4   5C               incb;
0FB5   8114             cmpa  #0x14;  /* 20 */
0FB7   2F06             ble   P0FBF;
0FB9   5C               incb;
0FBA   813C             cmpa  #0x3C;  /* 60 */
0FBC   2F01             ble   P0FBF;
0FBE   5C               incb;
0FBF   D79A      P0FBF: stb   0x9A;      /* Save the quadrant number */
0FC1   8EC8B5           ldx   #0xC8B5;
0FC4   A685             lda   b,x;
0FC6   9799             sta   0x99;      /* Save the wall bitmask */
0FC8   8E0FD3           ldx   #RelativeOffsetConversionTable;
0FCB   58               aslb;
0FCC   EC85             ldd   b,x;
0FCE   D39B             addd  0x9B;
0FD0   DD9B             std   0x9B;      /* Make into a relative point */
0FD2   39               rts;

                 RelativeOffsetConversionTable:
0FD3   E0               .byte 0xE0;  /* Quad 0 y */
0FD4   64               .byte 0x64;  /* Quad 0 x */
0FD5   E0               .byte 0xE0;  /* Quad 1 y */
0FD6   3C               .byte 0x3C;  /* Quad 1 x */
0FD7   E0               .byte 0xE0;  /* Quad 2 y */
0FD8   14               .byte 0x14;  /* Quad 2 x */
0FD9   E0               .byte 0xE0;  /* Quad 3 y */
0FDA   EC               .byte 0xEC;  /* Quad 3 x */
0FDB   E0               .byte 0xE0;  /* Quad 4 y */
0FDC   C4               .byte 0xC4;  /* Quad 4 x */
0FDD   20               .byte 0x20;  /* Quad 5 y */
0FDE   64               .byte 0x64;  /* Quad 5 x */
0FDF   20               .byte 0x20;  /* Quad 6 y */
0FE0   3C               .byte 0x3C;  /* Quad 6 x */
0FE1   20               .byte 0x20;  /* Quad 7 y */
0FE2   14               .byte 0x14;  /* Quad 7 x */
0FE3   20               .byte 0x20;  /* Quad 8 y */
0FE4   EC               .byte 0xEC;  /* Quad 8 x */
0FE5   20               .byte 0x20;  /* Quad 9 y */
0FE6   C4               .byte 0xC4;  /* Quad 9 x */
0FE7   60               .byte 0x60;  /* Quad 10 y */
0FE8   64               .byte 0x64;  /* Quad 10 x */
0FE9   60               .byte 0x60;  /* Quad 11 y */
0FEA   3C               .byte 0x3C;  /* Quad 11 x */
0FEB   60               .byte 0x60;  /* Quad 12 y */
0FEC   14               .byte 0x14;  /* Quad 12 x */
0FED   60               .byte 0x60;  /* Quad 13 y */
0FEE   EC               .byte 0xEC;  /* Quad 13 x */
0FEF   60               .byte 0x60;  /* Quad 14 y */
0FF0   C4               .byte 0xC4;  /* Quad 14 x */

                /* These appear to be unused bytes */
0FF1   01               .byte 0x01;
0FF2   6C               .byte 0x6C;
0FF3   DD               .byte 0xDD;
0FF4   74               .byte 0x74;
0FF5   DD               .byte 0xDD;
0FF6   47               .byte 0x47;
0FF7   96               .byte 0x96;
0FF8   67               .byte 0x67;
0FF9   84               .byte 0x84;
0FFA   03               .byte 0x03;
0FFB   97               .byte 0x97;
0FFC   68               .byte 0x68;
0FFD   0F               .byte 0x0F;
0FFE   67               .byte 0x67;
0FFF   39               .byte 0x39;

