1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-10-04 11:59:38 +00:00
SixtyPical/eg/game.60p
2014-04-13 13:42:15 +01:00

366 lines
7.0 KiB
Plaintext

assign byte[256] screen $0400
assign byte[256] screen2 1274
assign byte[256] screen3 1524
assign byte[256] screen4 1774
assign byte[256] colormap 55296
assign byte[256] colormap2 55546
assign byte[256] colormap3 55796
assign byte[256] colormap4 56046
assign byte vic_border 53280
assign byte[4] vic_bg 53281
assign byte joy2 $dc00
assign vector cinv 788
/* --------- */
reserve vector save_cinv
// these are zero-page so that we can use them as indirect addresses
// through which we write to screen memory
assign word position $fb
assign word new_position $fd
reserve word delta
reserve byte value
reserve word compare_target
reserve word[16] actor_pos
reserve word[16] actor_delta
reserve vector[16] actor_logic
reserve vector dispatch_state
reserve vector dispatch_logic
reserve byte[18] press_fire_msg: "PRESS`FIRE`TO`PLAY"
// could be routine-local, if they were truly static
reserve byte button_down: 0
/******************************************
* Utility routines for manipulating/checking the current actor's
* position and delta.
******************************************/
routine reverse_delta {
lda #40
cmp <delta
if beq {
// copy #-40 delta
lda #216
sta <delta
lda #255
sta >delta
} else {
// copy #40 delta
lda #40
sta <delta
lda #0
sta >delta
}
}
routine calculate_new_position outputs (new_position) {
clc
lda <position
adc <delta
sta <new_position
lda >position
adc >delta
sta >new_position
}
routine compare_new_pos outputs (.c) {
lda >new_position
cmp >compare_target
if beq {
lda <new_position
cmp <compare_target
} else {
}
}
routine check_new_position_in_bounds outputs (.c) {
copy #$07e8 compare_target // just past bottom of screen
jsr compare_new_pos
if bcs {
clc
} else {
copy #$0400 compare_target
jsr compare_new_pos
if bcc {
clc
} else {
sec
}
}
}
/******************************************
* Utility routines for dealing with the current actor's logic routine.
******************************************/
routine indirect_jsr_logic {
jmp (dispatch_logic)
}
routine read_stick outputs (delta) {
lda #0
sta <delta
sta >delta
ldx joy2
txa
and #1 // up
if beq {
lda #216 // -40
sta <delta
lda #255
sta >delta
} else {
txa
and #2 // down
if beq {
lda #40
sta <delta
} else {
txa
and #4 // left
if beq {
lda #255 // -1
sta <delta
sta >delta
} else {
txa
and #8 // right
if beq {
lda #1
sta <delta
} else { }
}
}
}
}
routine check_fire outputs (.z) {
ldx joy2
txa
and #16
}
/********************
*** Actor Logics ***
********************/
routine logic_player {
jsr read_stick
jsr calculate_new_position
jsr check_new_position_in_bounds
if bcs {
ldy #0
lda (new_position), y
cmp #32
if beq {
lda #32
ldy #0
sta (position), y
copy new_position position
lda #81
ldy #0
sta (position), y
} else {
// copy routine state_game_over to dispatch_state
}
} else { }
}
routine logic_obstacle {
jsr calculate_new_position
jsr check_new_position_in_bounds
if bcs {
ldy #0
lda (new_position), y
cmp #32
if beq {
lda #32
ldy #0
sta (position), y
copy new_position position
lda #82
ldy #0
sta (position), y
} else {
copy routine state_game_over to dispatch_state
}
} else {
jsr reverse_delta
}
}
/******************************************
* Utility routines used in dealing with the game state.
******************************************/
routine clear_screen {
ldy #0
repeat bne {
lda #1
sta colormap, y
sta colormap2, y
sta colormap3, y
sta colormap4, y
lda #32
sta screen, y
sta screen2, y
sta screen3, y
sta screen4, y
iny
cpy #250
}
}
// You can repeatedly (i.e. as part of actor logic or an IRQ handler)
// call this routine.
// Upon return, if carry is set, the button was pressed then released.
routine check_button outputs (.c) {
lda button_down
if beq {
lda joy2
and #$10
if beq {
lda #1
sta button_down
} else { }
clc
} else {
lda joy2
and #$10
if bne {
lda #0
sta button_down
sec
} else {
clc
}
}
}
routine init_game {
ldy #0
ldx #0
repeat bne {
copy #$04 >actor_pos, y
txa
copy .a <actor_pos, y
inx
inx
inx
inx
inx
inx
inx
// sigh
// copy #$0001 actor_delta, y
copy #00 >actor_delta, y
copy #40 <actor_delta, y
cpy #0
if beq {
copy routine logic_player to actor_logic, y
} else {
copy routine logic_obstacle to actor_logic, y
}
iny
cpy #16
}
}
/*******************
*** Game States ***
*******************/
routine state_title_screen {
lda #5
sta vic_border
lda #0
sta vic_bg
ldy #0
repeat bne {
lda press_fire_msg, y
sec
sbc #64 // yuck
sta screen, y
iny
cpy #18
}
jsr check_button
if bcs {
jsr clear_screen
jsr init_game
copy routine state_play_game to dispatch_state
} else { }
jmp (save_cinv)
}
routine state_game_over {
inc vic_border
jsr check_button
if bcs {
jsr clear_screen
copy routine state_title_screen to dispatch_state
} else { }
jmp (save_cinv)
}
routine state_play_game {
reserve byte save_x
ldx #0
repeat bne {
stx save_x
copy actor_pos, x position
copy actor_delta, x delta
copy actor_logic, x dispatch_logic
jsr indirect_jsr_logic
ldx save_x
copy position actor_pos, x
copy delta actor_delta, x
inx
cpx #16
}
jmp (save_cinv)
}
/*************************
* Main Game Loop Driver *
*************************/
routine our_cinv {
jmp (dispatch_state)
}
routine main {
jsr clear_screen
copy routine state_title_screen to dispatch_state
with sei {
copy cinv save_cinv
copy routine our_cinv to cinv
}
clc
repeat bcc { }
}