#include "ti-82.h" shipx = TEXT_MEM ;your ship's x coordinate bulletx = TEXT_MEM+1 ;x coordinate of your bullet bullety = TEXT_MEM+2 ;y coord of your bullet aliensx = TEXT_MEM+3 ;base x coordinate of aliens aliensy = TEXT_MEM+4 ;y cood of aliens aliensdir = TEXT_MEM+7 ;direction the aliens are moving (either 1 or -1) alienaddr = TEXT_MEM+8 ;the address of the current alien sprite (word) counter = TEXT_MEM+11 ;counter for slowing the ships down hitsa1 = TEXT_MEM+12 ;hits remaining until alien 1 is dead hitsa2 = TEXT_MEM+13 ;you guessed it hitsa3 = TEXT_MEM+14 ;... hitsa4 = TEXT_MEM+15 ;... hitsa5 = TEXT_MEM+16 ;... level = TEXT_MEM+20 ;current level (word) shotx = TEXT_MEM+30 ;x coord of alien shot shoty = TEXT_MEM+31 ;y coord of alien shot score = TEXT_MEM+50 ;current score (word) randvar = TEXT_MEM+52 ;used by rand .org 0 .db "Alien 1.2",0 ld a,$8c ;set correct rom page for FIND_PIXEL OUT (2),A ; ROM_CALL(CLEARTEXT) ;doesn't seem to work as it should? ld a,44 ;initialize ship's x coord so that it starts in the middle of the screen ld (shipx),a ld a,0 ;so, instead of simply using CLEARTEXT, I have to do all this ld (counter),a ld hl,0 ld (level),hl ld (score),hl ld (shotx),hl ld (bulletx),hl CALL_(set_up_level) ;execute set_up_level subroutine keyloop: CALL_(try_shot) ;see if one of the aliens can shoot, if so, set up the shot CALL_(draw_ship) ;draw the blaster CALL_(update_bullets) ;update all of the bullets ld a,(counter) ;counter loops 0-7 inc a and %111 ;keep it 7 or below ld (counter),a cp 1 ;update aliens only if counter is 1, otherwise they go too fast CALL_Z(update_aliens) ROM_CALL(_GRBUFCPY_V) ;copy GRAPH_MEM to lcd CALL_(check_for_win) ;check to see if all of the aliens are dead ld a,(aliensy) ;if aliens get too low, you die cp 47 jr z,died ld a,0ffh ;some of this keyscanning routine was yanked from Spaze Invaders 83 by movax out (1),a ld a,0feh out (1),a in a,(1) cp 253 ;unless you get 253 back, Left isn't down jr nz,NOLEFT ld a,(shipx) cp 0 ;ship can't go off the screen jr z,NOLEFT ld hl,shipx dec (hl) ;decrement Ship's X coordinate NOLEFT: cp 251 jr nz,NORIGHT ;Right isn't down if it's not 251 ld a,(shipx) cp 88 ;can't go off the screen to the right either jr z,NORIGHT ld hl,shipx inc (hl) ;increment Ship's X coordinate NORIGHT: ld a,0ffh ;reset the port out (1),a ld a,0fdh ;load mask for Clear key (among others) out (1),a ;send it to the port in a,(1) ;get the results back cp 191 ;check for Clear's Status jr nz,NOCLR ret NOCLR: ld a,0ffh ;reset port 1 out (1),a ld a,0bfh ;load mask for 2nd key (among others) out (1),a ;send it to the port in a,(1) ;get the resultant byte cp 223 ;check to see if 2nd is down jr nz,NO2ND ld a,(bullety) ;if so, try shooting a "friendly" bullet cp 0 jr nz,NO2ND ;if bullety isn't 0 (ie there is a bullet already in the air) you can't shoot ld a,55 ld (bullety),a ;put 55 into bullety ld a,(shipx) add a,3 ;put ship's x coord + 3 into bulletx ld (bulletx),a NO2ND: ld a,0ffh ;reset the port out (1),a ld a,0bfh ;load another mask out (1),a ;"send" it to the port in a,(1) ;get something back cp 191 ;test for mode key jr nz,NOMODE CALL_(status_screen) ;if mode is pressed, show status screen NOMODE: JUMP_(keyloop) died: ld hl,$1921 ;set up coords for printing "You Died!" ld (CURSOR_X),hl ld hl,(PROGRAM_ADDR) ;get the corret offset to "You Died!" string ld de,dead add hl,de ROM_CALL(D_ZM_STR) ;print "You Died!" in menu style font ROM_CALL(_GETKEY) cp R_ARROW ;otherwise you might not see this screen jr z,died cp L_ARROW jr z,died ret check_for_win: ld hl,hitsa1 ;load address of hitsa1 (number of hits left for alien 1) ld b,5 ;there are 5 aliens check_loop: ld a,(hl) cp 0 ;see if hitsax is 0 ret nz ;if it isn't there are more aliens to hit/kill inc hl ;increment hl to get the address of the hit counter for the next alien djnz check_loop ;loop CALL_(high_beep) ;if all the aliens are dead, it will get to here and make a little beep ld hl,(level) ;then it increments the level inc hl ld (level),hl CALL_(set_up_level) ;set up new level ret status_screen: LD HL,$0803 ;set up the coords for displaying the score LD ($800C),HL ld hl,(score) ROM_CALL(D_HL_DECI) ;display score LD HL,$0303 ;set up coords for displaying "Score:" LD ($800C),HL ld hl,(PROGRAM_ADDR) ld de,scorestr add hl,de ;get offset to scorestr into hl ROM_CALL(D_ZT_STR) ;write "Score:" LD HL,$0804 ;set up the coords for displaying the level LD ($800C),HL ld hl,(level) ;put level into hl inc hl ;increment it because 0=1, 1=2, 2=3 etc ROM_CALL(D_HL_DECI) ;display level LD HL,$0304 ;set up coords for displaying "Level:" LD ($800C),HL ld hl,(PROGRAM_ADDR) ld de,levelstr add hl,de ;get offset to levelstr ROM_CALL(D_ZT_STR) ;write "Level:" ROM_CALL(_GETKEY) ;wait for key ret ;and return update_aliens: ld a,(aliensx) cp 24 ;if aliensx (x coord of leftmost alien) is 24, we've hit the right edge and need to turn around jr z,go_to_neg cp 0 ;if it is 0, it has hit the right, again we need to turn around jr z,go_to_pos jr no_dir_switch ;if it is niether of these, we don't have o do anything go_to_pos: ld a,1 ld (aliensdir),a ;make aliensdir (what is added to aliensx) 1 jr onward go_to_neg: ld a,-1 ld (aliensdir),a ;make aliensdir -1 onward: ld a,(aliensy) ;move ships down one pixel inc a ld (aliensy),a no_dir_switch: CALL_(erase_aliens) ;erase the aliens ld a,(aliensdir) ;add aliensdir to aliensx ld b,a ld a,(aliensx) add a,b ld (aliensx),a CALL_(draw_aliens) ;put the aliens back ret draw_ship: ;draws the ship at (shipx,56) ld a,(shipx) ld b,a ld c,56 ld hl,ship CALL_(PutSprite) ret set_up_level: CALL_(CLRGBU) ;clear GRAPH_MEM ld a,12 ld (aliensx),a ;starting coodrinate of aliens is 12 ld a,(level) add a,4 ld (aliensy),a ;level+4 goes into y-coord of aliens ld a,(level) inc a sra a ;level/2 cp 0 ;if it is 0, we have to make it 1 jr nz,fine ;otherwise it is fine inc a ;make it 1 fine: ld h,a ;put level/2 into hitsa(1-5) ld l,a ld (hitsa1),hl ld (hitsa3),hl ld (hitsa5),a ld a,r ;ld a with r register and 3 ;get it 3 or below ld hl,alien1 ;get address of first alien sprite add a,a ;times 2 add a,a ;times 4 add a,a ;times 8 (8 bytes per sprite) ld d,0 ld e,a ;put shipnum*8 into de add hl,de ;add that to the address of the first alien sprite ld (alienaddr),hl ;and you have the address of the current alien sprite ld a,1 ld (aliensdir),a ;set aliensdir to 1 (aliens move in a positive x direction to start with) CALL_(draw_ground) ;draw pattern on bottom CALL_(draw_aliens) ;draw the aliens ret erase_aliens: ld b,5 ;there are 5 aliens erase_loop: push bc dec b ;but they are "numbered" 0-4 ld a,b add a,a ;*2 add a,a ;*4 add a,a ;*8 add a,a ;*16 ld c,a ld a,(aliensx) add a,c ;add offset calcualted above, so we get the x coord of the proper alien (according to the loop counter) ld b,a ld a,(aliensy) ld c,a ;put aliensy into c ld hl,blank ;we are putting a blank sprite CALL_(PutSprite) ;now put it pop bc djnz erase_loop ret draw_aliens: ld hl,hitsa5 ;address of hits left on alien5 ld b,5 ;5 aliens draw_loop: push hl ld a,(hl) cp 0 jr z,dont_draw ;if there are no hits left (alien is killed) don't draw it push bc dec b ld a,b ;look at explanation for similar routine in erase_aliens (could they be consolidated into 1 to save space? go for it :) add a,a add a,a add a,a add a,a ld c,a ld a,(aliensx) add a,c ld b,a ld a,(aliensy) ld c,a ld hl,(alienaddr) CALL_(PutSprite) pop bc dont_draw: pop hl dec hl djnz draw_loop ret update_bullets: CALL_(alien_shot) ;update alien shot ld a,(bullety) cp 2 ;if bullety is 2, it is close enough to the top of the screen to call it quits JUMP_C(hit_top) ld a,(bulletx) ld b,a ld a,(bullety) ld c,a ld hl,blankbul CALL_(PutSprite) ;put blank 2x2 sprite at (bulletx,bullety) ld a,(bullety) dec a ld (bullety),a ;move bullet up a pixel ld b,a ld a,(aliensy) add a,8 cp b jr c,skip_test ;if bullety is not less than aliensy+8, we can go ahead and skip the hit test (there's nothing to hit except alien bullets which are handled later on) ld a,(bulletx) ld b,a ld a,(bullety) ld c,a CALL_(GetPixel) ;check pixel at *new* (bulletx,bullety) cp 0 jr nz,hit_alien ;if we don't get a 0 back, an alien has bee hit skip_test: ld a,(bulletx) ld b,a ld a,(bullety) ld c,a ld hl,bullet ;put bullet at (bulletx,bulety) CALL_(PutSprite) ld hl,bulletx call LD_HL_MHL ex de,hl ld hl,shotx call LD_HL_MHL call CP_HL_DE ;check if word at bulletx (contains both bulletx and bullety) equals word at shotx (contains both x and y coords as it is a word) jr z,hit_bullet ;if so, we hit another bullet ret hit_alien: ld hl,score ;add 1 to score inc (hl) CALL_(detect_which_one) ;detect which alien has been hit CALL_(make_noise) ;sound is neat jr hit_top hit_bullet: ld hl,$0000 ld (shotx),hl ;re-initialize shotx and shoty hit_top: ld a,(bulletx) ld b,a ld a,(bullety) ld c,a ld hl,blankbul CALL_(PutSprite) ;erase 2x2 square at bulletx,bullety ld hl,$0000 ld (bulletx),hl ;put 0 into both bulletx and bullety ret alien_shot: ld a,(shotx) ;same idea as the routine above that updates friendly bullets (perhaps another chance for consolidation? :) cp 0 jr z,hit_bot ld a,(shoty) cp 0 jr z,hit_bot cp 58 jr z,hit_bot ld a,(shotx) ld b,a ld a,(shoty) ld c,a ld hl,blankbul CALL_(PutSprite) ld a,(shoty) inc a ld (shoty),a ld b,a ld a,56 cp b jr nc,skip_test1 ld a,(shotx) ld b,a ld a,(shoty) inc a ld c,a CALL_(GetPixel) cp 0 jr nz,hit_ship skip_test1: ld a,(shotx) ld b,a ld a,(shoty) ld c,a ld hl,bullet CALL_(PutSprite) ret hit_bot: ld a,(shotx) ld b,a ld a,(shoty) ld c,a ld hl,blankbul CALL_(PutSprite) ld hl,$0000 ld (shotx),hl ret hit_ship: CALL_(died) inc sp ;so it will return to the shell rather than keyloop inc sp inc sp inc sp ret try_shot: ;see if any alien can shoot and set it up accordingly ld a,(shotx) cp 0 jr nz,cant_shoot ld a,(shoty) cp 0 jr nz,cant_shoot ld a,(aliensx) ld d,a CALL_(rand) ld b,d and 3 bit 2,d jr z,dont_inc inc a dont_inc: ld c,a ld hl,hitsa1 ld d,0 ld e,a add hl,de ld a,(hl) cp 0 jr z,cant_shoot ld a,c add a,a add a,a add a,a add a,a add a,b add a,3 ld (shotx),a ld a,(aliensy) add a,6 ld (shoty),a cant_shoot: ret detect_which_one: ld a,(aliensx) ld b,a ld a,(bulletx) sub b sra a sra a sra a sra a ld d,0 ld e,a ld hl,hitsa1 add hl,de ld a,(hl) cp 0 ret z dec a ld (hl),a ret high_beep: ld b,8 beep_loop: ld de,200 ;length ld hl,400 ;tone CALL_(beep) djnz beep_loop ret make_noise: ld b,8 beep_loop2: ld de,100 ;length ld hl,1000 ;tone CALL_(beep) djnz beep_loop2 ret #define P_HI %11000000 ;code to put port high #define P_LO %11111100 ;code to put port low #define C_PORT %00000000 ;addres of com port beep: ;by Eric Linenberg push af push bc di set_low: ld b,P_LO ld c,C_PORT out (c),b push hl Delay16bit1: dec hl ld a,l or h jr nz,Delay16bit1 pop hl set_high: ld b,P_HI ld c,C_PORT out (c),b push hl Delay16bit2: dec hl ld a,l or h jr nz,Delay16bit2 pop hl dec de ld a,d cp 0 jr nz,beep ei pop bc pop af ret rand: ;by Chris Busch ld a,(randvar) ld b,a ld a,0 add a,b sla b sla b add a,b sla b sla b add a,b inc a ld (randvar),a srl a ret draw_ground: ld b,12 ld e,0 gnd_loop: push bc ld c,60 ld b,e ld hl,ground push de CALL_(PutSprite) pop de ld a,e add a,8 ld e,a pop bc djnz gnd_loop ret PutSprite: ; Puts a sprite stored at (HL) at B,C (by Jimmy Mardell) ld de,(PROGRAM_ADDR) add hl,de push bc push de ld a,63 sub c ld c,a push hl push hl call $4166 ld de,$88B8 add hl,de ex de,hl pop hl ld b,(hl) inc hl ld c,(hl) inc hl push hl pop ix ex de,hl PS_NewRow: push bc ld d,(ix) inc ix push af push hl PS_NewCol: rl d ld e,a jr nc,PS_NoPixel or (hl) ld (hl),a jr PS_NextPixel PS_NoPixel: cpl and (hl) ld (hl),a PS_NextPixel: ld a,e rrca jr nc,PS_SameByte inc hl PS_SameByte: djnz PS_NewCol pop hl pop af ld de,12 add hl,de pop bc dec c jr nz,PS_NewRow pop hl pop de pop bc ret GetPixel: ;returns 0 only if the pixel is off, otherwise you get a non-zero value ld a,63 sub c ld c,a push bc call $4166 ld b,a push hl pop de ld hl,GRAPH_MEM add hl,de ld a,(hl) and b pop bc ret CLRGBU: ld hl,$88B8 ld de,$88B9 ld bc,$2FF xor a ld (hl),a ldir ret .include alienspr.txt dead: .db "You Died!",0 levelstr: .db "Level:",0 scorestr: .db "Score:",0 .end END