Code Listing

 

Download SI-Final Code.c

 

//Thomas Graziano

//Final Project- Space Invaders Test

//Based on Professor Bruce Land's VideoOpt32.c code

//http://instruct1.cit.cornell.edu/courses/ee476/

//This code is not for commercial sale

//original graphics developed by Atari

//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 

//C.0 is sound

 

#pragma regalloc-    //We allocate the registers

#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 T0reload 256-60 

#define WIDTH 126  

#define HEIGHT 100

 

#define up1      !PINA.0

#define down1  !PINA.1

#define left1   !PINA.2

#define right1  !PINA.3

#define button1 !PINA.4

#define button2 !PINA.5

 

#define bullet_length 4

#define number_of_invaders 30

#define bar1 30

#define bar2 58

#define bar3 89 

#define INV_SHOOT_DELAY 250   

#define PLAYER_BARRIER 20

 

//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+

 

//***********************************************

//Video Generation variables

//***********************************************

char syncON, syncOFF;

int LineCount;  

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

//************************************************

 

//************************************************

//Declarations for the space invaders coding

//************************************************

int j, k; //temp variables

int inv_speed, count; //counts the ticks before a toggle + invader march speed

bit toggle;  //just a toggle variable for invader march

bit left, right, previous_shoot;  //state variables

char shoot_x, shoot_y; //player 1 current shot

int pos1;  //position of player 1

 

//Top 6 bits of each char represent the invaders left to right on the screen

//[0] char is the top line, and [5] char is the bottom line of invaders on the screen 

char number_of_dead_invaders;           //self explanitory

char inv_x;        //x, y coord of top left column of invaders block

char inv_y;       

bit flag;             //update invaders on the screen?        

bit flag2;          

bit flag3;  

char tick;                      //dummy for printing invaders to screen

bit march;                     //polarity of the march (i.e. march left or march right?)

bit march_down;           //are the invaders in the process of marching down

char caser;        //dummy for printing invaders to the screen in steps

char current_inv;

char current_inv2;       

char inv_width;             //invaders block width

char inv_height; //invaders block height

char soundflag; 

char musicon;

char dead_row_top;     //begin of top invader block

char dead_row_bottom;

char dead_col_left;

char dead_col_right;     //end of right invader block

char tmp;        

char just_killed;    

int score;           

char s1;

char s2;

char s3;

char s4;      

bit win;

int win_count;

bit player_toggle_enable;

bit player_toggle;  

char dead_row[5];   

char dead_col[6];

char invaders[5];  //holds info on whether or not invaders is "dead" 

 

//invader random shoot variables

int random_num;

bit last_invader_shoot_flag; //flag the shoot

char last_invader_shoot; //pointer to last shoot

char invader_shoot_clock;

char previous_invader_shoot_x[6];      

char previous_invader_shoot_y[6];

char random_inv_col;       

char random_inv_row;  

char lives1;   

flash char tone[33] = {75, 0, 100, 0, 60, 0, 45, 0, 60, 0, 45, 0, 45, 0, 60, 0, 100, 0, 75, 0 , 60, 0, 45, 0 ,60,0 , 45, 0 , 100, 0 , 75, 75 };

char deathcount;

char soundcount;

char shootsound;

char inv_deathsound;

char inc;

//*************************************************

 

char screen[1600];

 

//Define space invader character bitmaps

//8x10 characters

flash char bitmap_invaders[17][10]=

