million-perfect-letters/src/ui.main.menu.a
2020-07-10 14:56:07 -04:00

407 lines
10 KiB
Plaintext

;license:MIT
;(c) 2020 by 4am
;
; main menu
;
; Public functions:
; - MainMenu
;
; Codes returned by event handlers
kStayOnMainMenu = 0
kRequestedQuit = 1
kStartPlaying = 2
kMainMenuKeys ; must keep in sync with kMainMenuKeyHandlersLo/Hi arrays
; except for last byte ($00) which doesn't need an associated handler
!byte $0D ; Return
!byte $43 ; C/c
!byte $03 ; Ctrl-C
!byte $53 ; S/s
!byte $13 ; Ctrl-S
!byte $2F ; /
!byte $3F ; ?
!byte $51 ; Q/q
!byte $11 ; Ctrl-Q
!byte $1B ; Esc
!byte $00
kMainMenuKeyHandlersLo
!byte <MainMenuEventReturn
!byte <MainMenuEventC
!byte <MainMenuEventC
!byte <MainMenuEventS
!byte <MainMenuEventS
!byte <MainMenuEventQuestion
!byte <MainMenuEventQuestion
!byte <MainMenuEventQ
!byte <MainMenuEventQ
!byte <MainMenuEventQ
kMainMenuKeyHandlersHi
!byte >MainMenuEventReturn
!byte >MainMenuEventC
!byte >MainMenuEventC
!byte >MainMenuEventS
!byte >MainMenuEventS
!byte >MainMenuEventQuestion
!byte >MainMenuEventQuestion
!byte >MainMenuEventQ
!byte >MainMenuEventQ
!byte >MainMenuEventQ
MainMenuEventLoop
; in: C clear if screen is already cleared and title is already drawn
; (will happen if animated title screen runs to completion)
; C set if full screen clear & redraw is required
; (will happen if key is pressed during title screen, or
; if user returns to main menu from play or any other screen)
; out: C clear if user selected a world to play, and
; A = world ID
; C set if user selected quit
bcc +
jsr DrawMainMenuTitle
+ jsr DrawMainMenuText
bit CLEARKBD
+LDADDR MainMenuMusic
jsr LoopSound
bit CLEARKBD
and #$7F
cmp #$7B
bcs +
cmp #$61
bcc +
sbc #$20 ; a-z -> A-Z
+ sta gLastKeyPressed
ldx #0
- ldy kMainMenuKeys, x
beq MainMenuEventLoop
cpy gLastKeyPressed
beq @dispatch
inx
bne -
beq MainMenuEventLoop
@dispatch
lda kMainMenuKeyHandlersLo, x
sta @j+1
lda kMainMenuKeyHandlersHi, x
sta @j+2
@j jsr $FDFD ; SMC
beq MainMenuEventLoop
rts
MainMenuEventQuestion
jsr HelpEventLoop
jmp +
MainMenuEventReturn
jsr SelectWorld
bcs + ; in next event handler
ldx #kStartPlaying ; Z=0 so caller will exit main menu event loop
; C=0 so grand-caller will start playing
; A=world ID (from SelectWorld)
rts
MainMenuEventC
jsr AboutPage
+ ldx #kStayOnMainMenu ; Z=1 so caller will stay in main menu event loop
sec ; C=1 so caller will do a full screen refresh
rts
MainMenuEventS
lda gSoundPref
eor #$01
sta gSoundPref
jsr SavePrefs
jsr ReinitSoundAfterPrefChange
ldx #kStayOnMainMenu ; Z=1 so caller will stay in main menu event loop
clc ; C=0 so caller will only do a partial screen refresh
rts
MainMenuEventQ
ldx #kRequestedQuit ; Z=0 so caller will exit main menu event loop
sec ; C=1 so grand-caller will call MLI quit
rts
DrawMainMenuTitle
jsr Home
lda #1
sta GlobalLeftMargin
ldy #3
- ldx #1
lda kTitleLine1-2, y
jsr DrawLargeCharacter
inx
lda kTitleLine2-2, y
jsr DrawLargeCharacter
inx
lda kTitleLine3-2, y
jsr DrawLargeCharacter
iny
cpy #$0A
bne -
rts
DrawMainMenuText
+PRINT_AT asterisk, 2, 30
+PRINT_AT version, 11, 26
+PRINT_AT mainmenu_play, 15, 10
+PRINT_AT mainmenu_sound, 16, 10
lda gSoundPref
beq @theSoundOfSilence
+LDADDR mainmenu_sound_on
bne + ; always branches
@theSoundOfSilence
+LDADDR mainmenu_sound_off
+ jsr DrawHeavySilkString
+PRINT_AT mainmenu_about, 17, 10
+PRINT_AT mainmenu_help, 18, 10
+PRINT_AT mainmenu_quit, 19, 10
+PRINT_AT disclaimer, 23, 0
rts
counter = $F2
selectedworld = $F3
SelectWorld
; in: none
; out: C clear if world was selected, and
; A = 0-based world ID
; C set if no world was selected and A is undefined
jsr Home
jsr UpdateWorldPercents
+LDADDR worlddescriptions
+ST16 $FE
lda #0
sta counter
sta selectedworld
lda #6
sta VTAB
- lda #10
sta HTAB
+LD16 $FE
ldx counter
cpx selectedworld
beq +
ldx #20
jsr DrawHeavySilkBuffer
jmp ++
+ ldx #20
jsr DrawHeavySilkBufferInverse
++ inc VTAB
lda $FE
clc
adc #20
sta $FE
bcc +
inc $FF
+ inc counter
lda counter
cmp #12
bcc -
+PRINT_AT worldhelp, 23, 0
bit CLEARKBD
@selectWorldLoop
lda KBD
bpl @selectWorldLoop
bit CLEARKBD
and #$7F
cmp #$0B ; up arrow
beq @eventUpArrow
cmp #$0A ; down arrow
beq @eventDownArrow
cmp #$08 ; left arrow
beq @eventLeftArrow
cmp #$15 ; right arrow
beq @eventRightArrow
cmp #$0D
beq @eventReturn
cmp #$1B
beq @eventEsc
rts
@eventReturn
jsr Home
lda selectedworld
clc
rts
@eventEsc
sec
rts
@eventLeftArrow
@eventUpArrow
jsr RedrawPreviouslySelectedWorld
ldx selectedworld
bne +
ldx #12
+ dex
stx selectedworld
jsr DrawNewlySelectedWorld
jmp @selectWorldLoop
@eventRightArrow
@eventDownArrow
jsr RedrawPreviouslySelectedWorld
ldx selectedworld
cpx #11
bne +
ldx #$FF
+ inx
stx selectedworld
jsr DrawNewlySelectedWorld
jmp @selectWorldLoop
RedrawPreviouslySelectedWorld
lda selectedworld
tax
clc
adc #6
sta VTAB
lda #10
sta HTAB
jsr GetWorldDescription
+LD16 $FE
ldx #20
jmp DrawHeavySilkBuffer
DrawNewlySelectedWorld
lda selectedworld
tax
clc
adc #6
sta VTAB
lda #10
sta HTAB
jsr GetWorldDescription
+LD16 $FE
ldx #20
jmp DrawHeavySilkBufferInverse
GetWorldDescription
; in: X = 0-based world ID
; out: $FE/$FF points to world description buffer
+LDADDR worlddescriptions
+ST16 $FE
jmp +
- lda $FE
clc
adc #20
sta $FE
bcc +
inc $FF
+ dex
bpl -
rts
worldindex=$FB
UpdateWorldPercents
+LDADDR worlddescriptions
+ST16 $FC
lda #0
sta worldindex
-- jsr FindPackedProgressAddr
ldy #$0E
lda ($FE), y
tax
lda #$20
jsr ToASCIIString
ldx #2
ldy #17
- lda $F2, x
sta ($FC), y
dey
dex
bpl -
lda $FC
clc
adc #20
sta $FC
bcc +
inc $FD
+ inc worldindex
lda worldindex
cmp #12
bne --
rts
asterisk
!byte 1
!byte "*"
version
!byte 4
!raw "V0.3"
mainmenu_play
!byte 20
!raw "RETURN.....PLAY GAME"
mainmenu_sound
!byte 18
!raw " S.....SOUND ("
mainmenu_sound_on
!byte 4
!raw "ON) "
mainmenu_sound_off
!byte 4
!raw "OFF)"
mainmenu_about
!byte 18
!raw " C.....CREDITS"
mainmenu_help
!byte 15
!raw " ?.....HELP"
mainmenu_quit
!byte 15
!raw " Q.....QUIT"
disclaimer
!byte 40
!raw "* NOT GUARANTEED, ACTUAL COUNT MAY VARY."
worlddescriptions
!raw " 4X3, EASY 0% "
!raw " 5X3, BASIC 0% "
!raw " 6X3, SIMPLE 0% "
!raw " 7X3, RELAXED 0% "
!raw " 4X4, FAIR 0% "
!raw " 5X4, QUICK 0% "
!raw " 6X4, MEDIUM 0% "
!raw " 7X4, AVERAGE 0% "
!raw " 4X5, HARD 0% "
!raw " 5X5, TOUGH 0% "
!raw " 6X5, TRICKY 0% "
!raw " 7X5, COMPLEX 0% "
kWorldShortNames
!byte 3
!raw "4X3"
!byte 3
!raw "5X3"
!byte 3
!raw "6X3"
!byte 3
!raw "7X3"
!byte 3
!raw "4X4"
!byte 3
!raw "5X4"
!byte 3
!raw "6X4"
!byte 3
!raw "7X4"
!byte 3
!raw "4X5"
!byte 3
!raw "5X5"
!byte 3
!raw "6X5"
!byte 3
!raw "7X5"
kDash
!byte 1
!raw "-"
worldhelp
!byte 40
!raw "ARROWS TO SELECT, RETURN TO PLAY, OR ESC"