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
@@ -371,11 +371,30 @@ burnRight:
|
||||
CALL addWord
|
||||
RET
|
||||
|
||||
; Gravity, which is the same small number every frame and the reason this is a game.
|
||||
; ---- Gravity, which is the reason this is a game ----
|
||||
;
|
||||
; NOT EVERY FRAME. One sixteenth of a pixel per frame per frame is the smallest step this
|
||||
; arithmetic can take and it is still far too much - it crossed the screen in a second and
|
||||
; flew like a gas giant. So it is applied one frame in FallEvery, which divides the pull by
|
||||
; that much and costs a byte and a compare.
|
||||
;
|
||||
; The alternative was a finer unit for velocity than for position, which means a shift every
|
||||
; time one is added to the other, twice a frame, for ever. A counter is cheaper and it is one
|
||||
; byte to change while the feel is being found.
|
||||
fall:
|
||||
SETD.1 FallTick
|
||||
LDA.1
|
||||
DECA
|
||||
STA.1
|
||||
BNA fallDone
|
||||
SETD.1 FallEvery
|
||||
LDA.1
|
||||
SETD.1 FallTick
|
||||
STA.1
|
||||
SETD.0 SpeedDown
|
||||
SETD.1 Gravity
|
||||
CALL addWord
|
||||
fallDone:
|
||||
RET
|
||||
|
||||
; ---- Where it is now ----
|
||||
@@ -425,7 +444,7 @@ follow:
|
||||
SETD.0 PixelLow
|
||||
LDB.0
|
||||
CALL eighth
|
||||
OUTA 0x36 ; The column origin.
|
||||
OUTQ 0x36 ; The column origin. IN Q, because RET puts A back.
|
||||
RET
|
||||
|
||||
; ---- The lander, put where it now is ----
|
||||
@@ -514,7 +533,16 @@ toPixels:
|
||||
; Three turns right is a divide by eight, and a moon 1024 pixels round is 128 columns, so the
|
||||
; whole answer is in the low half and the high half is the bits that rotated out of it.
|
||||
;
|
||||
; B cannot be read. Adding nothing to it puts it in Q, which can be moved.
|
||||
; ---- And the answer comes back in Q ----
|
||||
;
|
||||
; It came back in A first, which is a lie a subroutine cannot tell: RET puts A back the way it
|
||||
; found it, so the caller wrote out the high byte of the position it had passed in. The fine
|
||||
; register was computed inline and was right, the coarse register was not, and the picture
|
||||
; scrolled smoothly within a cell and never advanced one. Q is the only register that crosses
|
||||
; a RET, which is why every answer in this program comes back in it.
|
||||
;
|
||||
; B cannot be read at all. Adding nothing to it puts it in Q, which is where this wanted to
|
||||
; be anyway.
|
||||
eighth:
|
||||
SHR
|
||||
SHR
|
||||
@@ -522,7 +550,6 @@ eighth:
|
||||
RSTA
|
||||
CCF
|
||||
ADD
|
||||
MVQA
|
||||
RET
|
||||
|
||||
waitFrame:
|
||||
@@ -550,14 +577,21 @@ SpeedAcross:
|
||||
SpeedDown:
|
||||
0x00 0x00
|
||||
|
||||
; ---- The four numbers the feel lives in ----
|
||||
;
|
||||
; Adjacent on purpose, because tuning them is what the first rung is for.
|
||||
Gravity:
|
||||
0x01 0x00
|
||||
FallEvery:
|
||||
0d6 ; Gravity one frame in six. Every frame was Jupiter.
|
||||
FallTick:
|
||||
0d1
|
||||
ThrustUp:
|
||||
0xEC 0xFF ; Twenty sixteenths upwards, which is minus twenty.
|
||||
0xF8 0xFF ; Eight sixteenths upwards, which is minus eight.
|
||||
ThrustLeft:
|
||||
0xF8 0xFF ; Eight sixteenths to the left.
|
||||
0xFC 0xFF ; Four to the left.
|
||||
ThrustRight:
|
||||
0x08 0x00
|
||||
0x04 0x00
|
||||
HalfScreen:
|
||||
0xA0 0x00 ; 160 pixels, which is half of a forty column screen.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user