ST STE Scanlines

From Atari Wiki
Revision as of 20:19, 2 October 2013 by Admin (talk | contribs) (initial formatting ~~~)
Jump to navigation Jump to search

THIS PAGE IS A DRAFT. IT'S NOT LINKED TO FROM ANYWHERE IN THE WIKI YET. FORMATTING IS MESSED UP, WILL FIX.

Troed / SYNC


The following is a pseudo code description of how the circuitry involved in creating scanlines, including sync pulses and displaying of pixel data, functions in the Atari ST and STE. By following the logic described here it's possible to implement emulators and simulators that will be able to run all existing Atari ST and STE programs that make use of "sync tricks" to create fullscreens and sync scrollers.

Disclaimer: This should hopefully contain everything that's currently known, but by no means it should be considered complete.

Information used to create these tables has mostly been sourced from, but a general thanks goes out to everyone who's ever written anything on the subject.

  • Alien (Overscan Techniques part I and II) [1] [2]
  • Paolo Simoes (posts on Atari-Forum, wakestate discovery and documentation) [3]
  • Dio (posts on Atari-Forum, trace diagrams) [4]

GLUE state machine, ST

Due to no synchronisation made between GLUE and CPU when an ST is powered on both chips, while running at 8MHz, can be offset from each other. This is the cause behind what's known as ST "wakeup modes" (where two were known and documented beginning 2006) and more recently divided into two more making four in total, now known as "wakestates" (2013).

At each cycle in the table below, as seen by the CPU, the value can be offset 0-3 cycles set when the ST is powered on. This offset does not change when reset, only when powered off and on again. While this looks like an emulator/simulator needing to be one-cycle accurate to fully capture these modes it's as far as currently known not needed. Since sync tricks can only be made with a resolution of two cycles (by using EXG+MOVE and similar instructions) it's possible to emulate all tricks with two cycle emulation granularity as well.

VAR H; H signal as per Alien's doc, combines with V and becomes DE detected by MMU
VAR LINE = (LORES) NTSC by default; PAL = 512 cycle 50Hz, NTSC = 508 cycle 60Hz, HIRES = 224 cycle 71Hz
VAR RES; $ff8260, 0 = LO, 2 = HI
VAR FREQ; $ff820a, 0 = 60, 2 = 50
VAR BLANK; Activate blank if true. When BLANK is set no RES/FREQ checks are made (or simply no DE changes?)
VAR HSYNC; Activate hsync if true, will also deactivate H
Cycle Action
4 IF(RES == HI) H = TRUE
30 IF(RES == LO) BLANK = FALSE
52 IF(FREQ == 60) H = TRUE
54 IF(FREQ == 50) LINE = PAL
56 IF(FREQ == 50) && (RES == LO) H = TRUE
164 IF(RES == HI) H = FALSE
184 IF(RES == HI) BLANK = TRUE
372 IF(FREQ == 60) H = FALSE
376 IF(FREQ == 50) && (RES == LO) H = FALSE
450 IF(RES == LO) BLANK = TRUE
462 IF(RES == LO) HSYNC = TRUE && H = FALSE
502 IF(RES == LO) HSYNC = FALSE

Due to the internal workings of the GLUE, cause unknown, all state checks of the RES register are made one cycle later than FREQ. This is best described with an example using position 56 in the table above:

  • Offset 0 reads values at cycle 56 (FREQ) and 57 (RES)
  • Offset 1 reads values at cycle 57 (FREQ) and 58 (RES)
  • Offset 2 reads values at cycle 58 (FREQ) and 59 (RES)
  • Offset 3 reads values at cycle 59 (FREQ) and 60 (RES)

The above, as seen by the CPU and a program, means that to be able to change the values of the registers for the GLUE to pick them up in the current wakestate they need to have been done at the following cycles:

  • WS1 (DL6): Changes made by 56 (FREQ), 56 (RES)
  • WS3 (DL5): Changes made by 56 (FREQ), 58 (RES)
  • WS4 (DL4): Changes made by 58 (FREQ), 58 (RES)
  • WS2 (DL3): Changes made by 58 (FREQ), 60 (RES)

As can be seen above these four different combinations have been given their own numbering - they are the four known wakestates. Any program that needs to do detailed sync manipulation, depending on how detailed, needs to detect which wakestate the ST is in and modify its code. Since wakeup modes where only documented and detected in 2006, some classic demos shows such side effects. The TCB "tv-snow" screen in Swedish New Year demo 2 has a disting logo that's only centered in wakestate 2 - in all the others it's offset to the left.

The DL3-DL6 moniker in parenthesis above is another way to name the wakestates, after how long the delay is between the GLUE raising DE (Display Enable) and the MMU picks it up. This has also the side effect of the wakestates being physically offset on screen by one pixel from eachother - WS2 (DL3) leftmost and WS1 (DL6) rightmost. This is caused by monitors using HSYNC to place the screen and depending on wakestate the distance between the HSYNC pulse and the pixels differs.

GLUE state machine, STE

In the STE the GLUE and MMU were combined into a single circuit, the GST MCU. This also meant that the GLUE and CPU were no longer offset by 0-3 cycles as on the ST but fully synchronised at 0. This means there are no GLUE wakeup modes/wakestates known on the STE.

