peasant: initial work toward loading from hard disk image

This commit is contained in:
Vince Weaver 2024-09-21 01:34:05 -04:00
parent 499c4da0e7
commit bb240f3c88
12 changed files with 1038 additions and 293 deletions

View File

@ -6,12 +6,12 @@ TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft
LINKER_SCRIPTS = ../../linker_scripts
EMPTY_DISK = ../../empty_disk
ZX02 = ~/research/6502_compression/zx02.git/build/zx02
PRODOSDIR = ../../utils/prodos-utils/
PRODOS = ../../utils/prodos-utils/prodos
PRODOS_RAW = ../../utils/prodos-utils/prodos_raw
all: peasant_disk1.dsk peasant_disk2.dsk peasant_disk3.dsk
# peasant.2mg
all: peasant_disk1.dsk peasant_disk2.dsk peasant_disk3.dsk peasant.2mg
submit: peasant_disk1.dsk peasant_disk2.dsk peasant_disk3.dsk
zip peasant.zip peasant_disk1.dsk peasant_disk2.dsk peasant_disk3.dsk
@ -63,8 +63,67 @@ peasant_disk3.dsk: ./trogdor/TROGDOR ./ending/ENDING \
peasant.2mg: dts_block PROBOOTHD QLOAD_HD \
./vid_logo/VID_LOGO ./title/TITLE ./intro/INTRO \
./music/MUSIC ./copy/COPY_CHECK ./inventory/INVENTORY \
SAVE1 SAVE2 SAVE3 PARSE_INPUT.ZX02 ./game_over/GAME_OVER
$(PRODOSDIR)/mkprodosfs peasant.2mg -n PeasantsQ -b 2800 -2
$(PRODOS_RAW) peasant.2mg 0 PROBOOTHD 0 0
$(PRODOS_RAW) peasant.2mg `./dts_block 0 1 0` QLOAD_HD 0 0
$(PRODOS_RAW) peasant.2mg `./dts_block 0 0 11` SAVE1 0 1
$(PRODOS_RAW) peasant.2mg `./dts_block 0 0 12` SAVE2 0 1
$(PRODOS_RAW) peasant.2mg `./dts_block 0 0 13` SAVE3 0 1
$(PRODOS_RAW) peasant.2mg `./dts_block 0 3 0` ./music/MUSIC 0 0
$(PRODOS_RAW) peasant.2mg `./dts_block 0 4 0` ./vid_logo/VID_LOGO 0 0
$(PRODOS_RAW) peasant.2mg `./dts_block 0 6 0` ./title/TITLE 0 0
$(PRODOS_RAW) peasant.2mg `./dts_block 0 9 0` ./intro/INTRO 0 0
$(PRODOS_RAW) peasant.2mg `./dts_block 0 13 0` PARSE_INPUT.ZX02 0 0
$(PRODOS_RAW) peasant.2mg `./dts_block 0 14 0` ./inventory/INVENTORY 0 0
$(PRODOS_RAW) peasant.2mg `./dts_block 0 15 0` ./game_over/GAME_OVER 0 0
$(PRODOS_RAW) peasant.2mg `./dts_block 0 30 0` ./copy/COPY_CHECK 0 0
###
dts_block: dts_block.o
$(CC) $(LFLAGS) -o dts_block dts_block.o
dts_block.o: dts_block.c
$(CC) $(CFLAGS) -c dts_block.c
###
PROBOOTHD: proboothd.o
ld65 -o PROBOOTHD proboothd.o -C $(LINKER_SCRIPTS)/apple2_800.inc
proboothd.o: proboothd.s
ca65 -o proboothd.o proboothd.s -l proboothd.lst
###
QLOAD_HD: qload_hd.o
ld65 -o QLOAD_HD qload_hd.o -C $(LINKER_SCRIPTS)/apple2_b00.inc
qload_hd.o: qload_hd.s qboot.inc \
zx02_optim.s \
hgr_font.s \
draw_box.s \
hgr_rectangle.s \
hgr_1x28_sprite_mask.s \
hgr_partial_save.s \
hgr_input.s \
hgr_tables.s \
hgr_text_box.s \
text/word_list.s \
clear_bottom.s \
hgr_hgr2.s \
hgr_copy.s \
gr_offsets.s \
qkumba_popwr.s \
random16.s
ca65 -o qload_hd.o qload.s -DFLOPPY=0 -l qload_hd.lst
####
QBOOT: qboot_sector.o
ld65 -o QBOOT qboot_sector.o -C $(LINKER_SCRIPTS)/apple2_800.inc
@ -93,9 +152,8 @@ qload.o: qload.s qboot.inc \
hgr_copy.s \
gr_offsets.s \
qkumba_popwr.s \
random16.s \
drive2.s
ca65 -o qload.o qload.s -l qload.lst
random16.s
ca65 -o qload.o qload.s -DFLOPPY=1 -l qload.lst
###
@ -145,10 +203,8 @@ qboot.inc: generate_common QBOOT
qload.inc: generate_common QLOAD
./generate_common -a 0xb00 -s load_file qload.lst > qload.inc
./generate_common -a 0xb00 -s sector_write qload.lst >> qload.inc
./generate_common -a 0xb00 -s check_floppy_in_drive2 qload.lst >> qload.inc
# ./generate_common -a 0xb00 -s check_floppy_in_drive2 qload.lst >> qload.inc
./generate_common -a 0xb00 -s requested_sector qload.lst >> qload.inc
# ./generate_common -a 0xb00 -s decompress_lzsa2_fast qload.lst >> qload.inc
# ./generate_common -a 0xb00 -s getsrc_smc qload.lst >> qload.inc
./generate_common -a 0xb00 -s zx02_full_decomp qload.lst >> qload.inc
./generate_common -a 0xb00 -s zx_src_l qload.lst >> qload.inc
./generate_common -a 0xb00 -s zx_src_h qload.lst >> qload.inc

