mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-12-29 00:31:52 +00:00
820 lines
12 KiB
ArmAsm
820 lines
12 KiB
ArmAsm
; Strongbad Zone
|
|
;
|
|
; Yet Another HR project
|
|
;
|
|
; by deater (Vince Weaver) <vince@deater.net>
|
|
|
|
; some notes on the engine from the original
|
|
; bullet moving is not 3d in any way, it's just 2D
|
|
; there are distinct Y locations with different sized sprites
|
|
; X velocity starts at 3
|
|
; hitting shield left, subs random 0..5
|
|
; hitting shield right, adds random 0..5
|
|
; hitting shield center, adds random -0.5 .. 0.5
|
|
; bounces off side walls roughly at same X as back walls
|
|
; doesn't even try to adjust for Y
|
|
; if it hits back wall, it reflects back
|
|
; if it misses you, makes small explosion, starts again at far wall
|
|
; with same X as it went off screen with
|
|
|
|
; things missing from real game
|
|
; some of the animations (both of player and head being destroyed)
|
|
; there are some pauses after things happen
|
|
;
|
|
|
|
; Notes
|
|
; collision detection on shield should really be 16 bit, some things
|
|
; get past the shield check but then collide on the next frame
|
|
; sprite routines cheat in a lot of ways. assume blue/orange
|
|
; assume X only in 3.5 pixel offsets
|
|
; do minimal transparency using black0
|
|
|
|
; Challenges:
|
|
; moving such huge sprites
|
|
; fitting all in RAM
|
|
; sound
|
|
|
|
|
|
.include "zp.inc"
|
|
.include "hardware.inc"
|
|
|
|
div7_table = $400
|
|
mod7_table = $500
|
|
hposn_high = $600
|
|
hposn_low = $700
|
|
|
|
|
|
strongbadzone_start:
|
|
|
|
;===================
|
|
; set graphics mode
|
|
;===================
|
|
jsr HOME
|
|
|
|
bit HIRES
|
|
bit FULLGR
|
|
bit SET_GR
|
|
bit PAGE1
|
|
|
|
;====================
|
|
; set up tables
|
|
;====================
|
|
|
|
lda #$20
|
|
sta HGR_PAGE
|
|
jsr hgr_make_tables
|
|
|
|
|
|
;==========================
|
|
; Load Sound
|
|
;===========================
|
|
|
|
lda SOUND_STATUS
|
|
and #SOUND_IN_LC
|
|
beq done_load_sound
|
|
|
|
; read/write RAM, use $d000 bank1
|
|
bit $C083
|
|
bit $C083
|
|
|
|
lda #<sound_data
|
|
sta ZX0_src
|
|
lda #>sound_data
|
|
sta ZX0_src+1
|
|
|
|
lda #$D0
|
|
|
|
jsr full_decomp
|
|
|
|
; read ROM/no-write
|
|
bit $C082
|
|
|
|
|
|
done_load_sound:
|
|
|
|
;==========================
|
|
; Load Title
|
|
;===========================
|
|
|
|
load_title:
|
|
lda #<title_data
|
|
sta ZX0_src
|
|
lda #>title_data
|
|
sta ZX0_src+1
|
|
|
|
lda #$20
|
|
|
|
jsr full_decomp
|
|
|
|
; load to page2 for color cycle
|
|
|
|
lda #<title_data
|
|
sta ZX0_src
|
|
lda #>title_data
|
|
sta ZX0_src+1
|
|
|
|
lda #$A0
|
|
|
|
jsr full_decomp
|
|
|
|
title_cycle_loop:
|
|
|
|
jsr cycle_colors
|
|
inc FRAME
|
|
|
|
|
|
lda KEYPRESS
|
|
bpl title_cycle_loop
|
|
|
|
bit KEYRESET
|
|
|
|
|
|
;===================
|
|
; setup game
|
|
;===================
|
|
|
|
;==========================
|
|
; Load Backgrounds
|
|
;===========================
|
|
; this is tricky as there's not enough room
|
|
; so we are over-writing stuff carefully
|
|
|
|
load_backgrounds:
|
|
|
|
lda #<bg2_data
|
|
sta ZX0_src
|
|
lda #>bg2_data
|
|
sta ZX0_src+1
|
|
|
|
lda #$A0
|
|
|
|
jsr full_decomp
|
|
|
|
lda #<bg1_data
|
|
sta ZX0_src
|
|
lda #>bg1_data
|
|
sta ZX0_src+1
|
|
|
|
lda #$80
|
|
|
|
jsr full_decomp
|
|
|
|
|
|
;===================
|
|
; set up variables
|
|
|
|
lda #16
|
|
sta STRONGBAD_X
|
|
sta PLAYER_X
|
|
|
|
lda #1
|
|
sta STRONGBAD_DIR
|
|
sta BULLET_YDIR
|
|
|
|
lda #SHIELD_DOWN
|
|
sta SHIELD_POSITION
|
|
sta SHIELD_COUNT
|
|
|
|
lda #0
|
|
sta BULLET_X_L
|
|
sta BULLET_X_VEL
|
|
sta HEAD_DAMAGE
|
|
|
|
lda #$80
|
|
sta BULLET_X_VEL_L
|
|
|
|
lda #20
|
|
sta BULLET_X
|
|
lda #0
|
|
sta BULLET_Y
|
|
|
|
jmp main_loop
|
|
|
|
|
|
title_data:
|
|
.incbin "asplode_graphics/sb_title.hgr.zx02"
|
|
|
|
bg1_data:
|
|
.incbin "asplode_graphics/sb_zone.hgr.zx02"
|
|
|
|
sound_data:
|
|
.incbin "asplode_sound/asplode_sound.btc.zx02"
|
|
|
|
.include "hgr_tables.s"
|
|
.include "zx02_optim.s"
|
|
|
|
; start at least 8k in?
|
|
|
|
;==========================
|
|
; main loop
|
|
;===========================
|
|
main_loop:
|
|
|
|
jsr flip_page
|
|
|
|
;========================
|
|
; copy over background
|
|
;========================
|
|
reset_loop:
|
|
|
|
lda FRAME
|
|
and #$2
|
|
beq odd_bg
|
|
even_bg:
|
|
lda #$A0
|
|
bne do_bg
|
|
odd_bg:
|
|
lda #$80
|
|
do_bg:
|
|
jsr hgr_copy
|
|
|
|
|
|
inc FRAME
|
|
|
|
;==========================
|
|
; adjust shield
|
|
;==========================
|
|
|
|
lda SHIELD_COUNT
|
|
beq done_shield_count
|
|
|
|
dec SHIELD_COUNT
|
|
bne done_shield_count
|
|
|
|
lda #SHIELD_DOWN ; put shield down if timeout
|
|
sta SHIELD_POSITION
|
|
|
|
done_shield_count:
|
|
|
|
;===========================
|
|
; move head
|
|
;===========================
|
|
|
|
lda FRAME
|
|
and #$3
|
|
bne no_move_head
|
|
|
|
lda STRONGBAD_X
|
|
cmp #21
|
|
bcs reverse_head_dir
|
|
cmp #12
|
|
bcs no_reverse_head_dir
|
|
reverse_head_dir:
|
|
lda STRONGBAD_DIR
|
|
eor #$FF
|
|
sta STRONGBAD_DIR
|
|
inc STRONGBAD_DIR
|
|
|
|
no_reverse_head_dir:
|
|
|
|
clc
|
|
lda STRONGBAD_X
|
|
adc STRONGBAD_DIR
|
|
sta STRONGBAD_X
|
|
|
|
no_move_head:
|
|
|
|
|
|
|
|
;==========================
|
|
; draw head
|
|
;===========================
|
|
|
|
ldx HEAD_DAMAGE
|
|
lda head_sprites_l,X
|
|
sta INL
|
|
lda head_sprites_h,X
|
|
sta INH
|
|
lda STRONGBAD_X
|
|
sta SPRITE_X
|
|
lda #36
|
|
sta SPRITE_Y
|
|
jsr hgr_draw_sprite_big
|
|
|
|
;==========================
|
|
; move bullet
|
|
;===========================
|
|
|
|
; 16 bit add
|
|
|
|
clc
|
|
lda BULLET_X_L
|
|
adc BULLET_X_VEL_L
|
|
sta BULLET_X_L
|
|
lda BULLET_X
|
|
adc BULLET_X_VEL
|
|
sta BULLET_X
|
|
|
|
;========================
|
|
; bounce off "walls"
|
|
; in reality just bounce if <9 or > 29?
|
|
|
|
lda BULLET_X
|
|
cmp #29
|
|
bcs walls_out ; bge
|
|
cmp #9
|
|
bcs walls_good ; bge
|
|
|
|
walls_out:
|
|
|
|
; flip X direction
|
|
|
|
sec
|
|
lda #0
|
|
sbc BULLET_X_VEL_L
|
|
sta BULLET_X_VEL_L
|
|
lda #0
|
|
sbc BULLET_X_VEL
|
|
sta BULLET_X_VEL
|
|
|
|
|
|
walls_good:
|
|
|
|
; move bullet Y
|
|
|
|
lda BULLET_YDIR
|
|
bne bullet_down
|
|
|
|
bullet_up:
|
|
dec BULLET_Y
|
|
jmp bullet_y_done
|
|
|
|
bullet_down:
|
|
inc BULLET_Y
|
|
bullet_y_done:
|
|
|
|
; see if off end
|
|
|
|
lda BULLET_Y
|
|
cmp #17
|
|
bcc bullet_still_good
|
|
|
|
; reset to top
|
|
|
|
lda #0
|
|
sta BULLET_Y
|
|
bullet_still_good:
|
|
|
|
;==========================
|
|
; check bullet collisions
|
|
;===========================
|
|
|
|
;===========================
|
|
; check player
|
|
; if (bullet_x > player_x+2) &&
|
|
; (bullet_x<player_x+6)
|
|
; if 2 < bx - px < 6 ???
|
|
|
|
; 012345678
|
|
; b-p
|
|
; --------
|
|
; 8765432101234567890123456
|
|
; p-b ----------------
|
|
; 8765432101234567890123456
|
|
; NNNNNNNNNNYYYYNNNNNNNNNNN
|
|
; XXXXXXXXPPOOOOPPXXXXXXXXX
|
|
|
|
; only if BULLET_Y=16?
|
|
|
|
lda BULLET_Y
|
|
cmp #16
|
|
bne skip_check_player_collide
|
|
check_player_collide:
|
|
sec
|
|
lda BULLET_X
|
|
sbc PLAYER_X
|
|
cmp #2
|
|
bcc skip_check_player_collide ; blt
|
|
cmp #8
|
|
bcs skip_check_player_collide
|
|
|
|
jmp asplode_asplode
|
|
|
|
skip_check_player_collide:
|
|
|
|
;===========================
|
|
; check shield collide
|
|
|
|
; only if Y=15 and YDIR=1
|
|
check_shield_collide:
|
|
lda BULLET_Y
|
|
cmp #15
|
|
beq do_check_shields
|
|
jmp skip_check_shield_collide
|
|
|
|
do_check_shields:
|
|
; sorta-random number in X
|
|
ldx FRAME
|
|
lda $6000,X ; from source code
|
|
and #$3
|
|
tax
|
|
|
|
lda SHIELD_POSITION
|
|
beq skip_check_shield_collide ; 0 means DOWN
|
|
|
|
shields_up:
|
|
; our rules
|
|
; SHIELD_X_VEL maxes at 1/-1
|
|
; hitting shield left subs random $10/$20/$20/$40
|
|
; hitting shield right adds random $10/$20/$20/$40
|
|
; hitting shield center adds/subs random $10/$20
|
|
|
|
cmp #SHIELD_UP_RIGHT
|
|
beq check_hit_shield_right
|
|
cmp #SHIELD_UP_CENTER
|
|
beq check_hit_shield_center
|
|
|
|
check_hit_shield_left:
|
|
|
|
sec
|
|
lda BULLET_X
|
|
sbc PLAYER_X
|
|
cmp #1
|
|
bcc skip_check_shield_collide ; blt
|
|
cmp #7
|
|
bcs skip_check_shield_collide ; bge
|
|
|
|
hit_shield_left:
|
|
sec
|
|
lda BULLET_X_VEL_L
|
|
sbc bullet_vals,X
|
|
sta BULLET_X_VEL_L
|
|
lda BULLET_X_VEL
|
|
sbc #0
|
|
sta BULLET_X_VEL
|
|
jmp done_hit_shield
|
|
|
|
|
|
check_hit_shield_right:
|
|
|
|
sec
|
|
lda BULLET_X
|
|
sbc PLAYER_X
|
|
cmp #4
|
|
bcc skip_check_shield_collide ; blt
|
|
cmp #10
|
|
bcs skip_check_shield_collide
|
|
|
|
|
|
hit_shield_right:
|
|
clc
|
|
lda BULLET_X_VEL_L
|
|
adc bullet_vals,X
|
|
sta BULLET_X_VEL_L
|
|
lda BULLET_X_VEL
|
|
adc #0
|
|
sta BULLET_X_VEL
|
|
jmp done_hit_shield
|
|
|
|
check_hit_shield_center:
|
|
|
|
sec
|
|
lda BULLET_X
|
|
sbc PLAYER_X
|
|
cmp #2
|
|
bcc skip_check_shield_collide ; blt
|
|
cmp #8
|
|
bcs skip_check_shield_collide ; bge
|
|
|
|
hit_shield_center:
|
|
|
|
cpx #1
|
|
bcs center_left
|
|
|
|
clc
|
|
lda BULLET_X_VEL_L
|
|
adc bullet_vals_center,X
|
|
sta BULLET_X_VEL_L
|
|
lda BULLET_X_VEL
|
|
adc #0
|
|
sta BULLET_X_VEL
|
|
jmp done_hit_shield
|
|
|
|
center_left:
|
|
sec
|
|
lda BULLET_X_VEL_L
|
|
sbc bullet_vals_center,X
|
|
sta BULLET_X_VEL_L
|
|
lda BULLET_X_VEL
|
|
sbc #0
|
|
sta BULLET_X_VEL
|
|
; jmp done_hit_shield
|
|
|
|
|
|
done_hit_shield:
|
|
; max at $1/$00 or $FF/$00
|
|
|
|
|
|
; flip ydir
|
|
|
|
lda #0
|
|
sta BULLET_YDIR
|
|
|
|
; play sound
|
|
|
|
ldy #5
|
|
jsr play_asplode
|
|
|
|
|
|
|
|
skip_check_shield_collide:
|
|
|
|
;===========================
|
|
; check head
|
|
|
|
; only if Y=0 and YDIR=0
|
|
|
|
lda BULLET_Y
|
|
bne done_check_head
|
|
|
|
lda BULLET_YDIR
|
|
bne done_check_head
|
|
|
|
check_head_collide:
|
|
|
|
sec
|
|
lda BULLET_X
|
|
sbc STRONGBAD_X
|
|
cmp #0
|
|
bcc skip_check_head_collide ; blt
|
|
cmp #6
|
|
bcs skip_check_head_collide
|
|
|
|
inc HEAD_DAMAGE ; increase head damage
|
|
lda HEAD_DAMAGE
|
|
cmp #5
|
|
bcc skip_check_head_collide
|
|
|
|
lda #0 ; reset
|
|
sta HEAD_DAMAGE
|
|
|
|
skip_check_head_collide:
|
|
lda #1
|
|
sta BULLET_YDIR ; bounce
|
|
|
|
|
|
done_check_head:
|
|
|
|
|
|
;=====================
|
|
; play bullet sound
|
|
|
|
|
|
; if Y=1 and YDIR=1
|
|
|
|
lda BULLET_Y
|
|
cmp #1
|
|
bne no_ysound
|
|
|
|
lda BULLET_YDIR
|
|
beq no_ysound
|
|
|
|
ldy #6
|
|
jsr play_asplode
|
|
no_ysound:
|
|
|
|
;==========================
|
|
; draw bullet
|
|
;===========================
|
|
|
|
ldy BULLET_Y
|
|
lda bullet_sprite_l,Y
|
|
sta INL
|
|
lda bullet_sprite_h,Y
|
|
sta INH
|
|
|
|
lda BULLET_X
|
|
sta SPRITE_X
|
|
|
|
lda bullet_sprite_y,Y
|
|
sta SPRITE_Y
|
|
jsr hgr_draw_sprite_big
|
|
|
|
;==========================
|
|
; draw player
|
|
;===========================
|
|
|
|
ldx SHIELD_POSITION
|
|
lda shield_sprites_l,X
|
|
sta INL
|
|
lda shield_sprites_h,X
|
|
sta INH
|
|
lda PLAYER_X
|
|
sta SPRITE_X
|
|
lda #138
|
|
sta SPRITE_Y
|
|
jsr hgr_draw_sprite_big
|
|
|
|
check_keypress:
|
|
lda KEYPRESS
|
|
bpl done_keyboard_check
|
|
|
|
bit KEYRESET ; clear the keyboard strobe
|
|
|
|
; clear high bit
|
|
and #$7f
|
|
|
|
and #$df ; convert lowercase to upper
|
|
|
|
; cmp #'Q'
|
|
; beq done_game
|
|
|
|
cmp #27 ; escape
|
|
beq done_game
|
|
|
|
cmp #'A' ; shield left
|
|
beq shield_left
|
|
cmp #'S' ; shield center
|
|
beq shield_center
|
|
cmp #'D' ; shield right
|
|
beq shield_right
|
|
|
|
cmp #'O'
|
|
beq back_off
|
|
|
|
cmp #8 ; left
|
|
beq move_left
|
|
|
|
cmp #$15
|
|
beq move_right ; right
|
|
|
|
|
|
done_keyboard_check:
|
|
jmp main_loop
|
|
|
|
move_left:
|
|
lda PLAYER_X
|
|
beq no_more_left
|
|
dec PLAYER_X
|
|
no_more_left:
|
|
jmp main_loop
|
|
|
|
move_right:
|
|
lda PLAYER_X
|
|
cmp #28 ; bge
|
|
bcs no_more_right
|
|
inc PLAYER_X
|
|
no_more_right:
|
|
jmp main_loop
|
|
|
|
shield_left:
|
|
lda SHIELD_POSITION
|
|
bne done_adjust_shield
|
|
lda #SHIELD_UP_LEFT
|
|
bne adjust_shield
|
|
shield_center:
|
|
lda SHIELD_POSITION
|
|
bne done_adjust_shield
|
|
lda #SHIELD_UP_CENTER
|
|
bne adjust_shield
|
|
shield_right:
|
|
lda SHIELD_POSITION
|
|
bne done_adjust_shield
|
|
lda #SHIELD_UP_RIGHT
|
|
adjust_shield:
|
|
sta SHIELD_POSITION
|
|
lda #4
|
|
sta SHIELD_COUNT
|
|
done_adjust_shield:
|
|
jmp main_loop
|
|
|
|
asplode_asplode:
|
|
|
|
jsr do_asplode
|
|
|
|
jmp reset_loop
|
|
|
|
|
|
back_off:
|
|
lda #7
|
|
bne really_done_game ; bra
|
|
|
|
;==========================
|
|
; done game
|
|
;==========================
|
|
|
|
done_game:
|
|
lda #0
|
|
really_done_game:
|
|
sta WHICH_LOAD
|
|
rts
|
|
|
|
|
|
|
|
|
|
wait_until_keypress:
|
|
lda KEYPRESS ; 4
|
|
bpl wait_until_keypress ; 3
|
|
bit KEYRESET ; clear the keyboard buffer
|
|
rts
|
|
|
|
|
|
.include "asplode_head.s"
|
|
|
|
;==========
|
|
; flip page
|
|
;==========
|
|
flip_page:
|
|
lda DRAW_PAGE
|
|
beq draw_page2
|
|
draw_page1:
|
|
bit PAGE2
|
|
lda #0
|
|
|
|
beq done_flip
|
|
|
|
draw_page2:
|
|
bit PAGE1
|
|
lda #$20
|
|
|
|
done_flip:
|
|
sta DRAW_PAGE
|
|
|
|
rts
|
|
|
|
|
|
|
|
.include "hgr_sprite_big.s"
|
|
.include "cycle_colors.s"
|
|
.include "hgr_copy_fast.s"
|
|
.include "audio.s"
|
|
.include "play_asplode.s"
|
|
|
|
.include "asplode_graphics/sb_sprites.inc"
|
|
|
|
|
|
shield_sprites_l:
|
|
.byte <player_sprite,<shield_left_sprite
|
|
.byte <shield_center_sprite,<shield_right_sprite
|
|
|
|
shield_sprites_h:
|
|
.byte >player_sprite,>shield_left_sprite
|
|
.byte >shield_center_sprite,>shield_right_sprite
|
|
|
|
|
|
head_sprites_l:
|
|
.byte <big_head0_sprite,<big_head1_sprite,<big_head2_sprite
|
|
.byte <big_head3_sprite,<big_head4_sprite
|
|
|
|
head_sprites_h:
|
|
.byte >big_head0_sprite,>big_head1_sprite,>big_head2_sprite
|
|
.byte >big_head3_sprite,>big_head4_sprite
|
|
|
|
y_positions:
|
|
; 90 to 160 roughly? Let's say 64?
|
|
; have 16 positions? 4 each?
|
|
|
|
; can probably optimize this
|
|
|
|
bullet_sprite_l:
|
|
.byte <bullet0_sprite, <bullet1_sprite, <bullet2_sprite, <bullet3_sprite
|
|
.byte <bullet4_sprite, <bullet5_sprite, <bullet6_sprite, <bullet7_sprite
|
|
.byte <bullet8_sprite, <bullet9_sprite,<bullet10_sprite,<bullet11_sprite
|
|
.byte <bullet12_sprite,<bullet13_sprite,<bullet14_sprite,<bullet15_sprite
|
|
.byte <bullet_done_sprite
|
|
|
|
bullet_sprite_h:
|
|
.byte >bullet0_sprite, >bullet1_sprite, >bullet2_sprite, >bullet3_sprite
|
|
.byte >bullet4_sprite, >bullet5_sprite, >bullet6_sprite, >bullet7_sprite
|
|
.byte >bullet8_sprite, >bullet9_sprite,>bullet10_sprite,>bullet11_sprite
|
|
.byte >bullet12_sprite,>bullet13_sprite,>bullet14_sprite,>bullet15_sprite
|
|
.byte >bullet_done_sprite
|
|
|
|
bullet_sprite_y:
|
|
.byte 83,88,93,98
|
|
.byte 103,108,113,118
|
|
.byte 123,128,133,138
|
|
.byte 143,148,153,158
|
|
.byte 163
|
|
|
|
bullet_vals:
|
|
.byte $10,$20,$20,$40
|
|
|
|
bullet_vals_center:
|
|
.byte $20,$00,$00,$20
|
|
|
|
; original
|
|
; 1 = 6
|
|
; 2 = 12
|
|
; 3 = 18
|
|
; 4 = 25
|
|
; 5 = 32
|
|
; 6 = 38
|
|
; 7 = 44
|
|
; 8 = 50
|
|
; 9 = 57
|
|
; 10= 63
|
|
; 11= 70
|
|
; 12= 77
|
|
; 13= 82
|
|
; 14= 89
|
|
; 15= 95
|
|
; 27= 167 (peak)
|
|
; 30= 148
|
|
; 31= 139
|
|
|
|
; 9,5 -> 22,14 = 12x9 roughly. 3 times smaller, 4x3? 2x6?
|
|
|
|
bg2_data:
|
|
.incbin "asplode_graphics/sb_zone2.hgr.zx02"
|