sb: work on cliff

This commit is contained in:
Vince Weaver 2023-08-14 01:40:08 -04:00
parent 82fa0203b3
commit bee32d7ab1
20 changed files with 1729 additions and 111 deletions

View File

@ -12,7 +12,7 @@ all: sb.dsk
####
sb.dsk: QBOOT QLOAD TITLE DUCK_POND ROOF ASPLODE BACK_OFF TARGET CLIFF RAT
sb.dsk: QBOOT QLOAD TITLE DUCK_POND ROOF ASPLODE BACK_OFF TARGET ./cliff/CLIFF RAT
cp $(EMPTY_DISK) sb.dsk
$(DOS33_RAW) sb.dsk 0 0 QBOOT 0 1
$(DOS33_RAW) sb.dsk 0 2 QBOOT 1 1
@ -23,7 +23,7 @@ sb.dsk: QBOOT QLOAD TITLE DUCK_POND ROOF ASPLODE BACK_OFF TARGET CLIFF RAT
$(DOS33_RAW) sb.dsk 10 0 ROOF 0 0
$(DOS33_RAW) sb.dsk 15 0 ASPLODE 0 0
$(DOS33_RAW) sb.dsk 20 0 TARGET 0 0
$(DOS33_RAW) sb.dsk 25 0 CLIFF 0 0
$(DOS33_RAW) sb.dsk 25 0 ./cliff/CLIFF 0 0
$(DOS33_RAW) sb.dsk 30 0 RAT 0 0
$(DOS33_RAW) sb.dsk 32 0 BACK_OFF 0 0
@ -97,16 +97,19 @@ back_off.o: back_off.s zx02_optim.s \
####
CLIFF: cliff.o
ld65 -o CLIFF cliff.o -C $(LINKER_SCRIPTS)/apple2_6000.inc
./cliff/CLIFF:
cd cliff && make
cliff.o: cliff.s zx02_optim.s \
cliff_graphics/cliff_base.hgr.zx02 \
zp.inc hardware.inc
ca65 -o cliff.o cliff.s -l cliff.lst
#CLIFF: cliff.o
# ld65 -o CLIFF cliff.o -C $(LINKER_SCRIPTS)/apple2_6000.inc
cliff_graphics/cliff_base.hgr.zx02:
cd cliff_graphics && make
#cliff.o: cliff.s zx02_optim.s \
# cliff_graphics/cliff_base.hgr.zx02 \
# zp.inc hardware.inc
# ca65 -o cliff.o cliff.s -l cliff.lst
#cliff_graphics/cliff_base.hgr.zx02:
# cd cliff_graphics && make
####

View File

@ -1,74 +0,0 @@
; Cliff climb minigame from Peasant's Quest
;
; Yet Another HR project
;
; by deater (Vince Weaver) <vince@deater.net>
.include "zp.inc"
.include "hardware.inc"
hires_start:
;===================
; set graphics mode
;===================
jsr HOME
bit HIRES
bit FULLGR
bit SET_GR
bit PAGE1
;===================
; Load graphics
;===================
load_loop:
;=============================
;==========================
; Load Image
;===========================
load_image:
; size in ldsizeh:ldsizel (f1/f0)
lda #<comp_data
sta ZX0_src
lda #>comp_data
sta ZX0_src+1
lda #$20
jsr full_decomp
; rts
wait_until_keypress:
lda KEYPRESS ; 4
bpl wait_until_keypress ; 3
bit KEYRESET ; clear the keyboard buffer
which_ok:
lda #0
sta WHICH_LOAD
rts
.include "zx02_optim.s"
comp_data:
.incbin "cliff_graphics/cliff_base.hgr.zx02"

30
games/sb/cliff/Makefile Normal file
View File

@ -0,0 +1,30 @@
include ../../../Makefile.inc
ZX02 = ~/research/6502_compression/zx02.git/build/zx02
PNG_TO_HGR = ../../utils/hgr-utils/png2hgr
LINKER_SCRIPTS = ../../../linker_scripts
DOS33 = ../../utils/dos33fs-utils/dos33
DOS33_RAW = ../../utils/dos33fs-utils/dos33_raw
EMPTY_DISK = ../../empty_disk/empty.dsk
TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft
all: CLIFF
####
CLIFF: cliff.o
ld65 -o CLIFF cliff.o -C $(LINKER_SCRIPTS)/apple2_6000.inc
cliff.o: cliff.s ../zx02_optim.s \
cliff_graphics/cliff_base.hgr.zx02 \
zp.inc hardware.inc
ca65 -o cliff.o cliff.s -l cliff.lst
cliff_graphics/cliff_base.hgr.zx02:
cd cliff_graphics && make
####
clean:
rm -f *.lst *.o CLIFF
cd cliff_graphics && make clean

161
games/sb/cliff/cliff.s Normal file
View File