18
games/peasant/dts_block.c Normal file
View File

@ -0,0 +1,18 @@
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int disk,track,sector;
int block;
disk=atoi(argv[1]);
track=atoi(argv[2]);
sector=atoi(argv[3]);
block=((disk+1)<<9)|(track<<3)|(sector>>1);
printf("%d",block);
return 0;
}

View File

@ -6,8 +6,14 @@ KEYRESET = $C010
; SOFT SWITCHES
CLR80COL = $C000 ; PAGE1/PAGE1 normal
SET80COL = $C001 ; PAGE1/PAGE2 switches PAGE1 in Aux instead
READMAINMEM = $C002 ; (w) to read from main mem ($0200..$BFFF)
READAUXMEM = $C003 ; (w) to read from aux mem ($0200..$BFFF)
WRITEMAINMEM = $C004 ; (w) to write to main mem ($0200..$BFFF)
WRITEAUXMEM = $C005 ; (w)to write to aux mem ($0200..$BFFF)
SETSTDZP = $C008 ; (w) to use main mem stack/zp ($00FF-$01FF)
EIGHTYCOLOFF = $C00C
EIGHTYCOLON = $C00D
PRIMARYCHARSET = $C00E ; (w) to disable mousetext
TBCOLOR = $C022 ; IIgs text foreground / background colors
NEWVIDEO = $C029 ; IIgs graphics modes
SPEAKER = $C030
@ -51,6 +57,7 @@ HPLOT0 = $F457 ; plot at (Y,X), (A)
;CLRTOP = $F836 ; clear only top of low-res screen
;SETCOL = $F864 ; COLOR=A
;ROM_TEXT2COPY = $F962 ; iigs
INIT_TEXT = $FB2F ; set lo-res/page1 and call text
TEXT = $FB36 ; qboot
;TABV = $FB5B ; VTAB to A
ROM_MACHINEID = $FBB3 ; iigs
@ -60,12 +67,12 @@ ROM_MACHINEID = $FBB3 ; iigs
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
SETINV = $FE80 ; INVERSE
SETNORM = $FE84 ; NORMAL
COUT = $FDED ; output A to screen ; qboot
COUT1 = $FDF0 ; output A to screen ; qload
SETKBD = $FE89 ; set input to keyboard
SETVID = $FE93 ; set output to video screen

142
games/peasant/proboothd.s Normal file
View File

