From e2e30040df0d5dff67e08d062cbbbc254996ace2 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Sat, 20 Jun 2020 18:29:00 -0400 Subject: [PATCH] anothermist: can blast the book --- another_myst/NOTES | 14 +- another_myst/alien.s | 557 +++++++++++++ another_myst/alien_laser.s | 96 +++ another_myst/anothermist.s | 28 +- another_myst/blast.s | 360 +++++++++ another_myst/collision.s | 606 ++++++++++++++ another_myst/door.s | 401 ++++++++++ another_myst/dummy_friend.s | 26 + another_myst/friend.s | 492 ++++++++++++ another_myst/gr_hlin.s | 34 + another_myst/gr_putsprite.s | 152 ++++ another_myst/gr_putsprite_crop.s | 353 +++++++++ another_myst/gr_putsprite_flipped.s | 157 ++++ another_myst/gun.s | 287 +++++++ another_myst/keyboard.s | 422 ++++++++++ another_myst/laser.s | 395 +++++++++ another_myst/ootw_c5_cave.s | 299 +++++++ .../ootw_graphics/temple_center_ex.png | Bin 0 -> 15572 bytes .../ootw_graphics/temple_center_w.png | Bin 0 -> 11405 bytes another_myst/physicist.s | 696 ++++++++++++++++ another_myst/shield.s | 294 +++++++ another_myst/sprites/alien.inc | 600 ++++++++++++++ another_myst/sprites/physicist.inc | 749 ++++++++++++++++++ 23 files changed, 7008 insertions(+), 10 deletions(-) create mode 100644 another_myst/alien.s create mode 100644 another_myst/alien_laser.s create mode 100644 another_myst/blast.s create mode 100644 another_myst/collision.s create mode 100644 another_myst/door.s create mode 100644 another_myst/dummy_friend.s create mode 100644 another_myst/friend.s create mode 100644 another_myst/gr_hlin.s create mode 100644 another_myst/gr_putsprite.s create mode 100644 another_myst/gr_putsprite_crop.s create mode 100644 another_myst/gr_putsprite_flipped.s create mode 100644 another_myst/gun.s create mode 100644 another_myst/keyboard.s create mode 100644 another_myst/laser.s create mode 100644 another_myst/ootw_c5_cave.s create mode 100644 another_myst/ootw_graphics/temple_center_ex.png create mode 100644 another_myst/ootw_graphics/temple_center_w.png create mode 100644 another_myst/physicist.s create mode 100644 another_myst/shield.s create mode 100644 another_myst/sprites/alien.inc create mode 100644 another_myst/sprites/physicist.inc 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 0000000000000000000000000000000000000000..574deca43e6caa9f7e9dc53cbb455ef6a64c02df GIT binary patch literal 15572 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 boksowRoqU9G_-9C00000NkvXXu0mjfI3U9J literal 0 HcmV?d00001 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