// ECE 476 MISSILE COMMAND PROJECT: MISSILE CODE

// CORNELL UNIVERSITY, 2005

// CEM OZKAYNAK, BRIAN SMITH

// Contact co37@cornell.edu, bcs27@cornell.edu

//

//video gen and sound

//D.5 is sync:1000 ohm + diode to 75 ohm resistor

//D.6 is video:330 ohm + diode to 75 ohm resistor 

//B.3 is sound  and should have a 10k resistor to gnd

 

#pragma regalloc-    //I allocate the registers myself

#pragma optsize-     //optimize for speed

                   

#include <Mega32.h>  

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <delay.h>  

 

//cycles = 63.625 * 16 Note NTSC is 63.55

//but this line duration makes each frame exactly 1/60 sec

//which is nice for keeping a realtime clock

#define lineTime 1018

 

#define begin {

#define end   }

#define ScreenTop 30

#define ScreenBot 230

#define width 126

#define height 78

#define max 8        // Maximum missile count per level

#define max_intercept 8

#define citycount 5

//game states

#define       PRNT_INTRO 1

#define       GET_INTRO 2

#define       PRNT_DIF 3

#define       GET_DIF 4

#define GAME_INIT 5

#define RUN_GAME 6

#define PRNT_GAMEOVER 7

#define GET_GAMEOVER 8

#define RESTART 9

#define PAUSE 10

 

//NOTE that v1 to v8 and i must be in registers! 

register char v1 @4;

register char v2 @5;

register char v3 @6;

register char v4 @7;

register char v5 @8;

register char v6 @9;

register char v7 @10;

register char v8 @11;

register int i @12;

 

#pragma regalloc+

 

char syncON, syncOFF;

int LineCount;

int time, vint;

unsigned char gamestate, printcount, level, justfired, justfiredr, temp, temp2;

unsigned long score;

unsigned long eeprom highscore;

unsigned char m_index, mpw;

unsigned char i_index, icount;

unsigned char c_index, deadcities, fastcount, fastcount2;

unsigned char cstatus[citycount], mstatus[max], istatus[max_intercept];

unsigned char curx, cury;

 

unsigned int mtimer[max];

unsigned char mx[max],my[max],mxp[max],myp[max],m_theta[max];

unsigned int mxp_long[max],myp_long[max];

unsigned char ix[max_intercept],iy[max_intercept],ixf[max_intercept],iyf[max_intercept],ixp[max_intercept],iyp[max_intercept],xbox[max_intercept],ybox[max_intercept];

unsigned int ixp_long[max_intercept],iyp_long[max_intercept];

 

char screen[1600], t, ts[10];

flash char cu1[]="MISSILE";

flash char cu2[]="COMMAND";

//flash char mc[]="MISSILECOMMAND";

flash char clb[]="CLICK2BEGIN";

flash char diff[]="DIFFICULTY";

flash char scorestr[]="SCORE";

flash char highstr[]="HIGH";

flash char easy[]="NKOREA";

flash char med[] ="PAKISTAN";

flash char hard[]="USSR";

flash char lose[]="BOOM";

flash char paused[]="P";

flash char pmenu[]="E";

char tempstr[10];                       

                                               

flash unsigned char start_max[] = {48, 71, 89, 105, 119, 126, 126, 126, 126, 126};

flash unsigned char start_min[] = {2, 2, 2, 2, 2, 7, 21, 37, 55, 78};

flash unsigned char del_start[] = {46, 69, 87, 103, 117, 119, 105, 89, 71, 48};

flash unsigned char cx[] = {3,28,44,82,104};           // X locations of Cities;

 

// Indexed by increasing difficulty levels

flash unsigned int mvy[] = {64, 128, 192, 255};        // Missile Y-Velocity [Pixels/(8 Frames)]

flash unsigned int time2gnd[] = {308, 152, 102, 77};   // Time to Ground [8 Frames]

flash signed int mvx[10][4] =

{

64,128,192,255,

45,90,134,179,

30,60,90,119,

17,34,51,69,

6,11,17,22,

-6,-11,-17,-22,

-17,-34,-51,-69,

-30,-60,-90,-119,

-45,-90,-134,-179,

-64,-128,-192,-255};

 

flash signed int ivx[42][26] = 

{

-256,-255,-254,-252,-250,-247,-243,-240,-236,-231,-227,-222,-217,-212,-208,-203,-198,-193,-189,-184,-180,-175,-171,-167,-163,-159,

-256,-255,-254,-252,-249,-246,-242,-238,-234,-229,-224,-219,-214,-209,-204,-199,-194,-189,-184,-179,-175,-170,-166,-162,-158,-154,

-256,-255,-253,-251,-248,-245,-241,-236,-231,-226,-221,-216,-211,-205,-200,-195,-189,-184,-179,-175,-170,-165,-161,-157,-153,-149,

-256,-255,-253,-250,-247,-243,-239,-234,-229,-224,-218,-212,-207,-201,-195,-190,-185,-179,-174,-169,-165,-160,-155,-151,-147,-143,

-256,-255,-253,-250,-246,-242,-237,-232,-226,-220,-214,-208,-202,-196,-190,-185,-179,-174,-169,-164,-159,-154,-150,-145,-141,-137,

-256,-255,-252,-249,-245,-240,-235,-229,-223,-217,-210,-204,-197,-191,-185,-179,-173,-168,-162,-157,-153,-148,-143,-139,-135,-131,

-256,-254,-252,-248,-243,-238,-232,-226,-219,-212,-205,-199,-192,-185,-179,-173,-167,-161,-156,-151,-146,-141,-137,-133,-129,-125,

-256,-254,-251,-247,-242,-236,-229,-222,-215,-207,-200,-193,-186,-179,-172,-166,-160,-154,-149,-144,-139,-134,-130,-126,-122,-118,

-256,-254,-250,-245,-239,-233,-225,-217,-209,-201,-194,-186,-179,-172,-165,-158,-152,-147,-141,-136,-131,-127,-122,-118,-114,-111,

-256,-253,-249,-244,-237,-229,-221,-212,-203,-195,-186,-178,-171,-163,-157,-150,-144,-138,-133,-128,-123,-119,-114,-111,-107,-103,

-255,-253,-248,-241,-233,-224,-215,-206,-196,-187,-178,-170,-162,-154,-147,-141,-135,-129,-124,-119,-114,-110,-106,-102,-99,-96,

-255,-252,-246,-238,-229,-219,-208,-198,-188,-178,-169,-160,-152,-144,-137,-131,-125,-120,-114,-110,-105,-101,-97,-94,-91,-87,

-255,-251,-244,-234,-223,-212,-200,-188,-177,-167,-158,-149,-141,-133,-126,-120,-114,-109,-104,-100,-96,-92,-88,-85,-82,-79,

-255,-250,-241,-229,-216,-203,-189,-177,-165,-155,-145,-136,-128,-121,-114,-109,-103,-98,-94,-89,-86,-82,-79,-76,-73,-70,

-255,-248,-236,-222,-206,-191,-176,-163,-151,-140,-131,-122,-114,-108,-101,-96,-91,-86,-82,-78,-75,-72,-69,-66,-64,-61,

-254,-244,-229,-211,-193,-175,-160,-146,-134,-124,-114,-106,-99,-93,-87,-82,-78,-74,-70,-67,-64,-61,-59,-56,-54,-52,

-253,-239,-218,-195,-174,-155,-140,-126,-114,-105,-96,-89,-83,-77,-73,-68,-64,-61,-58,-55,-53,-50,-48,-46,-44,-43,

-251,-229,-200,-172,-149,-130,-114,-102,-92,-83,-76,-70,-65,-61,-57,-53,-50,-47,-45,-43,-41,-39,-37,-36,-34,-33,

-246,-208,-169,-137,-114,-97,-85,-75,-67,-60,-55,-50,-46,-43,-40,-38,-35,-34,-32,-30,-29,-27,-26,-25,-24,-23,

-229,-160,-114,-87,-70,-59,-50,-44,-39,-35,-32,-29,-27,-25,-23,-22,-20,-19,-18,-17,-16,-16,-15,-14,-14,-13,

-114,-50,-32,-23,-18,-15,-13,-11,-10,-9,-8,-7,-7,-6,-6,-5,-5,-5,-5,-4,-4,-4,-4,-4,-3,-3,

181,95,62,46,36,30,25,22,20,18,16,15,13,12,12,11,10,10,9,9,8,8,8,7,7,7,

238,181,136,106,86,72,62,54,48,43,40,36,33,31,29,27,25,24,23,22,21,20,19,18,17,17,

248,217,181,151,127,109,95,84,75,68,62,57,53,49,46,43,40,38,36,34,33,31,30,29,28,26,

252,233,207,181,158,139,123,110,100,91,83,77,71,66,62,58,55,52,49,47,45,43,41,39,38,36,

253,241,222,201,181,163,147,133,121,111,103,95,89,83,78,73,69,65,62,59,56,54,52,50,48,46,

254,246,232,215,198,181,166,152,140,129,120,112,105,98,92,87,82,78,74,71,68,65,62,60,57,55,

255,248,238,224,210,195,181,168,156,145,136,127,119,112,106,100,95,90,86,82,79,75,72,69,67,64,

255,250,242,231,219,206,193,181,170,159,149,141,133,125,119,113,107,102,97,93,89,85,82,79,76,73,

255,251,245,236,225,214,203,192,181,171,161,153,145,137,130,124,118,113,108,103,99,95,91,88,85,82,

255,252,247,239,231,221,211,201,191,181,172,163,155,148,141,134,128,123,118,113,108,104,100,97,93,90,

256,253,248,242,235,226,217,208,199,190,181,173,165,158,151,144,138,132,127,122,117,113,109,105,102,98,

256,253,250,244,238,230,222,214,206,197,189,181,173,166,159,153,147,141,136,131,126,121,117,113,109,106,

256,254,251,246,240,234,227,219,211,204,196,188,181,174,167,161,155,149,144,139,134,129,125,121,117,113,

256,254,251,247,242,236,230,223,216,209,202,195,188,181,175,168,162,157,151,146,141,137,132,128,124,120,

256,254,252,248,244,239,233,227,220,214,207,200,194,187,181,175,169,164,158,153,148,144,139,135,131,127,

256,255,252,249,245,241,236,230,224,218,212,205,199,193,187,181,175,170,165,160,155,150,146,141,137,133,

256,255,253,250,247,242,238,233,227,221,216,210,204,198,192,187,181,176,171,166,161,156,152,147,143,139,

256,255,253,251,248,244,240,235,230,225,219,214,208,202,197,192,186,181,176,171,166,162,157,153,149,145,

256,255,253,251,248,245,241,237,232,227,222,217,212,207,201,196,191,186,181,176,172,167,163,159,154,151,

256,255,254,252,249,246,242,239,234,230,225,220,215,210,205,200,195,190,186,181,176,172,168,164,160,156,

256,255,254,252,250,247,244,240,236,232,227,223,218,214,209,204,199,195,190,185,181,177,172,168,164,161

};

 

 

