;license:MIT ;(c) 2018 by 4am ; ; glue code to load and call ZINFO, the On Beyond Z-Machine! saved game parser ; ; Public functions ; - LoadSavedGameInfo ; ; Public variables ; - gSavedGamesStore ; - gSavedGamesSlotsInUse ; ; TODO move these to a ZINFO_MLI kind of separate file zinfo_base = $2000 zinfo_maxslots = 8 name_offset = 0 ;1+37 bytes, a zero-length name is an empty record time_offset = 42 ;1+8 bytes ("12:01 pm") score_offset = 51 ;1+6 bytes (-12345) moves_offset = 58 ;1+5 bytes (12345) date_offset = 64 ;1+10 bytes ("10/10/2099") zinfo_recordlen= 75 ;bytes gSavedGamesStore !word $FDFD ; set in LoadGameInfo gSavedGamesSlotsInUse !byte $FD ; set in LoadSavedGameInfo ;------------------------------------------------------------------------------ ; LoadSavedGameInfo ; load ZINFO, call it with the current game, and parse the results ; ; in: current ProDOS prefix is the same as the PITCH.DARK file ; out: none ;------------------------------------------------------------------------------ LoadSavedGameInfo jsr okvs_init !word gSavedGamesStore stz gSavedGamesSlotsInUse jsr LoadFile ; load ZINFO.SYSTEM at $2000 !word kZINFOFilename !word kSystemAddress !word kProDOSFileBuffer bcc + jmp SoftBell + jsr SetStartupPathToCurrentVersionOfCurrentGame jsr kSystemAddress ; call ZINFO (despite being a .SYSTEM program, it returns via RTS) +LDADDR zinfo_base +STAY ZPTR ldx #0 @zParseLoop +LDAY ZPTR pha phy phx jsr ResetPath lda (ZPTR) beq @branchToNextSlot ; no saved game in this slot inc gSavedGamesSlotsInUse ; update number of slots in use (separate from length of store) +LDAY ZPTR jsr AddToPathWithHighBit ; add location information ldx #0 ; count elements to print (there can be 0-3 of them) jsr @queryTime beq + inx + jsr @queryScore beq + inx + jsr @queryMoves beq + inx + jsr @queryDate beq + inx + stx @tempX+1 plx ply pla pha phy phx +STAY ZPTR @tempX ldx #0 ; self-modified cpx #0 ; to allow branch-linking from above @branchToNextSlot beq @saveAndMoveToNextSlot; only location, nothing more to print phx +LDADDR kLeftParen jsr AddToPathWithHighBit ; add ' (' jsr @queryTime beq @noTime +LDAY ZPTR jsr AddToPathWithHighBit ; add time information ; execution falls through here plx dex beq @doneState phx +LDADDR kSlash jsr AddToPathWithHighBit ; add '/' because we have more to print @noTime jsr @queryScore beq @noScore +LDAY ZPTR jsr AddToPathWithHighBit ; add score information ; execution falls through here plx dex beq @doneState phx +LDADDR kSlash jsr AddToPathWithHighBit ; add '/' because we have more to print @noScore jsr @queryMoves beq @noMoves +LDAY ZPTR jsr AddToPathWithHighBit ; add moves information ; execution falls through here plx dex beq @doneState phx +LDADDR kSlash jsr AddToPathWithHighBit ; add '/' because we have more to print @noMoves jsr @queryDate beq @noDate plx +LDAY ZPTR jsr AddToPathWithHighBit ; add date information ; execution falls through here @noDate @doneState +LDADDR kRightParen jsr AddToPathWithHighBit ; add ')' +LDADDR kNullByte jsr AddToPath ; add 0x00 ; execution falls through here @saveAndMoveToNextSlot plx phx txa ora #$30 sta kSlotNumber lda gPathname beq + lda #9 + sta kSlotName ; set length of key (0 if value is empty, otherwise 9) jsr okvs_append ; add this key/value to saved games store (used by ResumeDialog) !word gSavedGamesStore !word kSlotName ; key = printable short label, or empty string if slot is unused !word gPathname ; value = printable long label, or empty string if slot is unused !byte 0 plx ply pla clc adc #zinfo_recordlen bcc + iny + +STAY ZPTR ; ZPTR -> start of next ZINFO record inx cpx #zinfo_maxslots bcs + jmp @zParseLoop + rts @queryTime lda ZPTR clc adc #time_offset-name_offset sta ZPTR bcc + inc ZPTR+1 + ; ZPTR -> ZINFO time field (length-prefixed string, may be empty string if no time) lda (ZPTR) rts @queryScore lda ZPTR clc adc #score_offset-time_offset sta ZPTR bcc + inc ZPTR+1 + ; ZPTR -> ZINFO score field (length-prefixed string, may be empty string if no score) lda (ZPTR) rts @queryMoves lda ZPTR clc adc #moves_offset-score_offset sta ZPTR bcc + inc ZPTR+1 + ; ZPTR -> ZINFO moves field (length-prefixed string, may be empty string if no moves) lda (ZPTR) rts @queryDate lda ZPTR clc adc #date_offset-moves_offset sta ZPTR bcc + inc ZPTR+1 + ; ZPTR -> ZINFO date field (length-prefixed string, may be empty string if no date) lda (ZPTR) rts kZINFOFilename !byte 12 !raw "ZINFO.SYSTEM" kSlotName !byte 9 !text " Slot " kSlotNumber !text "x:",0 ; ends with null byte on purpose kLeftParen !byte 2 !text " (" kSlash !byte 1 !text "/" kRightParen !byte 1 !text ")" kNullByte !byte 1,0