working versions dialog

This commit is contained in:
4am 2018-04-11 15:12:36 -04:00
parent 4af523afd7
commit 4a698edb5c
9 changed files with 616 additions and 163 deletions

View File

@ -5,9 +5,10 @@
;
; Public functions
; - LoadGameInfo
; - CheckForSavedGames
;
; Public variables
; - gHasSavedGames 0=false, 1=true
; - gHasSavedGames 0=false, 1=true (set in CheckForSavedGames)
;
; Public constants (keys in gOptionsStore)
; - kHasArtwork
@ -136,7 +137,8 @@ LoadGameInfo
!word gOptionsStore
!word addrOptions
!byte 0
; execution falls through here
CheckForSavedGames
jsr okvs_get ; get shortname of current game
!word gGlobalPrefsStore
!word kLastPlayed

View File

@ -35,6 +35,8 @@
!source "src/ui.main.a"
!source "src/ui.main.keys.a"
!source "src/ui.options.a"
; !source "src/ui.resume.a"
!source "src/ui.versions.a"
!source "src/ui.artwork.a"
Start
@ -59,13 +61,15 @@ MainScreen
txs
jsr PaintMain ; create all WeeGUI views (UI elements) and paint them
bit $C010 ; clear keyboard strobe
ldx #WGClearPendingClick ; clear WeeGUI mouse strobe
jsr WeeGUI
.mainRunLoop
jsr RepaintMainIfDirty
ldx #WGPendingViewAction
jsr WeeGUI ; handle mouse movement and clicks
lda $c000
lda $C000
bpl .mainRunLoop
bit $c010
bit $C010
jsr HandleKey ; handle keypresses
bra .mainRunLoop

View File

@ -50,20 +50,18 @@ DisplayArtwork
sta $C052
sta $C054
sta $C050
bit $C010 ; clear keyboard strobe
ldx #WGClearPendingClick ; clear WeeGUI mouse strobe
jsr WeeGUI
.artworkRunLoop
.runLoop
ldx #WGPendingClick
jsr WeeGUI
cpx #$FF
bne + ; X != #$FF -> user clicked mouse
lda $C000
bpl .artworkRunLoop
+ bit $C010 ; clear keyboard strobe
ldx #WGClearPendingClick ; clear WeeGUI mouse strobe
jsr WeeGUI
sta $C051 ; back to text
bpl .runLoop
+ sta $C051 ; back to text
rts
.error
jmp SoftBell

View File

@ -10,6 +10,7 @@
; - PaintTitleBar
; - PrintAt
; - SimulateClick
; - GetCheckedRadioButton
;
; Public constants
; - kStringOK
@ -140,6 +141,8 @@ PrintAt
;------------------------------------------------------------------------------
; SimulateClick
; focus, activate, and unfocus a WeeGUI view
; note: does *not* select the view first, which you may or may not wish to do
; before calling
;
; in: WeeGUI initialized
; A contains WeeGUI view ID
@ -154,3 +157,43 @@ SimulateClick
ldx #WGViewUnfocus
jmp WeeGUI
}
;------------------------------------------------------------------------------
; GetCheckedRadioButton
; determine which radio button on screen is visually checked
; WeeGUI only supports a single radio group, so there is only ever one
; selected radio button.
; WeeGUI has no way to query the type of a view, so this function takes the
; lower and upper IDs and all views within that range are presumed to be
; radio buttons.
; WeeGUI has no way to query if a view is in use, so all views within the
; given range are presumed to exist and be initialized properly.
;
; in: WeeGUI initialized
; A contains WeeGUI view ID of first radio button
; Y contains 1 greater than the WeeGUI view ID of last radio button
; out: C clear -> A contains WeeGUI view ID of selected radio button
; C set -> error, there is no selected radio button
; all other registers and flags clobbered
;------------------------------------------------------------------------------
!zone {
GetCheckedRadioButton
sty .max
- pha
ldx #WGSelectView
jsr WeeGUI
ldx #WGGetState
jsr WeeGUI
lda PARAM0
and #1
bne .found
pla
inc
.max=*+1
cmp #$FD ; SMC
bcc -
!byte $2C
.found pla
clc
rts
}

View File