@ -0,0 +1,142 @@
;license:BSD-3-Clause
; vaguely based on the minimal open/read binary file in ProDOS filesystem
; from 4cade
;
;copyright (c) Peter Ferrie 2016-2019
.include "hardware.inc"
.include "zp.inc"
; we want to load 10 blocks from 1024 to $0b00
QLOAD_BLOCK = ((0+1)*512)+(1*8)+(0) ; D0 T1 S0
QLOAD_ADDR = $0b00
QLOAD_SIZE = 10
; start of boot sector, presumably how many sectors to load
; 512 bytes on prodos/hard-disk(???)
.byte 1
proboot_start:
txa
pha ; save slot for later
; init. is all this necessary?
; originally "4cade.init.machine.a"
cld ; clear direction flag
sta $C082 ; read rom / no write (language card)
sta PRIMARYCHARSET ; turn off mouse text
sta EIGHTYCOLOFF ; disable 80-col mode
h sta CLR80COL
sta READMAINMEM ; make sure not using aux mem
sta WRITEMAINMEM
sta SETSTDZP
; more init
; originally "4cade.init.screen.a"
; initializes and clears screen using ROM routines
jsr INIT_TEXT ; setup text mode
jsr HOME ; clear screen
jsr SETNORM ; normal text
jsr SETKBD ; keyboard input
jsr SETVID ; video output
; set up disk stuff?
pla ; restore slot
sta UNIT ; save for later (also has meaning)
tax
; 4cade calls a print-title routine here that exits with Y=0
ldy #0
; from IIgs smartport firmware manual
; prodos entry point is $CX00+($CXFF)
; so if slot 7, $C700 + value in $C7ff (say, A) so $C70A
; smartport entry point is $CX00+(CXFF)+3
setup_loop:
txa
lsr
lsr
lsr
lsr
and #7
ora #$c0
sta slot_smc+2
sta entry_smc+2 ; set up smartport/prodos entry point
slot_smc:
lda $cfff
sta entry_smc+1 ; set up rest of smartport/prodos entry
;opendir:
ldy #>QLOAD_BLOCK ; high
ldx #<QLOAD_BLOCK ; low
lda #>QLOAD_ADDR ; high
sta ADRHI
lda #0
sta ADRLO
lda #QLOAD_SIZE
jsr seekread
done:
jmp QLOAD_ADDR
;================================
; seek + read blocks
;================================
; this calls the smartport PRODOS entrypoint
; command=1 READBLOCK
; I can't find this documented anywhere
; but the paramaters are stored in the zero page
;================================
; Y:X = block number to load (???)
; A = num blocks
seekread:
sta COUNT
stx BLOKLO
sty BLOKHI
seekread_loop:
lda #1 ; READBLOCK
sta COMMAND
lda ADRHI
pha
entry_smc:
jsr $d1d1
pla
sta ADRHI
inc ADRHI ; twice, as 512 byte chunks
inc ADRHI
inc BLOKLO ; increment block pointer
bne no_blokloflo
inc BLOKHI
no_blokloflo:
dec COUNT
bne seekread_loop
rts

View File

@ -1,40 +1,39 @@
load_file =$0b2a
sector_write =$0c85
check_floppy_in_drive2 =$0de6
load_file =$0b16
sector_write =$0c61
requested_sector =$0d17
zx02_full_decomp =$0e35
zx_src_l =$0e37
zx_src_h =$0e3b
hgr2 =$17bc
hgr_make_tables =$1530
hgr_put_string =$0ec3
restore_bg_1x28 =$13fb
hgr_draw_sprite_1x28 =$1394
input_buffer =$1508
hgr_text_box =$15a6
hgr_text_box_nosave =$163d
hgr_partial_restore =$147e
clear_bottom =$1791
hgr_input =$14ae
draw_box =$1245
disp_put_string =$15e1
disp_one_line =$15f5
invert_smc1 =$0f3b
disp_put_string_cursor =$15f1
hgr_put_char_cursor =$0eef
vgi_simple_rectangle =$12c6
peasant_text =$1ef0
save_menu =$186f
load_menu =$1864
location_names_l =$1b9c
location_names_h =$1bbb
wait_until_keypress =$1ddb
random16 =$1de4
score_points =$1e69
print_score =$1e19
update_score =$1e24
speaker_beep =$1ed7
speaker_duration =$1eee
speaker_frequency =$1eef
zx02_full_decomp =$0de6
zx_src_l =$0de8
zx_src_h =$0dec
hgr2 =$176d
hgr_make_tables =$14e1
hgr_put_string =$0e74
restore_bg_1x28 =$13ac
hgr_draw_sprite_1x28 =$1345
input_buffer =$14b9
hgr_text_box =$1557
hgr_text_box_nosave =$15ee
hgr_partial_restore =$142f
clear_bottom =$1742
hgr_input =$145f
draw_box =$11f6
disp_put_string =$1592
disp_one_line =$15a6
invert_smc1 =$0eec
disp_put_string_cursor =$15a2
hgr_put_char_cursor =$0ea0
vgi_simple_rectangle =$1277
peasant_text =$1ea1
save_menu =$1820
load_menu =$1815
location_names_l =$1b4d
location_names_h =$1b6c
wait_until_keypress =$1d8c
random16 =$1d95
score_points =$1e1a
print_score =$1dca
update_score =$1dd5
speaker_beep =$1e88
speaker_duration =$1e9f
speaker_frequency =$1ea0
hposn_high = $BA00
hposn_low = $BB00

View File