flash signed int ivy[42][26] =

{

8,21,33,45,57,69,80,90,100,110,119,127,135,143,150,156,162,168,173,178,182,187,191,194,198,201,

9,22,35,48,60,72,83,94,105,114,124,132,140,148,155,161,167,173,178,183,187,191,195,198,201,204,

9,23,37,50,63,76,87,99,109,119,129,137,146,153,160,166,172,178,183,187,192,195,199,202,205,208,

10,25,39,53,67,80,92,104,114,125,134,143,151,159,165,172,177,183,188,192,196,200,203,207,209,212,

10,26,41,56,70,84,97,109,120,130,140,149,157,164,171,177,183,188,193,197,201,204,208,211,213,216,

11,28,44,60,75,89,102,114,126,137,146,155,163,170,177,183,188,193,198,202,206,209,212,215,217,220,

12,30,47,63,79,94,108,121,132,143,153,162,170,177,183,189,194,199,203,207,210,214,216,219,221,224,

13,32,50,68,85,100,114,128,140,150,160,169,176,183,189,195,200,204,208,212,215,218,221,223,225,227,

14,34,54,73,91,107,122,135,147,158,167,176,183,190,196,201,206,210,214,217,220,222,225,227,229,231,

15,37,59,79,97,114,130,143,156,166,175,184,191,197,203,207,212,215,219,222,224,227,229,231,233,234,

16,41,64,86,105,123,139,153,165,175,184,192,198,204,209,214,218,221,224,227,229,231,233,235,236,237,

18,45,70,94,114,133,149,162,174,184,193,200,206,211,216,220,223,226,229,231,233,235,237,238,239,241,

20,50,78,103,125,144,160,173,185,194,202,208,214,219,223,226,229,232,234,236,237,239,240,241,243,243,

23,57,87,114,137,157,172,185,195,204,211,217,222,226,229,232,234,236,238,240,241,242,244,245,245,246,

27,65,99,128,152,171,186,197,207,214,220,225,229,232,235,237,239,241,242,244,245,246,247,247,248,249,

32,76,114,145,169,186,200,210,218,224,229,233,236,238,241,242,244,245,246,247,248,249,249,250,250,251,

39,92,134,165,188,203,215,223,229,234,237,240,242,244,246,247,248,249,249,250,251,251,251,252,252,252,

50,114,160,189,208,221,229,235,239,242,244,246,248,249,250,250,251,252,252,252,253,253,253,253,254,254,

70,149,193,216,229,237,242,245,247,249,250,251,252,252,253,253,254,254,254,254,254,255,255,255,255,255,

114,200,229,241,246,249,251,252,253,254,254,254,255,255,255,255,255,255,255,255,255,256,256,256,256,256,

229,251,254,255,255,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,

181,238,248,252,253,254,255,255,255,255,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,

95,181,217,233,241,246,248,250,251,252,253,253,254,254,254,255,255,255,255,255,255,255,255,255,255,255,

62,136,181,207,222,232,238,242,245,247,248,250,251,251,252,252,253,253,253,254,254,254,254,254,255,255,

46,106,151,181,201,215,224,231,236,239,242,244,246,247,248,249,250,251,251,252,252,252,253,253,253,253,

36,86,127,158,181,198,210,219,225,231,235,238,240,242,244,245,247,248,248,249,250,250,251,251,252,252,

30,72,109,139,163,181,195,206,214,221,226,230,234,236,239,241,242,244,245,246,247,248,248,249,250,250,

25,62,95,123,147,166,181,193,203,211,217,222,227,230,233,236,238,240,241,242,244,245,246,246,247,248,

22,54,84,110,133,152,168,181,192,201,208,214,219,223,227,230,233,235,237,239,240,241,243,244,244,245,

20,48,75,100,121,140,156,170,181,191,199,206,211,216,220,224,227,230,232,234,236,238,239,240,242,243,

18,43,68,91,111,129,145,159,171,181,190,197,204,209,214,218,221,225,227,230,232,234,235,237,238,240,

16,40,62,83,103,120,136,149,161,172,181,189,196,202,207,212,216,219,222,225,227,230,232,233,235,236,

15,36,57,77,95,112,127,141,153,163,173,181,188,195,200,205,210,214,217,220,223,225,228,230,231,233,

13,33,53,71,89,105,119,133,145,155,165,173,181,188,194,199,204,208,212,215,218,221,223,226,228,230,

12,31,49,66,83,98,112,125,137,148,158,166,174,181,187,193,198,202,207,210,214,217,219,222,224,226,

12,29,46,62,78,92,106,119,130,141,151,159,167,175,181,187,192,197,201,205,209,212,215,218,220,222,

11,27,43,58,73,87,100,113,124,134,144,153,161,168,175,181,187,192,196,200,204,207,211,213,216,219,

10,25,40,55,69,82,95,107,118,128,138,147,155,162,169,175,181,186,191,195,199,203,206,209,212,215,

10,24,38,52,65,78,90,102,113,123,132,141,149,157,164,170,176,181,186,190,195,198,202,205,208,211,

9,23,36,49,62,74,86,97,108,118,127,136,144,151,158,165,171,176,181,186,190,194,198,201,204,207,

9,22,34,47,59,71,82,93,103,113,122,131,139,146,153,160,166,171,176,181,185,190,193,197,200,203,

8,21,33,45,56,68,79,89,99,108,117,126,134,141,148,155,161,166,172,176,181,185,189,193,196,199

};

 

