IDE, Memory control & video
===========#==#=======#===============================================#=====
----------------------|IDE Bus |-----
===========#==#=======#===============================================#=====
$FFF00000.W|RW|IDE_DAT|Data Register |
$FFF00005.B|RW|IDE_ERR|Read:Error / Write:Features Register |
$FFF00005 IDE_ERR Error Register (read) / Features (write)
READ - error register, valid when the error bit is set in the
status register at $FFF0001D:
Bit 7 Bad Block Mark
Bit 6 Uncorrectable Error
Bit 5 (reserved)
Bit 4 ID Field Not Found
Bit 3 (reserved)
Bit 2 Command Aborted
Bit 1 Track 0 Not Found
Bit 0 DAM (Data Address Mark) Not Found
WRITE - features register, command specific. Used mainly by
SET FEATURES to enable or disable drive options.
Bit assignments from the Atari Compendium, matching the
standard ATA error register layout.
$FFF00009.B|RW|IDE_SCC|Sector count |
$FFF0000D.B|RW|IDE_SNR|Sector number |
$FFF00011.B|RW|IDE_CYL|Cylinder low |
$FFF00011 and $FFF00015 Cylinder Low / Cylinder High
$FFF00011 Cylinder Low bits 7-0 of the cylinder number
$FFF00015 Cylinder High bits 9-8 of the cylinder number
Together these form the ten bit cylinder number used in CHS
addressing.
In LBA mode the same two registers carry LBA bits 23-8 instead,
with the full eight bits of each used.
From the Atari Compendium, matching the standard ATA layout.
$FFF00015.B|RW|IDE_CYH|Cylinder high |
$FFF00019.B|RW|IDE_H_D|Head/Drive Register |
$FFF00019 IDE_H_D Drive / Head Register
Bit 7 (always 1 on early ATA)
Bit 6 0 = CHS addressing, 1 = LBA addressing
Bit 5 (always 1 on early ATA)
Bit 4 Drive select: 0 = master, 1 = slave
Bits 3-0 Head number, 0-15
In LBA mode bits 3-0 carry LBA bits 27-24 instead of the head
number.
Drive select and head number from the Atari Compendium. The
addressing and reserved bits follow the standard ATA layout.
$FFF0001D.B|RW|IDE_S_C|Read:Status Register/Write:Command Register |
$FFF0001D IDE_S_C Status (read) / Command (write)
READ - status register:
Bit 7 BSY busy, drive owns the registers
Bit 6 DRDY drive ready
Bit 5 DF drive fault
Bit 4 DSC drive seek complete
Bit 3 DRQ data request, drive wants a transfer
Bit 2 CORR corrected data
Bit 1 IDX index
Bit 0 ERR error, see the error register at $FFF00005
Reading this register clears a pending interrupt. Read the
alternate status at $FFF00039 instead when polling, since that
does not clear the interrupt.
WRITE - command register. Writing starts a command using the
values already loaded into the other registers.
RESOLVED: EmuTOS bios/ide.c places status and command at this
offset. The Atari Compendium places them at $FFF0001F and
marks $FFF0001A to $FFF0001D as unused. FALREG.TXT, an
independent hardware-level Falcon listing, agrees with EmuTOS:
it documents $FFF0001D as the first status register and notes
that reading it clears the pending interrupt. Two independent
sources against one settles this at $FFF0001D; the Compendium
entry is wrong.
Bit assignments follow the standard ATA status register.
$FFF00039.B|RW|IDE_ALT|Read:Alt Status/Write:Device Control |
$FFF00039 IDE_ALT Alternate Status (read) / Device Control (write)
READ - alternate status. Returns exactly the same bits as the
status register at $FFF0001D, but reading it does NOT clear a
pending interrupt. This is the register to poll with.
WRITE - device control:
Bit 2 SRST software reset
Bit 1 nIEN 1 = disable the drive's interrupt
From the Atari Compendium, which names it Alternate Status on
read and Alternate Command on write, and the standard ATA
layout.
$FFF0003D.B|R-|IDE_ACT|Active Address Register %W~~~~SM_ |F | | | drive currently Writing---------------+|||||| |F | | | one's complement of selected head------++++|| |F | | | Slave active-------------------------------+| |F | | | Master active-------------------------------+ |F
$FFF0003D IDE_ACT Active Address Register
Bit 7 (not documented)
Bit 6 1 = drive is currently writing
Bits 5-2 one's complement of the currently selected head
Bit 1 1 = slave drive active
Bit 0 1 = master drive active
This is the ATA Drive Address register, traditionally at
offset 7 of the control block, reflecting the state of the
drive select and head lines.
From FALREG.TXT (Aura), which documents it under the name
Aktive Adresse. Not referenced by EmuTOS, whose IDE structure
ends its named registers at $FFF00039, and not in the Atari
Compendium. The bit layout matches the standard ATA Drive
Address register, which supports FALREG's reading.
CONFLICT NOTE for the whole IDE block: the CT60 accelerator
claims the entire range $FFF00000 to $FFFBFFFF for its own
registers (per the F030/CT60 listing). That overlaps this IDE
register block and the TRUDIE add-on registers below. On a
CT60 equipped Falcon these addresses do not behave as listed
here.
$FFF00042.B|RW| - |Add-on control, not present on stock hardware |*
$FFF00042 and $FFF00044 Add-on control registers
Not present on stock Atari hardware. These sit in the same
address space as the IDE interface above.
Known to be used by: TRUDIE.
TRUDIE also claims $FFF00000 to $FFF00038, which is the IDE
register range itself, and $FFFFFFFF.
Extended bit information is not currently available for these
registers. The addresses are documented; what each bit does is
not.
Checked against EmuTOS: its IDE driver uses a plain ATA
register structure based at $FFF00000 and touches only the
standard offsets. It does not reference $FFF00042 or $FFF00044,
and has no concept of add-on IDE hardware in this range.
$FFF00044.B|RW| - |Add-on control, not present on stock hardware |*
===========#==#=======#===============================================#=====
----------------------|Memory Controller, System Control |-----
===========#==#=======#===============================================#=====
$FFFF8001.B|RW|MEM_CTL|Memory Controller |
$FFFF8001 MEM_CTL Memory Controller Configuration
Bits 3-2 Bank 1 size
Bits 1-0 Bank 0 size
Size encoding, same for both banks:
00 = 128k
01 = 512k
10 = 2M
11 = reserved
A shadow copy of this byte is kept in the system variable
memcntlr at $00000424, validated by memval2 at $0000043A.
Bit assignments from the Atari Compendium.
$FFFF8006.W|RW|SYS_CTL|System Control %MM______ _RS_bB_C |F | | | Monitor Type (M0,M1)--------++ || || | |F | | | Monochrome Monitor----------00 || || | |F | | | RGB Monitor-----------------01 || || | |F | | | VGA Monitor-----------------10 || || | |F | | | TV--------------------------11 || || | |F | | | Reset 0:ignore resetvector------------+| || | |F | | | STE-compatible-I/O 0:off,1:on----------+ || | |F | | | Blitterflag 0:on,1:off-------------------+| | |F | | | Blitterspeed 0:half clock,1:full clock----+ | |F | | | CPUspeed 0:half clock,1:full clock----------+ |F
$FFFF8006 SYS_CTL System Control / Connected Monitor Type
Bits 15-14, monitor type:
0 = Atari monochrome
1 = Atari colour (RGB)
2 = VGA colour
3 = television
Bit 9 Reset: 0 = ignore reset vector
Bit 8 STE compatible I/O: 0 = off, 1 = on
Bit 6 Blitter flag: 0 = on, 1 = off
Bit 5 Blitter speed: 0 = half clock, 1 = full clock
Bit 3 CPU speed: 0 = half clock, 1 = full clock
Bits 13-12 of the word (bits 5-4 of the byte at $FFFF8006)
report the fitted ST RAM per the F030/CT60 listing:
00 = 1MB 01 = 4MB 10 = 14MB 11 = no boot
This wiki's older ST/STe/MSTe/TT/F030 listing gives the same
field as 00 = 1MB, 01 = 4MB, 10 = 16MB, so the third value is
in dispute: 14MB is what a Falcon can actually carry with the
top of ST RAM reserved, 16MB the round figure. Unresolved.
That same older listing continues the byte with fields no
other source lists:
Bits 3-2 ROM wait states: 00 reserved, 01 two waits
(default), 10 one wait, 11 zero waits
Bit 1 video bus width: 0 = 16 bit, 1 = 32 bit (default)
Bit 0 RAM wait states: 0 = one wait (default),
1 = zero waits
UNVERIFIED: these three are not in Hatari, EmuTOS, any TOS
source or the Compendium, and Hatari treats the byte as read
only, so nothing here exercises them. Recorded because they
are plausible for a memory controller and nobody else
documents them, not because they are confirmed.
The Combel chip latches this byte during read; Hatari names it
"Monitor and memory conf" and restores the value on any write
(src/falcon/videl.c).
Monitor bits confirmed by Atari TOS 4.04, which tests
(byte >> 6) & 3 == 0 to detect a monochrome monitor, and by
the Atari Compendium value table.
Falcon only. On earlier machines monitor detection is through
MFP GPIP bit 7 at $FFFFFA01.
$FFFF8007.B|RW|SYS_FBC|Falcon Bus Control %_SB_BS__ |F | | | Start type 0:cold,1:warm-------------+||||||| | | | | STe Bus emulation 0:on,1:off----------+|||||| | | | | Blitter control 0:on,1:off--------------+|||| | | | | Blitter speed 0:8MHz,1:16MHz-------------+||| | | | | CPU speed 0:8MHz,1:16MHz--------------------+ | | | | Verified: EmuTOS bios/machine.c documents all | | | | five bits and writes $25 (STe bus emulation | | | | off, 16MHz blitter and CPU). Atari TOS | | | | 3.06/4.04 bios/startup.S writes the same $25. |
$FFFF8007 SYS_FBC Falcon Bus Control
Bit 6 Start type: 0 = cold start, 1 = warm start
Bit 5 STe Bus emulation: 0 = on, 1 = off
Bit 3 Blitter control: 0 = on, 1 = off
Bit 2 Blitter speed: 0 = 8MHz, 1 = 16MHz
Bit 0 CPU speed: 0 = 8MHz, 1 = 16MHz
STe bus emulation has to be switched off for bus-error based
hardware detection to work on the Falcon.
EmuTOS bios/machine.c documents all five bits and writes $25,
setting STe bus emulation off with 16MHz blitter and CPU.
Atari TOS 3.06/4.04 bios/startup.S writes the same $25 and
tests bit 6.
Falcon only.
===========#==#=======#===============================================#=====
----------------------|DMA, VIDEL Controller |-----
===========#==#=======#===============================================#=====
$FFFF8201.B|RW|VDL_VBH|Video Base Hi |
$FFFF8201 / $FFFF8203 / $FFFF820D Video Base Address
Three byte registers holding the screen memory address:
$FFFF8201 bits 23-16, high
$FFFF8203 bits 15-8, middle
$FFFF820D bits 7-0, low (STE and Falcon only)
On the ST and Mega ST only the high and middle bytes exist, so
the screen base must be on a 256 byte boundary. The STE added
the low byte, allowing any even address.
Bit 0 of the low byte is ignored; the address is always even.
The current value is shadowed in the system variable
_v_bas_ad at $0000044E. Changing the base takes effect at the
next vertical blank, or immediately if written during one.
From the Atari Compendium.
$FFFF8203.B|RW|VDL_VBM|Video Base Mi |
$FFFF8205.B|Rw|VDL_VCH|Video Count Hi |
$FFFF8205 / $FFFF8207 / $FFFF8209 Video Address Counter
Three byte registers holding the address the shifter is
currently reading from:
$FFFF8205 bits 23-16, high
$FFFF8207 bits 15-8, middle
$FFFF8209 bits 7-0, low
On the ST and Mega ST these are read only; the Atari
Compendium marks them so. From the STE onward they are
writable, and Hatari implements real writes on STE, TT and
Falcon (src/video.c, src/falcon/videl.c). Writing them moves
the fetch position mid-frame, which is how some demos do
full-screen hardware scrolling without moving data.
Reading these during display gives the shifter's position in
screen memory, which is how raster-timed effects work out where
the beam is. The three bytes are not read atomically, so the
counter can advance between reads. Hatari notes that when one
byte is read, all three are latched together from the current
counter (src/video.c, fix for Braindamage demo).
From the Atari Compendium, writability from Hatari.
$FFFF8207.B|Rw|VDL_VCM|Video Count Mi |
$FFFF8209.B|Rw|VDL_VCL|Video Count Lo %xxxxxxx_ |
$FFFF820A.B|RW|VDL_SYM|Sync mode %______VS | | | | Vfrequency 0:60hz(NTSC),1:50Hz(PAL)--------+| | | | | Sync 0:internal,1:external------------------+ |
$FFFF820A VDL_SYM Video Shifter Sync Mode
Bit 1 Vertical frequency: 0 = 60Hz (NTSC), 1 = 50Hz (PAL)
Bit 0 Sync source: 0 = internal, 1 = external
Setting bit 0 stops the shifter generating its own sync and
makes it follow an external signal. This is the register used
for the classic sync-switching border removal tricks: writing
it at a precise point in the scanline makes the shifter miss
the border, opening the display area.
On the Falcon the register keeps the same meaning: TOS 4.04
sets bit 1 for 50Hz and clears it for 60Hz, and bits 7-2 are
hard wired to zero. Some Falcon documents (the Aura video
guide among them) claim bit 1 reads back the monitor type
instead; Hatari src/falcon/videl.c states explicitly that
those documents are wrong.
Bit assignments from the Atari Compendium; Falcon behaviour
from Hatari.
$FFFF820D.B|RW|VDL_VBL|Video Base Lo %xxxxxxx_ |STE,F
$FFFF820E.W|RW|VDL_LOF|Line Offset in Words %_______x xxxxxxxx |F
$FFFF820E / $FFFF820F / $FFFF8210 Line Offset and Line Width
$FFFF820E Falcon: Line Offset, word register. Number of
EXTRA words added to the video address at the end
of each display line. 0 = lines are contiguous.
$FFFF820F STE: LINEWID, byte register, same meaning. Number
of extra words added per line; the low byte of the
Falcon word above.
$FFFF8210 Falcon: Line Width, word register. Length of one
display line in words (for example $50 = 80 words
for ST low).
The offset lets the shifter display a window onto a screen
buffer wider than the visible display, which is how the STE
does hardware horizontal scrolling.
CORRECTION: this page previously called $FFFF820F "Line Width
minus one", following the Atari Compendium. That is wrong.
The value is the extra words to SKIP per line, not the line
width. Hatari's rendering code adds the two together on every
display line:
lineoffset = IoMem_ReadWord(0xff820e) & 0x01ff; 9 bits
linewidth = IoMem_ReadWord(0xff8210) & 0x03ff; 10 bits
videl.videoRaster += linewidth + lineoffset;
(src/falcon/videl.c, in both the line and the screen-convert
paths). That is behavioural code, not a comment, so it also
settles the register widths: 9 bits for the offset, 10 for the
width. EmuTOS bios/videl.c writes 0 to the offset for normal
screens and the true width to $FFFF8210.
On the STE, when the horizontal scroll value is non zero the
shifter fetches an extra chunk of words per line, so LINEWID
is normally programmed to compensate (reduced by the number
of planes).
How the two Falcon registers work together. This is what
Hatari's renderer actually does, and mikro's VIDEL document
states the same rule:
length of logical line = line width + line offset
So for a 512 pixel wide virtual screen displayed 320 pixels
wide in true colour:
$FFFF820E = 512 - 320 = 192 (offset)
$FFFF8210 = 320 (width)
and the width in words for any mode is
line width = (horizontal resolution / 16) x bitplanes
with bitplanes 1, 2, 4, 8 or 16 for 2, 4, 16, 256 or 65536
colours.
PRACTICAL LIMIT: the line offset is only 9 bits, masked to
$01FF in Hatari's renderer, so the largest value is 511 words.
Combined with a 320 pixel display that caps a hardware-
scrolled virtual screen at roughly 1342 pixels wide (511 x 2 +
320 in true colour). Anything wider needs multiple buffers, a
blit per frame, or a Timer B interrupt rewriting the video
address every line. This trips people up because most listings
give the bit width without spelling out what it costs (raised
on Atari-Forum, January 2024).
SOURCING NOTE for this register pair and for $FFFF8260 and
$FFFF8266 below: Hatari's source comments on these four
registers are copied verbatim from mikro's VIDEL document,
ASCII bit diagrams and all, so the two are not independent
documentary sources. What IS independent is Hatari's code -
the masks and the raster arithmetic above - and EmuTOS, which
was written separately. Where this page says a claim is
confirmed by Hatari for these registers, it means the code
path, not the comment.
$FFFF820F.B|RW|VDL_LNW|LINEWID - extra words per line |STE
$FFFF8210.W|RW|VDL_LWD|Line Width in Words %______xx xxxxxxxx |F
$FFFF8240.W|RW|VDL_STC|ST Palette Register 00 %____rRRR gGGGbBBB |
$FFFF8240 to $FFFF825E ST/STE Palette Registers 0-15
Word registers, one per palette entry.
ST layout: XXXX XRRR XGGG XBBB (3 bits per gun, 512
colours)
STE layout: XXXX RRRR GGGG BBBB (4 bits per gun, 4096
colours)
IMPORTANT: on the STE the four bits within each nibble are NOT
in natural order. The bit arrangement per nibble is 0-3-2-1.
The extra bit the STE adds is placed at the TOP of the nibble
rather than the bottom, so that an ST program writing only the
lower three bits still produces the same colour it would on an
ST. Reading an STE palette value as a plain 4 bit number gives
the wrong intensity.
Hatari masks writes to $0777 on an ST and $0FFF on an STE.
Some games write $FFFF and read the value back to detect
whether they are running on an STE.
These registers are simulated for compatibility on the TT and
Falcon, which have their own wider palettes at $FFFF8400 and
$FFFF9800.
Layout and nibble ordering from the Atari Compendium, masking
behaviour from Hatari src/video.c.
...........|RW| - |...................... |
$FFFF825E.W|RW| - |ST Palette Register 15 |
$FFFF8260.B|RW|VDL_SSM|ST-Shift-Mode %_____xxx | | | | 320*200*4---------------------------------000 | | | | 640*200*2---------------------------------001 | | | | 640*400*1---------------------------------010 |
$FFFF8260 VDL_SSM ST Video Shifter Mode
Bits 1-0 resolution
00 = 320x200, 4 planes (low)
01 = 640x200, 2 planes (medium)
10 = 640x400, 1 plane (high)
11 = reserved
The TT modes were previously listed here. Atari uses a separate
TT shifter register at $FFFF8262.
A shadow copy of the current value is kept in the system
variable sshiftmd at $0000044C.
Writing 11 is not a documented mode. On real hardware it
produces the same output as one of the other modes rather than
anything useful; neither Atari TOS nor EmuTOS ever writes it.
FALCON QUIRK: writing this register on a Falcon OVERWRITES the
Line Width register at $FFFF8210 and the Video Mode register
at $FFFF82C2, loading compatibility values for the selected ST
mode. EmuTOS bios/videl.c rewrites both registers immediately
after setting the ST shifter for exactly this reason, and the
Aura video guide tabulates the values loaded:
ST shift $8210 $82C2 (RGB/TV) $82C2 (VGA)
00 low $0050 $0000 $0005
01 medium $0050 $0004 $0009
10 high $0028 $0006 $0008
11 $0050 $0000 $0000
Writing it can also drop the VIDEL back into the STE palette
when the mode bits of $FFFF8266 are clear. Set the Falcon
registers AFTER the ST shifter, never before.
This is confirmed in operating system code, not just in
documentation. EmuTOS bios/videl.c, in its mode-set routine,
writes the line width and video control registers, then writes
the ST shifter, then writes both of them AGAIN, with the
comment that "writing to the ST shifter has just overwritten
these registers":
videlword(0x10) = linewidth;
videlword(0xc2) = vctl;
...
videlregs[0x60] = 0x01;
videlword(0x10) = linewidth;
videlword(0xc2) = vctl;
Hatari implements the hardware side in
VIDEL_ST_ShiftModeWriteByte (src/falcon/videl.c): writing
$FFFF8260 sets bUseSTShifter, masks the register to bits 1-0,
and writes a line width and a video mode value into $FFFF8210
and $FFFF82C2 chosen by the shift mode and the monitor type -
exactly the table above.
EmuTOS also CLEARS $FFFF8266 (SPSHIFT) before touching the ST
shifter in the same routine, which is the practical rule
mikro's VIDEL document gives: set the timing registers for the
320x200, 640x200 or 640x400 mode first, clear $FFFF8266, then
write this register. Skipping the clear gives strange
resolutions.
Bit assignments from the Atari Compendium and Atari TOS
bios/startup.S; the clobber behaviour verified in EmuTOS
bios/videl.c and Hatari src/falcon/videl.c; the value table
cross-checked against the Aura video guide and mikro.
===========#==#=======#===============================================#=====
$FFFF8262.B|RW|VDL_TSM|TT-Shift-Mode %_____xxx |TT | | | ST low 320*200*4----------------------000 |TT | | | ST medium 640*200*2----------------------001 |TT | | | ST high 640*400*1----------------------010 |TT | | | (Falcon rez marker)-----------------------011 |TT | | | TT medium 640*480*4----------------------100 |TT | | | (unused)----------------------------------101 |TT | | | TT high 1280*960*1----------------------110 |TT | | | TT low 320*480*8----------------------111 |TT
$FFFF8262 VDL_TSM TT Video Shifter Mode
Word register. The byte at $FFFF8262 is the high half:
Bit 7 Sample/Hold mode, also called Smear Mode
Bit 4 Hyper Mono mode
Bits 2-0 resolution
000 = 320x200, 4 planes ST low
001 = 640x200, 2 planes ST medium
010 = 640x400, 1 plane ST high
011 = (Falcon rez marker)
100 = 640x480, 4 planes TT medium
101 = (unused)
110 = 1280x960, 1 plane TT high
111 = 320x480, 8 planes TT low
The byte at $FFFF8263 is the low half and holds the ST Palette
Bank, selecting which 16 entry bank of the 256 entry TT palette
the ST compatible palette registers map onto.
RESOLVED, which bit is which: the Atari Compendium names the
two special modes Smear Mode and Hyper Mono Mode but does not
say which bit carries which, and this page previously marked
that as a CHECK. Hatari settles it in code rather than in a
comment. It reads both bits together as a mask of 0x90
(src/video.c), then uses them separately:
src/conv_gen.c bTTSampleHold = (TTSpecialVideoMode & 0x80)
src/video.c if (TTSpecialVideoMode & 0x10) Hyper-mono
So bit 7 is Sample/Hold, which is the mode the Compendium
calls Smear, and bit 4 is Hyper Mono. This wiki's own older
ST/STe/MSTe/TT/F030 listing agrees, giving word bit 15 as
Sample/Hold and word bit 12 as Hypermono, which are the same
two bits.
Sample/Hold holds each pixel value across the following
pixels, smearing the image horizontally. Hyper Mono is a
256 grey level mode built by feeding the 8 bit pixel value
straight to the palette DAC.
Atari TOS 3.06 bios/startup.S declares this register as
shift_tt and defines TTMED=4, TTHIGH=6, TTLOW=7. When the
resolution is 2 or lower, Hatari mirrors the value into
$FFFF8260 so the ST shifter register stays consistent.
Resolution values from Atari TOS source, bit positions from
Hatari src/video.c, names from the Atari Compendium.
===========#==#=======#===============================================#=====
$FFFF8264.B|RW|VDL_HSH|H-Scroll (no prefetch) %____xxxx |STE,F
$FFFF8264 and $FFFF8265 Horizontal Scroll
Both hold a pixel scroll offset of 0 to 15, shifting the
display left by that many pixels. The difference is prefetch:
$FFFF8265 scroll WITH prefetch. With a non zero value the
shifter fetches an extra chunk of words at the
start of each line and the display starts 16
pixels early, so LINEWID at $FFFF820F is normally
programmed to compensate. This is the documented
STE scroll register.
$FFFF8264 scroll WITHOUT prefetch. Same shift, but no extra
fetch and no 16 pixel early start. Undocumented by
Atari; used by some STE demos (Hatari cites
Digiworld 2 by ICE).
Both exist on the STE as well as the Falcon: Hatari
src/video.c implements the pair on STE ($ff8264 no prefetch,
$ff8265 prefetch). On the Falcon the Aura video guide lists
$FFFF8264 as a shadow of $FFFF8265.
Widely circulated STE scrolling documentation adds that
writing $FFFF8265 clears LINEWID at $FFFF820F, so the scroll
value should be written before the width. That side effect is
not modelled by Hatari and is not confirmed by EmuTOS or TOS
source; treat it as unverified but harmless to respect.
$FFFF8265 is documented in the Atari Compendium as the
Horizontal Scroll Register. $FFFF8264 is not listed there.
$FFFF8265.B|RW|VDL_HSL|H-Scroll Lo (with prefetch) %____xxxx |STE,F
$FFFF8266.W|RW|VDL_FSM|Falcon Shift Mode %_____2OT _HV8PPPP |F | | | 2 Color mode 0:off,1:on----------+|| ||||||| |F | | | Overlay mode 0:off,1:on-----------+| ||||||| |F | | | True(high) color 0:off,1:on--------+ ||||||| |F | | | Hsync 0:internal,1:external-----------+|||||| |F | | | Vsync 0:internal,1:external------------+||||| |F | | | 8 Bitplanes 0:off,1:on------------------+|||| |F | | | falcon Palette 16 of 256 colors----------++++ |F
$FFFF8266 VDL_FSM SPSHIFT / Falcon Shift Mode
Bit 10 Enable 2-colour mode
Bit 8 Enable truecolor mode
Bit 6 Use external HSYNC
Bit 5 Use external VSYNC
Bit 4 Enable bitplane mode (8 bitplanes)
Bits 3-0 Falcon palette bank, 16 of 256 colours
Bit 9 is the overlay mode bit.
Only one of the mode bits should be set at a time. Truecolor
mode takes the pixel value straight to the DAC and ignores the
palette entirely.
What writing this register DOES:
- activates the Falcon palette, as against the STE palette
that $FFFF8260 selects. Hatari implements exactly this:
VIDEL_Falcon_ShiftMode_WriteWord clears bUseSTShifter,
the same flag $FFFF8260 sets
- because of that flag, once this register is in use
$FFFF8260 is ignored and does not need writing at all
- with bits 10, 8 and 4 all CLEAR it selects Falcon 16
colour mode, which is not the same as ST low: the Falcon
palette is in use, and bits 3-0 pick which bank of 16 out
of the 256 palette entries
This is the mirror image of the $FFFF8260 quirk: whichever of
the two shift registers you write last decides which palette
and which mode path the VIDEL follows.
Atari TOS 4.04 (tos3x bios/vsetmode.c) writes $0100 to select
truecolor and $0010 to select 8 bitplane mode, confirming bits
8 and 4. EmuTOS bios/videl.c writes $0400 for 2 colour mode
and tests the same bit through its SPS_2COLOR define,
confirming bit 10.
Bit meanings from the Atari Compendium, confirmed against
Atari TOS 4.04 and EmuTOS. mikro's VIDEL document agrees bit
for bit including bit 9 overlay, which no code path covers.
$FFFF827E.B|RW|STY_DSP|STACY Display State |STB | | | UNVERIFIED: Atari Compendium only. Not | | | | referenced by EmuTOS or any available TOS | | | | source. |
$FFFF827E STY_DSP STACY Display State
Bit 1 1 = backlight off
Bit 0 1 = display off
STACY only, the portable ST. Rare hardware.
CONFLICT on the bit positions: the Atari Compendium gives the
two bits as 1 and 0 of the byte, as shown above. This wiki's
older ST/STe/MSTe/TT/F030 listing gives them as bits 10 and 9
of a WORD at the same address, with backlight the higher of
the two in both readings. The orderings agree, only the
positions differ, and nothing else documents this register at
all. Unresolved. On such rare hardware it is worth reading the
register back after a write to see which interpretation the
machine agrees with.
UNVERIFIED beyond that: not referenced by EmuTOS, Hatari or
any available TOS source.
$FFFF8280.W|RW|VDL_HHC|Horizontal Hold Counter %_______x xxxxxxxx |F
$FFFF8280 to $FFFF82AC VIDEL Timing Registers
These define the video timing directly, replacing the fixed
timings the ST shifter used. All are word registers, Falcon
only.
Horizontal, in pixel clocks unless noted:
$FFFF8280 Horizontal Hold Counter
$FFFF8282 Horizontal Hold Timer
$FFFF8284 Horizontal Border Begin
$FFFF8286 Horizontal Border End
$FFFF8288 Horizontal Display Begin (bit 8 selects which
half line the display starts on)
$FFFF828A Horizontal Display End
$FFFF828C Horizontal Sync Start
$FFFF828E Horizontal FS
$FFFF8290 Horizontal EE
Vertical, in half lines:
$FFFF82A0 Vertical Frequency Counter
$FFFF82A2 Vertical Frequency Timer
$FFFF82A4 Vertical Border Begin
$FFFF82A6 Vertical Border End
$FFFF82A8 Vertical Display Begin
$FFFF82AA Vertical Display End
$FFFF82AC Vertical Sync Start
The FS and EE registers only have an effect when bit 4 of the
Video Control register at $FFFF82C0 is SET. They relate to the
15 half-line HSYNC pulses generated at the start of the bottom
border when bit 3 of Video Control is set: FS controls how
long the HSYNC pulses of the previous half-line are held into
the next half-line for the middle five pulses, and EE does the
same for the first and last five pulses (Aura video guide,
measured on hardware). With bit 4 clear neither register has
an observable function. An earlier version of this note said
"bit 3, clear", which was wrong on both counts.
Atari TOS 4.04 (tos3x bios/vsetmode.c) and EmuTOS both write
this whole block as a table of values per video mode rather
than computing them, so the exact meaning of each field is
best understood from those mode tables.
Names from the Atari Compendium; register set confirmed
against Atari TOS 4.04 and EmuTOS bios/videl.c.
$FFFF8282.W|RW|VDL_HHT|Horizontal Hold Timer %_______x xxxxxxxx |F
$FFFF8284.W|RW|VDL_HBB|Horizontal Border Begin %_______x xxxxxxxx |F
$FFFF8286.W|RW|VDL_HBE|Horizontal Border End %_______x xxxxxxxx |F
$FFFF8288.W|RW|VDL_HDB|Horizontal Display Begin %______Hx xxxxxxxx |F
| | | 0:1.Halfline, 1:2.Halfline--------+ |F
$FFFF828A.W|RW|VDL_HDE|Horizontal Display End %_______x xxxxxxxx |F
$FFFF828C.W|RW|VDL_HSS|Horizontal Sync Start %_______x xxxxxxxx |F
$FFFF828E.W|RW|VDL_HFS|Horizontal FS %_______x xxxxxxxx |F
$FFFF8290.W|RW|VDL_HEE|Horizontal EE %_______x xxxxxxxx |F
$FFFF82A0.W|RW|VDL_VFC|Vertical Frequency Counter %_____xxx xxxxxxxx |F
$FFFF82A2.W|RW|VDL_VFT|Vertical Frequency Timer %_____xxx xxxxxxxx |F
$FFFF82A4.W|RW|VDL_VBB|Vertical Border Begin %_____xxx xxxxxxxx |F
$FFFF82A6.W|RW|VDL_VBE|Vertical Border End %_____xxx xxxxxxxx |F
$FFFF82A8.W|RW|VDL_VDB|Vertical Display Begin %_____xxx xxxxxxxx |F
$FFFF82AA.W|RW|VDL_VDE|Vertical Display End %_____xxx xxxxxxxx |F
$FFFF82AC.W|RW|VDL_VSS|Vertical Sync Start %_____xxx xxxxxxxx |F
$FFFF82C0.W|RW|VDL_VCT|Video Control %_______O BHVUSCMM |F | | | h-base-Offset 0:128cyc,1:64cyc-----+ |||||||| |F | | | Buswide 0:16bit,1:32bit--------------+||||||| |F | | | Hsync 0:negative,1:positive-----------+|||||| |F | | | Vsync 0:negative,1:positive------------+||||| |F | | | Use FS & EE 0:off,1:on------------------+|||| |F | | | 15 halfline hSyncs at VBB----------------+||| |F | | | video Clock 0:32Mhz,1:25.175Mhz-----------+|| |F | | | Monitor 0:Mono,1:RGB,2:VGA,3:TV------------++ |F | | | Naming settled: Hatari (VCO) and the Aura |F | | | video guide both call $82C0 Video Control. |F
$FFFF82C0 VDL_VCT Video Control
Bit 8 h-base offset: 0 = 128 cycles, 1 = 64 cycles
Bit 7 Bus width: 0 = 16 bit, 1 = 32 bit
Bit 6 HSYNC polarity: 0 = negative, 1 = positive
Bit 5 VSYNC polarity: 0 = negative, 1 = positive
Bit 4 Use FS and EE registers: 0 = off, 1 = on
Bit 3 15 half-line HSYNCs at vertical border begin
Bit 2 Video clock: 0 = 32MHz, 1 = 25.175MHz
Bits 1-0 Monitor: 0 = mono, 1 = RGB, 2 = VGA, 3 = TV
EmuTOS writes $0080 for monochrome, $0186 for VGA, and
$0181 or $0183 for RGB and television. Decoding those confirms
the monitor field, the clock bit set only for VGA, the bus
width bit always set, and bit 8 set for all VGA modes (64
cycle base offset) and clear for monochrome (128 cycles),
matching FALREG.TXT.
CORRECTION: bit 4 was previously listed as "0 = on, 1 = off".
The Aura video guide, the origin document for this register,
states under $FFFF828E and $FFFF8290 that the FS and EE
functions apply "if Video-Control Bit 4 = 1", so the bit is
active HIGH. The old polarity came from the Hohwiller listing
this page descends from.
Note that bit 4 is the one bit in this register the sources do
not agree on. The Aura guide's own bit map for $FFFF82C0 marks
bit 4 "??Unknown??" even though its FS and EE entries name it;
mikro's VIDEL document lists the register as
%_______8765_3210, with bit 4 left out; this wiki's own older
ST/STE/MSTe/TT/F030 listing shows BIT 8 7 6 5 . 3 2 1 0, also
leaving bit 4 out; and FALREG.TXT lists it as
%_______8765__21_, leaving out bits 4, 3 and 0. Every other
bit in this register is identical across all four. Treat bit 4
as "gates FS and EE, otherwise no known function", which is
what the four documents amount to between them.
Bit 4 is also the one bit here that CANNOT be checked against
code: neither Hatari nor EmuTOS models the FS and EE registers
at all, and no TOS mode table sets bit 4. It rests on the Aura
guide alone. Every other bit in this register is confirmed by
the values EmuTOS writes, listed above.
NAMING SETTLED: this register's name was queried because
Atari TOS 4.04 (tos3x bios/vsetmode.c) and EmuTOS use the
internal variable name video_control for $FFFF82C2 and
video_clock for $FFFF82C0. Those are only source code
variable names. Three independent documents name the
registers as this page does: Hatari (VCO "Video control" at
$82C0, VMD "Video mode" at $82C2), mikro's VIDEL document
("Video Control (VCO)" at $82C0, "Video Mode" at $82C2), and
the Aura video guide (VIDEO-CONTROL at $82C0, VIDEO-MODE at
$82C2).
Hatari is the strongest of the three here because the names
are in its code, not only in a comment: src/ioMemTabFalcon.c
dispatches $ff82c0 to VIDEL_VCO_WriteWord and $ff82c2 to
VIDEL_VMD_WriteWord, so the two registers carry those names
throughout the emulator's Falcon video implementation.
The naming history is worth recording, because older listings
circulate with the labels the other way round, and the two
older pages on this wiki do not agree with each other:
"Atari ST STe MSTe TT F030 Hardware Register Listing"
$FF82C0 Video Control (VCO)
$FF82C2 VDM (labelled VDM but with the description
text "Video Control" left over from the older
version, which is part of why this got muddled)
"Atari F030 and CT60 Hardware Register Listing V1.0"
$FF82C0 ??? - Video Clock (?)
$FF82C2 VCO - Video Control
A later revision of that same document exists, V2.1 dated
March 2009, and it still carries the old names, so a newer
date does not mean a corrected document. V2.1 also still has
$FF820F as "width in words-1", which is the Compendium error
corrected above, and the_env at $4BC rather than $4BE. It is
the same lineage one revision on, with low memory added, not
an independent check.
So the older ST/STE/MSTe/TT/F030 page already carried the
corrected names, while the F030/CT60 page still has the
original Dan Hollis lineage names. These pages follow the
corrected set, which is also what Hatari, mikro and the Aura
guide use.
The same mix-up happened independently on the Atari Forum Wiki
at temlib.org, a SEPARATE wiki from this one: its copy ended
up with both registers labelled VCO, which was spotted on
Atari-Forum in January 2024 (thread "Falcon Video Registers?")
and corrected there to "Video Mode (VDM)" for $FF82C2. That is
corroboration of which naming is right, nothing more; no
content has been taken from that wiki, and what else may
differ there has not been checked.
FALREG.TXT is the remaining outlier, calling $82C0
"Clock-Control (VCO)" and $82C2 "Resolution-Control" -
descriptive of the contents, but not the names anyone else
uses.
This address is not listed in the Atari Compendium, which
only documents $FFFF82C2.
Bit assignments confirmed against Atari TOS 4.04, EmuTOS
bios/videl.c, the Aura video guide and mikro's VIDEL
document.
$FFFF82C2.W|RW|VDL_VMD|Video Mode %________ ____xxID |F | | | Pixclock:4,Divider:4(VGA)/16(STE)/4------00|| |F | | | Pixclock:2,Divider:2(VGA)/16(STE)/2------01|| |F | | | Pixclock:1,Divider:2(VGA)/16(STE)/1------10|| |F | | | (unused)---------------------------------11|| |F | | | Interlace 0:off,1:on-----------------------+| |F | | | Double Scan 0:off,1:on----------------------+ |F
$FFFF82C2 VDL_VMD Video Mode
Bit 3 Quarter pixel width
Bit 2 Halve pixel width
Bit 1 Interlace mode
Bit 0 Line doubling
Bits 3-2 together give the pixel clock divider:
00 = full width (divider 4 on VGA, 16 on STE)
01 = half width (divider 2 on VGA, 16 on STE)
10 = quarter width(divider 2 on VGA, 16 on STE)
11 = not used, never written by TOS or EmuTOS
Line doubling and interlace are mutually exclusive: line
doubling is used on VGA to display a 200 line mode at 400
lines, interlace on television output.
NAMING SETTLED: TOS and EmuTOS source use the internal
variable name video_control when writing this register, which
raised the question of whether the labels here were swapped.
Hatari (VMD "Video mode"), mikro's VIDEL document ("Video
Mode") and the Aura video guide (VIDEO-MODE) all name this
register Video Mode and $FFFF82C0 Video Control, so the labels
on this page stand. This wiki's older ST/STE/MSTe/TT/F030
listing already used the mnemonic VDM here, though it kept the
stale description text "Video Control" alongside it, which is
part of how the confusion spread. See the fuller note on
$FFFF82C0.
The Aura video guide adds that bits 3-2 set both the video
system divider and the pixel cycle length, with the divider
fixed at 16 in STE compatibility mode whatever the monitor.
mikro's document gives the same encoding from the programmer's
side: 00 = 4 cycles per pixel, 01 = 2, 10 = 1, 11 not
available, and notes that the pixel cycle length is what you
actually choose when designing a custom resolution, with the
divider following from it.
Bit assignments from the Atari Compendium, confirmed against
Atari TOS 4.04, EmuTOS, the Aura video guide and mikro's
VIDEL document.
$FFFF8210-$FFFF82C2 VIDEL standard mode register values (reference tables) |F
VIDEL standard mode values, from the Aura video guide
(measured with an oscilloscope and confirmed against TOS).
Word values, hexadecimal, register offsets $FFFF82xx.
RGB and TV modes, 50 Hz:
MODE | 10| 60| 66| 82| 84| 86| 88| 8A| 8C| A2| A4| A6| A8| AA| AC| C0| C2
ST-LOW: 050 000 000 03E 032 009 23F 01C 034 271 265 02F 06F 1FF 26B 081 000
ST-MED: 050 010 000 03E 032 009 23F 01C 034 271 265 02F 06F 1FF 26B 081 004
ST-HIG: 028 0x0 400 1FE 199 050 3EF 0A0 1B2 270 265 02F 07E 20E 26B 181 006
2/80: 028 0x0 400 1FE 199 050 3EF 0A0 1B2 271 265 02F 07F 20F 26B 181 004
4/40: 028 010 000 03E 030 008 239 012 034 271 265 02F 07F 20F 26B 181 000
4/80: 050 010 000 03E 030 008 002 020 034 271 265 02F 07F 20F 26B 181 004
16/40: 050 0x0 000 0FE 0CB 027 00C 06D 0D8 271 265 02F 07F 20F 26B 181 000
16/80: 0A0 0x0 000 1FE 199 050 04D 0FE 1B2 271 265 02F 07F 20F 26B 181 004
256/40: 0A0 0x0 010 0FE 0CB 027 01C 07D 0D8 271 265 02F 07F 20F 26B 181 000
256/80: 140 0x0 010 1FE 199 050 05D 10E 1B2 271 265 02F 07F 20F 26B 181 004
TRU/40: 140 0x0 100 0FE 0CB 027 02E 08F 0D8 271 265 02F 07F 20F 26B 181 000
TRU/80: 280 0x0 100 1FE 199 050 071 122 1B2 271 265 02F 07F 20F 26B 181 004
Interlace: subtract 1 from $84, $A4 and $A6, add 2 to $C2.
ST-High values are already interlaced on RGB monitors.
VGA modes, 60 Hz (59.58 Hz on the Falcon), double line on:
MODE | 10| 60| 66| 82| 84| 86| 88| 8A| 8C| A2| A4| A6| A8| AA| AC| C0| C2
ST-LOW: 050 000 000 017 012 001 20E 00D 011 419 3AF 08F 08F 3AF 415 186 005
ST-MED: 050 010 000 017 012 001 20E 00D 011 419 3AF 08F 08F 3AF 415 186 009
ST-HIG: 028 0x0 400 0C6 08D 015 273 050 096 419 3AF 08F 08F 3AF 415 186 008
2/80: 028 0x0 400 0C6 08D 015 273 050 096 419 3FF 03F 03F 3FF 415 186 009
4/40: 028 010 000 017 012 001 20A 009 011 419 3FF 03F 03F 3FF 415 186 005
4/80: 050 010 000 017 012 001 20E 00D 011 419 3FF 03F 03F 3FF 415 186 009
16/40: 050 0x0 000 0C6 08D 015 28A 06B 096 419 3FF 03F 03F 3FF 415 186 005
16/80: 0A0 0x0 000 0C6 08D 015 2A3 07C 096 419 3FF 03F 03F 3FF 415 186 009
256/40: 0A0 0x0 010 0C6 08D 015 29A 07B 096 419 3FF 03F 03F 3FF 415 186 005
256/80: 140 0x0 010 0C6 08D 015 2AB 084 096 419 3FF 03F 03F 3FF 415 186 009
TRU/40: 140 0x0 100 0C6 08D 015 2AC 091 096 419 3FF 03F 03F 3FF 415 186 005
TRU/80: officially impossible on VGA.
Double line off: subtract 1 from $C2.
SM124 monochrome, 71 Hz:
MODE | 10| 60| 66| 82| 84| 86| 88| 8A| 8C| A2| A4| A6| A8| AA| AC| C0| C2
ST-HIG: 028 020 000 01A 000 000 20F 00C 014 3E9 000 000 043 363 3E7 080 008
Mode names are compatibility mode or colours/columns. 0x0 in
the $60 column means the ST shifter value is not significant
for that mode. The XBIOS may adjust some values after setting
a mode, so values read back from a running system can differ
slightly.
===========#==#=======#===============================================#=====
----------------------|TT Palette Registers |-----
===========#==#=======#===============================================#=====
$FFFF8400.W|RW|TT__PAL|TT Palette Register 000 |TT
$FFFF8400 to $FFFF85FE TT Palette Registers 0-255
Word registers, one per palette entry, 256 entries.
Layout: XXXX RRRR GGGG BBBB
Unlike the ST and STE registers at $FFFF8240, each nibble here
is in natural order, 3-2-1-0. There is no compatibility
reordering.
The ST compatible palette registers at $FFFF8240 map onto a
16 entry bank of this palette, selected by the ST Palette Bank
field in the low byte of $FFFF8262.
TT only.
Layout from the Atari Compendium.
...........|RW| - |....................... |TT
$FFFF85FE.W|RW| - |TT Palette Register 255 |TT
===========#==#=======#===============================================#=====
----------------------|VIDEL Palette Register |-----
===========#==#=======#===============================================#=====
$FFFF9800.L|RW|VDL_PAL|Palette Register 000 %RRRRRR__ GGGGGG__ |F
$FFFF9800 to $FFFF9BFC VIDEL Palette Registers 0-255
Longword registers, one per palette entry, 256 entries.
Layout, across the four bytes of each longword:
Byte 0 RRRRRR-- red, 6 bits
Byte 1 GGGGGG-- green, 6 bits
Byte 2 -------- unused
Byte 3 BBBBBB-- blue, 6 bits
Six bits per gun, so 262144 possible colours, of which 256 can
be displayed at once. The low two bits of each byte are unused
and read back as zero.
256 longword entries starting at $FFFF9800 occupy 1024 bytes,
so the last register is at $FFFF9BFC. An earlier version of
this page gave the end as $FFFF98FC, which is wrong: that
address is only 64 registers in.
Falcon only. Ignored entirely in truecolor mode, where the
pixel value goes straight to the DAC.
Layout from the Atari Compendium, extent confirmed against
FALREG.TXT which lists $FFFF9BFC as colour 256.
...........|RW| - |.................... ________ BBBBBB__ |F
$FFFF9BFC.L|RW| - |Palette Register 255 |F
===========#==#=======#===============================================#=====
----------------------|DMA, Blitter |-----
===========#==#=======#===============================================#=====
$FFFF8A00.W|RW|BLT_HTR|Halftone-RAM 00 |BLT
$FFFF8A00 to $FFFF8A1E Blitter Halftone RAM
Sixteen word registers, one per halftone line.
Which word is used for a given blit line is chosen by the
halftone line number in bits 3-0 of the control register at
$FFFF8A3C, or by source bits 0-3 when the SMUDGE bit is set.
The halftone word feeds the halftone operation at $FFFF8A3A,
which in turn feeds the logical operation at $FFFF8A3B.
Verified against Hatari src/blitter.c.
...........|RW| - |............... |BLT
$FFFF8A1E.W|RW| - |Halftone-RAM 15 |BLT
$FFFF8A20.W|RW|BLT_SXI|Source X increment %xxxxxxxx xxxxxxx_ |BLT
$FFFF8A20 / $FFFF8A22 / $FFFF8A2E / $FFFF8A30 Increments
$FFFF8A20 Source X increment
$FFFF8A22 Source Y increment
$FFFF8A2E Destination X increment
$FFFF8A30 Destination Y increment
All four are signed word values in BYTES, added to the current
address as the blit proceeds.
X increment is added after each word within a line. Y increment
is added at the end of each line, and is applied INSTEAD of the
final X increment, not in addition to it.
Bit 0 is ignored in all four: the blitter works in words, so
increments are always even. Negative values are allowed and are
how downward or right-to-left blits are done, which matters for
overlapping copies.
Verified against Hatari src/blitter.c.
$FFFF8A22.W|RW|BLT_SYI|Source Y increment %xxxxxxxx xxxxxxx_ |BLT
$FFFF8A24.L|RW|BLT_SRC|Source Address %xxxxxxxx xxxxxxxx xxxxxxx_ |BLT
$FFFF8A24 and $FFFF8A32 Source and Destination Address
$FFFF8A24 Source address, longword
$FFFF8A32 Destination address, longword
Both are 24 bit addresses held in a longword. The Atari
Compendium notes that bits 7-0 of the first byte are bits
23-16 of the address, which is the usual 68000 24 bit layout.
Bit 0 is ignored; addresses are always even.
These registers ADVANCE during a blit. After the operation
completes they hold the address just past the last word
transferred, not the value originally written, so they must be
reloaded for each new blit.
Verified against Hatari src/blitter.c.
$FFFF8A28.W|RW|BLT_EM1|Endmask 1 |BLT
$FFFF8A28 / $FFFF8A2A / $FFFF8A2C Endmasks
$FFFF8A28 Endmask 1, applied to the FIRST word of each line
$FFFF8A2A Endmask 2, applied to all MIDDLE words
$FFFF8A2C Endmask 3, applied to the LAST word of each line
Each is a 16 bit mask. Where a mask bit is 1 the result is
written; where it is 0 the destination is left alone.
Endmask 2 is normally $FFFF. Endmasks 1 and 3 are used to clip
a blit to a pixel boundary within the first and last words.
IMPORTANT: whenever a mask is not all ones, the blitter must
read the destination before writing it, turning the operation
into a read-modify-write and roughly halving throughput. Atari
documentation states NFSR can also trigger this; Hatari's
authors state that is wrong and only the mask does.
If a line is only one word wide, endmask 1 and endmask 3 are
ANDed together and endmask 2 is not used.
Verified against Hatari src/blitter.c.
$FFFF8A2A.W|RW|BLT_EM2|Endmask 2 |BLT
$FFFF8A2C.W|RW|BLT_EM3|Endmask 3 |BLT
$FFFF8A2E.W|RW|BLT_DXI|Destination X increment %xxxxxxxx xxxxxxx_ |BLT
$FFFF8A30.W|RW|BLT_DYI|Destination Y increment %xxxxxxxx xxxxxxx_ |BLT
$FFFF8A32.L|RW|BLT_DST|Destination Adr. %xxxxxxxx xxxxxxxx xxxxxxx_ |BLT
$FFFF8A36.W|RW|BLT_WPL|Words per Line in BOB (0:65536)|BLT
$FFFF8A36 and $FFFF8A38 X Count and Y Count
$FFFF8A36 X count, words per line
$FFFF8A38 Y count, number of lines
A value of 0 means 65536, not zero.
Y count is the register the blitter decrements as it works.
When it reaches 0 the transfer is complete and the busy bit in
$FFFF8A3C clears. Reading Y count during a blit shows how many
lines remain.
X count is reloaded at the start of each line.
The Atari Compendium calls these BLiTTER X Count and Y Count.
This listing calls them Words per Line and Lines per BOB;
they are the same registers.
Quirk: with x count = 1 and NFSR set, real STE and Falcon
hardware produce results that depend on the sign of the source
X increment.
Verified against Hatari src/blitter.c.
$FFFF8A38.W|RW|BLT_LPB|Lines per BOB (0:65536)|BLT
$FFFF8A3A.B|RW|BLT_HTO|Halftone Operation %______xx |BLT | | | 0:set all Bits, 1:HTR, 2:SRC, 3:SRC & HTR |BLT
$FFFF8A3A BLT_HTO Halftone Operation, bits 1-0
0 all ones ($FFFF)
1 halftone RAM word
2 source word
3 source word AND halftone RAM word
HOP runs first, LOP second. The HOP result is what the logical
operation sees as its "source" input.
Verified against Hatari src/blitter.c.
$FFFF8A3B.B|RW|BLT_LGO|Logical Operation %____xxxx |BLT | | | (!S AND !D)------------------------------+||| |BLT | | | (!S AND D)-------------------------------+|| |BLT | | | ( S AND !D)--------------------------------+| |BLT | | | ( S AND D)---------------------------------+ |BLT
$FFFF8A3B BLT_LGO Logical Operation, bits 3-0
S = output of the halftone operation above
D = current destination word
$0 all zeros $8 NOT S AND NOT D (NOR)
$1 S AND D $9 NOT (S XOR D) (NXOR)
$2 S AND NOT D $A NOT D
$3 S $B S OR NOT D
$4 NOT S AND D $C NOT S
$5 D $D NOT S OR D
$6 S XOR D $E NOT (S AND D) (NAND)
$7 S OR D $F all ones
The register takes a value 0-15 selecting one of sixteen
operations, not just the four AND combinations shown above.
Verified against Hatari src/blitter.c.
$FFFF8A3C.B|RW|BLT_LNM|Line Number %BHS_xxxx |BLT | | | Busy (1:start Blitter)---------------+|| |||| |BLT | | | HOG (1:stop CPU when Busy)------------+| |||| |BLT | | | SMUDGE (use sourcebits 0-3 as HTR num)-+ |||| |BLT | | | Halftone-RAM number----------------------++++ |BLT
$FFFF8A3C BLT_LNM Control, %BHS_nnnn
Bit 7 BUSY write 1 to start the blitter. Reads 1 while a
transfer is in progress, cleared when y count
reaches 0.
Bit 6 HOG 0 = share the bus with the CPU, 1 = take the
bus for the whole transfer.
Bit 5 SMUDGE use source bits 0-3 as the halftone line
number instead of bits 3-0 of this register.
Bit 4 unused. Hardware masks this bit off on write.
Bits 3-0 halftone line number, 0-15.
In non-hog mode the blitter runs for 64 bus accesses, then
hands the bus to the CPU for 64. Writing 0 to bit 7 while the
CPU owns the bus pauses the blitter; writing 1 resumes it.
Pausing does not end the transfer, and busy still reads 1.
Quirk: in non-hog mode the blitter sometimes uses only 63 bus
accesses rather than 64, if the CPU makes a bus access during
the 4-cycle latency after the busy bit is set.
Verified against Hatari src/blitter.c.
$FFFF8A3D.B|RW|BLT_SKW|SKEW %FN__xxxx |BLT | | | FXSR (Force eXtra Source Read)-------+| |||| |BLT | | | NFSR (No Final Source Read)-----------+ |||| |BLT | | | SKEW (shift)-----------------------------++++ |BLT
$FFFF8A3D BLT_SKW Skew, %FN__nnnn
Bit 7 FXSR Force eXtra Source Read
Bit 6 NFSR No Final Source Read
Bits 5-4 unused
Bits 3-0 skew, 0-15 pixels
Read-modify-write happens whenever an endmask is not all ones.
Atari's own documentation states NFSR can also trigger this;
Hatari's authors state that is wrong and only the mask does.
Quirk: with x count = 1 and NFSR set, real STE and Falcon
hardware produce results that depend on whether the source X
increment is positive or negative.
Verified against Hatari src/blitter.c.