@ -1,251 +1,30 @@
; Loader for Peasant's Quest
; Based on QLOAD by qkumba which loads raw tracks off of disks
; This particular version only supports using a single disk drive
; (I have other versions that can look for disks across two drives)
; it also loads the QLOAD paramaters from disk separately
.include "zp.inc"
;LOAD_TEXT_TITLE = 16 ; ???
LOAD_FIRST_SECTOR = 22 ; ???
tmpsec = $3C
;WHICH_LOAD=$80
;WHICH_SLOT=$DA
;CURRENT_DISK=$DC
;OUTL = $FE
;OUTH = $FF
.include "hardware.inc"
;.include "common_defines.inc"
.include "qboot.inc"
qload_start:
; 0..$10?
; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10
; AA AA AA AA AA 07 05 40 20 01 01 01 00 0A 00 AA AA
; 00 C6 00 00 ff 07 05 40 20 00 01 01 00 0a 00 00 AA
; $300
; 80+OK, 40 bad, 60 bad, 70 good, 68=bad
; 0 1 2 3 4 5 6 7 8 9 A B C D
; $360 = DC E0 00 E4 E8 EC F0 F4 00 00 00 00 = bad
; $360 = dc e0 00 e4 e8 ec f0 f4 f8 fc 00 00 00 01 00 00 02 03 = good
; boot = ff ff 00 00 ff ff 00 00 ff ff 00 00 00 01 00 00 02 03
; preshift table is $300 - $369
; $36C to $3D5 is used as decode table by disk II drive
.if 0
ldy WHICH_SLOT ; temporarily save
lda #$AA
ldx #$2
zp_clear_loop:
sta $00,X
inx
bne zp_clear_loop
sty WHICH_SLOT
.if FLOPPY=1
.include "qload_floppy.s"
.else
.include "qload_hd.s"
.endif
; init the write code
lda WHICH_SLOT
jsr popwr_init
; first time entry
; start by loading text title
lda #LOAD_VID_LOGO ; load intro
sta WHICH_LOAD
lda #1
sta CURRENT_DISK ; current disk number
sta DRIVE1_DISK ; it's in drive1
sta CURRENT_DRIVE ; and currently using drive 1
lda #$FF
sta DRIVE1_TRACK
sta DRIVE2_TRACK
jsr load_file ; actually load intro
jsr $6000 ; run intro
lda #LOAD_TITLE ; next load title
sta WHICH_LOAD
main_game_loop:
jsr load_file
jsr $6000 ; all entry points currently $6000
jmp main_game_loop
;====================================
; loads file specified by WHICH_LOAD
;====================================
load_file:
ldx WHICH_LOAD
lda which_disk_array,X ; get disk# for file to load
cmp CURRENT_DISK ; if not currently using
bne change_disk ; need to change disk
load_file_no_diskcheck:
lda load_address_array,X
sta load_address
lda track_array,X
sta load_track
lda sector_array,X
sta load_sector
lda length_array,X
sta load_length
jsr load_new
rts
;===================================================
;===================================================
; change disk
;===================================================
;===================================================
; WHICH_LOAD is still in X?
change_disk:
; see if disk we want is in drive1
check_drive1:
lda which_disk_array,X
cmp DRIVE1_DISK
bne check_drive2
jsr switch_drive1 ; switch to drive1
jmp update_disk
check_drive2:
cmp DRIVE2_DISK
bne disk_not_found
jsr switch_drive2 ; switch to drive2
jmp update_disk
disk_not_found:
; check if disk in drive2
; carry clear if not
; jsr check_floppy_in_drive2
; bcc nothing_in_drive2
; a disk is in drive2, try to use it
; bcs verify_disk
nothing_in_drive2:
; switch back to drive1
; jsr switch_drive1
;==============================
; print "insert disk" message
lda #<insert_disk_string
sta OUTL
lda #>insert_disk_string
sta OUTH
ldx WHICH_LOAD
lda which_disk_array,X
clc
adc #48
; patch error string to say correct disk to insert
ldy #27
sta (OUTL),Y
jsr hgr_text_box
fnf_keypress:
lda KEYPRESS
bpl fnf_keypress
bit KEYRESET
;==============================================
; actually verify proper disk is there
; read T0:S0 and verify proper disk
verify_disk:
lda WHICH_LOAD
pha
ldx #LOAD_FIRST_SECTOR ; load track 0 sector 0
stx WHICH_LOAD
jsr load_file_no_diskcheck
pla
sta WHICH_LOAD
tax
; first sector now in $BC00
; offset 5B
; disk1 = $12
; disk2 = $32 ('2')
; disk3 = $33 ('3')
lda $BC5B
cmp #$12
beq is_disk1
cmp #$32
beq is_disk2
cmp #$33
beq is_disk3
bne change_disk ; unknown disk
is_disk1:
lda #1
bne disk_compare ; bra
is_disk2:
lda #2
bne disk_compare ; bra
is_disk3:
lda #3
disk_compare:
cmp which_disk_array,X
bne change_disk ; disk mismatch
;==============================================
; all good, retry original load
update_disk:
ldx WHICH_LOAD
lda which_disk_array,X
sta CURRENT_DISK
ldx CURRENT_DRIVE
sta DRIVE1_DISK-1,X ; indexed from 1
jmp load_file
; offset for disk number is 27
insert_disk_string:
.byte 0,43,24, 0,240,74
.byte 10,41
.byte "PLEASE INSERT DISK 1",13
.byte " THEN PRESS RETURN",0
.align $100
which_disk_array:
.byte 1,1,1,1 ; VID_LOGO, TITLE, INTRO. COPY_CHECK
@ -292,13 +71,10 @@ length_array:
.byte 1,1,1 ; SAVE1, SAVE2, SAVE3
.byte 1 ; disk detect
.include "qkumba_popwr.s"
.include "drive2.s"
.include "zx02_optim.s"
;.include "decompress_fast_v2.s"
.include "hgr_font.s"
.include "draw_box.s"
.include "hgr_rectangle.s"
@ -323,3 +99,7 @@ qload_end:
;.assert (>qload_end - >qload_start) < $e , error, "loader too big"
.assert (>qload_end - >qload_start) < $15 , error, "loader too big"

View File

@ -0,0 +1,198 @@
qload_floppy:
; init the write code
lda WHICH_SLOT
jsr popwr_init
; first time entry
; start by loading text title
lda #LOAD_VID_LOGO ; load intro
sta WHICH_LOAD
lda #1
sta CURRENT_DISK ; current disk number
main_game_loop:
jsr load_file ; actually load intro
entry_smc:
jsr $6000 ; run intro
; lda #LOAD_TITLE ; next load title
; sta WHICH_LOAD
; jsr load_file
; jsr $6000 ; all entry points currently $6000
jmp main_game_loop
;====================================
; loads file specified by WHICH_LOAD
;====================================
load_file:
ldx WHICH_LOAD
lda which_disk_array,X ; get disk# for file to load
cmp CURRENT_DISK ; if not currently using
bne change_disk ; need to change disk
load_file_no_diskcheck:
lda load_address_array,X
sta load_address
lda track_array,X
sta load_track
lda sector_array,X
sta load_sector
lda length_array,X
sta load_length
jsr load_new
rts
;===================================================
;===================================================
; change disk
;===================================================
;===================================================
; WHICH_LOAD is still in X?
change_disk:
; see if disk we want is in drive1
check_drive1:
lda which_disk_array,X
cmp DRIVE1_DISK
bne disk_not_found
; jsr switch_drive1 ; switch to drive1
; jmp update_disk
;check_drive2:
; cmp DRIVE2_DISK
; bne disk_not_found
; jsr switch_drive2 ; switch to drive2
; jmp update_disk
disk_not_found:
; check if disk in drive2
; carry clear if not
; jsr check_floppy_in_drive2
; bcc nothing_in_drive2
; a disk is in drive2, try to use it
; bcs verify_disk
nothing_in_drive2:
; switch back to drive1
; jsr switch_drive1
;==============================
; print "insert disk" message
lda #<insert_disk_string
sta OUTL
lda #>insert_disk_string
sta OUTH
ldx WHICH_LOAD
lda which_disk_array,X
clc
adc #48
; patch error string to say correct disk to insert
ldy #27
sta (OUTL),Y
jsr hgr_text_box
fnf_keypress:
lda KEYPRESS
bpl fnf_keypress
bit KEYRESET
;==============================================
; actually verify proper disk is there
; read T0:S0 and verify proper disk
verify_disk:
lda WHICH_LOAD
pha
LOAD_FIRST_SECTOR = 22
ldx #LOAD_FIRST_SECTOR ; load track 0 sector 0
stx WHICH_LOAD
jsr load_file_no_diskcheck
pla
sta WHICH_LOAD
tax
; first sector now in $BC00
; offset 5B
; disk1 = $12
; disk2 = $32 ('2')
; disk3 = $33 ('3')
lda $BC5B
cmp #$12
beq is_disk1
cmp #$32
beq is_disk2
cmp #$33
beq is_disk3
bne change_disk ; unknown disk
is_disk1:
lda #1
bne disk_compare ; bra
is_disk2:
lda #2
bne disk_compare ; bra
is_disk3:
lda #3
disk_compare:
cmp which_disk_array,X
bne change_disk ; disk mismatch
;==============================================
; all good, retry original load
update_disk:
ldx WHICH_LOAD
lda which_disk_array,X
sta CURRENT_DISK
ldx CURRENT_DRIVE
sta DRIVE1_DISK-1,X ; indexed from 1
jmp load_file
; offset for disk number is 27
insert_disk_string:
.byte 0,43,24, 0,240,74
.byte 10,41
.byte "PLEASE INSERT DISK 1",13
.byte " THEN PRESS RETURN",0

203
games/peasant/qload_hd.s Normal file
View File

@ -0,0 +1,203 @@
qload_hd:
; set up prodos entry
lda UNIT ;
ldy #0
setup_loop:
lsr
lsr
lsr
lsr
and #7
ora #$c0
sta slot_smc+2
sta entry_smc+2 ; set up smartport/prodos entry point
slot_smc:
lda $cfff
sta entry_smc+1 ; set up rest of smartport/prodos entry
; init the write code if needed
; ???
lda #0
sta CURRENT_DISK
lda #LOAD_VID_LOGO
sta WHICH_LOAD
main_game_loop:
jsr load_file
entry_point_smc:
jsr $6000 ; most entry points currently $6000
; CHECK LEVEL_OVER
; if high bit set, jump to change_disk
; lda LEVEL_OVER
; bmi change_disk
jmp main_game_loop
;====================================
; loads file specified by WHICH_LOAD
;====================================
load_file:
ldx WHICH_LOAD
lda load_address_array,X
sta ADRHI
sta entry_point_smc+2
lda CURRENT_DISK
sta BLOKHI
inc BLOKHI ; off by one
lda track_array,X ; track
asl
asl
asl
rol BLOKHI
sta BLOKLO
lda sector_array,X ; sector
lsr
clc
adc BLOKLO
sta BLOKLO
lda length_array,X
clc
adc #1
lsr ; important! blocks=sectors/2
; need to round up if it was odd
; careful: this could over-write if not careful
sta COUNT
jsr seekread
rts ; todo: tail call
;===================================================
;===================================================
; change disk
;===================================================
;===================================================
; LEVEL_OVER bottom 4 bits hold which exit
change_disk:
; lda LEVEL_OVER
; and #$f
; sta LEVEL_OVER
; tax
; set up locations
; lda DISK_EXIT_DISK,X
; sta CURRENT_DISK
; lda DISK_EXIT_LOAD,X
; sta WHICH_LOAD
; lda DISK_EXIT_LEVEL,X
; sta LOCATION
; lda DISK_EXIT_DIRECTION,X
; sta DIRECTION
; lda DISK_EXIT_DNI_H,X
; sta NUMBER_HIGH
; lda DISK_EXIT_DNI_L,X
; sta NUMBER_LOW
; see if disk we want is in drive
;==========================
; load QLOAD table
; check if disk matches
;verify_disk:
; jsr load_qload_offsets
;==============================================
; all good, continue
update_disk:
jmp main_game_loop
.if 0
load_qload_offsets:
lda #$12
sta ADRHI
lda CURRENT_DISK
sta BLOKHI
inc BLOKHI ; off by one
lda #0 ; track
asl
asl
asl
rol BLOKHI
sta BLOKLO
lda #$2 ; sector
lsr
clc
adc BLOKLO
sta BLOKLO
; lda #$0
; sta load_track
; lda #$02 ; track 0 sector 2
; sta load_sector
lda #$1
sta COUNT
jmp seekread
.endif
;================================
; seek + read blocks
;================================
; this calls the smartport PRODOS entrypoint
; command=1 READBLOCK
; I can't find this documented anywhere
; but the paramaters are stored in the zero page
;================================
; BLOKHI:BLOKLO = block number to load (???)
; COUNT = num blocks
seekread:
seekread_loop:
lda #1 ; READBLOCK
sta COMMAND
lda ADRHI
pha
entry_smc:
jsr $d1d1
pla
sta ADRHI
inc ADRHI ; twice, as 512 byte chunks
inc ADRHI
inc BLOKLO ; increment block pointer
bne no_blokloflo
inc BLOKHI
no_blokloflo:
dec COUNT
bne seekread_loop
rts

View File

