Lunar Porter flies on a controller

A held thruster burns every tick it is held for, which is the whole reason
the pad exists: the console can only say a key went down, so a thruster
driven by it could be pumped and never leaned on.

The burn happens on the same tick gravity does, and for the same reason -
a sixteenth of a pixel is the smallest step this arithmetic takes, and
applied sixty times a second it is an enormous acceleration. On the tick,
thrust and gravity are two numbers whose RATIO is the whole feel of the
thing. Position still moves every frame; only the acceleration is stepped,
and nothing can see that.

Two against gravity's one, so climbing and falling are the same speed.
Three was the first try and it left the moon after about a second of
holding.

If there is a pad the console's arrows are ignored, because under a window
the same keypress reaches both - the pad as a level, the console as a byte
- and a thruster that fired twice for one press would be a mystery to
anybody tuning it. q still quits, since a pad has no letter for it. With
no pad the arrows still burn once a press, which is the most that can be
done down a wire.

And break.sh now rebuilds the disk images as well as the binaries. Half
the things worth breaking here are SplitBit assembly rather than C, and
those live on the fixture disks - so an edit to a .asm file changed
nothing the suite could see, and the tool reported that nothing caught the
break. That is the exact lie it was written to prevent, turning up in a
new place. With the disks rebuilt it catches this one: the lander falls
between the two captures instead of climbing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-09-02 21:58:31 -04:00
co-authored by Claude Opus 5
parent fed1453e6e
commit b1dde7908c
14 changed files with 154 additions and 24 deletions
+94 -12
View File
@@ -59,8 +59,20 @@ start:
INIA 0x01
OUTA 0x02 ; Key mode.
; ---- Is there a controller ----
;
; Asked once. If there is, the console's arrow keys are ignored: under a window the same
; keypress reaches BOTH - the pad as a level and the console as a byte - and a thruster that
; fired twice for one press would be a mystery to anybody tuning it.
INA 0x64
INIB 0x01
AND
SETD.1 HasPad
STQ.1
everyFrame:
CALL waitFrame
CALL readPad
CALL readControls
CALL fall
CALL move
@@ -312,12 +324,23 @@ putLander:
OUTA 0xE9 ; No flags, natural size, no depth.
RET
; ---- The controls ----
; ---- What the pad is holding ----
;
; ONE KEY IS ONE BURN. The console says which key was pressed and there is no such thing as a
; key being released, so a thruster cannot be held down - what a press does is add to the
; velocity once. It reads as pumping the engine rather than leaning on it, which is a choice
; this machine makes rather than one this program did.
; One read, every button at once, and it does not go away when it is looked at. THIS IS THE
; THING THE CONSOLE CANNOT DO: a key that is down and staying down sends nothing, so a
; thruster driven by the console can only be pumped and never leaned on.
readPad:
INA 0x60
SETD.1 Held
STA.1
RET
; ---- The console, which is still worth reading ----
;
; For q, always, because a pad has no letter for it. And for the arrows on a machine with no
; controller, where one press is one burn and that is the best that can be done - it reads as
; pumping the engine, which is a thing this machine makes true rather than a thing this
; program chose.
readControls:
INA 0x01
INIB 0x01 ; READY
@@ -325,12 +348,23 @@ readControls:
BRQ noKey
INA 0x00
SETD.1 KeyHeld
STA.1
INIB 0x71 ; q, whatever else is plugged in.
CCF
SUB
BRQ quit
SETD.0 HasPad
LDA.0
BNA noKey ; There is a pad, so the arrows are its business and not this.
LDA.1 ; DP1 is still KeyHeld, from storing the key above.
INIB 0x80 ; Up
CCF
SUB
BRQ burnUp
SETD.1 KeyHeld
STA.1
LDA.1
INIB 0x82 ; Left
CCF
@@ -341,11 +375,6 @@ readControls:
CCF
SUB
BRQ burnRight
LDA.1
INIB 0x71 ; q
CCF
SUB
BRQ quit
noKey:
RET
@@ -394,6 +423,41 @@ fall:
SETD.0 SpeedDown
SETD.1 Gravity
CALL addWord
; ---- And whatever is being leaned on, on the same tick ----
;
; A held thruster fires here rather than every frame, for the reason gravity does: a
; sixteenth of a pixel is the smallest step this arithmetic takes, and applied sixty times a
; second it is an enormous acceleration. On the tick, thrust and gravity are two numbers
; whose RATIO is the whole feel of the thing, and both are one byte to change.
;
; Position still moves every frame. Only the acceleration is stepped, which nothing can see.
SETD.0 Held
LDA.0
INIB 0x08 ; Up
AND
BRQ fallNotUp
SETD.0 SpeedDown
SETD.1 PadUp
CALL addWord
fallNotUp:
SETD.0 Held
LDA.0
INIB 0x02 ; Left
AND
BRQ fallNotLeft
SETD.0 SpeedAcross
SETD.1 PadLeft
CALL addWord
fallNotLeft:
SETD.0 Held
LDA.0
INIB 0x01 ; Right
AND
BRQ fallDone
SETD.0 SpeedAcross
SETD.1 PadRight
CALL addWord
fallDone:
RET
@@ -586,12 +650,30 @@ FallEvery:
0d6 ; Gravity one frame in six. Every frame was Jupiter.
FallTick:
0d1
; A press on a machine with no pad, which has to be a whole burn because it happens once.
ThrustUp:
0xF8 0xFF ; Eight sixteenths upwards, which is minus eight.
ThrustLeft:
0xFC 0xFF ; Four to the left.
ThrustRight:
0x04 0x00
; ---- And a held one, which happens on every tick it is held for ----
;
; TWO AGAINST GRAVITY'S ONE, which makes climbing and falling the same speed: hold it and you
; rise as fast as letting go drops you. Three was the first try and it left the moon in about
; a second of holding. The ratio between these and Gravity is the whole feel of the thing and
; it is one byte each.
PadUp:
0xFE 0xFF ; Minus two.
PadLeft:
0xFE 0xFF ; Minus two.
PadRight:
0x02 0x00
Held:
0x00
HasPad:
0x00
HalfScreen:
0xA0 0x00 ; 160 pixels, which is half of a forty column screen.