VAR H; H signal as per Alien's doc, combines with V and becomes DE detected by MMU
VAR LINE = (LORES) NTSC by default; PAL = 512 cycle 50Hz, NTSC = 508 cycle 60Hz, HIRES = 224 cycle 71Hz
VAR RES; $ff8260, 0 = LO, 2 = HI
VAR FREQ; $ff820a, 0 = 60, 2 = 50
VAR BLANK; Activate blank if true. When BLANK is set no RES/FREQ checks are made (or simply no DE changes?)
VAR HSYNC; Activate hsync if true, will also deactivate H
Cycle Action
0 IF(RES == HI) H = TRUE
4 IF(RES == LO && H == TRUE) SUBTRACT 6 BYTES FROM LEFT BORDER (= +20)
28 IF(RES == LO) BLANK = FALSE
36 IF(FREQ == 60) H = TRUE
40 IF(FREQ == 50) && (RES == LO) H = TRUE
44 IF(RES == HI && H == TRUE) SUBTRACT 2 BYTES FROM PREFETCH (= +6)
48 IF(RES == HI && H == TRUE) SUBTRACT 4 BYTES FROM PREFETCH (= +4)
54 IF(FREQ == 50) LINE = PAL
56 SYNC-pos - must be LO
164 IF(RES == HI) H = FALSE
184 IF(RES == HI) BLANK = TRUE
372 IF(FREQ == 60) H = FALSE
376 IF(FREQ == 50) && (RES == LO) H = FALSE
448 IF(RES == LO) BLANK = TRUE
460 IF(RES == LO) HSYNC = TRUE && H = FALSE
500 IF(RES == LO) HSYNC = FALSE

MMU state machine

VAR H; Same signal as raised by GLUE above (it's actually combined with V forming DE)
VAR DE; DE as detected by the MMU

Note: These cycle timings are NOT affected by wake states on ST

To be updated: 2 cycle later detection or later raised DE from GLUE?

Cycle Action
8 IF(H == TRUE) DE = TRUE
STE 40 IF(H == TRUE) DE = TRUE*
STE 44 IF(H == TRUE) DE = TRUE*
STF 56 IF(H == TRUE) DE = TRUE
STF 60 IF(H == TRUE) DE = TRUE
168 IF(H == FALSE) DE = FALSE
376 IF(H == FALSE) DE = FALSE
380 IF(H == FALSE) DE = FALSE
468 IF(H == TRUE) DE = FALSE

STE due to its capability for hardscroll raises signal H 16 cycles earlier, but the prefetched pixels are only displayed if additional registers are set. However, it's possible to manipulate the prefetched data on regular lines to create +20 (left border), +6 and +4 (regular lines) regardless.

MMU detects GLUE DE at cycle 62 and raises LOAD at cycle 64. From this we can calculate the DL-moniker for the ST wakestates depending on when GLUE raised DE:

  • 64-58 = 6 = DL6
  • 64-59 = 5 = DL5
  • 64-60 = 4 = DL4
  • 64-61 = 3 = DL3

After LOAD it takes 16 cycles, plus 1 due to internal delays, for the Shifter to set the first values on the RGB pins.

Shifter state machine

TBD

Regular sync scrolling is made with changes affecting GLUE. 4-pixel sync scrolling as well as the cause for "stable" and "unstable" sync lines is due to Shifter.

Sync line lengths

Sync scrollers are created by combining scanlines of different lengths, as read in bytes, to cause the displayed screen to be offset by a chosen amount. It's possible to calculate the amount of bytes lines created by modifying the FREQ and RES registers in GLUE as follows (see the GLUE state machines for the specific actions needed):

0 byte line: DE never activated
54 byte line: DE activated at 60, deactivated at 168. (168-60)/2 = 54
56 byte line: DE activated at 56, deactivated at 168. (168-56)/2 = 56
80 byte line: DE activated at 8, deactivated at 168. (168-8)/2 = 80
158 byte line: DE activated at 60, deactivated at 376. (376-60)/2 = 158
160 byte line: DE activated at 60, deactivated at 380. (380-60)/2 = 160
162 byte line: DE activated at 56, deactivated at 380. (380-56)/2 = 162
184 byte line: DE activated at 8, deactivated at 376. (376-8)/2 = 184
186 byte line: DE activated at 8, deactivated at 380. (380-8)/2 = 186
204 byte line: DE activated at 60, deactivated at 468. (468-60)/2 = 204
206 byte line: DE activated at 56, deactivated at 468. (468-56)/2 = 206
230 byte line: DE activated at 8, deactivated at 468. (468-8)/2 = 230

The above examples are PAL, as most demos use. It's however equally easy to calculate how wide (in bytes - thus pixels) a left border would be in NTSC compared to PAL:

DE activated at 8 compared to regular NTSC line at 56. (56-8)/2 = 24 bytes
DE activated at 8 compared to regular PAL line at 60. (60-8)/2 = 26 bytes
DE deactivated at 468 compared to regular PAL line at 380. (468-380)/2 = 44 bytes
DE deactivated at 464 compared to regular NTSC line at 376. (464-376)/2 = 44 bytes
 - Note: An NTSC line is 508 cycles instead of 512 so the deactivation due to HSYNC will happen at 464

Future research / Incomplete

  • The "just blank" lines possible to create with switches of both RES and FREQ
  • the 14 byte line (RES = HI at cycle 32 will cause HSYNC which will cancel DE 4 cycles later. (36-8)/2 = 14)
  • Shifter state machine