#include #include #include #include #include #include #include #include #define SCREEN_WIDTH 40 #define SCREEN_HEIGHT 24 #define BYTES_PER_PIXEL 2 #include "vmwsoft.h" #include "opener.h" #include "vince.h" #include "tom.h" #include "phobos.h" #include "game_sprites.h" #include "boss.h" #include "ending.h" int play_sound=0; char hi_player[4]="KRG"; int hiscore=100; int dump_screen=0; void load_hi_score() { FILE *hi_score; hi_score=fopen("/tmp/tb_asm.hsc","r"); if (hi_score!=NULL) { fscanf(hi_score,"%i\n",&hiscore); fgets(hi_player,4,hi_score); fclose(hi_score); } } int clear_framebuffer(char *buffer,char color,char value) { int i=0; while(i=xsize) { offset+=((SCREEN_WIDTH-xsize)*BYTES_PER_PIXEL); xx=0; yy++; } } return 0; } int put_text_xy(char *text,int x,int y,int color, char *framebuffer) { int offset,i; offset=(y*SCREEN_WIDTH+x)*BYTES_PER_PIXEL; i=0; while(i7,colors[color&7]); old_color=color; } temp_string[0]=framebuffer[((i+j*SCREEN_WIDTH)*BYTES_PER_PIXEL)+1]; if (temp_string[0]==219) { if (!block_mode){ block_mode=1; size+=to_buffer(out_buffer,"\016"); } temp_string[0]='0'; } else { if (block_mode) { block_mode=0; size+=to_buffer(out_buffer,"\017"); } } size+=to_buffer(out_buffer,temp_string); } size+=to_buffer(out_buffer,"\n"); } if (size>40*44*10) { printf("\a\a\a\n"); exit(10); } write(1,out_buffer,size); if (dump_screen) { int fd; fd=creat("screen",0x666); write(fd,out_buffer,size); close(fd); dump_screen=0; } // fdatasync(1); return 0; } int get_timer() { static int initialized=0; static int startseconds,startusecs; struct timeval our_time; int temp_time; if (!initialized) { gettimeofday(&our_time,NULL); startseconds=time(NULL); startusecs=our_time.tv_usec; initialized=1; } gettimeofday(&our_time,NULL); temp_time=(time(NULL)-startseconds)*1000; temp_time+=(our_time.tv_usec/1000); return temp_time; } void clear_keyboard_buffer() { int ch; while(read(0,&ch,1)==1); } void pause_a_while(int msecs) { int ch,our_time; our_time=get_timer(); while ( read(0,&ch,1)!=1) { usleep(1); if ( (get_timer()-our_time) > msecs ) break; } clear_keyboard_buffer(); } int get_char() { char ch; int result; result=read(0,&ch,1); if (result<1) return 0; else return ch; } int get_a_char() { char ch,ch1,ch2,ch3; ch=get_char(); if (ch==27) { ch1=get_char(); ch2=get_char(); ch3=get_char(); if ((ch1==0) && (ch2==0)) return 'q'; if ((ch1==91) && (ch2==66)) return 'm'; if ((ch1==91) && (ch2==65)) return 'i'; if ((ch1==91) && (ch2==67)) return 'k'; if ((ch1==91) && (ch2==68)) return 'j'; if ((ch1==91) && (ch2==91)) { if (ch3==65) return 'h'; } { FILE *fff; fff=fopen("bob","w"); fprintf(fff,"%i %i %i\n",ch1,ch2,ch3); fclose(fff); } // } } return ch; } void null() { } void put_attention_block(char *framebuffer,int color) { int i,j; for(i=5;i<12;i++) for(j=0;j<40;j++) put_text_xy("*",j,i,color,framebuffer); } int verify_quit(char *framebuffer) { int quit_bar=0; char ch; put_attention_block(framebuffer,14); put_text_xy(" QUIT? Are you sure? ",9,7,12,framebuffer); put_text_xy(" NO!",9,8,12,framebuffer); put_text_xy(" YES!",9,9,12,framebuffer); quit_loop: if (quit_bar==0) { put_text_xy(" --> NO! ",9,8,13,framebuffer); put_text_xy(" YES ",9,9,5,framebuffer); } else { put_text_xy(" NO ",9,8,5,framebuffer); put_text_xy(" --> YES! ",9,9,13,framebuffer); } dump_to_screen(framebuffer); while ((ch=get_a_char())==0) usleep(5000); if ((ch=='i') || (ch=='j') || (ch=='k') || (ch=='m')) quit_bar=!quit_bar; if (ch=='y') quit_bar=1; if (ch=='n') quit_bar=0; if (ch=='\n') { return quit_bar; } goto quit_loop; return 0; } int ending(char *framebuffer) { sleep(3); clear_keyboard_buffer(); clear_framebuffer(framebuffer,0,' '); blit(earth_sprite,framebuffer,219,32,0,5,6); put_text_xy("INCOMING MESSAGE FROM",0,0,15,framebuffer); put_text_xy(" ** EARTH **",0,1,15,framebuffer); put_text_xy("Congratulations Tom!",0,3,14,framebuffer); put_text_xy("You've destroyed the",0,4,14,framebuffer); put_text_xy(" Marketing Menace!!",0,5,14,framebuffer); put_text_xy("But wait...",0,7,14,framebuffer); put_text_xy("Our sensors detect another batch of",0,8,14,framebuffer); put_text_xy(" enemies, moving even faster!",0,9,14,framebuffer); put_text_xy("Feel free to quit at any time, but",0,11,14,framebuffer); put_text_xy(" remember no paycheck bonus unless",0,12,14,framebuffer); put_text_xy(" all are destroyed.",0,13,14,framebuffer); put_text_xy("PS Your pet guinea",0,15,14,framebuffer); put_text_xy(" pig is doing",0,16,14,framebuffer); put_text_xy(" well. -->",0,17,14,framebuffer); blit(susie_sprite,framebuffer,219,20,15,19,7); put_text_xy("** END TRANSMISSION **",0,22,15,framebuffer); dump_to_screen(framebuffer); while(get_char()==0) usleep(30); clear_framebuffer(framebuffer,0,' '); blit(tom_head_sprite,framebuffer,219,0,0,7,7); put_text_xy("Tom: *Sigh*",10,0,9,framebuffer); put_text_xy("Press Any Key to Resume Fighting",0,10,15,framebuffer); dump_to_screen(framebuffer); while(get_char()==0) usleep(30); return 0; } int help(char *framebuffer) { clear_framebuffer(framebuffer,0,' '); put_text_xy("TOM BOMBEM",10,0,15,framebuffer); put_text_xy("by",14,1,7,framebuffer); put_text_xy("Vince Weaver",9,2,15,framebuffer); put_text_xy("Key Bindings:",0,4,15,framebuffer); put_text_xy("UP or 'i' : Move menu up",2,6,7,framebuffer); put_text_xy("DOWN or 'm' : Move menu down",2,7,7,framebuffer); put_text_xy("ENTER : Selects current option",2,8,7,framebuffer); put_text_xy("RIGHT or 'k' : Move ship right",2,10,7,framebuffer); put_text_xy("LEFT or 'j' : Move ship left",2,11,7,framebuffer); put_text_xy("SPACEBAR : Shoots",2,12,7,framebuffer); put_text_xy("F1 or 'h' : Displays help",2,14,7,framebuffer); put_text_xy("ESC or 'q' : Quits",2,15,7,framebuffer); put_text_xy("'p' : Pauses",2,16,7,framebuffer); put_text_xy("'s' : Toggles sound",2,17,7,framebuffer); dump_to_screen(framebuffer); while(get_char()==0) usleep(30); return 0; } int hi_score(char *framebuffer) { char temp_string[BUFSIZ]; load_hi_score(); put_attention_block(framebuffer,12); put_text_xy("HIGH SCORE",15,7,14,framebuffer); sprintf(temp_string," %s %i ",hi_player,hiscore); put_text_xy(temp_string,(40-strlen(temp_string))/2,9,15,framebuffer); dump_to_screen(framebuffer); return 0; } int new_hi_score(char *framebuffer) { FILE *hi_score; char temp_name[4]="AAA"; int char_num=0,ch; put_attention_block(framebuffer,9); put_text_xy("NEW HIGH SCORE",13,5,13,framebuffer); put_text_xy("Use the arrows to pick your initials",2,7,14,framebuffer); put_text_xy("Press ENTER when you are done",5,8,14,framebuffer); hi_score_loop: put_text_xy(" ",17,10,15,framebuffer); put_text_xy(" ",18,11,15,framebuffer); put_text_xy(temp_name,18,10,15,framebuffer); put_text_xy("^",18+char_num,11,15,framebuffer); dump_to_screen(framebuffer); while ((ch=get_a_char())==0) usleep(5000); if (ch=='k') { char_num++; if (char_num>2) char_num=0; } if (ch=='j') { char_num--; if (char_num<0) char_num=2; } if (ch=='i') { temp_name[char_num]--; if (temp_name[char_num]<64) temp_name[char_num]=126; } if (ch=='m') { temp_name[char_num]++; if (temp_name[char_num]>126) temp_name[char_num]=64; } if (ch!='\n') goto hi_score_loop; strncpy(hi_player,temp_name,3); hi_score=fopen("/tmp/tb_asm.hsc","w"); if (hi_score!=NULL) { fprintf(hi_score,"%i\n",hiscore); fprintf(hi_score,"%s\n",hi_player); fclose(hi_score); } return 0; } void set_sound(int freq,int duration) { printf("%c[10;%i]%c[11;%i]\n",27,freq,27,duration); play_sound=1; } #define UP_SHIELDS 200 int new_game(char *framebuffer) { int i,j,xadd=0,scroll=0,quit=0,x=20,bigx=20<<8,y=16; int sound=1,shields=8,score=0; int game_paused=0,current_enemy_type=0 /*0*/,current_enemy_kind=-1,current_init_x=-1, total_enemies_out=0,level=1,enemies_spawned=1,enemy_wave=0; char temp_string[BUFSIZ]; int done_waiting; struct timeval timing_info; int time_spent,oldusec=0,oldsec=0; struct boss_type { int x,xadd,count; int waiting,hits,smoke,exploding; int shooting; } boss; struct missile_type { int out,x,y; } missile[2]; struct enemy_type { int x,y,out,kind; int xadd,yadd,xmin,xmax; int hitsneeded; int exploding; } enemies[5]; int enemy_wait=30,enemy_count=0; char ch; char *background; FILE *debug; debug=fopen("debug","w"); load_hi_score(); clear_keyboard_buffer(); clear_framebuffer(framebuffer,0x0,' '); background=calloc(1600,sizeof(char)); missile[0].out=0; missile[1].out=0; for(i=0;i<5;i++) enemies[i].out=0; /* RANDOMIZE TIMER */ srand(time(NULL)); /* Draw the Stars */ for(i=0;i<50;i++) { *(background+(rand()%40)*40+rand()%40)=7; *(background+(rand()%40)*40+rand()%40)=8; } while(!quit) { clear_framebuffer(framebuffer,0x0,' '); /* Scrolling Stars */ scroll-=1; if (scroll<0) scroll=78; if (scroll/2<20) { blit(background+(scroll/2*40),framebuffer,'.',0,0,40,20); } else { blit(background+(scroll/2*40),framebuffer,'.',0,0,40,40-scroll/2); blit(background,framebuffer,'.',0,40-scroll/2,40,scroll/2-20); } /* Put out new enemies */ /* Type 0: "Diagonal No Wait" x_init=rand, xadd=1, yadd=1 * Type 1: "horiz then fall" xadd=1. After random, xadd=0 yadd=1 * Type 2: "diagonal, wait" wait(all_free) then 0 with same type * Type 4: "Wiggle" x=rand() * Type 5: "Rain" x=rand() xadd=0 yadd=1 * Type 6: Wait for Boss * Type 7: BOSS * * * After enemies_destroyed>20 switch types * After enemies_destroyed>500? Wait till all destroyed then BOSS * After boss keep going, knocking up speed each 100 */ /* Keep a level indicator? */ /* Keep a count of how close to place enemies */ /* Don't want all to appear at once */ enemy_count++; if (enemy_count==enemy_wait) { enemy_count=0; if (current_enemy_type==7) enemies_spawned=1; /* make length random? */ if (enemies_spawned%15==0) { enemies_spawned++; /* hack to keep from getting stuck */ current_enemy_type=rand()%6; enemy_wave++; if (enemy_wave==15) current_enemy_type=6; if ((current_enemy_type==0) || (current_enemy_type==1)) enemy_wait=30; else enemy_wait=10; current_enemy_kind=-1; current_init_x=-1; } i=0; while (i<5) { if (!enemies[i].out) break; i++; } if (current_enemy_type==2) { if (total_enemies_out>0) goto move_enemies; current_enemy_type=3; current_enemy_kind=rand()%6; current_init_x=rand()%300; enemy_wait=10; } if (current_enemy_type==6) { if (total_enemies_out>0) goto move_enemies; boss.x=13; boss.xadd=1; boss.count=10+rand()%40; boss.waiting=1; boss.hits=20+(5*level); boss.smoke=0; boss.exploding=0; current_enemy_type=7; enemy_wait=10; } if ((current_enemy_type==7) && (boss.waiting)) goto move_enemies; if (i<5) { enemies_spawned++; enemies[i].out=1; enemies[i].exploding=0; total_enemies_out++; enemies[i].y=0; enemies[i].hitsneeded=0; enemies[i].xmin=0; enemies[i].xmax=37; if (current_enemy_kind<0) enemies[i].kind=rand()%6; else enemies[i].kind=current_enemy_kind; if (current_init_x<0) enemies[i].x=rand()%300; else enemies[i].x=current_init_x; switch(current_enemy_type) { case 0: enemies[i].xadd=level; enemies[i].yadd=level; break; case 1: enemies[i].xadd=5; enemies[i].yadd=-(rand()%100); break; case 3: enemies[i].xadd=3; enemies[i].yadd=level; break; case 4: enemies[i].xadd=4; enemies[i].yadd=level; enemies[i].xmin=2+rand()%34; enemies[i].xmax=enemies[i].xmin+(rand()%20); if (enemies[i].xmax>35) enemies[i].xmax=35; enemies[i].x=enemies[i].xmin*8; // fprintf(debug,"%i %i\n",enemies[i].xmin,enemies[i].xmax) break; case 5: enemies[i].xadd=0; enemies[i].yadd=2; if (rand()%3==0) enemies[i].x=x; break; case 7: enemies[i].xadd=0; enemies[i].yadd=2; enemies[i].x=(boss.x+5)*8; enemies[i].y=3*8; break; } } } move_enemies: /* Move the enemies */ for(i=0;i<5;i++) { if (enemies[i].out) { /* Move on x */ if (enemies[i].xadd!=0) { enemies[i].x+=enemies[i].xadd; if ((enemies[i].x/8>37) || (enemies[i].x/8<0)) { enemies[i].xadd=-enemies[i].xadd; enemies[i].x+=enemies[i].xadd; } if (current_enemy_type==4) { if ((enemies[i].x/8>enemies[i].xmax) || (enemies[i].x/80) { enemies[i].y+=enemies[i].yadd; if (enemies[i].y/8>18) { enemies[i].out=0; total_enemies_out--; } } /* Ship <-> Enemies Collision Detection */ if (!enemies[i].exploding) { if ( ( (enemies[i].x/8+2 >= x) && (enemies[i].x/8+2 <= x +6) ) || ( (enemies[i].x/8 >=x) && (enemies[i].x/8 <= x+6))) { if ( ((enemies[i].y/8 >= y) && (enemies[i].y/8 <=y+2)) || ( (enemies[i].y/8+1 >=y) && (enemies[i].y/8+1 <=y+2)) ) { enemies[i].exploding=1; shields--; set_sound(120,50); } } } } } /* Draw the enemies */ for(i=0;i<5;i++) { if (enemies[i].out) { if (enemies[i].exploding) { blit(explosion_sprites[enemies[i].exploding/2-1],framebuffer,219,enemies[i].x/8,enemies[i].y/8,3,2); enemies[i].exploding++; if (enemies[i].exploding>7) { enemies[i].out=0; total_enemies_out--; } } else { blit(enemy_sprites[enemies[i].kind],framebuffer,219,enemies[i].x/8,enemies[i].y/8,3,2); } } } /* Draw the Boss */ if (current_enemy_type==7) { if (boss.exploding!=1) blit(boss_sprite,framebuffer,219,boss.x,0,13,3); if (boss.smoke) { blit(smoke_sprites[boss.smoke/4],framebuffer,219,boss.x+5,3,3,1); blit(smoke_sprites[boss.smoke/4],framebuffer,219,boss.x+5-boss.xadd,4,3,1); boss.smoke--; } if (boss.shooting) { boss.shooting--; for(i=0;i<8;i++) { blit(laser_sprite[boss.shooting%2],framebuffer,219,boss.x,3+(i*2),1,2); blit(laser_sprite[boss.shooting%2],framebuffer,219,boss.x+12,3+(i*2),1,2); set_sound(200+boss.shooting,20); } } if (boss.exploding) { boss.waiting=1; for(i=0;i<30;i++) { blit(smoke_sprites[boss.exploding/8],framebuffer,219,boss.x+rand()%11,rand()%4,3,1); } set_sound(120,20); boss.exploding--; if (boss.exploding==0) { level++; boss.shooting=0; for(i=0;i<5;i++) enemies[i].exploding=2; ending(framebuffer); current_enemy_type=2; enemy_wave=0; } } else { boss.count--; if (boss.count<0) { if (boss.waiting) { boss.waiting=0; boss.count=40+rand()%320; } else { boss.waiting=1; boss.count=30+rand()%40; boss.shooting=30; } } } if (!boss.waiting) { boss.x+=boss.xadd; if ((boss.x>26) || (boss.x<0)) { boss.xadd=-boss.xadd; boss.x+=boss.xadd; } } /* Collision detection for lasers */ if (boss.shooting) { if (((boss.x < x+6) && (boss.x>=x)) || ((boss.x+12=x))) { if (boss.shooting%7==0) shields--; } } } /* Move the missiles */ for(i=0;i<2;i++) { if (missile[i].out) { missile[i].y--; if (missile[i].y<0) missile[i].out=0; /* Missile Collision Detection */ for(j=0;j<5;j++) { /* Missile <-> Enemy Collision Detection */ if ((enemies[j].out)&&(!enemies[j].exploding)) { if ((missile[i].x >=enemies[j].x/8) && (missile[i].x < enemies[j].x/8+3)) { if ((missile[i].y >= enemies[j].y/8) && (missile[i].y <=enemies[j].y/8+1) ) { missile[i].out=0; enemies[j].exploding=2; set_sound(150,40); score+=10; if (score%UP_SHIELDS==0) { shields++; set_sound(220,50); if (shields>9) shields=9; } } } } } /* Missile <-> Boss Collision Detection */ if ((current_enemy_type==7) && (!boss.exploding)) { if ((missile[i].x >= boss.x) && (missile[i].x < boss.x+13)) { if ((missile[i].y>= 0) && (missile[i].y <=2)) { missile[i].out=0; boss.smoke=11; set_sound(150,50); boss.hits--; if (boss.hits<0) boss.exploding=23; } } } } } /* Draw the missiles */ for(i=0;i<2;i++) { if (missile[i].out) blit(missile_sprite,framebuffer,219,missile[i].x,missile[i].y,1,3); } ch=0; while( (ch=get_a_char()) ) { switch(ch) { case 'd': dump_screen=1; break; case 'q': case 'Q': if (verify_quit(framebuffer)) { quit=1; } else { game_paused=1; } break; case 'j': if (xadd<=0) xadd-=128; else xadd=0; break; case 'k': if (xadd>=0) xadd+=128; else xadd=0; break; case 'p': put_attention_block(framebuffer,14); put_text_xy(" GAME PAUSED! ",13,8,12,framebuffer); dump_to_screen(framebuffer); while (get_char()==0) usleep(5000); game_paused=1; break; case 's': sound=!sound; /*level++;*/ break; case 'h': help(framebuffer); /*game_paused=1;*/ break; case ' ': if (!missile[0].out) { missile[0].out=1; missile[0].x=x+3; missile[0].y=y; set_sound(110,30); } else if (!missile[1].out) { missile[1].out=1; missile[1].x=x+3; missile[1].y=y; set_sound(110,30); } break; } } bigx+=xadd; if (bigx<0) { bigx=0; xadd=0; } if (bigx>(32<<8)) { bigx=32<<8; xadd=0; } x=bigx>>8; blit(ship_sprite,framebuffer,219,x,y,8,4); put_text_xy("SHIELDS: ",0,21,shields?12:14,framebuffer); for(i=0;i<10;i++) { if (ihiscore) { hiscore=score; fprintf(debug,"score=%i hiscore=%i\n",score,hiscore); new_hi_score(framebuffer); } hi_score(framebuffer); pause_a_while(5000); return 0; } int about(char *framebuffer) { clear_framebuffer(framebuffer,0,' '); blit(vince_sprite,framebuffer,219,24,0,16,20); put_text_xy("TOM BOMBEM",7,0,13,framebuffer); put_text_xy("by",11,1,14,framebuffer); put_text_xy("Vince Weaver",6,2,9,framebuffer); put_text_xy("author if you squint ->",0,3,12,framebuffer); put_text_xy("* Testing my asm skills",0,5,11,framebuffer); put_text_xy("* Based on Tom Bombem: ",0,7,10,framebuffer); put_text_xy(" Invasion of Inanimate",0,8,10,framebuffer); put_text_xy(" Objects, a game I ",0,9,10,framebuffer); put_text_xy(" started 10 years ago ",0,10,10,framebuffer); put_text_xy(" in Pascal/asm and is ",0,11,10,framebuffer); put_text_xy(" still languishing ",0,12,10,framebuffer); put_text_xy(" uncompleted in C/SDL.",0,13,10,framebuffer); put_text_xy("Contact Vince:",0,17,5,framebuffer); put_text_xy("vince@deater.net",0,18,9,framebuffer); put_text_xy("http://www.deater.net/weave/",0,19,9,framebuffer); dump_to_screen(framebuffer); while(get_char()==0) usleep(30); return 0; } int story(char *framebuffer) { int x; clear_framebuffer(framebuffer,0,' '); blit(phobos_sprite,framebuffer,219,0,0,40,16); /* 0 5 0 5 0 5 0 5 0 */ put_text_xy("It is the year 2025. All telemarketers",0,17,15,framebuffer); put_text_xy("and unsolicited bulk e-mailers have ",0,18,15,framebuffer); put_text_xy("been exiled to Phobos.",0,19,15,framebuffer); dump_to_screen(framebuffer); pause_a_while(7000); put_text_xy("Right before being trapped forever they",0,17,10,framebuffer); put_text_xy("manage to launch one last marketing ",0,18,10,framebuffer); put_text_xy("droid. ",0,19,10,framebuffer); dump_to_screen(framebuffer); pause_a_while(4000); x=19; while(x<37) { blit(evil_ship_sprite,framebuffer,219,x,9,3,1); dump_to_screen(framebuffer); pause_a_while(250); put_text_xy(" ",x,9,0,framebuffer); x++; } pause_a_while(2000); clear_framebuffer(framebuffer,0,' '); blit(tom_sprite,framebuffer,219,24,1,16,18); /*0 5 0 5 0 */ put_text_xy("You are Tom Bombem.",0,0,9,framebuffer); put_text_xy("You drew the short straw.",0,2,9,framebuffer); put_text_xy("So it is up to you to",0,4,9,framebuffer); put_text_xy(" fight through the ads",0,5,9,framebuffer); put_text_xy(" and destroy the evil ",0,6,9,framebuffer); put_text_xy(" marketing robot, thus",0,7,9,framebuffer); put_text_xy(" restoring harmony to ",0,8,9,framebuffer); put_text_xy(" the space lanes.",0,9,9,framebuffer); put_text_xy(" GOOD LUCK!",0,12,11,framebuffer); dump_to_screen(framebuffer); pause_a_while(20000); return 0; } int main(int argc, char **argv) { static struct termios new_tty,old_tty; char *framebuffer; int i,menu_item; char ch; framebuffer=calloc(SCREEN_WIDTH*SCREEN_HEIGHT*BYTES_PER_PIXEL,sizeof(char)); /* setup non-blocking non-echo mode */ tcgetattr(0,&old_tty); new_tty=old_tty; new_tty.c_lflag&=~ICANON; new_tty.c_cc[VMIN]=1; new_tty.c_lflag&=~ECHO; tcsetattr(0,TCSANOW,&new_tty); fcntl(0,F_SETFL,fcntl(0,F_GETFL) | O_NONBLOCK); /* clear screen */ printf("\033[2J\n"); clear_framebuffer(framebuffer,0,' '); blit(vmw_sprite,framebuffer,219,8,6,23,8); put_text_xy("A VMW Software Production",7,15,15,framebuffer); dump_to_screen(framebuffer); pause_a_while(3000); opening_screen: clear_framebuffer(framebuffer,0,' '); blit(opener_sprite,framebuffer,219,0,0,40,20); put_text_xy("Merciless Marauding Malicious Marketers",0,5,14,framebuffer); dump_to_screen(framebuffer); pause_a_while(10000); menu_item=0; put_attention_block(framebuffer,0); while(1) { put_text_xy("New Game",15,6,(menu_item==0)?13:5,framebuffer); put_text_xy("About",15,7,(menu_item==1)?13:5,framebuffer); put_text_xy("Story",15,8,(menu_item==2)?13:5,framebuffer); put_text_xy("Hi Score",15,9,(menu_item==3)?13:5,framebuffer); put_text_xy("Quit",15,10,(menu_item==4)?13:5,framebuffer); put_text_xy("F1 or 'h' for HELP",0,20,7,framebuffer); for(i=0;i<5;i++) if (i==menu_item) put_text_xy("-->",12,6+menu_item,14,framebuffer); else put_text_xy(" ",12,6+i,0,framebuffer); dump_to_screen(framebuffer); while( !(ch=get_a_char()) ) usleep(30); switch(ch) { case 'q': case 'Q': menu_item=4; ch='\n'; break; case 'i': case 'j': menu_item--; if (menu_item<0) menu_item=4; break; case 'm': case 'k': menu_item++; if (menu_item>4) menu_item=0; break; case 'h': menu_item=5; ch='\n'; break; case 10: case 13: case 32: break; } if ((ch==10) || (ch==13) || (ch==32)) { switch(menu_item) { case 0: new_game(framebuffer); break; case 1: about(framebuffer); break; case 2: story(framebuffer); break; case 3: hi_score(framebuffer); while(get_char()==0) usleep(30); break; case 4: if (verify_quit(framebuffer)) goto done_the_game; break; case 5: help(framebuffer); break; } goto opening_screen; } } done_the_game: printf("%c\n",15); set_sound(750,125); /* The default. No way I know of to save/restore */ tcsetattr(0,TCSANOW,&old_tty); return 0; }