//define some character bitmaps

//5x7 characters

flash int cities[3][8]={

       // City

       0b0000111011110000,

       0b0000101011010000,

       0b0000111010110000,

       0b0001101011011100,

       0b0001111110110100,

       0b0001101011011100,

       0b1101111110110100,

       0b1111111111111111,     

       // Hit City

       0b0000000000000000,

       0b0000000000000000,

       0b0001000000000000,

       0b0001100000100000,

       0b0001100001100000,

       0b0011111011110000,

       0b0110111110111000,

       0b1111011111011111,

       // Wrecked City

       0b0000000000000000,

       0b0000000000000000,

       0b0000000000000000,

       0b0000000000000000,

       0b0000000000000000,

       0b0000100001000000,

       0b0011110011100110,

       0b1111111111111111};

 

flash char explosion[2][5]={

       // Explosion Frame1

       0b00000,

       0b00100,

       0b01110,

       0b00100,

       0b00000,

 

       // Explosion Frame2

       0b01110,

       0b11111,

       0b11111,

       0b11111,

       0b01110};

 

 

//Point plot lookup table  

//One bit masks

flash char pos[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};              

 

//define some character bitmaps

//5x7 characters

flash char bitmap[38][7]={

       //0

       0b01110000,

       0b10001000,

       0b10011000,

       0b10101000,

       0b11001000,

       0b10001000,

       0b01110000,

       //1

       0b00100000,

       0b01100000,

       0b00100000,

       0b00100000,

       0b00100000,

       0b00100000,

       0b01110000, 

       //2

       0b01110000,

       0b10001000,

       0b00001000,

       0b00010000,

       0b00100000,

       0b01000000,

       0b11111000,

       //3

       0b11111000,

       0b00010000,

       0b00100000,

       0b00010000,

       0b00001000,

       0b10001000,

       0b01110000,

       //4

       0b00010000,

       0b00110000,

       0b01010000,

       0b10010000,

       0b11111000,

       0b00010000,

       0b00010000,

       //5

       0b11111000,

       0b10000000,

       0b11110000,

       0b00001000,

       0b00001000,

       0b10001000,

       0b01110000,

       //6

       0b01000000,

       0b10000000,

       0b10000000,

       0b11110000,

       0b10001000,

       0b10001000,

       0b01110000,

       //7

       0b11111000,

       0b00001000,

       0b00010000,

       0b00100000,

       0b01000000,

       0b10000000,

       0b10000000,

       //8

       0b01110000,

       0b10001000,

       0b10001000,

       0b01110000,

       0b10001000,

       0b10001000,

       0b01110000,

       //9

       0b01110000,

       0b10001000,

       0b10001000,

       0b01111000,

       0b00001000,

       0b00001000,

       0b00010000, 

       //A

       0b01110000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b11111000,

       0b10001000,

       0b10001000,

       //B

       0b11110000,

       0b10001000,

       0b10001000,

       0b11110000,

       0b10001000,

       0b10001000,

       0b11110000,

       //C

       0b01110000,

       0b10001000,

       0b10000000,

       0b10000000,

       0b10000000,

       0b10001000,

       0b01110000,

       //D

       0b11110000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b11110000,

       //E

       0b11111000,

       0b10000000,

       0b10000000,

       0b11111000,

       0b10000000,

       0b10000000,

       0b11111000,

       //F

       0b11111000,

       0b10000000,

       0b10000000,

       0b11111000,

       0b10000000,

       0b10000000,

       0b10000000,

       //G

       0b01110000,

       0b10001000,

       0b10000000,

       0b10011000,

       0b10001000,

       0b10001000,

       0b01110000,

       //H

       0b10001000,

       0b10001000,

       0b10001000,

       0b11111000,

       0b10001000,

       0b10001000,

       0b10001000,

       //I

       0b01110000,

       0b00100000,

       0b00100000,

       0b00100000,

       0b00100000,

       0b00100000,

       0b01110000,

       //J

       0b00111000,

       0b00010000,

       0b00010000,

       0b00010000,

       0b00010000,

       0b10010000,

       0b01100000,

       //K

       0b10001000,

       0b10010000,

       0b10100000,

       0b11000000,

       0b10100000,

       0b10010000,

       0b10001000,

       //L

       0b10000000,

       0b10000000,

       0b10000000,

       0b10000000,

       0b10000000,

       0b10000000,

       0b11111000,

       //M

       0b10001000,

       0b11011000,

       0b10101000,

       0b10101000,

       0b10001000,

       0b10001000,

       0b10001000,

       //N

       0b10001000,

       0b10001000,

       0b11001000,

       0b10101000,

       0b10011000,

       0b10001000,

       0b10001000,

       //O

       0b01110000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b01110000,

       //P

       0b11110000,

       0b10001000,

       0b10001000,

       0b11110000,

       0b10000000,

       0b10000000,

       0b10000000,

       //Q

       0b01110000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b10101000,

       0b10010000,

       0b01101000,

       //R

       0b11110000,

       0b10001000,

       0b10001000,

       0b11110000,

       0b10100000,

       0b10010000,

       0b10001000,

       //S

       0b01111000,

       0b10000000,

       0b10000000,

       0b01110000,

       0b00001000,

       0b00001000,

       0b11110000,

       //T

       0b11111000,

       0b00100000,

       0b00100000,

       0b00100000,

       0b00100000,

       0b00100000,

       0b00100000,

       //U

       0b10001000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b01110000,

       //V

       0b10001000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b01010000,

       0b00100000,

       //W

       0b10001000,

       0b10001000,

       0b10001000,

       0b10101000,

       0b10101000,

       0b10101000,

       0b01010000,

       //X

       0b10001000,

       0b10001000,

       0b01010000,

       0b00100000,

       0b01010000,

       0b10001000,

       0b10001000,

       //Y

       0b10001000,

       0b10001000,

       0b10001000,

       0b01010000,

       0b00100000,

       0b00100000,

       0b00100000,

       //Z

       0b11111000,

       0b00001000,

       0b00010000,

       0b00100000,

       0b01000000,

       0b10000000,

       0b11111000,

       //figure1

       0b01110000,

       0b00100000,

       0b01110000,

       0b10101000,

       0b00100000,

       0b01010000,

       0b10001000,

       //figure2

       0b01110000,

       0b10101000,

       0b01110000,

       0b00100000,

       0b00100000,

       0b01010000,

       0b10001000};

 

 

//================================

//3x5 font numbers, then letters

//packed two per definition for fast

//copy to the screen at x-position divisible by 4