@ -0,0 +1,161 @@
; Cliff climb minigame from Peasant's Quest
;
; Yet Another HR project
;
; by deater (Vince Weaver) <vince@deater.net>
.include "zp.inc"
.include "hardware.inc"
;div7_table = $400
;mod7_table = $500
;hposn_high = $600
;hposn_low = $700
div7_table = $b800
mod7_table = $b900
hposn_high = $ba00
hposn_low = $bb00
cliff_base:
;===================
; set graphics mode
;===================
jsr HOME
bit HIRES
bit FULLGR
bit SET_GR
bit PAGE1
lda #0
sta LEVEL_OVER
sta FRAME
lda #10
sta PEASANT_X
lda #100
sta PEASANT_Y
jsr hgr_make_tables
;===================
; Load graphics
;===================
lda #<priority_data
sta ZX0_src
lda #>priority_data
sta ZX0_src+1
lda #$20 ; temporarily load to $2000
jsr full_decomp
; copy to $400
jsr gr_copy_to_page1
;=============================
;==========================
; Load Image
;===========================
load_image:
; size in ldsizeh:ldsizel (f1/f0)
lda #<bg_data
sta ZX0_src
lda #>bg_data
sta ZX0_src+1
lda #$20
jsr full_decomp
jsr hgr_copy
;==========================
;==========================
; main loop
;==========================
;==========================
game_loop:
;=====================
; move peasant
jsr move_peasant
;=====================
; draw peasant
jsr draw_peasant
;=====================
; increment frame
inc FRAME
;=====================
; check keyboard
jsr check_keyboard
lda LEVEL_OVER
bne done_cliff
; delay
lda #200
jsr wait
jmp game_loop
done_cliff:
lda #0
sta WHICH_LOAD
rts
.include "../hgr_tables.s"
.include "../zx02_optim.s"
.include "wait.s"
.include "keyboard.s"
.include "draw_peasant.s"
.include "move_peasant.s"
.include "hgr_partial_save.s"
.include "hgr_1x28_sprite_mask.s"
.include "gr_copy.s"
.include "hgr_copy.s"
.include "cliff_graphics/peasant_robe_sprites.inc"
bg_data:
.incbin "cliff_graphics/cliff_base.hgr.zx02"
priority_data:
.incbin "cliff_graphics/cliff_base_priority.zx02"

View File

@ -0,0 +1,51 @@
include ../../../../Makefile.inc
ZX02 = ~/research/6502_compression/zx02.git/build/zx02 -f
PNG_TO_HGR = ../../../../utils/hgr-utils/png2hgr
PNG2GR = ../../../../utils/gr-utils/png2gr
PNG2SPRITES = ../../../../utils/gr-utils/png2sprites
HGR_SPRITE = ../../../../utils/hgr-utils/hgr_make_sprite
all: cliff_base.hgr.zx02 peasant_robe_sprites.inc \
cliff_base_priority.zx02
####
peasant_robe_sprites.inc: peasant_sprites.png
$(HGR_SPRITE) -l peasant_right1_sprite peasant_sprites.png 133 1 133 29 > peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_right1_mask peasant_sprites.png 119 1 119 29 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_right2_sprite peasant_sprites.png 133 34 133 62 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_right2_mask peasant_sprites.png 119 34 119 62 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_up1_sprite peasant_sprites.png 133 68 133 96 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_up1_mask peasant_sprites.png 119 68 119 96 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_up2_sprite peasant_sprites.png 133 102 133 130 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_up2_mask peasant_sprites.png 119 102 119 130 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_left1_sprite peasant_sprites.png 182 1 188 29 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_left1_mask peasant_sprites.png 168 1 174 29 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_left2_sprite peasant_sprites.png 182 34 188 62 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_left2_mask peasant_sprites.png 168 34 174 62 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_down1_sprite peasant_sprites.png 182 68 188 96 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_down1_mask peasant_sprites.png 168 68 174 96 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_down2_sprite peasant_sprites.png 182 102 188 130 >> peasant_robe_sprites.inc
$(HGR_SPRITE) -l peasant_down2_mask peasant_sprites.png 168 102 174 130 >> peasant_robe_sprites.inc
####
cliff_base.hgr.zx02: cliff_base.hgr
$(ZX02) cliff_base.hgr cliff_base.hgr.zx02
cliff_base.hgr: cliff_base.png
$(PNG_TO_HGR) cliff_base.png > cliff_base.hgr
####
cliff_base_priority.zx02: cliff_base_priority.gr
$(ZX02) -f cliff_base_priority.gr cliff_base_priority.zx02
cliff_base_priority.gr: cliff_base_priority.png
$(PNG2GR) cliff_base_priority.png cliff_base_priority.gr
####
clean:
rm -f *~ *.o *.zx02 *.lst peasant_robe_sprites.inc

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,116 @@
;============================
; draw peasant
;============================
draw_peasant:
; skip if room over, as otherwise we'll draw at the
; wrong edge of screen
lda LEVEL_OVER
bne done_draw_peasant
lda PEASANT_X
sta CURSOR_X
lda PEASANT_Y
sta CURSOR_Y
lda PEASANT_DIR
cmp #PEASANT_DIR_RIGHT
beq peasant_right
cmp #PEASANT_DIR_LEFT
beq peasant_left
cmp #PEASANT_DIR_DOWN
beq peasant_down
; else we are up
;=====================
; up up up up
peasant_up:
lda PEASANT_Y
and #4
beq peasant_up1
peasant_up2:
lda #<peasant_up2_sprite
sta INL
lda #>peasant_up2_sprite
jmp done_pick_draw
peasant_up1:
lda #<peasant_up1_sprite
sta INL
lda #>peasant_up1_sprite
jmp done_pick_draw
;=====================
; down down down
peasant_down:
lda PEASANT_Y
and #4
beq peasant_down1
peasant_down2:
lda #<peasant_down2_sprite
sta INL
lda #>peasant_down2_sprite
jmp done_pick_draw
peasant_down1:
lda #<peasant_down1_sprite
sta INL
lda #>peasant_down1_sprite
jmp done_pick_draw
;=====================
; left left left
peasant_left:
lda CURSOR_X
and #1
bne draw_left1
draw_left2:
lda #<peasant_left2_sprite
sta INL
lda #>peasant_left2_sprite
jmp done_pick_draw
draw_left1:
lda #<peasant_left1_sprite
sta INL
lda #>peasant_left1_sprite
jmp done_pick_draw
peasant_right:
lda CURSOR_X
and #1
bne draw_right1
draw_right2:
lda #<peasant_right2_sprite
sta INL
lda #>peasant_right2_sprite
jmp done_pick_draw
draw_right1:
lda #<peasant_right1_sprite
sta INL
lda #>peasant_right1_sprite
done_pick_draw:
sta INH
jsr hgr_draw_sprite_1x28
done_draw_peasant:
rts
;.include "sprites/peasant_sprites.inc"
;.include "sprites/peasant_robe_sprites.inc"

