Penetrator-apple2/src/apple2/ui.inc

1144 lines
36 KiB
PHP

;-----------------------------------------------------------------------------
; ui.inc
; Part of penetrator, the zx spectrum game, made for Apple II
;
; Stefan Wessels, 2019
; This is free and unencumbered software released into the public domain.
;-----------------------------------------------------------------------------
.segment "CODE"
;-----------------------------------------------------------------------------
.proc uiTitleScreen
zaCounterL = tempBlock + 17 ; timer for flipping text
zaCounterH = tempBlock + 18
zaState = tempBlock + 19 ; which text to show
lda #0
bit KBDSTRB ; flush the keyboard buffer before uiWriteName
sta lastInput
jsr drawClearScreen
jsr uiWriteName ; also looks for a key press
jsr uiShowHighScores
jsr drawPresent ; present and
jsr uiShowHighScores ; show again so it's on both layers
loopo:
lda #0 ; set all keys to down for joystick
bit KBDSTRB
sta lastInput ; debounce the last key if it was a joy button
sta zaCounterL
sta zaState
loop:
lda #$08
sta zaCounterH
lda zaState
bne :+
print textPhilip , #(00), #(8*21) ; the text shows in 3 stages
print textCopyright, #(00), #(8*22)
lda zaState
:
cmp #1
bne :+
print textApple2 , #(00), #(8*21)
print textStefan , #(00), #(8*22)
lda zaState
:
cmp #2
bne :+
print textSupport , #(00), #(8*21)
print textOliver , #(00), #(8*22)
lda zaState
:
cmp #3
bne :+
print textSource , #(00), #(8*21)
print textGitHub , #(00), #(8*22)
:
jsr drawPresent ; show the sceen
:
jsr inputCheckForInput ; wait for user interaction
bne done
dec zaCounterL
bne :-
dec zaCounterH
bne :-
inc zaState
lda zaState
cmp #4
bcc :+
jmp loopo
:
jmp loop
done:
rts
.endproc
;-----------------------------------------------------------------------------
.proc uiShowHighScores
zaStrL = tempBlock + 1
zaStrH = tempBlock + 2
zaForce = tempBlock + 3
textX = tempBlock + 10
textY = tempBlock + 11
scorePtrL = tempBlock + 14 ; 2 + 3 used by textOut
scorePtrH = tempBlock + 15
scoreIdx = tempBlock + 16
scoreShown = tempBlock + 17
lda #<highScores ; set up a pointer to the scores
sta scorePtrL
lda #>highScores
sta scorePtrH
lda #0 ; and init two counters
sta scoreIdx ; which high-score is being processed
sta scoreShown ; were any high-scores printed
loop:
ldy #3 ; 3 bytes to a score
ldx #0 ; don't force a number
lda scorePtrL ; get the score to convert
sta zaStrL
lda scorePtrH
sta zaStrH
jsr textBCDtoSZ ; convert it
dex ; step back from the null-terminator
lda textNumber, x ; get the last character out
cmp #' ' ; was it a space
bne show ; no - there was a score so show it
beq heading ; as soon as there's no score there won't be any more
next:
inc scoreIdx ; go to next score
lda scoreIdx
cmp #5 ; all 5 scores shown?
bcc cont ; if not, carry on processing
heading:
lda scoreShown ; were any score printed
beq done ; if not, nothing more
print textHighScores, #(11), #(8*0) ; Show the scores' heading
done:
rts
cont:
lda scorePtrL ; advance the score ptr to the next 3 bytes
adc #3
sta scorePtrL
bcc loop
inc scorePtrH
bne loop ; JuMP
show: ; a high-score was set, so show it
inc scoreShown
inx ; back to the null terminator
lda #'0' ; Show score as 10x the actual score
sta textNumber, x ; append the 0 to the buffer
ldx scoreIdx ; get the index of which score
lda #<textNumber ; print the converted score text
sta zaStrL
lda #>textNumber
sta zaStrH
lda scorePosX, x ; get the X position of where
sta textX
lda scoreTextPosY, x ; and the Y position
sta textY
jsr textOut ; now render the text
ldx scoreIdx ; get the score index again
lda scoreTextOffset, x ; and figure out the start of the name text for this score
clc
adc #<textHS ; offset from where the names are stored
sta zaStrL
lda #0
adc #>textHS
sta zaStrH
lda scoreTextPosX, x ; get the x position
sta textX
lda scoreTextPosY, x ; and the y position
sta textY
jsr textOut ; and render the text
jmp next ; and go to the next score
.endproc
;-----------------------------------------------------------------------------
; Uses line drawing to spell out the Penetrator logo
.proc uiWriteName
x0 = tempBlock + 0 ; local variables
x1 = tempBlock + 1
y0 = tempBlock + 2
y1 = tempBlock + 3
dx = tempBlock + 4
dy = tempBlock + 5
sx = tempBlock + 6
sy = tempBlock + 7
dyNeg = tempBlock + 8
err = tempBlock + 9
err2 = tempBlock + 10
index = tempBlock + 11
remain = tempBlock + 12
skip = tempBlock + 13
width = tempBlock + 14
height = tempBlock + 15
lda #0
sta audioExplFrame ; use this as a delay counter for logo sound
lda #((dataLogoLinesEnd - dataLogoLines) / 4)
sta remain
ldx #0
stx index ; current line
stx skip ; impatient user
lda #1 ; set up the plot
sta width
lda #1
sta height
loop:
dec remain ; iterate over all lines
bpl :+
lda #0
sta audioExplFrame
rts
:
ldx index
lda dataLogoLines,x ; Load x0,y0 x1,y1 into variables
sta x0
inx
lda dataLogoLines,x
sta y0
inx
lda dataLogoLines,x
sta x1
inx
lda dataLogoLines,x
sta y1
inx
stx index ; update the index to next line params
ldy #2 ; dx = abs(x1-x0) - sx=2
lda x1
sec
sbc x0
bcs :+ ; x1 >= x0
eor #$ff ; abs
adc #1
ldy #0 ; sx=0
:
sta dx
dey ; sx=-1|1
sty sx
ldy #2 ; dy = abs(y1-y0) - sy=2
lda y1
sec
sbc y0
bcs :+ ; y1 >= y0
eor #$ff ; abs
adc #1
ldy #0 ; sy=0
sec
:
sta dy
lda #0
sbc dy
sta dyNeg ; = -dy
dey ; sy=-1|1
sty sy
lda dx ; err = dx-dy
sec
sbc dy
sta err
plot:
ldx x0
ldy y0
jsr drawPlotXY ; plot a "pixel" at x y
jsr drawPresent ; present this plot
ldx x0 ; do for the 2nd buffer the same
ldy y0
jsr drawPlotXY
lda skip ; if key/button pressed - fast draw logo
bne :+
lda audioMask
beq nosnd
snd:
ldy audioExplFrame
ldx #4
jsr playNote ; play the note
dec audioExplFrame ; alter the note
dec audioExplFrame
bmi nosnd ; variable decay so that the duration
dec audioExplFrame ; is a close match to when the logo ends
dec audioExplFrame
nosnd:
jsr inputCheckForInput ; check for user interaction
sta skip
bne :+
wait #$01
:
lda x0 ; if(x0=x1 && y0=y1) done
cmp x1
bne :+
lda y0
cmp y1
bne :+
jmp loop
:
lda err ; e2 = err << 1
asl
sta err2
lda dyNeg ; if(e2 > -dy)
sec
sbc err2
bpl :+
lda err ; err = err - dy
sec
sbc dy
sta err
lda x0 ; x0 = x0 + sx
clc
adc sx
sta x0
:
lda dx ; if(e2 < dx)
sec
sbc err2
bpl :+
jmp plot
:
lda err ; err = err + dx
clc
adc dx
sta err
lda y0 ; y0 = y0 + sy
clc
adc sy
sta y0
jmp plot
.endproc
;-----------------------------------------------------------------------------
; Shows the main menu and waits for user choice
.proc uiMainMenu
jsr drawClearScreen
redraw:
print textInstructions, #(10), #(8*04)
print textPress , #(13), #(8*08)
print textUnderline , #(13), #(8*09)
print textOneTwo , #(00), #(8*11)
print textTrain , #(00), #(8*12)
print textEdit , #(02), #(8*13)
print textLoad , #(01), #(8*14)
print textSirens , #(05), #(8*15)
print textQuit , #(12), #(8*16)
lda audioMask
beq none
bit Bit8432Mask
bne :+
print textAudio2 , #(20), #(8*15)
jmp present
:
print textAudio1 , #(20), #(8*15)
jmp present
none:
print textAudio3 , #(20), #(8*15)
present:
jsr drawPresent
lda #GAME_MODE_PLAY ; assume the player will play (play is 0)
sta gameMode
sta stage ; and set the stage to 0
sta lastInput
loop:
lda #(optionsEnd-options) ; how many options on this menu
ldx #<options ; x - lo options "string"
ldy #>options ; y - hi options "string"
jsr uiHandleOptions ; on return, x is the option selected (0 based)
cpx #(optionsEnd-options) + 1
bne :+
rts
:
cpx #2 ; 0 & 1 for 1/2 player game
bcs train ; greater means another option
stx numPlayers ; x happens to be the value for numPlayers
jmp gamePlay ; go gameplay and return to title screen
train:
bne edit ; still on the cpx #2 here
jmp uiTrainerMode ; 2 means train, and then return to title screen
edit:
cpx #3
bne load
jsr editLoop ; 3 means edit
jmp uiMainMenu ; and go to main menu, not title
load:
cpx #4
bne sirens
lda #1 ; 1 means load
jsr uiFileLoadSave ; call the code to do file name and load
jmp uiMainMenu
sirens: ; For Apple II this is the "set sound type"
cpx #5
bne quit
lda audioMask
beq audioSetAll
bit Bit8432Mask
bne :+
lda #0
beq :++
:
lda #(AUDIO_EXPLOSION | AUDIO_BOMB_DROP | AUDIO_FIRE | AUDIO_UI_TICK)
bne :+
audioSetAll:
lda #%01111111
:
sta audioMask
jmp redraw
quit:
inc PWREDUP ; Make sure this isn't a power vector
jsr MLI ; call the prodos mli ($bf00) - never returns here
.byte QUIT_CALL ; call type = quit
.addr quitParam ; pointer to parameter table
quitParam:
.byte 4 ; number of parameters is 4
.byte 0 ; quit type
.word 0000 ; reserved
.byte 0 ; reserved
.word 0000 ; reserved
options: .byte "12TELSQ"
optionsEnd:
.endproc
;-----------------------------------------------------------------------------
; Shows the trainer menu asking for a stage to train (1-4). Allows
; backspace to go back to main menu
.proc uiTrainerMode
jsr drawClearScreen
print textTrainingMode, #(11), #(8*04)
print textPressStage , #(02), #(8*12)
print textOneToFour , #(08), #(8*13)
print textBackup , #(03), #(8*23)
jsr drawPresent
lda #GAME_MODE_TRAIN
sta gameMode
lda #(optionsEnd-options)
ldx #<options
ldy #>options
jsr uiHandleOptions
cpx #4 ; backspace option
bcc stageSel
cpx #(optionsEnd-options)+1 ; time out goes to title, not main menu like backup
bne :+
rts
:
jmp uiMainMenu ; on backspace go back to main menu
stageSel:
stx stage
jmp gamePlay
rts
options: .byte "1234", $1b ; $1b is ESC
optionsEnd:
.endproc
;-----------------------------------------------------------------------------
; Take the number of options in accumulator
; Take a pointer to a number of options in x (lo) y (hi)
; returns when an option was selected, the index of the selected option in x
.proc uiHandleOptions
sta len + 1 ; set the length for the number of options to look at
stx option + 1 ; set address of the options "string"
sty option + 2
lda #0
bit KBDSTRB ; flush the keyboard buffer
sta lastInput
loop:
jsr inputCheckForInput ; get the input
beq loop ; no input keep looping
bit KBDSTRB ; reset the keyboard buffer
cmp len + 1 ; if a >= num options
bcs len ; then it's a keyboard menu
tax ; it's a joystick selection
dex ; so 0 based, x-1 is the chosen option
rts ; done
len:
ldx #0 ; placeholder 0
option:
cmp PLACEHOLDER,x ; placeholder address
beq done ; compare the keyboard to the options
dex
bpl option ; check all options
bmi loop ; when x is -1 it was an invalid entry so loop back
done:
rts ; x contains the number of the chosen option
.endproc
;-----------------------------------------------------------------------------
.proc uiShowEditHelp
lda #0 ; clear the keyboard buffer
bit KBDSTRB
sta lastInput
jsr drawClearScreen ; clear the screen
print textEdtHlp01, #(04), #(8*00) ; show all the help text
print textEdtHlp02, #(04), #(8*01)
print textEdtHlp03, #(00), #(8*03)
print textEdtHlp04, #(00), #(8*05)
print textEdtHlp05, #(00), #(8*06)
print textEdtHlp06, #(00), #(8*08)
print textEdtHlp07, #(00), #(8*09)
print textEdtHlp08, #(00), #(8*11)
print textEdtHlp09, #(00), #(8*12)
print textEdtHlp10, #(00), #(8*14)
print textEdtHlp11, #(00), #(8*15)
print textEdtHlp12, #(00), #(8*17)
print textEdtHlp13, #(00), #(8*18)
print textEdtHlp14, #(00), #(8*19)
print textEdtHlp15, #(04), #(8*21)
print textEdtHlp16, #(04), #(8*22)
print textEdtHlp17, #(03), #(8*23)
jsr drawPresent
:
jsr inputCheckForInput ; wait for the user to dismiss the help
beq :-
jsr drawClearScreen ; clear the screen
lda #2 ; and force a
sta updateHUD ; HUD update
rts
.endproc
;-----------------------------------------------------------------------------
.proc uiWinScreen
cntrl = tempBlock + 14 ; some delay counters, past the text* temporary vars
cntrh = tempBlock + 15
jsr drawClearScreen
lda #$0 ; init the counters - value
sta cntrl
lda #2 ; init the counters - value
sta cntrh ; not important what these are init with
jsr drawPresent
print textBonus , #(13), #(8*00) ; show the win screen text
printBig textPoints, #$08, #$04, #$01, #$01
printBig text1000 , #$03, #$0D, #$02, #$02
lda stage ; last word changes for home vs victory
beq :+
printBig textWow , #$02, #$1D, #$03, #$03
jmp present
:
printBig textHome , #$04, #$1D, #$02, #$03
present:
jsr drawPresent
lda #0
bit KBDSTRB ; flush the keyboard buffer
sta lastInput
loop:
dec cntrl
bne :+
dec cntrh
bne :+
ldy #$0
sty cntrl
ldy #2
sty cntrh
jsr drawInvertVisibleScreen
:
jsr inputCheckForInput
beq loop ; exit on a key / button
done:
rts
.endproc
;-----------------------------------------------------------------------------
; Show the portions of the HUD that don't change between runs
.proc uiShowGameLabels
lda #2 ; mark the HUD as needing update
sta updateHUD
loop:
print textTopLine , #(00), #(8*00)
print textPlayerNum, #(17), #(8*00)
print textDanger , #(00), #(8*23)
lda gameMode
bne :+
print textShips , #(23), #(8*23)
beq show ; JuMP to show - print always leaves with Z flag set
:
print textTrainer , #(24), #(8*23)
show:
jsr uiUpdateGameHud
jsr drawPresent
lda updateHUD
beq done
jmp loop
done:
rts
.endproc
;-----------------------------------------------------------------------------
; show the HUD variables that change over time
.proc uiUpdateGameHud
clc ; prep the HUD text for the stage
lda stage
adc #'1' ; zero based but HUD display 1-5 not 0-4
sta textStage
print textStage , #(06), #(8*00)
print textDangerBar, #(06), #(8*23)
printBCD score , #3, #0, #(25), #(8*00)
lda gameMode
bne :+
printBCD lives , #1, #1, #(30), #(8*23)
:
dec updateHUD ; dec "show" counter
rts
.endproc
;-----------------------------------------------------------------------------
; Show the portions of the HUD that don't change between runs
.proc uiShowEditLabels
brushType = tempBlock + 16
lda #2 ; mark the HUD as needing update
sta updateHUD
clc ; prep the HUD text for the stage
lda stage
adc #'1' ; zero based but HUD display 1-5 not 0-4
sta textStage
loop:
print textEditStage , #(05), #(8*00)
print textStage , #(12), #(8*00)
print textEditHelp , #(01), #(8*23)
print textEditBrush , #(19), #(8*00)
lda brushType
bne modeEnemy
print textEditTerrain, #(26), #(8*00)
jmp :+
modeEnemy:
print textEditEnemies, #(26), #(8*00)
:
jsr drawPresent
dec updateHUD ; dec "show" counter
beq done
jmp loop
done:
rts
.endproc
;-----------------------------------------------------------------------------
.proc uiCheckHighScore
scoreIdx = tempBlock + 16
clc
lda score ; make sure one of the score components is non-zero
adc score + 1 ; because a zero score is not high-score eligible
adc score + 2
bne didScore
rts
didScore:
lda #((highScoresEnd-highScores) / 3) ; score insert point (1 past end of 0 based table)
sta scoreIdx ; save the index
ldx #((highScoresEnd-highScores) - 1) ; point x at the high byte of the last score
nextScore:
ldy #2 ; point y at the high byte of the current score
nextByte:
lda score, y ; get the score byte
cmp highScores, x ; compare to the high score byte
bcc lt ; if it's smaller, then this high-score is bigger than the score
beq eq
: ; score > highscore so ignore remaining bytes in this comparison
dex
dey
bpl:-
bmi gt ; step over this smaller highscore
eq:
dex ; go to the next bytes
dey
bpl nextByte ; look at the whole score
gt:
dec scoreIdx ; the score is bigger than this high score so move "up" one
bne nextScore ; compare against all high-scores in the table
lt:
ldx #((highScoresEnd-highScores) / 3) ; get the index past end
cpx scoreIdx ; see if the scoreIdx still matches
bne newHS ; if not, then a new table entry needs to be made
rts
newHS:
dex ; x now points at last table entry (zero based)
cpx scoreIdx ; see if the score overwrites the last table entry
beq copyScore ; if yes, just copy score over last table entry
jsr uiInsertHighScoreRow ; otherwise scores need to be moved so the score inserts
copyScore:
lda scoreIdx ; calc the offset of the last byte of the score being replaced
asl ; start with index * 2 (and clears carry)
adc scoreIdx ; + index (* 3 now sice 3 bytes / score)
adc #2 ; and add 2 to point at the last byte
tax ; save this offset in x
ldy #2 ; last byte of the score
:
lda score, y ; copy the score
sta highScores, x ; over the high-score
dex ; for all 3 bytes
dey
bpl :-
jsr uiGetHighScoreName ; now get the new name
jmp saveHighScores
.endproc
;-----------------------------------------------------------------------------
; move the score and the name in the highscore table "down" a row
; so the new entry can go into the "space"
; scoreIdx is the number of the row that will move down
.proc uiInsertHighScoreRow
bytes = tempBlock + 15
scoreIdx = tempBlock + 16
rows = tempBlock + 17
lda #(((highScoresEnd-highScores) / 3) - 1) ; Get the length of the table 0 based
sec
sbc scoreIdx ; subtract the insert row
sta rows ; number of rows to move
asl ; mult by 3
adc rows
sta bytes ; that's how many bytes to move
:beq:-
ldy #((highScoresEnd-highScores)-4) ; point at the second last row, last byte
ldx #((highScoresEnd-highScores)-1) ; point at the last row, last byte
scoreLoop:
lda highScores, y ; copy the bytes
sta highScores, x
dex
dey
dec bytes
bne scoreLoop ; till all bytes copied
lda rows ; prep to copy name rows
asl ; * 8 - 1 is * 7 (7 bytes/name - incl null terminator)
asl
asl
sec
sbc rows
sta bytes ; set the number of bytes to copy
ldy #((textHSEnd-textHS)-8) ; point at the second last row, last byte
ldx #((textHSEnd-textHS)-1) ; point at the last row, last byte
nameLoop:
lda textHS, y ; copy the bytes
sta textHS, x
dex
dey
dec bytes
bne nameLoop ; till all bytes copied
rts
.endproc
;-----------------------------------------------------------------------------
; Let the player enter a name for the high score table
; the table entry (0 based) is in scoreIdx when called
.proc uiGetHighScoreName
zaStrL = tempBlock + 1 ; ptr to a string to print
zaStrH = tempBlock + 2
zaEntryL = zWorldPtr ; ptr to a string being entered (abusing world ptr)
zaEntryH = zWorldPtr + 1
scoreIdx = tempBlock + 16 ; 0 based index into score table
entryLen = tempBlock + 17 ; how many characters the player has entered - shared with uiGetUserText
textLen = tempBlock + 18 ; how many characters the player may enter with uiGetUserText
jsr drawClearScreen
clc
ldx scoreIdx ; get the index into the score table
lda #<textHS ; and zaEntry with the start of the
adc scoreTextOffset, x ; 1st byte of where the text must go
sta zaEntryL
lda #0
adc #>textHS
sta zaEntryH
lda #95 ; the "_" character so stomp the current entry with underscores
ldx #((textHighScore2-textHighScore1)-1) ; all scores have the same length
stx textLen ; save how long the name may be
ldy #0 ; start at character 0
:
sta (zaEntryL), y ; write the underscores (also restores the original length)
iny ; by overwriting terminators of old entered text
dex
bne :-
stx entryLen ; save 0 to the length of the new name
showName:
print textCongrats , #(00), #(8*05) ; show the screen
print textHSPlayer , #(10), #(8*06)
print textPlayerNum, #(20), #(8*06)
print textHSPlayer , #(10), #(8*06)
print textTop5 , #(03), #(8*08)
print textTypeName , #(04), #(8*09)
lda zaEntryL ; prep the print string
sta zaStrL ; by using the entry string location
lda zaEntryH ; zaStrL is modified through printing
sta zaStrH ; but the entry copy is stable
printZAStr #(13), #(8*11) ; print the name
jsr drawPresent
jsr uiGetUserText ; Get a character
bcc enter ; on carry clear enter was pressed
jmp showName ; show the updated name
enter:
ldy entryLen ; get how many characters entered
lda #0 ; load a null terminator
sta (zaEntryL), y ; terminate the string
done:
jsr drawClearScreen
rts
.endproc
;-----------------------------------------------------------------------------
; Show a UI screen asking for a file name to load or save
; Parameter in acc. 0 is save and 1 is load
.proc uiFileLoadSave
zaStrL = tempBlock + 1 ; internal - ptr to a string to print
zaStrH = tempBlock + 2 ; internal
zaEntryL = zWorldPtr ; internal - ptr to a string being entered (abusing world ptr)
zaEntryH = zWorldPtr + 1 ; internal
entryLen = tempBlock + 17 ; internal - how many characters the player has entered
textLen = tempBlock + 18 ; internal - how many characters the player may enter
forLoad = tempBlock + 15 ; Parameter - 0 means save, 1 means load
allOver = tempBlock + 16 ; internal - on enter, redraw the screen 1 more time
sta forLoad
jsr drawClearScreen
lda #<textFileName ; point at the file name
sta zaEntryL
lda #>textFileName
sta zaEntryH
lda #((textFileNameEnd - textFileName) - 1) ; get how long the name may be
sta textLen
ldy #0
sty KBDSTRB ; clear the keyboard buffer
sty lastInput ; and the last key
sty allOver ; 1 when the name has been entered - for redraw
: ; get the length of the file name there already
lda (zaEntryL), y ; get the first letter
beq :+ ; if trailing zero then name is known
iny
bne :-
:
sty entryLen ; save the length of the name
lda #95 ; the "_" character so stomp the remaining name with underscores
:
cpy textLen
bcs showName
sta (zaEntryL), y ; write the underscores (also restores the original length)
iny ; by overwriting terminators of old entered text
bne :-
showName:
lda forLoad
beq :+
print textFileLoad , #(12), #(8*02)
print textFileInfoL , #(09), #(8*08)
jmp cont
:
print textFileSave , #(12), #(8*02)
print textFileInfoS , #(09), #(8*08)
cont:
print textFileLines , #(12), #(8*03)
print textFileInfo , #(14), #(8*08)
print textFileEnter , #(05), #(8*10)
lda zaEntryL ; prep the print string
sta zaStrL ; by using the entry string location
lda zaEntryH ; zaStrL is modified through printing
sta zaStrH ; but the entry copy is stable
printZAStr #(11), #(8*14)
lda allOver ; is this the last redraw before going to disc
bne disc ; if <> 0 then time to go to disc
jsr drawPresent ; show the screen with changes to file name
jsr uiGetUserText ; Get a character
bcc enter ; on carry clear enter was pressed
jmp showName ; show the updated name
enter:
ldy entryLen ; get how many characters entered
lda #0 ; and null terminate the string
sta (zaEntryL), y
jsr setWorldFileName
lda #1 ; enter has been pressed - it's all over
sta allOver ; time to attempt a disc action, but just redraw once more
jmp showName
disc:
lda forLoad ; load or save
beq save
jsr loadWorld ; load the file by the name
bcs fail ; if carry set then there's an error
jmp success ; no error - all good
save:
jsr saveWorld ; save the file
bcs fail ; if carry set then there's an error
success:
print textFileSuccess, #(13), #(8*18)
jmp show
fail: ; there was an error saving the file
pha ; error code in the accumulator, so save it
print textFileThe , #(01), #(8*18)
print textFileFailed , #(10), #(8*18)
lda forLoad ; message for load/save differ
beq :+
print textFileInfoL , #(05), #(8*18)
jmp errcde
:
print textFileInfoS , #(05), #(8*18)
errcde:
pla ; get the saved error code
jsr toHex ; print it as human readable hex and show it to the user
print szHex , #(30), #(8*18)
show:
jsr drawPresent ; finally show the whole screen
getkey:
jsr inputCheckForInput ; wait for the user to acknowledge
beq getkey
jsr drawClearScreen ;
rts
.endproc
;-----------------------------------------------------------------------------
; Called with zaEntry pointing at a location to receive some text
; and entryLen should be 0 and is used internally to track where the current
; edit location in the string is.
; returns with partial string when carry set
; User pressed enter and accepted the string when carry clear on return
.proc uiGetUserText
zaEntryL = zWorldPtr ; ptr to a string being entered (abusing world ptr)
entryLen = tempBlock + 17 ; Parameter/Internal - how many characters the player has entered
textLen = tempBlock + 18 ; how many characters the player may enter
lda #0
bit KBDSTRB ; flush the keyboard buffer
loop:
lda KBD ; wait for a key
bit Bit8Mask
beq loop
bit KBDSTRB
pha
lda #AUDIO_UI_TICK
sta audioFrame
jsr serviceAudio
pla
and #$7F
cmp #$0D ; enter key then done
beq enter
cmp #$08 ; backspace key is handled
beq erase
cmp #$20
beq accept ; space is okay
cmp #'0'
bcc loop ; ignore below '0'
cmp #('9'+1)
bcc accept ; 0-9 okay
cmp #'A' ; < 'A' ignore
bcc loop
cmp #('Z'+1)
bcc accept
cmp #'a'
bcc loop
cmp #('z'+1)
bcs loop ; ignore past 'Z'
accept:
; lda theChar
ldy entryLen ; how many characters already entered
cpy textLen ; vs how many can be entered
bcs loop ; already full, don't accept
sta (zaEntryL), y ; and write this character there
inc entryLen ; and increase the length entered
goShow:
sec ; on carry set, not done
rts
erase:
ldy entryLen ; get how many characters have been entered
beq loop ; if none then ignore the backspace key
dec entryLen ; 1 less character entered
dey
lda #95 ; load the underscore
sta (zaEntryL), y ; stomp the last character with the underscore
bne goShow ; redraw the screen
enter:
clc
rts
.endproc