@ -0,0 +1,325 @@
; Loader for Peasant's Quest
.include "zp.inc"
;LOAD_TEXT_TITLE = 16 ; ???
LOAD_FIRST_SECTOR = 22 ; ???
tmpsec = $3C
;WHICH_LOAD=$80
;WHICH_SLOT=$DA
;CURRENT_DISK=$DC
;OUTL = $FE
;OUTH = $FF
.include "hardware.inc"
;.include "common_defines.inc"
.include "qboot.inc"
qload_start:
; 0..$10?
; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10
; AA AA AA AA AA 07 05 40 20 01 01 01 00 0A 00 AA AA
; 00 C6 00 00 ff 07 05 40 20 00 01 01 00 0a 00 00 AA
; $300
; 80+OK, 40 bad, 60 bad, 70 good, 68=bad
; 0 1 2 3 4 5 6 7 8 9 A B C D
; $360 = DC E0 00 E4 E8 EC F0 F4 00 00 00 00 = bad
; $360 = dc e0 00 e4 e8 ec f0 f4 f8 fc 00 00 00 01 00 00 02 03 = good
; boot = ff ff 00 00 ff ff 00 00 ff ff 00 00 00 01 00 00 02 03
; preshift table is $300 - $369
; $36C to $3D5 is used as decode table by disk II drive
.if 0
ldy WHICH_SLOT ; temporarily save
lda #$AA
ldx #$2
zp_clear_loop:
sta $00,X
inx
bne zp_clear_loop
sty WHICH_SLOT
.endif
; init the write code
lda WHICH_SLOT
jsr popwr_init
; first time entry
; start by loading text title
lda #LOAD_VID_LOGO ; load intro
sta WHICH_LOAD
lda #1
sta CURRENT_DISK ; current disk number
sta DRIVE1_DISK ; it's in drive1
sta CURRENT_DRIVE ; and currently using drive 1
lda #$FF
sta DRIVE1_TRACK
sta DRIVE2_TRACK
jsr load_file ; actually load intro
jsr $6000 ; run intro
lda #LOAD_TITLE ; next load title
sta WHICH_LOAD
main_game_loop:
jsr load_file
jsr $6000 ; all entry points currently $6000
jmp main_game_loop
;====================================
; loads file specified by WHICH_LOAD
;====================================
load_file:
ldx WHICH_LOAD
lda which_disk_array,X ; get disk# for file to load
cmp CURRENT_DISK ; if not currently using
bne change_disk ; need to change disk
load_file_no_diskcheck:
lda load_address_array,X
sta load_address
lda track_array,X
sta load_track
lda sector_array,X
sta load_sector
lda length_array,X
sta load_length
jsr load_new
rts
;===================================================
;===================================================
; change disk
;===================================================
;===================================================
; WHICH_LOAD is still in X?
change_disk:
; see if disk we want is in drive1
check_drive1:
lda which_disk_array,X
cmp DRIVE1_DISK
bne check_drive2
jsr switch_drive1 ; switch to drive1
jmp update_disk
check_drive2:
cmp DRIVE2_DISK
bne disk_not_found
jsr switch_drive2 ; switch to drive2
jmp update_disk
disk_not_found:
; check if disk in drive2
; carry clear if not
; jsr check_floppy_in_drive2
; bcc nothing_in_drive2
; a disk is in drive2, try to use it
; bcs verify_disk
nothing_in_drive2:
; switch back to drive1
; jsr switch_drive1
;==============================
; print "insert disk" message
lda #<insert_disk_string
sta OUTL
lda #>insert_disk_string
sta OUTH
ldx WHICH_LOAD
lda which_disk_array,X
clc
adc #48
; patch error string to say correct disk to insert
ldy #27
sta (OUTL),Y
jsr hgr_text_box
fnf_keypress:
lda KEYPRESS
bpl fnf_keypress
bit KEYRESET
;==============================================
; actually verify proper disk is there
; read T0:S0 and verify proper disk
verify_disk:
lda WHICH_LOAD
pha
ldx #LOAD_FIRST_SECTOR ; load track 0 sector 0
stx WHICH_LOAD
jsr load_file_no_diskcheck
pla
sta WHICH_LOAD
tax
; first sector now in $BC00
; offset 5B
; disk1 = $12
; disk2 = $32 ('2')
; disk3 = $33 ('3')
lda $BC5B
cmp #$12
beq is_disk1
cmp #$32
beq is_disk2
cmp #$33
beq is_disk3
bne change_disk ; unknown disk
is_disk1:
lda #1
bne disk_compare ; bra
is_disk2:
lda #2
bne disk_compare ; bra
is_disk3:
lda #3
disk_compare:
cmp which_disk_array,X
bne change_disk ; disk mismatch
;==============================================
; all good, retry original load
update_disk:
ldx WHICH_LOAD
lda which_disk_array,X
sta CURRENT_DISK
ldx CURRENT_DRIVE
sta DRIVE1_DISK-1,X ; indexed from 1
jmp load_file
; offset for disk number is 27
insert_disk_string:
.byte 0,43,24, 0,240,74
.byte 10,41
.byte "PLEASE INSERT DISK 1",13
.byte " THEN PRESS RETURN",0
which_disk_array:
.byte 1,1,1,1 ; VID_LOGO, TITLE, INTRO. COPY_CHECK
.byte 2,2,2,2 ; PEASANT1, PEASANT2, PEASANT3, PEASANT4
.byte 3,3,1,3 ; TROGDOR, ENDING, MUSIC, CLIFF
.byte 1,1,1,3 ; GAME_OVER, INVENTORY, PARSE_INPUT, INN
.byte 3,3,3 ; INSIDE, ARCHERY, MAP
.byte 1,1,1 ; SAVE1, SAVE2, SAVE3
.byte $f ; disk detect
load_address_array:
.byte $60,$60,$60,$60 ; VID_LOGO, TITLE, INTRO, COPY_CHECK
.byte $60,$60,$60,$60 ; PEASANT1, PEASANT2, PEASANT3, PEASANT4
.byte $60,$60,$D0,$60 ; TROGDOR, ENDING, MUSIC, CLIFF
.byte $60,$D0,$20,$60 ; GAME_OVER, INVENTORY, PARSE_INPUT, INN
.byte $60,$60,$60 ; INSIDE, ARCHERY, MAP
.byte $BC,$BC,$BC ; SAVE1, SAVE2, SAVE3
.byte $BC ; disk detect
track_array:
.byte 4, 6, 9,1 ; VID_LOGO, TITLE, INTRO, COPY_CHECK
.byte 15,20,25,30 ; PEASANT1, PEASANT2, PEASANT3, PEASANT4
.byte 19,24, 3,29 ; TROGDOR, ENDING, MUSIC, CLIFF
.byte 15,14,13,14 ; GAME_OVER, INVENTORY, PARSE_INPUT, INN
.byte 9,6,4 ; INSIDE, ARCHERY, MAP
.byte 0, 0, 0 ; SAVE1, SAVE2, SAVE3
.byte 0 ; disk detect
sector_array:
.byte 0, 0, 0, 0 ; VID_LOGO, TITLE, INTRO, COPY_CHECK
.byte 0, 0, 0, 0 ; PEASANT1, PEASANT2, PEASANT3, PEASANT4
.byte 0, 0, 0, 0 ; TROGDOR, ENDING, MUSIC, CLIFF
.byte 0, 0, 0, 0 ; GAME_OVER, INVENTORY, PARSE_INPUT, INN
.byte 0, 0, 0 ; INSIDE, ARCHERY, MAP
.byte 11,12,13 ; SAVE1, SAVE2, SAVE3
.byte 0 ; disk detect
length_array:
.byte 32, 50, 60, 20 ; VID_LOGO, TITLE, INTRO, COPY_CHECK
.byte 80, 88, 88, 80 ; PEASANT1, PEASANT2, PEASANT3, PEASANT4
.byte 80, 80, 16, 80 ; TROGDOR, ENDING, MUSIC, CLIFF
.byte 16, 16, 16, 80 ; GAME_OVER, INVENTORY, PARSE_INPUT, INN
.byte 80, 64, 16 ; INSIDE, ARCHERY, MAP
.byte 1,1,1 ; SAVE1, SAVE2, SAVE3
.byte 1 ; disk detect
.include "qkumba_popwr.s"
.include "drive2.s"
.include "zx02_optim.s"
;.include "decompress_fast_v2.s"
.include "hgr_font.s"
.include "draw_box.s"
.include "hgr_rectangle.s"
.include "hgr_1x28_sprite_mask.s"
.include "hgr_partial_save.s"
.include "hgr_input.s"
.include "hgr_tables.s"
.include "hgr_text_box.s"
.include "clear_bottom.s"
.include "hgr_hgr2.s" ; this one is maybe only needed once?
.include "gr_offsets.s"
.include "loadsave_menu.s"
.include "wait_keypress.s"
.include "random16.s"
.include "score.s"
.include "speaker_beeps.s"
peasant_text:
.byte 25,2,"Peasant's Quest",0
qload_end:
;.assert (>qload_end - >qload_start) < $e , error, "loader too big"
.assert (>qload_end - >qload_start) < $15 , error, "loader too big"