39
games/sb/cliff/gr_copy.s Normal file
View File

@ -0,0 +1,39 @@
;=========================================================
; gr_copy_to_page1, 40x48 version
;=========================================================
; copy $2000 to $400, careful to avoid screen holes
gr_copy_to_page1:
ldy #119 ; for early ones, copy 120 bytes ; 2
gr_copy_line:
lda $2000,Y ; load a byte (self modified) ; 4
sta $400,Y ; store a byte (self modified) ; 5
lda $2080,Y ; load a byte (self modified) ; 4
sta $480,Y ; store a byte (self modified) ; 5
lda $2100,Y ; load a byte (self modified) ; 4
sta $500,Y ; store a byte (self modified) ; 5
lda $2180,Y ; load a byte (self modified) ; 4
sta $580,Y ; store a byte (self modified) ; 5
lda $2200,Y ; load a byte (self modified) ; 4
sta $600,Y ; store a byte (self modified) ; 5
lda $2280,Y ; load a byte (self modified) ; 4
sta $680,Y ; store a byte (self modified) ; 5
lda $2300,Y ; load a byte (self modified) ; 4
sta $700,Y ; store a byte (self modified) ; 5
lda $2380,Y ; load a byte (self modified) ; 4
sta $780,Y ; store a byte (self modified) ; 5
dey ; decrement pointer ; 2
bpl gr_copy_line ; ; 2nt/3
rts ; 6

View File

@ -0,0 +1,5 @@
gr_offsets:
.word $400,$480,$500,$580,$600,$680,$700,$780
.word $428,$4a8,$528,$5a8,$628,$6a8,$728,$7a8
.word $450,$4d0,$550,$5d0,$650,$6d0,$750,$7d0

105
games/sb/cliff/hardware.inc Normal file
View File

@ -0,0 +1,105 @@
; HARDWARE LOCATIONS
KEYPRESS = $C000
KEYRESET = $C010
; SOFT SWITCHES
CLR80COL = $C000 ; PAGE1/PAGE1 normal
SET80COL = $C001 ; PAGE1/PAGE2 switches PAGE1 in Aux instead
EIGHTYCOLOFF = $C00C
EIGHTYCOLON = $C00D
TBCOLOR = $C022 ; IIgs text foreground / background colors
NEWVIDEO = $C029 ; IIgs graphics modes
SPEAKER = $C030
CLOCKCTL = $C034 ; bits 0-3 are IIgs border color
SET_GR = $C050
SET_TEXT = $C051
FULLGR = $C052
TEXTGR = $C053
PAGE1 = $C054
PAGE2 = $C055
LORES = $C056 ; Enable LORES graphics
HIRES = $C057 ; Enable HIRES graphics
AN3 = $C05E ; Annunciator 3
PADDLE_BUTTON0 = $C061
PADDL0 = $C064
PTRIG = $C070
LCBANK2 = $C083
LCBANK1 = $C08B
; APPLESOFT BASIC ROUTINES
;NORMAL = $F273
;HGR2 = $F3D8
;HGR = $F3E2
;BKGND0 = $F3F4 ; clear current page to A
;HPOSN = $F411 ; (Y,X),(A) (values stores in HGRX,XH,Y)
HPLOT0 = $F457 ; plot at (Y,X), (A)
;COLOR_SHIFT = $F47E
;HLINRL = $F530 ; (X,A),(Y)
;HGLIN = $F53A ; line to (X,A),(Y)
;COLORTBL = $F6F6
; MONITOR ROUTINES
;HLINE = $F819 ; HLINE Y,$2C at A
;VLINE = $F828 ; VLINE A,$2D at Y
;CLRSCR = $F832 ; Clear low-res screen
;CLRTOP = $F836 ; clear only top of low-res screen
;SETCOL = $F864 ; COLOR=A
;ROM_TEXT2COPY = $F962 ; iigs
TEXT = $FB36 ; qboot
;TABV = $FB5B ; VTAB to A
ROM_MACHINEID = $FBB3 ; iigs
;BELL = $FBDD ; ring the bell
;BASCALC = $FBC1 ;
;VTAB = $FC22 ; VTAB to CV
HOME = $FC58 ; Clear the text screen ; qboot
;WAIT = $FCA8 ; delay 1/2(26+27A+5A^2) us
;CROUT1 = $FD8B
;SETINV = $FE80 ; INVERSE
;SETNORM = $FE84 ; NORMAL
COUT = $FDED ; output A to screen ; qboot
COUT1 = $FDF0 ; output A to screen ; qload
COLOR_BLACK = 0
COLOR_RED = 1
COLOR_DARKBLUE = 2
COLOR_PURPLE = 3
COLOR_DARKGREEN = 4
COLOR_GREY = 5
COLOR_MEDIUMBLUE = 6
COLOR_LIGHTBLUE = 7
COLOR_BROWN = 8
COLOR_ORANGE = 9
COLOR_GREY2 = 10
COLOR_PINK = 11
COLOR_LIGHTGREEN = 12
COLOR_YELLOW = 13
COLOR_AQUA = 14
COLOR_WHITE = 15
COLOR_BOTH_BLACK = $00
COLOR_BOTH_RED = $11
COLOR_BOTH_DARKBLUE = $22
COLOR_BOTH_DARKGREEN = $44
COLOR_BOTH_GREY = $55
COLOR_BOTH_MEDIUMBLUE = $66
COLOR_BOTH_LIGHTBLUE = $77
COLOR_BOTH_BROWN = $88
COLOR_BOTH_ORANGE = $99
COLOR_BOTH_PINK = $BB
COLOR_BOTH_LIGHTGREEN = $CC
COLOR_BOTH_YELLOW = $DD
COLOR_BOTH_AQUA = $EE
COLOR_BOTH_WHITE = $FF