{

            //0-> Alien 1a

            0b00011000,

            0b01111110,

            0b11011011,

            0b11111111,

            0b01000010,

            0b01000010,

            0b00100010,

            0b00010001,

            0b00010001,

            0b00001001,

            //1-> Alien 1b

            0b00011000,

            0b01011010,

            0b11011011,

            0b11111111,

            0b01000010,

            0b01000010,

            0b01000100,

            0b10001000,

            0b10001000,

            0b10010000,

            //2-> Alien 2a

            0b00111100,

            0b01111110,

            0b11001111,

            0b11001111,

            0b11111111,

            0b00111010,

            0b00100010,

            0b00100010,

            0b00100010,

            0b11101110,

            //3-> Alien 2b

            0b00111100,

            0b01111110,

            0b11110011,

            0b11110011,

            0b11111111,

            0b01011100,

            0b01000100,

            0b01000100,

            0b01000100,

            0b01110111,

            //4-> Alien 3a

            0b00111100,

            0b01111110,

            0b11010111,

            0b01111110,

            0b00111100,

            0b00100100,

            0b01000010,

            0b01011010,

            0b00100100,

            0b00000000,

            //5-> Alien 3b

            0b00111100,

            0b01111110,

            0b11101011,

            0b01111110,

            0b00111100,

            0b00100100,

            0b00100100,

            0b01000010,

            0b01000010,

            0b10000001,

            //6-> Alien 4a

            0b10000001,

            0b10000001,

            0b10100101,

            0b10111101,

            0b01011010,

            0b00011000,

            0b00011000,

            0b00011000,

            0b00100100,

            0b11000011,

            //7-> Alien 4b

            0b00000000,

            0b00011000,

            0b01011010,

            0b10111101,

            0b10011001,

            0b10011001,

            0b10100101,

            0b00100100,

            0b01000010,

            0b00100100,

            //8-> Alien 5a

            0b00111100,

            0b01111110,

            0b01011010,

            0b11111111,

            0b10100101,

            0b10011001,

            0b01011010,

            0b01011010,

            0b01011010,

            0b01000010,

            //9-> Alien 5b

            0b00111100,

            0b01111110,

            0b01011010,

            0b11111111,

            0b10100101,

            0b10011001,

            0b10011001,

            0b10100101,

            0b10100101,

            0b10100101,

            //10-> Alien 6a

            0b10000000,

            0b01000010,

            0b00100101,

            0b00011001,

            0b01111100,

            0b01010110,

            0b01111110,

            0b01111110,

            0b01000010,

            0b11000110,

            //11-> Alien 6b

            0b00000001,

            0b01000010,

            0b10100100,

            0b10011000,

            0b00111110,

            0b01101011,

            0b01111110,

            0b01111110,

            0b01000010,

            0b11100111,

            //12-> Player

            0b00010000,

            0b00111000,

            0b00111000,

            0b01111100,

            0b00111000,

            0b00111000,

            0b11111110,

            0b01111100,

            0b11111110,

            0b11111110,

            //13-> Bonus

            0b00000000,

            0b00000000,

            0b00000000,

            0b00111000,

            0b01111100,

            0b10101010,

            0b11111110,

            0b11111110,

            0b01111100,

            0b00111000,

            //14-> Wall(Top)

            0b00111100,

            0b00111100,

            0b01111110,

            0b01111110,

            0b01111110,

            0b01111110,

            0b01111110,

            0b01111110,

            0b01111110,

            0b01111110,

            //15-> Wall(Bottom)

            0b11111111,

            0b11111111,

            0b11111111,

            0b11111111,

            0b11111111,

            0b11111111,

            0b11000011,

            0b11000011,

            0b00000000,

            0b00000000,

            //16-> Clear

            0b00000000,

            0b00000000,

            0b00000000,

            0b00000000,

            0b00000000,

            0b00000000,

            0b00000000,

            0b00000000,

            0b00000000,

            0b00000000                                                   

};

 

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

//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;    

  //count timer 0 at 1/usec

  //TCNT0=0;

  //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+

   

//*********************************************

// Invader Bitmap to Screen

// c is index into bitmap

//*********************************************

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

