dos33fsprogs/games/lemm/keyboard.s
Vince Weaver c6fa85acf0 lemm: let you switch jobs if digging, etc
I think the actual game lets you do this
2022-04-19 21:27:36 -04:00

720 lines
11 KiB
ArmAsm

;==============================
; Handle Keypress
;==============================
handle_keypress:
; first handle joystick
lda JOYSTICK_ENABLED
beq actually_handle_keypress
; only check joystick every-other frame
lda FRAMEL
and #$1
beq actually_handle_keypress
check_button:
lda PADDLE_BUTTON0
bpl button_clear
lda JS_BUTTON_STATE
bne js_check
lda #1
sta JS_BUTTON_STATE
lda #' '
jmp handle_input
button_clear:
lda #0
sta JS_BUTTON_STATE
js_check:
jsr handle_joystick
js_check_left:
lda value0
cmp #$20
bcs js_check_right ; if less than 32, left
lda #'A'
bne handle_input
js_check_right:
cmp #$40
bcc js_check_up
lda #'D'
bne handle_input
js_check_up:
lda value1
cmp #$20
bcs js_check_down
lda #'W'
bne handle_input
js_check_down:
cmp #$40
bcc done_joystick
lda #'S'
bne handle_input
done_joystick:
actually_handle_keypress:
lda KEYPRESS
bmi keypress
jmp no_keypress
keypress:
and #$7f ; clear high bit
cmp #$40
bcc handle_input ; make sure not to lose space
; and numbers
and #$df ; convert uppercase to lower case
handle_input:
; first check if 1...8 pressed
cmp #'1'
bcc check_sound
cmp #'9'
bcs check_sound
sec ; map 1->3, 2->4, 4->5, etc
sbc #'1'
clc
adc #3
jsr handle_menu_which_in_a
jmp done_keypress
check_sound:
cmp #$14 ; control-T
bne check_joystick
lda SOUND_STATUS
eor #SOUND_DISABLED
sta SOUND_STATUS
jmp done_keypress
; can't be ^J as that's the same as down
check_joystick:
cmp #'J'
bne check_left
lda JOYSTICK_ENABLED
eor #1
sta JOYSTICK_ENABLED
jmp done_keypress
check_left:
cmp #'A'
beq left_pressed
cmp #8 ; left key
bne check_right
left_pressed:
lda CURSOR_X ; if X==0 don't decrement
beq done_left_pressed
do_dec_cursor_x:
dec CURSOR_X
done_left_pressed:
jmp done_keypress
check_right:
cmp #'D'
beq right_pressed
cmp #$15 ; right key
bne check_up
right_pressed:
lda CURSOR_X ; if X>=38 don't increment
cmp #38
bcs done_right_pressed
do_inc_cursor_x:
inc CURSOR_X
done_right_pressed:
jmp done_keypress
check_up:
cmp #'W'
beq up_pressed
cmp #$0B ; up key
bne check_down
up_pressed:
lda CURSOR_Y ; if Y==0 don't increment
beq done_up_pressed
do_dec_cursor_y:
dec CURSOR_Y
dec CURSOR_Y
dec CURSOR_Y
dec CURSOR_Y
done_up_pressed:
jmp done_keypress
check_down:
cmp #'S'
beq down_pressed
cmp #$0A
bne check_escape
down_pressed:
lda CURSOR_Y ; if Y>=176 then don't inc?
cmp #176 ; cursor is 14 in size
; bcc do_inc_cursor_y
; cmp #$EE
bcs done_down_pressed
do_inc_cursor_y:
inc CURSOR_Y
inc CURSOR_Y
inc CURSOR_Y
inc CURSOR_Y
done_down_pressed:
jmp done_keypress
check_escape:
cmp #27
bne check_cheat
escape_pressed:
lda #LEVEL_FAIL
sta LEVEL_OVER
jmp done_keypress
check_cheat:
cmp #'!'
bne check_return
cheat_pressed:
lda #20
ldx #7
cheat_loop:
sta CLIMBER_COUNT,X
dex
bpl cheat_loop
jsr update_remaining_all
jmp done_keypress
check_return:
cmp #' '
beq return_pressed
cmp #13
bne done_keypress
return_pressed:
; first check if off bottom of screen
lda CURSOR_Y
cmp #168-8 ; center of cursor
bcc return_check_lemming
jsr handle_menu
jmp done_keypress
; next check if over lemming
return_check_lemming:
lda OVER_LEMMING
bmi not_over_lemming
tay
; check if digging selected
jsr click_speaker
lda BUTTON_LOCATION
tax
lda button_jump_h,X
pha
lda button_jump_l,X
pha
rts ; jump to it
not_over_lemming:
done_keypress:
no_keypress:
bit KEYRESET
rts
button_jump_l:
.byte <(make_nop-1)
.byte <(make_climber-1)
.byte <(make_floater-1)
.byte <(make_exploding-1)
.byte <(make_stopper-1)
.byte <(make_builder-1)
.byte <(make_basher-1)
.byte <(make_miner-1)
.byte <(make_digger-1)
button_jump_h:
.byte >(make_nop-1)
.byte >(make_climber-1)
.byte >(make_floater-1)
.byte >(make_exploding-1)
.byte >(make_stopper-1)
.byte >(make_builder-1)
.byte >(make_basher-1)
.byte >(make_miner-1)
.byte >(make_digger-1)
make_nop:
jmp done_keypress
;========================
; make climber
;========================
make_climber:
lda CLIMBER_COUNT ; only if we have some left
beq done_make_climber
lda lemming_attribute,Y ; don't make climber if already one
and #LEMMING_CLIMBER
bne done_make_climber
lda #LEMMING_CLIMBER
ora lemming_attribute,Y
sta lemming_attribute,Y
dec CLIMBER_COUNT
ldx #0
jsr update_remaining
done_make_climber:
jmp done_keypress
;========================
; make floater
;========================
make_floater:
lda FLOATER_COUNT ; only if we have some left
beq done_make_floater
lda lemming_attribute,Y ; don't make floater if already one
and #LEMMING_FLOATER
bne done_make_floater
lda #LEMMING_FLOATER
ora lemming_attribute,Y
sta lemming_attribute,Y
dec FLOATER_COUNT
ldx #1
jsr update_remaining
done_make_floater:
jmp done_keypress
;========================
; make exploding
;========================
make_exploding:
lda EXPLODER_COUNT ; only if we have some left
beq done_make_exploder
ldx #0 ; regular frame start
jsr explode_lemming
dec EXPLODER_COUNT
ldx #2
jsr update_remaining
done_make_exploder:
jmp done_keypress
;========================
; make stopper
;========================
make_stopper:
lda STOPPER_COUNT ; only if we have some left
beq cant_stop
lda lemming_status,Y
cmp #LEMMING_FLOATER ; can't stop if floating
beq cant_stop
cmp #LEMMING_FALLING ; can't stop if falling
beq cant_stop
cmp #LEMMING_STOPPING ; an unmoving object can't be
beq cant_stop ; stopped!
lda #LEMMING_STOPPING
sta lemming_status,Y
; put line on page2 to make lemmings reverse
; make it a specific pattern so climbers won't climb over
lda lemming_x,Y
sta dbl_smc2+1
lda lemming_y,Y
tax
inx
clc
adc #8
sta dbl_smc+1
draw_blocker_loop:
lda hposn_high,X
clc
adc #$20
sta GBASH
lda hposn_low,X
sta GBASL
dbl_smc2:
ldy #30
lda #$10
sta (GBASL),Y
inx
dbl_smc:
cpx #8
bne draw_blocker_loop
dec STOPPER_COUNT
ldx #3
jsr update_remaining
cant_stop:
jmp done_keypress
;========================
; make builder
;========================
make_builder:
; if walking, shrugging, bashing
lda lemming_status,Y
cmp #LEMMING_WALKING
beq really_make_builder
cmp #LEMMING_SHRUGGING
beq really_make_builder
cmp #LEMMING_BASHING
beq really_make_builder
jmp done_make_builder
really_make_builder:
lda BUILDER_COUNT ; only if we have some left
beq done_make_builder
lda #LEMMING_BUILDING
sta lemming_status,Y
; build count=0
lda lemming_attribute,Y
and #$f0
sta lemming_attribute,Y
dec BUILDER_COUNT
ldx #4
jsr update_remaining
done_make_builder:
jmp done_keypress
;========================
; make basher
;========================
; note on Level 9 we have one-way blocks
; cheat and just only allow digging when facing left on L9
make_basher:
lda BASHER_COUNT ; only if we have some left
beq done_make_basher
; only do it if walking, digging, mining, building, bashing
lda lemming_status,Y
cmp #LEMMING_WALKING
beq yes_make_basher
cmp #LEMMING_DIGGING
beq yes_make_basher
cmp #LEMMING_MINING
beq yes_make_basher
cmp #LEMMING_BUILDING
beq yes_make_basher
cmp #LEMMING_BASHING
bne done_make_basher
yes_make_basher:
; see if level #9
lda WHICH_LEVEL
cmp #9
bne not_oneway
lda lemming_direction,Y
bpl couldnt_bash ; on l9 only if facing left
not_oneway:
lda #LEMMING_BASHING
sta lemming_status,Y
couldnt_bash:
dec BASHER_COUNT
ldx #5
jsr update_remaining
done_make_basher:
jmp done_keypress
;========================
; make miner
;========================
make_miner:
lda MINER_COUNT ; only if we have some left
beq done_make_miner
; only do it if walking, digging, mining, building, bashing
lda lemming_status,Y
cmp #LEMMING_WALKING
beq yes_make_miner
cmp #LEMMING_DIGGING
beq yes_make_miner
cmp #LEMMING_MINING
beq yes_make_miner
cmp #LEMMING_BUILDING
beq yes_make_miner
cmp #LEMMING_BASHING
bne done_make_miner
yes_make_miner:
lda #LEMMING_MINING
sta lemming_status,Y
dec MINER_COUNT
ldx #6
jsr update_remaining
done_make_miner:
jmp done_keypress
;========================
; make digger
;========================
make_digger:
lda DIGGER_COUNT ; only if we have some left
beq done_make_digger
; only do it if walking, digging, mining, building, bashing
lda lemming_status,Y
cmp #LEMMING_WALKING
beq yes_make_digger
cmp #LEMMING_DIGGING
beq yes_make_digger
cmp #LEMMING_MINING
beq yes_make_digger
cmp #LEMMING_BUILDING
beq yes_make_digger
cmp #LEMMING_BASHING
bne done_make_digger
yes_make_digger:
lda #LEMMING_DIGGING
sta lemming_status,Y
dec DIGGER_COUNT
ldx #7
jsr update_remaining
done_make_digger:
jmp done_keypress
;=============================
;=============================
; handle menu
;=============================
;=============================
handle_menu:
; see where we clicked
lda CURSOR_X
; urgh need to multiply by 7
clc
asl
adc CURSOR_X
asl
adc CURSOR_X
clc
adc #24 ; adjust to center
lsr ; /16 for on-screen co-ords
lsr
lsr
lsr ; each box is 16 wide
handle_menu_which_in_a:
cmp #3
bcc plus_minus_buttons
cmp #11
beq pause_button
cmp #12
beq nuke_button
bcs map_grid_button
;==========================
; otherwise was job button
job_button:
pha
jsr click_speaker
pla
pha
; erase old
jsr erase_menu
; update value
pla
sec
sbc #2
sta BUTTON_LOCATION
; draw new
jsr update_selection
jmp done_menu
;============================
;============================
; plus/minus button
;============================
;============================
plus_minus_buttons:
lda release_lemming_speed+1
cmp #1
beq done_plus_adjust
lsr release_lemming_speed+1 ; make release faster
done_plus_adjust:
jmp done_menu
;============================
;============================
; nuke
;============================
;============================
nuke_button:
; stop lemmings from exiting
lda #0
sta LEMMINGS_TO_RELEASE
ldx #0 ; initial frame offset
ldy #0
nuke_loop:
jsr explode_lemming
dex
iny
cpy #MAX_LEMMINGS
bne nuke_loop
jmp done_menu
;============================
;============================
; map grid
;============================
;============================
map_grid_button:
; TODO
jmp done_menu
;============================
;============================
; pause
;============================
;============================
; FIXME: should stop clock too
pause_button:
bit KEYRESET
jsr wait_until_keypress
done_menu:
rts
;=====================
;=====================
; explode lemming
;=====================
;=====================
; which is in Y
; frame is in X
explode_lemming:
; only explode if not already exploding
lda lemming_exploding,Y
bne skip_explode
txa
sta lemming_exploding_frame,Y
lda #2 ; 2 not 1 as we don't display the
; first partial second
sta lemming_exploding,Y
skip_explode:
rts