add cheats subsystem (parsing of games.conf, UI, loading appropriate prelaunch file)

This commit is contained in:
4am 2019-09-15 17:55:16 -04:00
parent 4682a8201a
commit 4b66697758
14 changed files with 273 additions and 35 deletions

View File

@ -20,7 +20,9 @@ ACME=acme
# https://github.com/mach-kernel/cadius
CADIUS=cadius
asm: md asmfx asmprelaunch
asm: md asmlauncher asmfx asmprelaunch
asmlauncher:
$(ACME) src/4cade.a 2>build/relbase.log
$(ACME) -r build/4cade.lst -DRELBASE=`cat build/relbase.log | grep "RELBASE =" | cut -d"=" -f2 | cut -d"(" -f2 | cut -d")" -f1` src/4cade.a

File diff suppressed because one or more lines are too long

View File

@ -72,6 +72,7 @@ RestoreStackNextTime
!source "src/ui.attract.dhgr.a"
!source "src/ui.attract.shr.a"
!source "src/ui.attract.gr.a"
!source "src/ui.cheats.a"
!source "src/prodos.path.a"
!source "src/glue.launch.a"
!source "src/glue.prorwts2.a"
@ -90,7 +91,7 @@ gDFXStore
gSlideshowStore
!word $0800
gGlobalPrefsStore
!word $D000
!word $D100
gGamesListStore
!word $FDFD ; SMC
!word Reenter ; NMI vector ($FFFA-B)

View File

@ -215,6 +215,10 @@ OneTimeSetup
!word gGamesListStore
sta GameCount
sta SAVE
lda #$80 ; TODO make this a pref
sta gCheatsEnabled
; calculate and update visible game count (3-digit decimal number as ASCII string)
ldy #0
@outer

View File

@ -81,5 +81,10 @@ gKey = $1F01
gValLen = $1F80
gVal = $1F81
; LC RAM 1
gCheatsAvailable = $D000 ; master cheats table, indexed by game index in gGamesListStore
; 1 byte per game, so max size = 256 games
gCheatsEnabled = $D0FF ; bit 7 = 1 if cheats are enabled
; actual constants
SUPPORTS_SHR = %00110000 ; AND mask for MachineStatus

View File

@ -9,6 +9,7 @@
; Public functions
; - DrawPage
; - Draw40Chars
; - DrawCenteredString
; - DrawString
; - DrawBuffer
;
@ -25,6 +26,12 @@ Draw40Chars
+READ_RAM1_WRITE_RAM1
rts
DrawCenteredString
+READ_RAM2_WRITE_RAM2
jsr DrawCenteredStringInternal
+READ_RAM1_WRITE_RAM1
rts
DrawString
+READ_RAM2_WRITE_RAM2
jsr DrawStringInternal

View File

@ -129,15 +129,29 @@ gCurrentlyVisibleSlideshowIndex
rts
.Go
; in: A/Y = lo/hi address of filename
; X = game index
+STAY SAVE
+STAY +
; TODO check if cheats are enabled and available for this game
bit gCheatsEnabled ; are cheats enabled?
bpl @noCheats
ldy gCheatsAvailable,x ; are there any cheats for this game?
beq @noCheats
jsr LoadFile ; load standard prelaunch code (|Launch| will call it)
!word kPrelaunchDirectory
jsr LoadFile ; cheats are enabled and this game has a prelaunch
!word kPrelaunchDirectory ; file that will set up the cheats, so load that
+ !word $FDFD ; SMC
!word $0106
jmp @loadedPrelaunch
@noCheats
jsr LoadFile ; no game-specific prelaunch file, so
!word kPrelaunchDirectory ; load standard prelaunch file instead
!word kStandardPrelaunch
!word $0106
@loadedPrelaunch
ldx #1 ; construct path to game's startup file
sec ; which is always /X/game/game
!byte $2c

View File

@ -116,7 +116,8 @@ okvs_len
; +3 [word] address of key
; +5 [word] address of value
; +7 [byte] maximum length of value (or 0 to fit)
; out: all registers clobbered
; out: X = new number of records (same as calling okvs_len after okvs_append)
; A/Y clobbered
; $00/$01 clobbered
; $02/$03 clobbered
; $04/$05 has the address of the next available byte after the new record
@ -130,6 +131,7 @@ okvs_append
lda (PTR),y ; A = number of keys in store
clc
adc #1
pha ; will return this later
sta (PTR),y ; increment number of keys
iny
lda (PTR),y ; get address of next free space
@ -201,6 +203,8 @@ okvs_append
iny
lda SRC+1
sta (PTR),y
pla
tax ; X = new OKVS length
jsr GetStoreAddress
; PTR -> store
ldy #1

View File

