The coarse scroll register was being sent the wrong register
CALL eighth OUTA 0x36 RET puts A back the way it found it, so the column origin was written the high byte of the position that had been passed in, and the answer the subroutine had worked out went nowhere. The fine register was computed inline with OUTQ and was correct, which is exactly what it looked like from the outside: smooth scrolling within a cell that never advanced one. Q is the only register that crosses a RET. Every other answer in this program already came back in it; this one had been written as if A would do, and A very nearly does, which is what makes it worth a comment rather than a fix. Gravity was Jupiter's. A sixteenth of a pixel per frame per frame is the smallest step this arithmetic can take and it crossed the screen in a second, so it is applied one frame in six instead - which divides the pull by six and costs a byte and a compare. The alternative was a finer unit for velocity than for position, and that means a shift every time one is added to the other, twice a frame, for ever. And the check that catches all this now looks 1.5 million cycles in rather than twelve. The first number came from assuming a program that saves a whole screen takes a long time to start; it does not, and by twelve million the lander had flown seven hundred frames and left the picture. A capture near the beginning is worth more than a tuned one - there is less between it and the start that can move. 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
d6c81fa32c
commit
88ecb208f4
+13
-7
@@ -1525,17 +1525,23 @@ EOT
|
||||
# takes the screen, changes the mode, redefines tiles, fills all 3,200 cells of the map from a
|
||||
# terrain it generated, and moves a sprite over it every frame.
|
||||
#
|
||||
# The keys are a burn of the lifting thruster every sixteenth frame, which is more than the
|
||||
# gravity and so keeps the lander up long enough to be looked at. The cycle count is tuned to
|
||||
# catch it before it climbs off the top; if CosmOS's size shifts the boot far enough, the
|
||||
# lander check fails saying it is not on screen, which is a request to re-tune.
|
||||
# A burn of the lifting thruster every forty eighth frame, which is exactly the gravity: one
|
||||
# sixteenth of a pixel every sixth frame against eight every forty eighth. Exactly cancelling
|
||||
# the ACCELERATION still leaves an average velocity, so it drifts upward slowly and this is
|
||||
# caught early rather than left to settle.
|
||||
#
|
||||
# EARLY, and that is the point of 1.5 million cycles. This program starts almost at once - the
|
||||
# first guess at where to look was ten million cycles in, on the assumption that taking a
|
||||
# screen was expensive, and by then the lander had flown 700 frames and left the picture. A
|
||||
# capture near the start is worth far more than a tuned one: there is much less between it and
|
||||
# the beginning that can move.
|
||||
python3 -c "
|
||||
keys = b'Lander\n'
|
||||
for i in range(400):
|
||||
keys += b'\x80' + b'\x00' * 15
|
||||
open('$BUILD/lander.keys','wb').write(keys + b'\x00' * 4000)
|
||||
keys += b'\x80' + b'\x00' * 47
|
||||
open('$BUILD/lander.keys','wb').write(keys + b'\x00' * 8000)
|
||||
"
|
||||
timeout 30 "$EMU" --fast --cycles 12000000 --keyboard "$BUILD/lander.keys" \
|
||||
timeout 30 "$EMU" --fast --cycles 1500000 --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
|
||||
|
||||
Reference in New Issue
Block a user