Lunar Porter moves into a directory of its own
The first application with things of its own, and the first customer for all three rungs before it at once. /Apps/Lander a launcher /Packages/app.Lander/Lander.sbx the program /Packages/app.Lander/splash.tune its tune Typing "Lander" starts the launcher, which needs no new rule: the shell runs what it reads, so a launcher beginning "#!" and Say.sbx beginning "SBEX" go down the same road and neither the shell nor the person has to know which kind of thing they started. It passes on what it was told with $args, and says #quiet, because a launcher is machinery and not narration. The game then asks where it came from and joins its tune's name to that, so nothing anywhere names /splash.tune. Every recorded Lander test still types just "Lander" and knows nothing about any of this, which is exactly the claim. ---- Why the directory is not in /Apps ---- A launcher and a directory of the same name cannot both be there; SBFS refuses the second. And /Apps is the directory the shell walks for every word it does not know and Tab walks for every first word, so doubling what is in it is a cost on the path that runs most. The "app." goes in FRONT rather than behind because Tab matches the start of a name: a prefix is a namespace and a suffix is a collision. Copy.app beside Copy.sbx makes "Copy" and Tab complete to the shared "Copy." and hand you a broken word. The launcher names drive 0, so a game started from a disk of your own is looked for where the game is rather than where you are - its lines run on your disk, which is what makes everything else in a script work. /lander.state stays at the root. A saved position belongs to whoever saved it and is found where they are standing; a tune belongs to the program and is found beside it. That pair is the whole distinction. ---- And what it cost ---- Two hundred thousand cycles, about twelve frames, between the machine starting and the game drawing: a script opened, a deeper path walked. Six video captures moved out by that much. The drift bar needed something else - its pad is counted from the MACHINE starting rather than the game, so the burn is now twelve frames shorter from the game's point of view, and the recording holds the button longer instead. 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
2defbb49e2
commit
94bdf71356
@@ -3591,7 +3591,27 @@ splashBlank:
|
||||
INIA 0d11
|
||||
CALL sayAtRow
|
||||
|
||||
SETD.0 SplashTune
|
||||
; ---- Where the tune is, asked rather than assumed ----
|
||||
;
|
||||
; This used to name /splash.tune, which was true for exactly as long as the game and its
|
||||
; things both sat at the root of the disk that started the machine. The game lives in a
|
||||
; directory of its own now and what somebody types is a launcher in /Apps, so the only
|
||||
; thing that says where the tune is, is where the game itself came from.
|
||||
;
|
||||
; And it has to be asked rather than worked out from the working directory, because that
|
||||
; is where the PERSON is standing. A player in their own directory is not standing in
|
||||
; Lander's, and should not have to be.
|
||||
SETD.0 MyPath
|
||||
INIB 0d192
|
||||
SWI osWhereAmI
|
||||
SETD.0 MyPath
|
||||
SETD.1 SplashTune
|
||||
SETD.2 TunePath
|
||||
INIB 0d192
|
||||
CALL pathBeside
|
||||
BNQ splashSilent ; A path that did not fit cannot name a tune.
|
||||
|
||||
SETD.0 TunePath
|
||||
SETD.1 SplashBuffer
|
||||
SWI osFileRead
|
||||
BNQ splashSilent
|
||||
@@ -4253,8 +4273,13 @@ StudioLine:
|
||||
" ANACHRONAUT"
|
||||
Nothing:
|
||||
0x00
|
||||
; Beside the game, wherever the game turns out to be. See splash, which asks.
|
||||
SplashTune:
|
||||
"/splash.tune"
|
||||
"splash.tune"
|
||||
MyPath:
|
||||
#Reserve 0d192
|
||||
TunePath:
|
||||
#Reserve 0d192
|
||||
SplashBuffer:
|
||||
#Reserve 0d1024
|
||||
|
||||
@@ -4666,6 +4691,10 @@ LanderArtAt:
|
||||
|
||||
#Include math.asm
|
||||
|
||||
; Joining a name to the place another thing is in, which is how the tune is found now that
|
||||
; the game does not know where it lives until it asks.
|
||||
#Include path.asm
|
||||
|
||||
#Include player.asm
|
||||
|
||||
#Include boom.asm
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#! script
|
||||
; The launcher for Lunar Porter, which is what typing "Lander" actually starts.
|
||||
;
|
||||
; An application with things of its own gets a DIRECTORY of its own, and a typed word names
|
||||
; a file rather than a directory - so what sits in /Apps is this, and the game sits with its
|
||||
; tune in /Packages/app.Lander. The shell decides what to run by reading it, so this file
|
||||
; beginning "#!" and Say.sbx beginning "SBEX" go down the same road and neither the shell nor
|
||||
; the person has to know which kind of thing they started.
|
||||
;
|
||||
; That indirection is the point of it. Where the game physically lives stops being part of
|
||||
; its name, so an installer may put it on another disk and change only this line.
|
||||
;
|
||||
; #quiet, because a launcher is machinery and not narration. Without it, starting a game
|
||||
; prints the path of the thing it is about to start.
|
||||
#quiet
|
||||
0:/Packages/app.Lander/Lander.sbx $args
|
||||
File diff suppressed because one or more lines are too long
@@ -26,13 +26,12 @@ Mode.sbx 48
|
||||
Flip.sbx 173
|
||||
Sprite.sbx 442
|
||||
Depth.sbx 672
|
||||
Lander.sbx 11260
|
||||
Packages <dir>
|
||||
Pad.sbx 264
|
||||
Crash.sbx 632
|
||||
vars.script 50
|
||||
blocks.script 343
|
||||
loops.script 272
|
||||
splash.tune 210
|
||||
tune.sbx 318
|
||||
Play.sbx 2526
|
||||
notes.txt 21
|
||||
@@ -51,7 +50,7 @@ args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
crossed.txt 560
|
||||
38 files, 1 directory
|
||||
36 files, 2 directories
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -16,13 +16,12 @@ Mode.sbx 48
|
||||
Flip.sbx 173
|
||||
Sprite.sbx 442
|
||||
Depth.sbx 672
|
||||
Lander.sbx 11260
|
||||
Packages <dir>
|
||||
Pad.sbx 264
|
||||
Crash.sbx 632
|
||||
vars.script 50
|
||||
blocks.script 343
|
||||
loops.script 272
|
||||
splash.tune 210
|
||||
tune.sbx 318
|
||||
Play.sbx 2526
|
||||
notes.txt 21
|
||||
@@ -40,7 +39,7 @@ aloud.script 59
|
||||
args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
37 files, 1 directory
|
||||
35 files, 2 directories
|
||||
> drive 1
|
||||
> dir
|
||||
other.txt 28
|
||||
|
||||
@@ -33,13 +33,12 @@ Mode.sbx 48
|
||||
Flip.sbx 173
|
||||
Sprite.sbx 442
|
||||
Depth.sbx 672
|
||||
Lander.sbx 11260
|
||||
Packages <dir>
|
||||
Pad.sbx 264
|
||||
Crash.sbx 632
|
||||
vars.script 50
|
||||
blocks.script 343
|
||||
loops.script 272
|
||||
splash.tune 210
|
||||
tune.sbx 318
|
||||
Play.sbx 2526
|
||||
notes.txt 21
|
||||
@@ -57,7 +56,7 @@ aloud.script 59
|
||||
args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
37 files, 1 directory
|
||||
35 files, 2 directories
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -23,13 +23,12 @@ Mode.sbx 48
|
||||
Flip.sbx 173
|
||||
Sprite.sbx 442
|
||||
Depth.sbx 672
|
||||
Lander.sbx 11260
|
||||
Packages <dir>
|
||||
Pad.sbx 264
|
||||
Crash.sbx 632
|
||||
vars.script 50
|
||||
blocks.script 343
|
||||
loops.script 272
|
||||
splash.tune 210
|
||||
tune.sbx 318
|
||||
Play.sbx 2526
|
||||
notes.txt 21
|
||||
@@ -47,7 +46,7 @@ aloud.script 59
|
||||
args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
37 files, 1 directory
|
||||
35 files, 2 directories
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -23,13 +23,12 @@ Mode.sbx 48
|
||||
Flip.sbx 173
|
||||
Sprite.sbx 442
|
||||
Depth.sbx 672
|
||||
Lander.sbx 11260
|
||||
Packages <dir>
|
||||
Pad.sbx 264
|
||||
Crash.sbx 632
|
||||
vars.script 50
|
||||
blocks.script 343
|
||||
loops.script 272
|
||||
splash.tune 210
|
||||
tune.sbx 318
|
||||
Play.sbx 2526
|
||||
notes.txt 21
|
||||
@@ -47,7 +46,7 @@ aloud.script 59
|
||||
args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
37 files, 1 directory
|
||||
35 files, 2 directories
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -109,13 +109,12 @@ Mode.sbx 48
|
||||
Flip.sbx 173
|
||||
Sprite.sbx 442
|
||||
Depth.sbx 672
|
||||
Lander.sbx 11260
|
||||
Packages <dir>
|
||||
Pad.sbx 264
|
||||
Crash.sbx 632
|
||||
vars.script 50
|
||||
blocks.script 343
|
||||
loops.script 272
|
||||
splash.tune 210
|
||||
tune.sbx 318
|
||||
Play.sbx 2526
|
||||
notes.txt 21
|
||||
@@ -133,7 +132,7 @@ aloud.script 59
|
||||
args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
37 files, 1 directory
|
||||
35 files, 2 directories
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -28,13 +28,12 @@ Mode.sbx 48
|
||||
Flip.sbx 173
|
||||
Sprite.sbx 442
|
||||
Depth.sbx 672
|
||||
Lander.sbx 11260
|
||||
Packages <dir>
|
||||
Pad.sbx 264
|
||||
Crash.sbx 632
|
||||
vars.script 50
|
||||
blocks.script 343
|
||||
loops.script 272
|
||||
splash.tune 210
|
||||
tune.sbx 318
|
||||
Play.sbx 2526
|
||||
notes.txt 21
|
||||
@@ -52,7 +51,7 @@ aloud.script 59
|
||||
args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
37 files, 1 directory
|
||||
35 files, 2 directories
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
@@ -16,13 +16,12 @@ Mode.sbx 48
|
||||
Flip.sbx 173
|
||||
Sprite.sbx 442
|
||||
Depth.sbx 672
|
||||
Lander.sbx 11260
|
||||
Packages <dir>
|
||||
Pad.sbx 264
|
||||
Crash.sbx 632
|
||||
vars.script 50
|
||||
blocks.script 343
|
||||
loops.script 272
|
||||
splash.tune 210
|
||||
tune.sbx 318
|
||||
Play.sbx 2526
|
||||
notes.txt 21
|
||||
@@ -40,7 +39,7 @@ aloud.script 59
|
||||
args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
37 files, 1 directory
|
||||
35 files, 2 directories
|
||||
> load
|
||||
load what?
|
||||
> load nosuch.sbx
|
||||
|
||||
@@ -14,13 +14,12 @@ Mode.sbx 48
|
||||
Flip.sbx 173
|
||||
Sprite.sbx 442
|
||||
Depth.sbx 672
|
||||
Lander.sbx 11260
|
||||
Packages <dir>
|
||||
Pad.sbx 264
|
||||
Crash.sbx 632
|
||||
vars.script 50
|
||||
blocks.script 343
|
||||
loops.script 272
|
||||
splash.tune 210
|
||||
tune.sbx 318
|
||||
Play.sbx 2526
|
||||
notes.txt 21
|
||||
@@ -38,7 +37,7 @@ aloud.script 59
|
||||
args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
37 files, 1 directory
|
||||
35 files, 2 directories
|
||||
> load Say.sbx
|
||||
loaded, starting at 5000
|
||||
> run the disk took its time
|
||||
|
||||
@@ -23,13 +23,12 @@ Mode.sbx 48
|
||||
Flip.sbx 173
|
||||
Sprite.sbx 442
|
||||
Depth.sbx 672
|
||||
Lander.sbx 11260
|
||||
Packages <dir>
|
||||
Pad.sbx 264
|
||||
Crash.sbx 632
|
||||
vars.script 50
|
||||
blocks.script 343
|
||||
loops.script 272
|
||||
splash.tune 210
|
||||
tune.sbx 318
|
||||
Play.sbx 2526
|
||||
notes.txt 21
|
||||
@@ -47,7 +46,7 @@ aloud.script 59
|
||||
args.script 64
|
||||
pass.script 20
|
||||
holds.script 87
|
||||
37 files, 1 directory
|
||||
35 files, 2 directories
|
||||
> exit
|
||||
halted
|
||||
Execution halted.
|
||||
|
||||
+22
-4
@@ -153,12 +153,22 @@ for i in 1 2 3 4 5 6 7 8; do "$TOOL" put "$DISKS/sbfs.img" "filler$i.txt" >/dev/
|
||||
"$ROOT/Assembler" -I "$ROOT/Programs/CosmOS/Source" \
|
||||
"$ROOT/Programs/CosmOS/Apps/Depth.asm" -o "$WORK/Depth.sbx" >/dev/null
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$WORK/Depth.sbx" >/dev/null
|
||||
# Lander.sbx is Lunar Porter, and the biggest program on the disk. It takes the screen, the
|
||||
# mode and the map, so it is also the one that says a program can have all three back.
|
||||
# ---- Lunar Porter, which is the first application with a directory of its own ----
|
||||
#
|
||||
# Lander.sbx is the biggest program on the disk. It takes the screen, the mode and the map,
|
||||
# so it is also the one that says a program can have all three back.
|
||||
#
|
||||
# It does NOT go in /Apps any more. A program with assets gets /Packages/app.<name> and a
|
||||
# LAUNCHER in /Apps under the bare name that is typed - so what "Lander" names is a script,
|
||||
# which the shell runs because of what is inside it rather than what it is called. Every
|
||||
# recorded Lander test still types just "Lander" and knows nothing about any of this, which
|
||||
# is exactly the claim being made.
|
||||
"$ROOT/Assembler" -I "$ROOT/Programs/Sounds" -I "$ROOT/Programs/Libraries" \
|
||||
-I "$ROOT/Programs/CosmOS/Source" \
|
||||
"$ROOT/Programs/CosmOS/Apps/Lander.asm" -o "$WORK/Lander.sbx" >/dev/null
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$WORK/Lander.sbx" >/dev/null
|
||||
"$TOOL" mkdir "$DISKS/cosmos.img" /Packages >/dev/null
|
||||
"$TOOL" mkdir "$DISKS/cosmos.img" /Packages/app.Lander >/dev/null
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$WORK/Lander.sbx" /Packages/app.Lander/Lander.sbx >/dev/null
|
||||
# Pad.sbx says what the controllers are doing, which is the only way to tell a pad nobody
|
||||
# noticed from one that is mapped to nothing.
|
||||
"$ROOT/Assembler" -I "$ROOT/Programs/CosmOS/Source" \
|
||||
@@ -188,9 +198,14 @@ printf '#! script\nfor a in 1 2\n for b in x y\n echo $a$b\n end\nend\nset
|
||||
# Written in the tune language and compiled here, so the music can be changed without
|
||||
# touching the game. Lander reads it off the disk at startup and starts anyway if it is not
|
||||
# there, the way it treats /lander.state.
|
||||
#
|
||||
# BESIDE THE GAME rather than at the root, which is what the game now asks for: it is told
|
||||
# where it was loaded from and joins the tune's name to that. /lander.state stays at the root
|
||||
# on purpose - a saved position is the PERSON's, so it is found where the person is standing,
|
||||
# and the two of them together are the whole distinction between an asset and a document.
|
||||
"$ROOT/SoundPatch" --blob "$ROOT/Programs/Sounds/Oboe.json" Oboe "$WORK/oboe.patch" >/dev/null
|
||||
"$ROOT/TuneC" -I "$WORK" "$ROOT/Programs/Tunes/splash.score" "$WORK/splash.tune" >/dev/null
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$WORK/splash.tune" splash.tune >/dev/null
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$WORK/splash.tune" /Packages/app.Lander/splash.tune >/dev/null
|
||||
|
||||
# tune.sbx, which used to be a boot image and is now a program like any other. It brings a
|
||||
# vector of its own - the timer's, so that it has a beat to play to - which makes it the
|
||||
@@ -237,6 +252,9 @@ python3 -c "open('twoblocks.txt','w').write('the second disk, at length. ' * 20)
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$WORK/Copy.sbx" /Apps/Copy.sbx >/dev/null
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$WORK/Say.sbx" /Apps/Say.sbx >/dev/null
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$WORK/Where.sbx" /Apps/Where.sbx >/dev/null
|
||||
# And the launcher for Lunar Porter, under the bare name somebody types. Put here rather than
|
||||
# beside the game above, because /Apps is not made until now.
|
||||
"$TOOL" put "$DISKS/cosmos.img" "$ROOT/Programs/CosmOS/Launchers/Lander" /Apps/Lander >/dev/null
|
||||
# A SCRIPT in the system's place, which is the one thing on this disk that is fetched from
|
||||
# drive 0 a block at a time WHILE it runs. Its own name carries the drive in front of it,
|
||||
# and resolving a name like that moves the machine to that drive - so a script started from
|
||||
|
||||
+30
-24
@@ -1623,7 +1623,7 @@ for i in range(400):
|
||||
keys += b'\x80' + b'\x00' * 47
|
||||
open('$BUILD/lander.keys','wb').write(keys + b'\x00' * 8000)
|
||||
"
|
||||
timeout 30 "$EMU" --fast --cycles 900000 --keyboard "$BUILD/lander.keys" \
|
||||
timeout 30 "$EMU" --fast --cycles 1100000 --keyboard "$BUILD/lander.keys" \
|
||||
--screen "$BUILD/lander.ppm" --disk "$ROOT/Tests/build/disks/cosmos.img" \
|
||||
--ram-disk 2048 "$BUILD/cosmos.bin" > "$BUILD/lander.out" 2>&1 || true
|
||||
read -r MOON SKY SHIP SHIPLEFT SHIPRIGHT <<EOT
|
||||
@@ -1698,7 +1698,7 @@ print(sum(1 for o in range(0, len(px), 3) if px[o:o + 3] == moon))
|
||||
# thrusters. The gap between the two captures is what the check is made of, and it is the
|
||||
# same gap.
|
||||
python3 -c "open('$BUILD/lander.pad','wb').write(b'\x00' * 40 + b'\x08' * 400)"
|
||||
for when in 1000000 1800000; do
|
||||
for when in 1200000 2000000; do
|
||||
timeout 30 "$EMU" --fast --cycles $when --keyboard "$BUILD/lander.keys" \
|
||||
--pad "$BUILD/lander.pad" --screen "$BUILD/held$when.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
@@ -1712,7 +1712,7 @@ def top(path):
|
||||
ship = bytes.fromhex('d8c048')
|
||||
ys = [i // 320 for i in range(len(px) // 3) if px[i * 3:i * 3 + 3] == ship]
|
||||
return min(ys) if ys else -1
|
||||
print(top('$BUILD/held1000000.ppm'), top('$BUILD/held1800000.ppm'))
|
||||
print(top('$BUILD/held1200000.ppm'), top('$BUILD/held2000000.ppm'))
|
||||
" 2>/dev/null || echo "-1 -1")
|
||||
EOT
|
||||
[ "$EARLY" -gt 0 ] && [ "$LATE" -gt 0 ] && [ "$LATE" -lt "$EARLY" ] \
|
||||
@@ -1827,7 +1827,7 @@ open('$BUILD/fly.keys','wb').write(b'Lander\n' + SKIP + b'\x00' * 8000)"
|
||||
python3 -c "open('$BUILD/none.pad','wb').write(b'\x00' * 60000)"
|
||||
cp "$ROOT/Tests/build/disks/cosmos.img" "$BUILD/orbit.img"
|
||||
"$ROOT/SplitDisk" put "$BUILD/orbit.img" "$BUILD/orbit.state" /lander.state > /dev/null
|
||||
for when in 3000000 13000000 25000000 37000000; do
|
||||
for when in 3200000 13200000 25200000 37200000; do
|
||||
timeout 60 "$EMU" --fast --cycles $when --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/none.pad" --screen "$BUILD/orbit$when.ppm" \
|
||||
--disk "$BUILD/orbit.img" --ram-disk 2048 \
|
||||
@@ -1842,8 +1842,8 @@ def height(path):
|
||||
ship = [i // width for i in range(len(px) // 3)
|
||||
if px[i * 3:i * 3 + 3] == bytes.fromhex('d8c048')]
|
||||
return min(ship) if ship else -1
|
||||
print(height('$BUILD/orbit3000000.ppm'), height('$BUILD/orbit13000000.ppm'),
|
||||
height('$BUILD/orbit25000000.ppm'), height('$BUILD/orbit37000000.ppm'))
|
||||
print(height('$BUILD/orbit3200000.ppm'), height('$BUILD/orbit13200000.ppm'),
|
||||
height('$BUILD/orbit25200000.ppm'), height('$BUILD/orbit37200000.ppm'))
|
||||
" 2>/dev/null || echo "-1 -1 -1 -1")
|
||||
EOT
|
||||
# A smaller row is higher up. Fifty pixels of change either way, against turning points that
|
||||
@@ -1976,11 +1976,17 @@ EOT
|
||||
# is the drift: it grows right from the middle of the screen for a rightward one and left for
|
||||
# a leftward one, and NOUGHT DRAWS NOTHING, so "stopped" is the state with no bar at all.
|
||||
#
|
||||
# The recording holds Right for eighty frames and then nothing. Checked in two places: with a
|
||||
# drift, where the bar starts at the middle and runs right; and with none, where a sprite of
|
||||
# no width is a sprite that is not drawn.
|
||||
python3 -c "open('$BUILD/drift.pad','wb').write(b'\x00' * 20 + b'\x01' * 80 + b'\x00' * 400)"
|
||||
timeout 30 "$EMU" --fast --cycles 1600000 --keyboard "$BUILD/lander.keys" \
|
||||
# The recording holds Right for a hundred and twenty frames and then nothing. Checked in two
|
||||
# places: with a drift, where the bar starts at the middle and runs right; and with none,
|
||||
# where a sprite of no width is a sprite that is not drawn.
|
||||
#
|
||||
# IT WAS EIGHTY, AND THE PAD IS COUNTED FROM THE MACHINE STARTING rather than from the game
|
||||
# starting. A launcher put twelve frames between those two, so the game saw twelve fewer
|
||||
# frames of the burn and drew a narrower bar - which is a real reading of a real drift, and
|
||||
# nothing to do with what this check is about. Longer, so that what is being asked about is
|
||||
# whether a drift draws a bar rather than how long the pilot held the button.
|
||||
python3 -c "open('$BUILD/drift.pad','wb').write(b'\x00' * 20 + b'\x01' * 120 + b'\x00' * 400)"
|
||||
timeout 30 "$EMU" --fast --cycles 1800000 --keyboard "$BUILD/lander.keys" \
|
||||
--pad "$BUILD/drift.pad" --screen "$BUILD/drift.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
"$BUILD/cosmos.bin" > "$BUILD/drift.out" 2>&1 || true
|
||||
@@ -2343,13 +2349,13 @@ python3 -c "
|
||||
pad = bytearray(b'\x08' * 3000)
|
||||
pad[100:108] = b'\x28' * 8 # Up and B together, so the climb is not interrupted.
|
||||
open('$BUILD/hoverwide.pad','wb').write(bytes(pad) + b'\x00' * 20000)"
|
||||
for when in 2000000 3000000 5000000 7000000; do
|
||||
for when in 2200000 3200000 5200000 7200000; do
|
||||
timeout 60 "$EMU" --fast --cycles $when --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/hoverwide.pad" --screen "$BUILD/station$when.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
"$BUILD/cosmos.bin" > "$BUILD/station.out" 2>&1 || true
|
||||
done
|
||||
timeout 60 "$EMU" --fast --cycles 3000000 --keyboard "$BUILD/fly.keys" \
|
||||
timeout 60 "$EMU" --fast --cycles 3200000 --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/hovernarrow.pad" --screen "$BUILD/stationnarrow.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
"$BUILD/cosmos.bin" > "$BUILD/stationnarrow.out" 2>&1 || true
|
||||
@@ -2366,11 +2372,11 @@ def station(path, band):
|
||||
if px[i * 3:i * 3 + 3] == blue and i // width < band]
|
||||
return len(at), (min(x for x, y in at) if at else -1)
|
||||
narrow = station('$BUILD/stationnarrow.ppm', 70)
|
||||
seen, x3 = station('$BUILD/station3000000.ppm', 200)
|
||||
seen, x3 = station('$BUILD/station3200000.ppm', 200)
|
||||
print(narrow[0], seen,
|
||||
station('$BUILD/station2000000.ppm', 200)[1], x3,
|
||||
station('$BUILD/station5000000.ppm', 200)[1],
|
||||
station('$BUILD/station7000000.ppm', 200)[1])
|
||||
station('$BUILD/station2200000.ppm', 200)[1], x3,
|
||||
station('$BUILD/station5200000.ppm', 200)[1],
|
||||
station('$BUILD/station7200000.ppm', 200)[1])
|
||||
" 2>/dev/null || echo "0 0 -1 -1 -1 -1")
|
||||
EOT
|
||||
# Forty pixels is the whole of the art, so none of it is clipped and it is the tile meant.
|
||||
@@ -2640,7 +2646,7 @@ open('$BUILD/crash.state','wb').write(struct.pack('<hhhhhhBBBB',
|
||||
"
|
||||
cp "$ROOT/Tests/build/disks/cosmos.img" "$BUILD/crash.img"
|
||||
"$ROOT/SplitDisk" put "$BUILD/crash.img" "$BUILD/crash.state" /lander.state > /dev/null
|
||||
for when in 1200000 1600000 2200000; do
|
||||
for when in 1400000 1800000 2400000; do
|
||||
timeout 60 "$EMU" --fast --cycles $when --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/none.pad" --screen "$BUILD/burst$when.ppm" \
|
||||
--disk "$BUILD/crash.img" --ram-disk 2048 \
|
||||
@@ -2658,8 +2664,8 @@ def bits(path):
|
||||
return 0, 0
|
||||
xs = [x for x, y in at]
|
||||
return len(at), max(xs) - min(xs)
|
||||
e = bits('$BUILD/burst1200000.ppm'); l = bits('$BUILD/burst1600000.ppm')
|
||||
print(e[0], e[1], l[0], l[1], bits('$BUILD/burst2200000.ppm')[0])
|
||||
e = bits('$BUILD/burst1400000.ppm'); l = bits('$BUILD/burst1800000.ppm')
|
||||
print(e[0], e[1], l[0], l[1], bits('$BUILD/burst2400000.ppm')[0])
|
||||
" 2>/dev/null || echo "0 0 0 0 -1")
|
||||
EOT
|
||||
# Forty pixels in one eight wide block is the lander; anything else in its colour is what is
|
||||
@@ -2671,7 +2677,7 @@ EOT
|
||||
&& result ok "and they carry on outwards" "$EARLYWIDE pixels apart, then $LATEWIDE" \
|
||||
|| result no "and they carry on outwards" "$EARLYWIDE pixels apart, then $LATEWIDE"
|
||||
# And they are gone by the time the verdict is up, rather than hanging over the words.
|
||||
[ "$AFTERBITS" = "0" ] && grep -q "Crashed" "$BUILD/burst2200000.out" \
|
||||
[ "$AFTERBITS" = "0" ] && grep -q "Crashed" "$BUILD/burst2400000.out" \
|
||||
&& result ok "and are gone before the verdict" "nothing left over the words" \
|
||||
|| result no "and are gone before the verdict" "$AFTERBITS pixels still there"
|
||||
|
||||
@@ -2933,7 +2939,7 @@ done
|
||||
# And a plain fall onto the pad it starts over, which lands rather than crashes.
|
||||
# Eight frames later than they used to be: the landing latch plays its two notes before the
|
||||
# dust goes up, and runPend waits for the second of them.
|
||||
for when in 2900000 3050000 3300000; do
|
||||
for when in 3100000 3250000 3500000; do
|
||||
timeout 60 "$EMU" --fast --cycles $when --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/none.pad" --screen "$BUILD/dust$when.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
@@ -2953,8 +2959,8 @@ def look(path):
|
||||
puff = len([1 for x, y in where('f0f0f0') if y > 20])
|
||||
ship = where('d8c048')
|
||||
return puff, (min(y for x, y in ship) if ship else -1)
|
||||
print(look('$BUILD/dust2900000.ppm')[0], look('$BUILD/dust3050000.ppm')[0],
|
||||
look('$BUILD/dust3300000.ppm')[0],
|
||||
print(look('$BUILD/dust3100000.ppm')[0], look('$BUILD/dust3250000.ppm')[0],
|
||||
look('$BUILD/dust3500000.ppm')[0],
|
||||
look('$BUILD/gas9900000.ppm')[0], look('$BUILD/gas10150000.ppm')[0],
|
||||
look('$BUILD/gas10800000.ppm')[0],
|
||||
look('$BUILD/gas10150000.ppm')[1], look('$BUILD/gas10800000.ppm')[1])
|
||||
|
||||
@@ -186,6 +186,21 @@ PROG_DEPS = $(BINARIES:.bin=.d)
|
||||
COSMOS = $(PROG_BUILD)/CosmOS/Source/cosmos.bin
|
||||
APPS = $(patsubst $(PROG_DIR)/CosmOS/Apps/%.asm,$(PROG_BUILD)/CosmOS/Apps/%.sbx,\
|
||||
$(wildcard $(PROG_DIR)/CosmOS/Apps/*.asm))
|
||||
|
||||
# ---- Applications that have things of their own ----
|
||||
#
|
||||
# A simple program is one file and lives in /Apps. One with ASSETS gets a directory of its
|
||||
# own - /Packages/app.<name> - and a launcher in /Apps under its bare name, which is what
|
||||
# somebody actually types. The launcher is indirection: where the thing lives stops being
|
||||
# part of its name, so an installer can put it elsewhere and change one line.
|
||||
#
|
||||
# Named here rather than found, because being packaged is a decision somebody makes and not
|
||||
# something a directory listing can say. Both halves of the placing below are driven from
|
||||
# this one list, so a name added here cannot end up half moved.
|
||||
PACKAGED = Lander
|
||||
# And what each of them owns beyond its own program. A tune named here is put in its
|
||||
# package instead of at the root, where the tunes that belong to nobody in particular go.
|
||||
LANDER_TUNES = splash
|
||||
COSMOS_DISK = $(PROG_BUILD)/cosmos.img
|
||||
|
||||
# ---- A disk that is yours ----
|
||||
@@ -585,7 +600,7 @@ $(COSMOS_DISK): makefile
|
||||
#
|
||||
# Found rather than wildcarded, because the tree the mirror walks is a tree and $(wildcard)
|
||||
# does not recurse. build is left out for the reason the mirror leaves it out.
|
||||
MIRRORED := $(shell find $(PROG_DIR) \( -name '*.asm' -o -name '*.score' \) -not -path '$(PROG_BUILD)/*' 2>/dev/null)
|
||||
MIRRORED := $(shell find $(PROG_DIR) \( -name '*.asm' -o -name '*.score' -o -path '*/Launchers/*' \) -not -path '$(PROG_BUILD)/*' 2>/dev/null)
|
||||
$(COSMOS_DISK): $(MIRRORED)
|
||||
$(COSMOS_DISK): $(APPS) $(NATIVE_ASM) $(COSMOS) $(STAGE2) \
|
||||
$(PROG_DIR)/testPrograms/stringKeyword.asm \
|
||||
@@ -624,6 +639,22 @@ $(COSMOS_DISK): $(APPS) $(NATIVE_ASM) $(COSMOS) $(STAGE2) \
|
||||
$(DISKTOOL) mkdir $@ /Lib
|
||||
$(DISKTOOL) mkdir $@ /System
|
||||
$(DISKTOOL) mkdir $@ /System/Boot
|
||||
@# ---- And what applications own ----
|
||||
@#
|
||||
@# One directory per packaged application, so its files can be found together and
|
||||
@# removed together - which is the question install and remove are both made of. NOT in
|
||||
@# /Apps, for two reasons: a launcher and a directory of the same name cannot both be
|
||||
@# there, and /Apps is the directory the shell walks for every word it does not know and
|
||||
@# Tab walks for every first word, so doubling what is in it is a cost on the path that
|
||||
@# runs most.
|
||||
@#
|
||||
@# The "app." in front rather than behind is what keeps them out of the way. Tab matches
|
||||
@# the START of a name, so a prefix is a namespace and a suffix is a collision: with
|
||||
@# Copy.app beside Copy.sbx, typing Copy and pressing Tab completes to the shared "Copy."
|
||||
@# and hands you a broken word.
|
||||
$(DISKTOOL) mkdir $@ /Packages
|
||||
@for app in $(PACKAGED); do \
|
||||
$(DISKTOOL) mkdir $@ /Packages/app.$$app >/dev/null || exit 1; done
|
||||
@# The system itself, as a file, which is the whole of what boot.cfg chooses between.
|
||||
@# No boot.cfg is written: stage two falls back to this name when there is none, and a
|
||||
@# clean install having nothing to configure is the right default.
|
||||
@@ -631,8 +662,17 @@ $(COSMOS_DISK): $(APPS) $(NATIVE_ASM) $(COSMOS) $(STAGE2) \
|
||||
@# What you run. /Apps is the second place the shell looks when a word it does not know
|
||||
@# turns out to be a program, so anything in here starts by name from anywhere.
|
||||
@for app in $(APPS); do \
|
||||
$(DISKTOOL) put $@ $$app /Apps/`basename $$app` >/dev/null || exit 1; done
|
||||
name=`basename $$app .sbx`; \
|
||||
case " $(PACKAGED) " in \
|
||||
*" $$name "*) where=/Packages/app.$$name/$$name.sbx ;; \
|
||||
*) where=/Apps/$$name.sbx ;; \
|
||||
esac; \
|
||||
$(DISKTOOL) put $@ $$app $$where >/dev/null || exit 1; done
|
||||
$(DISKTOOL) put $@ $(NATIVE_ASM) /Apps/Asm.sbx
|
||||
@# The launcher goes where the program used to be, under the bare name that is typed.
|
||||
@for app in $(PACKAGED); do \
|
||||
$(DISKTOOL) put $@ $(PROG_DIR)/CosmOS/Launchers/$$app /Apps/$$app >/dev/null \
|
||||
|| exit 1; done
|
||||
@# ---- And the music, compiled ----
|
||||
@#
|
||||
@# A .score is written and a .tune is what the machine reads, the same way a .asm is
|
||||
@@ -656,7 +696,11 @@ $(COSMOS_DISK): $(APPS) $(NATIVE_ASM) $(COSMOS) $(STAGE2) \
|
||||
name=`basename $$score .score`; \
|
||||
$(TUNE_RUN) -I $(PROG_BUILD)/tunes $$score $(PROG_BUILD)/tunes/$$name.tune \
|
||||
>/dev/null || exit 1; \
|
||||
$(DISKTOOL) put $@ $(PROG_BUILD)/tunes/$$name.tune $$name.tune >/dev/null \
|
||||
case " $(LANDER_TUNES) " in \
|
||||
*" $$name "*) where=/Packages/app.Lander/$$name.tune ;; \
|
||||
*) where=$$name.tune ;; \
|
||||
esac; \
|
||||
$(DISKTOOL) put $@ $(PROG_BUILD)/tunes/$$name.tune $$where >/dev/null \
|
||||
|| exit 1; done
|
||||
@# ---- What you assemble: all of it ----
|
||||
@#
|
||||
|
||||
Reference in New Issue
Block a user