From e335988aa006bbb56a5b2e69c199ec0482383d0f Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Wed, 2 Oct 2019 00:03:00 -0400 Subject: [PATCH] ds: merge in the starbase code --- demosplash/appleII_intro.s | 4 +- demosplash/demosplash.s | 16 +- demosplash/gr_hlin.s | 34 + demosplash/gr_pageflip.s | 24 + demosplash/gr_putsprite.s | 152 +++++ demosplash/gr_putsprite_crop.s | 353 ++++++++++ demosplash/gr_twoscreen_scroll.s | 130 ++++ demosplash/keyboard.s | 422 ++++++++++++ demosplash/starbase.s | 94 +++ demosplash/starbase_action.s | 1058 +++++++++++++++++++++++++++++ demosplash/starbase_alien.s | 557 +++++++++++++++ demosplash/starbase_alien_laser.s | 96 +++ demosplash/starbase_blast.s | 343 ++++++++++ demosplash/starbase_charger.s | 217 ++++++ demosplash/starbase_collision.s | 604 ++++++++++++++++ demosplash/starbase_doors.s | 401 +++++++++++ demosplash/starbase_friend.s | 26 + demosplash/starbase_gun.s | 287 ++++++++ demosplash/starbase_laser.s | 355 ++++++++++ demosplash/starbase_physicist.s | 694 +++++++++++++++++++ demosplash/starbase_shield.s | 294 ++++++++ 21 files changed, 6154 insertions(+), 7 deletions(-) create mode 100644 demosplash/gr_hlin.s create mode 100644 demosplash/gr_pageflip.s create mode 100644 demosplash/gr_putsprite.s create mode 100644 demosplash/gr_putsprite_crop.s create mode 100644 demosplash/gr_twoscreen_scroll.s create mode 100644 demosplash/keyboard.s create mode 100644 demosplash/starbase.s create mode 100644 demosplash/starbase_action.s create mode 100644 demosplash/starbase_alien.s create mode 100644 demosplash/starbase_alien_laser.s create mode 100644 demosplash/starbase_blast.s create mode 100644 demosplash/starbase_charger.s create mode 100644 demosplash/starbase_collision.s create mode 100644 demosplash/starbase_doors.s create mode 100644 demosplash/starbase_friend.s create mode 100644 demosplash/starbase_gun.s create mode 100644 demosplash/starbase_laser.s create mode 100644 demosplash/starbase_physicist.s create mode 100644 demosplash/starbase_shield.s diff --git a/demosplash/appleII_intro.s b/demosplash/appleII_intro.s index 7a29899a..2ae97cfb 100644 --- a/demosplash/appleII_intro.s +++ b/demosplash/appleII_intro.s @@ -148,9 +148,9 @@ page1_loop: ; delay 115+(7 loop)+4 (bit)+4(extra) jsr do_nothing ; 6 lda KEYPRESS ; 4 - bpl no_keypress ; 3 + bpl no_keypress2 ; 3 jmp appleii_done -no_keypress: +no_keypress2: jmp display_loop ; 3 diff --git a/demosplash/demosplash.s b/demosplash/demosplash.s index 9544d2b5..ba2f3443 100644 --- a/demosplash/demosplash.s +++ b/demosplash/demosplash.s @@ -7,7 +7,7 @@ ending: - jsr appleII_intro +; jsr appleII_intro ;========================= ; set up sound @@ -51,11 +51,14 @@ ending: ; cli ; enable interrupts + jsr starbase + + ; wait wait wait - jsr wait_until_keypressed -repeat_ending: - jmp repeat_ending +; jsr wait_until_keypressed +;repeat_ending: +; jmp repeat_ending @@ -79,10 +82,13 @@ wait_until_keypressed: .include "gr_copy.s" ;.include "text_print.s" -;.include "gr_pageflip.s" +.include "gr_pageflip.s" ;.include "gr_fast_clear.s" ;.include "gr_overlay.s" +; Starbase +.include "starbase.s" + .include "pt3_setup.s" .include "pt3_lib.s" .include "interrupt_handler.s" diff --git a/demosplash/gr_hlin.s b/demosplash/gr_hlin.s new file mode 100644 index 00000000..51d7c91f --- /dev/null +++ b/demosplash/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/demosplash/gr_pageflip.s b/demosplash/gr_pageflip.s new file mode 100644 index 00000000..f199f5be --- /dev/null +++ b/demosplash/gr_pageflip.s @@ -0,0 +1,24 @@ + ;========== + ; page_flip + ;========== + +page_flip: + lda DISP_PAGE ; 3 + beq page_flip_show_1 ; 2nt/3 +page_flip_show_0: + bit PAGE0 ; 4 + lda #4 ; 2 + sta DRAW_PAGE ; DRAW_PAGE=1 ; 3 + lda #0 ; 2 + sta DISP_PAGE ; DISP_PAGE=0 ; 3 + rts ; 6 +page_flip_show_1: + bit PAGE1 ; 4 + sta DRAW_PAGE ; DRAW_PAGE=0 ; 3 + lda #1 ; 2 + sta DISP_PAGE ; DISP_PAGE=1 ; 3 + rts ; 6 + ;==================== + ; DISP_PAGE=0 26 + ; DISP_PAGE=1 24 + diff --git a/demosplash/gr_putsprite.s b/demosplash/gr_putsprite.s new file mode 100644 index 00000000..da9253f5 --- /dev/null +++ b/demosplash/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/demosplash/gr_putsprite_crop.s b/demosplash/gr_putsprite_crop.s new file mode 100644 index 00000000..cdd67f9a --- /dev/null +++ b/demosplash/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/demosplash/gr_twoscreen_scroll.s b/demosplash/gr_twoscreen_scroll.s new file mode 100644 index 00000000..bf90920f --- /dev/null +++ b/demosplash/gr_twoscreen_scroll.s @@ -0,0 +1,130 @@ + ;========================================================= + ; gr_twoscreen_scroll, 40x48 version + ;========================================================= + ; offset is in BG_SCROLL, must be multiple of 2 + ; + ; two screens, top is at $1000, bottom at $BC00 + ; copy lines Y-48 from $1000 to $c00 + ; copy lines 0 - (48-y) from $BC00 to $c00 + +gr_twoscreen_scroll: + + lda #0 + sta TEMPY ; dest + + ldy BG_SCROLL + cpy #48 + beq gr_twoscreen_bottom ; no top to draw + +gr_twoscreen_top: + + ; calculate source + + lda gr_offsets+1,Y + clc + adc #($10-4) + sta gr_twoscreen_smc_src+2 + lda gr_offsets,Y + sta gr_twoscreen_smc_src+1 + tya + pha + + ; calculate destination + + lda TEMPY + tay + lda gr_offsets+1,Y + clc + adc #($c-4) + sta gr_twoscreen_smc_dst+2 + lda gr_offsets,Y + sta gr_twoscreen_smc_dst+1 + + ldx #0 +gr_twoscreen_line_loop: + +gr_twoscreen_smc_src: + lda $1000,X +gr_twoscreen_smc_dst: + sta $c00,X + + inx + cpx #40 + bne gr_twoscreen_line_loop + + + inc TEMPY + inc TEMPY + + pla + tay + + iny + iny + + cpy #48 + + bne gr_twoscreen_top + + + ;=============================== + ; now copy the bottom from $BC00 + + lda BG_SCROLL + beq done_twoscreen_bottom ; if 0, no bottom + +gr_twoscreen_bottom: + + ldy #0 + +gr_twoscreen_bottom_loop: + + ; calculate source + + lda gr_offsets+1,Y + clc + adc #($bc-4) + sta gr_twoscreen_bottom_smc_src+2 + lda gr_offsets,Y + sta gr_twoscreen_bottom_smc_src+1 + tya + pha + + ; calculate destination + + lda TEMPY + tay + lda gr_offsets+1,Y + clc + adc #($c-4) + sta gr_twoscreen_bottom_smc_dst+2 + lda gr_offsets,Y + sta gr_twoscreen_bottom_smc_dst+1 + + ldx #0 +gr_twoscreen_bottom_line_loop: + +gr_twoscreen_bottom_smc_src: + lda $BC00,X +gr_twoscreen_bottom_smc_dst: + sta $c00,X + + inx + cpx #40 + bne gr_twoscreen_bottom_line_loop + + + inc TEMPY + inc TEMPY + + pla + tay + + iny + iny + + cpy BG_SCROLL + + bne gr_twoscreen_bottom_loop +done_twoscreen_bottom: + rts ; 6 diff --git a/demosplash/keyboard.s b/demosplash/keyboard.s new file mode 100644 index 00000000..b2d9483a --- /dev/null +++ b/demosplash/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/demosplash/starbase.s b/demosplash/starbase.s new file mode 100644 index 00000000..47c4833c --- /dev/null +++ b/demosplash/starbase.s @@ -0,0 +1,94 @@ +; starbase + +starbase: + + ; Initialize some variables + + ;======================= + ; Run the "intro" + ;======================= + ; just us falling? + + jsr starbase_init + + ;========================= + ; starbase_new_room + ;========================= + ; enter new room on starbase + +starbase_new_room: + lda #0 + sta GAME_OVER + + jsr ootw_city + +c4_check_done: + lda GAME_OVER + cmp #$ff + beq quit_starbase + + ;==================== + ; go to next level +l4_defeated: + lda WHICH_ROOM + cmp #5 + bne starbase_new_room + + lda #5 + sta WHICH_LOAD + rts + + +;=========================== +; quit_starbase +;=========================== + +quit_starbase: + +wait_loop: + lda KEYPRESS + bpl wait_loop + + lda KEYRESET ; clear strobe + + lda #0 + sta GAME_OVER + + rts + +.include "starbase_action.s" +;.include "text_print.s" +;.include "gr_pageflip.s" +;.include "gr_unrle.s" +;.include "gr_fast_clear.s" +;.include "gr_copy.s" +.include "gr_hlin.s" +.include "gr_twoscreen_scroll.s" +.include "gr_putsprite.s" +;.include "gr_putsprite_flipped.s" +.include "gr_putsprite_crop.s" +;.include "gr_offsets.s" +.include "keyboard.s" + +.include "starbase_physicist.s" +.include "starbase_alien.s" + +.include "starbase_doors.s" +.include "starbase_charger.s" +.include "starbase_gun.s" +.include "starbase_laser.s" +.include "starbase_shield.s" +.include "starbase_blast.s" +.include "starbase_collision.s" +.include "starbase_friend.s" +.include "starbase_alien_laser.s" + +;.include "ootw_c4_action.s" + +; room backgrounds +.include "graphics/starbase/ootw_c4_city.inc" +; sprites +.include "graphics/sprites/physicist.inc" +.include "graphics/sprites/alien.inc" + + diff --git a/demosplash/starbase_action.s b/demosplash/starbase_action.s new file mode 100644 index 00000000..d37b3286 --- /dev/null +++ b/demosplash/starbase_action.s @@ -0,0 +1,1058 @@ + + ;======================= + ;======================= + ; starbase_init + ;======================= + ;======================= + ; call once before entering city for first time +starbase_init: + lda #0 + sta WHICH_ROOM + sta BG_SCROLL + sta DIRECTION ; left + sta LASER_OUT + sta BLAST_OUT + sta CHARGER_COUNT + sta GUN_STATE + sta GUN_FIRE + sta NUM_DOORS + + sta ACTION_TRIGGERED + sta ACTION_COUNT + + lda #100 + sta GUN_CHARGE + + ;==================== + ; reset doors + lda #DOOR_STATUS_CLOSED + sta c4_r0_door0_status + sta c4_r0_door1_status + lda #DOOR_STATUS_LOCKED + sta c4_r0_door2_status + sta c4_r0_door3_status + sta c4_r0_door4_status + + ;=============== + ; set up aliens + + jsr clear_aliens + + lda #1 + sta ALIEN_OUT + + lda #2 + sta alien0_room + lda #27 + sta alien0_x + lda #18 + sta alien0_y + lda #A_STANDING + sta alien0_state + lda #0 + sta alien0_direction + + + ; set up physicist + + lda #1 + sta HAVE_GUN + + lda #19 + sta PHYSICIST_X + lda #230 ; start offscreen + sta PHYSICIST_Y + + lda #28 + sta fall_down_destination_smc+1 + + lda #28 + sta fall_sideways_destination_smc+1 + + lda #P_FALLING_DOWN ; fall into level + sta PHYSICIST_STATE + + lda #$2c + sta falling_stop_smc + + rts + + + ;=========================== + ;=========================== + ; enter new room in jail + ;=========================== + ;=========================== +ootw_city: + ;================================= + ; setup vars + + lda #0 + sta GAIT + sta GAME_OVER + sta NUM_DOORS + + ;============================ + ; init shields + + jsr init_shields + + +; jsr alien_room_init + + + lda #0 + sta FRAMEL ; reset frame count for action timer + sta FRAMEH + sta ACTION_COUNT ; cancel if we leave room mid-action + + ;============================== + ; setup per-room variables + ;============================== + + lda WHICH_ROOM + bne room1 + + ;====================== + ; Room0 with recharger +room0: + + ; set up doors + + lda #5 + sta NUM_DOORS + + lda #door_c4_r0 + sta setup_door_table_loop_smc+2 + jsr setup_door_table + + ; set up room limits + + lda #(6+128) + sta LEFT_LIMIT + lda #(39+128) + sta RIGHT_LIMIT + + ; set right exit + lda #1 + sta cer_smc+1 + + ; set left exit + lda #0 + sta cel_smc+1 + + lda PHYSICIST_STATE + cmp #P_FALLING_DOWN + beq room0_falling + + lda #28 + sta PHYSICIST_Y +room0_falling: + + ; load background + lda #>(recharge_rle) + sta GBASH + lda #<(recharge_rle) + + jmp room_setup_done + + ;=========================== + ; hallway with weird ceiling +room1: + cmp #1 + bne room2 + + lda #(-4+128) + sta LEFT_LIMIT + lda #(39+128) + sta RIGHT_LIMIT + + ; set right exit + lda #2 + sta cer_smc+1 + + ; set left exit + lda #0 + sta cel_smc+1 + + lda #8 + sta PHYSICIST_Y + + ; load background + lda #>(hallway_rle) + sta GBASH + lda #<(hallway_rle) + + jmp room_setup_done + + ;=================== + ; causeway part 1 +room2: + cmp #2 + bne room3 + + lda #(-4+128) + sta LEFT_LIMIT + lda #(39+128) + sta RIGHT_LIMIT + + ; set right exit + lda #3 + sta cer_smc+1 + + ; set left exit + lda #1 + sta cel_smc+1 + + lda #18 + sta PHYSICIST_Y + + ; load background + lda #>(causeway1_rle) + sta GBASH + lda #<(causeway1_rle) + + jmp room_setup_done + + ;======================= + ; causeway part 2 / pit +room3: + cmp #3 + bne room4 + + ; set falling floors + lda #48 + sta fall_down_destination_smc+1 + + lda #48 + sta fall_sideways_destination_smc+1 + + lda #(-4+128) + sta LEFT_LIMIT + lda #(39+128) + sta RIGHT_LIMIT + + ; set right exit + lda #4 + sta cer_smc+1 + + ; set left exit + lda #2 + sta cel_smc+1 + + lda #18 + sta PHYSICIST_Y + + ; load top high + lda #>(causeway2_rle) + sta GBASH + lda #<(causeway2_rle) + sta GBASL + lda #$10 ; load to page $1000 + jsr load_rle_gr + + ; load pit background even higher + lda #>(pit_rle) + sta GBASH + lda #<(pit_rle) + sta GBASL + lda #$BC ; load to page $BC00 + jsr load_rle_gr + + ; load background + lda #>(causeway2_rle) + sta GBASH + lda #<(causeway2_rle) + + jmp room_setup_done + + ;====================== + ; down at the bottom +room4: + + ; set up doors + + lda #1 + sta NUM_DOORS + + lda #door_c4_r4 + sta setup_door_table_loop_smc+2 + jsr setup_door_table + + lda #(16+128) + sta LEFT_LIMIT + lda #(39+128) + sta RIGHT_LIMIT + + ; set right exit + lda #5 + sta cer_smc+1 + + lda PHYSICIST_STATE + cmp #P_IMPALED + beq r4_impaled + cmp #P_FALLING_DOWN + beq r4_impaled + + lda #8 + sta PHYSICIST_Y + + lda #P_CROUCHING + sta PHYSICIST_STATE + +r4_impaled: + ; load background + lda #>(pit_rle) + sta GBASH + lda #<(pit_rle) + + jmp room_setup_done + + +room_setup_done: + + ; load bg image + sta GBASL + lda #$c ; load to page $c00 + jsr load_rle_gr + + ; setup walk collision + jsr recalc_walk_collision + +ootw_room_already_set: + ;=========================== + ; Enable graphics + + bit LORES + bit SET_GR + bit FULLGR + + ;============================================ + ; Setup pages (is this necessary?) + ; FIXME: use code from c3 which clears better + + lda #0 + sta DRAW_PAGE + lda #1 + sta DISP_PAGE + + + ;============================ + ;============================ + ; City Loop + ;============================ + ;============================ +city_loop: + + ;====================================== + ; draw split screen if falling into pit + ;====================================== + + ; only fall in room3 + lda WHICH_ROOM + cmp #3 + bne no_scroll + + lda BG_SCROLL + beq no_scroll + + lda FRAMEL ; slow down a bit + and #$1 + bne no_scroll_progress + + inc BG_SCROLL + inc BG_SCROLL +no_scroll_progress: + + ldy BG_SCROLL + cpy #48 + bne scroll_it + + ; exit to next room when done scrolling + + lda #0 + sta BG_SCROLL + lda #4 + sta WHICH_ROOM + rts + +scroll_it: + jsr gr_twoscreen_scroll +no_scroll: + + + ;================================ + ;================================ + ; copy background to current page + ;================================ + ;================================ + + jsr gr_copy_to_current + + + ;========================= + ;========================= + ; Handle Falling into Pit + ;========================= + ;========================= + + lda WHICH_ROOM + cmp #3 + beq check_falling + cmp #4 + beq check_falling + + jmp not_falling + +check_falling: + ; only fall if falling sideways/down + lda PHYSICIST_STATE + cmp #P_FALLING_SIDEWAYS + beq falling_sideways + cmp #P_FALLING_DOWN + beq falling_down + + jmp not_falling + +falling_sideways: + ; if falling sideways + + lda BG_SCROLL + cmp #16 + bcc before ; blt + + lda FRAMEL + and #$3 + bne no_fall_undo + + dec PHYSICIST_X + dec PHYSICIST_Y + dec PHYSICIST_Y + dec PHYSICIST_Y + dec PHYSICIST_Y +no_fall_undo: + jmp scroll_check +before: + + lda FRAMEL + and #$1 + bne extra_boost + + inc PHYSICIST_X +extra_boost: + jmp scroll_check + + +falling_down: + ; if falling down, and Y>=32, then impale + lda PHYSICIST_Y + cmp #32 + bcc scroll_check ; blt + + lda #9 + sta PHYSICIST_X + + lda #38 + sta PHYSICIST_Y + + lda #0 + sta GAIT + + lda #P_IMPALED + sta PHYSICIST_STATE + + jmp not_falling + +scroll_check: + lda BG_SCROLL ; if done scrolling, re-enable falling + bne scroll_bg_check22 + + lda #$2c ; re-enable falling + sta falling_stop_smc + jmp not_far_enough + +scroll_bg_check22: + + lda PHYSICIST_Y ; once Y=22, stop falling (scroll instead) + cmp #22 + bcc not_far_enough ; blt + + lda #$4c ; disable yinc in falling + sta falling_stop_smc + +not_far_enough: + +not_falling: + + ;================================== + ; draw background action + ;================================== + + lda WHICH_JAIL + +bg_room0: + ; Room #0, draw pulsing recharger + + cmp #0 + bne c4_no_bg_action + + lda FRAMEL + and #$c + lsr + tay + + + lda #11 + sta XPOS + lda #24 + sta YPOS + + lda recharge_bg_progression,Y + sta INL + lda recharge_bg_progression+1,Y + sta INH + + jsr put_sprite + + lda FRAMEL + and #$18 + lsr + lsr + tay + + lda #5 + sta XPOS + lda #24 + sta YPOS + + lda recharge_sprite_progression,Y + sta INL + lda recharge_sprite_progression+1,Y + sta INH + + + + jsr put_sprite + + + + +c4_no_bg_action: + + ;=============================== + ; check keyboard + ;=============================== + + jsr handle_keypress + + ;=============================== + ; move physicist + ;=============================== + + jsr move_physicist + + ;=================== + ; check room limits + ;=================== + lda PHYSICIST_STATE + cmp #P_FALLING_DOWN + beq done_room_limits + cmp #P_IMPALED + beq done_room_limits + + jsr check_screen_limit + +done_room_limits: + + ;============================= + ;============================= + ; Detect if falling off ledge + ;============================= + ;============================= + + ; only fall in room#3 + lda WHICH_ROOM + cmp #3 + bne regular_room + + ; don't start fall if impaled or already falling + lda PHYSICIST_STATE + cmp #P_IMPALED + beq regular_room + cmp #P_FALLING_DOWN + beq regular_room + cmp #P_FALLING_SIDEWAYS + beq regular_room + + + ; only start falling if y>=18 + lda PHYSICIST_Y + cmp #18 + bcc regular_room ; blt + + ; only start falling if x>=7 and positive + lda PHYSICIST_X + bmi regular_room + cmp #7 + bcc regular_room ; blt + + lda PHYSICIST_STATE + cmp #P_JUMPING + beq fall_sideways + + ; if not jumping then fall down + + lda #P_FALLING_DOWN + sta PHYSICIST_STATE + + lda #2 + sta BG_SCROLL + + jmp regular_room + +fall_sideways: + + lda #P_FALLING_SIDEWAYS + sta PHYSICIST_STATE + + lda #2 + sta BG_SCROLL + +regular_room: + + ;=============== + ; draw physicist + ;=============== + + ; if in charger, draw that + lda WHICH_ROOM ; charger only room0 + bne just_draw_physicist + + lda PHYSICIST_X + cmp #10 + bne just_draw_physicist + + lda GUN_CHARGE + cmp #200 + bcs just_draw_physicist ; bge + + lda #P_STANDING + sta PHYSICIST_STATE + + jsr draw_charger + + jmp after_draw_physicist + +just_draw_physicist: + jsr draw_physicist +after_draw_physicist: + + ;=============== + ; draw alien + ;=============== + + lda ALIEN_OUT + beq no_draw_alien + + jsr move_alien + jsr draw_alien +no_draw_alien: + + ;================ + ; handle gun + ;================ + + jsr handle_gun + + ;================ + ; handle doors + ;================ + + jsr handle_doors + + ;================ + ; draw doors + ;================ + + jsr draw_doors + + + ;======================== + ; draw foreground cover + ;======================== + + lda WHICH_ROOM + cmp #2 + beq c4_room2_cover + + cmp #4 + beq c4_room4_cover + + jmp c4_no_fg_cover +c4_room2_cover: + + lda #0 + sta XPOS + lda #18 + sta YPOS + + lda #causeway_door_cover + sta INH + + jsr put_sprite + + + jmp c4_no_fg_cover +c4_room4_cover: + + lda #30 + sta XPOS + lda #8 + sta YPOS + + lda #pit_door_cover + sta INH + + jsr put_sprite + +c4_no_fg_cover: + + + ;======================== + ; handle cinematic action + ;======================== + + lda WHICH_ROOM ; only on causeway1 + cmp #2 + bne no_action_movie + + lda FRAMEH + cmp #1 + bne action_no_trigger + + lda ACTION_TRIGGERED ; already triggered + bne action_no_trigger + +action_trigger: + lda #1 + sta ACTION_COUNT + sta ACTION_TRIGGERED +action_no_trigger: + + lda ACTION_COUNT + beq no_action_movie + +; jsr action_sequence +no_action_movie: + + ;=============== + ; page flip + ;=============== + + jsr page_flip + + ;================ + ; inc frame count + + inc FRAMEL + bne city_frame_no_oflo + inc FRAMEH +city_frame_no_oflo: + + ;========================= + ; exit hack + ;========================= + + lda WHICH_ROOM + cmp #4 + bne regular_exit_check + + lda PHYSICIST_X + cmp #32 + bcc regular_exit_check ; blt + + lda #5 + sta WHICH_ROOM + rts + +regular_exit_check: + + + ;========================== + ; check if done this level + ;========================== + + lda GAME_OVER + beq still_in_city + + cmp #$ff ; if $ff, we died + beq done_city + + ;=============================== + ; check if exited room to right + cmp #1 + beq city_exit_left + + ;================= + ; exit to right + +city_right_yes_exit: + + lda #0 + sta PHYSICIST_X +cer_smc: + lda #$0 ; smc+1 = exit location + sta WHICH_CAVE + jmp done_city + + ;===================== + ; exit to left + +city_exit_left: + + lda #37 + sta PHYSICIST_X +cel_smc: + lda #0 ; smc+1 + sta WHICH_CAVE + jmp done_city + + ; loop forever +still_in_city: + lda #0 + sta GAME_OVER + + jmp city_loop + +done_city: + rts + + +recharge_sprite_progression: + .word recharge_sprite1 + .word recharge_sprite2 + .word recharge_sprite3 + .word recharge_sprite4 + + +recharge_sprite1: + .byte 1,10 + .byte $eA + .byte $ff + .byte $ee + .byte $ff + .byte $e6 + .byte $ff + .byte $6e + .byte $ff + .byte $fe + .byte $a6 + +recharge_sprite2: + .byte 1,10 + .byte $fA + .byte $f6 + .byte $ef + .byte $fe + .byte $66 + .byte $fe + .byte $6e + .byte $f6 + .byte $6e + .byte $af + +recharge_sprite3: + .byte 1,10 + .byte $eA + .byte $f6 + .byte $ef + .byte $ef + .byte $6f + .byte $f6 + .byte $e6 + .byte $f6 + .byte $6f + .byte $ae + +recharge_sprite4: + .byte 1,10 + .byte $fA + .byte $fe + .byte $fe + .byte $6e + .byte $fe + .byte $6e + .byte $ee + .byte $f6 + .byte $ef + .byte $ae + + +recharge_bg_progression: + .word recharge_bg1 + .word recharge_bg2 + .word recharge_bg3 + .word recharge_bg4 + +recharge_bg1: + .byte 2,10 + .byte $6A,$FA + .byte $27,$f6 + .byte $ff,$7f + .byte $6f,$7f + .byte $ff,$5f + .byte $f5,$5f + .byte $62,$f2 + .byte $72,$65 + .byte $5f,$7f + .byte $A2,$a5 + +recharge_bg2: + .byte 2,10 + .byte $2A,$6A + .byte $76,$65 + .byte $5f,$f5 + .byte $ff,$77 + .byte $22,$f2 + .byte $5f,$f6 + .byte $2f,$75 + .byte $52,$f5 + .byte $f2,$52 + .byte $A6,$a2 + +recharge_bg3: + .byte 2,10 + .byte $fA,$7A + .byte $f5,$27 + .byte $5f,$ff + .byte $2f,$5f + .byte $77,$ff + .byte $f5,$f6 + .byte $25,$52 + .byte $5f,$52 + .byte $5f,$2f + .byte $A7,$a2 + +recharge_bg4: + .byte 2,10 + .byte $5A,$2A + .byte $55,$76 + .byte $f5,$5f + .byte $77,$ff + .byte $75,$22 + .byte $f2,$5f + .byte $27,$22 + .byte $7f,$5f + .byte $6f,$f5 + .byte $A7,$a2 + + + +; 0x18 +causeway_door_cover: + .byte 8,8 + .byte $00,$00,$00,$00,$00,$00,$22,$AA + .byte $00,$00,$00,$00,$00,$00,$22,$AA + .byte $00,$00,$00,$00,$00,$00,$22,$AA + .byte $00,$00,$00,$00,$00,$00,$02,$2A + .byte $00,$00,$00,$00,$00,$00,$00,$22 + .byte $00,$00,$00,$00,$00,$00,$00,$22 + .byte $00,$00,$00,$00,$00,$00,$00,$22 + .byte $00,$00,$00,$00,$00,$00,$00,$22 + +; 30x8 +pit_door_cover: + .byte 8,8 + .byte $02,$22,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00 + .byte $20,$00,$00,$00,$00,$00,$00,$00 + .byte $22,$02,$00,$00,$00,$00,$00,$00 + .byte $22,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00 + .byte $00,$00,$00,$00,$00,$00,$00,$00 + + + +;clear_c00: +; lda #$94 +; ldy #0 +;clear1: +; sta $c00,Y +; sta $d00,Y +; sta $e00,Y +; sta $f00,Y +; iny +; bne clear1 +; 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 + c4_r0_door1_status: .byte DOOR_STATUS_CLOSED + c4_r0_door2_status: .byte DOOR_STATUS_LOCKED + c4_r0_door3_status: .byte DOOR_STATUS_LOCKED + c4_r0_door4_status: .byte DOOR_STATUS_LOCKED + +door_c4_r0_x: + c4_r0_door0_x: .byte 7 + c4_r0_door1_x: .byte 18 + c4_r0_door2_x: .byte 29 + c4_r0_door3_x: .byte 31 + c4_r0_door4_x: .byte 33 + +door_c4_r0_y: + c4_r0_door0_y: .byte 24 + c4_r0_door1_y: .byte 24 + c4_r0_door2_y: .byte 24 + c4_r0_door3_y: .byte 24 + c4_r0_door4_y: .byte 24 + +door_c4_r0_xmin: + c4_r0_door0_xmin: .byte 0 ; 7-4-5 + c4_r0_door1_xmin: .byte 11 ; 18-4-5 + c4_r0_door2_xmin: .byte 20 ; 29-4-5 + c4_r0_door3_xmin: .byte 22 ; 31-4-5 + c4_r0_door4_xmin: .byte 24 ; 33-4-5 + +door_c4_r0_xmax: + c4_r0_door0_xmax: .byte 11 ; 7+4 + c4_r0_door1_xmax: .byte 21 ; 18+4 + c4_r0_door2_xmax: .byte 33 ; don't care + c4_r0_door3_xmax: .byte 35 ; don't care + c4_r0_door4_xmax: .byte 37 ; don't care + + + +door_c4_r4: + .word door_c4_r4_status + .word door_c4_r4_x + .word door_c4_r4_y + .word door_c4_r4_xmin + .word door_c4_r4_xmax + +door_c4_r4_status: + c4_r4_door0_status: .byte DOOR_STATUS_LOCKED + +door_c4_r4_x: + c4_r4_door0_x: .byte 27 + +door_c4_r4_xmin: ; don't care (door does not open) +door_c4_r4_xmax: ; don't care (door does not open) +door_c4_r4_y: + c4_r4_door0_y: .byte 4 + diff --git a/demosplash/starbase_alien.s b/demosplash/starbase_alien.s new file mode 100644 index 00000000..d210e85c --- /dev/null +++ b/demosplash/starbase_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/demosplash/starbase_alien_laser.s b/demosplash/starbase_alien_laser.s new file mode 100644 index 00000000..909c6612 --- /dev/null +++ b/demosplash/starbase_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/demosplash/starbase_blast.s b/demosplash/starbase_blast.s new file mode 100644 index 00000000..1787cb96 --- /dev/null +++ b/demosplash/starbase_blast.s @@ -0,0 +1,343 @@ +; 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 + 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: + + ; 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/demosplash/starbase_charger.s b/demosplash/starbase_charger.s new file mode 100644 index 00000000..bac057a7 --- /dev/null +++ b/demosplash/starbase_charger.s @@ -0,0 +1,217 @@ + + ;====================== + ;====================== + ; draw charger + ;====================== + ;====================== +draw_charger: + + lda #6 + sta XPOS + lda #24 + sta YPOS + + lda CHARGER_COUNT + tay + + lda charger_sequence_lo,Y + sta INL + + lda charger_sequence_hi,Y + sta INH + + jsr put_sprite + + lda FRAMEL ; slow it down + and #$7 + bne done_drawing_charger + + inc CHARGER_COUNT + lda CHARGER_COUNT + cmp #11 + bne done_drawing_charger + + lda #200 ; actually charge + sta GUN_CHARGE + + lda #0 + sta CHARGER_COUNT + +done_charging: + +done_drawing_charger: + + + rts + +charger_sequence_hi: + .byte >zapper1_sprite + .byte >zapper2_sprite + .byte >zapper3_sprite + .byte >zapper4_sprite + .byte >zapper5_sprite + .byte >zapper6_sprite + .byte >zapper7_sprite + .byte >zapper8_sprite + .byte >zapper9_sprite + .byte >zapper10_sprite + .byte >zapper11_sprite + +charger_sequence_lo: + .byte 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/demosplash/starbase_friend.s b/demosplash/starbase_friend.s new file mode 100644 index 00000000..fe332026 --- /dev/null +++ b/demosplash/starbase_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/demosplash/starbase_gun.s b/demosplash/starbase_gun.s new file mode 100644 index 00000000..38b8a304 --- /dev/null +++ b/demosplash/starbase_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/demosplash/starbase_laser.s b/demosplash/starbase_laser.s new file mode 100644 index 00000000..f514e981 --- /dev/null +++ b/demosplash/starbase_laser.s @@ -0,0 +1,355 @@ + +; 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 + +MAX_LASERS = 2 + +laser_out: +laser0_out: .byte $0 +laser1_out: .byte $0 + +laser_start: +laser0_start: .byte $0 +laser1_start: .byte $0 + +laser_end: +laser0_end: .byte $0 +laser1_end: .byte $0 + +laser_y: +laser0_y: .byte $0 +laser1_y: .byte $0 + +laser_direction: +laser0_direction: .byte $0 +laser1_direction: .byte $0 + +laser_count: +laser0_count: .byte $0 +laser1_count: .byte $0 + + ;========================= + ; fire laser + ;========================= + +fire_laser: + lda PHYSICIST_X + 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 + + + + diff --git a/demosplash/starbase_physicist.s b/demosplash/starbase_physicist.s new file mode 100644 index 00000000..a868b734 --- /dev/null +++ b/demosplash/starbase_physicist.s @@ -0,0 +1,694 @@ + ;======================================= + ; 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: + + 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/demosplash/starbase_shield.s b/demosplash/starbase_shield.s new file mode 100644 index 00000000..5037035a --- /dev/null +++ b/demosplash/starbase_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