Atari ST Shifter Screen Fetching: Base Registers, Address Counter, and MMU Timing
Track Atari ST screen-base alignment, Shifter fetch addresses, resolution-dependent memory use, and MMU arbitration across ST and STE hardware.
The Atari ST display is produced by cooperation among the GLUE, MMU, and Shifter. The GLUE generates sync, blanking, and display-enable signals; the MMU schedules RAM reads and arbitrates CPU/video access; the Shifter turns fetched words into pixels and applies its palette. Screen memory is ordinary system RAM, so an address register alone cannot explain what appears on a given scanline. An accurate model also needs fetch progression, resolution mode, bus ownership, and the model-specific register behavior of ST versus STE machines.
The programmer reference Atari ST Internals documents screen-base, video-address-counter, resolution, and STE-specific registers. MAME’s Atari ST video implementation explains the timing division among GLUE, MMU, and Shifter and exposes its video-fetch schedule. The register documentation is the primary basis for software-visible behavior; MAME is a transparent, testable implementation reference for cycle-level interpretation, not a measurement of a particular board revision.
Screen base and live fetch counter are distinct
The screen-base registers describe where the display memory begins. On a standard ST, $FFFF8201 supplies the high byte and $FFFF8203 the middle byte. The low byte is not present as a writable base-address register on the original ST, so its display base is aligned to a 256-byte boundary. The STE adds $FFFF820D as a low-byte register, with the bottom bit unused; that allows finer base positioning on an even-byte boundary.
The video address counter is a separate set of registers: $FFFF8205, $FFFF8207, and $FFFF8209 expose the current address being read by the Shifter/MMU path. On an ST, these are read-only status; the programmer reference marks them writable on STE. That difference matters for raster effects. Reading the counter tells software where scanout has progressed, while writing the STE counter can reposition video fetching. Treating a base write and a live-counter write as the same operation breaks code that changes the display source in the middle of a frame.
The counter is split across multiple byte reads and is not necessarily an atomic snapshot. The value can advance between accesses. Software that needs a stable 24-bit address can use a retry or high-low-high consistency check. Emulation should preserve the machine’s read semantics and any documented latch behavior, while avoiding a host-side convenience API that returns a frozen three-byte value when the hardware exposes a moving counter.
The address registers should be decoded in the configured model. An ST will ignore or lack the STE low-byte facility; an emulator must not silently accept unsupported writes as if the machine were an STE. Conversely, STE tests should verify both the low-bit alignment and the additional screen-base behavior. This is one reason to keep machine identity in the memory-mapped I/O layer rather than one global Atari video register struct with every feature always enabled.
Resolution selects the fetch geometry
The ST Shifter supports three principal screen modes described in Atari ST Internals: low resolution at 320 by 200 with four bitplanes, medium resolution at 640 by 200 with two bitplanes, and high-resolution monochrome at 640 by 400 with one bitplane. The display width and number of data planes change how many memory words are needed to produce a group of pixels and how quickly the address counter advances.
In planar color modes, a bit from each plane contributes to a pixel’s palette index. In low resolution, four bitplanes provide a four-bit color index. Medium resolution uses two bitplanes for a two-bit index. High resolution carries a single monochrome plane. An emulator should fetch and combine the actual plane words according to the current mode; it should not convert a packed chunky framebuffer and then increment the hardware counter by a guessed line width.
Video software can change resolution or palette at raster boundaries, and demos often mix parts of different modes. The GLUE display-enable and sync counters determine which pixels are visible; the Shifter’s output mode determines how fetched bits become pixels. A mode change in the middle of active display may affect the following fetch group or change the pixel clock phase according to the actual hardware. Apply writes at the correct bus event rather than redrawing the whole line under the last mode seen at VBL.
Screen-base alignment, horizontal scroll state, and the data-fetch schedule are related but not interchangeable. STE hardware adds a low-order base register and additional scroll-related controls, whereas the original ST relies on coarser base alignment and software raster timing. Document the selected capabilities separately so a low-byte screen-base trick is not mistakenly attributed to the base ST.
MMU arbitration interleaves CPU and video accesses
The MMU, not the Shifter alone, controls access to shared RAM. MAME’s implementation describes the MMU as alternating CPU and video access slots at the 32 MHz timing reference; CPU accesses and video fetches occupy distinct phases, and the MMU can extend a CPU access using DTACK when a rare phase alignment would otherwise violate the schedule. In that model, accesses to Shifter registers behind the MMU are also constrained by the bus phase, while MMU/GLUE registers do not necessarily have that same delay.
This is not the same as a Spectrum-style rule that simply adds a wait penalty whenever the CPU touches a display-memory address. For the ST, the expected bus transactions are scheduled into the memory cycle structure. A CPU may appear to perform back-to-back nominal 68000 accesses while the MMU transparently places video fetches between them. If the emulator only inserts a flat slowdown during visible lines, it can get the average throughput close but miss the precise phase of register writes and fetches.
The hardware relationship also explains why raster synchronization is sensitive to CPU instruction timing. A palette or base-register write can reach the display path only at a bus phase that is valid for the MMU. The CPU’s cycle count, the MMU’s arbitration, the register-access timing, and the Shifter’s pixel pipeline must therefore share a single timeline. Renderer code should consume the sequence of fetched words and register changes instead of reconstructing a line from final memory contents.
A deterministic base-address decoder
This Python helper decodes the visible screen-base byte fields for ST and STE test fixtures. It is not a complete MMU map or a substitute for the bus timing model.
def decode_screen_base(high, middle, low=0, *, ste=False):
for value in (high, middle, low):
if not 0 <= value <= 0xFF:
raise ValueError("screen-base register fields are bytes")
low_field = (low & 0xFE) if ste else 0
return (high << 16) | (middle << 8) | low_field
assert decode_screen_base(0x00, 0x12, 0xFF, ste=False) == 0x001200
assert decode_screen_base(0x00, 0x12, 0xFF, ste=True) == 0x0012FE
The helper deliberately clears bit zero for STE and ignores the low register for ST, matching the register alignment documented by Atari ST Internals. A full test must additionally verify which writes are accepted on the active model, how the current address counter changes, and when the display pipeline consumes the new base.
Verification matrix
Test register decoding independently from rendering. On an ST profile, write high and middle base fields and verify 256-byte alignment; attempt a low-byte write and confirm the documented unsupported behavior. On STE, vary the low field through even and odd values and verify the resulting even-aligned address. Read the live counter across multiple byte accesses during display and test the software’s retry logic around a byte rollover.
Next test all three resolution modes with a framebuffer whose bitplanes have distinct patterns. Verify that the Shifter combines plane bits into the documented color-index width, that the counter advances through the expected memory words, and that the 640-by-400 monochrome path does not reuse a color-mode group size. Exercise a screen-base change at VBlank and a mid-frame change, recording the first fetch that uses the new address.
Add bus-level traces containing 68000 accesses, MMU slot, video-read address, DTACK extension, Shifter register writes, pixel clock, and frame/line position. Run contention-sensitive test routines that make back-to-back memory accesses and writes at different clock phases. Compare against the ST Internals register map and MAME’s video timing implementation, while labeling any behavior supported only by emulator agreement as such.
For STE, test its additional low base byte and scroll-related controls as separate features. Check that a model configured as a standard ST does not accidentally gain STE access paths. Save states must preserve the current video counter, shifter pipeline, MMU access phase, GLUE counters, resolution, palette, and in-flight CPU access. Restoring during the middle of a fetch group should produce the same next memory address and pixels.
Acceptance criteria
A faithful Atari ST display model distinguishes screen base from the live video counter, respects ST/STE alignment and register availability, fetches memory according to the selected planar resolution, and interleaves video and CPU traffic through MMU timing. It can explain which RAM words formed a pixel group and which bus phase delayed a CPU or Shifter-register access. That evidence is more useful than a screenshot when a raster effect is one word or one clock phase out of position.
Related:
- Atari 7800 MARIA: Display Lists, Line RAM, and CPU Bus Time
- Commodore 64 VIC-II Bad Lines: Raster Fetches and CPU Arbitration
Sources: