ds: merge in the starbase code

This commit is contained in:
Vince Weaver 2019-10-02 00:03:00 -04:00
parent 0cdec7d305
commit e335988aa0
21 changed files with 6154 additions and 7 deletions

View File

@ -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

View File

@ -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"

34
demosplash/gr_hlin.s Normal file
View File

@ -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

24
demosplash/gr_pageflip.s Normal file
View File

@ -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

152
demosplash/gr_putsprite.s Normal file
View File

@ -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

View File

@ -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

View File

@ -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

422
demosplash/keyboard.s Normal file
View File

@ -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

94
demosplash/starbase.s Normal file
View File

@ -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"

1058
demosplash/starbase_action.s Normal file

File diff suppressed because it is too large Load Diff

557
demosplash/starbase_alien.s Normal file
View File

@ -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
astate_table_hi:
.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 INL
lda #>alien_stand
sta INH
jmp finally_draw_alien
;==================================
; SHOOTING
;==================================
alien_shooting:
lda #<alien_shoot_sprite
sta INL
lda #>alien_shoot_sprite
sta INH
jmp finally_draw_alien
;===================================
; CROUCHING
;===================================
alien_crouching:
; FIXME: we have an animation?
lda #<alien_crouch2
sta INL
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 INL
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

View File

@ -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

343
demosplash/starbase_blast.s Normal file
View File

@ -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 INL
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

View File

