pitch-dark/src/ui.resume.a

294 lines
10 KiB
Plaintext

;license:MIT
;(c) 2018 by 4am
;
; User interface - views and paint routines for 'resume game' screen
;
; Public functions
; - ResumeDialog
;
; 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
; action keys for options screen
kResumeKeys
!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_RADIO_PREVIOUS ; left arrow
!byte $95,ID_RADIO_NEXT ; right arrow
!byte $8B,ID_RADIO_PREVIOUS ; up arrow
!byte $8A,ID_RADIO_NEXT ; down arrow
_endResumeKeys
;------------------------------------------------------------------------------
; ResumeDialog
; call WeeGUI to create and paint 'resume game' screen, and run to completion
;
; in: WeeGUI initialized
; out: exits via MainScreen, LaunchInterpreterWithSavedGame, or LaunchInterpreterWithNewGame
;------------------------------------------------------------------------------
ResumeDialog
ldx #$FF
txs
jsr HardResetWeeGUI
jsr LoadSavedGameInfo ; call ZINFO to get the information we need for this dialog
lda gSavedGamesSlotsInUse ; populated by LoadSavedGameInfo
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 ; create decorated frame
!word kViewResumeFrame
!word kStringResumeFrame
jsr CreateButton ; create OK/Cancel buttons
!word kViewResumeOK
jsr CreateButton
!word kViewResumeCancel
jsr okvs_iter ; create radio buttons for saved games
!word gSavedGamesStore
!word CreateResumeRadioCallback
lda iResumeVTAB ; create 'new game' radio button
sta kViewResumeNewGameTop
jsr CreateRadio
!word kViewResumeNewGame
lda gLastSavedGameSlot ; initial checked radio button = last save slot + 1
bmi +
inc
+HIDE_NEXT_2_BYTES
+ lda #ID_RESUME_NEWGAME ; if last save slot is invalid, just check 'new game'
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
jsr ClearPendingInput
- ldx #WGPendingViewAction
jsr WeeGUI
lda $C000
bpl -
jsr ClearPendingInput
jsr HandleResumeKey
bra -
;------------------------------------------------------------------------------
; internal functions
;------------------------------------------------------------------------------
; HandleResumeKey
;
; in: A = key pressed
; out: all registers and flags clobbered
;------------------------------------------------------------------------------
HandleResumeKey
ldx #(_endResumeKeys-kResumeKeys)-2
- cmp kResumeKeys,x
beq @found
dex
dex
bpl -
@error jmp SoftBell
@found lda kResumeKeys+1,x ; get action ID associated with this key
bmi @updown
tax ; action ID < #$80 is a WeeGUI view, so activate it
ldy gViewInUse,x
beq @error
ldx #WGSelectView
jsr WeeGUI
jmp SimulateClick
@updown ldx #ID_RESUME_SLOT0
ldy #ID_RESUME_NEWGAME
jmp HandleUpDownRadio
;------------------------------------------------------------------------------
; CreateResumeRadioCallback
; called via okvs_iter
;
; in: 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)
; out: all registers and flags clobbered
;------------------------------------------------------------------------------
CreateResumeRadioCallback
+STAY PTR
lda (PTR)
beq @exit ; 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
@exit rts
;------------------------------------------------------------------------------
; PrintResumeLabelCallback
; called via okvs_iter_values
;
; in: 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)
; out: all registers and flags clobbered
;------------------------------------------------------------------------------
PrintResumeLabelCallback
+STAY PTR
lda (PTR)
beq .printResumeExit ; 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
.printResumeExit
rts
;------------------------------------------------------------------------------
; ResumeOKCallback
; called via OK button activation
;
; in: none
; out: exits via LaunchInterpreterWithGame
;------------------------------------------------------------------------------
ResumeOKCallback
ldx #ID_RESUME_SLOT0
ldy #ID_RESUME_NEWGAME
jsr GetCheckedRadioButton ; returns A = WeeGUI view ID
cmp #ID_RESUME_NEWGAME
bne +
lda #0
+ dec ; A = saved game slot or #$FF
jmp LaunchInterpreterWithGame
;------------------------------------------------------------------------------
; WeeGUI view configuration records
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
kViewResumeOK
!byte ID_RESUME_OK ; view ID
!byte 63 ; left
!byte $FD ; top
!byte 10 ; width
!word ResumeOKCallback ; callback
!word kStringOK ; caption
kViewResumeCancel
!byte ID_RESUME_CANCEL ; view ID
!byte 63 ; left
!byte $FD ; top
!byte 10 ; width
!word MainScreen ; 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
kStringResumeFrame
!text "Resume Game",0
kStringNewGame
!text " Start ",110,"ew game",0