@ -66,15 +66,17 @@ ParseGamesList
@filterOnMemory
jsr IncAndGetChar ; get second filter character ('1' if game requires 128K)
cmp #$30 ; '0' -> no filtering on memory
beq @swallowComma
beq @parseCheatsAvailable
cmp #$31 ; not '0' or '1' -> ignore entire line
bne @skipLine
bit zpMachineStatus
bvc @skipLine ; game requires 128K but we only have 64K, so ignore entire line
@parseCheatsAvailable
jsr IncAndGetChar ; get third character (cheat category, int)
and #$0F
pha
@swallowComma
jsr IncAndGetChar
cmp #$2C ; ',' delimiter (required)
bne @skipLine
@gatherKey
jsr IncAndGetChar
cmp #$3D ; '=' ends the key
@ -100,8 +102,12 @@ ParseGamesList
!word gKeyLen
!word gValLen
!byte 0
pla
; X = new OKVS length
pla ; pop saved Y
tay
pla ; pop cheat category
dex ; X = new OKVS length - 1
sta gCheatsAvailable,x
clc
bcc @newkey ; always branches

View File

@ -130,12 +130,10 @@ GameCount = *+1
sta UI_ToPlay,x
dex
bpl -
ldx #40
lda #0
- sta UILine1-1,x ; reset UI line 1
dex
bne -
jsr DrawSearchBarOffscreen ; actually draw the search UI (offscreen)
ldx @index
jsr BuildUILine1WithNoDots ; build UI line 1 with bars and other shapes
ldx @index
jsr DrawSearchBarOffscreen ; actually draw the UI (offscreen)
jmp ShowOtherPage ; now show everything at once
;------------------------------------------------------------------------------

145
src/ui.cheats.a Normal file
View File

@ -0,0 +1,145 @@
BuildUILine1WithNoDots
; in: X = game index, or #$FF if no game selected
; out: all registers clobbered
; UILine1 contains 40-character buffer (not length-prefixed) to print
cpx #$FF
beq +
ldy gCheatsAvailable,x
+HIDE_NEXT_2_BYTES
+
ldy #.kCheatsEnabled
ldx #40
lda #$00 ; horizontal bar
- sta UILine1-1,x ; first, reset entire line to solid bar
dex
bne -
bit gCheatsEnabled
bpl @done ; if cheats are not enabled, we're done
lda .kCheatDescriptionLo,y
sta PTR
lda .kCheatDescriptionHi,y
sta PTR+1
; (PTR) -> length-prefixed cheat description
ldy #0
lda (PTR),y ; A = length of cheat description
clc
adc #8 ; extra padding (4 on each side) for string
sta @len
lda #40
sec
sbc @len
lsr
tax
lda #$09 ; rounded bottom-right character
sta UILine1,x
ldy #1 ; fill the proper width with spaces
lda #$20 ; space character
- inx
sta UILine1,x
iny
@len=*+1
cpy #$FD ; SMC
bne -
lda #$08 ; rounded bottom-left character
sta UILine1,x
@done rts
BuildCheatLine1
; in: X = game index, or #$FF if no game is selected
; out: gPathname contains length-prefixed string to print centered
; all registers clobbered
; PTR clobbered
cpx #$FF
beq +
ldy gCheatsAvailable,x
+HIDE_NEXT_2_BYTES
+
ldy #.kCheatsEnabled
ldx #39 ; reset gPathname+2 to gPathname+41 to
lda #$00 ; horizontal bar character
- sta gPathname+1,x
dex
bne -
lda #$06 ; gPathname+1 = top-left rounded corner character
sta gPathname+1
lda .kCheatDescriptionLo,y
sta PTR
lda .kCheatDescriptionHi,y
sta PTR+1
; (PTR) -> length-prefixed cheat description
ldy #0
lda (PTR),y ; A = length of cheat description
clc
adc #8 ; extra padding (4 on each side) for string
sta gPathname ; gPathname = length
tax
lda #$07 ; gPathname+length = top-right rounded corner character
sta gPathname,x
rts
BuildCheatLine2
; in: X = game index, or #$FF if no game is selected
; out: gPathname contains length-prefixed string to print centered
; all registers clobbered
; PTR clobbered
; SAVE clobbered
cpx #$FF
beq +
ldy gCheatsAvailable,x
+HIDE_NEXT_2_BYTES
+
ldy #.kCheatsEnabled
lda .kCheatDescriptionLo,y
sta SAVE
lda .kCheatDescriptionHi,y
sta SAVE+1
; (SAVE) -> length-prefixed cheat description
+LDADDR .sCheatDescriptionPrefix
jsr SetPath
+LDAY SAVE
jsr AddToPath
+LDADDR .sCheatDescriptionSuffix
jmp AddToPath
.kCheatsEnabled = 3 ; index of 'cheats enabled' string in following table
.kCheatDescriptionLo
!byte <.sNoCheats
!byte <.sInfiniteLives
!byte <.sInfiniteLivesAndWeapons
!byte <.sCheatsEnabled
.kCheatDescriptionHi
!byte >.sNoCheats
!byte >.sInfiniteLives
!byte >.sInfiniteLivesAndWeapons
!byte >.sCheatsEnabled
.sNoCheats
!byte 14
!text "no cheats yet!"
.sInfiniteLives
!byte 14
!text "infinite lives"
.sInfiniteLivesAndWeapons
!byte 24
!text "infinite lives & weapons"
.sCheatsEnabled
!byte 14
!text "cheats enabled"
.sCheatDescriptionPrefix
!byte 4
!byte $03 ; vertical line
!text " "
!byte $16 ; bolt
!text " "
.sCheatDescriptionSuffix
!byte 4
!text " "
!byte $16 ; bolt
!text " "
!byte $03 ; vertical line

