The pad was working; the game was told there was not one
0x64 counted only the RECORDED pads. So a controller plugged into Voyager reported its buttons perfectly, and every game asking whether there was a controller was told no - which is exactly what Lunar Porter asked, once, at startup, before falling back to the console for the rest of the run. The cause is worth naming: a front end calls padSet every frame for every pad, so "held nothing" is the commonest thing it says and cannot also mean "there is no pad here". Connected is said separately now. Pad nought is always there behind a window, because the keyboard is behind it - which is the useful answer rather than the literal one. And Pad.asm, which is what should have existed before any of that guessing began. It prints a line whenever a pad changes, and tells apart the three states that look identical from inside a game that will not respond: one nobody noticed, one mapped to nothing, and a mapping that is wrong. WHY A PROGRAM AND NOT A PRINT IN THE FRONT END: because the question is what the MACHINE can see. A front end reporting what it thinks it is sending answers a different question, and the gap between those two is the whole of this bug. It also found that osPrintNumber takes A as the HIGH half - the same way round as the shift register and every other pair here, and not what a byte in A wants. Every value came out 256 times too big. Gravity is one frame in ten rather than six. The ratio between thrust and gravity is the feel; how often the tick comes round is how fast that feel arrives, and one in six was still touchy. Same lander, more time to think. And the verdict waits for a key. It printed and left immediately, taking the screen with it - so the one thing worth seeing, the lander sitting on the ground it had just reached, was gone before it could be looked at. 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
8eb4e4d67e
commit
df50c2f0f8
@@ -0,0 +1,162 @@
|
||||
; What the controllers are doing, as they do it.
|
||||
;
|
||||
; Prints a line whenever any pad changes: which pad, and the byte it is now reporting. That is
|
||||
; the whole of the diagnostic, and it is enough to tell apart the three things that look
|
||||
; identical from inside a game which is not responding.
|
||||
;
|
||||
; Nothing printed at all, and nought pads present: the front end never saw a controller.
|
||||
; A pad present but no lines: it is seen, and the buttons are mapped to nothing.
|
||||
; Lines that do not match the buttons pressed: the mapping is wrong rather than missing.
|
||||
;
|
||||
; ---- Why a program rather than a print in the front end ----
|
||||
;
|
||||
; Because the question is what the MACHINE can see. A front end that printed what it thought
|
||||
; it was sending would answer a different question, and the gap between those two is exactly
|
||||
; where a controller that was detected, mapped and reported still did nothing: the port that
|
||||
; says which pads exist counted only recorded ones, so a game asked whether there was a
|
||||
; controller and was told no while the buttons underneath worked perfectly.
|
||||
;
|
||||
; Written by Anachronaut
|
||||
|
||||
#Include services.asm
|
||||
|
||||
#Program
|
||||
|
||||
#Base 0x5000
|
||||
|
||||
start:
|
||||
SETD.0 Intro
|
||||
SWI osPrintString
|
||||
|
||||
; How many are there, before anybody presses anything. One bit a pad.
|
||||
SETD.0 PresentText
|
||||
SWI osPrintString
|
||||
INA 0x64
|
||||
CALL sayByte
|
||||
INIA 0x0A
|
||||
OUTA 0x00
|
||||
|
||||
INIA 0x01
|
||||
OUTA 0x02 ; Key mode, so q arrives without a Return.
|
||||
|
||||
everyFrame:
|
||||
INA 0x30
|
||||
INIB 0x01
|
||||
AND
|
||||
BRQ everyFrame ; A frame, which is when a pad's recording steps.
|
||||
|
||||
RSTA
|
||||
SETD.2 Which
|
||||
STA.2
|
||||
eachPad:
|
||||
CALL onePad
|
||||
SETD.2 Which
|
||||
LDA.2
|
||||
INCA
|
||||
STA.2
|
||||
INIB 0d4
|
||||
CCF
|
||||
SUB
|
||||
BNQ eachPad
|
||||
|
||||
; q gives the machine back. Anything else typed is ignored, because a pad test that
|
||||
; stopped on a stray keypress would be a poor thing to lean on.
|
||||
INA 0x01
|
||||
INIB 0x01
|
||||
AND
|
||||
BRQ everyFrame
|
||||
INA 0x00
|
||||
INIB 0x71 ; q
|
||||
CCF
|
||||
SUB
|
||||
BNQ everyFrame
|
||||
|
||||
RSTA
|
||||
OUTA 0x02
|
||||
SWI osExit
|
||||
|
||||
; ---- One pad, printed only when it changes ----
|
||||
;
|
||||
; A line a frame for four pads would be two hundred and forty lines a second and unreadable.
|
||||
; What is worth seeing is the moment something goes down or comes up.
|
||||
onePad:
|
||||
; The port is 0x60 plus the pad number, and a port is an immediate byte inside the
|
||||
; instruction that names it - so it cannot be computed, and the four are written out.
|
||||
SETD.2 Which
|
||||
LDA.2
|
||||
BRA padZero
|
||||
DECA
|
||||
BRA padOne
|
||||
DECA
|
||||
BRA padTwo
|
||||
INA 0x63
|
||||
BRI padGot
|
||||
padZero:
|
||||
INA 0x60
|
||||
BRI padGot
|
||||
padOne:
|
||||
INA 0x61
|
||||
BRI padGot
|
||||
padTwo:
|
||||
INA 0x62
|
||||
|
||||
padGot:
|
||||
; Against what it was last time. Last is four bytes, one a pad, so DP1 walks to this one.
|
||||
SETD.1 Last
|
||||
PSHA
|
||||
SETD.2 Which
|
||||
LDA.2
|
||||
DPUA.1
|
||||
POPA
|
||||
LDB.1
|
||||
CCF
|
||||
SUB
|
||||
BRQ padSame ; The same as last frame, so there is nothing to say.
|
||||
|
||||
STA.1 ; Remembered, so the next frame has something to compare with.
|
||||
PSHA
|
||||
LDA.2 ; DP2 is still Which, from working out where in Last to look.
|
||||
INIB 0x30 ; '0'
|
||||
CCF
|
||||
ADD
|
||||
OUTQ 0x00
|
||||
INIA 0x3A ; ':'
|
||||
OUTA 0x00
|
||||
INIA 0x20
|
||||
OUTA 0x00
|
||||
POPA
|
||||
CALL sayByte
|
||||
INIA 0x0A
|
||||
OUTA 0x00
|
||||
padSame:
|
||||
RET
|
||||
|
||||
; ---- One byte, as a number ----
|
||||
;
|
||||
; osPrintNumber takes A and B TOGETHER, A being the high half - which is the same way round as
|
||||
; the shift register and every other pair on this machine, and is not what a byte in A wants.
|
||||
; Passed as it stood, every value came out two hundred and fifty six times too big.
|
||||
sayByte:
|
||||
RSTB
|
||||
CCF
|
||||
ADD
|
||||
MVQB ; The byte, in the low half where it belongs.
|
||||
RSTA ; And nothing in the high one.
|
||||
SWI osPrintNumber
|
||||
RET
|
||||
|
||||
#Data
|
||||
|
||||
#Base 0x3000
|
||||
|
||||
Intro:
|
||||
"Press buttons on a controller. q quits.
|
||||
"
|
||||
PresentText:
|
||||
"Pads present, as a bit each: "
|
||||
|
||||
; One byte a pad, holding what it said last frame.
|
||||
Last:
|
||||
0x00 0x00 0x00 0x00
|
||||
Which:
|
||||
0x00
|
||||
Reference in New Issue
Block a user