diff --git a/another_myst/NOTES b/another_myst/NOTES index af6e95d4..e6daf238 100644 --- a/another_myst/NOTES +++ b/another_myst/NOTES @@ -1,25 +1,25 @@ Title screen +play intro music??? intro ending, with scrolling text +sound effects for splash? + zap appear underwater, but different background climb out by clock sea creature gets you -solve puzzle +solve puzzle (spaceship puzzle) zap linking book -atrus zaps out of linking book, picks you up and flies off +* atrus zaps out of linking book, picks you up and flies off +* the end +* has not yet been written -the end -has not yet been written -play intro music - -sound effects for splash? 0123456789012345678901234567890123456789 ______ diff --git a/another_myst/alien.s b/another_myst/alien.s new file mode 100644 index 00000000..d210e85c --- /dev/null +++ b/another_myst/alien.s @@ -0,0 +1,557 @@ +; draw/move the bad guy aliens + +MAX_ALIENS = 3 + +alien_room: + alien0_room: .byte 0 + alien1_room: .byte 0 + alien2_room: .byte 0 + +alien_x: + alien0_x: .byte 0 + alien1_x: .byte 0 + alien2_x: .byte 0 + +alien_y: + alien0_y: .byte 0 + alien1_y: .byte 0 + alien2_y: .byte 0 + +alien_state: + alien0_state: .byte 0 + alien1_state: .byte 0 + alien2_state: .byte 0 + +A_STANDING = 0 +A_WALKING = 1 +A_RUNNING = 2 +A_CROUCHING = 3 +A_TURNING = 4 +A_YELLING = 5 +A_SHOOTING_UP = 6 +A_DISINTEGRATING = 7 +A_SHOOTING = 8 + +alien_gait: + alien0_gait: .byte 0 + alien1_gait: .byte 0 + alien2_gait: .byte 0 + +alien_direction: + alien0_direction: .byte 0 + alien1_direction: .byte 0 + alien2_direction: .byte 0 + +alien_gun: + alien0_gun: .byte 0 + alien1_gun: .byte 0 + alien2_gun: .byte 0 + + + + + + ;======================================= + ; Move alien based on current state + ; + +move_alien: + + ldx #0 + +move_alien_loop: + lda alien_room,X + cmp WHICH_ROOM + bne done_move_alien + + lda alien_state,X + + cmp #A_WALKING + beq move_alien_walking + cmp #A_RUNNING + beq move_alien_running + cmp #A_YELLING + beq move_alien_yelling + cmp #A_SHOOTING_UP + beq move_alien_yelling + cmp #A_STANDING + beq move_alien_standing + cmp #A_SHOOTING + beq move_alien_shooting + +done_move_alien: + + inx + cpx #MAX_ALIENS + bne move_alien_loop + + rts + + ;====================== + ; yelling +move_alien_yelling: + inc alien_gait,X ; cycle through animation + jmp done_move_alien + + ;====================== + ; walking + +move_alien_walking: + inc alien_gait,X ; cycle through animation + + lda alien_gait,X + and #$f + cmp #$8 ; only walk roughly 1/8 of time + bne alien_no_move_walk + + lda alien_direction,X + beq a_walk_left + + inc alien_x,X ; walk right + jmp done_move_alien +a_walk_left: + dec alien_x,X ; walk left +alien_no_move_walk: + jmp done_move_alien + + ;====================== + ; running +move_alien_running: + inc alien_gait,X ; cycle through animation + + lda alien_gait,X + and #$3 + cmp #$2 ; only run roughly 1/4 of time + bne alien_no_move_run + + lda alien_direction,X + beq a_run_left + + inc alien_x,X ; run right + jmp done_move_alien +a_run_left: + dec alien_x,X ; run left +alien_no_move_run: + jmp done_move_alien + + ;====================== + ; standing + +move_alien_standing: + + ; turn to face physicist if on same level + lda PHYSICIST_Y + cmp alien_y,X + bne done_move_alien_standing + + ;================= + ; delay a bit so it doesn't happen instantaneously + + lda FRAMEL + and #$3f + bne done_move_alien_standing + + lda PHYSICIST_X + cmp alien_x,X + bcs alien_face_right + +alien_face_left: + lda #0 + beq alien_done_facing +alien_face_right: + lda #1 + +alien_done_facing: + sta alien_direction,X + + ; change to shooting + + lda #A_SHOOTING + sta alien_state,X + + +done_move_alien_standing: + + + jmp done_move_alien + + ;====================== + ; shooting + +move_alien_shooting: + + ; only fire occasionally + lda FRAMEL + and #$7f + bne done_alien_shooting_now + + jsr fire_alien_laser + +done_alien_shooting_now: + jmp done_move_alien + + +astate_table_lo: + .byte alien_standing ; 00 + .byte >alien_walking ; 01 + .byte >alien_running ; 02 + .byte >alien_crouching ; 03 + .byte >alien_turning ; 04 + .byte >alien_yelling ; 05 + .byte >alien_shooting_up; 06 + .byte >alien_disintegrating; 07 + .byte >alien_shooting ; 08 + +; Urgh, make sure this doesn't end up at $FF or you hit the +; NMOS 6502 bug + +.align 2 + +ajump: + .word $0000 + +.align 1 + +;====================================== +;====================================== +; draw alien +;====================================== +;====================================== + +draw_alien: + + ldx #0 +draw_alien_loop: + lda alien_room,X + cmp WHICH_ROOM + bne no_alien + + txa + pha + + lda alien_state,X + tay + lda astate_table_lo,y + sta ajump + lda astate_table_hi,y + sta ajump+1 + jmp (ajump) +done_draw_alien_loop: + pla + tax + +no_alien: + inx + cpx #MAX_ALIENS + bne draw_alien_loop + + rts + +;================================== +; STANDING +;================================== + +alien_standing: + + lda #alien_stand + sta INH + + jmp finally_draw_alien + +;================================== +; SHOOTING +;================================== + +alien_shooting: + + lda #alien_shoot_sprite + sta INH + + jmp finally_draw_alien + + +;=================================== +; CROUCHING +;=================================== + +alien_crouching: + + ; FIXME: we have an animation? + + lda #alien_crouch2 + sta INH + + jmp finally_draw_alien + + +;=============================== +; Walking +;================================ + +alien_walking: + lda alien_gait,X + cmp #64 + bcc alien_gait_fine ; blt + + lda #0 + sta alien_gait,X + +alien_gait_fine: + lsr + lsr + and #$fe + + tay + + lda alien_gun,X + beq alien_walk_nogun + +alien_walk_gun: + + lda alien_walk_gun_progression,Y + sta INL + + lda alien_walk_gun_progression+1,Y + sta INH + + jmp finally_draw_alien + +alien_walk_nogun: + lda alien_walk_progression,Y + sta INL + + lda alien_walk_progression+1,Y + sta INH + + jmp finally_draw_alien + +;=============================== +; Running +;================================ + +alien_running: + lda alien_gait,X + cmp #32 + bcc alien_run_gait_fine ; blt + + lda #0 + sta alien_gait,X + +alien_run_gait_fine: + lsr + and #$fe + + tay + + lda alien_run_progression,Y + sta INL + + lda alien_run_progression+1,Y + sta INH + + jmp finally_draw_alien + +;=============================== +; Turning +;================================ + +alien_turning: + + dec alien_gait,X + bpl alien_draw_turning + + lda #0 + sta alien_gait,X + + ; switch direction + lda alien_direction,X + eor #$1 + sta alien_direction,X + + lda #A_WALKING + sta alien_state,X + +alien_draw_turning: + lda #alien_turning_sprite + sta INH + + jmp finally_draw_alien + + + +;=============================== +; Yelling +;================================ + +alien_yelling: + lda alien_gait,X + + ; 00 + ; 01 + ; 10 + ; 11 + + and #$40 + bne alien_yelling_no_waving + + lda alien_gait,X + +alien_yelling_no_waving: + and #$10 + lsr + lsr + lsr + and #2 + + tay + + lda alien_yell_progression,Y + sta INL + + lda alien_yell_progression+1,Y + sta INH + + jmp finally_draw_alien + + +;=============================== +; Disintegrating +;================================ + +alien_disintegrating: + lda alien_gait,X + + cmp #13 + bne alien_keep_disintegrating + + lda #$ff + sta alien_room,X + + dec ALIEN_OUT + + jmp done_draw_alien_loop + +alien_keep_disintegrating: + + asl + tay + + lda alien_disintegrating_progression,Y + sta INL + + lda alien_disintegrating_progression+1,Y + sta INH + + lda FRAMEL + and #$7 + bne slow_disintegration + + inc alien_gait,X +slow_disintegration: + + jmp finally_draw_alien + + +;=============================== +; Shooting Upward +;================================ + +alien_shooting_up: + lda alien_gait,X + and #$30 + + ; 000 000 + ; 010 000 + ; 100 000 + ; 110 000 + + lsr + lsr + lsr + + and #6 + tay + + lda alien_shoot_up_progression,Y + sta INL + + lda alien_shoot_up_progression+1,Y + sta INH + + cpy #0 + + lda alien_gait,X +; and #$ff + bne finally_draw_alien + + lda #32 + sta SHOOTING_BOTTOM + lda #28 + sta SHOOTING_TOP + + inc LITTLEGUY_OUT + +; bne finally_draw_alien ; bra + + + +;============================= +; Actually Draw Alien +;============================= + + +finally_draw_alien: + lda alien_x,X + sta XPOS + + lda alien_y,X + sta YPOS + + lda alien_direction,X + bne alien_facing_right + +alien_facing_left: + jsr put_sprite_crop + jmp done_draw_alien_loop + +alien_facing_right: + jsr put_sprite_flipped_crop + jmp done_draw_alien_loop + + ;================== + ;================== + ; clear aliens + ;================== + ;================== +clear_aliens: + lda #$ff + sta alien0_room + sta alien1_room + sta alien2_room + + rts + + diff --git a/another_myst/alien_laser.s b/another_myst/alien_laser.s new file mode 100644 index 00000000..909c6612 --- /dev/null +++ b/another_myst/alien_laser.s @@ -0,0 +1,96 @@ + +; Handle alien laser + +; uses laser1 slot + +; should handle multiple at once? + +;laser1_out: .byte $0 +;laser1_start: .byte $0 +;laser1_end: .byte $0 +;laser1_y: .byte $0 +;laser1_direction: .byte $0 +;laser1_count: .byte $0 + + ;========================= + ; fire alien laser + ;========================= + ; which alien in X + +fire_alien_laser: + + lda laser1_out + bne done_fire_alien_laser + + lda alien_x,X + sta COLLISION_X + lda alien_y,X + sta COLLISION_Y + + ; activate laser slot + + inc laser1_out + + ; reset count + + lda #0 + sta laser1_count + + ; set y + + ; assume for now no crouching + + lda alien_y,X + clc + adc #4 + sta laser1_y + + ; set direction + + lda alien_direction,X + sta laser1_direction + + beq alien_laser_left + bne alien_laser_right + + ; set x + +alien_laser_left: + stx LASER_TEMP + + jsr calc_gun_left_collision + + ldx LASER_TEMP + + lda alien_x,X + sec + sbc #2 + sta laser1_end + + sec + sbc #10 + sta laser1_start + + jmp done_fire_alien_laser + +alien_laser_right: + + stx LASER_TEMP + + jsr calc_gun_right_collision + + ldx LASER_TEMP + + lda alien_x,X + clc + adc #5 + sta laser1_start + + clc + adc #10 + sta laser1_end + +done_fire_alien_laser: + rts + + diff --git a/another_myst/anothermist.s b/another_myst/anothermist.s index 3c54ed0f..b1ff10e9 100644 --- a/another_myst/anothermist.s +++ b/another_myst/anothermist.s @@ -13,8 +13,6 @@ another_mist: - - ending: ;========================= @@ -90,9 +88,12 @@ repeat_ending: sta DISP_PAGE ;=========================== - ; show some pictures + ; do the shooting part ;============================ + jsr ootw_cave_init + jsr ootw_cave + ;=========================== ; ending sequence @@ -860,6 +861,27 @@ long_wait: .include "pt3_lib_mockingboard_setup.s" +.include "keyboard.s" +.include "gr_putsprite.s" +.include "gr_putsprite_crop.s" +.include "laser.s" +.include "gr_hlin.s" +.include "blast.s" +.include "shield.s" +.include "collision.s" +.include "dummy_friend.s" +.include "alien.s" +.include "physicist.s" +.include "gun.s" +.include "ootw_c5_cave.s" +.include "door.s" +.include "alien_laser.s" + +; sprites + +.include "sprites/physicist.inc" +.include "sprites/alien.inc" + ; backgrounds diff --git a/another_myst/blast.s b/another_myst/blast.s new file mode 100644 index 00000000..7279bac9 --- /dev/null +++ b/another_myst/blast.s @@ -0,0 +1,360 @@ +; Handle blast + +blast0_out: .byte $0 +blast0_start: .byte $0 +blast0_end: .byte $0 +blast0_y: .byte $0 +blast0_direction: .byte $0 +blast0_count: .byte $0 + + ;========================= + ; fire blast + ;========================= + +fire_blast: + + lda blast0_out + bne done_fire_blast + + lda PHYSICIST_X + + ldx DIRECTION ; 0=left, 1=right + beq blast_facing_left + + clc + adc #5 + jmp blast_done_adjust + + +blast_facing_left: + sec + sbc #2 + +blast_done_adjust: + + sta COLLISION_X + lda PHYSICIST_Y + sta COLLISION_Y + + ; activate blast slot + + inc blast0_out + + ; reduce gun charge + ; FIXME: don't shoot if too low + lda GUN_CHARGE + sec + sbc #10 + sta GUN_CHARGE + + ; reset blast count + + lda #0 + sta blast0_count + + ; set y + + lda PHYSICIST_Y + clc + adc #4 + + ldx PHYSICIST_STATE + cpx #P_CROUCH_SHOOTING + bne blast_ypos_done + +blast_crouch: + clc + adc #4 +blast_ypos_done: + + sta blast0_y + + ; set direction + + lda DIRECTION + sta blast0_direction + + beq blast_left + bne blast_right + + ; set x + +blast_left: + jsr calc_gun_left_collision + + ldx PHYSICIST_X + dex + stx blast0_end + + txa + sec + sbc #10 + sta blast0_start + + jmp done_fire_blast + +blast_right: + jsr calc_gun_right_collision + + lda PHYSICIST_X + clc + adc #5 + sta blast0_start + + clc + adc #10 + sta blast0_end + +done_fire_blast: + rts + + + ;==================== + ; draw blast + ;==================== + +draw_blast: + + lda blast0_out + beq done_draw_blast + + lda #$fe + sta hlin_color_smc+1 + + lda #$00 + sta hlin_mask_smc+1 + + ldy blast0_y + + sec + lda blast0_end + sbc blast0_start + tax + + lda blast0_start + + jsr hlin + + ldy blast0_y + sty YPOS + + lda blast0_direction + beq blast_going_left + ldy blast0_end + jmp blast_going_done +blast_going_left: + ldy blast0_start +blast_going_done: + sty XPOS + + lda #gun_charge_sprite8 + sta INH + + jsr put_sprite_crop + +done_draw_blast: + + rts + + + + ;=================== + ; move blast + ;=================== +move_blast: + lda blast0_out + beq done_move_blast + + ; slow down blast + lda blast0_count + and #$3 + bne no_move_blast + + lda blast0_direction + bne move_blast_right + +move_blast_left: + + lda blast0_count + cmp #4 + bcc still_starting_blast_left + cmp #8 + bcc still_shooting_blast_left + +continue_shooting_blast_left: +still_shooting_blast_left: + + lda blast0_end + sec + sbc #10 + sta blast0_end + +still_starting_blast_left: + + lda blast0_start + sec + sbc #10 + sta blast0_start + +blast_edge_detect_left: + + lda blast0_end + cmp LEFT_SHOOT_LIMIT + bmi disable_blast_left + + lda blast0_start + cmp LEFT_SHOOT_LIMIT + bpl no_move_blast + + lda LEFT_SHOOT_LIMIT + sta blast0_start + + jmp no_move_blast + + +move_blast_right: + + lda blast0_count + cmp #4 + bcc still_starting_blast_right + cmp #8 + bcc still_shooting_blast_right + +continue_shooting_blast_right: + lda blast0_start + clc + adc #10 + sta blast0_start + +still_shooting_blast_right: + lda blast0_end + clc + adc #10 + sta blast0_end + +still_starting_blast_right: + +blast_edge_detect_right: + + ; detect if totally off screen + lda blast0_start + cmp RIGHT_SHOOT_LIMIT + bcs disable_blast_right + + lda blast0_end + cmp RIGHT_SHOOT_LIMIT + bcc no_move_blast + + lda RIGHT_SHOOT_LIMIT + sta blast0_end + +no_move_blast: + inc blast0_count + +done_move_blast: + + rts + + ;===================== + ; hit something, left + ;===================== +disable_blast_left: + lda LEFT_SHOOT_TARGET + jmp blast_something_common + + ;================== + ; hit something, right + ;================== +disable_blast_right: + + lda RIGHT_SHOOT_TARGET + + + ;========================= + ; blash something, common + ;========================= +blast_something_common: + + ldx #0 + stx blast0_out + tax + and #$f0 + + cmp #TARGET_DOOR + beq blast_door + + cmp #TARGET_ALIEN + beq blast_alien + + cmp #TARGET_FRIEND + beq blast_friend + + cmp #TARGET_SHIELD + beq blast_shield + + jmp done_blasting_common + + +blast_alien: + txa + and #$f + tax + + lda #A_DISINTEGRATING + sta alien_state,X + + lda #0 + sta alien_gait,X + + jmp done_blasting_common + +blast_friend: + + lda #F_DISINTEGRATING + sta friend_state + + lda #FAI_DISINTEGRATING + sta friend_ai_state + + lda #0 + sta friend_gait + + jmp done_blasting_common + +blast_shield: + + ; FIXME: need animation for this + + txa + and #$f + tax + + lda #0 + sta shield_out,X + + dec SHIELD_OUT + + jmp done_blasting_common + +blast_door: + + inc BLASTED_WALL + + ; FIXME: change direction based on blast + txa + and #$f + tay + + lda #DOOR_STATUS_EXPLODING1 + sta (DOOR_STATUS),Y + + jsr recalc_walk_collision + + +done_blasting_common: + + rts + + diff --git a/another_myst/collision.s b/another_myst/collision.s new file mode 100644 index 00000000..f5d2e9e5 --- /dev/null +++ b/another_myst/collision.s @@ -0,0 +1,606 @@ +TARGET_NONE = $00 +TARGET_DOOR = $10 +TARGET_SHIELD = $20 +TARGET_FRIEND = $30 +TARGET_ALIEN = $40 +TARGET_PHYSICIST= $80 + + ;============================= + ;============================= + ; recalc_walk_collision + ;============================= + ;============================= + ; far left limit is LEVEL_LEFT limit + ; far right limit is LEVEL_RIGHT limit + ; any LOCKED doors in the way also stop things + ; FIXME: only door collision if on same level +recalc_walk_collision: + + ; note the limits have $80 added to them :( + + lda RIGHT_LIMIT + sta RIGHT_WALK_LIMIT + + lda LEFT_LIMIT + sta LEFT_WALK_LIMIT + + lda NUM_DOORS + beq done_recalc_walk_right_collision + +recalc_walk_left: + + ldy NUM_DOORS + dey +recalc_walk_left_loop: + + lda PHYSICIST_X + cmp (DOOR_X),Y + bcc recalc_walk_left_continue ; blt + + ; only if on same level + lda (DOOR_Y),Y + clc + adc #4 + cmp PHYSICIST_Y + bne recalc_walk_left_continue + + ; only if closer than previous found + lda (DOOR_X),Y + ora #$80 + cmp LEFT_WALK_LIMIT + + bcc recalc_walk_left_continue ; blt + + lda (DOOR_STATUS),Y + cmp #DOOR_STATUS_LOCKED + bne recalc_walk_left_continue + + ; early exit + lda (DOOR_X),Y + ora #$80 + sta LEFT_WALK_LIMIT +; jmp done_recalc_walk_left_collision + +recalc_walk_left_continue: + dey + bpl recalc_walk_left_loop + +done_recalc_walk_left_collision: + + + ldy #0 +recalc_walk_right_loop: + + ; only if on same level + lda (DOOR_Y),Y + clc + adc #4 + cmp PHYSICIST_Y + bne recalc_walk_right_continue + + lda PHYSICIST_X + cmp (DOOR_X),Y + bcs recalc_walk_right_continue ; bge + + ; only if closer than previous found + lda (DOOR_X),Y + ora #$80 + cmp RIGHT_WALK_LIMIT + + bcs recalc_walk_right_continue ; bge + + lda (DOOR_STATUS),Y + cmp #DOOR_STATUS_LOCKED + bne recalc_walk_right_continue + + ; early exit + lda (DOOR_X),Y + sec + sbc #4 + ora #$80 + sta RIGHT_WALK_LIMIT + jmp done_recalc_walk_right_collision + +recalc_walk_right_continue: + iny + cpy NUM_DOORS + bne recalc_walk_right_loop + +done_recalc_walk_right_collision: + + + rts + + + + + + ;============================= + ;============================= + ; calc_gun_right_collision + ;============================= + ;============================= + ; far right limit is LEVEL_RIGHT + ; any LOCKED or CLOSED doors with SAME_Y to left of LEVEL_RIGHT + ; any shield stops things + ; our friend stops things + ; any enemies stop things + +calc_gun_right_collision: + + lda #$00 + sta RIGHT_SHOOT_TARGET + + ;===================================================================== + ; by default set it to left limit (which is often but not always a wall) + + lda RIGHT_LIMIT + and #$7f + sta RIGHT_SHOOT_LIMIT + + ;=========================== + ; stop if hit door + +calc_gun_right_door: + lda NUM_DOORS + beq done_calc_gun_right_door_collision + +calc_gun_right_doors: + + + ldy #0 +calc_gun_right_door_loop: + + ; only if on same level + lda (DOOR_Y),Y + clc + adc #4 + cmp COLLISION_Y + bne calc_gun_right_door_continue + + lda COLLISION_X + cmp (DOOR_X),Y + bcs calc_gun_right_door_continue ; bge + + lda (DOOR_STATUS),Y + cmp #DOOR_STATUS_LOCKED + beq calc_gun_right_door_there + cmp #DOOR_STATUS_CLOSED + bne calc_gun_right_door_continue + +calc_gun_right_door_there: + ; early exit + lda (DOOR_X),Y + sta RIGHT_SHOOT_LIMIT + + tya ; set target if hit + ora #TARGET_DOOR + sta RIGHT_SHOOT_TARGET + + jmp done_calc_gun_right_door_collision + +calc_gun_right_door_continue: + iny + cpy NUM_DOORS + bne calc_gun_right_door_loop + +done_calc_gun_right_door_collision: + + + ;========================== + ; adjust for shield + +calc_gun_right_shield: + + lda SHIELD_OUT + beq done_calc_gun_right_shield_collision + + ldx #0 +calc_gun_right_shield_loop: + + ; FIXME: check for on same level? + + lda shield_out,X + beq calc_gun_right_shield_continue + + lda COLLISION_X + cmp shield_x,X + bcs calc_gun_right_shield_continue ; bge + + ; be sure closer than current max limit + lda RIGHT_SHOOT_LIMIT + cmp shield_x,X + bcc calc_gun_right_shield_continue ; blt + +calc_gun_right_shield_there: + + lda shield_x,X + sta RIGHT_SHOOT_LIMIT + + txa ; set target if hit + ora #TARGET_SHIELD + sta RIGHT_SHOOT_TARGET + + ; can't early exit + +calc_gun_right_shield_continue: + inx + cpx #MAX_SHIELDS + bne calc_gun_right_shield_loop + +done_calc_gun_right_shield_collision: + + + ;========================== + ; adjust for friend + +calc_gun_right_friend: + + lda friend_room + cmp WHICH_ROOM + bne done_calc_gun_right_friend_collision + + lda COLLISION_X + cmp friend_x + bcs calc_gun_right_friend_continue ; bge + + ; only if closer than previous found + lda RIGHT_SHOOT_LIMIT + cmp friend_x + bcc calc_gun_right_friend_continue ; blt + + lda friend_state + cmp #F_DISINTEGRATING + beq calc_gun_right_friend_continue + +calc_gun_right_friend_there: + ; early exit + lda friend_x + sta RIGHT_SHOOT_LIMIT + + ; set target if hit + lda #TARGET_FRIEND + sta RIGHT_SHOOT_TARGET + +calc_gun_right_friend_continue: + +done_calc_gun_right_friend_collision: + + + ;========================== + ; adjust for physicist + +calc_gun_right_physicist: + + lda COLLISION_X + cmp PHYSICIST_X + bcs calc_gun_right_physicist_continue ; bge + + ; only if closer than previous found + lda RIGHT_SHOOT_LIMIT + cmp PHYSICIST_X + bcc calc_gun_right_physicist_continue ; blt + + lda PHYSICIST_STATE + cmp #P_DISINTEGRATING + beq calc_gun_right_physicist_continue + +calc_gun_right_physicist_there: + + lda PHYSICIST_X + sta RIGHT_SHOOT_LIMIT + + ; set target if hit + lda #TARGET_PHYSICIST + sta RIGHT_SHOOT_TARGET + +calc_gun_right_physicist_continue: +done_calc_gun_right_physicist_collision: + + + + ;========================== + ; adjust for alien + +calc_gun_right_alien: + + lda ALIEN_OUT + beq done_calc_gun_right_alien_collision + + ldx #0 +calc_gun_right_alien_loop: + + lda alien_room,X + cmp WHICH_ROOM + bne calc_gun_right_alien_continue + + ; only if on same level + lda alien_y,X + cmp COLLISION_Y + bne calc_gun_right_alien_continue + + lda COLLISION_X + cmp alien_x,X + bcs calc_gun_right_alien_continue ; bge + + ; only if closer than previous found + lda RIGHT_SHOOT_LIMIT + cmp alien_x,X + bcc calc_gun_right_alien_continue ; blt + + lda alien_state,X + cmp #A_DISINTEGRATING + beq calc_gun_right_alien_continue + +calc_gun_right_alien_there: + lda alien_x,X + sta RIGHT_SHOOT_LIMIT + + txa ; set target if hit + ora #TARGET_ALIEN + sta RIGHT_SHOOT_TARGET + + ; can't early exit + +calc_gun_right_alien_continue: + inx + cpx #MAX_ALIENS + bne calc_gun_right_alien_loop + +done_calc_gun_right_alien_collision: + + + rts + + + + ;============================= + ;============================= + ; calc_gun_left_collision + ;============================= + ;============================= + ; far right limit is LEVEL_LEFT + ; any LOCKED or CLOSED doors stop things + ; any shield stops things + ; our friend stops things + ; any enemies stop things + +calc_gun_left_collision: + + lda #0 + sta LEFT_SHOOT_TARGET + + ;============================= + ; by default set to left limit + ; tricky as LEFT_LIMIT does some hacks to put it up above $80 + + lda LEFT_LIMIT + sec + sbc #$80 + bpl left_limit_ok + lda #0 + +left_limit_ok: + sta LEFT_SHOOT_LIMIT + + ;========================== + ; stop if hit door + +calc_gun_left_door: + lda NUM_DOORS + beq done_calc_gun_left_door_collision + +calc_gun_left_doors: + + + ldy NUM_DOORS + dey +calc_gun_left_door_loop: + + ; only if on same level + lda (DOOR_Y),Y + clc + adc #4 + cmp COLLISION_Y + bne calc_gun_left_door_continue + + lda COLLISION_X + cmp (DOOR_X),Y + bcc calc_gun_left_door_continue ; blt + + lda (DOOR_STATUS),Y + cmp #DOOR_STATUS_LOCKED + beq calc_gun_left_door_there + cmp #DOOR_STATUS_CLOSED + bne calc_gun_left_door_continue + +calc_gun_left_door_there: + ; early exit + lda (DOOR_X),Y + sta LEFT_SHOOT_LIMIT + + tya ; set target if hit + ora #TARGET_DOOR + sta LEFT_SHOOT_TARGET + + jmp done_calc_gun_left_door_collision + +calc_gun_left_door_continue: + dey + bpl calc_gun_left_door_loop + +done_calc_gun_left_door_collision: + + + ;========================== + ; adjust for shield + +calc_gun_left_shield: + + lda SHIELD_OUT + beq done_calc_gun_left_shield_collision + + ldx #0 + +calc_gun_left_shield_loop: + + ; if shield not out, skip + lda shield_out,X + beq calc_gun_left_shield_continue + + ; if current wall is closer, skip + lda COLLISION_X + cmp shield_x,X + bcc calc_gun_left_shield_continue ; blt + + ; be sure closer than current max limit + lda LEFT_SHOOT_LIMIT + cmp shield_x,X + bcs calc_gun_left_shield_continue ; bge + +calc_gun_left_shield_there: + + lda shield_x,X + sta LEFT_SHOOT_LIMIT + + txa ; set target if hit + ora #TARGET_SHIELD + sta LEFT_SHOOT_TARGET + + ; can't early exit + +calc_gun_left_shield_continue: + inx + cpx #MAX_SHIELDS + bne calc_gun_left_shield_loop + + +done_calc_gun_left_shield_collision: + + + ;========================== + ; adjust for friend + +calc_gun_left_friend: + + lda friend_room + cmp WHICH_ROOM + bne done_calc_gun_left_friend_collision + + lda COLLISION_X + cmp friend_x + bcc calc_gun_left_friend_continue ; blt + + ; only if closer than previous found + lda LEFT_SHOOT_LIMIT + cmp friend_x + bcs calc_gun_left_friend_continue ; bge + + lda friend_state + cmp #F_DISINTEGRATING + beq calc_gun_left_friend_continue + +calc_gun_left_friend_there: + + lda friend_x + sta LEFT_SHOOT_LIMIT + ; set target if hit + lda #TARGET_FRIEND + sta LEFT_SHOOT_TARGET + +calc_gun_left_friend_continue: +done_calc_gun_left_friend_collision: + + + + ;========================== + ; adjust for physicist + +calc_gun_left_physicist: + + lda COLLISION_X + cmp PHYSICIST_X + beq calc_gun_left_physicist_continue ; ble (not w self) + bcc calc_gun_left_physicist_continue ; blt + + ; only if closer than previous found + lda LEFT_SHOOT_LIMIT + cmp PHYSICIST_X + bcs calc_gun_left_physicist_continue ; bge + + lda PHYSICIST_STATE + cmp #P_DISINTEGRATING + beq calc_gun_left_physicist_continue + +calc_gun_left_physicist_there: + + lda PHYSICIST_X + sta LEFT_SHOOT_LIMIT + ; set target if hit + lda #TARGET_PHYSICIST + sta LEFT_SHOOT_TARGET + +calc_gun_left_physicist_continue: +done_calc_gun_left_physicist_collision: + + + + + ;========================== + ; adjust for alien + +calc_gun_left_alien: + + lda ALIEN_OUT + beq done_calc_gun_left_alien_collision + + ldx #MAX_ALIENS + dex + +calc_gun_left_alien_loop: + + lda alien_room,X + cmp WHICH_ROOM + bne calc_gun_left_alien_continue + + ; only if on same level + lda alien_y,X + cmp COLLISION_Y + bne calc_gun_left_alien_continue + + lda COLLISION_X + cmp alien_x,X + beq calc_gun_left_alien_continue ; if exact equal + ; might be ourselves + bcc calc_gun_left_alien_continue ; blt + + ; only if closer than previous found + lda LEFT_SHOOT_LIMIT + cmp alien_x,X + bcs calc_gun_left_alien_continue ; bge + + lda alien_state,X + cmp #A_DISINTEGRATING + beq calc_gun_left_alien_continue + +calc_gun_left_alien_there: + ; early exit + lda alien_x,X + sta LEFT_SHOOT_LIMIT + + txa ; set target if hit + ora #TARGET_ALIEN + sta LEFT_SHOOT_TARGET + + jmp done_calc_gun_left_alien_collision + +calc_gun_left_alien_continue: + dex + bpl calc_gun_left_alien_loop + +done_calc_gun_left_alien_collision: + + + rts + + diff --git a/another_myst/door.s b/another_myst/door.s new file mode 100644 index 00000000..c44b074c --- /dev/null +++ b/another_myst/door.s @@ -0,0 +1,401 @@ +DOOR_STATUS_OPENING1 = $00 +DOOR_STATUS_OPENING2 = $01 +DOOR_STATUS_OPEN = $02 +DOOR_STATUS_CLOSING1 = $03 +DOOR_STATUS_CLOSING2 = $04 +DOOR_STATUS_CLOSED = $05 +DOOR_STATUS_EXPLODED = $06 +DOOR_STATUS_LOCKED = $07 +DOOR_STATUS_EXPLODING1 = $08 +DOOR_STATUS_EXPLODING2 = $09 +DOOR_STATUS_EXPLODING3 = $0A +DOOR_STATUS_EXPLODING4 = $0B +DOOR_STATUS_EXPLODING5 = $0C +DOOR_STATUS_EXPLODING6 = $0D + + + ;================================== + ; draw_doors + ;================================== + ; be sure to smc to point to right place + +draw_doors: + lda NUM_DOORS + beq done_draw_doors + + ldy #0 +draw_doors_loop: + + lda (DOOR_STATUS),Y + tax + + lda door_sprite_lookup_lo,X + sta INL + lda door_sprite_lookup_hi,X + sta INH + +actually_draw_door: + lda (DOOR_X),Y + sta XPOS + + lda (DOOR_Y),Y + sta YPOS + + tya + pha + + lda (DOOR_STATUS),Y + cmp #DOOR_STATUS_EXPLODING1 + bcs draw_exploding_door + + jsr put_sprite_crop + +after_door_put_sprite: + + pla + tay + +draw_doors_continue: + iny + cpy NUM_DOORS + bne draw_doors_loop + +done_draw_doors: + + rts + +draw_exploding_door: + + lda FRAMEL + and #$7 + bne not_done_exploding_door + + lda (DOOR_STATUS),Y + clc + adc #1 + sta (DOOR_STATUS),Y + + cmp #DOOR_STATUS_EXPLODING6 + bcc not_done_exploding_door + + lda #DOOR_STATUS_EXPLODED + sta (DOOR_STATUS),Y + +not_done_exploding_door: + dec XPOS + + jsr put_sprite_crop + + jmp after_door_put_sprite + + + + ;========================== + ;========================== + ; handle doors + ;========================== + ;========================== +handle_doors: + + lda NUM_DOORS + beq done_handle_doors + + ldy #0 +handle_doors_loop: + + ; state machine + lda (DOOR_STATUS),Y + + ; if locked->do nothing + cmp #DOOR_STATUS_LOCKED + beq handle_doors_continue + + ; if exploded->do nothing + cmp #DOOR_STATUS_EXPLODED + beq handle_doors_continue + + + ; if closed and xpos/ypos in range: open + ; if open and xpos/ypos not ni range: close + cmp #DOOR_STATUS_OPEN + beq handle_doors_open + cmp #DOOR_STATUS_CLOSED + beq handle_doors_closed + + ; if exploding: continue exploding + ; we handle the increment elsewhere + cmp #DOOR_STATUS_EXPLODING1 + bcs handle_doors_continue ; bge + + ; if opening, continue to open + ; if closing, continue to close +handle_door_inc_state: + lda (DOOR_STATUS),Y + clc + adc #1 + sta (DOOR_STATUS),Y + +handle_doors_continue: + iny + cpy NUM_DOORS + bne handle_doors_loop + +done_handle_doors: + rts + +handle_doors_open: + + ; only open/close if on same level + lda (DOOR_Y),Y + clc + adc #4 + cmp PHYSICIST_Y + bne close_door + + lda PHYSICIST_X + cmp (DOOR_XMAX),Y + bcs close_door ; bge + + cmp (DOOR_XMIN),Y + bcc close_door ; blt + + ; made it here, we are in bounds, stay open + + jmp handle_doors_continue + +close_door: + lda #DOOR_STATUS_CLOSING1 + sta (DOOR_STATUS),Y + jmp handle_doors_continue + +handle_doors_closed: + + ; only open if on same level + + lda (DOOR_Y),Y + clc + adc #4 + cmp PHYSICIST_Y + bne handle_doors_continue + + lda PHYSICIST_X + cmp (DOOR_XMAX),Y + bcs handle_doors_continue + + cmp (DOOR_XMIN),Y + bcc handle_doors_continue + +open_door: + lda #DOOR_STATUS_OPENING1 + sta (DOOR_STATUS),Y + jmp handle_doors_continue + + + ;==================== + ;==================== + ; setup door table + ;==================== + ;==================== +setup_door_table: + + ldx #9 +setup_door_table_loop: +setup_door_table_loop_smc: + lda $1000,X + sta DOOR_STATUS,X + dex + bpl setup_door_table_loop + rts + + + + + +;====================================== +;====================================== +; door sprites +;====================================== +;====================================== + + +door_sprite_lookup_lo: + .byte door_opening_sprite1 ; DOOR_STATUS_OPENING1 + .byte >door_opening_sprite2 ; DOOR_STATUS_OPENING2 + .byte >door_open_sprite ; DOOR_STATUS_OPEN + .byte >door_closing_sprite1 ; DOOR_STATUS_CLOSING1 + .byte >door_closing_sprite2 ; DOOR_STATUS_CLOSING2 + .byte >door_closed_sprite ; DOOR_STATUS_CLOSED + .byte >door_exploded_sprite ; DOOR_STATUS_EXPLODED + .byte >door_closed_sprite ; DOOR_STATUS_LOCKED + .byte >door_exploding_sprite1 ; DOOR_STATUS_EXPLODING1 + .byte >door_exploding_sprite2 ; DOOR_STATUS_EXPLODING2 + .byte >door_exploding_sprite3 ; DOOR_STATUS_EXPLODING3 + .byte >door_exploding_sprite4 ; DOOR_STATUS_EXPLODING4 + .byte >door_exploding_sprite5 ; DOOR_STATUS_EXPLODING5 + .byte >door_exploding_sprite6 ; DOOR_STATUS_EXPLODING6 + + +door_closed_sprite: + .byte 1,10 + .byte $00 + .byte $00 + .byte $00 + .byte $00 + .byte $00 + .byte $00 + .byte $00 + .byte $00 + .byte $00 + .byte $00 + +door_open_sprite: + .byte 1,10 + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + +door_opening_sprite2: +door_closing_sprite1: + .byte 1,10 + .byte $00 + .byte $A0 + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $0A + .byte $00 + +door_opening_sprite1: +door_closing_sprite2: + .byte 1,10 + .byte $00 + .byte $00 + .byte $00 + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $00 + .byte $00 + .byte $00 + + +door_exploded_sprite: + .byte 1,10 + .byte $00 + .byte $A5 + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $AA + .byte $A5 + +door_exploding_sprite1: + .byte 3,10 + .byte $AA,$FF,$66 + .byte $AA,$FF,$66 + .byte $AA,$FF,$AA + .byte $AA,$FF,$AA + .byte $AA,$FF,$AA + .byte $AA,$FF,$AA + .byte $AA,$FF,$AA + .byte $AA,$FF,$AA + .byte $AA,$FF,$66 + .byte $AA,$FF,$66 + +door_exploding_sprite2: + .byte 3,10 + .byte $AA,$FF,$EE + .byte $AA,$FF,$EE + .byte $EE,$FF,$EE + .byte $FF,$FF,$EE + .byte $FF,$FF,$EE + .byte $FF,$FF,$EE + .byte $EE,$FF,$EE + .byte $AA,$FF,$EE + .byte $AA,$FF,$EE + .byte $AA,$FF,$EE + +door_exploding_sprite3: + .byte 3,10 + .byte $AA,$00,$AA + .byte $AA,$A5,$AA + .byte $FF,$AA,$AA + .byte $FF,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $FF,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$A5,$AA + +door_exploding_sprite4: + .byte 3,10 + .byte $AA,$00,$AA + .byte $AA,$A5,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $FF,$AA,$AA + .byte $FF,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $FF,$AA,$AA + .byte $AA,$A5,$AA + +door_exploding_sprite5: + .byte 3,10 + .byte $AA,$00,$AA + .byte $AA,$A5,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $FA,$AA,$AA + .byte $AF,$A5,$AA + +door_exploding_sprite6: + .byte 3,10 + .byte $AA,$00,$AA + .byte $AA,$A5,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $AA,$AA,$AA + .byte $FA,$AA,$AA + .byte $AF,$A5,$AA + + diff --git a/another_myst/dummy_friend.s b/another_myst/dummy_friend.s new file mode 100644 index 00000000..fe332026 --- /dev/null +++ b/another_myst/dummy_friend.s @@ -0,0 +1,26 @@ +; Include on levels where there is no friend + + +FAI_FOLLOWING = 0 +FAI_RUNTO_PANEL = 1 +FAI_OPENING_PANEL = 2 +FAI_DISINTEGRATING = 3 +FAI_END_L2 = 4 + + +F_STANDING = 0 +F_WALKING = 1 +F_RUNNING = 2 +F_CROUCHING = 3 +F_TURNING = 4 +F_KEYPAD = 5 +F_OPEN_VENT = 6 +F_DISINTEGRATING= 7 + +friend_ai_state: +friend_state: +friend_x: +friend_gait: +.byte $00 +friend_room: +.byte $ff diff --git a/another_myst/friend.s b/another_myst/friend.s new file mode 100644 index 00000000..8bbde57d --- /dev/null +++ b/another_myst/friend.s @@ -0,0 +1,492 @@ +; draw/move our friend + +friend_room: .byte 0 ; $FF means not out +friend_x: .byte 0 +friend_y: .byte 0 +friend_state: .byte 0 +friend_gait: .byte 0 +friend_direction: .byte 0 +friend_ai_state: .byte 0 + +FAI_FOLLOWING = 0 +FAI_RUNTO_PANEL = 1 +FAI_OPENING_PANEL = 2 +FAI_DISINTEGRATING = 3 +FAI_END_L2 = 4 + + +F_STANDING = 0 +F_WALKING = 1 +F_RUNNING = 2 +F_CROUCHING = 3 +F_TURNING = 4 +F_KEYPAD = 5 +F_OPEN_VENT = 6 +F_DISINTEGRATING= 7 + +fai_table_lo: + .byte friend_ai_following ; 00 + .byte >friend_ai_runto_panel ; 01 + .byte >friend_ai_opening_panel ; 02 + .byte >friend_ai_disintegrating ; 03 + .byte >friend_ai_end_l2 ; 04 + + + ;======================================= + ; Process friend AI + ; + +handle_friend_ai: + + lda friend_ai_state + tay + lda fai_table_lo,y + sta fjump + lda fai_table_hi,y + sta fjump+1 + jmp (fjump) + + rts + +friend_ai_end_l2: + ; FAI_END_L2 + ; crouch, holding panel open + rts + +friend_ai_following: + ; FAI_FOLLOWING + ; if x> phys_x by more than 8, walk left + ; if x< phys_x by more than 8, walk right + +friend_ai_runto_panel: + ; FAI_RUNTO_PANEL + ; otherwise, if not in ROOM#2, run right + ; if in room#2, run to panel + + lda #1 + sta friend_direction + + lda #F_RUNNING + sta friend_state + + lda WHICH_ROOM + cmp #3 + bne ai_runto_panel_done + + lda friend_x + cmp #30 + bcc ai_runto_panel_done + + ; hack, if running stop wrong place? + lda #31 + sta friend_x + + lda #FAI_OPENING_PANEL + sta friend_ai_state + + lda #0 + sta friend_direction + +ai_runto_panel_done: + jmp friend_ai_done + +friend_ai_opening_panel: + ; FAI_OPENING_PANEL + ; if door2 unlocked -> FAI_FOLLOWING + + ; FIXME: open panel for a bit, then open door and continue + lda #F_KEYPAD + sta friend_state + +friend_ai_disintegrating: +friend_ai_done: + rts + + + ;======================================= + ; Move friend based on current state + ; + +move_friend: + lda friend_room + cmp WHICH_ROOM + bne done_move_friend + + jsr handle_friend_ai + + lda friend_state + beq done_move_friend + + lda friend_state + + cmp #F_WALKING + beq move_friend_walking + cmp #F_RUNNING + beq move_friend_running + +done_move_friend: + rts + + ;====================== + ; walking + +move_friend_walking: + inc friend_gait ; cycle through animation + + lda friend_gait + and #$f + cmp #$8 ; only walk roughly 1/8 of time + bne friend_no_move_walk + + lda friend_direction + beq f_walk_left + + inc friend_x ; walk right + rts +f_walk_left: + dec friend_x ; walk left +friend_no_move_walk: + rts + + ;====================== + ; running +move_friend_running: + inc friend_gait ; cycle through animation + + lda friend_gait + and #$7 + cmp #5 ; only run roughly 3/8 of time + bcc friend_no_move_run + + lda friend_direction + beq f_run_left + + inc friend_x ; run right + jmp friend_running_check_limits +f_run_left: + dec friend_x ; run left +friend_no_move_run: + +friend_running_check_limits: + lda friend_x + cmp #39 + bcc friend_done_running ; blt + + ; move to next room + lda #0 + sta friend_x + + inc friend_room + +friend_done_running: + rts + + ;====================== + ; standing + +move_friend_standing: + + + + + +fstate_table_lo: + .byte friend_standing ; 00 + .byte >friend_walking ; 01 + .byte >friend_running ; 02 + .byte >friend_crouching ; 03 + .byte >friend_turning ; 04 + .byte >friend_keypad ; 05 KEYPAD + .byte >friend_open_vent ; 06 + .byte >friend_disintegrating ; 07 + +; Urgh, make sure this doesn't end up at $FF or you hit the +; NMOS 6502 bug + +.align 2 + +fjump: + .word $0000 +.align 1 + +;====================================== +; draw friend +;====================================== + +draw_friend: + + lda friend_room + cmp WHICH_ROOM + bne no_friend + + lda friend_state + tay + lda fstate_table_lo,y + sta fjump + lda fstate_table_hi,y + sta fjump+1 + jmp (fjump) + +no_friend: + rts + +;================================== +; STANDING +;================================== + +friend_standing: + + lda #friend_stand + sta INH + + jmp finally_draw_friend + + +;=================================== +; CROUCHING +;=================================== + +friend_crouching: + + ; FIXME: we have an animation? + + lda #friend_crouch2 + sta INH + + jmp finally_draw_friend + +;=================================== +; OPEN_VENT +;=================================== + +friend_open_vent: + + ; draw vent -- HACK + + lda #1 + sta VENT_OPEN + + lda #$00 + sta COLOR + + ; X, V2 at Y + ; from x=top, v2=bottom + + + ldy #18 + lda #48 + sta V2 + ldx #24 + jsr vlin + + ldy #19 + lda #48 + sta V2 + ldx #24 + jsr vlin + + + + lda #21 + sta friend_x + lda #8 + sta friend_y + + lda #friend_crouch2 + sta INH + + jmp finally_draw_friend + + + +;=============================== +; Walking +;================================ + +friend_walking: + lda friend_gait + cmp #64 + bcc friend_gait_fine ; blt + + lda #0 + sta friend_gait + +friend_gait_fine: + lsr + lsr + and #$fe + + tay + + lda friend_walk_progression,Y + sta INL + + lda friend_walk_progression+1,Y + sta INH + + jmp finally_draw_friend + +;=============================== +; Running +;================================ + +friend_running: + lda friend_gait + cmp #32 + bcc friend_run_gait_fine ; blt + + lda #0 + sta friend_gait + +friend_run_gait_fine: + lsr + and #$fe + + tay + + lda friend_run_progression,Y + sta INL + + lda friend_run_progression+1,Y + sta INH + + jmp finally_draw_friend + +;=============================== +; Turning +;================================ + +friend_turning: + + dec friend_gait + bpl friend_draw_turning + + lda #0 + sta friend_gait + + ; switch direction + lda friend_direction + eor #$1 + sta friend_direction + + lda #F_WALKING + sta friend_state + +friend_draw_turning: + lda #friend_turning_sprite + sta INH + + jmp finally_draw_friend + + +;=============================== +; Using Keypad +;================================ + +friend_keypad: + + inc friend_gait + + lda friend_gait + and #$10 + lsr + lsr + lsr + tay + +friend_draw_keypad: + lda friend_keypad_progression,Y + sta INL + + lda friend_keypad_progression+1,Y + sta INH + + jmp finally_draw_friend + +;=============================== +; Disintegrating +;================================ + +friend_disintegrating: + lda friend_gait + cmp #13 + bne friend_keep_disintegrating + + lda #$ff + sta friend_room + + rts + +friend_keep_disintegrating: + asl + tay + + ; re-use alien sprites + + lda alien_disintegrating_progression,Y + sta INL + + lda alien_disintegrating_progression+1,Y + sta INH + + lda FRAMEL + and #$7 + bne slow_friend_disintegration + + inc friend_gait +slow_friend_disintegration: + + jmp finally_draw_friend + + + +;============================= +; Actually Draw Friend +;============================= + + +finally_draw_friend: + lda friend_x + sta XPOS + + lda friend_y + sta YPOS + + lda friend_direction + bne friend_facing_right + +friend_facing_left: + jmp put_sprite_crop + +friend_facing_right: + jmp put_sprite_flipped_crop + diff --git a/another_myst/gr_hlin.s b/another_myst/gr_hlin.s new file mode 100644 index 00000000..51d7c91f --- /dev/null +++ b/another_myst/gr_hlin.s @@ -0,0 +1,34 @@ + ;=============================== + ; hlin + ;=============================== + ; Y = y position + ; A = start + ; X = length +hlin: + clc + adc gr_offsets,Y + sta hlin_smc1+1 + sta hlin_smc2+1 + + lda gr_offsets+1,Y + clc + adc DRAW_PAGE + sta hlin_smc1+2 + sta hlin_smc2+2 + + +hlin_loop: + +hlin_smc1: + lda $c00,X +hlin_mask_smc: + and #$f0 +hlin_color_smc: + ora #$01 +hlin_smc2: + sta $c00,X + + dex + bpl hlin_loop + + rts diff --git a/another_myst/gr_putsprite.s b/another_myst/gr_putsprite.s new file mode 100644 index 00000000..da9253f5 --- /dev/null +++ b/another_myst/gr_putsprite.s @@ -0,0 +1,152 @@ + + ;============================================= + ; put_sprite + ;============================================= + ; Sprite to display in INH,INL + ; Location is XPOS,YPOS + ; Note, only works if YPOS is multiple of two + + ; transparent color is $A (grey #2) + ; this means we can have black ($0) in a sprite + + ; also note all the cycle count is out of date + + ; time= 28 setup + ; Y*outerloop + ; outerloop = 34 setup + ; X*innerloop + ; innerloop = 30 if $00 17+13(done) + ; 64 if $0X 16+7+8+20(put_sprite_mask)+13(done) + ; 69 if $X0 16+8+7+5+20(put_sprite_mask)+13(done) + ; 54 if if $XX 16+8+8+9(put_all)+13(done) + + + ; -1 for last iteration + ; 18 (-1 for last) + ; 6 return + + ; so cost = 28 + Y*(34+18)+ (INNER-Y) -1 + 6 + ; = 33 + Y*(52)+(INNER-Y) + ; = 33 + Y*(52)+ [30A + 64B + 69C + 54D]-Y + +put_sprite: + + ldy #0 ; byte 0 is xsize ; 2 + lda (INL),Y ; 5 + sta CH ; xsize is in CH ; 3 + iny ; 2 + + lda (INL),Y ; byte 1 is ysize ; 5 + sta CV ; ysize is in CV ; 3 + iny ; 2 + + lda YPOS ; make a copy of ypos ; 3 + sta TEMPY ; as we modify it ; 3 + ;=========== + ; 28 +put_sprite_loop: + sty TEMP ; save sprite pointer ; 3 + ldy TEMPY ; 3 + lda gr_offsets,Y ; lookup low-res memory address ; 4 + clc ; 2 + adc XPOS ; add in xpos ; 3 + sta OUTL ; store out low byte of addy ; 3 + lda gr_offsets+1,Y ; look up high byte ; 4 + adc DRAW_PAGE ; ; 3 + sta OUTH ; and store it out ; 3 + ldy TEMP ; restore sprite pointer ; 3 + + ; OUTH:OUTL now points at right place + + ldx CH ; load xsize into x ; 3 + ;=========== + ; 34 +put_sprite_pixel: + lda (INL),Y ; get sprite colors ; 5 + iny ; increment sprite pointer ; 2 + + sty TEMP ; save sprite pointer ; 3 + ldy #$0 ; 2 + + ; check if completely transparent + ; if so, skip + + cmp #$aa ; if all zero, transparent ; 2 + beq put_sprite_done_draw ; don't draw it ; 2nt/3 + ;============== + ; 16/17 + + sta COLOR ; save color for later ; 3 + + ; check if top pixel transparent + + and #$f0 ; check if top nibble zero ; 2 + cmp #$a0 + bne put_sprite_bottom ; if not skip ahead ; 2nt/3 + ;============== + ; 7/8 + + lda COLOR + and #$0f + sta COLOR + + lda #$f0 ; setup mask ; 2 + sta MASK ; 3 + bmi put_sprite_mask ; always? ; 3 + ;============= + ; 8 + +put_sprite_bottom: + lda COLOR ; re-load color ; 3 + and #$0f ; check if bottom nibble zero ; 2 + cmp #$0a + bne put_sprite_all ; if not, skip ahead ; 2nt/3 + ;============= + ; 7/8 + + lda COLOR + and #$f0 + sta COLOR + lda #$0f ; 2 + sta MASK ; setup mask ; 3 + ;=========== + ; 5 + +put_sprite_mask: + lda (OUTL),Y ; get color at output ; 5 + and MASK ; mask off unneeded part ; 3 + ora COLOR ; or the color in ; 3 + sta (OUTL),Y ; store it back ; 6 + + jmp put_sprite_done_draw ; we are done ; 3 + ;=========== + ; 20 + +put_sprite_all: + lda COLOR ; load color ; 3 + sta (OUTL),Y ; and write it out ; 6 + ;============ + ; 9 + +put_sprite_done_draw: + + ldy TEMP ; restore sprite pointer ; 3 + + inc OUTL ; increment output pointer ; 5 + dex ; decrement x counter ; 2 + bne put_sprite_pixel ; if not done, keep looping ; 2nt/3 + ;============== + ; 12/13 + + inc TEMPY ; each line has two y vars ; 5 + inc TEMPY ; 5 + dec CV ; decemenet total y count ; 5 + bne put_sprite_loop ; loop if not done ; 2nt/3 + ;============== + ; 17/18 + + rts ; return ; 6 + + + + diff --git a/another_myst/gr_putsprite_crop.s b/another_myst/gr_putsprite_crop.s new file mode 100644 index 00000000..cdd67f9a --- /dev/null +++ b/another_myst/gr_putsprite_crop.s @@ -0,0 +1,353 @@ + ;============================================= + ; put_sprite_crop + ;============================================= + ; Sprite to display in INH,INL + ; Location is XPOS,YPOS + ; Note, only works if YPOS is multiple of two + + ; transparent color is $A (grey #2) + ; this means we can have black ($0) in a sprite + + ; FIXME: force YPOS to be even? + +put_sprite_crop: + + ldy #0 ; byte 0 is xsize ; 2 + lda (INL),Y ; 5 + sta CH ; xsize is in CH ; 3 + iny ; 2 + clc + adc XPOS + sta XMAX + + lda (INL),Y ; byte 1 is ysize ; 5 + sta CV ; ysize is in CV ; 3 + iny ; 2 + + lda YPOS ; make a copy of ypos ; 3 + sta TEMPY ; as we modify it ; 3 + ;=========== + ; 28 +put_sprite_crop_loop: + sty TEMP ; save sprite pointer ; 3 + ldy TEMPY ; 3 + + bpl put_sprite_crop_pos ; if < 0, skip to next + + clc ; skip line in sprite too + lda TEMP + adc CH + tay + + bne crop_increment_y + +put_sprite_crop_pos: + cpy #48 ; bge if >= 48, done sprite + bcs crop_sprite_done + + + lda gr_offsets,Y ; lookup low-res memory address ; 4 + clc ; 2 + adc XPOS ; add in xpos ; 3 + sta OUTL ; store out low byte of addy ; 3 + clc ; never wraps, handle negative + lda gr_offsets+1,Y ; look up high byte ; 4 + adc DRAW_PAGE ; ; 3 + sta OUTH ; and store it out ; 3 + ldy TEMP ; restore sprite pointer ; 3 + + ; OUTH:OUTL now points at right place + + ldx XPOS ; load xposition into x ; 3 + ;=========== + ; 34 +crop_put_sprite_pixel: + lda (INL),Y ; get sprite colors ; 5 + iny ; increment sprite pointer ; 2 + sty TEMP ; save sprite pointer ; 3 + + + cpx #0 ; if off-screen left, skip draw + bmi skip_drawing + cpx #40 + bcs skip_drawing ; if off-screen right, skip draw + + ldy #$0 ; 2 + + ; check if completely transparent + ; if so, skip + + cmp #$aa ; if all zero, transparent ; 2 + beq crop_put_sprite_done_draw ; don't draw it ; 2nt/3 + ;============== + ; 16/17 + + sta COLOR ; save color for later ; 3 + + ; check if top pixel transparent + + and #$f0 ; check if top nibble zero ; 2 + cmp #$a0 + bne crop_put_sprite_bottom ; if not skip ahead ; 2nt/3 + ;============== + ; 7/8 + + lda COLOR + and #$0f + sta COLOR + + lda #$f0 ; setup mask ; 2 + sta MASK ; 3 + bmi crop_put_sprite_mask ; always? ; 3 + ;============= + ; 8 + +crop_put_sprite_bottom: + lda COLOR ; re-load color ; 3 + and #$0f ; check if bottom nibble zero ; 2 + cmp #$0a + bne crop_put_sprite_all ; if not, skip ahead ; 2nt/3 + ;============= + ; 7/8 + + lda COLOR + and #$f0 + sta COLOR + lda #$0f ; 2 + sta MASK ; setup mask ; 3 + ;=========== + ; 5 + +crop_put_sprite_mask: + lda (OUTL),Y ; get color at output ; 5 + and MASK ; mask off unneeded part ; 3 + ora COLOR ; or the color in ; 3 + sta (OUTL),Y ; store it back ; 6 + + jmp crop_put_sprite_done_draw ; we are done ; 3 + ;=========== + ; 20 + +crop_put_sprite_all: + lda COLOR ; load color ; 3 + sta (OUTL),Y ; and write it out ; 6 + ;============ + ; 9 + +crop_put_sprite_done_draw: +skip_drawing: + + ldy TEMP ; restore sprite pointer ; 3 + + inc OUTL ; increment output pointer ; 5 + inx ; increment x counter ; 2 + cpx XMAX + bne crop_put_sprite_pixel ; if not done, keep looping ; 2nt/3 + ;============== + ; 12/13 +crop_increment_y: + + inc TEMPY ; each line has two y vars ; 5 + inc TEMPY ; 5 + dec CV ; decemenet total y count ; 5 + bne put_sprite_crop_loop ; loop if not done ; 2nt/3 + ;============== + ; 17/18 +crop_sprite_done: + rts ; return ; 6 + + + +; 0,0 = 400+0 +; -1,0 = 400+ff=4ff, inc=400 + +; sprite: 5x4 +; +; -2,0 Xstart=0, sprite_offset=2, xsize=3 +; -1,0, Xstart=0, sprite_offset=1, xsize=4 +; 0,0, Xstrat=0, sprite_offset=0, xsize=5 +; 1,0, Xstart=1, sprite_offset=0, xsize=5 +; +; 39,0 Xstart=39, sprite_offset=0, xsize=1 +; +; +; +; + + ;============================================= + ; put_sprite_flipped_crop + ;============================================= + ; Sprite to display in INH,INL + ; Location is XPOS,YPOS + ; Note, only works if YPOS is multiple of two + + ; transparent color is $A (grey #2) + ; this means we can have black ($0) in a sprite + + +put_sprite_flipped_crop: + + ldy #0 ; byte 0 is xsize ; 2 + lda (INL),Y ; 5 + sta CH ; xsize is in CH ; 3 + iny ; 2 + + + lda (INL),Y ; byte 1 is ysize ; 5 + sta CV ; ysize is in CV ; 3 + dey ; make Y zero again ; 2 + + lda INH ; ??? + sta ppfc_smc+2 + clc + lda INL + adc #1 ; add one (not two) because X counts + ; from CH to 1 (not CH-1 to 0) + sta ppfc_smc+1 + bcc psfc16 + inc ppfc_smc+2 +psfc16: + + + lda YPOS ; make a copy of ypos ; 3 + + sta TEMPY ; as we modify it ; 3 + ;=========== + ; 28 + + + +put_spritefc_loop: +; sty TEMP ; save sprite pointer ; 3 + ldy TEMPY ; 3 + + bmi fcrop_increment_y ; if < 0, skip to next + cpy #48 ; bge if >= 48, done sprite + bcs fcrop_sprite_done + + + lda gr_offsets,Y ; lookup low-res memory address ; 4 + clc ; 2 + adc XPOS ; add in xpos ; 3 + sta OUTL ; store out low byte of addy ; 3 + lda gr_offsets+1,Y ; look up high byte ; 4 + clc + adc DRAW_PAGE ; ; 3 + sta OUTH ; and store it out ; 3 +; ldy TEMP ; restore sprite pointer ; 3 + + ; OUTH:OUTL now points at right place + + ldx CH ; load xsize into x ; 3 + ;=========== + ; 34 +put_spritefc_pixel: + + clc + txa ; want (CH-X-1)+XPOS + eor #$ff + adc CH + adc XPOS + + bmi cskip_drawing + cmp #40 + + bcs cskip_drawing ; if off-screen right, skip draw + +ppfc_smc: + lda $C000,X ; get sprite colors ; 5 +; iny ; increment sprite pointer ; 2 +; sty TEMP ; save sprite pointer ; 3 + ldy #$0 ; 2 + + ; check if completely transparent + ; if so, skip + + cmp #$aa ; if all zero, transparent ; 2 + beq put_spritefc_done_draw ; don't draw it ; 2nt/3 + ;============== + ; 16/17 + + sta COLOR ; save color for later ; 3 + + ; check if top pixel transparent + + and #$f0 ; check if top nibble zero ; 2 + cmp #$a0 + bne put_spritefc_bottom ; if not skip ahead ; 2nt/3 + ;============== + ; 7/8 + + lda COLOR + and #$0f + sta COLOR + + lda #$f0 ; setup mask ; 2 + sta MASK ; 3 + bmi put_spritefc_mask ; always? ; 3 + ;============= + ; 8 + +put_spritefc_bottom: + lda COLOR ; re-load color ; 3 + and #$0f ; check if bottom nibble zero ; 2 + cmp #$0a + bne put_spritefc_all ; if not, skip ahead ; 2nt/3 + ;============= + ; 7/8 + + lda COLOR + and #$f0 + sta COLOR + lda #$0f ; 2 + sta MASK ; setup mask ; 3 + ;=========== + ; 5 + +put_spritefc_mask: + lda (OUTL),Y ; get color at output ; 5 + and MASK ; mask off unneeded part ; 3 + ora COLOR ; or the color in ; 3 + sta (OUTL),Y ; store it back ; 6 + + jmp put_spritefc_done_draw ; we are done ; 3 + ;=========== + ; 20 + +put_spritefc_all: + lda COLOR ; load color ; 3 + sta (OUTL),Y ; and write it out ; 6 + ;============ + ; 9 + +put_spritefc_done_draw: +cskip_drawing: +; ldy TEMP ; restore sprite pointer ; 3 + + inc OUTL ; increment output pointer ; 5 + dex ; decrement x counter ; 2 + bne put_spritefc_pixel ; if not done, keep looping ; 2nt/3 + ;============== + ; 12/13 +fcrop_increment_y: + inc TEMPY ; each line has two y vars ; 5 + inc TEMPY ; 5 + + lda CH + clc + adc ppfc_smc+1 + sta ppfc_smc+1 + bcc psfco + inc ppfc_smc+2 +psfco: + + dec CV ; decemenet total y count ; 5 + beq fcrop_sprite_done ; loop if not done ; 2nt/3 + jmp put_spritefc_loop + ;============== + ; 17/18 + +fcrop_sprite_done: + rts ; return ; 6 + + diff --git a/another_myst/gr_putsprite_flipped.s b/another_myst/gr_putsprite_flipped.s new file mode 100644 index 00000000..0e5c623e --- /dev/null +++ b/another_myst/gr_putsprite_flipped.s @@ -0,0 +1,157 @@ + ;============================================= + ; put_sprite_flipped + ;============================================= + ; Sprite to display in INH,INL + ; Location is XPOS,YPOS + ; Note, only works if YPOS is multiple of two + + ; transparent color is $A (grey #2) + ; this means we can have black ($0) in a sprite + + +put_sprite_flipped: + + ldy #0 ; byte 0 is xsize ; 2 + lda (INL),Y ; 5 + sta CH ; xsize is in CH ; 3 + iny ; 2 + + + lda (INL),Y ; byte 1 is ysize ; 5 + sta CV ; ysize is in CV ; 3 + dey ; make Y zero again ; 2 + + lda INH + sta ppf_smc+2 + clc + lda INL + adc #1 ; add one (not two) because X counts + ; from CH to 1 (not CH-1 to 0) + sta ppf_smc+1 + bcc psf16 + inc ppf_smc+2 +psf16: + + + lda YPOS ; make a copy of ypos ; 3 + + sta TEMPY ; as we modify it ; 3 + ;=========== + ; 28 + + + +put_spritef_loop: + sty TEMP ; save sprite pointer ; 3 + ldy TEMPY ; 3 + lda gr_offsets,Y ; lookup low-res memory address ; 4 + clc ; 2 + adc XPOS ; add in xpos ; 3 + sta OUTL ; store out low byte of addy ; 3 + lda gr_offsets+1,Y ; look up high byte ; 4 + adc DRAW_PAGE ; ; 3 + sta OUTH ; and store it out ; 3 + ldy TEMP ; restore sprite pointer ; 3 + + ; OUTH:OUTL now points at right place + + ldx CH ; load xsize into x ; 3 + ;=========== + ; 34 +put_spritef_pixel: +ppf_smc: + lda $C000,X ; get sprite colors ; 5 + iny ; increment sprite pointer ; 2 + + sty TEMP ; save sprite pointer ; 3 + ldy #$0 ; 2 + + ; check if completely transparent + ; if so, skip + + cmp #$aa ; if all zero, transparent ; 2 + beq put_spritef_done_draw ; don't draw it ; 2nt/3 + ;============== + ; 16/17 + + sta COLOR ; save color for later ; 3 + + ; check if top pixel transparent + + and #$f0 ; check if top nibble zero ; 2 + cmp #$a0 + bne put_spritef_bottom ; if not skip ahead ; 2nt/3 + ;============== + ; 7/8 + + lda COLOR + and #$0f + sta COLOR + + lda #$f0 ; setup mask ; 2 + sta MASK ; 3 + bmi put_spritef_mask ; always? ; 3 + ;============= + ; 8 + +put_spritef_bottom: + lda COLOR ; re-load color ; 3 + and #$0f ; check if bottom nibble zero ; 2 + cmp #$0a + bne put_spritef_all ; if not, skip ahead ; 2nt/3 + ;============= + ; 7/8 + + lda COLOR + and #$f0 + sta COLOR + lda #$0f ; 2 + sta MASK ; setup mask ; 3 + ;=========== + ; 5 + +put_spritef_mask: + lda (OUTL),Y ; get color at output ; 5 + and MASK ; mask off unneeded part ; 3 + ora COLOR ; or the color in ; 3 + sta (OUTL),Y ; store it back ; 6 + + jmp put_spritef_done_draw ; we are done ; 3 + ;=========== + ; 20 + +put_spritef_all: + lda COLOR ; load color ; 3 + sta (OUTL),Y ; and write it out ; 6 + ;============ + ; 9 + +put_spritef_done_draw: + + ldy TEMP ; restore sprite pointer ; 3 + + inc OUTL ; increment output pointer ; 5 + dex ; decrement x counter ; 2 + bne put_spritef_pixel ; if not done, keep looping ; 2nt/3 + ;============== + ; 12/13 + + inc TEMPY ; each line has two y vars ; 5 + inc TEMPY ; 5 + + lda CH + clc + adc ppf_smc+1 + sta ppf_smc+1 + bcc psfo + inc ppf_smc+2 +psfo: + + dec CV ; decemenet total y count ; 5 + bne put_spritef_loop ; loop if not done ; 2nt/3 + ;============== + ; 17/18 + + rts ; return ; 6 + + diff --git a/another_myst/gun.s b/another_myst/gun.s new file mode 100644 index 00000000..38b8a304 --- /dev/null +++ b/another_myst/gun.s @@ -0,0 +1,287 @@ +; +; Gun behavior +; +; When 'L' pressed gun is charging +; we handle that here + + + ;=================================== + ; handle/draw all gun related stuff + ;=================================== +handle_gun: + + ;=================== + ; check_gun_firing + ;=================== + jsr check_gun_firing + + ;======================= + ; draw gun charge effect + ;======================= + + jsr draw_gun_charging + + ;================ + ; move laser + ;================ + + jsr move_laser + + ;================ + ; draw laser + ;================ + + jsr draw_laser + + ;================ + ; move blast + ;================ + + jsr move_blast + + ;================ + ; draw blast + ;================ + + jsr draw_blast + + ;================ + ; draw shields + ;================ + + jmp draw_shields + +; rts + + + ;==================== + ;==================== + ; check gun firing + ;==================== + ;==================== + +check_gun_firing: + + lda HAVE_GUN ; no gun, do nothing + beq no_have_gun + + ;================ + ; fire laser + ;================ + + lda LASER_OUT + beq no_fire_laser + jsr fire_laser +no_fire_laser: + lda #0 + sta LASER_OUT + + + lda GUN_STATE ; gun not charging, do nothing + beq done_gun + + lda GUN_FIRE ; if fired, fire it + bne fire_gun + + ; increment gun state + + lda FRAMEL ; slow down + and #$7 + bne done_inc_gun_state + + inc GUN_STATE + + ; saturate + + lda GUN_STATE + cmp #24 + bne done_inc_gun_state + + lda #21 ; wrap at end + sta GUN_STATE + +done_inc_gun_state: + + + jmp done_gun + +fire_gun: + ; fire here + + lda GUN_STATE + cmp #5 + bcc done_gun ; too short, do nothing + + cmp #21 + bcs do_blast ; too long, blast + + ; shield + + jsr activate_shield + jmp done_firing +do_blast: + jsr fire_blast + +done_firing: + lda #0 + sta GUN_STATE +done_gun: +no_have_gun: + lda #0 + sta GUN_FIRE + + rts + + + ;============================ + ; draw gun charging effect + ;============================ +draw_gun_charging: + + lda HAVE_GUN ; no gun, do nothing + beq done_draw_gun_charging + + lda GUN_STATE ; gun not charging, do nothing + beq done_draw_gun_charging + + + ; set direction + + lda DIRECTION + bne zap_right + +zap_left: + + ldx PHYSICIST_X + dex + dex + stx XPOS + + jmp done_zap + +zap_right: + + lda PHYSICIST_X + clc + adc #5 + sta XPOS +done_zap: + + lda PHYSICIST_Y + clc + adc #4 + + ldy PHYSICIST_STATE + cpy #P_CROUCH_SHOOTING + bne done_zap_ypos + clc + adc #4 + +done_zap_ypos: + sta YPOS + + ldy GUN_STATE + lda gun_charge_progression,Y + tay + + lda gun_charge_table_lo,Y + sta INL + + lda gun_charge_table_hi,Y + sta INH + + jsr put_sprite + +done_draw_gun_charging: + rts + +; progression + +gun_charge_progression: + .byte 0,0,0,1,2,3 + .byte 4,5,6,4,5,6,4,5,6,4,5,6,4,5,6 ; 20 + .byte 7,8,9 + +gun_charge_table_lo: + .byte gun_charge_sprite0 + .byte >gun_charge_sprite1 + .byte >gun_charge_sprite2 + .byte >gun_charge_sprite3 + .byte >gun_charge_sprite4 + .byte >gun_charge_sprite5 + .byte >gun_charge_sprite6 + .byte >gun_charge_sprite7 + .byte >gun_charge_sprite8 + .byte >gun_charge_sprite9 + + + +; startup + +gun_charge_sprite0: + .byte 2,2 + .byte $AA,$AA + .byte $AA,$AA + +gun_charge_sprite1: + .byte 2,2 + .byte $fA,$AA + .byte $AA,$AA + +gun_charge_sprite2: + .byte 2,2 + .byte $22,$AA + .byte $AA,$AA + +gun_charge_sprite3: + .byte 2,2 + .byte $ef,$eA + .byte $fe,$Ae + +; medium + +gun_charge_sprite4: + .byte 2,2 + .byte $ff,$AA + .byte $Ae,$AA + +gun_charge_sprite5: + .byte 2,2 + .byte $ef,$AA + .byte $Ae,$AA + +gun_charge_sprite6: + .byte 2,2 + .byte $ef,$AA + .byte $Af,$AA + +; large + +gun_charge_sprite7: + .byte 2,2 + .byte $fe,$fe + .byte $Ae,$Ae + +gun_charge_sprite8: + .byte 2,2 + .byte $fe,$fe + .byte $ef,$ef + +gun_charge_sprite9: + .byte 2,2 + .byte $ff,$ff + .byte $Ae,$Ae + + diff --git a/another_myst/keyboard.s b/another_myst/keyboard.s new file mode 100644 index 00000000..b2d9483a --- /dev/null +++ b/another_myst/keyboard.s @@ -0,0 +1,422 @@ + +;====================================== +; handle keypress +;====================================== + +; A or <- : start moving left +; D or -> : start moving right +; W or up : jump or elevator/transporter up +; S or down : crouch or pickup or elevator/transporter down +; L : charge gun +; space : action +; escape : quit + +; if left: if running right, walk right +; if walk right, stand right +; if stand right, stand left +; if stand left, walk left +; if walk left, run left +; if up: if crouching, stand up +; if standing, jump +; if walking, jump +; if running, run-jump +; if down: if standing, crouch +; if walking, crouch +; if if running, slide-crouch + + +handle_keypress: + + lda PHYSICIST_STATE + bmi no_keypress ; ignore keypress if dying/action + + lda KEYPRESS ; 4 + bmi keypress ; 3 +no_keypress: + bit KEYRESET ; clear + ; avoid keeping old keys around + rts ; nothing pressed, return + +keypress: + ; -1 + + and #$7f ; clear high bit + + ;====================== + ; check escape + +check_quit: + cmp #27 ; quit if ESCAPE pressed + bne check_left + + ;===================== + ; QUIT + ;===================== +quit: + lda #$ff ; could just dec + sta GAME_OVER + rts + + ;====================== + ; check left +check_left: + cmp #'A' + beq left_pressed + cmp #$8 ; left arrow + bne check_right + + + ;==================== + ;==================== + ; Left/A Pressed + ;==================== + ;==================== +left_pressed: + inc GUN_FIRE ; fire gun if charging + + ; left==0 + lda DIRECTION ; if facing right, turn to face left + bne left_going_right + +left_going_left: + lda PHYSICIST_STATE + cmp #P_STANDING + beq walk_left + cmp #P_SHOOTING + beq walk_left + cmp #P_WALKING + beq run_left + and #STATE_CROUCHING + bne stand_left + + ;============================= + ; already running, do nothing? + jmp done_keypress + +left_going_right: + lda PHYSICIST_STATE + cmp #P_RUNNING + beq walk_right + cmp #P_WALKING + beq stand_right + cmp #P_STANDING + beq stand_left + cmp #P_SHOOTING + beq stand_left + and #STATE_CROUCHING + bne stand_left + + ;=========================== + ; otherwise? + jmp done_keypress + + ;======================== + ; check for right pressed + +check_right: + cmp #'D' + beq right_pressed + cmp #$15 + bne check_up + + ;=================== + ;=================== + ; Right/D Pressed + ;=================== + ;=================== +right_pressed: + inc GUN_FIRE ; fire if charging + + ; right==1 + lda DIRECTION ; if facing left, turn to face right + beq right_going_left + + +right_going_right: + lda PHYSICIST_STATE + cmp #P_STANDING + beq walk_right + cmp #P_SHOOTING + beq walk_right + cmp #P_WALKING + beq run_right + and #STATE_CROUCHING + bne stand_right + + ;============================= + ; already running, do nothing? + jmp done_keypress + +right_going_left: + lda PHYSICIST_STATE + cmp #P_RUNNING + beq walk_left + cmp #P_WALKING + beq stand_left + cmp #P_STANDING + beq stand_right + cmp #P_SHOOTING + beq stand_right + and #STATE_CROUCHING + bne stand_right + + + ;=========================== + ; otherwise? + jmp done_keypress + + + ;===================== + ; Left, direction=0 + ; Right, direction=1 + +stand_left: + lda #0 ; left + sta DIRECTION + sta GAIT + lda #P_STANDING + beq update_state + +walk_left: + lda #P_WALKING + bne update_state + +run_left: + lda #P_RUNNING + bne update_state + + +stand_right: + lda #0 + sta GAIT + lda #1 ; just inc DIRECTION? + sta DIRECTION + lda #P_STANDING + beq update_state + +walk_right: + lda #P_WALKING + bne update_state + +run_right: + lda #P_RUNNING + bne update_state + +update_state: + sta PHYSICIST_STATE + jmp done_keypress + + + + + ;===================== + ; check up + +check_up: + cmp #'W' + beq up + cmp #$0B + bne check_down +up: + ;============================= + ;============================= + ; Up/W Pressed -- Jump, Get up + ;============================= + ;============================= + + lda PHYSICIST_STATE ; shoot if charging + cmp #P_CROUCH_SHOOTING + beq up_no_fire + + inc GUN_FIRE +up_no_fire: + + lda ON_ELEVATOR + beq up_not_elevator + +up_on_elevator: + lda #P_ELEVATING_UP + jmp change_state_clear_gait + +up_not_elevator: + + lda PHYSICIST_STATE + cmp #P_CROUCHING + beq stand_up + cmp #P_CROUCH_SHOOTING + beq stand_up_shoot + cmp #P_RUNNING + beq run_jump + +up_jump: + lda #P_JUMPING + jmp change_state_clear_gait + +run_jump: + lda #P_JUMPING|STATE_RUNNING + jmp change_state_clear_gait + +stand_up: + lda #P_STANDING + jmp change_state_clear_gait + +stand_up_shoot: + lda #P_SHOOTING + jmp change_state_clear_gait + + + ;========================== +check_down: + cmp #'S' + beq down + cmp #$0A + bne check_gun + + ;========================== + ;========================== + ; Down/S Pressed -- Crouch + ;========================== + ;========================== +down: + + lda PHYSICIST_STATE ; shoot if charging + cmp #P_SHOOTING + beq down_no_fire + + inc GUN_FIRE +down_no_fire: + + lda ON_ELEVATOR + beq down_not_elevator + +down_on_elevator: + lda #P_ELEVATING_DOWN + jmp change_state_clear_gait + +down_not_elevator: + lda PHYSICIST_STATE + cmp #P_SHOOTING + bne start_crouch + +start_crouch_shoot: + and #STATE_RUNNING + ora #P_CROUCH_SHOOTING + jmp change_state_clear_gait + +start_crouch: + and #STATE_RUNNING + beq start_crouch_norun + + ldx #4 ; slide a bit + stx GAIT + ora #P_CROUCHING + sta PHYSICIST_STATE + jmp done_keypress + +start_crouch_norun: + ora #P_CROUCHING + jmp change_state_clear_gait + + + ;========================== + +check_gun: + cmp #'L' + bne check_space + + ;====================== + ; 'L' to charge gun + ;====================== +charge_gun: + lda HAVE_GUN ; only if have gun + beq done_keypress + + lda GUN_STATE + beq not_already_firing + + inc GUN_FIRE ; if charging, fire + + jmp done_keypress + +not_already_firing: + + inc GUN_STATE + + lda PHYSICIST_STATE + and #STATE_CROUCHING + beq crouch_charge + ldy #P_CROUCH_SHOOTING + bne crouch_charge_go ; bra +crouch_charge: + ldy #P_SHOOTING +crouch_charge_go: + sty PHYSICIST_STATE + + jmp shoot + + +check_space: + cmp #' ' + beq space +; cmp #$15 ; ascii 21=?? + jmp unknown + + ;====================== + ; SPACE -- Kick or shoot + ;====================== +space: + lda HAVE_GUN + beq kick + + ; shoot pressed + + inc GUN_FIRE ; if charging, shoot +shoot: + lda PHYSICIST_STATE ; if in stance, then shoot + cmp #P_SHOOTING + beq in_position + cmp #P_CROUCH_SHOOTING + bne no_stance + +in_position: + lda #1 + sta LASER_OUT + jmp done_keypress + +no_stance: + and #STATE_CROUCHING + beq stand_stance + +crouch_stance: + lda #P_CROUCH_SHOOTING + jmp change_state_clear_gait + +stand_stance: + lda #P_SHOOTING + jmp change_state_clear_gait + +kick: + bit PHYSICIST_STATE ; crouching state in V now + bvc kick_standing + + lda #P_CROUCH_KICKING + jmp kick_final + +kick_standing: + lda #P_KICKING +kick_final: + sta PHYSICIST_STATE + lda #15 + sta GAIT +unknown: +done_keypress: + bit KEYRESET ; clear the keyboard strobe ; 4 + + rts ; 6 + + +change_state_clear_gait: + sta PHYSICIST_STATE + lda #0 + sta GAIT + jmp done_keypress diff --git a/another_myst/laser.s b/another_myst/laser.s new file mode 100644 index 00000000..4b92bad9 --- /dev/null +++ b/another_myst/laser.s @@ -0,0 +1,395 @@ +; FIXME: merge a lot of the target code + +; Handle laser + +; should handle multiple at once? + +; when pressed, find empty slot? +; initially 10 wide, from gun to right or left +; expand to 20 wide +; stop when encounter door, enemy, or edge of screen +; should bounds check carefully + +; should handle shooting while crouching + +; in general, 0 for physicist, 1/2 for alien + +MAX_LASERS = 3 + +; 0=not out, else out. ff=can't hurt +laser_out: +laser0_out: .byte $0 +laser1_out: .byte $0 +laser2_out: .byte $0 +laser3_out: .byte $0 + +laser_start: +laser0_start: .byte $0 +laser1_start: .byte $0 +laser2_start: .byte $0 +laser3_start: .byte $0 + +laser_end: +laser0_end: .byte $0 +laser1_end: .byte $0 +laser2_end: .byte $0 +laser3_end: .byte $0 + +laser_y: +laser0_y: .byte $0 +laser1_y: .byte $0 +laser2_y: .byte $0 +laser3_y: .byte $0 + +laser_direction: +laser0_direction: .byte $0 +laser1_direction: .byte $0 +laser2_direction: .byte $0 +laser3_direction: .byte $0 + +laser_count: +laser0_count: .byte $0 +laser1_count: .byte $0 +laser2_count: .byte $0 +laser3_count: .byte $0 + + ;========================= + ; fire laser + ;========================= + +fire_laser: + lda PHYSICIST_X + + ; adjust so laser pokes out from shield + + ldx DIRECTION ; 0=left, 1=right + beq laser_facing_left + + clc + adc #5 ; only add 5 if facing right + jmp laser_done_adjust + +laser_facing_left: + sec + sbc #2 ; decrement 2 if facing left + +laser_done_adjust: + sta COLLISION_X + + lda PHYSICIST_Y + sta COLLISION_Y + + lda laser0_out + bne done_fire_laser + + ; activate laser slot + + inc laser0_out + + ; reset count + + lda #0 + sta laser0_count + + ; set y + + lda PHYSICIST_Y + clc + adc #4 + + ldx PHYSICIST_STATE + cpx #P_CROUCH_SHOOTING + bne laser_crouch_done +laser_crouch: + clc + adc #4 +laser_crouch_done: + sta laser0_y + + ; set direction + + lda DIRECTION + sta laser0_direction + + beq laser_left + bne laser_right + + ; set x + +laser_left: + + jsr calc_gun_left_collision + + ldx PHYSICIST_X + dex + stx laser0_end + + txa + sec + sbc #10 + sta laser0_start + + jmp done_fire_laser + +laser_right: + + jsr calc_gun_right_collision + + lda PHYSICIST_X + clc + adc #5 + sta laser0_start + + clc + adc #10 + sta laser0_end + +done_fire_laser: + rts + + + + + ;==================== + ; draw laser + ;==================== + +draw_laser: + + ldx #0 +draw_laser_loop: + lda laser_out,X + beq done_draw_laser + + txa + pha ; save X on stack + + lda #$10 + sta hlin_color_smc+1 + + lda #$0f + sta hlin_mask_smc+1 + + ldy laser_y,X + + sec + lda laser_end,X + sbc laser_start,X + sta LASER_TEMP + + lda laser_start,X + + ldx LASER_TEMP + + jsr hlin + + pla ; restore X from stack + tax + +done_draw_laser: + inx + cpx #MAX_LASERS + bne draw_laser_loop + + rts + + + + ;=================== + ; move laser + ;=================== +move_laser: + ldx #0 + +move_laser_loop: + lda laser_out,X + beq done_move_laser + + ; slow down laser + lda laser_count,X + and #$3 + bne no_move_laser + + lda laser_direction,X + bne move_laser_right + +move_laser_left: + + lda laser_count,X + cmp #4 + bcc still_starting_left + cmp #8 + bcc still_shooting_left + +continue_shooting_left: +still_shooting_left: + + lda laser_end,X + sec + sbc #10 + sta laser_end,X + +still_starting_left: + + lda laser_start,X + sec + sbc #10 + sta laser_start,X + +laser_edge_detect_left: + + lda laser_end,X + cmp LEFT_SHOOT_LIMIT + bmi disable_laser_left + + lda laser_start,X + cmp LEFT_SHOOT_LIMIT + bpl no_move_laser + + lda LEFT_SHOOT_LIMIT + sta laser_start,X + + jmp no_move_laser + + +move_laser_right: + + lda laser_count,X + cmp #4 + bcc still_starting_right + cmp #8 + bcc still_shooting_right + +continue_shooting_right: + lda laser_start,X + clc + adc #10 + sta laser_start,X + +still_shooting_right: + lda laser_end,X + clc + adc #10 + sta laser_end,X + +still_starting_right: + +laser_edge_detect_right: + + ; detect if totally off screen + lda laser_start,X + cmp RIGHT_SHOOT_LIMIT + bcs disable_laser_right + + lda laser_end,X + cmp RIGHT_SHOOT_LIMIT + bcc no_move_laser + + lda RIGHT_SHOOT_LIMIT + sta laser_end,X + +no_move_laser: + inc laser_count,X + +done_move_laser: + inx + cpx #MAX_LASERS + bne move_laser_loop + + rts + + ;=================== + ; hit something, left + ;=================== +disable_laser_left: + lda LEFT_SHOOT_TARGET + jmp hit_something_common + + ;==================== + ; hit something, right + ;==================== +disable_laser_right: + + lda RIGHT_SHOOT_TARGET + + + ;====================== + ; hit something, common + ;====================== +hit_something_common: + pha + + ; disable laser + lda #0 + sta laser_out,X + + pla + + tay + and #$f0 + + cmp #TARGET_ALIEN + beq laser_hit_alien + + cmp #TARGET_FRIEND + beq laser_hit_friend + + cmp #TARGET_PHYSICIST + beq laser_hit_physicist + + ; FIXME: reduce shields if hit them? + + jmp done_hit_something + +laser_hit_alien: + + tya + and #$f + tay + + lda #A_DISINTEGRATING + sta alien_state,Y + + lda #0 + sta alien_gait,Y + + jmp done_hit_something + +laser_hit_friend: + + lda #F_DISINTEGRATING + sta friend_state + + lda #FAI_DISINTEGRATING + sta friend_ai_state + + lda #0 + sta friend_gait + + jmp done_hit_something + +laser_hit_physicist: + + lda #P_DISINTEGRATING + sta PHYSICIST_STATE + + lda #0 + sta GAIT + +done_hit_something: + jmp done_move_laser +; rts + + + ;=============== + ; clear lasers + ;=============== +clear_lasers: + ldx #MAX_LASERS + lda #0 +clear_laser_loop: + sta laser_out,X + dex + bne clear_laser_loop + + rts diff --git a/another_myst/ootw_c5_cave.s b/another_myst/ootw_c5_cave.s new file mode 100644 index 00000000..a9159200 --- /dev/null +++ b/another_myst/ootw_c5_cave.s @@ -0,0 +1,299 @@ +; Ootw Checkpoint5 -- Running around the Caves + + + ; call once before entering cave for first time +ootw_cave_init: + lda #0 + sta WHICH_CAVE + sta BLASTED_WALL + ; yes you fall in facing left for some reason + sta DIRECTION ; left + sta NUM_DOORS + + lda #1 + sta HAVE_GUN + + lda #0 + sta PHYSICIST_X + lda #24 + sta PHYSICIST_Y + + ;==================== + ; reset doors + lda #DOOR_STATUS_CLOSED + sta c4_r0_door0_status + + + rts + + + ;=========================== + ; enter new room in cave + ;=========================== + +ootw_cave: + + ;============================== + ; each room init + + + ;============================== + ; setup per-room variables + + lda WHICH_CAVE + bne cave1 + + jsr init_shields + + ; Room0 entrance +cave0: + lda #(0+128) + sta LEFT_LIMIT + lda #(39+128) + sta RIGHT_LIMIT + + ; set right exit + lda #$ff + sta cer_smc+1 + + ; set left exit + lda #0 + sta cel_smc+1 + +; set up doors + + lda #1 + sta NUM_DOORS + + lda #door_c4_r0 + sta setup_door_table_loop_smc+2 + jsr setup_door_table + +not_falling_in: + lda #24 + sta PHYSICIST_Y + + ; load background + lda #>(temple_center_w_rle) + sta GBASH + lda #<(temple_center_w_rle) + sta GBASL + lda #$c ; load to page $c00 + jsr load_rle_gr ; tail call + + ;===================== + ; setup walk collision + jsr recalc_walk_collision + + +cave1: + +ootw_cave_already_set: + ;=========================== + ; Enable graphics + + bit LORES + bit SET_GR + bit FULLGR + + ;=========================== + ; Setup pages (is this necessary?) + + lda #0 + sta DRAW_PAGE + lda #1 + sta DISP_PAGE + + ;================================= + ; setup vars + + lda #0 + sta GAIT + sta GAME_OVER + + ;============================ + ;============================ + ; Cave Loop + ;============================ + ;============================ +cave_loop: + + ;================================ + ; copy background to current page + + jsr gr_copy_to_current + + ;================================== + ; draw background action + + lda WHICH_CAVE + +bg_cave0: + + +c5_no_bg_action: + + ;============================ + ; switch bg if exploded + + lda BLASTED_WALL + cmp #1 + bne wall_good + + ; load background + lda #>(temple_center_ex_rle) + sta GBASH + lda #<(temple_center_ex_rle) + sta GBASL + lda #$c ; load to page $c00 + jsr load_rle_gr ; tail call + + inc BLASTED_WALL +wall_good: + + ;=============================== + ; check keyboard + + jsr handle_keypress + + ;=============================== + ; move physicist + ;=============================== + + jsr move_physicist + + ;=============== + ; check room limits + + jsr check_screen_limit + + ;================= + ; adjust floor + + +check_floor0_done: + +check_floor1: + + + ;=============== + ; draw physicist + + jsr draw_physicist + + + ;=============== + ; handle gun + + jsr handle_gun + + + ;=============== + ; handle doors + + jsr handle_doors + + ;========= +; jsr draw_doors + + ;======================== + ; draw foreground action + +c5_no_fg_action: + + + + ;================ + ; move fg objects + ;================ + + + + ;=============== + ; page flip + + jsr page_flip + + ;================ + ; inc frame count + + inc FRAMEL + bne cave_frame_no_oflo + inc FRAMEH +cave_frame_no_oflo: + + ;========================== + ; check if done this level + ;========================== + + lda GAME_OVER + beq still_in_cave + + cmp #$ff ; if $ff, we died + beq done_cave + + ;=============================== + ; check if exited room to right + cmp #1 + beq cave_exit_left + + ;================= + ; exit to right + +cave_right_yes_exit: + + lda #0 + sta PHYSICIST_X +cer_smc: + lda #$0 ; smc+1 = exit location + sta WHICH_CAVE + jmp done_cave + + ;===================== + ; exit to left + +cave_exit_left: + + lda #37 + sta PHYSICIST_X +cel_smc: + lda #0 ; smc+1 + sta WHICH_CAVE + jmp done_cave + + ; loop forever +still_in_cave: + lda #0 + sta GAME_OVER + + jmp cave_loop + +done_cave: + rts + + +door_c4_r0: + .word door_c4_r0_status + .word door_c4_r0_x + .word door_c4_r0_y + .word door_c4_r0_xmin + .word door_c4_r0_xmax + +door_c4_r0_status: + c4_r0_door0_status: .byte DOOR_STATUS_CLOSED + +door_c4_r0_x: + c4_r0_door0_x: .byte 19 + +door_c4_r0_y: + c4_r0_door0_y: .byte 20 + +door_c4_r0_xmin: + c4_r0_door0_xmin: .byte 11 ; 7-4-5 + +door_c4_r0_xmax: + c4_r0_door0_xmax: .byte 24 ; 7+4 + + diff --git a/another_myst/ootw_graphics/temple_center_ex.png b/another_myst/ootw_graphics/temple_center_ex.png new file mode 100644 index 00000000..574deca4 Binary files /dev/null and b/another_myst/ootw_graphics/temple_center_ex.png differ diff --git a/another_myst/ootw_graphics/temple_center_w.png b/another_myst/ootw_graphics/temple_center_w.png new file mode 100644 index 00000000..56526a35 Binary files /dev/null and b/another_myst/ootw_graphics/temple_center_w.png differ diff --git a/another_myst/physicist.s b/another_myst/physicist.s new file mode 100644 index 00000000..480574a4 --- /dev/null +++ b/another_myst/physicist.s @@ -0,0 +1,696 @@ + ;======================================= + ; Move physicist based on current state + ; + +move_physicist: + lda PHYSICIST_STATE + cmp #P_WALKING + beq move_physicist_walking + cmp #P_RUNNING + beq move_physicist_running + rts + + ;====================== + ; walking + +move_physicist_walking: + inc GAIT ; cycle through animation + + lda GAIT + and #$7 + cmp #$4 ; only walk roughly 1/8 of time + bne no_move_walk + + lda DIRECTION + beq p_walk_left + + inc PHYSICIST_X ; walk right + rts +p_walk_left: + dec PHYSICIST_X ; walk left +no_move_walk: + rts + + ;====================== + ; running +move_physicist_running: +; inc GAIT ; cycle through animation + inc GAIT ; cycle through animation + + lda GAIT + and #$3 + cmp #$2 ; only run roughly 1/4 of time + bne no_move_run + + lda DIRECTION + beq p_run_left + + inc PHYSICIST_X ; run right + rts +p_run_left: + dec PHYSICIST_X ; run left +no_move_run: + rts + ;====================== + ; standing + +move_physicist_standing: + + + + + +pstate_table_lo: + .byte physicist_standing + .byte >physicist_walking + .byte >physicist_running + .byte >physicist_crouching + .byte >physicist_kicking + .byte >physicist_jumping + .byte >physicist_collapsing + .byte >physicist_falling_sideways + .byte >physicist_standing ; 08 swinging + .byte >physicist_standing ; 09 elevator up + .byte >physicist_standing ; 0A elevator down + .byte >physicist_shooting ; 0B + .byte >physicist_falling_down ; 0C + .byte >physicist_impaled ; 0D + .byte >physicist_crouch_shooting; 0E + .byte >physicist_crouch_kicking ; 0F + .byte >physicist_disintegrating ; 10 + +; Urgh, make sure this doesn't end up at $FF or you hit the +; NMOS 6502 bug + +.align 2 + +pjump: + .word $0000 + +.align 1 + +;====================================== +; draw physicist +;====================================== + +draw_physicist: + + lda PHYSICIST_STATE + and #$1f ; mask off high state bits + tax + lda pstate_table_lo,x + sta pjump + lda pstate_table_hi,x + sta pjump+1 + jmp (pjump) + + +;================================== +; STANDING +;================================== + +physicist_standing: + + lda #phys_stand + sta INH + + jmp finally_draw_him + +;================================== +; SHOOTING +;================================== + +physicist_shooting: + + lda #shooting1 + sta INH + + jmp finally_draw_him + + +;================================== +; KICKING +;================================== + +physicist_kicking: + lda #kick1 + sta INH + + ; If kicking long enough, return to standing + + dec GAIT + bne short_draw + + lda #P_STANDING + sta PHYSICIST_STATE + +short_draw: + jmp finally_draw_him + +;=================================== +; CROUCHING +;=================================== + +physicist_crouching: + + ; FIXME: we have an animation? + + ; if we have some gait left, slide a bit + lda GAIT + beq crouch_done_slide + + dec GAIT + bne crouch_done_slide + + lda DIRECTION + beq p_slide_left + inc PHYSICIST_X + jmp crouch_done_slide +p_slide_left: + dec PHYSICIST_X + +crouch_done_slide: + + lda #crouch2 + sta INH + + jmp finally_draw_him + +;=================================== +; CROUCH KICKING +;=================================== + +physicist_crouch_kicking: + + dec GAIT + lda GAIT + bpl still_kicking + + lda #P_CROUCHING + sta PHYSICIST_STATE + +still_kicking: + + lda #crouch_kicking + sta INH + + jmp finally_draw_him + +;=================================== +; CROUCH SHOOTING +;=================================== + +physicist_crouch_shooting: + + lda #crouch_shooting + sta INH + + jmp finally_draw_him + + +;=================================== +; JUMPING +;=================================== + +physicist_jumping: + + lda GAIT + cmp #32 + bcc still_jumping ; blt + + ; done juming + lda #STATE_RUNNING + bit PHYSICIST_STATE + beq jump_to_stand + +jump_to_run: + lda #0 + sta GAIT + lda #P_RUNNING + sta PHYSICIST_STATE + jmp physicist_running + +jump_to_stand: + lda #0 + sta GAIT + lda #P_STANDING + sta PHYSICIST_STATE + jmp physicist_standing + +still_jumping: + + lsr + and #$fe + + tax + + lda phys_jump_progression,X + sta INL + + lda phys_jump_progression+1,X + sta INH + + inc GAIT + + lda #STATE_RUNNING + bit PHYSICIST_STATE + beq jump_change_x_regular + +jump_change_x_running: + lda GAIT + ; 1/4 not enough, 1/2 too much + ; 3/8? + and #$7 + cmp #5 + bcc jump_no_move + jmp jump_change_x + + ; only change X every 8th frame +jump_change_x_regular: + lda GAIT + and #$7 + bne jump_no_move +jump_change_x: + lda DIRECTION + beq jump_left + +jump_right: + inc PHYSICIST_X + jmp finally_draw_him + +jump_left: + dec PHYSICIST_X + +jump_no_move: + jmp finally_draw_him + + + +;=============================== +; Walking +;================================ + +physicist_walking: + lda GAIT + cmp #40 + bcc gait_fine ; blt + + lda #0 + sta GAIT + +gait_fine: + lsr + and #$fe + + tax + + lda phys_walk_progression,X + sta INL + + lda phys_walk_progression+1,X + sta INH + + jmp finally_draw_him + +;=============================== +; Running +;================================ + +physicist_running: + lda GAIT + cmp #40 + bcc run_gait_fine ; blt + + lda #0 + sta GAIT + +run_gait_fine: + lsr + and #$fe + + tax + + lda phys_run_progression,X + sta INL + + lda phys_run_progression+1,X + sta INH + + jmp finally_draw_him + + +;================================== +; COLLAPSING +;================================== + +physicist_collapsing: + + lda GAIT + cmp #18 + bne collapse_not_done + +really_dead: + lda #$ff + sta GAME_OVER + jmp finally_draw_him + +collapse_not_done: + + ldx GAIT + + lda collapse_progression,X + sta INL + lda collapse_progression+1,X + sta INH + + lda FRAMEL + and #$1f + bne no_collapse_progress + + inc GAIT + inc GAIT + +no_collapse_progress: + + + jmp finally_draw_him + +;================================== +; DISINTEGRATING +;================================== + +physicist_disintegrating: + + lda GAIT + cmp #28 + bne disintegrate_not_done + +disintegrate_really_dead: + lda #$ff + sta GAME_OVER + jmp finally_draw_him + +disintegrate_not_done: + + ldx GAIT + + lda disintegrate_progression,X + sta INL + lda disintegrate_progression+1,X + sta INH + + lda FRAMEL + and #$7 + bne no_disintegrate_progress + + inc GAIT + inc GAIT + +no_disintegrate_progress: + + + jmp finally_draw_him + + + +;================================== +; FALLING SIDEWAYS +;================================== + +physicist_falling_sideways: + + + lda FRAMEL + and #$3 + bne no_fall_progress + + inc PHYSICIST_X + inc PHYSICIST_Y ; must me mul of 2 + inc PHYSICIST_Y + +no_fall_progress: + + lda PHYSICIST_Y +fall_sideways_destination_smc: + cmp #22 + bne still_falling +done_falling: +; lda #0 +; sta GAIT + + lda #P_CROUCHING + sta PHYSICIST_STATE + jmp physicist_crouching + +still_falling: + + lda #phys_falling + sta INH + + jmp finally_draw_him + + +;================================== +; FALLING DOWN +;================================== + +physicist_falling_down: + +falling_stop_smc: ; $2C to fall, $4C for not + bit still_falling_down + + lda FRAMEL + and #$1 + bne no_fall_down_progress + + inc PHYSICIST_Y ; must be mul of 2 + inc PHYSICIST_Y + +no_fall_down_progress: + + lda PHYSICIST_Y +fall_down_destination_smc: + cmp #22 + bne still_falling_down +done_falling_down: + + jsr recalc_walk_collision + + lda #P_CROUCHING + sta PHYSICIST_STATE + jmp physicist_crouching + +still_falling_down: + + lda #phys_stand + sta INH + + jmp finally_draw_him + + + +;================================== +; IMPALED +;================================== + +physicist_impaled: + + lda GAIT + cmp #$80 + bne impale_not_done + +impale_really_dead: + lda #$ff + sta GAME_OVER + jmp finally_draw_him + +impale_not_done: + + cmp #2 ; slide down one more + bne impale_enough + inc PHYSICIST_Y + inc PHYSICIST_Y + +impale_enough: + inc GAIT + + lda #physicist_spike_sprite + sta INH + + jmp finally_draw_him + +;============================= +; Actually Draw Him +;============================= + + +finally_draw_him: + lda PHYSICIST_X + sta XPOS + + lda PHYSICIST_Y + sec + sbc EARTH_OFFSET ; adjust for earthquakes + sta YPOS + + lda DIRECTION + bne facing_right + +facing_left: + jmp put_sprite_crop + +facing_right: + jmp put_sprite_flipped_crop + + + +;====================================== +;====================================== +; Check screen limits +;====================================== +;====================================== +; If too far right or left, stop at boundary +; If also > 39 or < -4 then exit room + +check_screen_limit: + + clc + lda PHYSICIST_X + adc #$80 + cmp LEFT_WALK_LIMIT + bcs just_fine_left ; (bge==bcs) + +left_on_screen: + + ; if limit was -4, means we are off screen + ; otherwise, stop physicist at limit + + lda LEFT_WALK_LIMIT + cmp #($80 - 4) + beq too_far_left + +left_stop_at_barrier: + lda #0 + sta PHYSICIST_STATE + + lda LEFT_WALK_LIMIT + sec + sbc #$7f + sta PHYSICIST_X + + rts + +too_far_left: + lda #1 + sta GAME_OVER + rts + +just_fine_left: + + ; Check right edge of screen + +; lda PHYSICIST_X + cmp RIGHT_WALK_LIMIT + bcc just_fine_right ; blt + + +right_on_screen: + + ; if limit was 39, means we are off screen + ; otherwise, stop physicist at limit + + lda RIGHT_WALK_LIMIT + cmp #($80 + 39) + beq too_far_right + +right_stop_at_barrier: + lda #0 + sta PHYSICIST_STATE + + lda RIGHT_WALK_LIMIT + clc + adc #$7f + sta PHYSICIST_X + rts + +too_far_right: + lda #2 + sta GAME_OVER + +just_fine_right: + + rts + + + +; LIMIT VALUE FLAGS +; 0 10 ----- +; 0 0 Z---- +; 0 FF + + +; 1 -> 129 +; 0 -> 128 +; -1 -> 127 FF + 80 = 7f + + + +; XPOS XSIZE XMAX +; -5 8 3 +; -4 4 +; -3 5 +; -2 6 +; -1 7 +; 0 8 +; 1 9 +; 2 +; 3 +; 4 +; 5 diff --git a/another_myst/shield.s b/another_myst/shield.s new file mode 100644 index 00000000..5037035a --- /dev/null +++ b/another_myst/shield.s @@ -0,0 +1,294 @@ +; Handle shield + +; when pressed, find empty slot? Up to 3? +; gradually expire, flash when done +; should update the laser range when start/stop +; destroyed by blast. Weakened by laser? + +MAX_SHIELDS = 3 + +shield_out: +shield0_out: .byte $0 +shield1_out: .byte $0 +shield2_out: .byte $0 + +shield_x: +shield0_x: .byte $0 +shield1_x: .byte $0 +shield2_x: .byte $0 + +shield_y: +shield0_y: .byte $0 +shield1_y: .byte $0 +shield2_y: .byte $0 + +shield_count: +shield0_count: .byte $0 +shield1_count: .byte $0 +shield2_count: .byte $0 + + ;========================= + ; activate_shield + ;========================= + +activate_shield: + + lda SHIELD_OUT + cmp #MAX_SHIELDS + beq done_activate_shield + + ; find slot + ldx #0 +activate_shield_loop: + lda shield_out,X + beq found_shield_slot + inx + bne activate_shield_loop ; bra + +found_shield_slot: + + ; take the slot + + inc SHIELD_OUT + inc shield_out,X + + ; reset count + + lda #0 + sta shield_count,X + + ; set y + + lda PHYSICIST_Y + sta shield_y,X + + ; set x + lda DIRECTION + bne shield_right + +shield_left: + + ldy PHYSICIST_X + dey + tya + sta shield_x,X + + jmp done_activate_shield + +shield_right: + + lda PHYSICIST_X + clc + adc #5 + sta shield_x,X + +done_activate_shield: + rts + + + ;==================== + ; draw shields + ;==================== + +draw_shields: + + lda SHIELD_OUT + beq done_draw_shields + + ldx #0 + +draw_shields_loop: + + lda shield_out,X + beq draw_shields_loop_continue + + lda shield_x,X + sta XPOS + lda shield_y,X + sta YPOS + + ldy shield_count,X + + lda shield_progression,Y + bmi destroy_shield + + tay + + lda FRAMEL + and #$7 + bne dont_increment_shield + + inc shield_count,X + +dont_increment_shield: + + lda shield_table_lo,Y + sta INL + lda shield_table_hi,Y + sta INH + + txa + pha + + jsr put_sprite + + pla + tax + jmp draw_shields_loop_continue + +destroy_shield: + lda #0 + sta shield_out,X + dec SHIELD_OUT + +draw_shields_loop_continue: + inx + cpx #MAX_SHIELDS + bne draw_shields_loop + +done_draw_shields: + + rts + + ;==================== + ; init shields + ;==================== + +init_shields: + + ldx #0 + stx SHIELD_OUT +init_shields_loop: + + lda #0 + sta shield_out,X + + inx + cpx #MAX_SHIELDS + bne init_shields_loop + + rts + +shield_progression: + .byte 0,1 + .byte 2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3 + .byte 2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3 + .byte 4,5,4,5,4,5,4,5,4,5,4,5 + .byte 4,5,4,5,4,5,4,5,4,5,4,5 + .byte 6,7,6,7,6,7,6,7 + .byte 6,7,6,7,6,7,6,7 + .byte 0 + .byte $FF + +shield_table_hi: + .byte >shield_flash_sprite ; 0 + .byte >shield_start_sprite ; 1 + .byte >shield_high1_sprite ; 2 + .byte >shield_high2_sprite ; 3 + .byte >shield_medium1_sprite ; 4 + .byte >shield_medium2_sprite ; 5 + .byte >shield_low1_sprite ; 6 + .byte >shield_low2_sprite ; 7 + +shield_table_lo: + .byte