;license:MIT ;(c) 2018 by 4am ; ; Parser for per-game configuration files ; ; Public functions ; - LoadGameInfo ; - CheckForSavedGames ; ; Public variables ; - gHasSavedGames byte 0=false, nonzero=true (set in CheckForSavedGames) ; - gLastSavedGameSlot byte 0-7 (only valid if gHasSavedGames=1) ; ; Public constants (keys in gOptionsStore) ; - kHasArtwork ; - kHasHints ; - kHasVersions kTextRootDirectory !byte 5 !raw "TEXT/" kHasArtwork !byte 7 !raw "ARTWORK" kHasHints !byte 5 !raw "CLUES" kHasVersions !byte 8 !raw "VERSIONS" gVersionsStore !word $FDFD ; set in LoadGlobalPreferences gOptionsStore !word $FDFD ; set in LoadGameInfo gHasSavedGames !byte $FD ; set in CheckForSavedGames gLastSavedGameSlot !byte $FD ; set in CheckForSavedGames sectionPointers ; array of pointers to start of each section addrEOF !word $FDFD addrOptions !word $FDFD addrVersions !word $FDFD addrDescription !word $FDFD addrInfo !word $FDFD ;------------------------------------------------------------------------------ ; FlushSaveInfo ; update aux data for the current game save-slot if needed ; ; in: current ProDOS prefix is the same as the PITCH.DARK binary ; out: all registers and flags clobbered ;------------------------------------------------------------------------------ FlushSaveInfo lda $50 cmp #$50 bne + lda $51 cmp #$44 bne + dec $50 ; prevent re-check in future lda $52 sta @slot jsr SetStartupPathToCurrentVersionOfCurrentGame ldx gPathname lda #'S' sta gPathname-1,x lda #'A' sta gPathname,x lda #'V' sta gPathname+1,x inc gPathname jsr SetAuxFileType ; best-effort !word gPathname @slot !word 0 + rts ;------------------------------------------------------------------------------ ; LoadGameInfo ; load file with information about the current game ; ; in: current ProDOS prefix is the same as the PITCH.DARK binary ; out: addrInfo, addrDescription, addrVersions, addrOptions populated ; gVersionsStore populated with keys/values in [versions] section ; gOptionsStore populated with keys/values in [options] section ; all registers and flags clobbered ; $00..$05 clobbered ; $0800..$1FFF clobbered ;------------------------------------------------------------------------------ LoadGameInfo jsr ResetPath +LDADDR kTextRootDirectory jsr AddToPath jsr okvs_get !word gGlobalPrefsStore !word kLastPlayed jsr AddToPath jsr LoadFile !word gPathname !word kGameInfoBuffer !word kProDOSFileBuffer +LDADDR (kGameInfoBuffer-1) +STAY $FE ; ($FE) points to start of data buffer ldy #$00 ; index into ($FE) pointing to current character ldx #$08 ; index into sectionPointers array, stores pointer to start of each section @convertSectionLoop jsr IncAndGetChar @convertSectionNoInc cmp #$5B ; '[' is the start of a new section beq @skipSectionName cmp #$0D ; CR -> 0x00 (WeeGUI wants null-terminated strings) beq @null cmp #$5E ; '^' -> closed-apple mousetext beq @ca cmp #$26 ; '&' -> open-apple mousetext beq @oa ora #$80 ; all other characters -> set high bit +HIDE_NEXT_2_BYTES @null lda #$00 +HIDE_NEXT_2_BYTES @ca lda #$40 +HIDE_NEXT_2_BYTES @oa lda #$41 sta ($FE),y bra @convertSectionLoop ; We found the start of a new section, so skip to the first character on the next line @skipSectionName jsr IncAndGetChar cmp #$0D ; CR bne @skipSectionName jsr IncAndGetChar ; We are at the start of a section, so save this address in the sectionPointers array pha tya clc adc $FE sta sectionPointers,x lda $FF bcc + inc + sta sectionPointers+1,x pla dex dex bpl @convertSectionNoInc ; We are done converting the game info file. ; Now handle the individual sections that require further parsing. jsr ParseKeyValueText ; parse [versions] section into gVersionsStore !word gVersionsStore ; (this handle was initialized in LoadGlobalPreferences) !word addrVersions !byte 0 +LDAY SRC +STAY gOptionsStore ; save pointer to free space for next store jsr ParseKeyValueText ; parse [options] section into gOptionsStore !word gOptionsStore !word addrOptions !byte 0 +LDAY SRC +STAY gSavedGamesStore ; save pointer to free space for next store ; execution falls through here CheckForSavedGames jsr okvs_get ; get shortname of current game !word gGlobalPrefsStore !word kLastPlayed +STAY + ; A/Y contains address jsr okvs_get ; get selected version of this game !word gGlobalPrefsStore + !word $FDFD ; SMC +STAY SRC ; A/Y contains address lda (SRC) dec tay phy - lda (SRC),y sta gVal,y dey bpl - ply lda #$53 ; add new suffix ('SAV') sta gVal,y iny lda #$41 sta gVal,y iny lda #$56 sta gVal,y inc gVal ; fix string length jsr ResetPath +LDADDR kGameRootDirectory jsr AddToPath jsr okvs_get !word gGlobalPrefsStore !word kLastPlayed jsr AddToPath +LDADDR kPathSeparator jsr AddToPath +LDADDR gVal jsr AddToPath jsr GetFileInfo !word gPathname bcs @no ; no file -> no saved games lda auxtype ; if low byte of auxtype is $3x, then saved and x is the last save slot and #$F0 cmp #$30 bne @no @yes lda auxtype and #$0F sta gLastSavedGameSlot lda #1 +HIDE_NEXT_2_BYTES @no lda #0 sta gHasSavedGames rts