Files
SplitBit-Emulator/Tests/periodic.py
T
AnachronautandClaude Opus 5 1aa45fcfc4 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
2026-08-30 19:00:28 -04:00

43 lines
1.9 KiB
Python

# Two questions video.sh cannot ask of a picture that moves.
#
# Grid scrolls a pixel a frame, so nothing can be asked about a particular pixel: whether
# pixel 4 is a grid line depends on which frame this is. Both questions below are true of the
# picture whatever the fine scroll offset happens to be.
#
# grid - is this a grid of one repeated tile? Periodic every eight pixels across, and
# not all one colour.
# bands - does the attribute nibble recolour each cell row? The colours found in one band
# of eight rows differ from those in the next, whatever the ground is doing.
import sys
data = open(sys.argv[1], "rb").read()
fields = data.split(b"\n", 3)
width = int(fields[1].split()[0])
body = fields[3]
def pixel(x, y):
at = (y * width + x) * 3
return tuple(body[at:at + 3])
if sys.argv[2] == "grid":
# ---- 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 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 -
# and looking at the whole band finds it without knowing where in the band it is.
first = set(pixel(0, y) for y in range(8))
second = set(pixel(0, y) for y in range(8, 16))
print("yes" if first != second else "the same in both: %s" % sorted(first))