View File

@ -0,0 +1,309 @@
;===============================================
; hgr 1x28 draw sprite, with bg mask in GR $400
;===============================================
; used primarily to draw Rather Dashing
;===============================================
;
; SPRITE in INL/INH
; Location at CURSOR_X CURSOR_Y
; for now, BG mask is only all or nothing
; so we just skip drawing if behind
; sprite AT INL/INH
; mask at INL/INH + 28
hgr_draw_sprite_1x28:
lda #0
sta MASK_COUNTDOWN
; calculate peasant priority
; based on head
lda PEASANT_Y
sec
sbc #48 ; Y=48
lsr ; div by 8
lsr
lsr
clc
adc #2
sta PEASANT_PRIORITY
; set up sprite pointers
lda INL
sta h728_smc1+1
lda INH
sta h728_smc1+2
; set up mask pointers
clc
lda INL
adc #28
sta h728_smc3+1
lda INH
adc #0
sta h728_smc3+2
ldx #0 ; X is row counter
hgr_1x28_sprite_yloop:
lda MASK_COUNTDOWN
and #$3 ; only update every 4th
bne mask_good
txa
pha ; save X
; recalculate mask
txa
clc
adc CURSOR_Y
tax
ldy CURSOR_X
jsr update_bg_mask
pla ; restore X
tax
mask_good:
lda MASK
bne draw_sprite_skip
txa ; X is current row
clc
adc CURSOR_Y ; add in cursor_y
; calc GBASL/GBASH
tay ; get output ROW into GBASL/H
lda hposn_low,Y
sta GBASL
lda hposn_high,Y
sta GBASH
ldy CURSOR_X
lda (GBASL),Y ; load background
h728_smc3:
and $d000,X ; mask with sprite mask
h728_smc1:
ora $d000,X ; or in sprite
sta (GBASL),Y ; store out
draw_sprite_skip:
inc MASK_COUNTDOWN
inx
cpx #28
bne hgr_1x28_sprite_yloop
rts
.if 0
;======================
; save bg 1x28
;======================
bsave_bg_1x28:
ldx #0
save_yloop:
txa
pha
clc
adc CURSOR_Y
; calc GBASL/GBASH
tax
lda hposn_low,X
sta GBASL
lda hposn_high,X
sta GBASH
pla
tax
ldy CURSOR_X
lda (GBASL),Y
sta save_sprite_1x28,X
inx
cpx #28
bne save_yloop
rts
.endif
;======================
; restore bg 1x28
;======================
restore_bg_1x28:
; restore bg behind peasant
; is this actually faster than using the generic version?
ldy CURSOR_Y ; y start point
ldx #27 ; height
restore_yloop:
; calc GBASL/GBASH using lookup table
clc
lda hposn_low,Y
adc PEASANT_X
sta restore_page1_smc+1
sta restore_page2_smc+1
; $40 -> $20 0100 0000 -> 0010 0000
; $41 -> $21 0100 0001 -> 0010 0001
; $51 -> $31 0101 0011 -> 0101 0001
lda hposn_high,Y
sta restore_page2_smc+2
eor #$60
sta restore_page1_smc+2
restore_page1_smc:
lda $DDDD
restore_page2_smc:
sta $DDDD
iny
dex
bpl restore_yloop
rts
;===================
; update_bg_mask
;===================
; newx/7 in Y
; newy in X
; updates MASK
update_bg_mask:
; rrrr rtii top 5 bits row, bit 2 top/bottom
sty xsave
mask_try_again:
stx ysave
txa
and #$04 ; see if odd/even
beq bg_mask_even
bg_mask_odd:
lda #$f0
bne bg_mask_mask ; bra
bg_mask_even:
lda #$0f
bg_mask_mask:
sta MASK
txa
lsr
lsr ; need to divide by 8 then * 2
lsr ; can't just div by 4 as we need to mask bottom bit
asl
tax
lda gr_offsets,X
sta BASL
lda gr_offsets+1,X
sta BASH
lda (BASL),Y
ldy MASK
cpy #$f0
bne mask_bottom
mask_top:
lsr
lsr
lsr
lsr
jmp mask_mask_mask
mask_bottom:
and #$0f
mask_mask_mask:
sta MASK
cmp #$0 ; 0 means collision, find mask
bne mask_not_zero ; by iteratively going down till
ldx ysave ; non-zero
ldy xsave
inx
inx
inx
inx
jmp mask_try_again
mask_not_zero:
cmp #$f ; priority F means always on top
beq mask_true
cmp PEASANT_PRIORITY
beq mask_false ; branch less than equal
bcc mask_false ; blt
mask_true:
lda #$ff
sta MASK
rts
mask_false:
lda #$00
sta MASK
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; priorities
; 0 = collision
; 1 = bg = always draw ; Y-48
; 2 0-55
; 3 56-63 ; 8/8+2 = 3
; 4 64-71 ; 16/8+2 = 4
; 5 72-79
; 6 80-87 ; 32/8+2 = 6
; 7 88-95
; 8 96-103
; 9 104-111
; 10 112-119
; 11 120-127
; 12 128-135 ; 8
; 13 136-143
; 14 144-151
; 15 = fg = always hide
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;====================
; save area
;====================
;save_sprite_1x28:
;.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
ysave:
.byte $00
xsave:
.byte $00