View File

@ -216,7 +216,7 @@ ssi_not_found:
mockingboard_notfound:
.if 0
;==================================
; check if disk in drive #2
;==================================
@ -245,7 +245,7 @@ yes_floppy_drive2:
no_floppy_drive2:
done_drive2_check:
.endif
skip_all_checks:
@ -372,6 +372,9 @@ done_loop:
bit KEYRESET
lda #LOAD_TITLE ; next load title
sta WHICH_LOAD
rts
;forever:

View File

@ -44,8 +44,6 @@ INSTRUMENT1 = $13
INSTRUMENT2 = $14
MADDRL = $15
MADDRH = $16
LOC4E = $4E
COUNT256 = $4F
HGR_BITS = $1C
@ -60,9 +58,25 @@ MASK = $2E
MASK_COUNTDOWN = $2F
PEASANT_PRIORITY = $30
; this is the structure for a ProDOS smartport command, at least
; for a read (command=1)
tmpsec = $3c
COMMAND = $42 ; ProDOS constant
UNIT = $43 ; ProDOS constant
ADRLO = $44 ; ProDOS constant
ADRHI = $45 ; ProDOS constant
BLOKLO = $46 ; ProDOS constant
BLOKHI = $47 ; ProDOS constant
SEEDL = $4E
SEEDH = $4F
LOC4E = $4E ; electric duet
COUNT256 = $4F
INVENTORY_MASK = $60
INVENTORY_Y = $61