A window: a layer that does not scroll
The map moves and this does not, which the map alone cannot express. The scroll registers move ALL of it, so a score printed into the map slides away, and one printed into whichever rows the view happens to be showing jumps a pixel at a time as the fine offset changes. Port 0x3D is how many rows tall and 0x3E is which row it starts at. Nought tall is no window, so a cleared screen has none and every program written before this means what it meant. A start row is a register because a status bar along the bottom is as common as one along the top. IT HAS ITS OWN MEMORY, and that is the argument for it. The cheaper design draws the top rows of the MAP without the scroll applied - no new memory, one register - and makes those rows part of the playfield's ring, so a game that scrolls vertically has to route its world around its own scoreboard for ever. The point of a status bar is that it is not somewhere in the level. Lunar Porter does not scroll vertically today and will the moment an orbit is a thing you can reach. 0xC000 in the screen bank, which the map does not reach: it ends at 0xBFFF. Same cells, same tiles, same pages, same schemes. Being in the screen bank makes it per screen, so flipping the buffer flips the status bar with it - what a double buffered game wants, and surprising the other way round. Drawn over everything, sprites included. A sprite that could cover the fuel gauge would be a bug in every game that had both. Tile modes only. In bitmap mode the picture is using that memory, so a bitmap program pins things to the screen with sprites, which are in screen coordinates for the same reason. 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
e3eccd17a8
commit
17c8da111f
@@ -202,6 +202,15 @@ pageTile() {
|
||||
pokeAtlasRun "$(( $1 * 0x4000 + $2 * 64 ))" "$3" 64
|
||||
}
|
||||
|
||||
# One cell of the window layer, which is 0xC000 in the screen bank and a page a row, exactly
|
||||
# as the map is - the same cells, and never anywhere near the map's own rows.
|
||||
pokeWindow() {
|
||||
# pokeWindow <row> <column> <tile> <attribute>
|
||||
local at=$(( 0xC000 + $1 * 256 + $2 * 2 ))
|
||||
pokeScreen "$at" "$3"
|
||||
pokeScreen "$(( at + 1 ))" "$4"
|
||||
}
|
||||
|
||||
# The top half one index and the bottom half another, which is how a tile gets a hole in it:
|
||||
# index nought is what a sprite does not draw.
|
||||
halfTile() {
|
||||
@@ -745,6 +754,75 @@ echo "Checking what the video device draws."
|
||||
&& result ok "a size past the screen is clipped" "it filled the screen and stopped there" \
|
||||
|| result no "a size past the screen is clipped" "$(pixel spritehuge 0 0) $(pixel spritehuge 319 199)"
|
||||
|
||||
# ---- A window, which does not scroll ----
|
||||
#
|
||||
# The map is scrolled five rows and three pixels, and the window cell has to come out at the
|
||||
# same place it would with neither. That is the entire feature: a window cell is at a SCREEN
|
||||
# position, where a map cell is at a position in a world the screen is looking at part of.
|
||||
{ prologue
|
||||
spriteColours
|
||||
solidTile 1 0x01
|
||||
pokeWindow 0 2 0x01 0x00
|
||||
port 0x3D 0x01 # One row tall.
|
||||
port 0x3E 0x00 # At the top.
|
||||
port 0x34 0x05 # And the map five rows down and three pixels into a cell.
|
||||
port 0x38 0x03
|
||||
epilogue
|
||||
} | run window || exit 1
|
||||
[ "$(pixel window 16 0)" = "255,0,0" ] && [ "$(pixel window 23 7)" = "255,0,0" ] \
|
||||
&& result ok "a window cell sits where the screen is" "the scroll registers did not move it" \
|
||||
|| result no "a window cell sits where the screen is" "$(pixel window 16 0) and $(pixel window 23 7)"
|
||||
[ "$(pixel window 24 0)" = "0,0,0" ] \
|
||||
&& result ok "and stops where it ends" "one cell wide, and the next is not it" \
|
||||
|| result no "and stops where it ends" "got $(pixel window 24 0)"
|
||||
|
||||
# ---- Where it starts is its own register ----
|
||||
#
|
||||
# A status bar along the bottom is as common as one along the top, and working the row out
|
||||
# from the screen height is a sum every program would otherwise do again.
|
||||
{ prologue
|
||||
spriteColours
|
||||
solidTile 1 0x01
|
||||
pokeWindow 0 2 0x01 0x00
|
||||
port 0x3D 0x01
|
||||
port 0x3E 10 # Ten rows down, which is eighty pixels. Shell arithmetic, so
|
||||
# ten and not 0d10 - that is the assembler's notation and this
|
||||
# is a printf away from being an INIA.
|
||||
epilogue
|
||||
} | run windowat || exit 1
|
||||
[ "$(pixel windowat 16 80)" = "255,0,0" ] && [ "$(pixel windowat 16 0)" = "0,0,0" ] \
|
||||
&& result ok "and it starts where it is told" "row ten, and nothing at the top" \
|
||||
|| result no "and it starts where it is told" "at 80 $(pixel windowat 16 80), at 0 $(pixel windowat 16 0)"
|
||||
|
||||
# ---- Over everything, sprites included ----
|
||||
#
|
||||
# A sprite that could cover the fuel gauge would be a bug in every game that had both.
|
||||
{ prologue
|
||||
spriteColours
|
||||
solidTile 1 0x01; solidTile 2 0x02
|
||||
pokeWindow 0 2 0x01 0x00
|
||||
spriteAt 0 2 0x00 16 0 0x11 0x00
|
||||
port 0x3D 0x01
|
||||
epilogue
|
||||
} | run windowover || exit 1
|
||||
[ "$(pixel windowover 16 0)" = "255,0,0" ] \
|
||||
&& result ok "a window covers a sprite" "the bar wins, which is what a bar is for" \
|
||||
|| result no "a window covers a sprite" "got $(pixel windowover 16 0)"
|
||||
|
||||
# ---- And none of it happens until it is asked for ----
|
||||
#
|
||||
# Nought rows is no window, so a cleared screen has none and every program written before this
|
||||
# existed means what it meant. The cell is written and the height is not set.
|
||||
{ prologue
|
||||
spriteColours
|
||||
solidTile 1 0x01
|
||||
pokeWindow 0 2 0x01 0x00
|
||||
epilogue
|
||||
} | run windowoff || exit 1
|
||||
[ "$(pixel windowoff 16 0)" = "0,0,0" ] \
|
||||
&& result ok "no height is no window" "written, and not drawn" \
|
||||
|| result no "no height is no window" "got $(pixel windowoff 16 0)"
|
||||
|
||||
# ---- Two screens, and the flip between them ----
|
||||
#
|
||||
# One red cell in each screen, in different rows: row one of the screen being shown, and the
|
||||
|
||||
Reference in New Issue
Block a user