@ -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 <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
zapper1_sprite:
.byte 10,10
.byte $AA,$00,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$AA,$9A,$9A,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$AA,$bb,$99,$AA,$AA,$AA
.byte $AA,$00,$AA,$0a,$0a,$AA,$0b,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$A0,$Ab,$b0,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$AA,$AA,$00,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$AA,$AA,$44,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$AA,$44,$c4,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$fA,$f4,$7A,$AA,$AA,$AA
zapper2_sprite:
.byte 10,10
.byte $AA,$00,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
.byte $AA,$A0,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$9A,$9A,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$bb,$99,$AA,$AA,$AA
.byte $AA,$AA,$AA,$0a,$0a,$AA,$0b,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$A0,$Ab,$b0,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$AA,$00,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$AA,$44,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$44,$c4,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$fA,$f4,$7A,$AA,$AA,$AA
zapper3_sprite:
.byte 10,10
.byte $AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
.byte $6a,$fe,$fe,$AA,$AA,$AA,$AA,$AA,$AA,$AA
.byte $ee,$ff,$ff,$ee,$AA,$9A,$9A,$AA,$AA,$AA
.byte $Ae,$ef,$ef,$6A,$AA,$bb,$99,$AA,$AA,$AA
.byte $AA,$AA,$66,$0a,$0a,$AA,$0b,$AA,$AA,$AA
.byte $6A,$66,$AA,$AA,$A0,$Ab,$b0,$AA,$AA,$AA
.byte $AA,$66,$AA,$AA,$AA,$AA,$00,$AA,$AA,$AA
.byte $AA,$66,$AA,$AA,$AA,$AA,$44,$AA,$AA,$AA
.byte $AA,$66,$AA,$AA,$AA,$44,$c4,$AA,$AA,$AA
.byte $AA,$A6,$AA,$AA,$fA,$af,$7A,$A7,$AA,$AA
zapper4_sprite:
.byte 10,10
.byte $AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
.byte $a6,$6a,$AA,$AA,$AA,$B9,$99,$AA,$AA,$AA
.byte $6a,$A6,$66,$AA,$AA,$AB,$b9,$AA,$AA,$AA
.byte $A6,$AA,$66,$A0,$00,$BA,$00,$AA,$AA,$AA
.byte $AA,$AA,$66,$AA,$AA,$AA,$0b,$AA,$AA,$AA
.byte $AA,$66,$A6,$AA,$AA,$AA,$40,$AA,$AA,$AA
.byte $AA,$66,$6a,$AA,$AA,$4A,$44,$AA,$AA,$AA
.byte $66,$AA,$66,$AA,$AA,$F4,$AC,$7A,$AA,$AA
.byte $A6,$AA,$A6,$AA,$AF,$AA,$A7,$AA,$AA,$AA
zapper5_sprite:
.byte 10,10
.byte $6A,$6A,$AA,$6a,$AA,$AA,$AA,$AA,$AA,$AA
.byte $A6,$AA,$AA,$66,$AA,$9A,$9A,$AA,$AA,$AA
.byte $AA,$AA,$6A,$A6,$AA,$BB,$99,$AA,$AA,$AA
.byte $AA,$AA,$66,$0A,$0A,$AA,$0b,$AA,$AA,$AA
.byte $A6,$66,$AA,$66,$A0,$AB,$b0,$AA,$AA,$AA
.byte $AA,$66,$AA,$66,$AA,$AA,$00,$AA,$EA,$f6
.byte $66,$AA,$AA,$66,$AA,$AA,$44,$AA,$EE,$FF
.byte $66,$AA,$AA,$66,$AA,$44,$C4,$AA,$A6,$A6
.byte $AA,$66,$66,$AA,$FA,$AF,$7A,$A7,$AA,$AA
.byte $AA,$A6,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
zapper6_sprite:
.byte 10,10
.byte $6A,$6A,$AA,$AA,$6A,$AA,$AA,$AA,$AA,$AA
.byte $A6,$AA,$AA,$66,$AA,$99,$99,$99,$AA,$AA
.byte $AA,$AA,$6A,$A6,$AA,$BB,$99,$A9,$AA,$AA
.byte $AA,$AA,$66,$0A,$0A,$AA,$0b,$AA,$AA,$AA
.byte $AA,$66,$66,$AA,$A0,$AB,$b0,$AA,$AA,$AA
.byte $AA,$66,$AA,$66,$AA,$AA,$00,$AA,$AA,$AA
.byte $66,$66,$AA,$A6,$6A,$AA,$44,$AA,$AA,$AA
.byte $66,$AA,$AA,$6A,$66,$44,$C4,$AA,$AA,$AA
.byte $AA,$AA,$6A,$A6,$FA,$AF,$7A,$A7,$AA,$6A
.byte $A6,$A6,$A6,$AA,$AA,$AA,$AA,$AA,$A6,$A6
zapper7_sprite:
.byte 10,10
.byte $6A,$6A,$6A,$6A,$6A,$AA,$AA,$AA,$AA,$AA
.byte $A6,$AA,$66,$AA,$AA,$99,$99,$99,$AA,$AA
.byte $AA,$AA,$66,$AA,$AA,$BB,$99,$A9,$AA,$AA
.byte $AA,$AA,$66,$0A,$0A,$AA,$0b,$AA,$AA,$AA
.byte $AA,$AA,$66,$AA,$A0,$AB,$b0,$AA,$AA,$AA
.byte $AA,$66,$AA,$66,$AA,$AA,$00,$AA,$AA,$AA
.byte $AA,$66,$AA,$A6,$6A,$AA,$44,$AA,$AA,$AA
.byte $66,$AA,$AA,$6A,$66,$AA,$44,$AA,$AA,$6A
.byte $66,$AA,$6A,$A6,$AA,$FA,$7F,$67,$6A,$66
.byte $A6,$AA,$A6,$AA,$AA,$AA,$AA,$6A,$A6,$A6
zapper8_sprite:
.byte 10,10
.byte $6A,$0A,$6A,$6A,$6A,$AA,$AA,$AA,$AA,$AA
.byte $AA,$00,$EA,$EA,$AA,$9A,$9A,$9A,$AA,$AA
.byte $AA,$EE,$FF,$DD,$AA,$B9,$99,$99,$AA,$AA
.byte $AA,$AA,$6E,$EE,$EA,$AB,$b9,$AA,$AA,$AA
.byte $AA,$AA,$66,$EE,$FF,$EE,$00,$AA,$AA,$AA
.byte $AA,$AA,$AA,$A6,$AE,$AE,$0b,$AA,$AA,$66
.byte $AA,$AA,$AA,$AA,$AA,$AA,$40,$AA,$AA,$66
.byte $AA,$A6,$6A,$6A,$6A,$AA,$44,$6A,$AA,$66
.byte $AA,$00,$66,$A6,$AA,$AA,$F4,$7A,$A6,$A6
.byte $AA,$00,$A6,$AA,$AA,$AF,$A7,$AA,$AA,$AA
zapper9_sprite:
.byte 10,10
.byte $AA,$00,$AA,$6A,$AA,$AA,$AA,$AA,$AA,$6A
.byte $AA,$00,$AA,$66,$AA,$9A,$9A,$9A,$AA,$66
.byte $AA,$00,$AA,$A6,$6A,$B9,$99,$99,$A6,$AA
.byte $AA,$00,$AA,$EA,$AA,$AB,$b9,$AA,$AA,$AA
.byte $AA,$00,$EE,$FF,$EE,$BA,$00,$AA,$AA,$AA
.byte $AA,$00,$AA,$AE,$AA,$AA,$0b,$AA,$AA,$AA
.byte $AA,$00,$6A,$AA,$AA,$AA,$40,$AA,$AA,$AA
.byte $AA,$00,$66,$AA,$AA,$AA,$44,$6A,$AA,$AA
.byte $AA,$00,$A6,$6A,$AA,$AA,$F4,$7A,$A6,$66
.byte $AA,$00,$AA,$AA,$A6,$AF,$A7,$AA,$AA,$AA
zapper10_sprite:
.byte 10,10
.byte $6A,$00,$AA,$6A,$AA,$AA,$AA,$AA,$AA,$AA
.byte $AA,$00,$AA,$A6,$6A,$9A,$9A,$9A,$6A,$6A
.byte $AA,$00,$AA,$AA,$AA,$B9,$99,$99,$AA,$66
.byte $AA,$00,$AA,$AA,$AA,$AB,$b9,$AA,$AA,$AA
.byte $AA,$00,$AA,$A0,$00,$BA,$00,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$AA,$AA,$0b,$AA,$A6,$A6
.byte $AA,$00,$AA,$6A,$AA,$AA,$40,$AA,$AA,$AA
.byte $6A,$00,$66,$AA,$AA,$AA,$44,$6A,$AA,$AA
.byte $AA,$00,$66,$AA,$AA,$AA,$F4,$7A,$A6,$6A
.byte $AA,$00,$A6,$AA,$AA,$AF,$A7,$AA,$AA,$A6
zapper11_sprite:
.byte 10,10
.byte $6A,$00,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
.byte $AA,$A0,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$9A,$9A,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$BB,$99,$AA,$AA,$AA
.byte $AA,$AA,$AA,$0A,$0A,$AA,$0b,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$A0,$AB,$b0,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$AA,$00,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$AA,$40,$AA,$AA,$AA
.byte $AA,$AA,$AA,$AA,$AA,$AA,$44,$AA,$AA,$AA
.byte $AA,$00,$AA,$AA,$AA,$FA,$7F,$A7,$AA,$AA