40
games/sb/cliff/hgr_copy.s Normal file
View File

@ -0,0 +1,40 @@
;=========================================================
; hgr copy from $2000 to $4000
;=========================================================
; copy $2000 to $4000
; intentionally slow for the miniblind effect
hgr_copy:
lda #0 ; blurgh
sta INL
sta OUTL
lda #$20
sta INH
lda #$40
sta OUTH
ldy #0
hgr_copy_outer:
hgr_copy_inner:
lda #1
jsr wait
lda (INL),Y
sta (OUTL),Y
iny
bne hgr_copy_inner
inc INH
inc OUTH
lda OUTH
cmp #$60
bne hgr_copy_outer
rts

View File

@ -0,0 +1,89 @@
;=======================
; HGR Partial Save
;=======================
; loads from $40
; save to $20
; only save from row in P2 to P2+P4
.if 0
hgr_partial_save:
clc
lda BOX_Y1
sta SAVED_Y1
ldx BOX_Y2
stx SAVED_Y2
partial_save_yloop:
lda hposn_low,X
sta psx_smc1+1
sta psx_smc2+1
lda hposn_high,X
sta psx_smc1+2
sec
sbc #$20
sta psx_smc2+2
ldy #$27
partial_save_xloop:
psx_smc1:
lda $d000,Y
psx_smc2:
sta $d000,Y
dey
bpl partial_save_xloop
dex
cpx BOX_Y1
bcs partial_save_yloop
rts
.endif
;=======================
; HGR Partial Restore
;=======================
; loads from $20
; save to $40
; restores from X = A<=to<=X
; Y = SAVED_Y1 to SAVED_Y2
hgr_partial_restore:
sta partial_restore_x1_smc+1
stx partial_restore_x2_smc+1
ldx SAVED_Y2
partial_restore_yloop:
lda hposn_low,X
sta prx_smc2+1
sta prx_smc1+1
lda hposn_high,X
sta prx_smc2+2
sec
sbc #$20
sta prx_smc1+2
partial_restore_x2_smc:
ldy #$27
partial_restore_xloop:
prx_smc1:
lda $d000,Y
prx_smc2:
sta $d000,Y
dey
partial_restore_x1_smc:
cpy #$00
bpl partial_restore_xloop
dex
cpx SAVED_Y1
bcs partial_restore_yloop ; bge
rts

152
games/sb/cliff/keyboard.s Normal file
View File

@ -0,0 +1,152 @@
;==========================
; check keyboard
; for main game
;==========================
; Movement
; Note in the game, pressing a key starts walking
; To stop you have to press the same direction again
; Text
; We require ENTER/RETURN pressed before entering text
; this is mildly annoying, but lets us use
; WASD to walk. The Apple II+ doesn't have
; up or down buttons
check_keyboard:
lda KEYPRESS
bmi key_was_pressed
rts
key_was_pressed:
inc SEEDL
and #$5f ; strip off high bit and make uppercase
;==========================
; Left
;==========================
check_left:
cmp #$8
beq left_pressed
cmp #'A'
bne check_right
left_pressed: ; if peasant_moving_left, stop
; otherwise clear all movement, move left
ldx PEASANT_XADD
jsr stop_peasant
cpx #$FF ; if not left, start moving left
beq continue_left
lda #$FF ; move left
sta PEASANT_XADD
continue_left:
lda #PEASANT_DIR_LEFT
sta PEASANT_DIR
jmp done_check_keyboard
check_right:
cmp #$15
beq right_pressed
cmp #'D'
bne check_up
right_pressed:
ldx PEASANT_XADD
jsr stop_peasant
cpx #$1 ; if already right, stop
beq continue_right
lda #$1
sta PEASANT_XADD
continue_right:
lda #PEASANT_DIR_RIGHT
sta PEASANT_DIR
jmp done_check_keyboard
check_up:
cmp #'W'
beq up_pressed
cmp #$0B
bne check_down
up_pressed:
ldx PEASANT_YADD
jsr stop_peasant
cpx #$FC ; if already up, stop
beq continue_up
lda #$FC
sta PEASANT_YADD
continue_up:
lda #PEASANT_DIR_UP
sta PEASANT_DIR
jmp done_check_keyboard
check_down:
cmp #'S'
beq down_pressed
cmp #$0A
bne check_enter
down_pressed:
ldx PEASANT_YADD
jsr stop_peasant
cpx #$04 ; if already down, stop
beq continue_down
lda #$4
sta PEASANT_YADD
continue_down:
lda #PEASANT_DIR_DOWN
sta PEASANT_DIR
jmp done_check_keyboard
check_enter:
cmp #13
beq enter_pressed
cmp #' '
bne done_check_keyboard
enter_pressed:
; jsr clear_bottom
; jsr hgr_input
; jsr parse_input
; jsr clear_bottom
done_check_keyboard:
bit KEYRESET
rts
stop_peasant:
lda #0
sta PEASANT_XADD
sta PEASANT_YADD
rts

