;license:MIT ;(c) 2018 by 4am ; ; User interface - views and paint routines for 'resume game' screen ; ; Public functions ; - ResumeGameDialog ; !zone { ; View IDs (application-specific, acceptable range 0..15, no duplicates) ID_RESUME_FRAME = 0 ID_RESUME_SLOT0 = 1 ID_RESUME_SLOT1 = 2 ID_RESUME_SLOT2 = 3 ID_RESUME_SLOT3 = 4 ID_RESUME_SLOT4 = 5 ID_RESUME_SLOT5 = 6 ID_RESUME_SLOT6 = 7 ID_RESUME_SLOT7 = 8 ID_RESUME_NEWGAME = 9 ID_RESUME_OK = 10 ID_RESUME_CANCEL = 11 gResumeViewInUse !byte 1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0 ; action keys for options screen .keys !byte $CF,ID_RESUME_OK ; O !byte $EF,ID_RESUME_OK ; o !byte $8D,ID_RESUME_OK ; Return !byte $C3,ID_RESUME_CANCEL ; C !byte $E3,ID_RESUME_CANCEL ; c !byte $9B,ID_RESUME_CANCEL ; Esc !byte $B0,ID_RESUME_SLOT0 ; 0 !byte $B1,ID_RESUME_SLOT1 ; 1 !byte $B2,ID_RESUME_SLOT2 ; 2 !byte $B3,ID_RESUME_SLOT3 ; 3 !byte $B4,ID_RESUME_SLOT4 ; 4 !byte $B5,ID_RESUME_SLOT5 ; 5 !byte $B6,ID_RESUME_SLOT6 ; 6 !byte $B7,ID_RESUME_SLOT7 ; 7 !byte $CE,ID_RESUME_NEWGAME ; N !byte $EE,ID_RESUME_NEWGAME ; n !byte $88,ID_RESUME_PREVIOUS; left arrow !byte $95,ID_RESUME_NEXT ; right arrow !byte $8B,ID_RESUME_PREVIOUS; up arrow !byte $8A,ID_RESUME_NEXT ; down arrow .endkeys ; IDs of actions that do not correspond to WeeGUI view IDs have high bit set ID_RESUME_PREVIOUS = $81 ID_RESUME_NEXT = $82 ;------------------------------------------------------------------------------ ; ResumeDialog ; call WeeGUI to create and paint 'resume game' screen, and run to completion ; ; in: WeeGUI initialized ; out: exits via MainScreen or LaunchInterpreterWithGame ; all registers and flags clobbered ;------------------------------------------------------------------------------ ResumeDialog ldx #$FF txs ldx #WGResetAll ; reset WeeGUI jsr WeeGUI jsr LoadSavedGameInfo lda gSavedGamesSlotsInUse asl clc adc #3 sta kViewResumeFrame+5 ; frame visible height = 3 + (2 * usedSlots) sta kViewResumeFrame+7 ; frame height lda #11 sec sbc gSavedGamesSlotsInUse sta kViewResumeFrame+3 ; frame top = 11 - usedSlots inc sta iResumeVTAB ; top of first radio button sta kViewResumeOK+2 ; OK top inc inc sta kViewResumeCancel+2 ; Cancel top jsr CreateDialog !word kViewResumeFrame !word kStringResumeFrame jsr CreateButton ; create UI controls !word kViewResumeOK jsr CreateButton !word kViewResumeCancel jsr okvs_iter !word gSavedGamesStore !word CreateResumeRadioCallback lda iResumeVTAB sta kViewResumeNewGameTop jsr CreateRadio !word kViewResumeNewGame ; TODO set proper radio button based on ZINFO lda #ID_RESUME_NEWGAME ldx #WGSelectView jsr WeeGUI lda #1 sta PARAM0 ldx #WGSetState jsr WeeGUI ldx #WGDesktop ; paint background jsr WeeGUI ldx #WGViewPaintAll ; paint UI controls (window frame, buttons, checkboxes, radio buttons) jsr WeeGUI jsr PaintTitleBar ; paint top title bar ldx #WGSelectView ; select frame (required for print routines that follow) lda #ID_RESUME_FRAME jsr WeeGUI lda #1 ; WeeGUI radio buttons are limited to 15 characters, so we sta iResumeVTAB ; print the longer labels separately jsr okvs_iter_values !word gSavedGamesStore !word PrintResumeLabelCallback .runLoop ldx #WGPendingViewAction jsr WeeGUI lda $c000 bpl .runLoop bit $c010 jsr HandleResumeKey bra .runLoop ;------------------------------------------------------------------------------ ; internal functions CreateResumeRadioCallback ; called via okvs_iter ; X = index (0-based) into gSavedGamesStore, which is also the slot number ; A/Y points to okvs record key, which we use as the radio button caption ; (length-prefixed and null-terminated, length=0 if slot is unused and should be skipped) ; +STAY PTR lda (PTR) sta gResumeViewInUse+1,x ; mark whether this view is in use (hotkeys activate based on this array) beq .createResumeRadioDone; length=0 means this slot is unused, so we're done lda PTR inc ; skip over length byte bne + iny + +STAY kViewResumeRadioCaption ; A/Y -> null-terminated string, which is what WeeGUI wants inx stx kViewResumeRadioSlot ; WeeGUI view ID = X + 1 lda iResumeVTAB sta kViewResumeRadioTop ; radio button top = frame top + 1 + (2 * X) jsr CreateRadio ; create radio button for this version (will print label later) !word kViewResumeRadio inc iResumeVTAB inc iResumeVTAB .createResumeRadioDone rts PrintResumeLabelCallback ; called via okvs_iter_values ; X = index (0-based) into gSavedGamesStore, which is also the slot number ; A/Y points to okvs record value, which we use as a printable label ; (length-prefixed and null-terminated, length=0 if slot is unused and should be skipped) +STAY PTR lda (PTR) beq .printResumeLabelDone ; length=0 means this slot is unused, so we're done lda PTR inc ; skip over length byte bne + iny + +STAY .printResumeLabel ; A/Y -> null-terminated string jsr PrintAt !byte 14 ; htab (constant) iResumeVTAB !byte $FD ; SMC .printResumeLabel !word $FDFD ; SMC inc iResumeVTAB inc iResumeVTAB .printResumeLabelDone rts HandleResumeKey ldx #.endkeys-.keys - cmp .keys,x beq .foundKey dex dex bpl - jmp SoftBell .foundKey lda .keys+1,x ldx #WGSelectView jsr WeeGUI jmp SimulateClick callback_resume_ok = LaunchInterpreterWithGame callback_resume_cancel = MainScreen kViewResumeFrame !byte ID_RESUME_FRAME ; view ID !byte 2 ; style (decorated frame) !byte 5 ; left !byte $FD ; top !byte 70 ; visible width !byte $FD ; visible height !byte 70 ; width !byte $FD ; height kStringResumeFrame !text "Resume Game",0 kViewResumeOK !byte ID_RESUME_OK ; view ID !byte 63 ; left !byte $FD ; top !byte 10 ; width !word callback_resume_ok ; callback !word kStringOK ; caption kViewResumeCancel !byte ID_RESUME_CANCEL ; view ID !byte 63 ; left !byte $FD ; top !byte 10 ; width !word callback_resume_cancel ; callback !word kStringCancel ; caption kViewResumeRadio ; reused for each slot kViewResumeRadioSlot !byte $FD ; view ID (SMC) !byte 8 ; left kViewResumeRadioTop !byte $FD ; top (SMC) kViewResumeRadioCaption !word $FDFD ; caption (SMC) kViewResumeNewGame !byte ID_RESUME_NEWGAME ; view ID !byte 8 ; left kViewResumeNewGameTop !byte $FD ; top (SMC) !word kStringNewGame ; caption kStringNewGame !text " Start ",110,"ew game",0 }