Lander opens on a splash, with music
The first customer for the player outside the program it was pulled out of, and the argument for doing it: a splash needs no resident player at all. Nothing else is happening while the logo is up, so Lander owns the timer and all four channels exactly as Play does. Music UNDER a running game is still deferred, and still the harder problem. It polls the timer rather than being interrupted by it. Lander has no vector segment and waits for the screen by reading port 0x30, so it waits for a beat by reading port 0x50 - the same shape, and it brings no handler that would have to be taken away before the game starts. The tune is read off the disk. A missing one means the logo and silence and the game starts anyway, the way a missing /lander.state means the defaults stand. FOUR THINGS THIS COST, each found by running it: A subroutine cannot answer in A. CALL saves and restores it, so splashSkip handed its caller back the A it already had - the channel number of the last stepVoice - and the splash ended on its first pass whatever anybody pressed. Q is what survives a RET, which nextRandom says twenty lines away and I did not read. Port 0x3D is how many window rows are SHOWN, and it is two once putGauge runs and nothing before. A line written to row eleven went somewhere real and was displayed nowhere. A nought is not a keypress. It is what a recorded keyboard file holds while nobody is typing, and a splash that took it for a key is one no test could ever watch. And skipping has to be free. Asked after blanking the window and reading the file, a skipped splash still cost a fifth of a second - enough to push the thruster test's early capture past the frame it looks at. Asked first, it costs a pad read. player.asm no longer asks a caller for Order0 to Order3: the voice records name NoOrder instead, so a program whose tune comes from a file does not have to define four order lists it never uses. That was the file case finding a wart in the contract. Every other Lander test now skips the splash with a space - a key the game itself ignores, since it answers to q, z and the arrows - so they go on testing what they tested. The one in sound.sh presses nothing, which is what makes it the one that hears the music. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
6bb1565dea
commit
00b31b88af
@@ -88,6 +88,13 @@ start:
|
||||
|
||||
CALL mulReady ; The quarter square table, once. The orbit below needs a product.
|
||||
CALL putTiles
|
||||
|
||||
; Key mode before the splash, because "press anything" needs the keystroke as it happens
|
||||
; rather than a line at the end of one.
|
||||
INIA 0x01
|
||||
OUTA 0x02
|
||||
CALL splash
|
||||
|
||||
CALL makeMoon
|
||||
CALL carvePads
|
||||
CALL drawMoon
|
||||
@@ -95,9 +102,6 @@ start:
|
||||
CALL putGauge
|
||||
CALL putOrbital
|
||||
|
||||
INIA 0x01
|
||||
OUTA 0x02 ; Key mode.
|
||||
|
||||
; ---- Is there a controller ----
|
||||
;
|
||||
; Asked once, and about all four. If there is one anywhere, the console's arrow keys are
|
||||
@@ -3541,6 +3545,168 @@ groundLevel:
|
||||
STA.0
|
||||
RET
|
||||
|
||||
; ---- The studio, and its theme ----
|
||||
;
|
||||
; What a splash screen is: whose game this is, over whatever music they want it said to. The
|
||||
; game's own title screen is a different thing and comes later.
|
||||
;
|
||||
; IT POLLS THE TIMER RATHER THAN BEING INTERRUPTED BY IT. This program has no vector segment
|
||||
; and waits for the screen by reading port 0x30, so waiting for a beat by reading port 0x50 is
|
||||
; the same shape - and it means the splash brings no handler that would have to be taken away
|
||||
; before the game starts. Reading the status is what answers a tick nobody was interrupted by.
|
||||
;
|
||||
; A tune that is not there is not a failure. The logo still shows, for a moment measured in
|
||||
; frames instead of ticks, and the game starts. That is what /lander.state does too.
|
||||
splash:
|
||||
; ---- Somebody already leaning on something means no splash at all ----
|
||||
;
|
||||
; Asked before anything is drawn or read, so that skipping costs nothing: the alternative
|
||||
; blanks twenty five rows of window and reads a file off the disk before it thinks to look,
|
||||
; which is a fifth of a second spent showing a picture nobody wanted.
|
||||
CALL splashSkip
|
||||
BNQ splashNone
|
||||
|
||||
; ---- The whole screen is window while the splash is up ----
|
||||
;
|
||||
; Port 0x3D is how many window rows are SHOWN, and putGauge sets it to two later for the
|
||||
; gauge. Two is not enough to put a line in the middle of the screen, and until putGauge
|
||||
; runs it is not even that - so the splash asks for all of them, which has the second use of
|
||||
; hiding the map, where the shell's prompt is still sitting.
|
||||
INIA 0d25
|
||||
OUTA 0x3D
|
||||
RSTA
|
||||
OUTA 0x3E ; From the top.
|
||||
|
||||
; Blanked a row at a time, because what is in the window is whatever was there before. A
|
||||
; CALL hands back A and B, so the row and the count both survive it.
|
||||
INIB 0d25 ; A is already nought, from setting the window's top above.
|
||||
splashBlank:
|
||||
SETD.0 Nothing
|
||||
CALL sayAtRow
|
||||
INCA
|
||||
DECB
|
||||
BNB splashBlank
|
||||
|
||||
SETD.0 StudioLine
|
||||
INIA 0d11
|
||||
CALL sayAtRow
|
||||
|
||||
SETD.0 SplashTune
|
||||
SETD.1 SplashBuffer
|
||||
SWI osFileRead
|
||||
BNQ splashSilent
|
||||
|
||||
SETD.0 SplashBuffer
|
||||
CALL useTune ; Which sets the tick out of the tune's own header.
|
||||
BNQ splashSilent
|
||||
|
||||
INIA 0x03
|
||||
OUTA 0x51 ; Run and repeat. NO interrupt: this waits by looking.
|
||||
|
||||
splashPlay:
|
||||
SETD.1 Voice0
|
||||
RSTA
|
||||
CALL stepVoice
|
||||
SETD.1 Voice1
|
||||
INIA 0d1
|
||||
CALL stepVoice
|
||||
SETD.1 Voice2
|
||||
INIA 0d2
|
||||
CALL stepVoice
|
||||
SETD.1 Voice3
|
||||
INIA 0d3
|
||||
CALL stepVoice
|
||||
|
||||
SETD.1 Playing
|
||||
LDA.1
|
||||
BRA splashDone ; Every voice has run out of order list.
|
||||
CALL splashSkip
|
||||
BNQ splashDone
|
||||
CALL waitTick
|
||||
BRI splashPlay
|
||||
|
||||
splashSilent:
|
||||
; No tune on the disk, so the logo is held for about a second and a half of frames.
|
||||
INIB 0d90
|
||||
splashHold:
|
||||
CALL waitFrame
|
||||
CALL splashSkip
|
||||
BNQ splashDone
|
||||
DECB
|
||||
BNB splashHold
|
||||
|
||||
splashDone:
|
||||
RSTA
|
||||
OUTA 0x51 ; The timer stopped, whether or not it was ever started.
|
||||
CALL hushVoices
|
||||
|
||||
; And the window given back, because putGauge is about to ask for the two rows it wants.
|
||||
RSTA
|
||||
OUTA 0x3D
|
||||
splashNone:
|
||||
RET
|
||||
|
||||
; ---- Anything pressed, on a pad or a key ----
|
||||
;
|
||||
; THE ANSWER COMES BACK IN Q, because Q is what survives a RET. A CALL saves and restores A,
|
||||
; so a routine that answered there would hand its caller back the A it already had - which
|
||||
; here was the channel number the last stepVoice was given, and the splash ended on its first
|
||||
; pass every time whatever anybody pressed. nextRandom above says the same thing about the
|
||||
; same register, which is where it should have been read.
|
||||
splashSkip:
|
||||
CALL readPad
|
||||
SETD.0 Held
|
||||
LDA.0
|
||||
INIB 0x50 ; A, or Start - the same two waitKey asks about, and for the same
|
||||
AND ; reason: a direction held on a stick is not somebody asking to
|
||||
BNQ splashSkipYes ; begin, and ANY bit counted one as such.
|
||||
INA 0x01
|
||||
INIB 0x01 ; READY
|
||||
AND
|
||||
BRQ splashSkipNo
|
||||
INA 0x00 ; Taken, so it is not still waiting at the prompt afterwards.
|
||||
BRA splashSkipNo ; A NOUGHT IS NOT A KEYPRESS. It is what a recorded keyboard file
|
||||
; holds while nobody is typing, and what readControls has always
|
||||
; ignored - a splash that took it for a key would be a splash
|
||||
; nothing could ever watch.
|
||||
splashSkipYes:
|
||||
INIA 0d1
|
||||
RSTB
|
||||
OR ; Q is one: somebody asked for the game.
|
||||
RET
|
||||
splashSkipNo:
|
||||
RSTA
|
||||
RSTB
|
||||
OR ; And Q is nought: nobody did.
|
||||
RET
|
||||
|
||||
; A beat, waited for by looking - the same shape as waitFrame, one device along. Reading the
|
||||
; status is what brings the tick down.
|
||||
waitTick:
|
||||
INA 0x50
|
||||
INIB 0x01
|
||||
AND
|
||||
BRQ waitTick
|
||||
RET
|
||||
|
||||
; Every voice let go of. The splash owns all four while it plays and the game wants them back
|
||||
; silent - and every sound in this game loads its own patch before its note, so nothing else
|
||||
; has to be put back.
|
||||
hushVoices:
|
||||
RSTA
|
||||
hushOne:
|
||||
OUTA 0x41
|
||||
PSHA
|
||||
RSTA
|
||||
OUTA 0x45
|
||||
POPA
|
||||
INCA
|
||||
INIB 0d4
|
||||
CCF
|
||||
SUB
|
||||
BNQ hushOne
|
||||
RET
|
||||
|
||||
; ---- A line of text, into the window ----
|
||||
;
|
||||
; DP0 names a string. It goes into window row one and the rest of the row is BLANKED, so a
|
||||
@@ -3554,12 +3720,21 @@ groundLevel:
|
||||
; The letters are ordinary tiles: the character generator starts at the space, so glyph n is
|
||||
; character n less thirty two.
|
||||
sayInWindow:
|
||||
INIA 0d1 ; Row one, which is where a base's message goes.
|
||||
sayAtRow:
|
||||
; A is which window row. Kept in memory across the bank select below, which needs A itself.
|
||||
SETD.1 SayRow
|
||||
STA.1
|
||||
INIA 0d5
|
||||
OUTA 0xE3
|
||||
INIA 0xC1
|
||||
OUTA 0xE3 ; Which needs A, so the row came out of it a moment ago.
|
||||
LDA.1 ; DP1 still holds SayRow.
|
||||
INIB 0xC0
|
||||
CCF
|
||||
ADD ; Window row n begins at 0xC000 plus n times 256.
|
||||
MVQA
|
||||
OUTA 0xE4
|
||||
RSTA
|
||||
OUTA 0xE5 ; Window row one begins at 0xC100.
|
||||
OUTA 0xE5
|
||||
SETD.1 SayAt
|
||||
STA.1
|
||||
|
||||
@@ -4072,6 +4247,17 @@ Wide:
|
||||
;
|
||||
; Named rather than numbered, so whatever writes one and this that reads it are describing the
|
||||
; same fields. Low byte first, the way every other word here is.
|
||||
SayRow:
|
||||
0d1
|
||||
StudioLine:
|
||||
" ANACHRONAUT"
|
||||
Nothing:
|
||||
0x00
|
||||
SplashTune:
|
||||
"/splash.tune"
|
||||
SplashBuffer:
|
||||
#Reserve 0d1024
|
||||
|
||||
StateName:
|
||||
"/lander.state"
|
||||
StateBuffer:
|
||||
@@ -4480,6 +4666,8 @@ LanderArtAt:
|
||||
|
||||
#Include math.asm
|
||||
|
||||
#Include player.asm
|
||||
|
||||
#Include boom.asm
|
||||
|
||||
#Include alarm.asm
|
||||
|
||||
Reference in New Issue
Block a user