View File

@ -0,0 +1,253 @@
; Move that Peasant!
move_peasant:
; redraw peasant if moved
lda PEASANT_XADD
ora PEASANT_YADD
bne really_move_peasant
jmp peasant_the_same
really_move_peasant:
; restore bg behind peasant
jsr erase_peasant
;=========================
;=========================
; move peasant
;=========================
;=========================
;==========================
; first move in X direction
clc
lda PEASANT_X
adc PEASANT_XADD ; A = new X
bmi peasant_x_negative ; if newx <0, handle
cmp #40
bcs peasant_x_toobig ; if newx>=40, hanfle (bge)
;======================================
; not off screen, so check if collision
pha
tay
; FIXME: should we add YADD first, like we do in peasant_move_tiny?
ldx PEASANT_Y
jsr peasant_collide
pla
bcc do_move_peasant_y ; no X collide
;==================================
; we collided in X, so stop moving
jsr stop_peasant ; stop moving
; leave PEASANT_X same as was
lda PEASANT_X
jmp do_move_peasant_y
;============================
peasant_x_toobig:
jsr move_map_east
lda #0 ; new X location
jmp done_movex
;============================
peasant_x_negative:
jsr move_map_west
lda #39 ; new X location
jmp done_movex
; check edge of screen
done_movex:
; if we get here we changed screens
sta PEASANT_X ; update new location
jmp peasant_the_same ; skip checking for Y collision
; Move Peasant Y
do_move_peasant_y:
sta PEASANT_X
clc
lda PEASANT_Y
adc PEASANT_YADD ; newy in A
cmp #45 ; if <45 then off screen
bcc peasant_y_negative ; blt
cmp #160 ; if >=150 then off screen
bcs peasant_y_toobig ; bge
; check collide
pha
ldy PEASANT_X
tax ; newy
jsr peasant_collide
pla
bcc done_movey ; no collide
jsr stop_peasant ; stop moving
lda PEASANT_Y ; leave same
jmp done_movey
;============================
peasant_y_toobig:
jsr move_map_south
lda #45 ; new X location
jmp done_movey
;============================
peasant_y_negative:
jsr move_map_north
lda #160 ; new X location
jmp done_movey
; check edge of screen
done_movey:
sta PEASANT_Y
; if we moved off screen, don't re-draw peasant ?
peasant_the_same:
rts
;===========================
; erase peasant
;===========================
; restore bg behind peasant
erase_peasant:
lda PEASANT_Y
sta SAVED_Y1
clc
adc #28
sta SAVED_Y2
ldx PEASANT_X
txa
inx
jmp hgr_partial_restore ; tail call
; when peasants collide
;===================
; peasant_collide
;===================
; newx/7 in Y
; newy in X
; returns C=0 if no collide
; C=1 if collide
peasant_collide:
; rrrr rtii top 5 bits row, bit 2 top/bottom
; add 28 to collide with feet
txa
clc
adc #28
tax
txa
and #$04 ; see if odd/even
beq peasant_collide_even
peasant_collide_odd:
lda #$f0
bne peasant_collide_mask ; bra
peasant_collide_even:
lda #$0f
peasant_collide_mask:
sta MASK
txa
lsr
lsr ; need to divide by 8 then * 2
lsr ; can't just div by 4 as we need to mask bottom bit
asl
tax
lda gr_offsets,X
sta INL
lda gr_offsets+1,X
sta INH
lda (INL),Y ; get value
and MASK
; ldy MASK
; cpy #$f0
; beq in_top
;in_bottom:
; and #$0f
; jmp done_feet
;in_top:
; lsr
; lsr
; lsr
; lsr
;done_feet:
beq collide_true ; true if color 0
;bne collide_false
collide_false:
clc
rts
collide_true:
sec
rts
move_map_east:
move_map_west:
move_map_north:
move_map_south:
rts
.include "gr_offsets.s"

18
games/sb/cliff/wait.s Normal file
View File

@ -0,0 +1,18 @@
; copy of ROM wait
; because we might disable ROM
wait:
sec
wait2:
pha
wait3:
sbc #$01
bne wait3
pla
sbc #$01
bne wait2
rts
wait_end:
.assert (>wait_end - >wait) < 1 , error, "wait crosses page boundary"

348
games/sb/cliff/zp.inc Normal file
View File

