4cade/src/glue.launch.a

278 lines
9.4 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
2019-10-08 18:43:41 +00:00
; - GetGameToLaunch
; - FindGame
; - FindGameInActionSlideshow
; - GetGameDisplayName
2019-09-21 03:26:32 +00:00
; - PlayGame
2019-06-26 02:44:39 +00:00
; - Launch
2019-01-15 00:06:58 +00:00
;
; Public variables:
2020-03-24 20:30:14 +00:00
; - gGameToLaunch - 0-based index into gGamesListStore (word)
;
2019-01-15 00:06:58 +00:00
2020-03-24 20:30:14 +00:00
gGameToLaunch
2020-05-30 14:53:29 +00:00
!word $FFFF
2020-03-24 20:30:14 +00:00
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
; AnyGameSelected
; get index of game that is currently selected in the UI (if any)
;
2020-03-24 20:30:14 +00:00
; in: none
; out: A/Y = gGameToLaunch (word)
; C clear if gGameToLaunch is not #$FFFF
; C set if gGameToLaunch is #$FFFF
; X preserved
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
AnyGameSelected
2020-03-24 20:30:14 +00:00
+LD16 gGameToLaunch
2020-05-30 15:14:04 +00:00
+CMP16 $FFFF
bne ForceGoodResult
rts ; CMP sets carry when equal
2020-03-24 20:30:14 +00:00
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
; GetGameToLaunch
; get filename of game that is currently selected in the UI (if any)
;
2020-03-24 20:30:14 +00:00
; in: gGameToLaunch = index into gGamesListStore (word) or #$FFFF if no game selected
; out: C clear if a game is selected, and
; A/Y points to game filename
; C set if no game is selected
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
GetGameToLaunch
2020-03-24 20:30:14 +00:00
jsr AnyGameSelected
2020-05-30 15:14:04 +00:00
bcs _gameToLaunchExit
2020-03-24 20:30:14 +00:00
+ST16 WINDEX
2019-10-08 18:43:41 +00:00
+LDADDR gGamesListStore
2020-03-24 20:30:14 +00:00
jsr okvs_nth
2020-05-30 15:14:04 +00:00
ForceGoodResult
2020-03-24 20:30:14 +00:00
clc
2020-05-30 15:14:04 +00:00
_gameToLaunchExit
rts
2019-10-08 18:43:41 +00:00
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
; FindGame
; check if an arbitrary game exists, for some definition of 'exists'
;
; in: A/Y points to game filename
; out: C clear if game exists in gGamesListStore, and
2020-03-24 20:30:14 +00:00
; $WINDEX = game index, or #$FFFF if the game doesn't really
; exist but we want to return a successful result anyway
; C set if game does not exist (this can happen because slideshows
; list games that require a joystick, but the games list parser
; filters them out if the machine doesn't have a joystick)
; all registers clobbered
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
FindGame
2020-03-24 20:30:14 +00:00
+ST16 @key
jsr okvs_find
!word gGamesListStore
@key !word $FDFD ; SMC
2020-05-30 15:14:04 +00:00
bcc GlueLaunchRTS
; Hack to allow self-running demos that don't correspond to a game
; filename. If the name ends in a '.', accept it unconditionally.
ldx #$FF
2020-03-24 20:30:14 +00:00
stx WINDEX
stx WINDEX+1
+LD16 @key
+ST16 PARAM
ldy #0
lda (PARAM),y
tay
lda (PARAM),y
cmp #"."
2020-05-30 15:14:04 +00:00
beq ForceGoodResult
sec
2020-05-30 15:14:04 +00:00
GlueLaunchRTS
rts
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
; FindGameInActionSlideshow
; check if an arbitrary game exists, for some definition of 'exists', while
; in the middle of a slideshow
;
; /!\ This function assumes that gSlideshowStore exists and is populated,
; which is generally only true during the callback function of a slideshow
;
; in: A/Y points to game filename
; out: C clear if game exists, and
2020-03-24 20:30:14 +00:00
; $WINDEX = game index, and
; A/Y points to game display name + game info bitfield
; C set if game can't be found by any means
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
FindGameInActionSlideshow
2020-03-24 20:30:14 +00:00
+ST16 @sskey
jsr FindGame
2020-05-30 15:14:04 +00:00
bcc GetGameDisplayName
; if the game was not found, try getting the value of the current record from
; gSlideshowStore (some games have multiple action screenshots, in which case
; the key is only the screenshot filename, and the value is the actual game
; filename)
jsr okvs_get
!word gSlideshowStore
@sskey !word $FDFD ; SMC
jsr FindGame
2020-05-30 15:14:04 +00:00
bcs GlueLaunchRTS
; /!\ execution falls through here to GetGameDisplayName
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
; GetGameDisplayName
; lookup or construct the display name for a specific game
;
; in: A/Y contains address of a key in gGamesListStore
; out: A/Y contains address of game display name + game info bitfield
; (this might be just the corresponding value in gGamesListStore,
; or it might be a temporary buffer in main memory that we constructed
; out of thin air)
; gValLen possibly clobbered (up to gValLen+MaxInputLength)
; X preserved
2020-05-30 15:14:04 +00:00
; C clear
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
GetGameDisplayName
2020-03-24 20:30:14 +00:00
+ST16 SAVE
jsr okvs_get_current ; get value for this key
; (PTR) -> truncated game display name + info bitfield
ldy #0
lda (PTR), y ; A = length of truncated game display name + info bitfield
cmp #1 ; 1 means there's no title, just info bitfield (1 byte)
beq +
2020-03-24 20:30:14 +00:00
+LD16 PTR
2020-05-30 15:14:04 +00:00
clc
rts
+ ; game display name is truncated, we must expand it
iny ; Y = 1
lda (PTR), y ; A = game info bitfield
pha ; save on stack
dey
lda (SAVE), y ; A = length of key
tay
iny
sty @len
sty gValLen
lda #$24 ; BIT opcode
2020-03-18 17:31:40 +00:00
sta @or ; first character remains capitalized
ldy #1
- lda (SAVE), y
2020-05-29 21:39:04 +00:00
cmp #$49 ; 'I'
bne +
cmp gValLen-1,y
beq ++ ; preserve 'II' casing
+ cmp #$2E
2020-03-18 17:31:40 +00:00
bne @or
lda #$20 ; convert '.' to ' '
@or ora #$20 ; SMC (opcode)
2020-05-29 21:39:04 +00:00
++ sta gValLen, y
2020-03-18 17:31:40 +00:00
cmp #$20
bne +
lda #$24 ; first character after ' ' remains capitalized
+HIDE_NEXT_2_BYTES
+ lda #$09 ; OR opcode
sta @or
@next iny
@len=*+1
cpy #$FD ; SMC
bne -
pla
sta gValLen, y
+LDADDR gValLen
2020-05-30 15:14:04 +00:00
clc
rts
2020-03-31 23:19:45 +00:00
;------------------------------------------------------------------------------
; PlayGame
;
; in: gGameToLaunch != #$FFFF
; out: exits via the game, but also backs up the stack, which may get
; restored in |Reenter|... what I'm saying is that we might actually
; 'return' from this after the user is done playing the game, which is
; a neat trick
;------------------------------------------------------------------------------
2019-09-21 03:26:32 +00:00
PlayGame
2019-10-08 18:43:41 +00:00
jsr GetGameToLaunch
2019-09-16 01:35:34 +00:00
; A/Y = address of game filename
2020-03-24 20:30:14 +00:00
+ST16 SAVE
+ST16 @pfile
2019-10-10 01:02:46 +00:00
jsr ClearScreens ; avoid seeing code load into the HGR page
; (clobbers $106, must do now before loading prelaunch code)
2019-09-15 02:57:52 +00:00
jsr LoadFile ; load this game's prelaunch file at $106
!word kPrelaunchDirectory
@pfile !word $FDFD
!word $0106
2019-09-15 02:57:52 +00:00
2019-10-09 04:25:10 +00:00
; we start by placing the subdirectory name at gPathname+kGameDirectoryLen
; to leave room for the GameDirectory name as the parent
lda #kGameDirectoryLen
sta gPathname
2020-03-24 20:30:14 +00:00
+LD16 SAVE
2019-10-09 04:25:10 +00:00
jsr AddToPath
; attach the separator
inc gPathname
lda #'/'
sta gPathname+1,x
2019-01-15 00:06:58 +00:00
2019-10-09 17:00:33 +00:00
; then we save the length of the resulting string without the count byte
dex
txa
pha
2019-10-09 04:25:10 +00:00
; then attach the game name
2020-03-24 20:30:14 +00:00
+LD16 SAVE
2019-10-09 04:25:10 +00:00
jsr AddToPath
; don't look while I do this
; we "place" a string at gPathname+kGameDirectoryLen
; whose length is the subdirectory name and game name
; then we load it
; the load sets the path to the GameDirectory
; and then finds the subdirectory name and game name right after it
; and attaches it to the path by overwriting the count byte
2019-11-27 21:51:43 +00:00
;;sec ; carry set by AddToPath
2019-10-09 04:25:10 +00:00
lda gPathname
sbc #kGameDirectoryLen
sta gPathname+kGameDirectoryLen
2019-06-26 02:44:39 +00:00
jsr LoadFile ; load the game startup file
2019-10-09 04:25:10 +00:00
!word kGameDirectory
!word gPathname+kGameDirectoryLen
2019-09-10 02:38:17 +00:00
!word 0 ; use file's default address
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
2019-09-10 02:38:17 +00:00
; so games can load other files without
2019-06-26 02:44:39 +00:00
; 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
jsr SwitchToBank2
2020-05-23 22:47:16 +00:00
lda #$BD
sta launchpatch
jsr saveslot ; set proper slot information
lda #$9D
sta launchpatch
jmp LaunchInternal
Joystick
jsr LoadFile
!word kPrelaunchDirectory
!word kStandardPrelaunch
!word $0106
jsr LoadFile
!word kRootDirectory
!word kJoystickFile
!word 0
jmp Launch