flash char smallbitmap[39][5]={

       //0

       0b11101110,

       0b10101010,

       0b10101010,

       0b10101010,

       0b11101110,

       //1

       0b01000100,

       0b11001100,

       0b01000100,

       0b01000100,

       0b11101110,

       //2

       0b11101110,

       0b00100010,

       0b11101110,

       0b10001000,

       0b11101110,

       //3

       0b11101110,

       0b00100010,

       0b11101110,

       0b00100010,

       0b11101110,

       //4

       0b10101010,

       0b10101010,

       0b11101110,

       0b00100010,

       0b00100010,

       //5

       0b11101110,

       0b10001000,

       0b11101110,

       0b00100010,

       0b11101110,

       //6

       0b11001100,

       0b10001000,

       0b11101110,

       0b10101010,

       0b11101110,

       //7

       0b11101110,

       0b00100010,

       0b01000100,

       0b10001000,

       0b10001000,

       //8

       0b11101110,

       0b10101010,

       0b11101110,

       0b10101010,

       0b11101110,

       //9

       0b11101110,

       0b10101010,

       0b11101110,

       0b00100010,

       0b01100110,

       //:

       0b00000000,

       0b01000100,

       0b00000000,

       0b01000100,

       0b00000000,

       //=

       0b00000000,

       0b11101110,

       0b00000000,

       0b11101110,

       0b00000000,

       //blank

       0b00000000,

       0b00000000,

       0b00000000,

       0b00000000,

       0b00000000,

       //A

       0b11101110,

       0b10101010,

       0b11101110,

       0b10101010,

       0b10101010,

       //B

       0b11001100,

       0b10101010,

       0b11101110,

       0b10101010,

       0b11001100,

       //C

       0b11101110,

       0b10001000,

       0b10001000,

       0b10001000,

       0b11101110,

       //D

       0b11001100,

       0b10101010,

       0b10101010,

       0b10101010,

       0b11001100,

       //E

       0b11101110,

       0b10001000,

       0b11101110,

       0b10001000,

       0b11101110,

       //F

       0b11101110,

       0b10001000,

       0b11101110,

       0b10001000,

       0b10001000,

       //G

       0b11101110,

       0b10001000,

       0b10001000,

       0b10101010,

       0b11101110,

       //H

       0b10101010,

       0b10101010,

       0b11101110,

       0b10101010,

       0b10101010,

       //I

       0b11101110,

       0b01000100,

       0b01000100,

       0b01000100,

       0b11101110,

       //J

       0b00100010,

       0b00100010,

       0b00100010,

       0b10101010,

       0b11101110,

       //K

       0b10001000,

       0b10101010,

       0b11001100,

       0b11001100,

       0b10101010,

       //L

       0b10001000,

       0b10001000,

       0b10001000,

       0b10001000,

       0b11101110,

       //M

       0b10101010,

       0b11101110,

       0b11101110,

       0b10101010,

       0b10101010,

       //N

       0b00000000,

       0b11001100,

       0b10101010,

       0b10101010,

       0b10101010,

       //O

       0b01000100,

       0b10101010,

       0b10101010,

       0b10101010,

       0b01000100,

       //P

       0b11101110,

       0b10101010,

       0b11101110,

       0b10001000,

       0b10001000,

       //Q

       0b01000100,

       0b10101010,

       0b10101010,

       0b11101110,

       0b01100110,

       //R

       0b11101110,

       0b10101010,

       0b11001100,

       0b11101110,

       0b10101010,

       //S

       0b11101110,

       0b10001000,

       0b11101110,

       0b00100010,

       0b11101110,

       //T

       0b11101110,

       0b01000100,

       0b01000100,

       0b01000100,

       0b01000100,

       //U

       0b10101010,

       0b10101010,

       0b10101010,

       0b10101010,

       0b11101110,

       //V

       0b10101010,

       0b10101010,

       0b10101010,

       0b10101010,

       0b01000100,

       //W

       0b10101010,

       0b10101010,

       0b11101110,

       0b11101110,

       0b10101010,

       //X

       0b00000000,

       0b10101010,

       0b01000100,

       0b01000100,

       0b10101010,

       //Y

       0b10101010,

       0b10101010,

       0b01000100,

       0b01000100,

       0b01000100,

       //Z

       0b11101110,

       0b00100010,

       0b01000100,

       0b10001000,

       0b11101110

       };    

//==================================

//This is the sync generator and raster generator. It MUST be entered from

//sleep mode to get accurate timing of the sync pulses

#pragma warn-

interrupt [TIM1_COMPA] void t1_cmpA(void) 

begin

  //start the Horizontal sync pulse   

  PORTD = syncON;    

  //update the curent scanline number

  LineCount++;  

  //begin inverted (Vertical) synch after line 247

  if (LineCount==248)

  begin

    syncON = 0b00100000;

    syncOFF = 0;

  end

  //back to regular sync after line 250

  if (LineCount==251)     

  begin

    syncON = 0;

    syncOFF = 0b00100000;

  end 

  //start new frame after line 262

  if (LineCount==263)

  begin

     LineCount = 1;

  end 

 

  delay_us(2); //adjust to make 5 us pulses

  //end sync pulse

  PORTD = syncOFF;  

 

  if (LineCount<ScreenBot && LineCount>=ScreenTop)

    begin

      

       //compute byte index for beginning of the next line

       //left-shift 4 would be individual lines

       // <<3 means line-double the pixels

       //The 0xfff8 truncates the odd line bit

       //i=(LineCount-ScreenTop)<<3 & 0xfff8; //

      

       #asm

       push r16

       lds   r12, _LineCount

       lds   r13, _Linecount+1

       ldi   r16, 30

       sub  r12, r16

       ldi  r16,0

       sbc  r13, r16

       lsl  r12

       rol  r13

       lsl  r12

       rol  r13

       lsl  r12   

       rol  r13

       mov  r16,r12

       andi r16,0xf0

       mov  r12,r16

       pop r16

       #endasm

       

       //load 16 registers with screen info

       #asm

       push r14

       push r15

       push r16

       push r17

       push r18

       push r19

       push r26

       push r27

      

       ldi  r26,low(_screen)   ;base address of screen

       ldi  r27,high(_screen)  

       add  r26,r12            ;offset into screen (add i)

       adc  r27,r13

       ld   r4,x+          ;load 16 registers and inc pointer

       ld   r5,x+

       ld   r6,x+ 

       ld   r7,x+

       ld   r8,x+

       ld   r9,x+

       ld   r10,x+ 

       ld   r11,x+

       ld   r12,x+

       ld   r13,x+

       ld   r14,x+ 

       ld   r15,x+

       ld   r16,x+  

       ld   r17,x+ 

       ld   r18,x+

       ld   r19,x

      

       pop  r27

       pop  r26

       #endasm 

 

       delay_us(4);  //adjust to center image on screen

      

       //blast 16 bytes to the screen  

       #asm

       ;but first a macro to make the code shorter 

       ;the macro takes a register number as a parameter

       ;and dumps its bits serially to portD.6  

       ;the nop can be eliminated to make the display narrower

       .macro videobits ;regnum

        BST  @0,7

       IN   R30,0x12

       BLD  R30,6

       nop

       OUT  0x12,R30 

      

       BST  @0,6

       IN   R30,0x12

       BLD  R30,6

       nop

       OUT  0x12,R30

      

       BST  @0,5

       IN   R30,0x12

       BLD  R30,6

       nop

       OUT  0x12,R30

      

       BST  @0,4

       IN   R30,0x12

       BLD  R30,6

       nop

       OUT  0x12,R30

      

       BST  @0,3

       IN   R30,0x12

       BLD  R30,6

       nop

       OUT  0x12,R30

      

       BST  @0,2

       IN   R30,0x12

       BLD  R30,6

       nop

       OUT  0x12,R30

      

       BST  @0,1

       IN   R30,0x12

       BLD  R30,6

       nop

       OUT  0x12,R30

      

       BST  @0,0

       IN   R30,0x12

       BLD  R30,6

       nop

       OUT  0x12,R30

       .endm    

       

       videobits r4 ;video line -- byte 1

        videobits r5 ;byte 2 

        videobits r6 ;byte 3

        videobits r7 ;byte 4

        videobits r8 ;byte 5

        videobits r9 ;byte 6

        videobits r10 ;byte 7

        videobits r11 ;byte 8

        videobits r12 ;byte 9

        videobits r13 ;byte 10 

        videobits r14 ;byte 11

        videobits r15 ;byte 12

        videobits r16 ;byte 13

        videobits r17 ;byte 14

        videobits r18 ;byte 15

        videobits r19 ;byte 16

       clt   ;clear video after the last pixel on the line

       IN   R30,0x12

       BLD  R30,6

       OUT  0x12,R30

                                                      

       pop r19

       pop r18

       pop r17

       pop r16 

       pop r15

       pop r14

       #endasm

             

    end  

 

 

