Grid: fill the map, not the window
Scrolling sideways walked off the end of what the program had filled, so the grid went blank for six seconds and then came round again. A map row holds 128 cells - 256 bytes at two a cell, whatever mode the screen is in - and an eighty column screen shows eighty of them, so 48 were empty. This is the third thing this loop has counted and the first right one. It said forty, which filled half the screen. Then it asked the screen how wide it was, which fixed what could be seen and was still wrong. ASKING THE SCREEN IS RIGHT FOR FILLING A SCREEN AND WRONG FOR FILLING A MAP: a program writing one screenful wants the window, and a program that scrolls wants everything the window can be moved over. There is no register for that because it is a property of video memory rather than of the display. The check that should have caught it did not, and that is the more useful half. periodic.py looked at 32 pixels - four cells at the left edge - so it could not see a gap that was on the right, and at the cycle count it samples the origin had moved to column 22 and the gap was off in the middle distance. It reads the whole scanline now and says which column the picture stops repeating at, which is how the two failures above were told apart. 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
bcd42e75ca
commit
1aa45fcfc4
@@ -349,13 +349,21 @@ everyRow:
|
||||
SETD.0 RowAttribute
|
||||
STQ.0
|
||||
|
||||
; ---- How wide the screen is, asked rather than assumed ----
|
||||
; ---- The map's width, which is not the screen's ----
|
||||
;
|
||||
; This said forty, and filled exactly half of an eighty column screen. CosmOS asks for the
|
||||
; wide mode when it starts, because its own help text is seventy-four characters across -
|
||||
; so a program that assumes the shape the MACHINE wakes up in is wrong about the shape the
|
||||
; SYSTEM is running in. The screen will say if it is asked.
|
||||
INA 0x32
|
||||
; A hundred and twenty-eight, because that is how many cells a map row holds: 256 bytes at
|
||||
; two bytes a cell, whatever mode the screen is in. It is a property of video memory rather
|
||||
; than of the display, so there is no register to ask and nothing to ask it of.
|
||||
;
|
||||
; This said forty first, and filled half of an eighty column screen. Then it asked the
|
||||
; screen how wide it was, which fixed what could be seen and was still wrong: scrolling
|
||||
; sideways walked off the 80 filled columns into the 48 that were not, and the grid went
|
||||
; blank for six seconds before coming round again.
|
||||
;
|
||||
; ASKING THE SCREEN IS RIGHT FOR FILLING A SCREEN AND WRONG FOR FILLING A MAP. A program
|
||||
; that writes one screenful wants the window; a program that scrolls wants everything the
|
||||
; window can be moved over.
|
||||
INIA 0d128
|
||||
SETD.0 RowCells
|
||||
STA.0
|
||||
|
||||
|
||||
@@ -690,6 +690,12 @@ carries. The map is 128 rows and 128 columns against a screen of 50 and 80, so t
|
||||
around the edge are already drawn - scrolling moves the origin rather than 2,000 bytes of
|
||||
screen, and what leaves the top has not gone anywhere.
|
||||
|
||||
It fills **all 128 columns of every map row**, not the eighty the screen shows. That is the
|
||||
distinction a scrolling program has to make: asking the screen how wide it is - which there is
|
||||
a register for - gives you the window, and a program that scrolls wants everything the window
|
||||
can be moved over. Filling only the window leaves 48 empty columns, and scrolling sideways
|
||||
walks into them.
|
||||
|
||||
The coarse registers move a whole cell and the fine ones move the remainder, and **they do not
|
||||
carry into each other**, so the program does:
|
||||
|
||||
|
||||
+10
-4
@@ -22,11 +22,17 @@ def pixel(x, y):
|
||||
|
||||
|
||||
if sys.argv[2] == "grid":
|
||||
row = [pixel(x, 4) for x in range(32)]
|
||||
periodic = all(row[x] == row[x + 8] for x in range(24))
|
||||
# ---- The WHOLE scanline, not the first few cells ----
|
||||
#
|
||||
# This looked at 32 pixels, which is four cells at the left edge, and so could not see a
|
||||
# program that had filled part of the map and scrolled off the end of what it filled. The
|
||||
# gap was on the right and nothing was looking there. A gap anywhere breaks periodicity at
|
||||
# its two edges, so the full width finds it wherever it is.
|
||||
row = [pixel(x, 4) for x in range(width)]
|
||||
bad = [x for x in range(width - 8) if row[x] != row[x + 8]]
|
||||
varied = len(set(row)) > 1
|
||||
print("yes" if periodic and varied else
|
||||
"not periodic" if not periodic else "all one colour")
|
||||
print("yes" if not bad and varied else
|
||||
"breaks at column %d" % bad[0] if bad else "all one colour")
|
||||
else:
|
||||
# A band is eight rows, which is one cell row wherever the boundary has slid to. The
|
||||
# ground is the same under every scheme, so what tells them apart is the line colour -
|
||||
|
||||
@@ -813,6 +813,20 @@ if [ -f "$BUILD/grid.ppm" ]; then
|
||||
&& result ok "a program drew a grid of its own tile" "the picture repeats every eight pixels" \
|
||||
|| result no "a program drew a grid of its own tile" "not a grid of one tile ($GRIDLIKE)"
|
||||
|
||||
# ---- And still a grid once it has scrolled off the filled part ----
|
||||
#
|
||||
# A map row holds 128 cells and an eighty column screen shows eighty of them, so a
|
||||
# program that fills what the SCREEN is wide leaves 48 columns empty - and scrolling
|
||||
# sideways walks into them. The grid went blank for six seconds and came back. Twenty
|
||||
# million cycles is well past where that happened.
|
||||
timeout 30 "$EMU" --fast --cycles 20000000 --keyboard "$BUILD/grid.keys" \
|
||||
--screen "$BUILD/gridfar.ppm" --disk "$ROOT/Tests/build/disks/cosmos.img" \
|
||||
"$BUILD/cosmos.bin" > "$BUILD/gridfar.out" 2>&1 || true
|
||||
FARGRID="$(python3 "$ROOT/Tests/periodic.py" "$BUILD/gridfar.ppm" grid)"
|
||||
[ "$FARGRID" = "yes" ] \
|
||||
&& result ok "and is still one after scrolling a long way" "no gap where the map ran out" \
|
||||
|| result no "and is still one after scrolling a long way" "$FARGRID"
|
||||
|
||||
# The attribute nibble adds sixteen to every index in the tile, so consecutive map rows
|
||||
# come out in consecutive schemes. Eight pixels apart is one cell row apart whatever the
|
||||
# fine offset is, so this one survives the scrolling too.
|
||||
|
||||
Reference in New Issue
Block a user