@ -0,0 +1,348 @@
JS_BUTTON_STATE = $03
JOYSTICK_ENABLED= $04
SOUND_STATUS = $05
SOUND_DISABLED = $80
SOUND_IN_LC = $01 ; sound in language card
SOUND_MOCKINGBOARD = $02 ; mockingboard detected
SOUND_SSI263 = $04 ; SSI-263 speech chip detected
MOCKINGBOARD_SLOT = $06
DISP_PAGE = $07 ; only in videlectrix intro?
DRAW_PAGE = $08
NIBCOUNT = $09
CURRENT_DRIVE = $0A
DRIVE1_DISK = $0B
DRIVE2_DISK = $0C
DRIVE1_TRACK = $0D
DRIVE2_TRACK = $0E
TEMP0 = $10
TEMP1 = $11
TEMP2 = $12
TEMP3 = $13
TEMP4 = $14
TEMP5 = $15
; zx02 code
offset = $10
offseth = $11
ZX0_src = $12
ZX0_dst = $14
ZX0_srch= $15
bitr = $16
pntr = $17
pntrh = $18
; electric duet
FREQ1 = $10
FREQ2 = $11
DURATION = $12
INSTRUMENT1 = $13
INSTRUMENT2 = $14
MADDRL = $15
MADDRH = $16
LOC4E = $4E
COUNT256 = $4F
HGR_BITS = $1C
CH = $24
CV = $25
GBASL = $26
GBASH = $27
BASL = $28
BASH = $29
MASK = $2E
MASK_COUNTDOWN = $2F
PEASANT_PRIORITY = $30
SEEDL = $4E
SEEDH = $4F
INVENTORY_MASK = $60
INVENTORY_Y = $61
CURSOR_X = $63
CURSOR_Y = $64
FRAME = $65
ALTFIRE = $66
ALTL = $67
ALTH = $68
SAVED_X = $69
PEASANT_XADD = $6A
PEASANT_YADD = $6B
LEVEL_OVER = $6C
NEW_LOCATION = $FF
NEW_FROM_DISK = $01
NEW_FROM_LOAD = $02 ; loaded from load/save menu
KERREK_SPEED = $6D
KERREK_DIRECTION= $6E ; 0 = left, 1=right
KERREK_LEFT = 0
KERREK_RIGHT = 1
SPEECH_PTRL = $70
SPEECH_PTRH = $71
; pt3 player registers
AY_REGISTERS = $70
A_FINE_TONE = $70
A_COARSE_TONE = $71
B_FINE_TONE = $72
B_COARSE_TONE = $73
C_FINE_TONE = $74
C_COARSE_TONE = $75
NOISE = $76
ENABLE = $77
PT3_MIXER_VAL = $77
A_VOLUME = $78
B_VOLUME = $79
C_VOLUME = $7A
ENVELOPE_FINE = $7B
ENVELOPE_COARSE = $7C
ENVELOPE_SHAPE = $7D
PATTERN_L = $7E
PATTERN_H = $7F
; rest of pt3_player
PT3_TEMP = $80
ORNAMENT_L = $81
ORNAMENT_H = $82
SAMPLE_L = $83
SAMPLE_H = $84
LOOP = $85
MB_VALUE = $86
MB_ADDR_L = $87
MB_ADDR_H = $88
DONE_PLAYING = $89
DONE_SONG = $8A
APPLEII_MODEL = $8B
ESC_PRESSED = $8C
PREVIOUS_LOCATION= $8D
;=======================
; savegame state
;=======================
WHICH_LOAD = $90
PEASANT_X = $91
PEASANT_Y = $92
PEASANT_DIR = $93
PEASANT_DIR_UP = 0
PEASANT_DIR_RIGHT = 1
PEASANT_DIR_LEFT = 2
PEASANT_DIR_DOWN = 3
GAME_STATE_3 = $94
; SWORD_THROWN = $01
MAP_LOCATION = $96
GAME_STATE_0 = $97
BABY_IN_WELL=$01
BUCKET_DOWN_WELL=$02
TALKED_TO_MENDELEV=$04
HALDO_TO_DONGOLEV=$08
ARROW_BEATEN=$10
GARY_SCARED=$20
LADY_GONE=$40
TRINKET_GIVEN=$80
GAME_STATE_1 = $98
FISH_FED=$01 ; also implies man gone and inn open
PUDDLE_WET=$02
IN_HAY_BALE=$04
ALREADY_GOT_ROOM=$08
RAINING=$10
NIGHT=$20
POT_ON_HEAD=$40
WEARING_ROBE=$80
GAME_STATE_2 = $99
ON_FIRE = $01
COTTAGE_ROCK_MOVED=$02
KNUCKLES_BLEED=$04
DRESSER_OPEN=$08
TALKED_TO_KNIGHT = $10
COVERED_IN_MUD = $20
GOT_MUDDY_ALREADY = $40
GREASE_ON_HEAD =$80
NED_STATUS = $9A
; 0 = hiding (no increment)
; 1..127 = count up to appearing
; 126,255 = hands on tree
; 127,254 = half out
; 128 = out (no increment)
BUSH_STATUS = $9B ; status of bush search
BUSH_1_SEARCHED = $01
BUSH_2_SEARCHED = $02
BUSH_3_SEARCHED = $04
BUSH_4_SEARCHED = $08
KERREK_STATE = $9C
KERREK_ALIVE = $00
KERREK_DEAD = $01
KERREK_DECOMPOSING = $02
KERREK_SKELETON = $03
KERREK_ROW1 = $40
KERREK_ONSCREEN = $80
ARROW_SCORE = $9D ; bottom=score, top=random num needed 3-5?
ARROW_DONE = $80
SCORE_HUNDREDS = $9E
SCORE_TENSONES = $9F
INVENTORY_1 = $A0
INV1_ARROW = $01
INV1_BABY = $02
INV1_KERREK_BELT = $04
INV1_CHICKEN_FEED = $08
INV1_BOW = $10
INV1_MONSTER_MASK = $20
INV1_PEBBLES = $40
INV1_PILLS = $80
INVENTORY_2 = $A1
INV2_RICHES = $01
INV2_ROBE = $02
INV2_SODA = $04
INV2_MEATBALL_SUB = $08
INV2_TRINKET = $10
INV2_TROGHELM = $20
INV2_TROGSHIELD = $40
INV2_TROGSWORD = $80
INVENTORY_3 = $A2
INV3_IMPOSSIBLE = $01
INV3_SHIRT = $02
INV3_MAP = $04
INVENTORY_1_GONE = $A3 ; had item, but now it's gone
INVENTORY_2_GONE = $A4
INVENTORY_3_GONE = $A5
KERREK_X = $A6 ; should be in save area, as we use
KERREK_Y = $A7 ; for skeleton location
VISITED_0 = $A8 ; for MAP drawing purposes
VISITED_1 = $A9
VISITED_2 = $AA
VISITED_3 = $AB
END_OF_SAVE = $AC
;=============================================
CURRENT_VERB = $B0 ; parser
CURRENT_NOUN = $B1
WORD_MATCH = $B2
INPUT_X = $C0
BOX_X1L = $C1
BOX_X1H = $C2
BOX_Y1 = $C3
BOX_X2L = $C4
BOX_X2H = $C5
BOX_Y2 = $C6
SAVED_Y1 = $C7
SAVED_Y2 = $C8
; temp for animations, etc
BABY_COUNT = $C9
PREV_X = $CA
PREV_Y = $CB
; D0-D? used by HGR?
WHICH_SLOT = $DA
CURRENT_DISK = $DC
HGR_COLOR = $E4
HGR_PAGE = $E6
P0 = $F1
P1 = $F2
P2 = $F3
P3 = $F4
P4 = $F5
P5 = $F6
INL = $FC
INH = $FD
OUTL = $FE
OUTH = $FF
; constants
LOAD_VID_LOGO = 0
LOAD_TITLE = 1
LOAD_INTRO = 2
LOAD_COPY_CHECK = 3
LOAD_PEASANT1 = 4
LOAD_PEASANT2 = 5
LOAD_PEASANT3 = 6
LOAD_PEASANT4 = 7
LOAD_TROGDOR = 8
LOAD_ENDING = 9
LOAD_MUSIC = 10
LOAD_CLIFF = 11
LOAD_GAME_OVER = 12
LOAD_INVENTORY = 13
LOAD_PARSE_INPUT= 14
LOAD_INN = 15
LOAD_INSIDE = 16
LOAD_ARCHERY = 17
LOAD_MAP = 18
LOAD_SAVE1 = 19
LOAD_SAVE2 = 20
LOAD_SAVE3 = 21
VGI_RCOLOR = P0
VGI_RX1 = P1
VGI_RY1 = P2
VGI_RXRUN = P3
VGI_RYRUN = P4
VGI_RCOLOR2 = P5 ; only for dither
COUNT = TEMP5
; LOCATIONS
LOCATION_POOR_GARY = 0
LOCATION_KERREK_1 = 1
LOCATION_OLD_WELL = 2
LOCATION_YELLOW_TREE = 3
LOCATION_WATERFALL = 4
LOCATION_HAY_BALE = 5
LOCATION_MUD_PUDDLE = 6
LOCATION_ARCHERY = 7
LOCATION_RIVER_STONE = 8
LOCATION_MOUNTAIN_PASS = 9
LOCATION_JHONKA_CAVE = 10
LOCATION_YOUR_COTTAGE = 11
LOCATION_LAKE_WEST = 12
LOCATION_LAKE_EAST = 13
LOCATION_OUTSIDE_INN = 14
LOCATION_OUTSIDE_NN = 15
LOCATION_WAVY_TREE = 16
LOCATION_KERREK_2 = 17
LOCATION_OUTSIDE_LADY = 18
LOCATION_BURN_TREES = 19
LOCATION_CLIFF_BASE = 20
LOCATION_CLIFF_HEIGHTS = 21
LOCATION_TROGDOR_OUTER = 22
LOCATION_TROGDOR_LAIR = 23
LOCATION_HIDDEN_GLEN = 24
LOCATION_INSIDE_LADY = 25
LOCATION_INSIDE_NN = 26
LOCATION_INSIDE_INN = 27
LOCATION_ARCHERY_GAME = 28
LOCATION_MAP = 29
LOCATION_EMPTY = 30

View File

@ -1,27 +0,0 @@
include ../../../Makefile.inc
ZX02 = ~/research/6502_compression/zx02.git/build/zx02 -f
PNG_TO_HGR = ../../../utils/hgr-utils/png2hgr
LINKER_SCRIPTS = ../../../linker_scripts
DOS33 = ../../../utils/dos33fs-utils/dos33
EMPTY_DISK = ../../../empty_disk/empty.dsk
TOKENIZE = ../../../utils/asoft_basic-utils/tokenize_asoft
PNG2GR = ../../../utils/gr-utils/png2gr
PNG2SPRITES = ../../../utils/gr-utils/png2sprites
HGR_SPRITE = ../../../utils/hgr-utils/hgr_make_sprite
all: cliff_base.hgr.zx02
####
cliff_base.hgr.zx02: cliff_base.hgr
$(ZX02) cliff_base.hgr cliff_base.hgr.zx02
cliff_base.hgr: cliff_base.png
$(PNG_TO_HGR) cliff_base.png > cliff_base.hgr
####
clean:
rm -f *~ *.o *.lst