diff --git a/Programs/CosmOS/Apps/Grid.asm b/Programs/CosmOS/Apps/Grid.asm index d205365..a1e8a52 100644 --- a/Programs/CosmOS/Apps/Grid.asm +++ b/Programs/CosmOS/Apps/Grid.asm @@ -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 diff --git a/Programs/CosmOS/README.md b/Programs/CosmOS/README.md index d8943b1..c053f1f 100644 --- a/Programs/CosmOS/README.md +++ b/Programs/CosmOS/README.md @@ -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: diff --git a/Tests/periodic.py b/Tests/periodic.py index fae43cc..33445be 100644 --- a/Tests/periodic.py +++ b/Tests/periodic.py @@ -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 - diff --git a/Tests/video.sh b/Tests/video.sh index 2e99150..fc584be 100755 --- a/Tests/video.sh +++ b/Tests/video.sh @@ -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.