pitch-dark/src/ui.main.a

410 lines
13 KiB
Plaintext

;license:MIT
;(c) 2018 by 4am
;
; User interface - views and paint routines for main screen
;
; Public functions
; - PaintMain
; - RepaintMainIfDirty
;
; Public variables
; - gMainScreenPaintDirty
; - gViewInUse
;
; View IDs (application-specific, acceptable range 0..15, no duplicates)
ID_PREVIOUS = 1
ID_OPTIONS = 2
ID_NEXT = 3
ID_PLAY = 4
ID_BOXART = 5
ID_HINTS = 6
ID_VERSIONS = 7
ID_INFO = 8
ID_DESCRIPTION = 9
gMainScreenPaintDirty
!byte 0 ; 0=false, 1=true
gViewInUse
!byte 0,1,1,1,1,0,0,0,0,0,0,0,0,0,0
;------------------------------------------------------------------------------
; PaintMain/RepaintMainIfDirty
; call WeeGUI to create all application views and paint them
; PaintMain entry point will clear the screen and unconditionally paint everything
; RepaintMainIfDirty will only repaint certain views that vary between games,
; and only if gMainScreenPaintDirty=1
;
; in: WeeGUI loaded and initialized
; out: all registers and flags clobbered
;------------------------------------------------------------------------------
!zone {
PaintMain
ldx #WGResetAll
jsr WeeGUI
stz gViewInUse+ID_BOXART
stz gViewInUse+ID_HINTS
stz gViewInUse+ID_VERSIONS
ldx #1 ; flag - clear screen before painting
stx gMainScreenPaintDirty
!byte $2C
RepaintMainIfDirty
ldx #0 ; flag - do not clear screen before painting
lda gMainScreenPaintDirty
bne +
rts
+ stz gMainScreenPaintDirty ; clear dirty flag
phx ; push 'clear screen' flag (will pop at end of procedure)
jsr CreateButton ; create 'previous' button
!word kViewPrevious
jsr CreateButton ; create 'settings' button
!word kViewOptions
jsr CreateButton ; create 'next game' button
!word kViewNext
lda gHasSavedGames ; create 'play game' or 'resume game' button
beq .wantPlayButton
jsr CreateButton
!word kViewResume
bra .donePlayOrResume
.wantPlayButton
jsr CreateButton
!word kViewPlay
.donePlayOrResume
jsr CreateOrDestroyButton ; create or destroy 'artwork' button
!byte ID_BOXART
!word kViewBoxArt
!word kHasArtwork
jsr CreateOrDestroyButton ; create or destroy 'hints' button
!byte ID_HINTS
!word kViewHints
!word kHasHints
jsr CreateOrDestroyButton ; create or destroy 'revisions' button
!byte ID_VERSIONS
!word kViewVersions
!word kHasVersions
pla ; clear screen before repainting?
beq .nohome ; no -> repaint over existing screen, YOLO
ldx #WGClearScreen ; clear screen
jsr WeeGUI
jsr PaintTitleBar ; paint top bar
lda #4 ; paint horizontal separator bar
sta PARAM1
ldy #78
lda #83
- sty PARAM0
ldx #WGSetGlobalCursor
jsr WeeGUI
ldx #WGPlot
jsr WeeGUI
dey
bne -
ldx #WGSyncGlobalCursor
jsr WeeGUI
.nohome
ldx #WGSelectView ; delete info box but leave its contents on screen
lda #ID_INFO ; (harmless if it doesn't exist yet)
jsr WeeGUI
ldx #WGResetView
jsr WeeGUI
ldx #WGSelectView ; delete description box but leave its contents on screen
lda #ID_DESCRIPTION ; (harmless if it doesn't exist yet)
jsr WeeGUI
ldx #WGResetView
jsr WeeGUI
ldx #WGSelectView ; WeeGUI does NOT like repainting if the selected view does not exist
lda #ID_PREVIOUS
jsr WeeGUI
ldx #WGViewPaintAll ; repaint all WeeGUI-controlled UI elements
jsr WeeGUI
ldx #WGCreateView ; (re)create borderless frame for game title and info
+LDADDR kViewInfo ; (has the nice side effect of resetting the scroll)
+STAY PARAM0
jsr WeeGUI
jsr PaintInfoView ; paint contents of info box
ldx #WGCreateView ; (re)create scrollable frame for game description text
+LDADDR kViewDescription
+STAY PARAM0
jsr WeeGUI
ldx #WGViewSetAction ; set view action (called automatically after scrolling)
+LDADDR PaintDescriptionView
+STAY PARAM0
jsr WeeGUI
ldx #WGPaintView ; paint frame of description box
jsr WeeGUI
jmp PaintDescriptionView ; paint contents of description box
}
;------------------------------------------------------------------------------
; CreateOrDestroyButton
; create or destroy a WeeGUI Button view, based on per-game options
; and whether the button already exists
;
; in: WeeGUI loaded and initialized
; gOptionsStore populated
; stack contains 5 bytes of parameters:
; +1 [byte] WeeGUI view ID
; +2 [word] address of WeeGUI view configuration record
; +4 [word] address of length-prefixed key into gOptionsStore
; out: all registers and flags clobbered
;------------------------------------------------------------------------------
!zone {
CreateOrDestroyButton
+PARAMS_ON_STACK 5
ldy #1
lda (PARAM),y
sta .viewID
ldy #3
lda (PARAM),y
pha
dey
lda (PARAM),y
ply
+STAY .viewConfigurationRecord
ldy #5
lda (PARAM),y
pha
dey
lda (PARAM),y
ply
+STAY .optionsStoreKey
jsr okvs_get
!word gOptionsStore
.optionsStoreKey
!word $FDFD ; SMC
.viewID=*+1
ldx #$FD ; SMC (X = WeeGUI view ID)
jsr okvs_as_boolean
beq .destroy
lda gViewInUse,x ; create button if it doesn't exist
bne .done ; oh it does exist, so we're done
lda #1
sta gViewInUse,x
jsr CreateButton
.viewConfigurationRecord
!word $FDFD ; SMC
bra .done
.destroy lda gViewInUse,x ; destroy button if it exists
beq .done ; oh it doesn't exist, so we're done
lda #0
sta gViewInUse,x
txa ; A = WeeGUI view ID
ldx #WGSelectView
jsr WeeGUI
ldx #WGEraseView
jsr WeeGUI
ldx #WGResetView
jsr WeeGUI
.done rts
}
!zone {
PaintDescriptionView
ldx #WGSelectView
lda #ID_DESCRIPTION
jsr WeeGUI
+LDAY addrDescription
ldx #kDescriptionPaintWidth
jsr MultiPrint
lda SAVE
cmp #10 ; minimum content height
bcs +
lda #10
+ ldx #WGSetContentHeight ; set content height so we stop scrolling on the last line of text
jmp WeeGUI
PaintInfoView
ldx #WGSelectView
lda #ID_INFO
jsr WeeGUI
+LDAY addrInfo
ldx #kInfoPaintWidth
phx
jsr MultiPrint
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 + ; A/Y contains address
jsr okvs_get ; get long description of this version
!word gVersionsStore
+ !word $FDFD ; SMC
; A/Y contains address
plx ; X = width a.k.a. where to put the null (rest is padded with spaces)
jsr CreateNullTerminatedString ; copies string to kNullTerminatedBuffer
+LDADDR kNullTerminatedBuffer ; now use that as the buffer to print the last line
!byte $2C
; execution falls through here
MultiPrint
stz SAVE ; VTAB, but 0-indexed
stx .printLineLength+1
+STAY SRC
.printLoop
stz PARAM0
lda SAVE
sta PARAM1
ldx #WGSetCursor
jsr WeeGUI
+LDAY SRC
+STAY PARAM0
bit MAGICRTS ; set overflow bit to trigger raw printing (with mousetext)
ldx #WGPrint
jsr WeeGUI
lda SRC
clc
.printLineLength
adc #$FD ; SMC
sta SRC
bcc +
inc SRC+1
+ inc SAVE
lda (SRC)
bne .printLoop
rts
}
;------------------------------------------------------------------------------
kViewPrevious
!byte ID_PREVIOUS ; view ID
!byte 1 ; left
!byte 2 ; top
!byte 13 ; width
!word callback_previous ; callback
!word kStringPrevious ; caption
kStringPrevious
!text "< "
!byte $10 ; 'P' inverse
!text "revious",0
kViewNext
!byte ID_NEXT ; view ID
!byte 66 ; left
!byte 2 ; top
!byte 13 ; width
!word callback_next ; callback
!word kStringNext ; caption
kStringNext
!byte $0E ; 'N' inverse
!text "ext game >",0
kViewOptions
!byte ID_OPTIONS ; view ID
!byte 34 ; left
!byte 2 ; top
!byte 12 ; width
!word callback_options ; callback
!word kStringOptions
kStringOptions
!byte $13 ; 'S' inverse
!text "ettings",0
kViewPlay
!byte ID_PLAY ; view ID
!byte 66 ; left
!byte 6 ; top
!byte 13 ; width
!word callback_play ; callback
!word kStringPlay ; caption
kStringPlay
!byte 144
!text "lay "
!byte $67 ; 'g' inverse
!text "ame",0
kViewResume
!byte ID_PLAY ; view ID
!byte 66 ; left
!byte 6 ; top
!byte 13 ; width
!word callback_resume ; callback
!word kStringResume ; caption
kStringResume
!byte 146
!text "esume "
!byte $67 ; 'g' inverse
!text "ame",0
kViewBoxArt
!byte ID_BOXART ; view ID
!byte 66 ; left
!byte 8 ; top
!byte 13 ; width
!word callback_boxart ; callback
!word kStringBoxArt ; caption
kStringBoxArt
!byte $01 ; 'A' inverse
!text "rtwork",0
kViewHints
!byte ID_HINTS ; view ID
!byte 66 ; left
!byte 10 ; top
!byte 13 ; width
!word callback_clues ; callback
!word kStringHints ; caption
kStringHints
!byte $08 ; 'H' inverse
!text "ints",0
kViewVersions
!byte ID_VERSIONS ; view ID
!byte 66 ; left
!byte 12 ; top
!byte 13 ; width
!word callback_versions ; callback
!word kStringVersions ; caption
kStringVersions
!byte $12 ; 'R' inverse
!text "evisions",0
kViewInfo
!byte ID_INFO ; view ID
!byte 0 ; style
!byte 0 ; left
!byte 6 ; top
!byte 65 ; visible width
!byte 6 ; visible height
!byte 65 ; width
!byte 6 ; height
kViewDescription
!byte ID_DESCRIPTION ; view ID
!byte 2 ; style
!byte 1 ; left
!byte 15 ; top
!byte 77 ; visible width
!byte 8 ; visible height
!byte 77 ; width
!byte 39 ; height