end 

#pragma warn+

 

//==================================

//plot one point

//at x,y with color 1=white 0=black 2=invert

#pragma warn-

void video_pt(char x, char y, char c)

begin  

      

       #asm

       ;  i=(x>>3) + ((int)y<<4) ;   the byte with the pixel in it

 

       push r16

       ldd r30,y+2          ;get x

       lsr r30

       lsr r30

       lsr r30              ;divide x by 8

       ldd r12,y+1          ;get y

              lsl r12              ;mult y by 16

              clr r13

       lsl r12

       rol r13

       lsl r12

       rol r13

       lsl r12

       rol r13

       add r12, r30         ;add in x/8

      

       ;v2 = screen[i];   r5

        ;v3 = pos[x & 7];  r6

       ;v4 = c            r7

       ldi r30,low(_screen)

       ldi r31,high(_screen)

       add r30, r12

       adc r31, r13

       ld r5,Z              ;get screen byte

       ldd r26,y+2          ;get x

       ldi r27,0

       andi r26,0x07           ;form x & 7

       ldi r30,low(_pos*2) 

       ldi r31,high(_pos*2)

       add r30,r26

       adc r31,r27

       lpm r6,Z

       ld r16,y             ;get c

      

       ;if (v4==1) screen[i] = v2 | v3 ;

       ;if (v4==0) screen[i] = v2 & ~v3;

       ;if (v4==2) screen[i] = v2 ^ v3 ;

      

       cpi r16,1

       brne tst0

       or  r5,r6

       tst0:

       cpi r16,0

       brne tst2

       com r6

       and r5,r6

       tst2:

       cpi r16,2

       brne writescrn

       eor r5,r6

       writescrn:

              ldi r30,low(_screen)

       ldi r31,high(_screen)

       add r30, r12

       adc r31, r13

       st Z, r5             ;write the byte back to the screen

      

       pop r16

       #endasm

      

end

#pragma warn+

 

//==================================

// put a big character on the screen

// c is index into bitmap

void video_putchar(char x, char y, char c) 

begin

    v7 = x;

    for (v6=0;v6<7;v6++)

    begin

        v1 = bitmap[c][v6];

        v8 = y+v6;

        video_pt(v7,   v8, (v1 & 0x80)==0x80); 

        video_pt(v7+1, v8, (v1 & 0x40)==0x40);

        video_pt(v7+2, v8, (v1 & 0x20)==0x20);

        video_pt(v7+3, v8, (v1 & 0x10)==0x10);

        video_pt(v7+4, v8, (v1 & 0x08)==0x08);

    end

end

 

//==================================

// put a string of big characters on the screen

void video_puts(char x, char y, char *str)

begin

       char i ;

       for (i=0; str[i]!=0; i++)

       begin 

              if (str[i]>=0x30 && str[i]<=0x3a)

                     video_putchar(x,y,str[i]-0x30);

              else video_putchar(x,y,str[i]-0x40+9);

              x = x+6;     

       end

end

 

//==================================

// put a string of big characters from flash on the screen

void video_putsf(char x, char y, flash char *str)

begin

       char i ;

       for (i=0; str[i]!=0; i++)

       begin 

              if (str[i]>=0x30 && str[i]<=0x3a)

                     video_putchar(x,y,str[i]-0x30);

              else video_putchar(x,y,str[i]-0x40+9);

              x = x+6;     

       end

end

     

//==================================

// put a small character on the screen

// x-cood must be on divisible by 4

// c is index into bitmap

void video_smallchar(char x, char y, char c) 

begin

       char mask;

       i=((int)x>>3) + ((int)y<<4) ;

       if (x == (x & 0xf8)) mask = 0x0f;     //f8

       else mask = 0xf0;

      

       screen[i] =    (screen[i] & mask) | (smallbitmap[c][0] & ~mask);

       screen[i+16] = (screen[i+16] & mask) | (smallbitmap[c][1] & ~mask);

        screen[i+32] = (screen[i+32] & mask) | (smallbitmap[c][2] & ~mask);

        screen[i+48] = (screen[i+48] & mask) | (smallbitmap[c][3] & ~mask);

       screen[i+64] = (screen[i+64] & mask) | (smallbitmap[c][4] & ~mask);

end   

 

 

//==================================

// put a string of small characters on the screen

// x-cood must be on divisible by 4

void video_putsmalls(char x, char y, char *str)

begin

       char i ;

       for (i=0; str[i]!=0; i++)

       begin 

              if (str[i]>=0x30 && str[i]<=0x3a)

                     video_smallchar(x,y,str[i]-0x30);

              else video_smallchar(x,y,str[i]-0x40+12);

              x = x+4;     

       end

end    

 

//==================================

// put a string of small characters from flash on the screen

// x-cood must be on divisible by 4

void video_putsmallsf(char x, char y, flash char *str)

begin

       char i ;

       for (i=0; str[i]!=0; i++)

       begin 

              if (str[i]>=0x30 && str[i]<=0x3a)

                     video_smallchar(x,y,str[i]-0x30);

              else video_smallchar(x,y,str[i]-0x40+12);

              x = x+4;     

       end

end

 

//==================================

// put a city on the screen

// c is index into bitmap

void video_putcity(char x, char y, char c) 

begin

    v7 = x;

    for (v6=0;v6<8;v6++)

    begin

        vint = cities[c][v6];

        v8 = y+v6;

        video_pt(v7,   v8, (vint & 0x8000)==0x8000);

        video_pt(v7+1, v8, (vint & 0x4000)==0x4000);

        video_pt(v7+2, v8, (vint & 0x2000)==0x2000);

        video_pt(v7+3, v8, (vint & 0x1000)==0x1000);

        video_pt(v7+4, v8, (vint & 0x800)==0x800);

        video_pt(v7+5, v8, (vint & 0x400)==0x400);

        video_pt(v7+6, v8, (vint & 0x200)==0x200); 

        video_pt(v7+7, v8, (vint & 0x100)==0x100);

        video_pt(v7+8, v8, (vint & 0x80)==0x80);

        video_pt(v7+9, v8, (vint & 0x40)==0x40);

        video_pt(v7+10, v8, (vint & 0x20)==0x20);       

        video_pt(v7+11, v8, (vint & 0x10)==0x10); 

        video_pt(v7+12, v8, (vint & 0x08)==0x08);

        video_pt(v7+13, v8, (vint & 0x04)==0x04);

        video_pt(v7+14, v8, (vint & 0x02)==0x02);

        video_pt(v7+15, v8, (vint & 0x01)==0x01);

    end

end

      

//==================================

//plot a line

//at x1,y1 to x2,y2 with color 1=white 0=black 2=invert

//NOTE: this function requires signed chars  

//Code is from David Rodgers,

//"Procedural Elements of Computer Graphics",1985

void video_line(char x1, char y1, char x2, char y2, char c)

begin  

       int e;

       signed char dx,dy,j, temp;

       signed char s1,s2, xchange;

        signed char x,y;

       

       x = x1;

       y = y1;

       dx = cabs(x2-x1);

       dy = cabs(y2-y1);

       s1 = csign(x2-x1);

       s2 = csign(y2-y1);

       xchange = 0;  

       if (dy>dx)

       begin

              temp = dx;

              dx = dy;

              dy = temp;

              xchange = 1;

       end

       e = ((int)dy<<1) - dx;  

       for (j=0; j<=dx; j++)

       begin

              video_pt(x,y,c) ;

              if (e>=0)

              begin

                     if (xchange==1) x = x + s1;

                     else y = y + s2;

                     e = e - ((int)dx<<1);

              end

              if (xchange==1) y = y + s2;

              else x = x + s1;

              e = e + ((int)dy<<1);

       end

end

 

//==================================

//return the value of one point

//at x,y with color 1=white 0=black 2=invert

char video_set(char x, char y)

begin

       //The following construction

       //detects exactly one bit at the x,y location

       i=((int)x>>3) + ((int)y<<4) ; 

    return ( screen[i] & 1<<(7-(x & 0x7)));    

