From cdaeb336f2ee29c2ca457ccb1ca30e79efa3b09c Mon Sep 17 00:00:00 2001 From: 4am Date: Tue, 16 Nov 2021 13:34:57 -0500 Subject: [PATCH] add lookup table to make okvs_nth O(1) --- bin/buildsearch.sh | 20 +++++++++---- res/_FileInformation.txt | 31 ++----------------- src/constants.a | 2 +- src/index/artwork.idx.a | 2 +- src/index/attract.idx.a | 2 +- src/index/cache00.idx.a | 2 +- src/index/cache01.idx.a | 2 +- src/index/cache10.idx.a | 2 +- src/index/cache11.idx.a | 2 +- src/index/dfx.idx.a | 2 +- src/index/dhgr.idx.a | 2 +- src/index/dtitle.idx.a | 2 +- src/index/fx.idx.a | 2 +- src/index/gamehelp.idx.a | 2 +- src/index/gr.idx.a | 2 +- src/index/hgr0.idx.a | 2 +- src/index/hgr1.idx.a | 2 +- src/index/hgr2.idx.a | 2 +- src/index/hgr3.idx.a | 2 +- src/index/hgr4.idx.a | 2 +- src/index/hgr5.idx.a | 2 +- src/index/hgr6.idx.a | 2 +- src/index/miniattract.idx.a | 2 +- src/index/prelaunch.idx.a | 2 +- src/index/search00.idx.a | 2 +- src/index/search01.idx.a | 4 +-- src/index/search10.idx.a | 4 +-- src/index/search11.idx.a | 4 +-- src/index/slideshow.idx.a | 2 +- src/index/title.idx.a | 2 +- src/okvs.a | 59 ++++++++++++++++++++++++++++++------- src/parse.prefs.a | 2 -- 32 files changed, 97 insertions(+), 77 deletions(-) diff --git a/bin/buildsearch.sh b/bin/buildsearch.sh index 2af64f5de..fb264a01e 100755 --- a/bin/buildsearch.sh +++ b/bin/buildsearch.sh @@ -25,10 +25,14 @@ dhgrlog=$(< "$3") echo "!word $(wc -l < "$records")") > "$1" # make temp assembly source file that represents the binary OKVS data structure -source=$(mktemp) -(echo "*=0" # dummy program counter for assembler - echo "!le16 $(wc -l <"$records"), 0" # OKVS header +#source=$(mktemp) +source=build/search.a +(echo '*=$6000' + echo "!le16 $(wc -l <"$records")" # OKVS header + echo "!word KeyLookup" + count=0 while IFS="=" read -r key value; do + count=$((count+1)) dhgr=$(echo "$key" | cut -c3) # 'has DHGR title screen' flag (0 or 1) cheat=$(echo "$key" | cut -c4) # 'cheat category' (0..5) key=$(echo "$key" | cut -d"," -f2) @@ -42,6 +46,7 @@ source=$(mktemp) offset=$(echo "$offset" | awk -F, '/^'"$key"',/ { print $2 }') size=$(echo "$size" | awk -F, '/^'"$key"',/ { print $3 }') echo "!byte ${#key}+${#value}+10" # OKVS record length + echo "Key${count}" echo "!byte ${#key}" # OKVS key length echo "!text \"$key\"" # OKVS key (filename) echo "!byte ${#value}" # OKVS value length @@ -50,7 +55,12 @@ source=$(mktemp) echo "!byte $((dhgr*128))+$cheat" echo "!be24 $offset" echo "!le16 $size" - done < "$records") > "$source" + done < "$records" + echo "KeyLookup" + for i in $(seq $count); do + echo "!word Key$i" + done +) > "$source" # assemble temp source file into binary OKVS data structure, then output that out=$(mktemp) @@ -59,5 +69,5 @@ cat "$out" # clean up rm "$out" -rm "$source" +#rm "$source" rm "$records" diff --git a/res/_FileInformation.txt b/res/_FileInformation.txt index 26614321a..8b3a335f6 100644 --- a/res/_FileInformation.txt +++ b/res/_FileInformation.txt @@ -3,37 +3,12 @@ LAUNCHER.SYSTEM=Type(FF),AuxType(2000),Access(C3) TOTAL.DATA=Type(06),AuxType(0000),Access(C3) TOTAL.IDX=Type(06),AuxType(0000),Access(C3) -PREFS.CONF=Type(04),AuxType(BD00),Access(C3) -ATTRACT.IDX=Type(06),AuxType(6000),Access(C3) -MINIATTRACT.IDX=Type(06),AuxType(6000),Access(C3) -FX.IDX=Type(06),AuxType(6000),Access(C3) -DFX.IDX=Type(06),AuxType(6000),Access(C3) -GAMEHELP.IDX=Type(06),AuxType(6000),Access(C3) -SLIDESHOW.IDX=Type(06),AuxType(4000),Access(C3) -PRELAUNCH.IDX=Type(06),AuxType(6000),Access(C3) -ARTWORK.IDX=Type(06),AuxType(2000),Access(C3) -HGR0.IDX=Type(06),AuxType(4000),Access(C3) -HGR1.IDX=Type(06),AuxType(4000),Access(C3) -HGR2.IDX=Type(06),AuxType(4000),Access(C3) -HGR3.IDX=Type(06),AuxType(4000),Access(C3) -HGR4.IDX=Type(06),AuxType(4000),Access(C3) -HGR5.IDX=Type(06),AuxType(4000),Access(C3) -HGR6.IDX=Type(06),AuxType(4000),Access(C3) -DHGR.IDX=Type(06),AuxType(4000),Access(C3) -GR.IDX=Type(06),AuxType(4600),Access(C3) -SEARCH00.IDX=Type(06),AuxType(6000),Access(C3) -SEARCH01.IDX=Type(06),AuxType(6000),Access(C3) -SEARCH10.IDX=Type(06),AuxType(6000),Access(C3) -SEARCH11.IDX=Type(06),AuxType(6000),Access(C3) -CACHE00.IDX=Type(06),AuxType(A000),Access(C3) -CACHE01.IDX=Type(06),AuxType(A000),Access(C3) -CACHE10.IDX=Type(06),AuxType(A000),Access(C3) -CACHE11.IDX=Type(06),AuxType(A000),Access(C3) +PREFS.CONF=Type(04),AuxType(0000),Access(C3) COVER=Type(06),AuxType(2000),Access(C3) TITLE=Type(06),AuxType(2000),Access(C3) HELP=Type(06),AuxType(2000),Access(C3) -CREDITS=Type(06),AuxType(6000),Access(C3) -HELPTEXT=Type(06),AuxType(6000),Access(C3) +CREDITS=Type(06),AuxType(0800),Access(C3) +HELPTEXT=Type(06),AuxType(0800),Access(C3) DECRUNCH=Type(06),AuxType(0200),Access(C3) JOYSTICK=Type(06),AuxType(0800),Access(C3) Finder.Data=Type(C9),AuxType(0000),Access(E7) diff --git a/src/constants.a b/src/constants.a index 52dd73c7a..d2eeaa6f8 100644 --- a/src/constants.a +++ b/src/constants.a @@ -11,7 +11,7 @@ ; ...unused... ; E000..E3FF - HGR font data ; ...unused... -; E8CA..FFEE - main program code +; E841..FFEE - main program code ; FFEF..FFF9 - API functions and global constants available for main program ; code, prelaunchers, transition effects, &c. ; (LoadFileDirect, Wait/UnwaitForVBL, MockingboardStuff, MachineStatus) diff --git a/src/index/artwork.idx.a b/src/index/artwork.idx.a index 34d5640cd..67fab0437 100644 --- a/src/index/artwork.idx.a +++ b/src/index/artwork.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 108539 + !be24 111209 !le16 4186 diff --git a/src/index/attract.idx.a b/src/index/attract.idx.a index e7338db35..4c9a16048 100644 --- a/src/index/attract.idx.a +++ b/src/index/attract.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 61954 + !be24 64624 !le16 5174 diff --git a/src/index/cache00.idx.a b/src/index/cache00.idx.a index 4466c9c0d..cea3cbdb6 100644 --- a/src/index/cache00.idx.a +++ b/src/index/cache00.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 7472 + !be24 8000 !le16 3580 diff --git a/src/index/cache01.idx.a b/src/index/cache01.idx.a index 4ad751a53..5eb8a98f4 100644 --- a/src/index/cache01.idx.a +++ b/src/index/cache01.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 19228 + !be24 20332 !le16 3940 diff --git a/src/index/cache10.idx.a b/src/index/cache10.idx.a index 4c661265c..b82ddb0b2 100644 --- a/src/index/cache10.idx.a +++ b/src/index/cache10.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 33845 + !be24 35693 !le16 4615 diff --git a/src/index/cache11.idx.a b/src/index/cache11.idx.a index c553869e5..0eb0184a0 100644 --- a/src/index/cache11.idx.a +++ b/src/index/cache11.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 50260 + !be24 52930 !le16 5562 diff --git a/src/index/dfx.idx.a b/src/index/dfx.idx.a index d95d7371e..6ded463b1 100644 --- a/src/index/dfx.idx.a +++ b/src/index/dfx.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 69274 + !be24 71944 !le16 1242 diff --git a/src/index/dhgr.idx.a b/src/index/dhgr.idx.a index 279eabff7..5bd4e998e 100644 --- a/src/index/dhgr.idx.a +++ b/src/index/dhgr.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 107197 + !be24 109867 !le16 1249 diff --git a/src/index/dtitle.idx.a b/src/index/dtitle.idx.a index 1d122722d..7e0b9cba8 100644 --- a/src/index/dtitle.idx.a +++ b/src/index/dtitle.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 93345 + !be24 96015 !le16 464 diff --git a/src/index/fx.idx.a b/src/index/fx.idx.a index 4b1bb0a31..a6a7bce53 100644 --- a/src/index/fx.idx.a +++ b/src/index/fx.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 67128 + !be24 69798 !le16 2146 diff --git a/src/index/gamehelp.idx.a b/src/index/gamehelp.idx.a index df5177df2..5b4b536b7 100644 --- a/src/index/gamehelp.idx.a +++ b/src/index/gamehelp.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 70516 + !be24 73186 !le16 6132 diff --git a/src/index/gr.idx.a b/src/index/gr.idx.a index 15ac46f4e..57dac9f4d 100644 --- a/src/index/gr.idx.a +++ b/src/index/gr.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 108446 + !be24 111116 !le16 93 diff --git a/src/index/hgr0.idx.a b/src/index/hgr0.idx.a index 3a5e4110a..bfdc4f67b 100644 --- a/src/index/hgr0.idx.a +++ b/src/index/hgr0.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 93809 + !be24 96479 !le16 4364 diff --git a/src/index/hgr1.idx.a b/src/index/hgr1.idx.a index 35e6ba3eb..4d2d5a71b 100644 --- a/src/index/hgr1.idx.a +++ b/src/index/hgr1.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 98173 + !be24 100843 !le16 1516 diff --git a/src/index/hgr2.idx.a b/src/index/hgr2.idx.a index 60719917e..a8013330c 100644 --- a/src/index/hgr2.idx.a +++ b/src/index/hgr2.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 99689 + !be24 102359 !le16 1031 diff --git a/src/index/hgr3.idx.a b/src/index/hgr3.idx.a index 03188b82d..cf6bc0b83 100644 --- a/src/index/hgr3.idx.a +++ b/src/index/hgr3.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 100720 + !be24 103390 !le16 3237 diff --git a/src/index/hgr4.idx.a b/src/index/hgr4.idx.a index c97db99a3..ed8e3f73d 100644 --- a/src/index/hgr4.idx.a +++ b/src/index/hgr4.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 103957 + !be24 106627 !le16 2694 diff --git a/src/index/hgr5.idx.a b/src/index/hgr5.idx.a index b30b3bff1..01dc195f9 100644 --- a/src/index/hgr5.idx.a +++ b/src/index/hgr5.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 106651 + !be24 109321 !le16 441 diff --git a/src/index/hgr6.idx.a b/src/index/hgr6.idx.a index 083237c18..4a1260a16 100644 --- a/src/index/hgr6.idx.a +++ b/src/index/hgr6.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 107092 + !be24 109762 !le16 105 diff --git a/src/index/miniattract.idx.a b/src/index/miniattract.idx.a index c4ab128bb..17f4f6e55 100644 --- a/src/index/miniattract.idx.a +++ b/src/index/miniattract.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 81484 + !be24 84154 !le16 6132 diff --git a/src/index/prelaunch.idx.a b/src/index/prelaunch.idx.a index 59c07bdfa..3d1260448 100644 --- a/src/index/prelaunch.idx.a +++ b/src/index/prelaunch.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 55822 + !be24 58492 !le16 6132 diff --git a/src/index/search00.idx.a b/src/index/search00.idx.a index 17b97b07d..03a53b0a5 100644 --- a/src/index/search00.idx.a +++ b/src/index/search00.idx.a @@ -5,4 +5,4 @@ ; !byte 0 !be24 0 - !le16 7472 + !le16 8000 diff --git a/src/index/search01.idx.a b/src/index/search01.idx.a index 4762d07be..26e7cf5f4 100644 --- a/src/index/search01.idx.a +++ b/src/index/search01.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 11052 - !le16 8176 + !be24 11580 + !le16 8752 diff --git a/src/index/search10.idx.a b/src/index/search10.idx.a index 83bc64886..779c0a320 100644 --- a/src/index/search10.idx.a +++ b/src/index/search10.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 23168 - !le16 10677 + !be24 24272 + !le16 11421 diff --git a/src/index/search11.idx.a b/src/index/search11.idx.a index dcb5c7941..811f84931 100644 --- a/src/index/search11.idx.a +++ b/src/index/search11.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 38460 - !le16 11800 + !be24 40308 + !le16 12622 diff --git a/src/index/slideshow.idx.a b/src/index/slideshow.idx.a index 22a83c472..40c2ffbd7 100644 --- a/src/index/slideshow.idx.a +++ b/src/index/slideshow.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 76648 + !be24 79318 !le16 4836 diff --git a/src/index/title.idx.a b/src/index/title.idx.a index eb09cfd5c..9f2bed0f5 100644 --- a/src/index/title.idx.a +++ b/src/index/title.idx.a @@ -4,5 +4,5 @@ ; This file is automatically generated ; !byte 0 - !be24 87616 + !be24 90286 !le16 5729 diff --git a/src/okvs.a b/src/okvs.a index c4d878d75..b945d842d 100644 --- a/src/okvs.a +++ b/src/okvs.a @@ -17,12 +17,15 @@ ; Call init() once. Call it again to reset the store to 0 records. ; ; Records are maintained in a singly linked list, so most functions are O(n). -; len() is O(1) though. +; len() is always O(1). okvs_nth() can be O(1) if some other code produces +; a key lookup table and stores its address in the 'free space pointer +; after last record' field in the header. ; ; Record count is stored as a word, so a store can hold 65535 records. ; ; Keys and values are length-prefixed strings (Pascal style), so max length -; of any single key or value is 255 bytes. +; of any single key or value is 255 bytes. Record length is stored as a byte +; that includes itself, so the maximum data length of a record is 254 bytes. ; ; Keys are case-sensitive. Lookups are an exact byte-for-byte comparison. ; @@ -31,6 +34,10 @@ ; size of a record is stored, so stores are easily relocatable. There is no ; overflow protection because this is assembly. ; +; There is an append() function but it has been separated out of this version +; because it is only used once during program startup, so it does not need +; to persist in LC RAM. +; ; There is no sort() function. ; ; There is no delete() function. @@ -38,11 +45,16 @@ ; Keys can be duplicated, but get() and find() will always return the first ; match. ; +; Records can technically have more fields than key and value, but callers +; are on their own for navigating inside the record. If you have a pointer +; to one length-prefixed field (including key or value), okvs_next_field() +; will find the start of the next field. +; ; Structures: ; ; Store ; +0 number of records (word) -; +2 free space pointer after last record (word) +; +2 free space pointer after last record (word) or $0000 ; +4 Record ; ...Record... ; ...Record... @@ -218,19 +230,45 @@ okvs_next ; $WINDEX = record index ; out: A/Y = lo/hi address of nth key ; $WINDEX preserved -; X = 0 -; Z = 0 ; all other flags clobbered ; $PTR clobbered ;------------------------------------------------------------------------------ okvs_nth - jsr GetStoreAddressFromAY - ; PTR -> store - jsr incptr4 - ; PTR -> first record + jsr GetStoreAddressFromAY ; PTR -> store +LD16 WINDEX +ST16 SAVE - jmp @next + jsr incptr2 ; PTR -> store+2 + ldy #1 + lda (PTR), y + beq @slowpath ; if no key lookup table, iterate through store + pha ; otherwise look up key address and return it + dey + lda (PTR), y + sta PTR + pla + sta PTR+1 ; PTR -> key lookup table + asl SAVE + rol SAVE+1 ; SAVE = WINDEX*2 (16-bit) + lda SAVE + clc + adc PTR + bcc + + clc + inc PTR+1 ++ sta PTR + lda SAVE+1 + adc PTR+1 + sta PTR+1 ; PTR -> nth record key lookup table + lda (PTR), y + pha + iny + lda (PTR), y + tay + pla ; A/Y -> nth key in store + rts +@slowpath + jsr incptr2 ; PTR -> first record + bne @next ; always branches - jsr stepptr @next lda SAVE @@ -243,7 +281,6 @@ okvs_nth bne - jsr incptr +LD16 PTR - ldx #0 rts ;------------------------------------------------------------------------------ diff --git a/src/parse.prefs.a b/src/parse.prefs.a index 67f6325e3..d4339cbff 100644 --- a/src/parse.prefs.a +++ b/src/parse.prefs.a @@ -104,8 +104,6 @@ PREFRTS rts ; gGlobalPrefsStore must be initialized (this is done in 4cade.init) ; out: A/Y = address of pref value ; $WINDEX = index of pref value in passed store -; (if OKVS parameter is 0, no validation occurs and X=0 and Z=1 on exit, -; some callers rely on this behavior, so don't change it!) ; PARAM clobbered ; PTR clobbered ; SRC clobbered