View File

@ -0,0 +1,604 @@
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:
lda shield_out,X
beq calc_gun_left_shield_continue
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

401
demosplash/starbase_doors.s Normal file
View File

@ -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_sprite_lookup_hi:
.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

View File

@ -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

287
demosplash/starbase_gun.s Normal file
View File

@ -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
gun_charge_table_hi:
.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

355
demosplash/starbase_laser.s Normal file
View File

@ -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

View File

@ -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 ; 00
.byte <physicist_walking ; 01
.byte <physicist_running ; 02
.byte <physicist_crouching ; 03
.byte <physicist_kicking ; 04
.byte <physicist_jumping ; 05
.byte <physicist_collapsing ; 06
.byte <physicist_falling_sideways; 07
.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
pstate_table_hi:
.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 INL
lda #>phys_stand
sta INH
jmp finally_draw_him
;==================================
; SHOOTING
;==================================
physicist_shooting:
lda #<shooting1
sta INL
lda #>shooting1
sta INH
jmp finally_draw_him
;==================================
; KICKING
;==================================
physicist_kicking:
lda #<kick1
sta INL
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 INL
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 INL
lda #>crouch_kicking
sta INH
jmp finally_draw_him
;===================================
; CROUCH SHOOTING
;===================================
physicist_crouch_shooting:
lda #<crouch_shooting
sta INL
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 INL
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 INL
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 INL
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

View File

@ -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 <shield_flash_sprite
.byte <shield_start_sprite
.byte <shield_high1_sprite
.byte <shield_high2_sprite
.byte <shield_medium1_sprite
.byte <shield_medium2_sprite
.byte <shield_low1_sprite
.byte <shield_low2_sprite
shield_flash_sprite:
.byte 1,8
.byte $f3
.byte $ff
.byte $ff
.byte $ff
.byte $ff
.byte $3f
.byte $AA
.byte $AA
shield_start_sprite:
.byte 1,8
.byte $11
.byte $11
.byte $11
.byte $11
.byte $11
.byte $11
.byte $11
.byte $11
shield_high1_sprite:
.byte 1,8
.byte $BA
.byte $3A
.byte $A1
.byte $A1
.byte $BA
.byte $A3
.byte $BA
.byte $13
shield_high2_sprite:
.byte 1,8
.byte $3A
.byte $1A
.byte $3A
.byte $AA
.byte $AB
.byte $3A
.byte $1B
.byte $3A
shield_medium1_sprite:
.byte 1,8
.byte $A1
.byte $AA
.byte $1B
.byte $AA
.byte $A3
.byte $AA
.byte $3A
.byte $BA
shield_medium2_sprite:
.byte 1,8
.byte $AB
.byte $AA
.byte $A3
.byte $A3
.byte $AA
.byte $B3
.byte $AA
.byte $1A
shield_low1_sprite:
.byte 1,8
.byte $A3
.byte $AB
.byte $AA
.byte $3A
.byte $AA
.byte $AA
.byte $1A
.byte $AA
shield_low2_sprite:
.byte 1,8
.byte $A1
.byte $AA
.byte $AA
.byte $A1
.byte $AA
.byte $AA
.byte $A3
.byte $AB