end

 

//==================================

// set up the ports and timers

void initialize(void)

begin

  //init timer 1 to generate sync

  OCR1A = lineTime; //One NTSC line

  TCCR1B = 9;              //full speed; clear-on-match

  TCCR1A = 0x00;     //turn off pwm and oc lines

  TIMSK = 0x10;            //enable interrupt T1 cmp

 

  //init ports

  DDRD = 0xf0;             //video out and switches

  //D.5 is sync:1000 ohm + diode to 75 ohm resistor

  //D.6 is video:330 ohm + diode to 75 ohm resistor

  DDRB = 0x00;

  DDRC = 0x00;

 

  //initialize synch constants

  LineCount = 1;

  syncON = 0b00000000;

  syncOFF = 0b00100000; 

 

  //side lines

  video_line(0,0,0,99,1);

  video_line(width,0,width,99,1);

 

  //top line & bottom lines

  video_line(0,0,width,0,1);

  video_line(0,99,width,99,1);

  video_line(0,11,width,11,1);

  video_line(0,89,width,89,1);

 

  //Print "MISSILE COMMAND"

  video_putsf(15,2,cu1);

  video_putsf(64,2,cu2);

 

  //Print "SCORE" and "HIGH"

  score = 0;

  video_putsmallsf(4,92,scorestr);

  video_putsmallsf(72,92,highstr);

  sprintf(tempstr,"%08d",highscore);     // Convert score to string

  video_putsmalls(92,92,tempstr);

   

  //init software timer

  t=0;

  time=0;

  m_index=0;

  c_index=0;

  i_index=0;

 

  //init variables

  printcount=0;

  gamestate=PRNT_INTRO;

  justfired = 1;

  icount = 0;

 

  //init cursor

  curx = 64;

  cury=50;

  video_pt(curx+1,cury,2);

  video_pt(curx-1,cury,2);

  video_pt(curx,cury+1,2);

  video_pt(curx,cury-1,2);

   

  //enable sleep mode

  MCUCR = 0b10000000;

  #asm ("sei");

 

end

 

 

//------------------------------------------------------------

 

void main(void)

begin

 

  initialize();

  // Begin Game

  //The following loop executes once/video line during lines

  //1-230, then does all of the frame-end processing

 

  while(1)

  begin

 

    //stall here until next line starts

    //sleep enable; mode=idle 

    //use sleep to make entry into sync ISR uniform time 

    

    #asm ("sleep");

   

    //generates a quasi random from 1-20 by counting once per line.

    //must divide the result by 2 (before using), or else we would only get 1,3,5, ect

    //in the linecount == 231 code, because both 10 and 262 are divisable by 2

    fastcount++;

    if (fastcount == 20)

       fastcount = 0;

    //another quasirandom counter

    fastcount2++;

    if (fastcount2 == 249)

       fastcount2 = 0;

   

    //The following code executes during the vertical blanking

    //Code here can be as long as 

    //a total of 60 lines x 63.5 uSec/line x 8 cycles/uSec

   

    if (LineCount==231)

    begin

              //erase old cursor (redrawn AFTER updating the screen 

              if (curx>1 && curx<width-1 && cury<=87 && cury>=13)

              begin

                     video_pt(curx+1,cury,2);

                     video_pt(curx-1,cury,2);

                     video_pt(curx,cury+1,2);

                     video_pt(curx,cury-1,2);

              end

              curx = PINB;         //Get x-coordinate from mouse

              cury = PINC;  //Get y-coordinate from mouse

             

   

        switch (gamestate)

        begin

              case PRNT_INTRO:    

                     // Only Print Part of the Menu in any one Frame

                     switch (printcount)

                     begin

                     case 0:

                       // All Cities are Healthy (Healthy=2, Wounded=1, Dead=0)

                                  deadcities = 0;

                                  icount = 0;

                                  for (temp=0; temp<citycount; temp++)

                                         cstatus[temp] = 2;

                                  //All interceptor are ready (ready = 0, detonating (second stage) = 1-4, detonating (first stage) = 5-6, in flight = 7)

                                  for(temp=0; temp<max_intercept; temp++)

                                         istatus[temp] = 0;

                                  //All Missiles are ready (ready = 0, detonated >= 49, in flight = 50)

                                  for(temp=0; temp<max; temp++)

                                         mstatus[temp] = 0;

                                  score = 0;                

                            sprintf(tempstr,"%08d",score);    // Convert score to string

                                  video_putsmalls(28,92,tempstr);

                                  break;

                           case 1:

                                  //Print "Click Mouse to Begin"

                           video_putsmallsf(36,50,clb);                        

                           gamestate=GET_INTRO;   

                           break;

                           end

                           printcount++;

                     break;

              case GET_INTRO:

                     printcount=0;

                     // Check for button press   

                     if (PIND.2)

                     begin

                            gamestate=PRNT_DIF;    

                            video_line(32,50,76,50,0);

                            video_line(32,51,76,51,0);

                            video_line(32,52,76,52,0);

                            video_line(32,53,76,53,0);

                            video_line(32,54,76,54,0);

                     end

                     break;

              case PRNT_DIF:      

                     // Print Menu

                           if (printcount == 0)

                           begin

                                  video_putsf(30,30,diff);

                               printcount++;

                           end

                           else if (printcount==1)

                           begin

                                  video_pt(30,43,1);

                                  video_putsf(32,40,easy);

                                  printcount++;

                           end

                           else

                           begin

                                  video_pt(30,53,1);

                                  video_pt(30,63,1);

                                  video_putsf(32,50,med);

                                  video_putsf(32,60,hard);

                                  printcount=11;                    // Prepare for clear screen

                                  justfired = 1;

                            gamestate=GET_DIF;

                            end 

                     break;                    

              case GET_DIF:

                      if (!PIND.2)  //look for mouse button release

                            justfired = 0;

                      if (PIND.2 && !justfired)

                                  begin

                                         if (curx>=30 && curx<70)

                                         begin

                                                if (cury>=40 && cury<=49)                level=1;

                                                else

                                                       if (cury>=50 && cury<=59)        level=2;

                                                       else if (cury>=60 && cury<=69)           level=3;

                                        

                          

                                                // difficulty level detemines number of missiles per wave (mpw)

                                                 switch (level)              

                                                begin

                                        case 1: mpw=4; break;

                                       case 2: mpw=6; break;

                                         case 3: mpw=8; break;

                                                end

                                                gamestate=GAME_INIT;

                                                justfired = 1;

                                                justfiredr = 0;

                                         end

                                  end

                                  break;

              case GAME_INIT:                   // Clear Screen

                      if (printcount<=85)

                      begin

                            video_line(1,printcount+1,width-1,printcount+1,0);

                            video_line(1,printcount+2,width-1,printcount+2,0);

                            video_line(1,printcount+3,width-1,printcount+3,0);

                            printcount=printcount+3;

                      end

                      else

                      begin

                            gamestate=RUN_GAME;

                            printcount=0;

                      end

                                  break;

              case RUN_GAME:

                        // VIDEO GENERATION SCHEME

                        // UPDATE/DRAW ONLY ONE CITY, ONE MISSILE, AND ONE INTERCEPTOR IN EACH FRAME

                                          

                    if (!PIND.2) //check for mouse button release                 

                           justfired = 0;

                     if (!PIND.1)

                           justfiredr = 0;

                   

                    // Check for Right-button click (Pause/Exit)

                    if (PIND.1 && !justfiredr)

                    begin

                           justfiredr = 1;

                           gamestate=PAUSE;     // Can be overwritten in frame by GAME_OVER

                    end

                                                   

                        // INTERCEPTOR SCHEME

                        switch (istatus[i_index])

                        begin

                        case 0:

                           // Generate One Interceptor

                               if (PIND.2 && icount<max_intercept && !justfired)

                                                begin

                                                       justfired = 1; // so we will wait for release to fire another                     

                                                       // Interceptor Target Location

                                                       ixf[i_index]= curx;

                                                       iyf[i_index] = cury-2;

                                                      

                                                       // Determine which box mouse coordinates fall into

                                                       // Determine xbox # and ybox #

                                                       ybox[i_index] = (char)(26-((cury-13)/3))-1;

                                                       xbox[i_index] = (char)(curx/3)-1;

                                 

                                                       // Interceptor Launch Location                        

                                                       ix[i_index]=66;

                                                       iy[i_index]=89;

                                 

                                                       // Current Interceptor Position = Interceptor Launch Location

                                                       ixp[i_index]=66;

                                                       iyp[i_index]=89;

                                                       ixp_long[i_index] = 0x4200;

                                                       iyp_long[i_index] = 0x5900;

                                 

                                                       istatus[i_index]=7;  // Interceptor is Alive (Alive=7, Partial Detonation=5-6, Full Det=1-4 Dead=0)

                                                       icount++;            // Interceptors Fired                                              

                                                end

                                                break;                                   

                        case 1:

                           //interceptor done exploding

                            // Draw Interceptor Explosion

                                                v7 = ixp[i_index];

                                                for (v6=0;v6<5;v6++)

                                                    begin

                                                        v8 = iyp[i_index]+v6;

                                                        video_pt(v7+2, v8, 0); 

                                                        video_pt(v7+1, v8, 0);

                                                        video_pt(v7,   v8, 0);

                                                        video_pt(v7-1, v8, 0);

                                                        video_pt(v7-2, v8, 0);

                                                    end      

                            // decrement state

                                                istatus[i_index]--;

                                                //give user an interceptor back

                                                icount--;

                                                break;

                                         case 2:

                                         case 3:

                                         case 4:

                                         case 6:

                                                istatus[i_index]--;

                                                break;                                  

                        case 5:

                        //interceptor exploding

                            // Draw Interceptor Explosion

                                                v7 = ixp[i_index];

                                                for (v6=0;v6<5;v6++)

                                                    begin

                                                        v1 = explosion[1][v6];

                                                        v8 = iyp[i_index]+v6;

                                                        video_pt(v7+2, v8, (v1 & 0x10)==0x10); 

                                                        video_pt(v7+1, v8, (v1 & 0x08)==0x08);

                                                        video_pt(v7,   v8, (v1 & 0x04)==0x04);

                                                        video_pt(v7-1, v8, (v1 & 0x02)==0x02);

                                                        video_pt(v7-2, v8, (v1 & 0x01)==0x01);

                                                    end      

                            // decrement state

                                                istatus[i_index]--;

                                                break;

                        case 7:

                        // For Alive Interceptor

                           video_pt(ixp[i_index],iyp[i_index],0);

                          

                           // Update Interceptor Position

                                                ixp_long[i_index]=ixp_long[i_index]+(ivx[xbox[i_index]][ybox[i_index]]<<1);      

                                                iyp_long[i_index]=iyp_long[i_index]-(ivy[xbox[i_index]][ybox[i_index]]<<1);

                                               

                                                ixp[i_index]=(char)(ixp_long[i_index]>>8);

                                                iyp[i_index]=(char)(iyp_long[i_index]>>8);

                               //iyp[i_index]--;

      

                                                // Draw Current Interceptor Position                             

                                                video_pt(ixp[i_index],iyp[i_index],1);

                                        

                                                // Check Interceptor Target Location

                                                if (iyp[i_index]<=iyf[i_index])

                                                begin

                                                       // Draw Interceptor Explosion

                                                       v7 = ixp[i_index];

                                                for (v6=0;v6<5;v6++)

                                                    begin

                                                        v1 = explosion[0][v6];

                                                        v8 = iyp[i_index]+v6;

                                                        video_pt(v7+2, v8, (v1 & 0x10)==0x10); 

                                                        video_pt(v7+1, v8, (v1 & 0x08)==0x08);

                                                        video_pt(v7,   v8, (v1 & 0x04)==0x04);

                                                        video_pt(v7-1, v8, (v1 & 0x02)==0x02);

                                                        video_pt(v7-2, v8, (v1 & 0x01)==0x01);

                                                    end      

                    

                                                       // decrement state

                                                       istatus[i_index]--;

                                                end

                                                break;

                                         end //end switch (istatus[i_index])

                                        

                                  video_pt(66, 89, 1);       //redraw pixel that sometimes gets cleared by interceptors

                                 

                                  // CITY SCHEME                                          

                    temp=2-cstatus[c_index];

                    video_putcity(cx[c_index],81,temp);                          

                                                                         

                                  // MISSILE SCHEME

                                  switch (mstatus[m_index])

                                  begin

                                  case 0:  //generate a missile

                                         if (m_index<mpw)    

                                         begin 

                                                //Missile Launch angle (angle in degrees = 45 - 10*m_theta[m_index])

                                                m_theta[m_index] = fastcount>>1;  //use quasi random number, but divide by 2 to get number from 0-9

                                               

                                                // Missile Launch Location

                                                // Start x0-coordinate

                                                // random number limited to the values that will have the missile land on screen

                                                mx[m_index]=start_min[m_theta[m_index]]+(fastcount2%(del_start[m_theta[m_index]]));  

                                                // Start y0-coordinate

                                                my[m_index]=13;     

                           

                                                // Current Missile Position = Missile Launch Location

                                                mxp[m_index]=mx[m_index];                             

                                                myp[m_index]=13;

                                                mxp_long[m_index] = ((int)(mx[m_index]))<<8;

                                                myp_long[m_index] = 0xd00;

                                                mstatus[m_index] = 50;                         

                                                mtimer[m_index]=time2gnd[level];

                                         end

                                  break;

                      

                           // For Alive Missile

                    case 50:

                       

                    //erase end of missile tail

                        video_pt(mxp[m_index],myp[m_index],0);

                       

                        // Update Missile Position

                                         mxp_long[m_index]=mxp_long[m_index]+mvx[m_theta[m_index]][level];      

                                         myp_long[m_index]=myp_long[m_index]+mvy[level];

                                         mxp[m_index]=(char)(mxp_long[m_index]>>8);

                                         myp[m_index]=(char)(myp_long[m_index]>>8);

                                         temp2 = 1;

                            

                         

                                   // Check Missile Explosion Conditions

                                         // 1. Check City Impact Condition

                                   if (myp[m_index] > 80 && video_set(mxp[m_index],myp[m_index]))

                                   begin

                                   // Determine Which City Was Hit

                                         temp=0;

                                                for(temp = 0; temp<citycount; temp++)

                                                begin

                                                       if ((mxp[m_index] > cx[temp]) && (mxp[m_index] < cx[temp]+16) && (cstatus[temp]!=0)) //found the hit city

                                                       begin

                                                              cstatus[temp]--;

                                                mstatus[m_index]=1; //set missile status to detonated

                                         if (cstatus[temp]==0) deadcities++;

                                   end

                                         end

                                   end

                            

                                   // 2. Check All Interceptors For Impact

                           for (temp=1;temp<=max_intercept;temp++)

                                         begin

                                                if (istatus[temp] == 7)           // Interceptor is Alive

                                                begin

                                                       if((mxp[m_index] <= ixp[temp]+1) && (myp[m_index] <= iyp[temp]+1) && (mxp[m_index] >= ixp[temp]-1) && (myp[m_index] >= iyp[temp]-1))     

                                           begin

                                                 mstatus[m_index]--;  //set missile status to destroyed

                                                 temp2 = 0;                        //dont redraw the missile

                                                 score = score + 10*level;  // Update Score for Successful Intercept

                                                 istatus[temp] = 6;

                                           end

                                                end

                                                if ((istatus[temp]) < 7 && (istatus[temp] > 4))        // Interceptor Partially Detonated

                                                begin

                                                       if((mxp[m_index] <= ixp[temp]+3) && (myp[m_index] <= iyp[temp]+3) && (mxp[m_index] >= ixp[temp]-3) && (myp[m_index] >= iyp[temp]-3))     

                                           begin

                                                 mstatus[m_index]--;  //set missile status to destroyed

                                                 temp2 = 0;                        //dont redraw the missile

                                                 score = score + 10*level;  // Update Score for Successful Intercept

                                           end

                                        end

                                                if ((istatus[temp]) < 5 && (istatus[temp] > 0))    // Interceptor Fully Detonated

                                                begin

                                                       if((mxp[m_index] <= ixp[temp]+5) && (myp[m_index] <= iyp[temp]+5) && (mxp[m_index] >= ixp[temp]-5) && (myp[m_index] >= iyp[temp]-5))     

                                           begin

                                                 mstatus[m_index]--;  //set missile status to destroyed

                                                 temp2 = 0;                        //dont redraw the missile

                                                 score = score + 10*level;  // Update Score for Successful Intercept

                                           end

                                        end                

                                       end

                                       

                                       // 3. Check All Exploding Missiles For Impact

                                       for (temp=1;temp<=max;temp++)

                                       begin

                                          if ((mstatus[temp] > 42) && (mstatus[temp] < 50) && temp2)  // Other Missile is Exploding and we havent already counted this missile as dead

                                                begin

                                                       if((mxp[m_index] <= mxp[temp]+5) && (myp[m_index] <= myp[temp]+5) && (mxp[m_index] >= mxp[temp]-5) && (myp[m_index] >= myp[temp]-5))     

                                           begin

                                                 mstatus[m_index]--;  //set missile status to destroyed

                                                 temp2 = 0;                        //dont redraw the missile

                                                 score = score + 20*level;  // Update Score for Successful Intercept

                                           end

                                                end

                                         end

                                        

                                         // Draw Current Missile Position

                                   //video_line(mx[index],my[index],mxp[index],mxy[index],1);

                                   video_pt(mxp[m_index],myp[m_index],temp2);

                             break;  //mstatus == 50

                            

                             case 49:

                                   // Draw Missile Explosion

                                         v7 = mxp[m_index];

                                  for (v6=0;v6<5;v6++)

                                         begin

                                             v1 = explosion[1][v6];

                                             v8 = myp[m_index]+v6;

                                             video_pt(v7+2, v8, (v1 & 0x10)==0x10); 

                                             video_pt(v7+1, v8, (v1 & 0x08)==0x08);

                                             video_pt(v7,   v8, (v1 & 0x04)==0x04);

                                             video_pt(v7-1, v8, (v1 & 0x02)==0x02);

                                             video_pt(v7-2, v8, (v1 & 0x01)==0x01);

                                         end   

                        // decrement state

                                         mstatus[m_index]--;

                             break;

                             case 43:

                                   // Erase Missile Explosion

                                         v7 = mxp[m_index];

                                  for (v6=0;v6<5;v6++)

                                         begin

                                             v8 = myp[m_index]+v6;

                                             video_pt(v7+2, v8, 0); 

                                             video_pt(v7+1, v8, 0);

                                             video_pt(v7,   v8, 0);

                                              video_pt(v7-1, v8, 0);

                                             video_pt(v7-2, v8, 0);

                                         end   

                        // decrement state

                                         mstatus[m_index]--;

                                  break;

                                 

                             default:

                                   mstatus[m_index]--;

                             end //       switch (mstatus[m_index])

                            

                             //Print score

                             sprintf(tempstr,"%08d",score);   // Convert score to string

                                  video_putsmalls(28,92,tempstr);

      

                     // CHECK GAMEOVER

                         if (deadcities==citycount) gamestate=PRNT_GAMEOVER;

                         else //decrement couters for missiles, etc

                         begin

                            if (mtimer[m_index]==0)    //check if missile has reached ground

                                   mstatus[m_index]=0;

                                  mtimer[m_index]--;

                                  if (c_index == citycount-1)

                                      c_index = 0;

                                  else

                                         c_index++;

                                 

                                  if (m_index == max-1)

                                      m_index = 0;

                                  else

                                         m_index++;

                                 

                                  if (i_index == max_intercept-1)

                                         i_index = 0;

                                  else

                                         i_index++;

                     end   

                           

                     break;  // END CASE 'RUN_GAME'

              case PRNT_GAMEOVER:

                     video_putsf(48,15,lose);

                     // Check High Score Condition

                           if (score>highscore)

                                  highscore=score;

                           sprintf(tempstr,"%08d",highscore); // Convert score to string

                           video_putsmalls(92,92,tempstr);

                     gamestate = GET_GAMEOVER;

                     justfired = 0;

                     printcount = 88;

                     break;

              case GET_GAMEOVER:

                           if (printcount>=25)

                           begin

                                  printcount--;                           

                           if (printcount>=80)

                                  video_line(130-printcount,printcount,70+(printcount-80),printcount,1);

                           else if(printcount>=55)

                                  video_line(50,printcount,70,printcount,1);

                            else if(printcount>=50)

                               video_line(50-4*(55-printcount),printcount,70+4*(55-printcount),printcount,1);

                           else if(printcount>=30)

                                  video_line(30,printcount,90,printcount,1);

                            else

                                  video_line(50-4*(printcount-25),printcount,70+4*(printcount-25),printcount,1);

                     end

                            else

                     begin

                         // Check Left Button Press

                                  if (PIND.2)

                                  begin

                                      printcount = 11;

                                         gamestate=RESTART;         // Restart Game

                                  end

                           end

                     break;

              case RESTART: //print count must equal 11 on entry

                     if (printcount<=85)

                           begin

                            video_line(1,printcount+1,width-1,printcount+1,0);

                            video_line(1,printcount+2,width-1,printcount+2,0);

                            video_line(1,printcount+3,width-1,printcount+3,0);

                            printcount=printcount+3;

                      end

                      else

                      begin

                            video_line(1,87,width-1,87,0);

                            video_line(1,88,width-1,88,0);

                            gamestate=PRNT_INTRO;

                            printcount=0;

                      end

                           break;

                     case PAUSE:

                           if (!PIND.1) //look for release of rt btn

                                  justfiredr = 0;

                           if (PIND.1 && !justfiredr)

                           begin

                                  justfiredr = 1;

                                  gamestate=RUN_GAME;

                                  // Clear E

                                  video_line(3,13,8,13,0);

                                  video_line(3,14,8,14,0);

                                  video_line(3,15,8,15,0);

                                  video_line(3,16,8,16,0);

                                  video_line(3,17,8,17,0);

                                  video_line(3,18,8,18,0);

                           video_line(3,19,8,19,0);

                                  // Clear P

                                  video_line(120,2,125,2,0);

                                  video_line(120,3,125,3,0);

                                  video_line(120,4,125,4,0);

                                  video_line(120,5,125,5,0);

                                  video_line(120,6,125,6,0);

                                  video_line(120,7,125,7,0);

                                  video_line(120,8,125,8,0);

                                 

                           end

                           else if (PIND.2==1 && curx<=7 && cury<=19)     

                           begin

                                  // Check High Score Condition

                                  if (score>highscore)

                                         highscore=score;

                                  gamestate=RESTART;  //clear screen and restart

                                  // Clear P

                                  video_line(120,2,125,2,0);

                                  video_line(120,3,125,3,0);

                                  video_line(120,4,125,4,0);

                                  video_line(120,5,125,5,0);

                                  video_line(120,6,125,6,0);

                                  video_line(120,7,125,7,0);

                                  video_line(120,8,125,8,0);

                                  printcount = 11;

                           end

                           else

                           begin

                                  video_putsf(3,13,pmenu);   // 'E' for return to Menu option

                                  video_putsf(120,2,paused);  // 'P' to indicate game is paused

                           end

                           break;

              end      // END SWITCH

     

      //draw new cursor

              if (curx>1 && curx<width-1 && cury<=87 && cury>=13)

              begin

                     video_pt(curx+1,cury,2);

                     video_pt(curx-1,cury,2);

                     video_pt(curx,cury+1,2);

                     video_pt(curx,cury-1,2);

          end

                    

    end  //line 231

  end  //while

end  //main