@ -363,7 +363,7 @@ kViewHints
!byte 66 ; left
!byte 10 ; top
!byte 13 ; width
!word callback_clues ; callback
!word callback_hints ; callback
!word kStringHints ; caption
kStringHints
!byte $08 ; 'H' inverse
@ -377,8 +377,8 @@ kViewVersions
!word callback_versions ; callback
!word kStringVersions ; caption
kStringVersions
!byte $12 ; 'R' inverse
!text "evisions",0
!byte $16 ; 'V' inverse
!text "ersion",0
kViewInfo
!byte ID_INFO ; view ID

View File

@ -27,6 +27,8 @@ ID_Z = $85
!byte $E8,ID_HINTS ; h
!byte $C1,ID_BOXART ; A
!byte $E1,ID_BOXART ; a
!byte $D6,ID_VERSIONS ; V
!byte $F6,ID_VERSIONS ; v
!byte $D3,ID_OPTIONS ; S
!byte $F3,ID_OPTIONS ; s
!byte $D0,ID_PREVIOUS ; P
@ -206,11 +208,9 @@ callback_next
jmp LoadGameInfo ; load new game info first
}
callback_versions
rts
callback_boxart = DisplayArtwork
callback_options = OptionsDialog
callback_clues = LaunchInterpreterWithHints
callback_play = LaunchInterpreterWithGame
callback_resume = ResumeDialog
callback_resume = LaunchInterpreterWithGame
callback_boxart = DisplayArtwork
callback_hints = LaunchInterpreterWithHints
callback_versions = VersionsDialog

View File

@ -83,11 +83,11 @@ OptionsDialog
ldx #WGDesktop ; paint background
jsr WeeGUI
jsr PaintTitleBar ; paint top title bar
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_OPTIONS_FRAME
jsr WeeGUI
@ -105,13 +105,16 @@ OptionsDialog
!byte 6,18
!word kStringAutoScriptDescription
bit $C010 ; clear keyboard strobe
ldx #WGClearPendingClick ; clear WeeGUI mouse strobe
jsr WeeGUI
.runLoop
ldx #WGPendingViewAction
jsr WeeGUI
jsr WeeGUI ; handle mouse movement and clicks
lda $C000
bpl .runLoop
bit $C010
jsr HandleOptionsKey
jsr HandleOptionsKey ; handle keypresses
bra .runLoop
;------------------------------------------------------------------------------

View File