View File

@ -142,20 +142,47 @@ CoverFade
; DrawSearchBarOffscreen
; draw 2-line search UI on the HGR page that is not currently showing
;
; in: none
; in: X = game index, or #$FF if no game is selected
; out: all flags and registers clobbered
;------------------------------------------------------------------------------
DrawSearchBarOffscreen
txa
pha
lda #22 ; draw visible search bar
sta VTAB
lda OffscreenPage
ror ; draw on offscreen page
ror ; draw line 1 on offscreen page
+LDADDR UILine1
jsr Draw40Chars
lda OffscreenPage
ror ; draw on offscreen page
ror ; draw line 2 on offscreen page
+LDADDR UILine2
jmp Draw40Chars
jsr Draw40Chars
pla
bit gCheatsEnabled
bpl @done ; if cheats are not enabled, we're done
pha
tax
lda #20
sta VTAB
jsr BuildCheatLine1
lda OffscreenPage
ror
+LDADDR gPathname
jsr DrawCenteredString
inc VTAB
pla
tax
jsr BuildCheatLine2
lda OffscreenPage
ror
+LDADDR gPathname
jsr DrawCenteredString
@done rts
;------------------------------------------------------------------------------
; ClearOffscreen

View File

@ -10,6 +10,7 @@
; Public functions
; - DrawPageInternal
; - Draw40CharsInternal
; - DrawCenteredStringInternal
; - DrawStringInternal
; - DrawBufferInternal
;
@ -86,6 +87,27 @@ Draw40CharsInternal
stx HTAB
rts
DrawCenteredStringInternal
; A/Y contains address of length-prefixed string
; carry bit clear -> draw on page 1
; carry bit set -> draw on page 2
; $25 contains textpage line (0..23) (this is the standard VTAB address)
; clobbers A/X/Y
; clobbers PTR/PTR+1
+STAY PTR
php
ldy #0
lda (PTR),y
sta HTAB
lda #40
sec
sbc HTAB
lsr
sta HTAB
plp
jmp +
DrawStringInternal
; A/Y contains address of length-prefixed string
; carry bit clear -> draw on page 1
@ -97,7 +119,7 @@ DrawStringInternal
+STAY PTR
ldy #0
lda (PTR),y
+ lda (PTR),y
tax
inc PTR
bne +

View File

@ -120,16 +120,17 @@ SearchMode
; no input, reset params and UI
lda #$FF
sta SelectedIndex ; no game selected
ldx #39 ; reset visible line
- lda #0
sta UILine1,x
lda Instructions,x
ldx #39 ; copy instructions to line 2
- lda Instructions,x
sta UILine2,x
dex
bpl -
jsr LoadTitleOffscreen
jsr DrawSearchBarOffscreen
jsr ShowOtherPage
ldx #$FF ; no game selected
jsr BuildUILine1WithNoDots; build UI line 1 with bars and other shapes
ldx #$FF ; no game selected
jsr DrawSearchBarOffscreen; draw everything at once (offscreen)
jsr ShowOtherPage ; show it all at once
clc
rts
@ -199,19 +200,20 @@ SearchMode
sta UI_ToPlay,x
dex
bpl -
ldx #40
lda #0
- sta UILine1-1,x ; reset search bar
dex
bne -
tay
ldx SelectedIndex
jsr BuildUILine1WithNoDots; build UI line 1 with bars and other shapes
; now add dots to UI line 1 to highlight matched characters
ldx #0
ldy #0
@dotloop
iny
lda (SRC),y
+LOW_ASCII_TO_LOWER
cmp InputBuffer,x
bne +
lda #$11 ; add dots to highlight matched characters
lda #$11 ; dot character
sta UILine1,y
inx
cpx InputLength ; if input buffer is exhausted, we're done
@ -220,6 +222,7 @@ SearchMode
cpy SAVE ; if game name is exhausted, we're done
bne @dotloop
@doneHighlight
ldx SelectedIndex
jsr DrawSearchBarOffscreen; actually draw the search UI (offscreen)
jmp ShowOtherPage ; now show everything at once