4cade/src/glue.launch.a

257 lines
8.7 KiB
Plaintext
Raw Normal View History

2019-01-15 00:06:58 +00:00
;license:MIT
;(c) 2018-9 by 4am
2019-01-15 00:06:58 +00:00
;
; Functions to launch games and self-running demos
;
; Public functions
; - GetGameDisplayName
; - PlayGameFromSearch
2019-07-03 22:31:50 +00:00
; - PlayGameFromBrowse
; - PlayGameFromAttract
2019-06-26 02:44:39 +00:00
; - Prelaunch
; - Launch
2019-01-15 00:06:58 +00:00
;
; Public variables
; - gCurrentAttractIndex ; [byte] numeric index in gAttractModeStore of current Mega-Attract Module
; - gCurrentlyVisibleSlideshowIndex ; [byte] numeric index in gSlideshowStore of currently visible slideshow picture
; (only valid during slideshows, not updated once a key is pressed)
2019-06-26 02:44:39 +00:00
!zone {
GetGameDisplayName
; in: A/Y points to game filename
; X = #$60 if we should only look in gGamesListStore for a match
; X = #$EA if we should also look in gSlideshowStore
; out: C clear if game exists in gGamesListStore, and
; A/Y points to game display name (but see hack notes below)
; C set if game does not exist (this can happen because slideshows
; list games that require a joystick, but the games list parser
; filters out joystick-only games if the machine doesn't have a
; joystick)
stx @maybeExit
+STAY @key
+STAY @slideshowKey
jsr okvs_get
!word gGamesListStore
@key !word $FDFD ; SMC
bcc @exit
; Hack to allow self-running demos that don't correspond to a game
; filename. If the name ends in a '.', accept it unconditionally.
; The filename is its own display name. Launching this fake game
; will of course fail, so don't do that.
+LDAY @key
+STAY PARAM
ldy #0
lda (PARAM),y
tay
lda (PARAM),y
cmp #"."
beq @forceGoodResult
sec
@maybeExit
!byte $00 ; SMC
; if the key is still not found, AND the caller said to try this, then try
; getting the value of the current record from gSlideshowStore
; (some games have multiple action screenshots, in which case the filename of
; the action screenshot is not the game name, but the value is)
jsr okvs_get
!word gSlideshowStore
@slideshowKey
!word $FDFD ; SMC
+STAY @key3
jsr okvs_get
!word gGamesListStore
@key3 !word $FDFD ; SMC
; note that the game might still not be found (C will be set by okvs_get),
; which can happen if the game can't be played due to memory or joystick
; requirements
rts
@forceGoodResult
+LDAY @key
clc
@exit rts
PlayGameFromSearch
2019-07-03 22:31:50 +00:00
PlayGameFromBrowse
2019-06-27 02:51:34 +00:00
stx @gameIndex
2019-06-20 18:18:23 +00:00
jsr okvs_nth
!word gGamesListStore
2019-06-27 02:51:34 +00:00
@gameIndex
2019-06-20 18:18:23 +00:00
!byte $FD ; SMC
2019-06-26 02:44:39 +00:00
jmp .Go
2019-06-20 18:18:23 +00:00
PlayGameFromAttract
2019-06-26 02:44:39 +00:00
jsr LoadAndParseAttractModeConf
2019-01-15 00:06:58 +00:00
jsr okvs_nth ; get filename of current attract-mode module
!word gAttractModeStore
gCurrentAttractIndex
2019-06-26 02:44:39 +00:00
!byte $FD ; set in MegaAttractMode
2019-01-15 00:06:58 +00:00
+STAY @key
jsr okvs_get
!word gAttractModeStore
@key !word $FDFD ; SMC
+STAY PTR
ldy #1
lda (PTR),y
and #$0F
bne @playFromSlideshow
; we reached here by pressing <RETURN> during a self-running demo,
; which means that @key points to the filename of the game we want to play
+LDAY @key
2019-06-26 02:44:39 +00:00
jmp .Go
2019-01-15 00:06:58 +00:00
@playFromSlideshow
; we reached here by pressing <RETURN> during a slideshow
; gSlideshowStore is still in memory, and gCurrentlyVisibleSlideshowIndex
; is the index into gSlideshowStore of the picture that is being displayed
jsr okvs_nth
!word gSlideshowStore
gCurrentlyVisibleSlideshowIndex
!byte $FD ; set in HGRTitleCallback, HGRActionCallback, DHGRTitleCallback
+STAY @sskey
+STAY @sskey2
jsr okvs_get
!word gGamesListStore
@sskey !word $FDFD ; SMC
bcs +
+LDAY @sskey
2019-06-26 02:44:39 +00:00
jmp .Go
2019-01-15 00:06:58 +00:00
+
; if the key is not found, try getting the value of the current record
; from gSlideshowStore and using that instead
; (some games have multiple action screenshots, value points to the key in gGamesListStore)
jsr okvs_get
!word gSlideshowStore
@sskey2 !word $FDFD ; SMC
2019-06-26 02:44:39 +00:00
bcc .Go
2019-01-15 00:06:58 +00:00
rts
2019-06-26 02:44:39 +00:00
.Go
2019-01-15 00:06:58 +00:00
+STAY PTR
2019-06-26 02:44:39 +00:00
ldx #1 ; construct path to game's startup file
sec ; which is always /X/game/game
2019-06-21 23:47:05 +00:00
!byte $2c
-- pha
clc
2019-01-15 00:06:58 +00:00
php
ldy #0
lda (PTR), y
tay
iny
sty @runlength+1
ldy #0
lda #'X'
sta ProDOS_prefix+1
lda #'/'
- inx
sta ProDOS_prefix, x
iny
lda (PTR), y
@runlength
cpy #$D1 ; SMC
bne -
2019-06-21 23:47:05 +00:00
txa
2019-01-15 00:06:58 +00:00
plp
bcs --
stx ProDOS_prefix
2019-06-19 02:40:17 +00:00
+LDADDR ProDOS_prefix
jsr SetPath
2019-06-26 02:44:39 +00:00
jsr LoadFile ; load the game startup file
2019-01-15 00:06:58 +00:00
2019-06-21 23:47:05 +00:00
pla
2019-06-26 02:44:39 +00:00
sta ProDOS_prefix ; set 'root' directory to the path part
; of the game startup file we just loaded
; so games can load other files without
; knowing which directory they're in
2019-01-15 00:06:58 +00:00
2019-06-26 02:44:39 +00:00
; execution falls through here
Launch
+READ_RAM2_WRITE_RAM2
ldx #1
- lda $100,x
2019-06-26 02:44:39 +00:00
sta $DF00,x ; back up stack
inx
bne -
2019-06-26 02:44:39 +00:00
tsx ; back up stack pointer
stx $DF00
2019-06-26 02:44:39 +00:00
lda #$38 ; 'sec' opcode to tell |Reenter| to
sta RestoreStackNextTime ; restore the stack and stack pointer
2019-01-15 00:06:58 +00:00
ldx #(End_Prelaunch-Prelaunch-1)
- lda Prelaunch,x ; copy pre-launch code to main memory
sta $100,x
dex
bpl -
ldx #(end_promote-promote-1)
- lda promote,x ; copy ProDOS shim to main memory
sta $bf00,x
dex
bpl -
jmp $106 ; jump to pre-launch code
;------------------------------------------------------------------------------
; Prelaunch
2019-06-26 02:44:39 +00:00
; code to set up and launch third-party code (either a self-running demo or
; an actual game)
; THIS IS NOT A FUNCTION. DO NOT CALL THIS DIRECTLY.
2019-01-15 00:06:58 +00:00
; must be run from main memory
; contains multiple entry points
;
2019-06-26 02:44:39 +00:00
; in: for first entry point, none
; for second entry point, the game must already be loaded in memory
; and ldrlo2/ldrhi2 must be the game entry point
2019-01-15 00:06:58 +00:00
; out: exits via JMP (ldrlo2), which is expected to exit via JMP |Prelaunch|
; (not here, but wherever it was copied to in main memory) or by
; manually enabling LC RAM then JMP |Reenter|
2019-01-15 00:06:58 +00:00
;------------------------------------------------------------------------------
2019-06-26 02:44:39 +00:00
Prelaunch
2019-06-27 14:55:07 +00:00
; copied to $0100 in main memory
; main entry point to return to launcher (used by self-running demos, vectors)
+READ_RAM1_NO_WRITE
2019-01-15 00:06:58 +00:00
jmp Reenter
2019-06-27 14:55:07 +00:00
!if * != Prelaunch+6 {
!error "Prelaunch entry points are messed up"
}
; copied to $0106 in main memory
; main entry point to launch game
2019-01-15 00:06:58 +00:00
+READ_ROM_NO_WRITE
lda ldrlo2 ; set up game entry point in stack page
ldy ldrhi2 ; (last load address - 1)
sec
sbc #$01
bcs +
dey
+
+STAY $1FE
ldx #0 ; wipe zero page
txa
- sta $00,x
inx
bne -
2019-06-26 02:44:39 +00:00
lda #$65 ; Initialize 'random' seed. These are
2019-06-27 14:55:07 +00:00
sta RNDSEED ; arbitrary values. Some games like Pooyan
2019-06-26 02:44:39 +00:00
lda #$02 ; require these to be non-zero. Ask me
2019-06-27 14:55:07 +00:00
sta RNDSEED+1 ; how long that one took to debug.
jsr ROM_IN0 ; Initialize machine like a cold boot.
jsr ROM_PR0 ; Many games assume a 'clean slate' and
jsr ROM_NORMAL ; rely on zero page values set by these
sta STOREOFF ; ROM routines,
sta READMAINMEM ; e.g. Wavy Navy just prints out text via
sta WRITEMAINMEM ; $FDED and expects it to work. Having it
sta CLR80VID ; print all null characters is amusing, in
sta PRIMARYCHARSET ; a quiet way, but not really helpful.
jsr ROM_TEXT
jsr ROM_HOME
bit CLEARKBD
2019-06-26 02:44:39 +00:00
ldx #$FD ; Jump to game entry point via stack pop.
2019-01-15 00:06:58 +00:00
txs
rts
End_Prelaunch
2019-06-26 02:44:39 +00:00
}