@ -67,40 +67,43 @@ ResumeDialog
ldx #WGResetAll ; reset WeeGUI
jsr WeeGUI
ldx #WGCreateView ; create frame
+LDADDR kViewResumeFrame
+STAY PARAM0
jsr WeeGUI
ldx #WGViewSetTitle
+LDADDR kStringResumeFrame
+STAY PARAM0
jsr WeeGUI
; TODO call ZINFO and calculate proper height
ldy #3
sty kViewResumeFrame+3 ; frame top
iny
sty kViewResumeOK+2 ; OK top
iny
iny
sty kViewResumeCancel+2 ; Cancel top
ldy #19
sty kViewResumeFrame+5 ; frame visible height
sty kViewResumeFrame+7 ; frame height
jsr CreateDialog
!word kViewResumeFrame
!word kStringResumeFrame
jsr CreateButton ; create UI controls
!word kViewOK
!word kViewResumeOK
jsr CreateButton
!word kViewCancel
jsr CreateCheckbox
!word kViewForce40
jsr CreateCheckbox
!word kViewForceUpper
jsr CreateCheckbox
!word kViewScriptToFile
jsr CreateCheckbox
!word kViewAutoScript
!word kViewResumeCancel
jsr SetCheckboxByPref ; set initial state of checkboxes based on preferences
!byte ID_RESUME_FORCE40
!word kForce40
jsr SetCheckboxByPref
!byte ID_RESUME_FORCEUPPER
!word kForceUpper
jsr SetCheckboxByPref
!byte ID_RESUME_SCRIPTTOFILE
!word kScriptToFile
jsr SetCheckboxByPref
!byte ID_RESUME_AUTOSCRIPT
!word kAutoScript
jsr CreateRadio
!word kViewResumeSlot0
jsr CreateRadio
!word kViewResumeSlot1
jsr CreateRadio
!word kViewResumeSlot2
jsr CreateRadio
!word kViewResumeSlot3
jsr CreateRadio
!word kViewResumeSlot4
jsr CreateRadio
!word kViewResumeSlot5
jsr CreateRadio
!word kViewResumeSlot6
jsr CreateRadio
!word kViewResumeSlot7
ldx #WGDesktop ; paint background
jsr WeeGUI
@ -114,63 +117,19 @@ ResumeDialog
lda #ID_RESUME_FRAME
jsr WeeGUI
ldx #WGSetCursor ; paint static text labels
lda #6
sta PARAM0
lda #3
sta PARAM1
jsr WeeGUI
ldx #WGPrint
+LDADDR kStringForce40Description
+STAY PARAM0
jsr WeeGUI
ldx #WGSetCursor
lda #6
sta PARAM0
lda #8
sta PARAM1
jsr WeeGUI
ldx #WGPrint
+LDADDR kStringForceUpperDescription
+STAY PARAM0
jsr WeeGUI
ldx #WGSetCursor
lda #6
sta PARAM0
lda #13
sta PARAM1
jsr WeeGUI
ldx #WGPrint
+LDADDR kStringScriptToFileDescription
+STAY PARAM0
jsr WeeGUI
ldx #WGSetCursor
lda #6
sta PARAM0
lda #18
sta PARAM1
jsr WeeGUI
ldx #WGPrint
+LDADDR kStringAutoScriptDescription
+STAY PARAM0
jsr WeeGUI
.runLoop
ldx #WGPendingViewAction
jsr WeeGUI
lda $c000
bpl .runLoop
bit $c010
jsr HandleOptionsKey
jsr HandleResumeKey
bra .runLoop
;------------------------------------------------------------------------------
; internal functions
HandleOptionsKey
HandleResumeKey
ldx #.endkeys-.keys
- cmp .keys,x
beq .foundKey
@ -182,92 +141,124 @@ HandleOptionsKey
lda .keys+1,x
ldx #WGSelectView
jsr WeeGUI
ldx #WGViewFocus
jsr WeeGUI
ldx #WGViewFocusAction
jsr WeeGUI
ldx #WGViewUnfocus
jmp WeeGUI
callback_resume_ok
callback_resume_cancel
jmp MainScreen
jmp SimulateClick
callback_resume_ok = LaunchInterpreterWithGame
callback_resume_cancel = MainScreen
kViewResumeFrame
!byte ID_RESUME_FRAME ; view ID
!byte 2 ; style (decorated frame)
!byte $FD ; left
!byte 5 ; left
!byte $FD ; top
!byte $FD ; visible width
!byte 70 ; visible width
!byte $FD ; visible height
!byte 56 ; width
!byte 19 ; height
!byte 70 ; width
!byte $FD ; height
kStringResumeFrame
!text "Resume Game",0
kViewOK
kViewResumeOK
!byte ID_RESUME_OK ; view ID
!byte $FD ; left
!byte 63 ; left
!byte $FD ; top
!byte 10 ; width
!word callback_resume_ok ; callback
!word callback_resume_ok ; callback
!word kStringOK ; caption
kViewCancel
!byte ID_RESUME_CANCEL ; view ID
!byte 56 ; left
!byte 6 ; top
kViewResumeCancel
!byte ID_RESUME_CANCEL ; view ID
!byte 63 ; left
!byte $FD ; top
!byte 10 ; width
!word callback_resume_cancel ; callback
!word kStringCancel ; caption
kViewForce40
!byte ID_RESUME_FORCE40 ; view ID
!byte 14 ; left
kViewResumeSlot0
!byte ID_RESUME_SLOT0 ; view ID
!byte 8 ; left
!byte 4 ; top
!word kStringForce40 ; caption
kStringForce40
!text "Force "
!word kStringSlot0 ; caption
kStringSlot0
!text " Slot "
!byte $30 ; '0' inverse
!text ":",0
kViewResumeSlot1
!byte ID_RESUME_SLOT1 ; view ID
!byte 8 ; left
!byte 6 ; top
!word kStringSlot1 ; caption
kStringSlot1
!text " Slot "
!byte $31 ; '1' inverse
!text ":",0
kViewResumeSlot2
!byte ID_RESUME_SLOT2 ; view ID
!byte 8 ; left
!byte 8 ; top
!word kStringSlot2 ; caption
kStringSlot2
!text " Slot "
!byte $32 ; '2' inverse
!text ":",0
kViewResumeSlot3
!byte ID_RESUME_SLOT3 ; view ID
!byte 8 ; left
!byte 10 ; top
!word kStringSlot3 ; caption
kStringSlot3
!text " Slot "
!byte $33 ; '3' inverse
!text ":",0
kViewResumeSlot4
!byte ID_RESUME_SLOT4 ; view ID
!byte 8 ; left
!byte 12 ; top
!word kStringSlot4 ; caption
kStringSlot4
!text " Slot "
!byte $34 ; '4' inverse
!text "0 column",0
kStringForce40Description
!text "Some games may be glitchy",0
!text ":",0
kViewForceUpper
!byte ID_RESUME_FORCEUPPER ; view ID
!byte 14 ; left
!byte 9 ; top
!word kStringForceUpper ; caption
kStringForceUpper
!text "Force "
!byte $75 ; 'u' inverse
!text "ppercase",0
kStringForceUpperDescription
!text "A MATTER OF PREFERENCE, I SUPPOSE",0
kViewScriptToFile
!byte ID_RESUME_SCRIPTTOFILE ; view ID
!byte 14 ; left
kViewResumeSlot5
!byte ID_RESUME_SLOT5 ; view ID
!byte 8 ; left
!byte 14 ; top
!word kStringScriptToFile ; caption
kStringScriptToFile
!text "SCRIPT to "
!byte $66 ; 'f' inverse
!text "ile",0
kStringScriptToFileDescription
!text "Save transcripts to a file instead of printer",0
!word kStringSlot5 ; caption
kViewAutoScript
!byte ID_RESUME_AUTOSCRIPT ; view ID
!byte 14 ; left
!byte 19 ; top
!word kStringAutoScript ; caption
kStringAutoScript
!text "Always "
!byte $13 ; 'S' inverse
!text "CRIPT",0
kStringAutoScriptDescription
!text "Turn on SCRIPT mode automatically",0
kStringSlot5
!text " Slot "
!byte $35 ; '5' inverse
!text ":",0
kViewResumeSlot6
!byte ID_RESUME_SLOT6 ; view ID
!byte 8 ; left
!byte 16 ; top
!word kStringSlot6 ; caption
kStringSlot6
!text " Slot "
!byte $36 ; '6' inverse
!text ":",0
kViewResumeSlot7
!byte ID_RESUME_SLOT7 ; view ID
!byte 8 ; left
!byte 18 ; top
!word kStringSlot7 ; caption
kStringSlot7
!text " Slot "
!byte $37 ; '7' inverse
!text ":",0
}

