;################################################################## ; ; P H O E N I X F O R T I - 8 3 ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated October 28, 2000. ; ;################################################################## .include "ion.inc" #ifdef TI83P .org progstart-2 .db $BB,$6D TEXT_MEM = $8508 APD_BUF = $86EC #else .org progstart TEXT_MEM = $80c9 APD_BUF = $8265 #endif xor a jr nc,Start progdesc: .db "Phoenix 0.90",0 GFX_AREA =GRAPH_MEM ;Key Definitions G_NONE = $00 ; NO KEY G_TAN = $16 ; TAN G_XTO = $28 ; x,T,theta| G_DOWN = $01 ; DOWN G_VARS = $17 ; VARS G_ON = $29 ; ON G_LEFT = $02 ; LEFT G_PERIODE = $19 ; . G_STO = $2A ; STO> G_RIGTH = $03 ; RIGHT G_RIGHT = $03 ; RIGHT G_2 = $1A ; 2 G_LN = $2B ; LN G_UP = $04 ; UP G_5 = $1B ; 5 G_LOG = $2C ; LOG G_ENTER = $09 ; ENTER G_8 = $1C ; 8 G_SQR = $2D ; X^2 G_PLUS = $0A ; + G_LPARAN = $1D ; ( G_INVERSE = $2E ; X^-1 G_MINUS = $0B ; - G_COS = $1E ; COS G_MATH = $2F ; MATH G_TIMES = $0C ; * G_PRGM = $1F ; PRGM G_ALPHA = $30 ; ALPHA G_DIV = $0D ; / G_STAT = $20 ; STAT G_GRAPH = $31 ; GRAPH G_POWER = $0E ; ^ G_0 = $21 ; 0 G_TRACE = $32 ; TRACE G_CLEAR = $0F ; CLEAR G_1 = $22 ; 1 G_ZOOM = $33 ; ZOOM G_NEG = $11 ; (-) G_4 = $23 ; 4 G_WINDOW = $34 ; WINDOW G_3 = $12 ; 3 G_7 = $24 ; 7 G_YEDIT = $35 ; Y= G_6 = $13 ; 6 G_COMMA = $25 ; , G_2nd = $36 ; 2nd G_9 = $14 ; 9 G_SIN = $26 ; SIN G_MODE = $37 ; MODE G_RPARAN = $15 ; ) G_MATRIX = $27 ; MATRIX G_DEL = $38 ; DEL ;############## Include variable and data structure definitions ;################################################################## ; ; Phoenix-Z80 (Variable and data structure defintions) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated November 24, 2000. ; ;################################################################## ;############## Player bullet structure definition pb_type =0 pb_dmg =1 pb_x =2 pb_w =3 pb_y =4 pb_h =5 pb_img =6 pb_data =8 pb_size =10 pb_num =16 ;############## Enemy structure definition e_type =0 ; Type (offset in jump table) e_phase =1 ; Phase of movement (enemy-specific use) e_timer =2 ; Timer (enemy-specific use) e_x =3 ; X coordinate e_w =4 ; Width e_y =5 ; Y coordinate e_h =6 ; Height e_pwr =7 ; Shield strength e_img =8 ; Image pointer (not required) e_data =10 ; Misc. data (enemy-specific use) e_size =12 e_num =18 ;############## Enemy bullet structure definition eb_type =0 eb_dmg =1 eb_x =2 eb_w =3 eb_y =4 eb_h =5 eb_data =6 eb_size =10 eb_num =15 ;############## Screen side data sidesdata =$AA70 leftsidecoord =$AB70 leftsidevel =$AB71 rightsidecoord =$AB72 rightsidevel =$AB73 ;############## Permanent variables perm_var_start =TEXT_MEM posqueue =TEXT_MEM player_y =TEXT_MEM+20 player_x =TEXT_MEM+21 enemies_left =TEXT_MEM+22 level =TEXT_MEM+23 player_pwr =TEXT_MEM+24 player_cash =TEXT_MEM+25 weapon_upgrade =TEXT_MEM+27 weapon_2 =TEXT_MEM+28 weapon_3 =TEXT_MEM+29 weapon_4 =TEXT_MEM+30 weapon_5 =TEXT_MEM+31 fire_counter =TEXT_MEM+32 chosen_weapon =TEXT_MEM+33 game_timer =TEXT_MEM+34 pattern =TEXT_MEM+36 companion_pwr =TEXT_MEM+38 companion_y =TEXT_MEM+39 companion_x =TEXT_MEM+40 companion_img =TEXT_MEM+41 difficulty =TEXT_MEM+43 which_shot =TEXT_MEM+44 time_score =TEXT_MEM+45 bonus_score =TEXT_MEM+47 completed =TEXT_MEM+49 speed =TEXT_MEM+50 perm_var_size =51 ;############## Temporary variables misc_flags =TEXT_MEM+111 data_addr =TEXT_MEM+112 ext_level =TEXT_MEM+114 level_addr =TEXT_MEM+115 doing_enemies =TEXT_MEM+117 beb_image =TEXT_MEM+118 temp =TEXT_MEM+120 shop_item =TEXT_MEM+121 test_coords =TEXT_MEM+122 timer =TEXT_MEM+126 jp2nd =TEXT_MEM+127 ;############## Initialization start: ld (_label-2),sp ;ld a,(INT_STATE) ;or a ;jp nz,interrupt_installed ld de,saferam1+473 ; Save data after GRAPH_MEM ld hl,plotsscreen+768 ld bc,256 ldir ld hl,timer_interrupt ld de,$8282 ld bc,timer_interrupt_end-timer_interrupt ldir ld a,$83 ld i,a ld hl,$8300 ld (hl),$82 ld bc,256 call OTH_FILL im 2 ld (iy+13),0 ld hl,level_table ld (level_addr),hl call restore_game ;############## Title screen redraw_title: bcall(_clrlcdf) ld hl,title_main show_title: call display_hl_msgs title_loop: bcall(_getcsc) cp G_2 jr z,show_contact cp G_3 jr z,show_instructions cp G_1 jp z,start_new_game cp G_CLEAR jr z,game_exit cp G_ALPHA jr z,show_highs cp G_DEL jr nz,title_loop game_exit: di im 1 call restore_memory OTH_EXIT: ld a,05h ; set x inc mode call DISP_DELAY ; out (16),a ; ld sp,0 _label: ei bcall(_clrlcdf) ret interrupt_installed: bcall(_clrlcdf) ld (currow),de ld hl,int_err bcall(_putc) jr OTH_EXIT show_highs: call no_high_score jr redraw_title show_contact: ld hl,title_contact jr show_title show_instructions: ld hl,title_instructions jr show_title ;############## Title screen messages int_err: .db "ERROR: You must" .db "remove installed" .db "interrupts.",0 title_main: .db " Phoenix 0.90",0 .db " Programmed by",0 .db "Patrick Davidson",0 .db "Ported by Mouse",0 .db "Mouse47@Aol.Com",0 .db " 1 - Start Game",0 .db "2 - Contact Info",0 .db "3 - Instructions",0 .db -1 title_instructions: .db "Arrows Move Ship",0 .db "#s Select Weapon",0 .db "2nd Fires Weapon",0 .db "MODE Save & Exit",0 .db -1 title_contact: .db "E-Mail: ",0 .db " pad@calc.org",0 .db "World Wide Web: ",0 .db " pad.calc.org ",0 .db -1 ;############## Initialize a new game start_new_game: call initialize_game pre_main_loop: ld hl,-6 add hl,sp ld (collision_done+1),hl ;############## Game main loop main_loop: ld hl,(game_timer) inc hl ld (game_timer),hl bit 0,l jr z,time_elapsed ld hl,(time_score) ld a,h or l jr z,time_elapsed dec hl ld (time_score),hl time_elapsed: call clear_buffer ; Prepare main display buffer call do_player ; Move and draw player call do_companion ; Move and draw companion ship call enemies ; Move and draw enemies call player_bullets ; Move and draw player bullets call enemy_bullets ; Move and draw enemy bullets call hit_player ; Collisions involving player call prepare_indicator ; Prepare the shield indicator call synchronize ; Wait for next 1/30 second cycle call display_screen ; Copy display buffer to video memory call hit_enemies ; Collisions btw. bullets & enemies call handle_input ; Process control keys ld a,(enemies_left) or a call z,load_level jr main_loop ;############## TI-82 library restore_memory: ld hl,saferam1+473 ; Restore data after GRAPH_MEM ld de,plotsscreen+768 ld bc,256 ldir ret DISP_DELAY: push ix pop ix ret OTH_CLEAR: ld (hl),0 OTH_FILL: ld d,h ld e,l inc de ldir ret OTH_ARROW: ld a,%00111111 out (1),a push ix pop ix in a,(1) or %00001111 ld b,a ld a,%01111110 out (1),a push ix pop ix in a,(1) and b ret ;############## Include remainder of game files ;################################################################## ; ; Phoenix-Z80 (low-level support routines) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last modified October 21, 2000. ; ;################################################################## ;############## Synchronization synchronize: ld hl,timer ld a,(speed) cp (hl) jr c,too_slow loop_wait: cp (hl) ; Test value of 4 - (timer) jr nc,loop_wait ; NC : timer <= 4 ld (hl),0 ;#ifdef __TI82__ ; ld a,(curcont) ; add a,$1e ; or $c0 ; out ($10),a ;#else ; ld a,(curcont) ; out (2),a ;#endif ret too_slow: ld (hl),0 ;#ifdef __TI82__ ; ld a,(curcont) ; add a,$16 ; or $c0 ; out ($10),a ;#else ; ld a,(curcont) ; dec a ; dec a ; out (2),a ;#endif ret timer_interrupt: push af push hl ld hl,timer inc (hl) pop hl pop af jp $38 timer_interrupt_end: ;############## Low-level support routines ADD_HL_A: add a,l ld l,a ret nc inc h ret FAST_RANDOM: push hl ld hl,0 ld a,(hl) inc hl xor (hl) inc hl xor (hl) inc hl res 6,h ld (FAST_RANDOM+2),hl pop hl ret ;################################################################## ; ; Phoenix-82 (New game initialization) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated October 21, 2000. ; ;################################################################## difficulty_msg: .db "Choose Difficulty",0 .db 0 .db "3) Beginner",0 .db "4) Intermediate",0 .db "5) Advanced",0 .db -1 speed_msg: .db "Choose Speed",0 .db 0 .db "6) Slow",0 .db "7) Fast",0 .db -1 ;############## Prepare new game initialize_game: bcall(_clrlcdf) ld hl,difficulty_msg call display_hl_msgs dsel_loop: bcall(_getcsc) cp G_3 jr z,play_easy cp G_4 jr z,play_medium cp G_5 jr z,play_hard cp G_DEL jp z,game_exit cp G_CLEAR jp z,game_exit cp G_MODE jr nz,dsel_loop jp game_exit play_hard: ld a,20 ld de,15000 jr install_game_variables play_medium: ld a,50 ld de,5000 jr install_game_variables play_easy: ld a,100 ld de,0 install_game_variables: push de ld hl,perm_var_start ld bc,perm_var_size-1 call OTH_CLEAR pop de ld (bonus_score),de ld (difficulty),a ld hl,player_y ld (hl),70 ; Player Y coord = 70 inc hl ld (hl),60 ; Player X coord = 60 inc hl inc hl inc hl ld (hl),16 ; Status of player's ship ld hl,19000 ld (time_score),hl bcall(_clrlcdf) ld hl,speed_msg call display_hl_msgs ssel_loop: bcall(_getcsc) cp G_6 jr z,play_slow cp G_7 jr z,play_fast cp G_DEL jp z,game_exit cp G_CLEAR jp z,game_exit cp G_MODE jr nz,ssel_loop jp game_exit play_slow: ld a,3 ld de,0 jr speed_chosen play_fast: ld a,2 ld de,5000 speed_chosen: ld (speed),a ld hl,(bonus_score) add hl,de ld (bonus_score),hl ld hl,permanent_data_start ld bc,game_data_end-permanent_data_start-1 jp OTH_CLEAR ;################################################################## ; ; Phoenix-82 (Screen display routines) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated October 28, 2000. ; ;################################################################## ;############## Display -1 terminated list of strings at (HL) display_hl_msgs: ld de,0 show_loop: ld (currow),de push de bcall(_puts) pop de ld a,(hl) inc a ret z inc e jr show_loop ;############## Prepares on-screen shield indicator prepare_indicator: ld a,(player_pwr) or a ret z ret m ld b,a ld hl,GFX_AREA+1024-3 ld de,-16 loop_ind: set 0,(hl) add hl,de set 0,(hl) add hl,de set 0,(hl) add hl,de set 0,(hl) add hl,de djnz loop_ind ret ;############## Clears screen buffer clear_buffer: ld (smc_savesp+1),sp ld hl,0 ld sp,GFX_AREA+1024 ld b,63 loop_super_clear: push hl push hl push hl push hl push hl push hl push hl push hl djnz loop_super_clear smc_savesp: ld sp,0 ld hl,GFX_AREA+2 ld bc,11 jp OTH_CLEAR ;############## Display entire screen from buffer display_screen: ld a,$80 ; 7 out ($10),a ; 11 ld hl,GRAPH_MEM+2-16-(-(16*64)+1) ; 10 ld a,$20 ; 7 ld c,a ; 4 ; 43 fastCopyAgain: ld b,64 ; 7 inc c ; 4 ld de,-(16*64)+1 ; 10 out ($10),a ; 11 add hl,de ; 11 ld de,15 ; 10 fastCopyLoop: add hl,de ; 11 inc hl ; 6 ret c ; 5 ld a,(hl) ; 7 out ($11),a ; 11 djnz fastCopyLoop ; 13/8 ; 3392 ld a,c ; 4 cp $2B+1 ; 7 jr nz,fastCopyAgain; 12/7 ret ; 11 ; 18 ;################################################################## ; ; Phoenix-Z80 ("sprite" drawing routine) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated September 26, 2000. ; ;################################################################## MIN_Y =32 MAX_Y =96 clip_top: pop hl ; HL -> image data inc hl add a,(hl) ; A = bottom Y coordinate + 1 sub MIN_Y+1 ; A = # of lines past 32 ret c inc a ; A = number of lines on screen ld b,a ; B = number of lines to draw sub (hl) neg ; A = number of lines skipped inc a ; A = number of bytes to skip add a,l jr nc,ctad inc h ctad: ld l,a ; HL -> start of image data to use ld a,d ; A = X coordinate ex de,hl ; DE -> start of image data to use smc_gfxmem_start: ld hl,GFX_AREA rra rra rra and 15 add a,l ld l,a ; HL -> screen address jr nc,drw_spr_main inc h jr drw_spr_main drw_spr: ld a,d ; A = X coordinate and 7 ld b,a add a,a add a,b ld (jumpintable+1),a ; Save selected shift amount push hl ; Save sprite image pointer ld b,0 smc_gfxmem_minus512: ld hl,GFX_AREA-512 ; HL -> start of buffer ld a,e cp MIN_Y jr c,clip_top ld (smc_start_y_coord+1),a add a,a ; A = Y * 2 add a,a rl b ; BA = Y * 4 add a,a rl b ; BA = Y * 8 add a,a rl b ; BA = Y * 16 ld c,d srl c srl c srl c ; C = X / 8 or c ld c,a add hl,bc ; HL = Screen address ex de,hl ; DE = Screen address pop hl inc hl ld b,(hl) ; B = height inc hl ; HL -> image ex de,hl ; HL -> screen, DE -> image smc_start_y_coord: ld a,0 ; Self-modification stores Y here cp MAX_Y ret nc add a,b ; A = maximum Y coordinate cp MAX_Y jr c,drw_spr_main sub b sub MAX_Y neg ld b,a drw_spr_main: ld c,0 scf ccf jumpintable: jr table table: jp routine0 jp routine1 jp routine2 jp routine3 jp routine4 jp routine5 jp routine6 routine7: inc hl routine7l: ld a,(de) ;7 inc de ;6 add a,a ;4 rl c ;8 or (hl) ;7 ld (hl),a ;7 dec hl ;6 ld a,(hl) ;7 or c ;4 ld (hl),a ;7 ld a,b ;4 ld bc,17 ;10 add hl,bc ;11 ld c,b ;4 ld b,a ;4 djnz routine7l ret routine0: ld c,16 ;7 routine0l: ld a,(de) ;7 inc de ;6 or (hl) ;7 ld (hl),a ;7 ld a,c ;4 add a,l ;4 ld l,a ;4 jp nc,done0 ;10 inc h ;4 done0: djnz routine0l ret routine1: ld a,(de) ;7 inc de ;6 rra ;4 rr c ;8 or (hl) ;7 ld (hl),a ;7 inc hl ;6 ld a,(hl) ;7 or c ;4 ld (hl),a ;7 ld a,b ;4 ld bc,15 ;10 add hl,bc ;11 ld c,b ;4 ld b,a ;4 djnz routine1 ret routine2: ld a,(de) ;7 inc de ;6 rrca ;4 rrca ;4 ld c,a ;4 and $3F ;7 or (hl) ;7 ld (hl),a ;7 ld a,c ;4 and $C0 ;7 inc hl ;6 or (hl) ;7 ld (hl),a ;7 ld a,15 ;7 add a,l ;4 ld l,a ;4 jp nc,done2 ;10 inc h ;4 done2: djnz routine2 ret routine3: ld a,(de) ;7 inc de ;6 rrca ;4 rrca ;4 rrca ;4 ld c,a ;4 and $1F ;7 or (hl) ;7 ld (hl),a ;7 ld a,c ;4 and $E0 ;7 inc hl ;6 or (hl) ;7 ld (hl),a ;7 ld a,15 ;7 add a,l ;4 ld l,a ;4 jp nc,done3 ;1 inc h ;4 done3: djnz routine3 ret routine4: ld a,(de) ;7 inc de ;6 rrca ;4 rrca ;4 rrca ;4 rrca ;4 ld c,a ;4 and $0F ;7 or (hl) ;7 ld (hl),a ;7 ld a,c ;4 and $F0 ;7 inc hl ;6 or (hl) ;7 ld (hl),a ;7 ld a,15 ;7 add a,l ;4 ld l,a ;4 jp nc,done4 ;10 inc h ;4 done4: djnz routine4 ;13 ret routine6: ld a,(de) ;7 inc de ;6 rlca ;4 rlca ;4 ld c,a ;4 and $03 ;7 or (hl) ;7 ld (hl),a ;7 ld a,c ;4 and $FC ;7 inc hl ;6 or (hl) ;7 ld (hl),a ;7 ld a,15 ;7 add a,l ;4 ld l,a ;4 jp nc,done6 ;10 inc h ;4 done6: djnz routine6 ;13 ret routine5: ld a,(de) ;7 inc de ;6 rlca ;4 rlca ;4 rlca ;4 ld c,a ;4 and $07 ;7 or (hl) ;7 ld (hl),a ;7 ld a,c ;4 and $F8 ;7 inc hl ;6 or (hl) ;7 ld (hl),a ;7 ld a,15 ;7 add a,l ;4 ld l,a ;4 jp nc,done5 ;10 inc h ;4 done5: djnz routine5 ;13 ret ;################################################################## ; ; Phoenix-82 (Player handling) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated September 29, 2000. ; ;################################################################## ;############## Movement, Firing (by OTH_ARROW) and ship display autofire: bit 5,c jr nz,fire_done ld hl,fire_counter inc (hl) ld a,(hl) cp 4 jr nz,fire_done ld (hl),0 push bc call player_shoot pop bc jr fire_done do_player: call OTH_ARROW ld c,a ld a,(weapon_upgrade) or a jr nz,autofire ld hl,jp2nd bit 5,c jr nz,notpressed ld a,(hl) ld (hl),1 or a push bc call z,player_shoot pop bc jr fire_done notpressed: ld (hl),0 fire_done: ld hl,player_y rr c jr c,no_down ld a,(hl) add a,1 cp 90 jr z,no_down ld (hl),a no_down: inc hl rr c jr c,no_left ld a,(hl) add a,-2 cp 14 jr z,no_left ld (hl),a no_left: rr c jr c,no_right ld a,(hl) add a,2 cp 106 jr z,no_right ld (hl),a no_right: ld d,(hl) dec hl rr c jr c,no_up ld a,(hl) add a,-1 cp 68 jr z,no_up ld (hl),a no_up: ld de,(player_y) ld hl,img_player_ship_normal ld a,(player_pwr) cp 4 jp nc,drw_spr ld hl,img_player_ship_damaged jp drw_spr ;############## Control keys (GET_KEY) handle_input: bcall(_getcsc) cp G_MODE jp z,game_save cp G_DEL jp z,game_exit ld hl,chosen_weapon cp G_5 jr z,select_weapon_5 cp G_4 jr z,select_weapon_4 cp G_3 jr z,select_weapon_3 cp G_2 jr z,select_weapon_2 sub G_1 ret nz ld (hl),a ret select_weapon_2: ld a,(weapon_2) or a ret z ld (hl),a ret select_weapon_3: ld a,(weapon_3) or a ret z ld (hl),2 ret select_weapon_4: ld a,(weapon_4) or a ret z ld (hl),3 ret select_weapon_5: ld a,(weapon_5) or a ret z ld (hl),4 ret ;################################################################## ; ; Phoenix-Z80 (Player firing) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated September 17, 2000. ; ;################################################################## ;############## Bullet descriptions bullet_data_normal: .db 6,2,2,6 bullet_data_enhanced: .db 3,4,4,8 bullet_double_left: .db 9,2,3,7 bullet_double_right: .db 12,2,3,7 bullet_triple_left: .db 15,3,4,4 bullet_triple_right: .db 18,3,4,4 bullet_triple_center: .db 21,4,4,4 bullet_quad_left: .db 24,8,3,5 bullet_quad_right: .db 27,8,3,5 bullet_super: .db 33,20,5,7 bullet_swing_left: .db 36,8,4,4 bullet_swing_right: .db 39,8,4,4 ;############## Main shooting routine player_shoot: ld a,(chosen_weapon) or a jr z,player_shoot_1 dec a jr z,player_shoot_2 dec a jr z,player_shoot_3 dec a jr z,player_shoot_4 player_shoot_5: ld hl,bullet_super ld a,(weapon_5) xor 2 ld (weapon_5),a rrca and 1 add a,3 ld c,a call fire_bullet ld hl,bullet_swing_left ld c,0 call fire_bullet ld hl,bullet_swing_right ld c,8 jr fire_bullet player_shoot_4: ld a,(weapon_4) xor 128 ld (weapon_4),a ld a,0 jp m,ps4l ld a,7 ps4l: ld (whichside+1),a add a,2 ld c,a ld hl,bullet_quad_right call fire_bullet whichside: ld c,0 ld hl,bullet_quad_left jr fire_bullet player_shoot_3: ld hl,bullet_triple_center ld c,4 call fire_bullet ld hl,bullet_triple_left ld c,2 call fire_bullet ld hl,bullet_triple_right ld c,6 jr fire_bullet player_shoot_2: ld hl,bullet_double_left ld c,1 call fire_bullet ld hl,bullet_double_right ld c,8 jr fire_bullet player_shoot_1: ld a,(weapon_upgrade) or a jr nz,shoot_enhanced ld hl,bullet_data_normal ld c,5 jr fire_bullet shoot_enhanced: ld c,4 ld hl,bullet_data_enhanced ;############## Fire bullet described at (HL) with X = C - 2 fire_bullet: push hl ld hl,pb_array ; Locate unused bullet in HL ld b,pb_num ld de,pb_size loop_search_bullet: ld a,(hl) or a jr z,found_bullet add hl,de djnz loop_search_bullet pop hl ret found_bullet: ex de,hl pop hl ;############## Copy bullet data, HL->description, DE->data, C-2 = X offset bullet_copy: ldi ; Type ldi ; Amount of damage ld a,(player_x) add a,c ld (de),a ; X-coordinate inc de ldi ; Width ld a,(player_y) add a,-3 ld (de),a ; Y-coordinate inc de ldi ; Height inc de inc de ld a,7 ld (de),a ; Data ret ;################################################################## ; ; Phoenix-Z80 (Player bullet code) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated September 17, 2000. ; ;################################################################## ;############## Player bullet routine ; ; Calls the code specified by the bullet 'type'. The 'type', which must ; be a multiple of 3, is an index into the table of jumps for bullet code. ; Bullet routines should move the bullet and draw its image. They are ; called with HL pointing to the bullet entry, and can change all registers. player_bullets: ld hl,pb_array ld b,pb_num loop_player_bullets: ld a,(hl) ld (do_player_bullet+1),a push hl push bc call do_player_bullet pop bc pop hl ld de,pb_size add hl,de djnz loop_player_bullets ret do_player_bullet: jr point_to_pbullet_code point_to_pbullet_code: ;############## Bullet routine table starts here no_pbullet: ld (hl),0 ret jp enhanced_bullet ;3 jp standard_bullet ;6 jp double_left ;9 jp double_right ;12 jp triple_right ;15 jp triple_left ;18 jp triple_center ;21 jp quad_left ;24 jp quad_right ;27 jp quad_goup ;30 jp super_shot ;33 jp swing_left ;36 ;39 ;############## Swinging right bullet swing_right: push hl inc hl inc hl dec (hl) jr z,destroy_bullet_stack ld de,6 add hl,de dec (hl) ld a,(hl) sra a pop hl ld bc,img_quad_bullet jr common_bullet ;############## Swinging left bullet swing_left: push hl inc hl inc hl inc (hl) ld a,124 cp (hl) jr z,destroy_bullet_stack ld de,6 add hl,de dec (hl) ld a,(hl) sra a pop hl ld bc,img_quad_bullet jr common_bullet destroy_bullet_stack: pop hl ld (hl),0 ret ;############## Super-powered bullet super_shot: ld a,-5 ld bc,img_player_bullet_5 jr common_bullet ;############## Companion ship's weapons companion_shots: quad_goup: ld a,-4 ld bc,img_quad_bullet jr common_bullet ;############## Quadruple shot right quad_right: ld a,(game_timer) rrca jr c,quad_goup inc hl inc hl inc (hl) ld a,(hl) cp 124 jr quad_x_updated ;############## Quadruple shot left quad_left: ld a,(game_timer) rrca jr c,quad_goup inc hl inc hl dec (hl) ld a,(hl) or a quad_x_updated: ld d,a ld a,-4 ld bc,img_quad_bullet jr nz,common_after_x_done jr destroy_bullet_x ;############## Triple shot center triple_center: ld a,-5 ld bc,img_player_bullet_3 jr common_bullet ;############## Double shot right side double_right: ld a,-4 ld bc,img_player_bullet_2r jr common_bullet ;############## Double shot left side double_left: ld a,-4 ld bc,img_player_bullet_2l jr common_bullet ;############## Standard bullet standard_bullet: ld bc,img_player_bullet_0 jr common_bullet_2 ;############## Enhanced bullet enhanced_bullet: ld bc,img_player_bullet_1 common_bullet_2: ld a,-2 common_bullet: inc hl inc hl ld d,(hl) common_after_x_done: inc hl inc hl add a,(hl) cp 24 jr c,destroy_bullet ld e,a ld (hl),e push bc pop hl jp drw_spr destroy_bullet: ld bc,-4 add hl,bc ld (hl),0 ret ;############## Triple shot right side triple_right: inc hl inc hl ld d,(hl) dec d jr z,destroy_bullet_x dec d jr z,destroy_bullet_x common_triple: ld (hl),d ld a,-4 ld bc,img_player_bullet_3 jr common_after_x_done destroy_bullet_x: dec hl dec hl ld (hl),0 ret ;############## Triple shot left side triple_left: inc hl inc hl ld a,(hl) add a,2 ld d,a cp 124 jr nc,destroy_bullet_x jr common_triple ;################################################################## ; ; Phoenix-Z80 (Enemies) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated November 24, 2000. ; ;################################################################## ;############## Enemy routines ; ; Calls the code specified by the enemy 'type'. The 'type', which must ; be a multiple of 3, is an index into the table of jumps for enemy code. ; Enemy routines should move the enemy and draw its image. They are ; called with HL pointing to the enemy entry, and can change all registers. enemies: xor a ;Reset list of used swoop patterns ld (misc_flags),a ;(used to prevent multiple entries ;of the same pattern in one frame) dec a ;Set enemy-processing flag (used by ld (doing_enemies),a ;code handling both enemies and ;something else to tell which it is ;being called for) ld hl,e_array ld b,e_num loop_enemies: ld a,(hl) ld (do_enemy+1),a push hl push bc call do_enemy pop bc pop hl ld de,e_size add hl,de djnz loop_enemies ret jp exploding_enemy ; This is offset -5 do_enemy: jr point_to_enemy_code point_to_enemy_code: ;############## Enemy routine table starts here no_enemy: ld (hl),0 ret jp standard_enemy ;3 jp figure_eight ;6 jp figure_eight_waiting ;9 jp standard_boss ;12 jp bounce_enemy ;15 jp advanced_boss ;18 jp spinner ;21 jp spinner_rampage ;24 jp super_boss ;27 jp operator_wait ;30 jp operator_main ;33 jp swooping_enemy_wait ;36 jp swoop_down ;39 jp swoop_horiz ;42 jp swoop_up ;45 ;############## Swooping horizontally ; ; e_phase holds X velocity ; e_timer holds X coordinate of destinatin swoop_horiz: call swoop_draw inc hl ;HL -> e_phase ld a,(hl) ;A = X velocity inc hl inc hl ;HL -> X coordinate add a,(hl) ld (hl),a ;Update X coordinate dec hl cp (hl) ;Compare X coordinate to destinatio ret nz dec hl dec hl ld (hl),45 ret ;############## Swooping enemy going up swoop_up: call swoop_draw ld de,e_y add hl,de dec (hl) ret nz inc hl ld (hl),0 ld de,-e_h add hl,de ld (hl),36 ret ;############## Swooping down ; ; e_phase holds Y coordinate of destination of this movement ; e_phase will hold X velocity for the horizontal movement ; e_timer holds X coordinate of destination of horizontal movement swoop_down: call swoop_draw ;Handle display ld de,e_y push hl add hl,de ;HL -> e_y inc (hl) ;Increment Y coordinate ld a,(hl) ;Load Y coordinate into A pop hl ;HL -> e_type inc hl ;HL -> e_phase cp (hl) ;Compare to destination coordinate ret nz ;Exit if not there inc hl ld a,(hl) ;A = X destination dec hl ld (hl),2 ;Initially set X velocity to 1 bit 6,a ;Check if X destination >= 64 jr nz,swoop_not_left ;If so, not going lef ld (hl),-2 ;If going left, change XV to -1 swoop_not_left: dec hl ld (hl),42 ;Set type to horizontal movement ret ;############## Draw swooping enemy at any point and handle firing ; ; called with HL -> e_y ; returns with HL unchanged swoop_draw: push hl inc hl inc hl inc hl ;HL -> X coordinate ld d,(hl) ;D = X coordinate call FAST_RANDOM ;randomly decide whether to fire and %11011011 jr nz,swoop_no_shoot inc (hl) ;temporarily increase X coord to inc (hl) ;fire from right position push de push hl call fire_big_bullet pop hl pop de dec (hl) dec (hl) swoop_no_shoot: inc hl inc hl ;HL -> Y coordinate ld e,(hl) ;E = Y coordinate ld a,(game_timer) ;Choose image based on timer rrca jr c,swoop_stage2 swoop_stage1: ld hl,swoop_l_stage1 push de call drw_spr pop de ld a,8 add a,d ld d,a ld hl,swoop_r_stage1 call drw_spr pop hl ret swoop_stage2: ld hl,swoop_l_stage2 push de call drw_spr pop de ld a,8 add a,d ld d,a ld hl,swoop_r_stage2 call drw_spr pop hl ret ;############## Swooping enemy waiting to enter swooping_enemy_wait: ld a,(game_timer) and 15 ret nz call FAST_RANDOM ;Choose pattern (0 - 3) and 3 add a,a add a,a ld (smc_hl_storage+1),hl ld hl,swoop_data call ADD_HL_A ;HL -> pattern data ld de,misc_flags ;DE -> flags of which patterns used ld a,(de) and (hl) ;Check flag; if already set, exit ret nz ;since this pattern already entered ld a,(de) or (hl) ld (de),a ;set the flag smc_hl_storage: ld de,0 ;DE -> enemy data ld a,39 ld (de),a ;set type to swooping down inc hl ;HL -> entry inc de ;DE -> enemy info byte 1 ldi ;copy Y destination ldi ;copy X destination ldi ;copy X entry ldi ex de,hl ;HL -> e_w ld (hl),11 ;width = 11 inc hl ld (hl),2 ;Y = 2 inc hl ld (hl),8 ;height = 8 ret ;############## Swooping enemy data ; ; Flag bit mask, Y destination, X destination, X entry swoop_data: .db 1,59,102,14 .db 2,50,30,90 .db 4,41,78,42 .db 8,32,54,66 ;############## Operator main code operator_main: call rampage_move push hl ld hl,img_operator call drw_spr pop hl jp semi_aim_shoot_nodraw ;############## Operating waiting operator_wait: ld (hl),33 inc hl ld (hl),1 inc hl ld (hl),1 inc hl call FAST_RANDOM and 63 add a,28 ld (hl),a inc hl ld (hl),8 inc hl call FAST_RANDOM and 15 ld (hl),a inc hl ld (hl),8 inc hl ld (hl),40 ret ;############## Super-boss sboss_shoot: ld a,13 add a,(hl) ld (hl),a push hl call fire_big_bullet pop hl ld a,-13 add a,(hl) ld (hl),a push hl call fire_big_bullet pop hl jr sboss_shot super_boss: call boss_move ld a,(game_timer) and %111111 jr z,sboss_shoot sboss_shot: ld d,(hl) inc hl inc hl ld e,(hl) push de ld hl,img_boss3_left call drw_spr pop de ld a,9 add a,d ld d,a ld hl,img_boss3_right jp drw_spr ;############## Rampaging spinning enemy spinner_rampage: call rampage_move inc hl inc hl inc hl ; HL -> e_img call spinner_image dec hl dec hl dec hl ; HL -> e_y jp semi_aim_shoot_nodraw ;############## Rampaging movement rampage_move: inc hl ld b,(hl) ; E = XV inc hl ld c,(hl) ; D = YV inc hl ld a,(hl) add a,b ; A = new X ld (hl),a ld d,a ; D = new X cp 16 jr c,rampage_right cp 40 jr z,rampage_choosex cp 71 jr z,rampage_choosex cp 93 jr z,rampage_choosex cp 105 jr nc,rampage_left rampage_xdone: inc hl inc hl ; HL -> e_y ld a,(hl) add a,c ; A = new Y ld (hl),a ld e,a ; E = new X cp 41 jr c,rampage_down cp 51 jr z,rampage_choosey cp 59 jr nc,rampage_up rampage_ydone: push hl dec hl dec hl dec hl ; HL -> YV ld (hl),c dec hl ; HL -> VV ld (hl),b pop hl ; HL -> e_y ret rampage_choosex: call FAST_RANDOM rrca jr c,rampage_left rampage_right: ld b,1 jr rampage_xdone rampage_left: ld b,-1 jr rampage_xdone rampage_choosey: call FAST_RANDOM rrca jr c,rampage_up rampage_down: ld c,1 jr rampage_ydone rampage_up: ld c,-1 jr rampage_ydone ;############## Spinning enemy spinner: ld a,(enemies_left) cp 9 jr nc,no_rampage ld (hl),24 inc hl ld (hl),1 inc hl ld (hl),1 dec hl dec hl jr spinner_rampage no_rampage: inc hl ; HL -> e_phase ld a,(hl) ld (which_phase+1),a inc hl ; HL -> e_timer inc (hl) ld a,(hl) rrca jr nc,no_move_enemy_s cp $88 jr nz,not_s_phase_end ld (hl),0 dec hl ; HL -> e_phase ld a,(hl) inc a inc a inc a inc a and 12 ld (hl),a inc hl ; HL -> e_timer not_s_phase_end: inc hl ; HL -> e_x push hl call which_phase spinner_final: ld e,(hl) ; E = e_y pop bc ; BC -> e_x ld a,(bc) ld d,a ; D = x coord inc hl inc hl inc hl ; E -> e_img call spinner_image dec hl dec hl dec hl call FAST_RANDOM and %01110110 ret nz jp semi_aim_shoot_now no_move_enemy_s: inc hl ; HL -> e_x push hl inc hl inc hl jr spinner_final spinner_image: push hl bcall(_ldhlind) ; HL = e_img push hl call drw_spr pop hl ; HL = e_img ld de,10 add hl,de ; HL -> next image ld a,(hl) ; Test for end of list inc a jr nz,spinner_image_ok ld de,-40 add hl,de ; Go back to start of list spinner_image_ok: ex de,hl pop hl ; HL -> img ld a,(game_timer) rrca ret c ld (hl),e inc hl ; HL -> e_img + 1 ld (hl),d dec hl ; HL -> e_img ret ;############## Advanced boss aboss_shoot: ld a,11 add a,(hl) ld (hl),a push hl call fire_big_bullet pop hl ld a,-11 add a,(hl) ld (hl),a push hl call fire_big_bullet pop hl jr aboss_shot advanced_boss: call boss_move ld a,(game_timer) and %111111 jr z,aboss_shoot aboss_shot: ld d,(hl) inc hl inc hl ld e,(hl) push de ld hl,img_boss2_left call drw_spr pop de ld a,8 add a,d ld d,a ld hl,img_boss2_right jp drw_spr ;############## Boss boss_shoot: ld a,14 add a,(hl) ld (hl),a push hl call fire_aimed_bullet pop hl ld a,-14 add a,(hl) ld (hl),a push hl call fire_aimed_bullet pop hl jr boss_shot standard_boss: call boss_move ld a,(game_timer) and %111111 jr z,boss_shoot boss_shot: ld d,(hl) inc hl inc hl ld e,(hl) push de ld hl,img_boss_left call drw_spr pop de ld a,8 add a,d ld d,a ld hl,img_boss_right jp drw_spr boss_move: inc hl ld a,(hl) or a jr z,boss_descending inc hl dec (hl) jr nz,boss_no_reverse neg dec hl ld (hl),a inc hl ld (hl),90 boss_no_reverse: inc hl add a,(hl) ld (hl),a ret boss_descending: inc hl dec (hl) jr nz,not_entered dec hl ld (hl),-1 inc hl ld (hl),83 not_entered: inc hl inc hl inc hl inc (hl) dec hl dec hl ret ;############## Figure-eight waiting code figure_eight_waiting: inc hl dec (hl) ret nz dec hl ld (hl),6 inc hl ld (hl),32 inc hl ld (hl),0 inc hl ld a,(level) cp SPLIT_LEVEL jr nz,nosplit bit 0,b jr nz,nosplit ld (hl),72 jr f8split nosplit: ld (hl),16 f8split: inc hl ld (hl),8 inc hl ld (hl),24 inc hl ld (hl),8 inc hl ld (hl),13 inc hl ld bc,3 jp OTH_CLEAR ;############## Figure-eight enemy code figure_eight: inc hl ld a,(hl) ; hl -> e_phase (holds timer info) or a jr z,next_phase dec (hl) inc hl ; hl -> e_timer (holds phase info) jr figure_phase next_phase: inc hl inc (hl) ld a,(hl) restart_phase: ld b,a add a,a add a,b ex de,hl ; de -> e_timer dec a ld hl,(pattern) call ADD_HL_A ld a,(hl) or a jr z,restart_pattern dec de ; de -> e_phase ld (de),a inc de ; de -> e_timer inc hl ; hl -> phase direction data jr phase_located restart_pattern: ex de,hl inc a ld (hl),a jr restart_phase figure_phase: ld a,(hl) ld b,a add a,a add a,b ex de,hl ; de -> e_timer ld hl,(pattern) call ADD_HL_A ; hl -> phase direction data phase_located: ex de,hl ; de -> direction data, hl -> e_timer ld bc,8 add hl,bc ; hl -> e_data ld a,(de) add a,(hl) ld b,a and 15 ld (hl),a ld a,b sra a sra a sra a sra a ld bc,-7 add hl,bc ; hl -> e_x add a,(hl) ld (hl),a inc de ld bc,8 add hl,bc ; hl -> e_data ld a,(de) add a,(hl) ld b,a and 15 ld (hl),a ld a,b sra a sra a sra a sra a ld bc,-6 add hl,bc ; hl -> e_y add a,(hl) ld (hl),a ld e,a push hl dec hl dec hl ld d,(hl) ld hl,img_enemy_3 semi_aim_shoot: call drw_spr pop hl semi_aim_shoot_nodraw: call FAST_RANDOM and %01111110 ret nz semi_aim_shoot_now: ld a,(player_y) sub (hl) ret c srl a srl a ld b,a ; B = (PY - EY) srl a add a,b ret z ld b,a ; B = (3/8) * (PY - EY) dec hl dec hl ld a,(player_x) sub (hl) ; A = PX - EX inc hl inc hl jr c,figurefireleft cp b jp c,fire_enemy_bullet_std jp fire_bullet_half_right figurefireleft: neg cp b jp c,fire_enemy_bullet_std jp fire_bullet_half_left ;############## Standard enemy code standard_enemy: inc hl ; HL -> e_phase ld a,(hl) ld (which_phase+1),a inc hl ; HL -> e_timer inc (hl) ld a,(hl) rrca jr nc,no_move_enemy cp $88 jr nz,not_phase_end ld (hl),0 dec hl ; HL -> e_phase ld a,(hl) inc a inc a inc a inc a and 12 ld (hl),a inc hl ; HL -> e_timer not_phase_end: inc hl ; HL -> e_x push hl call which_phase enemy_display: ld e,(hl) ; E = e_y inc hl inc hl inc hl ; E -> e_img bcall(_ldhlind) ; HL = e_img pop bc ld a,(bc) ld d,a jp drw_spr no_move_enemy: inc hl ; HL -> e_x push hl inc hl inc hl call FAST_RANDOM and %01111110 push hl call z,normal_enemy_shoot pop hl jr enemy_display which_phase: jr phase1 phase0: inc hl inc hl inc (hl) ret phase1: inc (hl) inc hl inc hl ret phase2: inc hl inc hl dec (hl) ret phase3: dec (hl) inc hl inc hl ret ;############## Exploding enemy exploding_enemy: inc hl inc hl inc hl ; HL -> e_x ld d,(hl) ; D = X inc hl inc hl ; HL -> e_y ld e,(hl) ; E = Y inc hl inc hl ; HL -> e_pwr ld (hl),25 ; Don't let explosion be killed inc hl push de ; Save X, Y push hl pop de ; DE -> e_img ld c,(hl) inc hl ld b,(hl) ld a,(game_timer) rrca jr c,no_next_step ld hl,8 add hl,bc ; HL = new image address ld a,(hl) add a,a jr c,end_of_explosion ; -1 -> end of list ld a,l ; Save new image address ld (de),a inc de ld a,h ld (de),a draw_explosion: pop de ; Restore X, Y jp drw_spr no_next_step: push bc pop hl jr draw_explosion end_of_explosion: ld hl,-e_img add hl,de ld (hl),0 ; HL -> e_type pop de ld a,(doing_enemies) or a ret z push hl ld hl,enemies_left dec (hl) pop hl call FAST_RANDOM and %01011000 ret nz ld de,e_y add hl,de ; HL -> e_y jp deploy_bonus ;############## Bouncing enemies bounce_enemy: inc hl ld c,(hl) ;C = YV (bit 1 - right, bit 0 - fast) inc hl ld b,(hl) ;B = XV (bit 1 - down, bit 0 - fast) inc hl ld a,(game_timer) or b rrca jr nc,bounce_nox bit 1,b jr z,bounce_left bounce_right: inc (hl) ld a,107 cp (hl) jr nz,bounce_nox dec hl call FAST_RANDOM and 1 ld (hl),a inc hl jr bounce_nox bounce_left: dec (hl) ld a,13 cp (hl) jr nz,bounce_nox dec hl call FAST_RANDOM and 1 or 2 ld (hl),a inc hl bounce_nox: ld d,(hl) inc hl inc hl ld a,(game_timer) or c rrca jr nc,bounce_noy bit 1,c jr z,bounce_up bounce_down: inc (hl) ld a,60 cp (hl) jr nz,bounce_noy push hl ld bc,-4 add hl,bc call FAST_RANDOM and 1 ld (hl),a pop hl jr bounce_noy bounce_up: dec (hl) ld a,31 cp (hl) jr nz,bounce_noy push hl ld bc,-4 add hl,bc call FAST_RANDOM and 1 or 2 ld (hl),a pop hl bounce_noy: ld e,(hl) push hl ld hl,img_bounce jp semi_aim_shoot ;################################################################## ; ; Phoenix-Z80 (Level initialization) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated November 24, 2000. ; ;################################################################## ;############## Load the next level load_row: ld b,(hl) inc hl ld a,(hl) ld (set_up_enemies+1),a inc hl ld a,(hl) inc hl ld c,(hl) inc hl push hl push af bcall(_ldhlind) pop af ex de,hl call set_up_enemies ex de,hl pop hl inc hl inc hl jr level_loader load_poke: ld b,(hl) inc hl push hl bcall(_ldhlind) ld (hl),b pop hl inc hl inc hl jr level_loader load_bounce: ld b,(hl) inc hl push hl ex de,hl call bounce_install ex de,hl pop hl jr level_loader restart: ld hl,level ld (hl),0 load_level: ld hl,level ld a,(hl) inc (hl) ld hl,(level_addr) add a,a call ADD_HL_A bcall(_ldhlind) ld de,e_array ld a,(hl) ld (enemies_left),a inc hl level_loader: ld a,(hl) inc hl ld (smc_loader_jump+1),a smc_loader_jump: jr loader_table loader_table: ret ;0 jp load_row ;1 jp load_single ;4 jp load_bounce ;7 jp load_delayed ;10 jp load_poke ;13 jp game_finished ;16 jp shop ;19 ;22 word_poke: ld c,(hl) inc hl ld b,(hl) inc hl push hl bcall(_ldhlind) ld (hl),c inc hl ld (hl),b pop hl inc hl inc hl jr level_loader load_single: push hl bcall(_ldhlind) ld bc,e_size ldir pop hl inc hl inc hl jr level_loader load_delayed: ld b,(hl) inc hl ld a,(hl) ld (loop_install_delayed+1),a inc hl push hl ex de,hl call install_delayed ex de,hl pop hl jr level_loader ;############## Initialize levels with bouncing enemies bounce_install: ld a,14 ld de,e_size-7 loop_put_bouncing: ld (hl),15 ; e_type inc hl ld (hl),3 ; XV inc hl ld (hl),3 ; YV inc hl ld (hl),a inc hl add a,10 ld (hl),8 inc hl ld (hl),20 inc hl ld (hl),9 inc hl ld (hl),36 add hl,de djnz loop_put_bouncing ret ;############## Install enemy data for one row of enemies ; ; HL -> position in e_array to start installing ; B = number of enemies in row ; C = Y coordinate of row (from top of screen) ; DE = enemy image ; ; Returns with HL -> first unused enemy, B = 0 set_up_enemies: ld (hl),3 ; Enemy type inc hl ld (hl),0 ; Phase inc hl ld (hl),-60 ; Timer inc hl ld (hl),a ; X-coordinate add a,15 inc hl push af ld a,(de) ld (hl),a ; Width inc hl ld (hl),c ; Y-coordinate inc hl inc de ld a,(de) ld (hl),a ; Height dec de inc hl dec de ld a,(de) ld (hl),a ; Power inc de pop af inc hl ld (hl),e ; Image, low byte inc hl ld (hl),d ; Image, high byte inc hl inc hl inc hl djnz set_up_enemies ret ;############## Initialize levels with circle/bar enemies install_delayed: ld a,b ld c,9 ld de,e_size-6 loop_install_delayed: ld (hl),9 ; e_type inc hl ld (hl),a ; e_phase inc hl inc hl ld (hl),c ; e_x inc hl ld (hl),c inc hl ld (hl),c ; e_y inc hl ld (hl),c add a,15 add hl,de djnz loop_install_delayed ret ;################################################################## ; ; Phoenix-Z80 (Collisions between enemies and player's bullets) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last modified September 26, 2000. ; ;################################################################## ;############## Builds table of enemies in GFX_AREA ; ; This puts enemies into columns, 0 to 7, on the high bits of their X ; coordinates. Column 0 is for X coordinates 0 to 15, 1 for 16 to 31, and ; so on. Then, they are split into groups; for enemies in only 1 column, ; the group is column * 2 + 1, for enemies that spill into the next column, ; the group is column * 2 + 2. ; ; Each group data structure has a one-byte size, followed by a list of ; pointers to each enemy in the group. The first column starts at ; GFX_AREA+48, the next at GFX_AREA+96, and so on. Empty columns are put ; at the edges to allow proper checking of side bullets. This allows up to ; 23 entries per column, more than enough to accomodate all enemies. hit_enemies: xor a ; Initialize all columns as empty ld b,19 ld de,48 ld hl,GFX_AREA loop_empty_columns: ld (hl),a add hl,de djnz loop_empty_columns ld hl,e_array ; HL -> enemy ld b,e_num build_table_loop: ld a,(hl) ; Skip empty enemy entries or a dec a jp m,none_here inc hl inc hl inc hl ld a,(hl) ; D = enemy X coordinate inc hl ld e,(hl) ; E = enemy Y coordinate dec hl dec hl dec hl dec hl ; HL -> width or a jr z,none_here ; Skip non-ready enemies call which_group ; Compute group number in A ld c,a add a,a ; A = 2 * group number add a,c ; A = 3 * group number add a,a add a,a ; A = 12 * group number push hl ld l,a ld h,0 ; HL = 12 * group number add hl,hl add hl,hl ; HL = 48 * group number ld de,GFX_AREA add hl,de ; HL -> group data structure ld a,(hl) ; A = group size before insertion inc (hl) ; increment group size add a,a inc a call ADD_HL_A ; HL = new entry in group pop de ; DE -> enemy ld (hl),e ; store DE in group inc hl ld (hl),d ex de,hl ; HL -> enemy none_here: ld de,e_size add hl,de djnz build_table_loop ;############## Process player bullets ; ; This routine will process every player bullet by checking it for collisions ; with appropriate columns. If it is all in one column, it must be tested ; against three groups, as shown below ; ; Column 2 | Column 3 | Column 4 ; | | ; <-----Bullet------> ; <---Enemy group 6---> ; <--Enemy group 7--> ; <---Enemy group 8---> ; ; If the bullet straddles two columns, it then must be checked against ; five groups of enemies, as indicated below ; ; Column 2 | Column 3 | Column 4 | Column 5 ; | | | ; <--------Bullet--------> ; <---Enemy group 6---> ; <--Enemy group 7--> ; <-----Enemy group 8----> ; <-Enemy group 9--> ; <---Enemy group 10---> ; ; Even so, this still saves a lot of time over the default collision testing ; strategy, to test all combinations of objects, which would effectively ; require testing with 15 groups in all cases (though without the sorting ; overhead introduced here). ld hl,pb_array ld b,pb_num loop_process_bullets: ld a,(hl) or a jr z,no_bullet push hl push bc ld (collision+1),hl inc hl inc hl ld a,(hl) inc hl ld e,(hl) dec hl call which_group ; A = group number ld de,test_coords ; Copy bullet data to test coords ldi ldi ldi ldi ld b,a dec a ld c,a add a,a ; A = 2 * group number add a,c ; A = 3 * group number add a,a add a,a ; A = 12 * group number ld l,a ld h,0 ; HL = 12 * group number add hl,hl add hl,hl ; HL = 48 * group number ld de,GFX_AREA add hl,de ; HL -> group data structure bit 0,b jr nz,check_3_groups check_5_groups: call list_collision_check ld bc,-48 add hl,bc call list_collision_check ld bc,96 add hl,bc check_3_groups: call list_collision_check ld bc,48 add hl,bc call list_collision_check ld bc,48 add hl,bc call list_collision_check pop bc pop hl no_bullet: ld de,pb_size add hl,de djnz loop_process_bullets ret ;############## Determine which group object is in ; ; Determines which group an object is in. A holds the X coordinate, E holds ; the width. Returns results in A. Modifies A, C, and D. which_group: ld d,a rlca rlca rlca rlca and 7 add a,a inc a ld c,a ld a,d and 15 add a,e cp 16 ld a,c ret c inc a ret ;############## Check bullet for collisions within one group ; ; Checks the bullet whose data is int test_coords with group (HL) list_collision_check: push hl ld a,(hl) or a jr z,exit_cc_list inc hl ; HL -> group data ld b,a ; B = number in group loop_column_scan: push hl ; HL -> somewhere in the list ld a,(hl) inc hl ld h,(hl) ld l,a ; HL -> item retrieved from list ld de,e_x push hl add hl,de call collision_check pop hl jr c,collision pop hl inc hl ; Move HL to next in list inc hl djnz loop_column_scan exit_cc_list: pop hl ret collision: ld de,0 ; DE -> bulelt ex de,hl ; DE -> enemy, HL -> bullet ld (hl),0 ; Delete bullet inc hl ld c,(hl) ; C = bullet damage ld hl,e_pwr add hl,de ; HL -> enemy damage ld a,(hl) sub c ld (hl),a jr nc,collision_done ; If enemy not destroyed ld a,-5 ; New enemy type (exploding) ld (de),a ld hl,e_img add hl,de ; HL -> enemy image ld de,image_explosion ld (hl),e inc hl ld (hl),d collision_done: ld sp,0 pop bc pop hl jr no_bullet ;################################################################## ; ; Phoenix-Z80 (Collision detection) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ;################################################################## ;############## Test for collisions between two objects ; ; Carry flag set if they collided, clear if they didn't ; Each object's information is in a structure consisting of four bytes: ; X-Coordinate, Width, Y-Coorinate, Height in that order ; Routine takes one object pointed to by HL, other in test_coords collision_check: ;############## Ensure that X1 < X2 + W2 ld de,(test_coords) ; E = X2, D = W2 ld a,(hl) ; A = X1 sub e ; A = X1 - X2 jr c,cc1 ; (X1 < X2) --> (X1 < X2 + W2) cp d ret nc ; Exit if (X1 - X2) >= W2 inc hl jr cc2 ; (X2 <= X1) --> (X2 < X1 + W1) ;############## Ensure that X2 < X1 + W1 cc1: neg ; A = X2 - X1 (which is > 0) inc hl cp (hl) ret nc ; Exit if (X2 - X1) >= W1 ;############## Ensure that Y1 < Y2 + H2 cc2: ld de,(test_coords+2) ; E = Y2, D = H2 inc hl ld a,(hl) ; A = Y1 sub e ; A = Y1 - Y2 jr c,cc3 ; (Y1 < Y2) --> (Y1 < Y2 + H2) cp d ; Carry set if (Y1 - Y2) < H2 ret ; End of testing (last cond. certain ; since Y2 <= Y1, due to jr c,cc3) ;############## Ensure that Y2 < Y1 + H1 cc3: neg ; A = Y2 - Y1 (which is > 0) inc hl cp (hl) ret ; Carry set if (Y2 - Y1) < H1 ;################################################################## ; ; Phoenix-Z80 (Enemy bullets) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated October 28, 2000. ; ;################################################################## ;############## Enemy bullet routine ; ; Calls the code specified by the bullet 'type'. The 'type', which must ; be a multiple of 3, is an index into the table of jumps for bullet code. ; Bullet routines should move the bullet and draw its image. They are ; called with HL pointing to the bullet entry, and can change all registers. enemy_bullets: xor a ld (doing_enemies),a ld hl,img_eb_3 ld (beb_image),hl ld a,(which_shot) rlca call c,enemy_bullets_2 ld hl,eb_array ld b,eb_num loop_enemy_bullets: ld a,(hl) ld (do_enemy_bullet+1),a push hl push bc call do_enemy_bullet pop bc pop hl ld de,eb_size add hl,de djnz loop_enemy_bullets ret enemy_bullets_2: ld hl,img_eb_4 ld (beb_image),hl ld hl,eb_array ld b,eb_num loop_enemy_bullets_2: ld a,(hl) cp 23 jr c,none ld (do_enemy_bullet+1),a push hl push bc call do_enemy_bullet pop bc pop hl none: ld de,eb_size add hl,de djnz loop_enemy_bullets_2 ret jp exploding_enemy ;This is offset -5 do_enemy_bullet: jr point_to_ebullet_code point_to_ebullet_code: ;############## Enemy bullet routine table starts here no_ebullet: ld (hl),0 ret jp std_ebullet ;3 jp bonus_ebullet ;6 jp left_ebullet ;9 jp right_ebullet ;12 jp half_left_ebullet ;15 jp half_right_ebullet ;18 jp arrow_bullet ;21 jp big_ebullet_left3 ;24 jp big_ebullet_left2 ;27 jp big_ebullet_left1 ;30 jp big_ebullet_down ;33 jp big_ebullet_right1 ;36 jp big_ebullet_right2 ;39 jp big_ebullet_right3 ;42 ;45 ;############## Big bullets big_ebullet_left1: ld a,(game_timer) rra jr c,big_ebullet_left2 jr big_ebullet_down big_ebullet_right1: ld a,(game_timer) rra jr c,big_ebullet_right2 big_ebullet_down: inc hl inc hl common_bigbullet: ld d,(hl) inc hl inc hl inc (hl) ld e,(hl) ld a,96 sub e jr z,destroy_ebullet ld hl,(beb_image) jp drw_spr big_ebullet_left3: call poss_up big_ebullet_left2: inc hl inc hl dec (hl) decide_bbullet: jr z,destroy_ebullet_x jr common_bigbullet big_ebullet_right3: call poss_up big_ebullet_right2: inc hl inc hl inc (hl) ld a,126 cp (hl) jr decide_bbullet poss_up: ld a,(game_timer) rra ret c push hl ld de,eb_y add hl,de dec (hl) pop hl ret ;############## Arrow enemy bullet arrow_bullet: inc hl inc hl ld d,(hl) inc hl inc hl inc (hl) ld e,(hl) ld a,96 sub e jr z,destroy_ebullet ld hl,img_eb_2 jp drw_spr ;############## Bullet moving half right half_right_ebullet: ld a,(game_timer) rra jr c,right_ebullet jr std_ebullet ;############## Bullet moving half left half_left_ebullet: ld a,(game_timer) rra jr c,left_ebullet jr std_ebullet ;############## Bullet moving right right_ebullet: inc hl inc hl inc (hl) ld a,126 cp (hl) jr decide_ebullet ;############## Bullet moving left left_ebullet: inc hl inc hl dec (hl) decide_ebullet: jr z,destroy_ebullet_x jr common_ebullet ;############## Standard enemy bullet std_ebullet: inc hl inc hl common_ebullet: ld d,(hl) inc hl inc hl inc (hl) ld e,(hl) ld a,96 sub e jr z,destroy_ebullet ld hl,img_eb_1 jp drw_spr destroy_ebullet: ld de,-4 add hl,de ld (hl),a ret destroy_ebullet_x: dec hl dec hl ld (hl),0 ret ;############## Falling bonus bonus_ebullet: inc hl inc hl ld d,(hl) inc hl inc hl ld a,(game_timer) rra jr c,no_fall_bonus inc (hl) no_fall_bonus: ld e,(hl) ld a,96 sub e jr z,destroy_ebullet ld hl,img_money jp drw_spr ;################################################################## ; ; Phoenix-Z80 (Collisions between player and other objects) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last modified November 25, 2000. ; ;################################################################## hit_companion: ld a,(companion_x) ld l,a ld h,7 ld (test_coords),hl ld a,(companion_y) ld l,a ld h,7 ld (test_coords+2),hl ld c,1 jr player_hit_scan hit_player: ld a,(player_x) ld l,a ld h,8 ld (test_coords),hl ld a,(player_y) ld l,a ld h,6 ld (test_coords+2),hl ;############## Enemy bullet scanning loop ld c,0 player_hit_scan: ld hl,eb_array ; HL -> enemy bullet to check ld b,eb_num loop_player_hit_scan: ld a,(hl) ; Check if this bullet exists or a jr z,no_ebullet_here jp m,no_ebullet_here push hl inc hl inc hl ; HL -> X coordinate of bullet call collision_check ; Does it collide? jr nc,no_player_collision ;############## Collision handling pop hl push hl ld (hl),-5 ; enemy bullet type to -5 inc hl ld a,(hl) ; A = damage amount or a jr z,money inc hl ; Shift up X and Y ld e,(hl) ; to "fake" enemy structure inc hl dec e dec e ld (hl),e inc hl ld e,(hl) inc hl dec e dec e ld (hl),e ; HL -> e_y inc hl ; HL -> e_h inc hl ; HL -> e_pwr inc hl ; HL -> e_img ld de,image_explosion ld (hl),e inc hl ld (hl),d ld e,a bit 0,c jr nz,did_hit_companion ld a,(player_pwr) sub e ld (player_pwr),a jr c,game_lose jr no_player_collision did_hit_companion: ld a,(companion_pwr) sub e ld (companion_pwr),a dec a bit 7,a jr z,no_player_collision ld a,-1 ld (companion_pwr),a ld hl,image_explosion ld (companion_img),hl ;############## End of collision handling no_player_collision: pop hl no_ebullet_here: ld de,eb_size ; Next bullet in array add hl,de djnz loop_player_hit_scan ret ;############## Money collection money: dec hl xor a ld (hl),a ld hl,(player_cash) ld de,(difficulty) ld d,a add hl,de jr c,no_player_collision ld de,10000 bcall(_cphlde) jr nc,no_player_collision ld (player_cash),hl jr no_player_collision ;############## Losing the game game_lose: call no_high_score jp game_exit ;################################################################## ; ; Phoenix-82 (Shop) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated November 27, 2000. ; ;################################################################## ;############## Test for money and intialize shop screen shop: ld hl,(player_cash) ld a,h or l ret z call restore_memory bcall(_clrlcdf) ld hl,0 ld (currow),hl ld hl,shopmessage bcall(_puts) ld a,1 ld (shop_item),a ;############## Shop main loop shop_loop: ld hl,$0B00 ld (currow),hl ld hl,(player_cash) ld a,l or h ret z bcall(_disphl) bcall(_getcsc) ld hl,shop_item cp G_DOWN jr z,shop_down cp G_UP jr z,shop_up cp G_MODE ret z cp G_DEL ret z cp G_CLEAR ret z cp G_ENTER call z,shop_select jr shop_loop ;############## Shop cursor movement shop_down: ld a,(hl) cp 7 jr z,shop_loop push hl ld l,a ld h,0 ld (currow),hl ld a,' ' bcall(_putc) pop hl inc (hl) ld a,(hl) ld l,a ld h,0 ld (currow),hl ld a,'>' bcall(_putc) jr shop_loop shop_up: ld a,(hl) cp 1 jr z,shop_loop push hl ld l,a ld h,0 ld (currow),hl ld a,' ' bcall(_putc) pop hl dec (hl) ld a,(hl) ld l,a ld h,0 ld (currow),hl ld a,'>' bcall(_putc) jr shop_loop ;############## Shop item purchases item3: ld bc,500 sbc hl,bc ret c ld a,(companion_pwr) cp 16 ret z ld (player_cash),hl get_companion: ld hl,companion_pwr ld (hl),16 inc hl ld (hl),90 inc hl ld (hl),60 ret shop_select: ld a,(hl) dec a add a,a ld (shop_jump_offset+1),a ld hl,(player_cash) shop_jump_offset: jr item_list item_list: jr item1 jr item2 jr item3 jr item4 jr item5 jr item6 item7: ld bc,2000 ld de,weapon_5 jr common_weapon_add item1: ld bc,100 sbc hl,bc ret c ld a,(player_pwr) cp 16 ret z inc a ld (player_pwr),a ld (player_cash),hl ret item2: ld bc,300 ld de,weapon_2 common_weapon_add: sbc hl,bc ret c ld a,(de) or a ret nz inc a ld (de),a ld (player_cash),hl ret item5: ld bc,1000 ld de,weapon_3 jr common_weapon_add item6: ld bc,1250 ld de,weapon_4 jr common_weapon_add item4: ld de,weapon_upgrade ld a,(de) or a ret nz ld bc,750 sbc hl,bc ret c ld (player_cash),hl inc a ld (de),a ret ;############## Shop messages shopmessage: .db "Phx Shop - " .db "> Shield + 100" .db " Weapon 2 300" .db " Helper 500" .db " Upgrade 750" .db " Weapon 3 1000" .db " Weapon 4 1250" .db " Weapon 5 2000",0 ;################################################################## ; ; Phoenix-Z80 (Companion ship) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated September 19, 2000. ; ;################################################################## do_companion: ld a,(companion_pwr) or a jp m,companion_explode ret z call hit_companion ld de,posqueue ; Move up ship position history ld hl,posqueue+2 ld bc,20 ldir call companion_dest ; Calculate destination of companion call companion_move ; Move call companion_shoot ld de,(companion_y) ld hl,img_companion jp drw_spr ;############## Exploding companion ship companion_explode: ld hl,(companion_img) ld a,(game_timer) rrca jr c,no_new_image ld bc,8 add hl,bc ld (companion_img),hl no_new_image: ld a,(hl) add a,a ld de,(companion_y) jp nc,drw_spr xor a ld (companion_pwr),a ret ;############## Calculation of destination at tail of queue companion_dest: ld hl,posqueue dec (hl) inc hl ld a,(hl) cp 60 jr c,companion_left companion_right: sub 10 ld (hl),a ret companion_left: add a,11 ld (hl),a ret ;############## Movement of companion towards destination companion_move: ld hl,companion_y ld a,(posqueue) cp (hl) jr z,companion_movedy jr nc,companion_moveyd dec (hl) jr companion_movedy companion_moveyd: inc (hl) companion_movedy: inc hl ld a,(posqueue+1) cp (hl) ret z jr nc,companion_movexr dec (hl) ret companion_movexr: inc (hl) ret ;############## Companion shooting, every 8 frames companion_shoot: ld a,(game_timer) and 7 ret nz ld hl,pb_array ; Locate unused bullet in HL ld b,pb_num ld de,pb_size comp_search_bullet: ld a,(hl) or a jr z,comp_found_bullet add hl,de djnz comp_search_bullet ret comp_found_bullet: ld (hl),30 ; Type inc hl ld (hl),10 ; Amount of damage inc hl ld a,(companion_x) add a,2 ld (hl),a ; X coordinate inc hl ld (hl),3 ; width inc hl ld a,(companion_y) sub 5 ld (hl),a ; Y coordinate inc hl ld (hl),5 ; height ret ;################################################################## ; ; Phoenix-Z80 (Enemy firing) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated October 21, 2000. ; ;################################################################## ;############## Deploy cash bonus (HL -> enemy Y coordinate) bonus_data: .db 6 .db 0 .db 5 .db 7 deploy_bonus: ld de,bonus_data jr fire_enemy_bullet ret ;############## Fire standard enemy bullet (HL -> enemy Y coordinate) big_ebullet_data: .db 3 .db 2 .db 3 .db 3 standard_ebullet_data: .db 3 ; Type .db 1 ; Power .db 2 ; Width .db 2 ; Height left_ebullet_data: .db 9 ; Type .db 1 ; Power .db 2 ; Width .db 2 ; Height right_ebullet_data: .db 12 ; Type .db 1 ; Power .db 2 ; Width .db 2 ; Height half_left_ebullet_data: .db 15 ; Type .db 1 ; Power .db 2 ; Width .db 2 ; Height half_right_ebullet_data: .db 18 ; Type .db 1 ; Power .db 2 ; Width .db 2 ; Height arrow_ebullet_data: .db 21 .db 1 .db 3 .db 7 ;############## Fire a large, fully-aimed bullet (HL -> X) fire_big_bullet: inc hl inc hl ld a,(player_y) sub (hl) ret c srl a srl a ld b,a ; B = (PY - EY) srl a add a,b ret z ld b,a ; B = (3/8) * (PY - EY) dec hl dec hl ld a,(player_x) sub (hl) ; A = PX - EX inc hl inc hl jr c,fire_big_left call get_angle ld a,c deploy_big: add a,33 ld de,big_ebullet_data ld (de),a jr fire_enemy_bullet fire_big_left: neg call get_angle ld a,c neg jr deploy_big get_angle: ld c,0 sub b ret c ; DX < (3/8) DY -> straight down ld c,3 sub b ret c ; DX < (3/4) DY -> slight angle ld c,6 sub b ret c ; DX < (3/2) DY -> 45 deg angle sub b ret c ld c,9 ; DX > (3/2) DY -> high angle ret ;############## Standard firing routines normal_enemy_shoot: ld a,(which_shot) rrca jr nc,fire_enemy_bullet_std ld de,arrow_ebullet_data jr fire_enemy_bullet fire_enemy_bullet_std: ld de,standard_ebullet_data ;############## Fire any type of bullet (HL -> Y coordinate, DE -> info) fire_enemy_bullet: push hl push de call locate_enemy_bullet ; HL -> enemy bullet entry pop de ; DE -> bullet description pop bc ; BC -> enemy Y coordinate ex de,hl ; HL -> bullet description ; DE -> enemy bullet entry ldi ; Copy type, BC -> enemy width ldi ; Copy power, BC -> enemy X ld a,(bc) add a,2 ld (de),a ; Store ebullet X inc de ldi ; Copy width, BC -> enemy X - 1 inc bc inc bc inc bc ; BC -> enemy Y ld a,(bc) add a,7 ld (de),a ; Store ebullet Y inc de ldi ; Copy height ret ;############## Fire an aimed bullet (HL -> X coordinate) fire_aimed_bullet: ld a,(player_x) add a,30 cp (hl) ; PlayerX + 30 - ShootX jr c,fire_bullet_left ; If ShootX > PlayerX + 30 sub 60 ; PlayerX - 30 jr c,fire_bullet_std ; If PlayerX < 30 cp (hl) ; PlayerX - 30 - ShootX jr nc,fire_bullet_right ; If ShootX <= PlayerX - 30 fire_bullet_std: inc hl inc hl ld de,standard_ebullet_data jr fire_enemy_bullet fire_bullet_left: inc hl inc hl ld de,left_ebullet_data jr fire_enemy_bullet fire_bullet_right: inc hl inc hl ld de,right_ebullet_data jr fire_enemy_bullet fire_bullet_half_left: ld de,half_left_ebullet_data jr fire_enemy_bullet fire_bullet_half_right: ld de,half_right_ebullet_data jr fire_enemy_bullet ;############## Locate an unused enemy bullet locate_enemy_bullet: ld hl,eb_array ld b,eb_num ld de,eb_size loop_locate_eb: ld a,(hl) or a ret z add hl,de djnz loop_locate_eb pop hl pop de pop hl ret ;################################################################## ; ; Phoenix-Z80 (High scores) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated November 25, 2000. ; ;################################################################## scoring_msg: .db "Shields",0 .db "Speed",0 .db "Bonus",0 .db "Money",0 .db 0 .db "Score",0 .db 0 .db " Press (ENTER)",0 .db -1 highscore_title: .db " High Scores",0 highscore_prompt: .db " Enter your name",0 ;############## Calculate and display player's score game_finished: ld hl,completed ld a,(hl) or a jp nz,no_high_score ld (hl),1 call synchronize call synchronize call restore_memory bcall(_clrlcdf) ld hl,scoring_msg call display_hl_msgs ld hl,$0B03 ld (currow),hl ld hl,(player_cash) ; max 10000 bcall(_disphl) ld hl,$0B02 ld (currow),hl ld hl,(bonus_score) ; max 20000 bcall(_disphl) ld hl,$0B01 ld (currow),hl ld hl,(time_score) ; max 19000 bcall(_disphl) ld a,(player_pwr) ; max 16000 ld hl,0 ld de,1000 or a jr z,shield_done ld b,a shield_addup: add hl,de djnz shield_addup shield_done: push hl ld de,(time_score) add hl,de ld de,(bonus_score) add hl,de ld de,(player_cash) add hl,de ld (bonus_score),hl ld de,$0B05 ld (currow),de bcall(_disphl) ld hl,$0B00 ld (currow),hl pop hl bcall(_disphl) loop_show_score: bcall(_getcsc) cp G_ENTER jr nz,loop_show_score ;############## Check if you have high score ld hl,(high_scores_end) ; Check against lowest score ld de,(bonus_score) bcall(_cphlde) jr nc,no_high_score ld (high_scores_end),de ; Put your score in bottom ld hl,high_scores+(13*6) ld b,10 loop_space: ld (hl),' ' inc hl djnz loop_space ld b,6 ; Bubble it towards the top ld de,high_scores_end ; DE -> entry to move up loop_bubble: ld hl,-13 add hl,de ; HL -> entry to compare with push de bcall(_ldhlind) ; HL = score above this one push hl ex de,hl ld e,(hl) inc hl ld d,(hl) ; DE = this score pop hl bcall(_cphlde) pop de ; DE -> this entry jr nc,no_bubble_up inc de ; DE -> very end of entry ld hl,-13 add hl,de ; HL -> previous entry push bc ld b,13 loop_exchange: ld a,(de) ld c,a ld a,(hl) ld (de),a ld (hl),c dec hl dec de djnz loop_exchange pop bc dec de ; DE -> previous entry djnz loop_bubble no_bubble_up: ld hl,-11 add hl,de push hl push bc call display_high_scores ld hl,0 ld (currow),hl ld hl,highscore_prompt bcall(_puts) pop bc pop hl inc b ld c,b ld b,0 ld (currow),bc call input_name ;############## Show high scores no_high_score: call display_high_scores ld hl,0 ld (currow),hl ld hl,highscore_title bcall(_puts) call loop_show_highs jp restart bcall(_getcsc) loop_show_highs: bcall(_getcsc) cp 6 jr c,loop_show_highs ret ;############## Prompt for name entry input_name: push hl pop ix ld b,0 enter_name_loop: bcall(_getcsc) or a jr z,enter_name_loop cp G_DEL jr z,backup cp G_ENTER ret z ld c,a ld a,10 cp b jr z,enter_name_loop ld hl,chartable-10 ld e,c ld d,0 add hl,de ld a,(hl) ld (ix),a bcall(_putc) inc b inc ix jr enter_name_loop backup: xor a cp b jr z,enter_name_loop dec b dec ix ld (ix),32 ld hl,curcol dec (hl) ld a,32 bcall(_putc) dec (hl) jr enter_name_loop chartable: .db ":WRMH." .db "..0VQLG!..ZUPKFC" .db "..YTOJEBX.>SNIDA" .db ".12345.." ;############## Display the high score table display_high_scores: call restore_memory bcall(_clrlcdf) bcall(_getcsc) ld hl,high_scores ld b,7 ld a,1 ld (currow),a loop_display_hs: xor a ld (curcol),a push hl bcall(_puts) pop hl ld de,11 add hl,de push hl bcall(_ldhlind) ld a,$b ld (curcol),a bcall(_disphl) pop hl inc hl inc hl djnz loop_display_hs ret ;################################################################## ; ; Phoenix-Z80 (Images) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated November 24, 2000. ; ;################################################################## ;############## Standard enemies .db 16 img_enemy_4: .db 7,9 .db %10000010 .db %11000110 .db %11111110 .db %10000010 .db %10000010 .db %10000010 .db %11111110 .db %01111100 .db %00111000 .db 3 img_enemy_1: .db 6,6 .db %10000100 .db %10000100 .db %11111100 .DB %11111100 .DB %01111000 .DB %00110000 .db 5 img_enemy_2: .db 8,5 .db %10000001 .db %11011011 .db %11111111 .db %11011011 .db %10000001 .db 7 img_enemy_2a: .db 5,5 .db %10001000 .db %11111000 .db %10001000 .db %01010000 .db %00100000 img_operator: .db 8,8 .db %01111110 .db %11111111 .db %11000011 .db %11000011 .db %11000011 .db %11000011 .db %11111111 .db %01111110 .db 20 img_spin_1a: .db 8,8 .db %00100000 .db %00111100 .db %01111111 .db %01100110 .db %01100110 .db %11111110 .db %00111100 .db %00000100 img_spin_1b: .db 8,8 .db %00001000 .db %00111100 .db %01111110 .db %11100110 .db %01100111 .db %01111110 .db %00111100 .db %00010000 img_spin_1c: .db 8,8 .db %00000010 .db %10111100 .db %01111110 .db %01100110 .db %01100110 .db %01111110 .db %00111101 .db %01000000 img_spin_1d: .db 8,8 .db %01000000 .db %01111111 .db %01111110 .db %01100110 .db %01100110 .db %01111110 .db %11111110 .db %00000010 .db -1 .db 30 img_spin_2a: .db 8,8 .db %00100000 .db %00111100 .db %01111111 .db %01111110 .db %01111110 .db %11111110 .db %00111100 .db %00000100 img_spin_2b: .db 8,8 .db %00001000 .db %00111100 .db %01111110 .db %11111110 .db %01111111 .db %01111110 .db %00111100 .db %00010000 img_spin_2c: .db 8,8 .db %00000010 .db %10111100 .db %01111110 .db %01111110 .db %01111110 .db %01111110 .db %00111101 .db %01000000 img_spin_2d: .db 8,8 .db %01000000 .db %01111111 .db %01111110 .db %01111110 .db %01111110 .db %01111110 .db %11111110 .db %00000010 .db -1 ;############## Special enemies img_bounce: .db 8,9 .db %00011000 .db %00011000 .db %00011000 .db %00100100 .db %01000010 .db %10000001 .db %10011001 .db %10100101 .db %11000011 img_enemy_3: .db 8,8 .db %00111100 .db %01000010 .db %10000001 .db %11111111 .db %11111111 .db %10000001 .db %01000010 .db %00111100 ;############## Bosses img_boss2_left: .db 8,12 .db %11111000 .db %10001111 .db %10001000 .db %10001000 .db %10001000 .db %10001000 .db %10001000 .db %10001111 .db %11111000 .db %11111000 .db %01110000 .db %00100000 img_boss2_right: .db 8,12 .db %00011111 .db %11110001 .db %00010001 .db %00010001 .db %00010001 .db %00010001 .db %00010001 .db %11110001 .db %00011111 .db %00011111 .db %00001110 .db %00000100 img_boss_left: .db 8,12 .db %10000000 .db %11000000 .db %11100000 .db %11111111 .db %11000111 .db %11000011 .db %11000001 .db %11000001 .db %11100001 .db %01110001 .db %00111111 .db %00011111 img_boss_right: .db 8,12 .db %00000001 .db %00000011 .db %00000111 .db %11111111 .db %11100011 .db %11000011 .db %10000011 .db %10000011 .db %10000111 .db %10001110 .db %11111100 .db %11111000 img_boss3_left: .db 8,15 .db %11111000 .db %11010100 .db %10101010 .db %11010101 .db %10101010 .db %11010101 .db %10101010 .db %11010101 .db %10101010 .db %11010101 .db %10101111 .db %11011000 .db %10101000 .db %11011000 .db %01110000 img_boss3_right: .db 8,15 .db %00111111 .db %00101011 .db %01010101 .db %10101011 .db %01010101 .db %10101011 .db %01010101 .db %10101011 .db %01010101 .db %10101011 .db %11110101 .db %00011011 .db %00010101 .db %00011011 .db %00001110 ;############## Swooping enemy swoop_l_stage1: .db %8,8 .db %11100000 .db %10101110 .db %11101110 .db %10111111 .db %11111111 .db %10101110 .db %11101110 .db %10100100 swoop_r_stage1: .db 3,8 .db %11100000 .db %10100000 .db %11100000 .db %10100000 .db %11100000 .db %10100000 .db %11100000 .db %10100000 swoop_l_stage2: .db %8,8 .db %11100000 .db %10101110 .db %11101110 .db %10111111 .db %11111111 .db %10101110 .db %11101110 .db %10100100 swoop_r_stage2: .db 3,8 .db %11100000 .db %10100000 .db %11100000 .db %10100000 .db %11100000 .db %10100000 .db %11100000 .db %10100000 ;############## Players img_player_ship_normal: .db 8,6 .db %10000001 .db %10000001 .db %10011001 .db %10100101 .db %11000011 .db %10000001 img_player_ship_damaged: .db 8,6 .db %10000000 .db %00000001 .db %10010000 .db %00000101 .db %11000000 .db %00000001 img_companion: .db 7,7 .DB %00010000 .DB %00111000 .DB %10111010 .DB %10111010 .DB %10111010 .DB %11111110 .DB %11111110 ;############## Player bullets img_player_bullet_0: .db 2,6 .db %11000000 .db %11000000 .db %11000000 .db %11000000 .db %11000000 .db %11000000 img_player_bullet_1: .db 4,8 .db %01100000 .db %11110000 .db %10100000 .db %01010000 .db %10100000 .db %01010000 .db %10100000 .db %01010000 img_player_bullet_2l: .db 3,7 .db %00100000 .db %01100000 .db %11100000 .db %11100000 .db %11100000 .db %11000000 .db %10000000 img_player_bullet_2r: .db 3,7 .db %10000000 .db %11000000 .db %11100000 .db %11100000 .db %11100000 .db %01100000 .db %00100000 img_player_bullet_3: .db 4,4 .db %01100000 .db %11110000 .db %11110000 .db %01100000 img_player_bullet_5: .db 5,7 .db %00100000 .db %01110000 .db %11111000 .db %11111000 .db %11111000 .db %11011000 .db %10001000 img_quad_bullet: .db 3,5 .db %01000000 .db %11100000 .db %11100000 .db %11100000 .DB %11100000 ;############## Dropped items img_eb_1: .db 2,2 .db %11000000 .db %11000000 img_eb_3: .db 3,3 .db %01000000 .db %11100000 .db %01000000 img_eb_2: .db 3,7 .db %10100000 .db %11100000 .db %11100000 .db %01000000 .db %01000000 .db %11100000 .db %01000000 img_money: .db 5,7 .db %00100000 .db %11111000 .db %10100000 .db %11111000 .db %00101000 .db %11111000 .db %00100000 img_eb_4: .db 5,5 .db %01110000 .db %11111000 .db %11111000 .db %11111000 .db %01110000 ; Explosion image_explosion: .db 8,6 .db %00000000 .db %00011100 .DB %00111110 .DB %01010110 .DB %00111000 .DB %00000000 .db 8,6 .db %00110000 .db %01001110 .DB %10111110 .DB %01001111 .DB %00111000 .DB %00011010 .db 8,6 .db %11110011 .db %01001110 .DB %10110101 .DB %01000101 .DB %00111110 .DB %11011010 .db 8,6 .db %11110011 .db %01001110 .DB %10110101 .DB %01000101 .DB %00111110 .DB %11011010 .db 8,6 .db %01000001 .db %00100110 .DB %00010101 .DB %01000100 .DB %00010010 .DB %10011010 .db 8,6 .db %01000010 .db %00100000 .DB %00000001 .DB %01000100 .DB %00100010 .DB %10001010 .db 8,6 .db %00001000 .db %11000010 .DB %00000000 .db %00100000 .db %00000001 .db %00110000 .db 8,6 .db %00000100 .DB %00000000 .DB %01000000 .DB %00000000 .db %00000001 .db %00100100 .db -1 ;################################################################## ; ; Phoenix-Z80 (Data storage, Save/Restore) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated October 28, 2000. ; ;################################################################## ;############## Save the game game_save: ld de,saved_flag ld a,1 ld (de),a inc de ld hl,perm_var_start ld bc,perm_var_size ldir jp game_exit ;############## Test for saved game, restoring if it exists restore_game: ld hl,saved_flag ld a,(hl) or a ret z ld (hl),0 inc hl ld de,perm_var_start ld bc,perm_var_size ldir ;############## Actual storage space permanent_data_start: saved_flag: .db 0 saved_data: .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 pb_array: .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 e_array: .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 eb_array: .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 game_data_end: saved_address: .db 31337 high_scores: .db "Patrick D ",0 .dw 30000 .db "Patrick D ",0 .dw 25000 .db "Patrick D ",0 .dw 20000 .db "Patrick D ",0 .dw 18000 .db "Patrick D ",0 .dw 16000 .db "Patrick D ",0 .dw 14000 .db "Patrick D ",0 high_scores_end: .dw 8000 permanent_data_end: ;################################################################## ; ; Phoenix-Z80 (Level definitions) ; ; Programmed by Patrick Davidson (pad@calc.org) ; ; Ported by Mouse (Mouse47@Aol.Com) ; ; This program is in the public domain. There is no warranty. ; ; This file was last updated November 24, 2000. ; ;################################################################## ;############## Table of level descriptions level_table: .dw lev1 .dw lev2 .dw lev3 .dw _shop .dw lev4 .dw lev5 .dw bounce6 .dw lev6 .dw _shop .dw lev4a .dw lev5a .dw bounce8 .dw lev6a .dw _shop .dw lev7 SPLIT_LEVEL =15 .dw lev8 .dw bounce10 .dw lev9 .dw _shop .dw lev10 .dw lev11 .dw lev12 .dw _shop .dw lev13 .dw lev14 .dw lev15 .dw _shop .dw lev13a .dw lev14a .dw lev15a .dw _shop .dw levsw .dw levl .dw _shop .dw levo1 .dw levo2 .dw levo3 .dw _shop .dw levsw .dw levl .dw _game_finished ;############## Level descriptions ; ; Level descriptions begin with a ; ; .db total_number_of_enemies ; ; followed by as many of the following level-initialization commands as ; needed to specify the level ; ; .db 0 ; end the level data ; ; .db 1,num,type,x,y ; install num enemies of specified type in ; .dw image ; a row starting at (x,y) with given image ; ; .db 4 ; install a single enemy, copying the whole ; .dw data ; structure from memory at (data) ; ; .db 7,num ; install num bouncing enemies ; ; .db 10,num,type ; install num "delayed-entry" enemies ; ; .db 13,byte ; write the byte to memory at address ; .dw addr ; ; .db 16 ; Marks the end of the game ; ; .db 19 ; Enters the shop ; ; .db 22 ; write misc. word to memory at address ; .dw word, addr ; ; Note the "image", "word", and "data" are expected to be offsets within ; the level data on the TI-85 (but "addr" is *NOT*). levsw: .db 9 .db 10,9,36 .db 0 levo1: .db 8 .db 10,8,30 .db 0 levo2: .db 12 .db 10,12,30 .db 0 levo3: .db 13 .db 10,12,30 .db 4 .dw boss_data2 .db 0 levl: .db 18 .db 4 .dw boss_data3 .db 13,128 .dw which_shot .db 10,17,9 .db 22 .dw huge_oval_pattern,pattern .db 0 lev1: .db 18 .db 1,6,3,18,0 .dw img_enemy_1 .db 1,6,3,18,10 .dw img_enemy_1 .db 1,6,3,18,20 .dw img_enemy_1 .db 13,0 .dw which_shot .db 0 lev2: .db 18 .db 1,6,3,18,0 .dw img_enemy_1 .db 1,6,3,20,10 .dw img_enemy_1 .db 1,6,3,18,20 .dw img_enemy_1 .db 0 lev3: .db 7 .db 1,6,3,18,20 .dw img_enemy_1 .db 4 .dw boss_data .db 0 lev4: .db 18 .db 1,6,3,18,0 .dw img_enemy_2 .db 1,6,3,18,10 .dw img_enemy_2 .db 1,6,3,18,20 .dw img_enemy_2 .db 0 lev5: .db 18 .db 1,6,3,18,0 .dw img_enemy_2 .db 1,6,3,20,10 .dw img_enemy_2 .db 1,6,3,18,20 .dw img_enemy_2 .db 0 lev6: .db 7 .db 1,6,3,18,20 .dw img_enemy_2 .db 4 .dw boss_data .db 0 lev4a: .db 18 .db 1,6,3,18,0 .dw img_enemy_2 .db 1,6,3,18,10 .dw img_enemy_2a .db 1,6,3,18,20 .dw img_enemy_2a .db 0 lev5a: .db 18 .db 1,6,3,18,0 .dw img_enemy_2a .db 1,6,3,20,10 .dw img_enemy_2a .db 1,6,3,18,20 .dw img_enemy_2a .db 0 lev6a: .db 13 .db 1,6,3,18,23 .dw img_enemy_2a .db 1,6,3,18,15 .dw img_enemy_2 .db 4 .dw boss_data .db 0 lev7: .db 14 .db 10,14,9 .db 22 .dw circle_pattern,pattern .db 0 lev8: .db 13 .db 10,13,9 .db 22 .dw figure_eight_pattern,pattern .db 0 lev9: .db 14 .db 10,13,9 .db 22 .dw oval_pattern,pattern .db 4 .dw boss_data .db 0 lev10: .db 18 .db 1,6,3,18,0 .dw img_enemy_4 .db 1,6,3,18,10 .dw img_enemy_4 .db 1,6,3,18,20 .dw img_enemy_4 .db 13,1 .dw which_shot .db 0 lev11: .db 18 .db 1,6,3,18,0 .dw img_enemy_4 .db 1,6,3,20,10 .dw img_enemy_4 .db 1,6,3,18,20 .dw img_enemy_4 .db 0 lev12: .db 13 .db 1,6,3,18,12 .dw img_enemy_2 .db 1,6,3,18,21 .dw img_enemy_2 .db 4 .dw boss_data2 .db 0 bounce6: .db 6 .db 7,6 .db 0 bounce8: .db 8 .db 7,8 .db 0 bounce10: .db 10 .db 7,10 .db 0 lev13: .db 18 .db 1,6,21,18,0 .dw img_spin_1a .db 1,6,21,18,10 .dw img_spin_1a .db 1,6,21,18,20 .dw img_spin_1a .db 0 lev14: .db 18 .db 1,6,21,12,0 .dw img_spin_1a .db 1,6,21,19,10 .dw img_spin_1a .db 1,6,21,12,20 .dw img_spin_1a .db 0 lev15: .db 14 .db 1,7,21,16,12 .dw img_spin_1a .db 1,6,21,22,21 .dw img_spin_1a .db 4 .dw boss_data2 .db 0 lev13a: .db 18 .db 1,6,21,18,0 .dw img_spin_2a .db 1,6,21,18,10 .dw img_spin_2a .db 1,6,21,18,20 .dw img_spin_2a .db 0 lev14a: .db 18 .db 1,6,21,12,0 .dw img_spin_2a .db 1,6,21,19,10 .dw img_spin_2a .db 1,6,21,12,20 .dw img_spin_2a .db 0 lev15a: .db 14 .db 1,7,21,16,12 .dw img_spin_2a .db 1,6,21,22,21 .dw img_spin_2a .db 4 .dw boss_data2 .db 0 _game_finished: .db 0,16 _shop: .db 0,19 ;############## Pattens huge_oval_pattern: .db 1,18 .db 64,20,0 .db 10,16,0 .db 8,12,-12 .db 24,0,-10 .db 8,-12,-12 .db 10,-16,0 .db 64,-20,0 .db 10,-16,0 .db 8,-12,12 .db 24,0,10 .db 8,12,12 .db 10,16,0 .db 0 ; KKK EEE ; L JJ DD F ; L JJ DD F ;| A JJDD G | ;| A DDJJ G | ;v A DD JJ G v ; B DD JJ H ; BCCC IIIH figure_eight_pattern: .db 0,12 .db 12,12,12 ;B .db 16,16,0 ;C .db 34,16,-12 ;D .db 16,15,0 ;E .db 12,12,12 ;F .db 8,0,12 ;G .db 12,-12,12 ;H .db 16,-15,0 ;I .db 34,-16,-12 ;J .db 16,-16,0 ;K .db 12,-12,12 ;L .db 8,0,12 ;A .db 0 circle_pattern: .db 0,14 .db 8,12,12 .db 16,16,0 .db 8,12,-12 .db 16,0,-16 .db 8,-12,-12 .db 16,-16,0 .db 8,-12,12 .db 16,0,16 .db 0 oval_pattern: .db 0,16 .db 4,12,12 .db 76,16,0 .db 4,12,-12 .db 6,0,-16 .db 4,-12,-12 .db 76,-16,0 .db 4,-12,12 .db 6,0,16 .db 0 ;############## Data for bosses boss_data: .db 12 ; e_type .db 0 ; e_phase .db 32 ; e_timer .db 90 ; e_x .db 16 ; e_w .db 1 ; e_y .db 10 ; e_h .db 60 ; e_pwr boss_data2: .db 18 ; e_type .db 0 ; e_phase .db 31 ; e_timer .db 90 ; e_x .db 16 ; e_w .db 1 ; e_y .db 10 ; e_h .db 100 ; e_pwr boss_data3: .db 27 .db 0 .db 40 .db 90 .db 17 .db 1 .db 15 .db 150 .end