//Duck Hunt //video gen //D.5 is sync:1000 ohm + diode to 75 ohm resistor //D.6 is video:330 ohm + diode to 75 ohm resistor #pragma regalloc- //I allocate the registers myself #pragma optsize- //optimize for speed #include #include #include #include #include //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 //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+ //Macro for fixed point multiplication #define mfix(a,b) ((int)((((long)(a))*((long)(b)))>>8)) //SCREEN DRAWING int LineCount; char syncON, syncOFF; char screen[1600], ts[10]; //DUCKS int x1, y1, vx1, vy1; int x2, y2, vx2, vy2; char flapcount,flap,spin; unsigned char tempx1,tempy1,tempx2,tempy2; char alive1, direction1, deathcount1, deathstate1; char alive2, direction2, deathcount2, deathstate2; //random motion int r, s; char random1, random2; unsigned int count1, count2; //GAME eeprom int highScore = 0; int vx, vy, s1, s2, Smax, score; unsigned int count, roundtime, count123; char gamestate, numducks ,ducksShot, mycount, currentduck, h; char round, mode, bulletcount, maybe, hit, trigger, level, players; //Flash Strings, @ is a space in small character map char advanceS[]="PTS@TO@ADVANCE"; char bulletsS[]="BULLETS000"; char clear4S[]="@@@@@@@@"; char clear7S[]="@@@@@@@@@@@@@@"; char clear9S[]="@@@@@@@@@@@@@@@@@@"; char duckS[]="@SELECT@DUCKS@"; char flyAwayS[]="FLY@AWAY"; char goodJobS[]="GOOD@JOB"; char highScoreS[]="HIGH@SCORE"; char levelS[]="LEVEL"; char playersS[]="SELECT@PLAYERS"; char roundS[]="ROUND"; char scoreS[]="SCORE000"; char startS[]="SHOOT@TO@START"; char yourScoreS[]="YOUR@SCORE"; //Scoring Array flash int reqScore[11]={0,6,18,36,60,90,126,168,216,270,330}; flash int maxScore[11]={0,10,30,60,100,150,210,280,360,450,550}; //Point plot lookup table //One bit masks flash char pos[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; //Character map for different lander angles flash char symbolbitmap[56][8]={ //0, duck head left flap 0b00000000, 0b00000001, 0b01110011, 0b11111111, 0b00001111, 0b00000011, 0b00000000, 0b00000000, //1, duck tail left flap 0b00000000, 0b11110000, 0b11111000, 0b11111111, 0b11111000, 0b11110000, 0b11110000, 0b00110000, //2, duck head left flap off 0b00000000, 0b00000001, 0b01110011, 0b11111111, 0b00001111, 0b00000000, 0b00000000, 0b00000000, //3, duck tail left flap off 0b00000000, 0b11110000, 0b11111000, 0b11111111, 0b11111000, 0b00000000, 0b00000000, 0b00000000, //4, duck tail right flap 0b00000000, 0b00001111, 0b00011111, 0b11111111, 0b00011111, 0b00001111, 0b00001111, 0b00001100, //5, duck head right flap 0b00000000, 0b10000000, 0b11001110, 0b11111111, 0b11110000, 0b11000000, 0b00000000, 0b00000000, //6, duck tail right flap off 0b00000000, 0b00001111, 0b00011111, 0b11111111, 0b00011111, 0b00000000, 0b00000000, 0b00000000, //7, duck head right flap off 0b00000000, 0b10000000, 0b11001110, 0b11111111, 0b11110000, 0b00000000, 0b00000000, 0b00000000, //8, D 0b11111000, 0b11111100, 0b11001110, 0b11000110, 0b11000110, 0b11001110, 0b11111100, 0b11111000, //9, U 0b11000110, 0b11000110, 0b11000110, 0b11000110, 0b11000110, 0b11000110, 0b11111110, 0b01111100, //10, C 0b00111100, 0b01111110, 0b11100110, 0b11000000, 0b11000000, 0b11100110, 0b01111110, 0b00111100, //11, K 0b11001110, 0b11011100, 0b11111000, 0b11110000, 0b11110000, 0b11111000, 0b11011100, 0b11001110, //12, H 0b11000110, 0b11000110, 0b11000110, 0b11111110, 0b11111110, 0b11000110, 0b11000110, 0b11000110, //13, N 0b11000110, 0b11100110, 0b11110110, 0b11110110, 0b11011110, 0b11011110, 0b11001110, 0b11000110, //14, T 0b11111100, 0b11111100, 0b00110000, 0b00110000, 0b00110000, 0b00110000, 0b00110000, 0b00110000, //15, Dog Top Left 0b00110110, 0b01111001, 0b11110000, 0b11110110, 0b11010010, 0b00010000, 0b00100001, 0b00100100, //16, Dog Bottom Left 0b00010011, 0b00101000, 0b01000110, 0b10010001, 0b10101000, 0b10101000, 0b01001000, 0b00001000, //17, Dog Top Right 0b01101100, 0b10011110, 0b00001111, 0b01101111, 0b01001011, 0b00001000, 0b10000100, 0b00100100, //18, Dog Bottom Right 0b11001000, 0b00010100, 0b01100010, 0b10001001, 0b00010101, 0b00010101, 0b00010010, 0b00010000, //19, blank 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, //20, grass 0b01100110, 0b00111100, 0b00011000, 0b11011011, 0b01111110, 0b00011000, 0b00011000, 0b00011000, //21, bottom half of the tree 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00011000, 0b00011000, //22, top half of the tree 0b01011010, 0b10111101, 0b01011010, 0b10111101, 0b01011010, 0b10111101, 0b01011010, 0b10111101, //23, W-left 0b11000000, 0b11000000, 0b01100001, 0b01100011, 0b00110111, 0b00110110, 0b00011110, 0b00011100, //24, W-right 0b00000110, 0b00000110, 0b00001100, 0b10001100, 0b11011000, 0b11011000, 0b11110000, 0b01110000, //25, I 0b11111100, 0b11111100, 0b00110000, 0b00110000, 0b00110000, 0b00110000, 0b11111100, 0b11111100, //26, E 0b11111110, 0b11111110, 0b11000000, 0b11111000, 0b11111000, 0b11000000, 0b11111110, 0b11111110, //27, R 0b11111100, 0b11111110, 0b11001110, 0b11001110, 0b11111100, 0b11111000, 0b11011100, 0b11001110, //28, L 0b11000000, 0b11000000, 0b11000000, 0b11000000, 0b11000000, 0b11000000, 0b11111110, 0b11111110, //29, O 0b00111000, 0b01111100, 0b11101110, 0b11000110, 0b11000110, 0b11101110, 0b01111100, 0b00111000, //30, S 0b01111100, 0b11111110, 0b11000000, 0b11111100, 0b01111110, 0b00000110, 0b11111110, 0b01111100, //31, top of the duck getting shot 0b00000000, 0b00000100, 0b00110110, 0b01111111, 0b00011011, 0b00111111, 0b00001111, 0b00000011, //32, bottom left of the duck getting shot 0b00000001, 0b00001111, 0b01111111, 0b11110011, 0b00000001, 0b00000001, 0b00000011, 0b00000011, //33, bottom right of the duck getting shot 0b11011100, 0b11111110, 0b11100111, 0b11110000, 0b11110000, 0b11110000, 0b00010000, 0b00011000, //34, top of falling duck (foot) 0b00110011, 0b00110110, 0b00101110, 0b00111000, 0b11111100, 0b11111110, 0b01111110, 0b00111110, //35, bottom of falling duck (head) 0b00111110, 0b00011100, 0b00001000, 0b00011100, 0b00011100, 0b00111110, 0b00111100, 0b00011110, //36, up left, killed ducks 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00011100, 0b00111110, //37, bottom left, killed ducks 0b00000111, 0b00000111, 0b00000110, 0b00001111, 0b00001111, 0b00011111, 0b00011111, 0b00011111, //38, mid bottom left, killed ducks 0b10010011, 0b01101000, 0b10000110, 0b01110001, 0b00001000, 0b10001000, 0b10001000, 0b10001000, //39, mid bottom right, killed ducks 2 0b11001001, 0b00010110, 0b01100001, 0b10001110, 0b00010000, 0b00010001, 0b00010001, 0b00010001, //40, up right, killed ducks 2 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00111000, 0b01111100, //41, bottom right, killed ducks 2 0b11100000, 0b11100000, 0b01100000, 0b11110000, 0b11110000, 0b11111000, 0b11111000, 0b11111000, //symbol 42 beginning of gun 0b00000000, 0b00000000, 0b00111000, 0b11111111, 0b11111111, 0b00111111, 0b00000000, 0b00000000, //symbol 43 0b00000000, 0b00000000, 0b00000011, 0b11111111, 0b11111111, 0b11111111, 0b01001011, 0b01011011, //symbol 44 0b00000000, 0b00110000, 0b11100000, 0b11111100, 0b11111111, 0b11111110, 0b11111000, 0b11111000, //symbol 45 all black 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, //symbol 46 0b01000011, 0b01111111, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, //symbol 47 0b11111000, 0b11111100, 0b11111110, 0b01111110, 0b01111111, 0b00111111, 0b00111111, 0b00011111, //symbol 48 beginning of controller 0b00000000, 0b00000000, 0b00000000, 0b00001110, 0b00011111, 0b00111011, 0b00110001, 0b01111011, //symbol 49 0b00000111, 0b00001100, 0b00001000, 0b00001000, 0b11111111, 0b11111111, 0b11111111, 0b11111111, //symbol 50 0b10000000, 0b10000000, 0b00000000, 0b11110000, 0b11111000, 0b11011100, 0b10111100, 0b01110110, //symbol 51 0b01111111, 0b11111111, 0b11111111, 0b11111110, 0b11111100, 0b11111100, 0b11110000, 0b01100000, //symbol 52 0b11011011, 0b11111111, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, //symbol 53 end of controller 0b11101110, 0b11011111, 0b01111111, 0b00111111, 0b00011111, 0b00001111, 0b00001111, 0b00000110, //symbol 54 top of inverse falling duck 0b11001100, 0b01101100, 0b01110100, 0b00011100, 0b00111111, 0b01111111, 0b01111110, 0b01111100, //symbol 55 bottom of inverse falling duck 0b01111100, 0b00111000, 0b00010000, 0b00111000, 0b00111000, 0b01111100, 0b00111100, 0b01111000 }; //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 0b01110000, 0b10001000, 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[40][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 #18 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 24 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 30 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, //bullet 0b01000100, 0b11101110, 0b11101110, 0b11101110, 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) { //start the Horizontal sync pulse PORTD = syncON; //update the curent scanline number LineCount ++ ; //{ inverted (Vertical) synch after line 247 if (LineCount==248) { syncON = 0b00100000; syncOFF = 0; } //back to regular sync after line 250 if (LineCount==251) { syncON = 0; syncOFF = 0b00100000; } //start new frame after line 262 if (LineCount==263) { LineCount = 1; } delay_us(2); //adjust to make 5 us pulses //} sync pulse PORTD = syncOFF; if (LineCount=ScreenTop) { //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 } } #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) { #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 } #pragma warn+ //================================== // put a big character on the screen // c is index into bitmap void video_putchar(char x, char y, char c) { v7 = x; for (v6=0;v6<7;v6++) { 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); } } //================================== // put 8x8 symbols on the screen, c is index into bitmap void video_putsymbol(char x, char y, char c) { v7 = x; for (v6=0;v6<8;v6++) { v1 = symbolbitmap[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); video_pt(v7+5, v8, (v1 & 0x04)==0x04); video_pt(v7+6, v8, (v1 & 0x02)==0x02); video_pt(v7+7, v8, (v1 & 0x01)==0x01); } } //================================== // put a string of big characters on the screen void video_puts(char x, char y, char *str) { char i ; for (i=0; str[i]!=0; i++) { 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; } } //================================== // 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) { 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); } //================================== // 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) { char i ; for (i=0; str[i]!=0; i++) { 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; } } //================================== //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) { 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) { temp = dx; dx = dy; dy = temp; xchange = 1; } e = ((int)dy<<1) - dx; for (j=0; j<=dx; j++) { video_pt(x,y,c) ; if (e>=0) { if (xchange==1) x = x + s1; else y = y + s2; e = e - ((int)dx<<1); } if (xchange==1) y = y + s2; else x = x + s1; e = e + ((int)dy<<1); } } //================================== //return the value of one point //at x,y with color 1=white 0=black 2=invert char video_set(char x, char y) { //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))); } //================================== // set up the ports and timers void main(void) { //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 interupts //D.5 is sync:1000 ohm + diode to 75 ohm resistor //D.6 is video:330 ohm + diode to 75 ohm resistor DDRA = 0x00; //controller input DDRC = 0xFF; //sound output DDRB = 0xFF; //gunshot/falling duck toggle output PORTB=0x0000; PORTC=0x0000; //initialize synch constants LineCount = 1; syncON = 0b00000000; syncOFF = 0b00100000; //side lines #define width 126 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,90,width,90,1); //Bullet Count video_putsmalls(40,92,bulletsS); video_smallchar(68,92,39); video_smallchar(72,92,39); video_smallchar(76,92,39); bulletcount=12; //Score video_putsmalls(88,92,scoreS); score=0; sprintf(ts,"%03d",score); video_putsmalls(108,92,ts); //Round video_smallchar(4,92,30); round=0; sprintf(ts,"%02d",round); video_putsmalls(8,92,ts); //Level video_smallchar(20,92,24); level=0; sprintf(ts,"%02d",level); video_putsmalls(24,92,ts); //Game roundtime=30000; gamestate=0;//0 for playing, 1 for after round, 5 for before round, 2 for ducks fly off, 3 for game over maybe=0; //Background video_putsymbol(4,82,20); video_putsymbol(12,82,20); video_putsymbol(20,82,21); video_putsymbol(20,74,22); video_putsymbol(28,82,20); video_putsymbol(36,82,20); video_putsymbol(44,82,20); video_putsymbol(52,82,20); video_putsymbol(60,82,20); video_putsymbol(68,82,20); video_putsymbol(76,82,20); video_putsymbol(84,82,20); video_putsymbol(92,82,20); video_putsymbol(100,82,20); video_putsymbol(108,82,20); video_putsymbol(116,82,20); //random motion TCCR0 = 0b00000001; r = 0x0100; s = (float)r*.707106781; //init ducks x1 = 0x2000; y1 = 0x2800; vx1= 0x0000; vy1= 0x0000; x2 = 0x4F00; y2 = 0x2800; vx2= 0x0000; vy2= 0x0000; count=0; flap=0; direction1=4; direction2=0; alive1=1; alive2=1; random1=0; random2=0; deathcount1=0; deathcount2=0; deathstate1=0; deathstate2=0; spin=0; //Controller s1=0x0100; s2=0x0100; Smax = 0x0200; //max speed mycount=0; currentduck = -1; //currentduck can be either 0 or -1, 0 being the first duck and -1 being the second duck //Start Up Screen //Menu Music PORTC=0b00000010; //DUCK HUNT video_putsymbol(28,24,8); video_putsymbol(36,24,9); video_putsymbol(44,24,10); video_putsymbol(52,24,11); video_putsymbol(68,24,12); video_putsymbol(76,24,9); video_putsymbol(84,24,13); video_putsymbol(92,24,14); //Dog video_putsymbol(56,40,15); video_putsymbol(56,48,16); video_putsymbol(64,40,17); video_putsymbol(64,48,18); //Label Ducks 1 & 2 for mode/player selection video_smallchar(28,44,1); video_smallchar(96,44,2); //SHOOT TO START video_putsmalls(36,72,startS); //HIGH SCORE video_putsmalls(36,64,highScoreS); sprintf(ts,"%03d",highScore); video_putsmalls(80,64,ts); //Enable Sleep Mode MCUCR = 0b10000000; //Configure external interupts edge triggered but no interupt thrown, just flags MCUCR=MCUCR|0b00001110; MCUCR=MCUCR&0b11111110; //Enable Interupts #asm ("sei"); //The following loop executes once/video line during lines //1-230, then does all of the frame-} processing while(1) { //stall here until next line starts //sleep enable; mode=idle //use sleep to make entry into sync ISR uniform time #asm ("sleep"); //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) { //Counters count++; flapcount++; if(deathcount1!=0)deathcount1--; if(deathcount2!=0)deathcount2--; //Controller if (gamestate==0 && level>0 && players==2) { if(deathstate1!=0||alive1==0)currentduck=-1; if(deathstate2!=0||alive2==0)currentduck=0; if (mycount == 16) //we check every 16 cycles { mycount=0; if (currentduck == 0) { if (PINA.6 ==0 && PINA.0 ==1 && s10) //button C for slow down { s1=s1-0x0080; } } else if (currentduck == -1) { if (PINA.6 ==0 && PINA.0 ==1 && s20) //button C for slow down { s2=s2-0x0080; } } //Duck1 if (currentduck == 0) { if (PINA.1 == 0 && PINA.3 == 0) //up and left { vy1=-s1; vx1=-s1; } else if (PINA.2 == 0 && PINA.3 == 0) //down and left { vy1=s1; vx1=-s1; } else if (PINA.1 == 0 && PINA.4 == 0) //up and right { vy1=-s1; vx1=s1; } else if (PINA.2 == 0 && PINA.4 ==0) //down and right { vx1=s1; vy1=s1; } else if (PINA.1 == 0) //up { vy1=-s1; vx1=0; } else if (PINA.2 == 0) //down { vy1=s1; vx1=0; } else if (PINA.3 == 0) //left { vx1=-s1; vy1=0; } else if (PINA.4 ==0) //right { vx1=s1; vy1=0; } } //Duck2 else if (currentduck ==-1) { if (PINA.1 == 0 && PINA.3 == 0) //up and left { vy2=-s2; vx2=-s2; } else if (PINA.2 == 0 && PINA.3 == 0) //down and left { vy2=s2; vx2=-s2; } else if (PINA.1 == 0 && PINA.4 == 0) //up and right { vy2=-s2; vx2=s2; } else if (PINA.2 == 0 && PINA.4 ==0) //down and right { vx2=s2; vy2=s2; } else if (PINA.1 == 0) //up { vy2=-s2; vx2=0; } else if (PINA.2 == 0) //down { vy2=s2; vx2=0; } else if (PINA.3 == 0) //left { vx2=-s2; vy2=0; } else if (PINA.4 ==0) //right { vx2=s2; vy2=0; } } if (players==2 && PINA.6 == 0 && PINA.0 == 0) //button B and C together for switching ducks { currentduck = currentduck ^ 0xFFFF; } } mycount++; } //duck 1 on even counts while its alive and we aren't in shot testing if((count&0b00000001)==0 && alive1==1 && maybe==0 && (gamestate==0||gamestate==2)){ tempx1=(unsigned char)(x1>>8); //We only want the upper 8 bits tempy1=(unsigned char)(y1>>8); //Because we only can draw whole pixels //Remove duck if(deathstate1==0){ video_putsymbol(tempx1,tempy1,19); video_putsymbol(tempx1+8,tempy1,19); } else if(deathstate1==1){ video_putsymbol(tempx1,tempy1,19); video_putsymbol(tempx1,tempy1+8,19); video_putsymbol(tempx1+8,tempy1+8,19); } else if(deathstate1==2||deathstate1==3){ video_putsymbol(tempx1,tempy1,19); video_putsymbol(tempx1,tempy1+8,19); } //collision detection and random motion only if the duck is flying normally if(deathstate1==0){ //random motion if(random1==1) { if(count1++>60)//every second { count1 = 0; if(TCNT0 < 31) { vy1 = r; vx1 = 0; } else if(TCNT0 < 63) { vy1 = s; vx1 = -(s); } else if(TCNT0 < 95) { vy1 = 0; vx1 = -(r); } else if(TCNT0 < 127) { vy1 = -(s); vx1 = -(s); } else if(TCNT0 < 159) { vy1 = -(r); vx1 = 0; } else if(TCNT0 < 191) { vy1 = -(s); vx1 = s; } else if(TCNT0 < 223) { vy1 = 0; vx1 = r; } else { vy1 = s; vx1 = s; } } } //collision detection only if the other duck is alive or dying if(alive2==1){ //duck2 flying normally if(deathstate2==0){ if((tempx1>tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2+8)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2+8)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy1tempx2)&&(tempx1tempy2)&&(tempy171){ y1=17920; vy1=-vy1; } else if(tempx1<5){ x1=1536; vx1=-vx1; } else if(tempx1>108){ x1=27392; vx1=-vx1; } //dying duck if(deathstate1==2){ vx1=0x0000; vy1=0x0100; } if(deathstate1==1){ if(!(alive2==1&&deathstate2==0))PORTC=0x00; vx1=0x0000; vy1=0x0000; if(deathcount1==0){ deathstate1=2; PORTB.1=~PORTB.1; } } //update position x1 = x1 + vx1; y1 = y1 + vy1; tempx1=(unsigned char)(x1>>8); tempy1=(unsigned char)(y1>>8); //set direction if(vx1>0)direction1=4; else direction1=0; //Draw duck if(deathstate1==0){ video_putsymbol(tempx1,tempy1,direction1+flap); video_putsymbol(tempx1+8,tempy1,direction1+flap+1); } else if(deathstate1==1){ video_putsymbol(tempx1,tempy1,31); video_putsymbol(tempx1,tempy1+8,32); video_putsymbol(tempx1+8,tempy1+8,33); } else if(deathstate1==2){ if(tempy1>64){ deathstate1=0; alive1=0; } else { video_putsymbol(tempx1,tempy1,34+spin); video_putsymbol(tempx1,tempy1+8,35+spin); } } else if(deathstate1==3){ deathstate1=0; alive1=0; } } //end duck1 //duck 2 on odd counts while its alive and we aren't in shot testing else if(count&0b00000001==1 && alive2==1 && maybe==0 && (gamestate==0||gamestate==2)){ tempx2=(unsigned char)(x2>>8); //We only want the upper 8 bits tempy2=(unsigned char)(y2>>8); //Because we only can draw whole pixels //Remove duck if(deathstate2==0){ video_putsymbol(tempx2,tempy2,19); video_putsymbol(tempx2+8,tempy2,19); } else if(deathstate2==1){ video_putsymbol(tempx2,tempy2,19); video_putsymbol(tempx2,tempy2+8,19); video_putsymbol(tempx2+8,tempy2+8,19); } else if(deathstate2==2||deathstate2==3){ video_putsymbol(tempx2,tempy2,19); video_putsymbol(tempx2,tempy2+8,19); } if(deathstate2==0){ //random motion if(random2==1) { if(count2++>60)//every second { count2 = 0; if(TCNT0 < 31) { vy2 = r; vx2 = 0; } else if(TCNT0 < 63) { vy2 = s; vx2 = -(s); } else if(TCNT0 < 95) { vy2 = 0; vx2 = -(r); } else if(TCNT0 < 127) { vy2 = -(s); vx2 = -(s); } else if(TCNT0 < 159) { vy2 = -(r); vx2 = 0; } else if(TCNT0 < 191) { vy2 = -(s); vx2 = s; } else if(TCNT0 < 223) { vy2 = 0; vx2 = r; } else { vy2 = s; vx2 = s; } } } //collision detection if(alive1==1){ //when they are both alive we dont need to check collisions for both ducks //duck1 falling from sky if(deathstate1==2){ if((tempx2>tempx1)&&(tempx2tempy1)&&(tempy2tempx1)&&(tempx2tempy1)&&(tempy2tempx1)&&(tempx2tempy1)&&(tempy2tempx1)&&(tempx2tempy1)&&(tempy2tempx1)&&(tempx2tempy1+8)&&(tempy2tempx1)&&(tempx2tempy1)&&(tempy2tempx1)&&(tempx2tempy1+8)&&(tempy2tempx1)&&(tempx2tempy1)&&(tempy2tempx1)&&(tempx2tempy1)&&(tempy2tempx1)&&(tempx2tempy1)&&(tempy2tempx1)&&(tempx2tempy1)&&(tempy2tempx1)&&(tempx2tempy1)&&(tempy271){ y2=17920; vy2=-vy2; } else if(tempx2<5){ x2=1536; vx2=-vx2; } else if(tempx2>108){ x2=27392; vx2=-vx2; } //duck dying if(deathstate2==2){ vx2=0x0000; vy2=0x0100; } if(deathstate2==1){ if(!(alive1==1&&deathstate1==0))PORTC=0x00; vx2=0x0000; vy2=0x0000; if(deathcount2==0){ deathstate2=2; PORTB.1=~PORTB.1; } } //update position x2 = x2 + vx2; y2 = y2 + vy2; tempx2=(unsigned char)(x2>>8); tempy2=(unsigned char)(y2>>8); //set direction if(vx2>0)direction2=4; else direction2=0; //Draw duck if(deathstate2==0){ video_putsymbol(tempx2,tempy2,direction2+flap); video_putsymbol(tempx2+8,tempy2,direction2+flap+1); } else if(deathstate2==1){ video_putsymbol(tempx2,tempy2,31); video_putsymbol(tempx2,tempy2+8,32); video_putsymbol(tempx2+8,tempy2+8,33); } else if(deathstate2==2){ if(tempy2>64){ deathstate2=0; alive2=0; } else { video_putsymbol(tempx2,tempy2,34+spin); video_putsymbol(tempx2,tempy2+8,35+spin); } } else if(deathstate2==3){ deathstate2=0; alive2=0; } } //Flapping Wings if(flapcount==15){ flapcount=0; if(flap==0){flap=2;spin=20;} else if(flap==2){flap=0;spin=0;} } //Hit Detection //If you are pointing at white, draw duck black, draw it white again - if gun sees that //transition then it was a hit. hit=GIFR&0b10000000;//ext int1 D3 trigger=GIFR&0b01000000;//ext int0 D2 if (maybe == 9) //target2 hit { maybe=0; if (hit ==0b10000000) //update score and kill duck { random2=0; if(level>0 && tempy2<64) { deathstate2=1; deathcount2=30; } else alive2=0; score=score+level; ducksShot+=1; sprintf(ts,"%03d",score); video_putsmalls(108,92,ts); video_putsymbol(tempx2+8,tempy2,19); video_putsymbol(tempx2,tempy2,19); } } else if (maybe == 8) maybe = 9; //pause stage else if (maybe == 7) //check to see if it is black to start with { video_putsymbol(tempx2,tempy2,direction2+flap); video_putsymbol(tempx2+8,tempy2,direction2+flap+1); if (hit == 0) { maybe = 8; } else { maybe=0; } } else if(maybe==6)maybe=7; //pause stage else if(maybe==5){ //start duck2 hit detection check if(alive2==1 && deathstate2==0 && hit == 0b10000000){ tempx2=(unsigned char)(x2>>8); tempy2=(unsigned char)(y2>>8); video_putsymbol(tempx2,tempy2,19); video_putsymbol(tempx2+8,tempy2,19); maybe=6; } else maybe = 0; //skip if duck2 is dead or you are pointing at black } else if (maybe == 4) //target1 hit { maybe = 5; if (hit ==0b10000000) { random1=0; if(level>0 && tempy1<64) { deathstate1=1; deathcount1=30; } else alive1=0; ducksShot+=1; score=score+level; sprintf(ts,"%03d",score); video_putsmalls(108,92,ts); maybe = 0; video_putsymbol(tempx1+8,tempy1,19); //turns target1 into black video_putsymbol(tempx1,tempy1,19); //turns target1 into black } } else if (maybe == 3) maybe =4; else if (maybe == 2) { video_putsymbol(tempx1,tempy1,direction1+flap); video_putsymbol(tempx1+8,tempy1,direction1+flap+1); if (hit == 0) //check to see if it is black to start with { maybe = 3; } else { maybe=5; } } else if(maybe==1)maybe=2; //pause stage else if (trigger==0b01000000 && maybe == 0 && bulletcount>0 && gamestate==0 && deathstate1!=1 && deathstate2!=1) //trigger is pulled { PORTB.0=~PORTB.0; //level 0 does things differently if(level!=0){ bulletcount=bulletcount-4; video_smallchar(68+bulletcount,92,12); } if(round==0&&level==0){ round=1; sprintf(ts,"%02d",round); video_putsmalls(8,92,ts); video_putsmalls(36,72,playersS); } else{ if(alive1==1 && deathstate1==0 && hit == 0b10000000){ tempx1=(char)(x1>>8); tempy1=(char)(y1>>8); video_putsymbol(tempx1,tempy1,19); //turns target1 into black video_putsymbol(tempx1+8,tempy1,19); maybe=1; } else maybe=5; //skip it if duck1 is dead or you are pointing at black } } //draw tree if(maybe==0 && (gamestate==0||gamestate==2) && level>0)video_putsymbol(20,74,22); if(deathstate1==0 && deathstate2==0 && gamestate==0 && maybe==0){ //wait until the ducks fall if(alive1==0 && alive2==0 && level!=0){gamestate=1;count=0;} //both ducks killed else if(bulletcount==0 && (alive1==1 || alive2==1)){gamestate=2;count=0;} //out of bullets and at least one duck alive else if(count==roundtime){gamestate=2;count=0;} //out of time } GIFR=GIFR|0b11000000; //clear trigger and hit flags //Playing the game //gamestate: 0 for playing, 1 for after round, 5 for before round, 2 for ducks fly off, 3 for game win, 4 for game lose if(level>0){ //pre-round if(gamestate==5){ if(count==1){ PORTC=0b00000000;//no music //score sprintf(ts,"%03d",reqScore[level]); video_putsmalls(28,48,ts); video_putsmalls(44,48,advanceS); } else if(count==2){ //Round sprintf(ts,"%02d",round); video_putsmalls(72,40,ts); video_putsmalls(8,92,ts); video_putsmalls(48,40,roundS); } else if(count==3){ //level sprintf(ts,"%02d",level); video_putsmalls(72,32,ts); video_putsmalls(24,92,ts); video_putsmalls(48,32,levelS); } //clean up else if(count==181){ video_putsmalls(28,48,clear9S); } else if(count==182){ video_putsmalls(48,40,clear4S); video_putsmalls(48,32,clear4S); } //set up round else if(count==183){ gamestate=0; count=0; alive2=1; x1 = 0x2000; y1 = 0x2800; x2 = 0x4000; y2 = 0x1000; s1=0x0180; s2=0x0180; deathstate1=0; deathstate2=0; vx1=0x0100; vx2=0x0180; vy1=0x0180; vy2=0x0100; if(numducks==2)alive1=1; ducksShot=0; if(players==1){random1=1;random2=1;} PORTC=0b00000100;//flapping sound } } //post-round else if(gamestate==1){ if(ducksShot==numducks){//hold up ducks killed if(count==1){ PORTC=0b00000000;//no music video_putsmalls(48,40,goodJobS); video_putsymbol(48,66,36); video_putsymbol(48,74,37); video_putsymbol(56,66,15); video_putsymbol(56,74,38); } else if(count==2){ video_putsymbol(64,66,17); if(numducks==1){ video_putsymbol(64,74,18); } else{ video_putsymbol(64,74,39); video_putsymbol(72,66,40); video_putsymbol(72,74,41); } } } else//dog laughing, moves up and down to simulate laughing { if(count==1){ video_putsymbol(56,66,15); video_putsymbol(56,74,16); video_putsymbol(64,66,17); video_putsymbol(64,74,18); video_putsmalls(48,40,clear4S); PORTC=0b00001010;//dog laughing } else if(count==15){ video_putsymbol(56,65,15); video_putsymbol(56,73,16); video_putsymbol(64,65,17); video_putsymbol(64,73,18); video_line(56, 81, 72, 81, 0); } else if(count==30){ video_putsymbol(56,66,15); video_putsymbol(56,74,16); video_putsymbol(64,66,17); video_putsymbol(64,74,18); video_line(56, 65, 72, 65, 0); } else if(count==45){ video_putsymbol(56,65,15); video_putsymbol(56,73,16); video_putsymbol(64,65,17); video_putsymbol(64,73,18); video_line(56, 81, 72, 81, 0); } else if(count==60){ video_putsymbol(56,66,15); video_putsymbol(56,74,16); video_putsymbol(64,66,17); video_putsymbol(64,74,18); video_line(56, 65, 72, 65, 0); } else if(count==75){ video_putsymbol(56,65,15); video_putsymbol(56,73,16); video_putsymbol(64,65,17); video_putsymbol(64,73,18); video_line(56, 81, 72, 81, 0); } else if(count==90){ video_putsymbol(56,66,15); video_putsymbol(56,74,16); video_putsymbol(64,66,17); video_putsymbol(64,74,18); video_line(56, 65, 72, 65, 0); } else if(count==105){ video_putsymbol(56,65,15); video_putsymbol(56,73,16); video_putsymbol(64,65,17); video_putsymbol(64,73,18); video_line(56, 81, 72, 81, 0); } else if(count==120){ video_putsymbol(56,66,15); video_putsymbol(56,74,16); video_putsymbol(64,66,17); video_putsymbol(64,74,18); video_line(56, 65, 72, 65, 0); } } //clean up if(count==145){ video_putsymbol(48,66,19); video_putsymbol(48,74,19); video_putsymbol(72,66,19); video_putsymbol(72,74,19); } else if(count==3){ video_line(0,0,0,99,1); video_line(width,0,width,99,1); video_line(0,0,width,0,1); } else if(count==146){ bulletcount=12; video_putsmalls(48,40,clear9S); video_smallchar(68,92,39); video_smallchar(72,92,39); video_smallchar(76,92,39); } else if(count==144){ video_putsymbol(56,66,19); video_putsymbol(56,74,19); video_putsymbol(64,66,19); video_putsymbol(64,74,19); } //check game conditions else if(count==147){ count=0; round=round+numducks; //lose if(scorehighScore)highScore=score; } else if(count==4){ //HIGH SCORE video_putsmalls(36,64,highScoreS); sprintf(ts,"%03d",highScore); video_putsmalls(80,64,ts); } //gun guy won, display gun else if(count==5 && players==2){ video_putsymbol(52,40,42); video_putsymbol(60,40,43); video_putsymbol(68,40,44); } else if(count==6 && players==2){ video_putsymbol(52,48,45); video_putsymbol(60,48,46); video_putsymbol(68,48,47); } //controller guy lost else if(count==301 && players==2){ PORTC=0b00001000;//win music video_putsymbol(44,24,28);//L video_putsymbol(52,24,29);//O video_putsymbol(60,24,30);//S } else if(count==302 && players==2){ video_putsymbol(68,24,26);//E video_putsymbol(76,24,27);//R } else if(count==303 && players==2){ //controller's score video_putsmalls(36,72,yourScoreS); sprintf(ts,"%03d",maxScore[level]-score); video_putsmalls(80,72,ts); if(maxScore[level]-score)highScore=maxScore[level]-score; } else if(count==304 && players==2){ //HIGH SCORE video_putsmalls(36,64,highScoreS); sprintf(ts,"%03d",highScore); video_putsmalls(80,64,ts); } //display controller else if(count==305 && players==2){ video_putsymbol(52,40,48); video_putsymbol(60,40,49); video_putsymbol(68,40,50); } else if(count==306 && players==2){ video_putsymbol(52,48,51); video_putsymbol(60,48,52); video_putsymbol(68,48,53); } //clean up and restart game else if(count==599){ video_putsymbol(52,40,19); video_putsymbol(68,40,19); video_putsymbol(52,48,19); video_putsymbol(68,48,19); } else if(count==600){ video_putsymbol(36,24,19);//V- video_putsymbol(44,24,19);//-V video_putsymbol(52,24,19);//I video_putsymbol(60,24,19);//N } else if(count==601){ video_putsymbol(68,24,19);//N video_putsymbol(76,24,19);//E video_putsymbol(84,24,19);//R } else if(count==602){ video_putsymbol(28,24,8); video_putsymbol(36,24,9); video_putsymbol(44,24,10); video_putsymbol(52,24,11); } else if(count==603){ video_putsymbol(68,24,12); video_putsymbol(76,24,9); video_putsymbol(84,24,13); video_putsymbol(92,24,14); } else if(count==604){ video_putsymbol(56,40,15); video_putsymbol(56,48,16); video_putsymbol(64,40,17); video_putsymbol(64,48,18); } else if(count==605){ //Label Ducks 1 & 2 for mode/player selection video_smallchar(28,44,1); video_smallchar(96,44,2); video_putsmalls(36,72,startS); //SHOOT TO START video_putsmalls(36,72,startS); //HIGH SCORE video_putsmalls(36,64,highScoreS); h=highScore; sprintf(ts,"%03d",h); video_putsmalls(80,64,ts); } else if(count==606){ //Bullet Count video_putsmalls(40,92,bulletsS); video_smallchar(68,92,39); video_smallchar(72,92,39); video_smallchar(76,92,39); bulletcount=12; //Score score=0; sprintf(ts,"%03d",score); video_putsmalls(108,92,ts); x1 = 0x2000; y1 = 0x2800; vx1= 0x0000; vy1= 0x0000; x2 = 0x4F00; y2 = 0x2800; vx2= 0x0000; vy2= 0x0000; } else if(count==607){ //Round round=0; sprintf(ts,"%02d",round); video_putsmalls(8,92,ts); //Level level=0; sprintf(ts,"%02d",level); video_putsmalls(24,92,ts); roundtime=30000; gamestate=0;//0 for playing, 1 for after round, 5 for before round, 2 for ducks fly off, 3 for game over count = 0; flap=0; direction1=4; direction2=0; alive1=1; alive2=1; random1=0; random2=0; deathcount1=0; deathcount2=0; PORTC=0b00000010;//menu music } } //lose else if(gamestate==4){ if(count==1){ video_putsymbol(44,24,28);//L video_putsymbol(52,24,29);//O video_putsymbol(60,24,30);//S } else if(count==2){ video_putsymbol(68,24,26);//E video_putsymbol(76,24,27);//R level=level-1; } else if(count==3){ //your score video_putsmalls(36,72,yourScoreS); sprintf(ts,"%03d",score); video_putsmalls(80,72,ts); if(score>highScore)highScore=score; } else if(count==4){ //HIGH SCORE video_putsmalls(36,64,highScoreS); h=highScore; sprintf(ts,"%03d",h); video_putsmalls(80,64,ts); } //gun guy lost, display gun else if(count==5 && players==2){ video_putsymbol(52,40,42); video_putsymbol(60,40,43); video_putsymbol(68,40,44); } else if(count==6 && players==2){ video_putsymbol(52,48,45); video_putsymbol(60,48,46); video_putsymbol(68,48,47); } //controller guy won else if(count==301 && players==2){ PORTC=0b00000110;//win music video_putsymbol(36,24,23);//V- video_putsymbol(44,24,24);//-V video_putsymbol(52,24,25);//I video_putsymbol(60,24,13);//N } else if(count==302 && players==2){ video_putsymbol(68,24,13);//N video_putsymbol(76,24,26);//E video_putsymbol(84,24,27);//R } else if(count==303 && players==2){ //controller's score video_putsmalls(36,72,yourScoreS); sprintf(ts,"%03d",maxScore[level]-score); video_putsmalls(80,72,ts); if(maxScore[level]-score>highScore)highScore=maxScore[level]-score; } else if(count==304 && players==2){ //HIGH SCORE video_putsmalls(36,64,highScoreS); sprintf(ts,"%03d",highScore); video_putsmalls(80,64,ts); } //display controller else if(count==305 && players==2){ video_putsymbol(52,40,48); video_putsymbol(60,40,49); video_putsymbol(68,40,50); } else if(count==306 && players==2){ video_putsymbol(52,48,51); video_putsymbol(60,48,52); video_putsymbol(68,48,53); } //clean up and reset game else if(count==599){ video_putsymbol(52,40,19); video_putsymbol(68,40,19); video_putsymbol(52,48,19); video_putsymbol(68,48,19); } else if(count==600){ video_putsymbol(44,24,19);//L video_putsymbol(52,24,19);//O video_putsymbol(60,24,19);//S } else if(count==601){ video_putsymbol(68,24,19);//E video_putsymbol(76,24,19);//R video_putsymbol(36,24,19);//V- video_putsymbol(84,24,19);//R } else if(count==602){ video_putsymbol(28,24,8); video_putsymbol(36,24,9); video_putsymbol(44,24,10); video_putsymbol(52,24,11); } else if(count==603){ video_putsymbol(68,24,12); video_putsymbol(76,24,9); video_putsymbol(84,24,13); video_putsymbol(92,24,14); } else if(count==604){ video_putsymbol(56,40,15); video_putsymbol(56,48,16); video_putsymbol(64,40,17); video_putsymbol(64,48,18); } else if(count==605){ //Label Ducks 1 & 2 for mode/player selection video_smallchar(28,44,1); video_smallchar(96,44,2); video_putsmalls(36,72,startS); //SHOOT TO START video_putsmalls(36,72,startS); //HIGH SCORE video_putsmalls(36,64,highScoreS); sprintf(ts,"%03d",highScore); video_putsmalls(80,64,ts); } else if(count==606){ //Bullet Count video_putsmalls(40,92,bulletsS); video_smallchar(68,92,39); video_smallchar(72,92,39); video_smallchar(76,92,39); bulletcount=12; //Score score=0; sprintf(ts,"%03d",score); video_putsmalls(108,92,ts); x1 = 0x2000; y1 = 0x2800; vx1= 0x0000; vy1= 0x0000; x2 = 0x4F00; y2 = 0x2800; vx2= 0x0000; vy2= 0x0000; } else if(count==607){ //Round round=0; sprintf(ts,"%02d",round); video_putsmalls(8,92,ts); //Level level=0; sprintf(ts,"%02d",level); video_putsmalls(24,92,ts); roundtime=30000; gamestate=0;//0 for playing, 1 for after round, 5 for before round, 2 for ducks fly off, 3 for game over PORTC=0b00000010;//menu music count = 0; flap=0; direction1=4; direction2=0; alive1=1; alive2=1; random1=0; random2=0; deathcount1=0; deathcount2=0; } } }//gamestates //LEVEL 0 Sets up the game, pull trigger to start, then pick # players, then pick # ducks else if(level==0){ //1P if(round==1&&alive1==0){ alive1=1; players=1; round=2; sprintf(ts,"%02d",round); video_putsmalls(8,92,ts); video_putsmalls(36,72,duckS); } //2P else if(round==1&&alive2==0){ alive2=1; players=2; round=2; sprintf(ts,"%02d",round); video_putsmalls(8,92,ts); video_putsmalls(36,72,duckS); } //1D else if(round==2&&alive1==0){ numducks=1; roundtime=900; round=3; alive2=0; tempx2=(char)(x2>>8); tempy2=(char)(y2>>8); video_putsymbol(tempx2,tempy2,19); video_putsymbol(tempx2+8,tempy2,19); } //2D else if(round==2&&alive2==0){ numducks=2; roundtime=1200; round=3; alive1=0; tempx1=(char)(x1>>8); tempy1=(char)(y1>>8); video_putsymbol(tempx1,tempy1,19); video_putsymbol(tempx1+8,tempy1,19); } //clean up else if(round==6){ video_smallchar(28,44,12); video_smallchar(96,44,12); video_putsmalls(36,64,clear7S); video_putsmalls(36,72,clear7S); round=1; count=0; level=1; deathstate1=0; deathstate2=0; if(players==1){ random1=1; random2=1; } gamestate=5; sprintf(ts,"%02d",round); video_putsmalls(8,92,ts); sprintf(ts,"%02d",level); video_putsmalls(24,92,ts); } else if(round==5){ video_putsymbol(56,40,19); video_putsymbol(56,48,19); video_putsymbol(64,40,19); video_putsymbol(64,48,19); round=6; } else if(round==4){ video_putsymbol(68,24,19); video_putsymbol(76,24,19); video_putsymbol(84,24,19); video_putsymbol(92,24,19); round=5; } else if(round==3){ video_putsymbol(28,24,19); video_putsymbol(36,24,19); video_putsymbol(44,24,19); video_putsymbol(52,24,19); round=4; } } //level 0 } //line 231 } //while } //main