Two zoom levels on a button, which the device already had
Forty columns and eighty are the same map, the same 8x8 cells and the same engine; only how many of them fit differs. The map is 128 by 128 either way and the moon is exactly 128 columns of it. And the front end scales whatever it is handed by the largest whole number that fits, so 320 by 200 at four times and 640 by 400 at twice fill the same glass. So the two modes ARE two zoom levels and nothing in the video device had to change to get them: forty columns shows under a third of the moon at twice the size, eighty shows nearly two thirds. Out for the orbit, in for the landing, and B says which. What did have to change is every screen coordinate in Lander, because the middle of the screen is 160 on one and 320 on the other. They now live in one block that setView copies over from whichever of two tables matches the mode, so a gauge reads a variable and never has to know which screen it is on. Several coordinates became sixteen bit on the way, since 620 will not go in a byte. follow already read HalfScreen and showLander already writes the world position straight through, so the lander itself needed nothing but its resting column. The moon is redrawn on a swap because it is filled as many rows deep as the mode shows, and a moon drawn 25 deep on a screen showing 50 floats over nothing. The swap is edge triggered. A pad is LEVEL and not an event, so a view that swapped while B was down would swap sixty times a second - which is not a zoom, it is a strobe, and it redraws the whole moon each time. The check for that holds the button for three hundred frames and requires the lander to land where a six frame tap left it; with the edge dropped it ends seventeen pixels adrift, which is the strobe costing it frames. Four checks, each seen to fail on its own break. The README's Lander entry also still described the relief orbit that the previous commit replaced, and now describes the one that is there.
This commit is contained in:
@@ -2032,6 +2032,71 @@ EOT
|
||||
&& result ok "orbital speed is marked on the drift bar" "64 pixels either side of the middle" \
|
||||
|| result no "orbital speed is marked on the drift bar" "marks at $MARKS"
|
||||
|
||||
# ---- Two zoom levels, on a button ----
|
||||
#
|
||||
# Forty columns and eighty are the same map, the same 8x8 cells and the same engine - and the
|
||||
# front end scales whatever it is handed up to the same window, so 320 by 200 and 640 by 400
|
||||
# fill the same glass. THE MODES ARE ALREADY A ZOOM, and nothing in the video device had to
|
||||
# change to get one. What had to change is every screen coordinate in Lander, because the
|
||||
# middle of the screen is 160 on one and 320 on the other.
|
||||
#
|
||||
# So the check is that the whole panel MOVED WITH THE MIDDLE and none of it stayed behind: the
|
||||
# lander at the centre of whichever screen it is on, and the orbital marks still 64 pixels
|
||||
# either side of that centre. A check on the picture size alone would pass with the gauges
|
||||
# still huddled in the top left corner.
|
||||
#
|
||||
# The third flight HOLDS the button for three hundred frames. A pad is level and not an event,
|
||||
# so a view that swapped on the level would swap sixty times a second - and the way that shows
|
||||
# is not only the mode it lands on but the TIME it costs, because each swap redraws the whole
|
||||
# moon. Holding is checked to land in the same place as tapping, which a strobe cannot do.
|
||||
python3 -c "open('$BUILD/narrow.pad','wb').write(b'\x00' * 8000)"
|
||||
python3 -c "open('$BUILD/tap.pad','wb').write(b'\x00' * 30 + b'\x20' * 6 + b'\x00' * 8000)"
|
||||
python3 -c "open('$BUILD/hold.pad','wb').write(b'\x00' * 30 + b'\x20' * 300 + b'\x00' * 8000)"
|
||||
for view in narrow tap hold; do
|
||||
timeout 60 "$EMU" --fast --cycles 2200000 --keyboard "$BUILD/fly.keys" \
|
||||
--pad "$BUILD/$view.pad" --screen "$BUILD/$view.ppm" \
|
||||
--disk "$ROOT/Tests/build/disks/cosmos.img" --ram-disk 2048 \
|
||||
"$BUILD/cosmos.bin" > "$BUILD/$view.out" 2>&1 || true
|
||||
done
|
||||
read -r NARROW WIDE HELD NSHIP WSHIP NMARKS WMARKS TAPY HELDY <<EOT
|
||||
$(python3 -c "
|
||||
def look(path):
|
||||
d = open(path, 'rb').read()
|
||||
head = d[:40].split()
|
||||
width = int(head[1])
|
||||
px = d[d.index(b'255\n') + 4:]
|
||||
def where(colour):
|
||||
c = bytes.fromhex(colour)
|
||||
return [(i % width, i // width) for i in range(len(px) // 3)
|
||||
if px[i * 3:i * 3 + 3] == c]
|
||||
ship = where('d8c048')
|
||||
marks = sorted(set(x for x, y in where('c860c0') if x > 25))
|
||||
return (width,
|
||||
'%d-%d' % (min(x for x, y in ship), max(x for x, y in ship)) if ship else 'none',
|
||||
','.join(str(x) for x in marks) or 'none',
|
||||
min(y for x, y in ship) if ship else -1)
|
||||
n = look('$BUILD/narrow.ppm'); w = look('$BUILD/tap.ppm'); h = look('$BUILD/hold.ppm')
|
||||
print(n[0], w[0], h[0], n[1], w[1], n[2], w[2], w[3], h[3])
|
||||
" 2>/dev/null || echo "0 0 0 none none none none -1 -2")
|
||||
EOT
|
||||
[ "$NARROW" = "320" ] && [ "$WIDE" = "640" ] \
|
||||
&& result ok "B swaps forty columns for eighty" "320 across, then 640 of the same map" \
|
||||
|| result no "B swaps forty columns for eighty" "$NARROW then $WIDE"
|
||||
# Forty pixels of lander in both, so none of it is clipped, and centred in both, so the whole
|
||||
# panel moved rather than the picture merely getting bigger around it.
|
||||
[ "$NSHIP" = "156-163" ] && [ "$WSHIP" = "316-323" ] \
|
||||
&& result ok "and the lander is centred in either" "156 on the narrow one, 316 on the wide" \
|
||||
|| result no "and the lander is centred in either" "$NSHIP then $WSHIP"
|
||||
[ "$NMARKS" = "94,95,224,225" ] && [ "$WMARKS" = "254,255,384,385" ] \
|
||||
&& result ok "and orbital speed is still 64 either side" "the marks moved with the middle" \
|
||||
|| result no "and orbital speed is still 64 either side" "$NMARKS then $WMARKS"
|
||||
# One press is one swap. A level triggered one would flip every frame and redraw the moon
|
||||
# every frame with it, which costs about a frame and a half each time: the lander would be
|
||||
# somewhere else entirely by now.
|
||||
[ "$TAPY" = "$HELDY" ] && [ "$HELD" = "640" ] \
|
||||
&& result ok "and holding it swaps once, not sixty times a second" "held lands where tapped did" \
|
||||
|| result no "and holding it swaps once, not sixty times a second" "tapped $TAPY, held $HELDY at $HELD across"
|
||||
|
||||
# ---- Clearing puts the cursor back at the top ----
|
||||
#
|
||||
# A screen with nothing on it and a cursor half way down it is not a cleared screen. This
|
||||
|
||||
Reference in New Issue
Block a user