412
src/ui.versions.a Normal file
View File

@ -0,0 +1,412 @@
;license:MIT
;(c) 2018 by 4am
;
; User interface - views and paint routines for versions screen
;
; Public functions
; - VersionsDialog
;
!zone {
; View IDs (application-specific, acceptable range 0..15, no duplicates)
ID_VERSIONS_FRAME = 0
ID_VERSIONS_1 = 1 ; WARNING lots of logic in this screen assumes that the radio
ID_VERSIONS_2 = 2 ; buttons for each version are sequentially numbered starting at 1
ID_VERSIONS_3 = 3 ; and it would be very difficult to untangle if that suddenly
ID_VERSIONS_4 = 4 ; stopped being true
ID_VERSIONS_5 = 5
ID_VERSIONS_6 = 6
ID_VERSIONS_7 = 7
ID_VERSIONS_8 = 8
ID_VERSIONS_9 = 9
ID_VERSIONS_OK = 10
ID_VERSIONS_CANCEL = 11
gVersionsViewInUse
!byte 1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0
; action keys for options screen
.keys
!byte $CF,ID_VERSIONS_OK ; O
!byte $EF,ID_VERSIONS_OK ; o
!byte $8D,ID_VERSIONS_OK ; Return
!byte $C3,ID_VERSIONS_CANCEL; C
!byte $E3,ID_VERSIONS_CANCEL; c
!byte $9B,ID_VERSIONS_CANCEL; Esc
!byte $B1,ID_VERSIONS_1 ; 1
!byte $B2,ID_VERSIONS_2 ; 2
!byte $B3,ID_VERSIONS_3 ; 3
!byte $B4,ID_VERSIONS_4 ; 4
!byte $B5,ID_VERSIONS_5 ; 5
!byte $B6,ID_VERSIONS_6 ; 6
!byte $B7,ID_VERSIONS_7 ; 7
!byte $B8,ID_VERSIONS_8 ; 8
!byte $B9,ID_VERSIONS_9 ; 9
!byte $88,ID_VERSIONS_PREVIOUS ; left arrow
!byte $95,ID_VERSIONS_NEXT ; right arrow
!byte $8B,ID_VERSIONS_PREVIOUS ; up arrow
!byte $8A,ID_VERSIONS_NEXT ; down arrow
.endkeys
; IDs of actions that do not correspond to WeeGUI view IDs have high bit set
ID_VERSIONS_PREVIOUS = $81
ID_VERSIONS_NEXT = $82
;------------------------------------------------------------------------------
; VersionsDialog
; call WeeGUI to create and paint 'select version' dialog, and run to completion
;
; in: WeeGUI initialized
; out: exits via MainScreen
; all registers and flags clobbered
;------------------------------------------------------------------------------
VersionsDialog
ldx #$FF
txs
ldx #WGResetAll ; reset WeeGUI
jsr WeeGUI
ldx #9
- stz gVersionsViewInUse,x ; reset flags for which radio buttons are in use (1-9)
dex
bne -
jsr okvs_len
!word gVersionsStore
sta .numVersions
; TODO calculate proper height based on number of available versions
ldy #3
sty kViewVersionsFrame+3 ; frame top
iny
sty kViewVersionsOK+2 ; OK top
iny
iny
sty kViewVersionsCancel+2 ; Cancel top
ldy #19
sty kViewVersionsFrame+5 ; frame visible height
sty kViewVersionsFrame+7 ; frame height
jsr CreateDialog
!word kViewVersionsFrame
!word kStringVersionsFrame
jsr CreateButton ; create UI controls
!word kViewVersionsOK
jsr CreateButton
!word kViewVersionsCancel
ldx #0
.createRadioLoop
phx
lda #1
sta gVersionsViewInUse+1,x ; mark this view as in use so hotkeys will activate
txa
asl
tax
lda kVersions,x
ldy kVersions+1,x
+STAY +
jsr CreateRadio ; create radio button for this version (will print label later)
+ !word $FDFD ; SMC
plx
inx
.numVersions=*+1
cpx #$FD ; SMC
bne .createRadioLoop
jsr okvs_get ; get current version of current game and check appropriate radio button
!word gGlobalPrefsStore
!word kLastPlayed
+STAY +
jsr okvs_get
!word gGlobalPrefsStore
+ !word $FDFD ; SMC
+STAY +
jsr okvs_get
!word gVersionsStore
+ !word $FDFD ; SMC
; X = 0-based index of current version in the list of versions for this game
inx ; X = 1-based index of current version, which is the WeeGUI view ID
txa
ldx #WGSelectView
jsr WeeGUI
lda #1
sta PARAM0
ldx #WGSetState
jsr WeeGUI
ldx #WGDesktop ; paint background
jsr WeeGUI
jsr PaintTitleBar ; paint top title bar
ldx #WGViewPaintAll ; paint UI controls (window frame, buttons, checkboxes, radio buttons)
jsr WeeGUI
ldx #WGSelectView ; select frame (required for print routines that follow)
lda #ID_VERSIONS_FRAME
jsr WeeGUI
lda #1
sta .vtab
ldx #0
.printLabelsLoop
phx
stx +
jsr okvs_nth
!word gVersionsStore
+ !byte $FD ; SMC
+STAY +
jsr okvs_get
!word gVersionsStore
+ !word $FDFD ; SMC
ldx #50
jsr CreateNullTerminatedString
jsr PrintAt
!byte 7
.vtab !byte $FD ; SMC
!word kNullTerminatedBuffer
inc .vtab
inc .vtab
plx
inx
cpx .numVersions
bne .printLabelsLoop
bit $C010 ; clear keyboard strobe
ldx #WGClearPendingClick ; clear WeeGUI mouse strobe
jsr WeeGUI
.runLoop
ldx #WGPendingViewAction
jsr WeeGUI ; handle mouse movement and clicks
lda $C000
bpl .runLoop
bit $C010
jsr HandleVersionsKey ; handle keypresses
bra .runLoop
;------------------------------------------------------------------------------
; internal functions
HandleVersionsKey
ldx #.endkeys-.keys
- cmp .keys,x
beq .foundKey
dex
dex
bpl -
.notFound
jmp SoftBell
.foundKey
lda .keys+1,x ; get ID associated with this key
bpl .activateView ; ID < #$80 is a WeeGUI view, so activate it
sta .keyID ; ID >= #$80 is a screen-specific action, so stash it for now
jsr GetCheckedVersion ; figure out which radio button is checked
ldx #WGSelectView ; uncheck it and repaint it
jsr WeeGUI
stz PARAM0
ldx #WGSetState
jsr WeeGUI
ldx #WGPaintView
jsr WeeGUI
tax ; X = WeeGUI view ID of previously checked radio button
.keyID=*+1
lda #$FD ; SMC
cmp #ID_VERSIONS_PREVIOUS
beq .previous
cpx .numVersions ; find 'next' view ID (wrapping around to 1)
bcs +
inx
!byte $2C
+ ldx #1
bra .gotNewID
.previous
dex
bne .gotNewID
ldx .numVersions
.gotNewID
txa
ldx #WGSelectView ; check new radio button and repaint it
jsr WeeGUI
ldx #WGViewFocus
jsr WeeGUI
ldx #WGSetState
lda #1
sta PARAM0
jsr WeeGUI
ldx #WGPaintView
jmp WeeGUI
.activateView
tax
ldy gVersionsViewInUse,x
beq .notFound
ldx #WGSelectView
jsr WeeGUI
jmp SimulateClick
GetCheckedVersion
lda #ID_VERSIONS_1
pha
clc
adc .numVersions ; .numVersions was populated during VersionsDialog and hasn't changed since
tay
pla
jmp GetCheckedRadioButton
callback_versions_ok
jsr GetCheckedVersion
dec
sta .n
jsr okvs_nth
!word gVersionsStore
.n !byte $FD ; SMC
+STAY .val
jsr okvs_get
!word gGlobalPrefsStore
!word kLastPlayed
+STAY .key
jsr okvs_update
!word gGlobalPrefsStore
.key !word $FDFD ; SMC
.val !word $FDFD ; SMC
lda #1
sta gGlobalPrefsDirty ; must set, otherwise SaveGlobalPreferences does nothing
jsr SaveGlobalPreferences ; immediately write new preferences to disk
jsr CheckForSavedGames ; recheck whether the (newly selected) version has saved games (affects painting in main screen)
; execution falls through here
callback_versions_cancel
jmp MainScreen
kViewVersionsFrame
!byte ID_VERSIONS_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
kStringVersionsFrame
!text "Select Version",0
kViewVersionsOK
!byte ID_VERSIONS_OK ; view ID
!byte 63 ; left
!byte $FD ; top
!byte 10 ; width
!word callback_versions_ok ; callback
!word kStringOK ; caption
kViewVersionsCancel
!byte ID_VERSIONS_CANCEL ; view ID
!byte 63 ; left
!byte $FD ; top
!byte 10 ; width
!word callback_versions_cancel ; callback
!word kStringCancel ; caption
kVersions
!word kViewVersions1
!word kViewVersions2
!word kViewVersions3
!word kViewVersions4
!word kViewVersions5
!word kViewVersions6
!word kViewVersions7
!word kViewVersions8
!word kViewVersions9
kViewVersions1
!byte ID_VERSIONS_1 ; view ID
!byte 8 ; left
!byte 4 ; top
!word kString1 ; caption
kString1
!text " "
!byte $31,0 ; '1' inverse
kViewVersions2
!byte ID_VERSIONS_2 ; view ID
!byte 8 ; left
!byte 6 ; top
!word kString2 ; caption
kString2
!text " "
!byte $32,0 ; '2' inverse
kViewVersions3
!byte ID_VERSIONS_3 ; view ID
!byte 8 ; left
!byte 8 ; top
!word kString3 ; caption
kString3
!text " "
!byte $33,0 ; '3' inverse
kViewVersions4
!byte ID_VERSIONS_4 ; view ID
!byte 8 ; left
!byte 10 ; top
!word kString4 ; caption
kString4
!text " "
!byte $34,0 ; '4' inverse
kViewVersions5
!byte ID_VERSIONS_5 ; view ID
!byte 8 ; left
!byte 12 ; top
!word kString5 ; caption
kString5
!text " "
!byte $35,0 ; '5' inverse
kViewVersions6
!byte ID_VERSIONS_6 ; view ID
!byte 8 ; left
!byte 14 ; top
!word kString6 ; caption
kString6
!text " "
!byte $36,0 ; '6' inverse
kViewVersions7
!byte ID_VERSIONS_7 ; view ID
!byte 8 ; left
!byte 16 ; top
!word kString7 ; caption
kString7
!text " "
!byte $37,0 ; '7' inverse
kViewVersions8
!byte ID_VERSIONS_8 ; view ID
!byte 8 ; left
!byte 18 ; top
!word kString8 ; caption
kString8
!text " "
!byte $38,0 ; '8' inverse
kViewVersions9
!byte ID_VERSIONS_9 ; view ID
!byte 8 ; left
!byte 20 ; top
!word kString9 ; caption
kString9
!text " "
!byte $39,0 ; '9' inverse
}