{

                        v7 = x;

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

            {

            v1 = bitmap_invaders[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 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

      

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

//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

 

//*********************************************************

//Main

//*********************************************************

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 switches

            DDRA = 0x00;  //controller 1 input

            DDRB = 0x08;

            PORTA =0xff;  //pullups

  

            //init timer 0 to 1/uSec 

            //TCCR0 = 2;

 

            // sound generation

            //TCCR2 = 0x9f;

            OCR2 = 50;

            TCCR2 = 0x8f;

            TCCR0 = 0x8d;

            OCR0 = 50;

 

            //initialize synch constants

            LineCount = 1;

            syncON = 0b00000000;

            syncOFF = 0b00100000; 

           

            //video initialize

            pos1 = (WIDTH/2) - 4;

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

 

            //draw player 1

            video_putinvader(pos1, 89, 12);

           

            //draw barriers

            video_putinvader(bar3, 65, 14);

            video_putinvader(bar3, 75, 15);    

            video_putinvader(bar2, 65, 14);

            video_putinvader(bar2, 75, 15); 

            video_putinvader(bar1, 65, 14);

            video_putinvader(bar1, 75, 15);   

 

            //initialize state variables

            previous_shoot = 0;  //no shots fired

            count = 0;               

            inv_speed = 2;

            inv_x = 1;

            inv_y = 0;        

            toggle = 0;         

            flag = 0; 

            march = 0;   

            march_down = 0;     

            flag3 = 0;   

            caser = 0;

            current_inv = 0;       

            inv_width = 88;

            inv_height = 66;    

            just_killed = 30;  //initialize just killed to "null"

            score = 0; 

            win_count = 0;          

            soundflag = 60;

            player_toggle = 0;

            player_toggle_enable = 0;         

            soundcount = 0;

            shootsound = 0;

            musicon = 0;

            deathcount = 0;

            inv_deathsound = 0;

            inc = 0;

            dead_row_bottom = 4;

            dead_col_left = 0;

            dead_col_right = 5;   

            dead_row_top = 0;      

            win = 0;       

           

            lives1 = 3;

 

            //all invaders alive initially

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

            {

                        invaders[j] = 0xff;

            }                           

            number_of_dead_invaders = 0;

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

            {

                        dead_row[j] = 0;

            } 

           

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

            {

                        dead_col[j] = 0;

            }

                

            //invaders shooting

            last_invader_shoot = 6; //pointer to last shoot- but no previous shot fired

            last_invader_shoot_flag = 0;

            invader_shoot_clock = 0;

           

            //**************************

            //t=0;  //init software timer

 

            //enable sleep mode

            MCUCR = 0b10000000;

            #asm ("sei");

 

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

            //1-230, then does all of the frame-end 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)

                        {

                        //Music coding

                                    soundflag--;

                                    if(button2)

                                {

                                    if(musicon)

                                                {

                                                musicon = 0;

                                   }

                                                else

                                    {

                                                TCCR2 = 0x9f;

                                                musicon = 1;                            

                                                }

                                    } 

                                   

                                    if (musicon)

                                    {

                                                if (soundflag == 0)

                                                {   

                                                            OCR2 = tone[soundcount];     

                                                            if (march_down) inc++;

                                                            soundflag = 20 - inc;

                                                            if (tone[soundcount]==0) TCCR2 = 0x8f;

                                                            else     

                                                            TCCR2 = 0x9f;

                                                            soundcount++;

                                                            if(soundcount==33) soundcount = 0;

                                                }         

                        }

                        else

                        {

                                                TCCR2 = 0x8f;

                                    }

                       

                                    // Sound Effects

                                    if (deathcount>0)

                                    {

                                    TCCR0 = 0x9d;

                                                OCR0 = 150;

                                                deathcount--;

                                    }

                           

                                    else if (deathcount == 1)

                                    {

                                                TCCR0 = 0x8d;

                                                deathcount--;

                                    }

                                    else

                                    {

                                                if (shootsound>0)

                                                {

                                                            TCCR0 = 0x9d;

                                                            OCR0 = shootsound*2 + 10;

                                                            shootsound--;

                                                }

                                                                                               

                                                if (inv_deathsound>0)

                                                {

                                                            TCCR0 = 0x9d;

                                                            OCR0 = inv_deathsound*3 + 40;

                                                            inv_deathsound--;

                                                }

                                                if ((inv_deathsound==0)&&(shootsound==0))

                                                {

                                                            TCCR0 = 0x8d;

                                                }

                                    }         

                                   

                                    //Invader Logic

                                    random_num++;

                                    count++; 

                                    invader_shoot_clock++;

                                   

                                    //player wins routine  

                                    if(win && count == 1)

                                    {

                                                //reinitialize       

                                                number_of_dead_invaders = 0;

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

                                                {

                                                            dead_row[j] = 0;

                                                } 

 

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

                                                {

                                                            dead_col[j] = 0;

                                                }

 

                                                previous_shoot = 0;  //no shots fired

                                                count = 0;               

                                                inv_speed = 2;

                                                inv_x = 1;

                                                inv_y = 0;        

                                                toggle = 0;         

                                                march = 0;   

                                                march_down = 0;    

                                                inc = 0;

                                                flag3 = 0;   

                                                caser = 0;

                                                current_inv = 0;       

                                                inv_width = 88;

                                                inv_height = 66;    

                                                just_killed = 30;  //initialize just killed to "null"

                                                tick = 0;                

           

                                                dead_row_bottom = 4;

                                                dead_col_left = 0;

                                                dead_col_right = 5;   

                                                dead_row_top = 0;

                                               

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

                                                {

                                                            invaders[j] = 0xff;

                                                }  

                                    flag = 0; 

                                                win = 0;   

                                                count = 0;   

                                    }     

                                   

                                    //prepare to draw invaders                               

                                    if(count == inv_speed)

                                    {       

                                                flag = 1; 

                                               

                                                if(toggle)

                                                {

                                                            toggle = 0;

                                                }

                                                else

                                                {

                                                            toggle = 1;

                                                }          

                                                tick = 0;       

                                                flag2 = 0;   

                                               

                                                //if not marching left, move invaders right

                                                if(!march)

                                                {

                                                            ++inv_x;

                                                            if(inv_x + 16*(dead_col_right + 1) - 8 == WIDTH - 2)

                                                            {         

                                                                        march = 1;  

                                                                        --inv_x; 

                                                                        inv_y +=4;

                                                                        march_down=1;

                                                            }

                                                }

                                                else

                                                {

                                                            --inv_x;

                                                            if(inv_x + 16*dead_col_left == 1)

                                                            {         

                                                                        ++inv_x;

                                                                        march = 0; 

                                                                        inv_y +=4;

                                                                        march_down = 1;

                                                            }    

                                                }  

      

                                                if(inv_y + 14*(dead_row_bottom - dead_row_top + 1) -4 > 89)

                                                {

                                                            //end of game... Invaders reach the bottom of the screen

                                                            video_putinvader(pos1, 89, 16);

                                                            TCCR2 = 0x8f; //flatline sound

                                                            while(1);

                                                } 

                                               

                                                //win condition test

                                                if(number_of_dead_invaders >= 30)

                                                { 

                                                            score +=100; 

                                                            flag = 1;   //update invaders on screen    

                                                            win = 1;    

                                                } 

                                    }

                                         

                                    //if the time has come to update the invaders on the screen?

                                    if (flag)

                                    {

                                                //draw left half of invaders (if they're alive)

                                                if(caser==0)

                                                {

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

                                                                        {                                         

                                                                                    if((invaders[current_inv/6]&(0b10000000>>(current_inv%6))) == (0b10000000>>(current_inv%6)))

                                                                                    {

                                                                                                video_line(inv_x+j*16-1, inv_y+tick*14, inv_x+j*16-1, inv_y+tick*14 + 10, 0);

                                                                                                video_putinvader(inv_x+j*16, inv_y+tick*14, (j*2)+toggle);

                                                                                                video_line(inv_x+j*16+8, inv_y+tick*14, inv_x+j*16+8, inv_y+tick*14 + 10, 0);

                                                                                                if(march_down)

                                                                                                {

                                                                                                            video_line(inv_x+j*16-1, inv_y+tick*14-1, inv_x+j*16+8, inv_y+tick*14-1, 0);

                                                                                                            video_line(inv_x+j*16-1, inv_y+tick*14-2, inv_x+j*16+8, inv_y+tick*14-2, 0);

                                                                                                            video_line(inv_x+j*16-1, inv_y+tick*14-3, inv_x+j*16+8, inv_y+tick*14-3, 0);

                                                                                                            video_line(inv_x+j*16-1, inv_y+tick*14-4, inv_x+j*16+8, inv_y+tick*14-4, 0);

                                                                                                }  

                                                                                    }

                                                                                    else

                                                                                    {

                                                                                                if(current_inv == just_killed)

                                                                                                {

                                                                                                            video_line(inv_x+j*16-1, inv_y+tick*14, inv_x+j*16-1, inv_y+tick*14 + 10, 0);

                                                                                                            video_putinvader(inv_x+j*16, inv_y+tick*14, 16);

                                                                                                            video_line(inv_x+j*16+8, inv_y+tick*14, inv_x+j*16+8, inv_y+tick*14 + 10, 0);

                                                                                                            just_killed = 30;            //reset the invader just killed to null  

                                                                                                            if(march_down)

                                                                                                            {

                                                                                                                        video_line(inv_x+j*16-1, inv_y+tick*14-1, inv_x+j*16+8, inv_y+tick*14-1, 0);

                                                                                                                        video_line(inv_x+j*16-1, inv_y+tick*14-2, inv_x+j*16+8, inv_y+tick*14-2, 0);

                                                                                                                        video_line(inv_x+j*16-1, inv_y+tick*14-3, inv_x+j*16+8, inv_y+tick*14-3, 0);

                                                                                                                        video_line(inv_x+j*16-1, inv_y+tick*14-4, inv_x+j*16+8, inv_y+tick*14-4, 0);

                                                                                                            }

                                                                                                } 

                                                                                    }                                                   

                                                                                    ++current_inv;  

                                                                        }    

                                                                        caser=1;

                                                } 

                                                //draw right half of invaders 

                                                else if(caser==1)

                                                {

                                                                        for(j = 3; j < 6; j++)

                                                                        {                                         

                                                                                    if((invaders[current_inv/6]&(0b10000000>>(current_inv%6))) == (0b10000000>>(current_inv%6)))

                                                                                    {

                                                                                                video_line(inv_x+j*16-1, inv_y+tick*14, inv_x+j*16-1, inv_y+tick*14 + 10, 0);

                                                                                                video_putinvader(inv_x+j*16, inv_y+tick*14, (j*2)+toggle);

                                                                                                video_line(inv_x+j*16+8, inv_y+tick*14, inv_x+j*16+8, inv_y+tick*14 + 10, 0);

                                                                                                if(march_down)

                                                                                                {

                                                                                                            video_line(inv_x+j*16-1, inv_y+tick*14-1, inv_x+j*16+8, inv_y+tick*14-1, 0);

                                                                                                            video_line(inv_x+j*16-1, inv_y+tick*14-2, inv_x+j*16+8, inv_y+tick*14-2, 0);

                                                                                                            video_line(inv_x+j*16-1, inv_y+tick*14-3, inv_x+j*16+8, inv_y+tick*14-3, 0);

                                                                                                            video_line(inv_x+j*16-1, inv_y+tick*14-4, inv_x+j*16+8, inv_y+tick*14-4, 0);

                                                                                                }  

                                                                                    }

                                                                                    else

                                                                                    {

                                                                                                if(current_inv == just_killed)

                                                                                                {

                                                                                                            video_line(inv_x+j*16-1, inv_y+tick*14, inv_x+j*16-1, inv_y+tick*14 + 10, 0);

                                                                                                            video_putinvader(inv_x+j*16, inv_y+tick*14, 16);

                                                                                                            video_line(inv_x+j*16+8, inv_y+tick*14, inv_x+j*16+8, inv_y+tick*14 + 10, 0);

                                                                                                            just_killed = 30;  //reset the invader just killed to "null"

                                                                                                            if(march_down)

                                                                                                            {

                                                                                                                        video_line(inv_x+j*16-1, inv_y+tick*14-1, inv_x+j*16+8, inv_y+tick*14-1, 0);

                                                                                                                        video_line(inv_x+j*16-1, inv_y+tick*14-2, inv_x+j*16+8, inv_y+tick*14-2, 0);

                                                                                                                        video_line(inv_x+j*16-1, inv_y+tick*14-3, inv_x+j*16+8, inv_y+tick*14-3, 0);

                                                                                                                        video_line(inv_x+j*16-1, inv_y+tick*14-4, inv_x+j*16+8, inv_y+tick*14-4, 0);

                                                                                                            }

                                                                                                } 

                                                                                    }                                                  

                                                                                    ++current_inv;   

                                                                        }

                                                                        ++tick;     

                                                                        caser=0;

                                                }    

                                               

                                                if (count == inv_speed +9)//(count == inv_speed+dead_row_bottom<<2-1)

                                                {

                                                            count = 0;       

                                                            flag = 0;               

                                                            current_inv = 0;                                                           

                                                }   

                                    }         

                                   

                                    //if the invaders aren't marching down a step (i.e. at the screen's edge)

                                    //it's ok for the other functions to update this frame.

                                    //if not, an update below this point will cause artifacts and flicker

                                    //(so don't update)

                                    if(!march_down)

                                    {         

                                                //is it time to fire an invader shot?- then setup shot

                                                if(invader_shoot_clock > INV_SHOOT_DELAY)

                                                {

                                                            random_inv_col = random_num%(6);

                                                            if(last_invader_shoot_flag != 1)

                                                            {         

                                                                        previous_invader_shoot_x[0] = inv_x + 16*random_inv_col+4;           

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

                                                                        {                  

                                                                                    tmp = invaders[j];

                                                                                    tmp = ((0b10000000>>(random_inv_col))) & tmp;

                                                                                    if(tmp)

                                                                                    {

                                                                                                previous_invader_shoot_y[0] = inv_y + 14*j + 11;

                                                                                                last_invader_shoot_flag = 1;

                                                                                    }         

                                                                        }

                                                                        if(last_invader_shoot_flag)

                                                                        {

                                                                                    video_line(previous_invader_shoot_x[0], previous_invader_shoot_y[0], previous_invader_shoot_x[0], previous_invader_shoot_y[0] + bullet_length,1);

                                                                        }

                                                            }       

                                                            invader_shoot_clock = 0;

                                                }  

                                        

                                                //if invaders have previously fired

                                                if(last_invader_shoot_flag)

                                                {

                                                            if(video_set(previous_invader_shoot_x[0], previous_invader_shoot_y[0]+bullet_length+1))

                                                            {

                                                                        last_invader_shoot_flag = 0;

                                                                        video_line(previous_invader_shoot_x[0], previous_invader_shoot_y[0], previous_invader_shoot_x[0], previous_invader_shoot_y[0] + bullet_length+2,0);

                                                                        if((previous_invader_shoot_y[0] + bullet_length > 88) && (pos1<previous_invader_shoot_x[0]+7) &&(pos1>previous_invader_shoot_x[0]-7))

                                                                        {

                                                                                    deathcount = 20;

                                                                                    --lives1;

                                                                                    if(lives1 <0)

                                                                                    {

                                                                                                while(1);

                                                                                    }

                                                                        }

                                                            }

                                                            else  

                                                            {

                                                                        video_pt(previous_invader_shoot_x[0], previous_invader_shoot_y[0], 0);

                                                                        ++previous_invader_shoot_y[0];

                                                                        video_pt(previous_invader_shoot_x[0], previous_invader_shoot_y[0] + bullet_length, 1);     

                                      

                                                                        //clear if at bottom of screen (i.e. don't erase bottom of screen)

                                                                        if(previous_invader_shoot_y[0] + bullet_length>= 98)

                                                                        {

                                                                                    last_invader_shoot_flag = 0;

                                                                                    video_line(previous_invader_shoot_x[0], previous_invader_shoot_y[0], previous_invader_shoot_x[0], 98,0);

                                                                        } 

                                                            }         

                                                }     

                                                                       

                                                //move right

                                                if(right1)

                                                {

                                                            if(pos1<WIDTH-9 - PLAYER_BARRIER)

                                                            {

                                                                        video_line(pos1, 89, pos1, 98, 0);  //clear to left

                                                                        video_putinvader(++pos1, 89, 12);

                                                            }

                                                } 

       

                                                //move left

                                                if(left1)

                                                {   

                                                            if(pos1 > 1 + PLAYER_BARRIER)

                                                            {

                                                                        video_line(pos1+8, 89, pos1+8, 98, 0);  //clear to right

                                                                                    video_putinvader(--pos1, 89, 12);

                                                                        }

                                                }

 

                                                //button just pressed?

                                                if(previous_shoot!=1)

                                                {                   

                                                            if(button1)

                                                            {    

                                                                        shootsound = 10;

                                                                        previous_shoot = 1;

                                                                        shoot_x = pos1+3;

                                                                        shoot_y = 88;

                                                                        video_line(shoot_x, shoot_y, shoot_x, shoot_y - bullet_length,1);

                                                            }

                                                }

 

                                                //previous shot fired

                                                else

                                                {                     

                                                            if(video_set(shoot_x, shoot_y-bullet_length-1))

                                                            {     

                                                                        //draw damage

                                                                        previous_shoot = 0;

                                                                        video_line(shoot_x, shoot_y, shoot_x, shoot_y - bullet_length-2,0);

                                                                        current_inv2 = 0;

                                                                        //hit invader?

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

                                                            {

                                                                        for(k = 0; k < 6; k++)

                                                                        {      

                                                                                    if((shoot_x < inv_x + k*16 + 8)&&(shoot_x >= inv_x + k*16))

                                                                                    {

                                                                                                if((shoot_y - bullet_length -1 < j*14 +inv_y+10)&&(shoot_y > j*14 +inv_y))

                                                                                                {   

                                                                                                            //if invader not already dead then:    

                                                                                                            tmp = invaders[current_inv2/6];

                                                                                                            tmp = (~(0b10000000>>(current_inv2%6))) & tmp;

                                                                                                            if(invaders[current_inv2/6] != tmp && just_killed== 30)

                                                                                                            {

                                                                                                                        invaders[current_inv2/6] = (~(0b10000000>>(current_inv2%6))) & invaders[current_inv2/6];      

                                                                                                                        ++dead_row[j];           

                                                                                                                        ++dead_col[k];

                                                                                                                                    just_killed = current_inv2;

                                                                                                            ++score;

                                                                                                            ++number_of_dead_invaders;  

                                                                                                            inv_deathsound=12;

 

                                                                                                                        //cases to deal with columns and rows of invaders being elimanated

                                                                                                                        tmp = k;  

                                                                                                                        while(dead_col[tmp] == 5 && tmp > 0)

                                                                                                                        {

                                                                                                                                    if(tmp == dead_col_right)

                                                                                                                                    {

                                                                                                                                                --dead_col_right;

                                                                                                                                    }   

                                                                                                                                    --tmp;

                                                                                                                        }

                                                                                                                        tmp = k;   

                                                                                                                        while(dead_col[tmp] == 5 && tmp<5)

                                                                                                                        {

                                                                                                                                    if(tmp == dead_col_left)

                                                                                                                                    {               

                                                                                                                                                ++dead_col_left;

                                                                                                                                    }   

                                                                                                                                    ++tmp;

                                                                                                                        }        

                                                                                                                        tmp = j;

                                                                                                                        while(dead_row[tmp] == 6 && tmp >0)

                                                                                                                        {

                                                                                                                                    if(tmp == dead_row_bottom)

                                                                                                                                    {

                                                                                                                                                --dead_row_bottom;

                                                                                                                                    }                     

                                                                                                                                    --tmp;                                                                                     

                                                                                                                        }

                                                                                                                        tmp = j;

                                                                                                                        while(dead_row[tmp] == 6 && tmp <6)

                                                                                                                        {

                                                                                                                                    if(tmp == dead_row_top)

                                                                                                                                    {

                                                                                                                                                ++dead_row_top;

                                                                                                                                    }                     

                                                                                                                                    ++tmp;                                                                                    

                                                                                                                        }  

                                                                                                            }

                                                                                                            else

                                                                                                            {

                                                                                                                        //video_smallchar(0, 0, 8);

                                                                                                            }         

                                                                                                            }         

                                                                                    }  

                                                                                    ++current_inv2;

                                                                        }

                                                            }

                                                            }

                                                            else

                                                            {

                                                                        video_pt(shoot_x, shoot_y, 0);

                                                                        shoot_y = shoot_y - 1;

                                                                        video_pt(shoot_x, shoot_y - bullet_length, 1);     

                                      

                                                                        //clear if at top of screen

                                                                        if(shoot_y-bullet_length < 1)

                                                                        {

                                                                                    previous_shoot = 0;

                                                                                    video_line(shoot_x, shoot_y, shoot_x, 0,0);

                                                                        } 

                                                            }

                                                }            

                                                 

                                    //to prevent artifacts only write the score when the invaders aren't being drawn

                                    if(count == 1)

                                    {

                                                //update score + lives

                                                            s1 = score%10;

                                                            s2 = (score/10)%10;

                                                s3 = (score/100)%10;

                                                s4 = (score/1000)%10;

                                                            video_smallchar(4, 90, lives1);

                                                video_smallchar(108, 90, s4);

                                                video_smallchar(112, 90, s3);

                                                video_smallchar(116, 90, s2);   

                                                video_smallchar(120, 90, s1);

                                    }

                   

                                    //debugging of dead_row, col etc.. variables

                                    //video_smallchar(0, 50, dead_row_bottom);

                                                //video_smallchar(0, 10, dead_row_top);

                                                //video_smallchar(0, 90, dead_col_left);

                                                //video_smallchar(60, 90, dead_col_right);

                                    }

                                    else

                                    {

                                                //reset after marchdown occurs

                                                if (count == 0)

                                                {

                                                            march_down = 0;                                                         

                                                }

                                    }  

                        }  //end line 231

            }          //end while

}  //end main