Complete memory map listing

From Atari Wiki
Revision as of 10:20, 26 July 2026 by Exxos (talk | contribs) (Created page with "The complete memory map assembled from the six section pages into one continuous listing. Nothing here is maintained directly: each section is pulled in from its own page, so edits made there appear here automatically. Use the section pages to edit; use this page to read or search the whole map in one place. __TOC__ == Exception vectors and basic RAM & ROM locations == ''Maintained at Exception vectors and basic RAM & ROM locations'' {{:Exception vectors and basic...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

The complete memory map assembled from the six section pages into one continuous listing. Nothing here is maintained directly: each section is pulled in from its own page, so edits made there appear here automatically. Use the section pages to edit; use this page to read or search the whole map in one place.

Exception vectors and basic RAM & ROM locations

Maintained at Exception vectors and basic RAM & ROM locations

===========#==#=======#===============================================#===== ----------------------|Exception Vectors |----- ===========#==#=======#===============================================#=====
$00000000.L|R-|XPT_SPR|SSP after Reset |
$00000000 and $00000004 Reset vectors $00000000 longword, supervisor stack pointer after reset $00000004 longword, program counter after reset These two are read from ROM, not RAM. At reset the memory controller maps ROM to address zero so the 68000 fetches the initial stack pointer and start address from there, then TOS switches the mapping so RAM appears at zero. Add-on ROM boards commonly claim $00000000 to $00000007 for exactly this reason: to supply their own reset vectors and take control before TOS. From the Atari Compendium and Atari TOS bios/startup.S.
$00000004.L|R-|XPT_PCR|PC after Reset | $00000008.L|RW|XPT_BUS|Bus Error | $0000000C.L|RW|XPT_ADR|Address Error | $00000010.L|RW|XPT_ILL|Illegal Instruction | $00000014.L|RW|XPT_DBZ|Divide by Zero | $00000018.L|RW|XPT_CHK|Chk, Chk2 Instruction | $0000001C.L|RW|XPT_TRV|Trapv Instruction | $00000020.L|RW|XPT_PRV|Privilege Violation | $00000024.L|RW|XPT_TRC|Trace |
$00000028.L|RW|XPT_LNA|Line-A |
$00000028 and $0000002C Line-A and Line-F vectors $00000028 longword, Line-A exception $0000002C longword, Line-F exception The 68000 traps any instruction whose top four bits are $A or $F, since neither is a valid opcode. Atari used Line-A for a set of fast low level graphics routines, documented on the wiki as Line-A. Those were removed on later machines, so anything using them must check the machine type first. Line-F is used by the 68881 and 68882 floating point coprocessors. On a machine without an FPU it is free. From the Atari Compendium and Atari TOS common/tosvars.inc.
$0000002C.L|RW|XPT_LNF|Line-F | $00000030.L|RW| - |reserved | $00000034.L|RW|XPT_FPU|Coprocessor Protocol Violation |030+ $00000038.L|RW|XPT_FRM|Format Error |010+ $0000003C.L|RW|XPT_DSP|DSP Transfer Interrupt |* $00000040.L|RW| - |reserved | $00000044.L|RW| - |reserved | $00000048.L|RW| - |reserved | $0000004C.L|RW| - |reserved | $00000050.L|RW| - |reserved | $00000054.L|RW| - |reserved | $00000058.L|RW| - |reserved | $0000005C.L|RW| - |reserved | $00000060.L|RW|XPT_SPU|Spurious Interrupt | $00000064.L|RW|XPT_LV1|Level 1 - |
$00000068.L|RW|XPT_HBL|Level 2 - HBL |
$00000068 to $0000007C Auto-vector interrupts $68 Level 2 HBL, horizontal blank $70 Level 4 VBL, vertical blank $78 Level 6 MFP 68901 Levels 1, 3, 5 and 7 exist in the table but are unused on a standard ST. Level 5 is the SCC on machines that have one. The VBL at level 4 is the one most software hooks, though the supported route is the VBL queue at $00000456 rather than taking the vector directly. The MFP at level 6 is the busiest: every timer, the keyboard, the floppy controller and the serial port all arrive through it, dispatched by the MFP's own vector table at $00000100. From the Atari Compendium and Atari TOS common/tosvars.inc.
$0000006C.L|RW|XPT_LV3|Level 3 - | $00000070.L|RW|XPT_VBL|Level 4 - VBL | $00000074.L|RW|XPT_LV5|Level 5 - SCC | $00000078.L|RW|XPT_LV6|Level 6 - MFP | $0000007C.L|RW|XPT_LV7|Level 7 - | $00000080.L|RW|XPT_T00|Trap #00 |
$00000084.L|RW|XPT_T01|Trap #01 - GEMDOS |
$00000080 to $000000BC Trap vectors Trap #1 ($84) GEMDOS Trap #2 ($88) AES and VDI Trap #13 ($B4) BIOS Trap #14 ($B8) XBIOS The remaining twelve traps are unused by TOS and free for application use, though some resident utilities claim them. Function number is passed on the stack, not in a register. Full call documentation is in tos.hyp rather than this map. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000088.L|RW|XPT_T02|Trap #02 - AES/VDI | $0000008C.L|RW|XPT_T03|Trap #03 | $00000090.L|RW|XPT_T04|Trap #04 | $00000094.L|RW|XPT_T05|Trap #05 | $00000098.L|RW|XPT_T06|Trap #06 | $0000009C.L|RW|XPT_T07|Trap #07 | $000000A0.L|RW|XPT_T08|Trap #08 | $000000A4.L|RW|XPT_T09|Trap #09 | $000000A8.L|RW|XPT_T10|Trap #10 | $000000AC.L|RW|XPT_T11|Trap #11 | $000000B0.L|RW|XPT_T12|Trap #12 | $000000B4.L|RW|XPT_T13|Trap #13 - BIOS | $000000B8.L|RW|XPT_T14|Trap #14 - XBIOS | $000000BC.L|RW|XPT_T15|Trap #15 | $000000C0.L|RW|FPU_BOS|FFCP Branch or Set |020+ $000000C4.L|RW|FPU_INX|FFCP Inexact Result |020+ $000000C8.L|RW|FPU_DBZ|FFCP Divide by Zero |020+ $000000CC.L|RW|FPU_UNR|FFCP Underflow |020+ $000000D0.L|RW|FPU_OPE|FFCP Operand Error |020+ $000000D4.L|RW|FPU_OVR|FFCP Overflow |020+ $000000D8.L|RW|FPU_NAN|FFCP signaling NAN |020+ $000000DC.L|RW| - |reserved | $000000E0.L|RW|XPT_MMU|MMU Configuration Error |030+ $000000E4.L|RW| - |reserved | $000000E8.L|RW| - |reserved | $000000EC.L|RW| - |reserved | $000000F0.L|RW| - |reserved | $000000F4.L|RW| - |reserved | $000000F8.L|RW| - |reserved | $000000FC.L|RW| - |reserved |
$00000100.L|RW|XPT_CTR|B0 Centronics busy |*
$00000100 to $0000013C MFP interrupt vectors The MFP 68901 supplies its own vector number, so its sixteen interrupt sources each get a dedicated entry here rather than sharing the level 6 auto-vector. Which source maps to which vector is set by the MFP vector register at $FFFFFA17, which holds the upper nibble of the vector base. On the Atari that is $40, putting the sixteen vectors at $40 to $4F, which are these addresses. Priority runs from the top of the list down: B7 (FDC/HDC) is higher priority than B0 (Centronics busy), and register A sources outrank register B. Enable, mask, pending and in-service for each source are controlled by the MFP registers at $FFFFFA07 to $FFFFFA15. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000104.L|RW|XPT_DCD|B1 RS232 DCD |* $00000108.L|RW|XPT_CTS|B2 RS232 CTS |* $0000010C.L|RW|XPT_BLT|B3 Blitter Done |*BLT $00000110.L|RW|XPT_T_D|B4 Timer D |* $00000114.L|RW|XPT_T_C|B5 Timer C |* $00000118.L|RW|XPT_KBD|B6 IKBD/MIDI |* $0000011C.L|RW|XPT_FDC|B7 FDC/HDC |* $00000120.L|RW|XPT_T_B|A0 Timer B |* $00000124.L|RW|XPT_XMT|A1 Transmit Error |* $00000128.L|RW|XPT_EMP|A2 Transmit Buffer empty |* $0000012C.L|RW|XPT_REC|A3 Receive Error |* $00000130.L|RW|XPT_FUL|A4 Receive Buffer full |* $00000134.L|RW|XPT_T_A|A5 Timer A |* $00000138.L|RW|XPT_RNG|A6 RS232 Ring Indicator |* $0000013C.L|RW|XPT_SND|A7 Monochrome Detect/Audio Subsystem |* $00000140.L|RW| - |User defined Vectors | ...........|RW| - |.................... | $000003FC.L|RW| - |User defined Vectors | | | | CHECK: $140-$17C are the TT MFP vectors and | | | | $180-$1BC the SCC vectors on machines that | | | | have them; $380-$3CC is the TOS exception | | | | crash save area. Not all of this range is | | | | genuinely user defined. | ===========#==#=======#===============================================#===== ----------------------|Random Access Memory |----- ===========#==#=======#===============================================#===== $00000008.B|RW|RAM_TOP|RAM TOP | ...........|RW| - |....... | $00CFFFFF.B|RW|RAM_END|RAM END | ===========#==#=======#===============================================#===== ----------------------|Alternative RAM (add-on boards) |----- ===========#==#=======#===============================================#=====
$00400000.B|RW|ALT_TOP|Alt-RAM TOP, add-on boards |*
$00400000 onward Alternative RAM Alt-RAM on the ST range conventionally starts at the 4MB mark, $00400000, immediately above the 4MB of ST RAM a stock machine can address. Common fits: $00400000 to $007FFFFF 4MB $00400000 to $00BFFFFF 8MB, the usual size $00400000 to $00DFFFFF 10MB Boards exist that go higher. The address range above the alt-RAM area is nominally VME bus space on machines that have it, the TT and Mega STE. That allocation should stand. In practice, on machines with no VME bus fitted or with VME unused, alt-RAM boards sometimes extend into that range as well. THE VME OVERLAP, now confirmed. On a Mega STE the VME bus address space begins at $00A00000, so it does NOT sit above the alt-RAM area, it sits INSIDE it: 4MB fit $00400000-$007FFFFF no overlap 8MB fit $00400000-$00BFFFFF overlaps VME from $00A00000 10MB fit $00400000-$00DFFFFF covers the whole VME range So an 8MB or larger alt-RAM board on a Mega STE is using address space the VME bus would otherwise claim. That is workable when no VME card is fitted, which is the usual case, but the two cannot coexist at those addresses. The TT is unaffected: its VME space is at $FE000000, well clear of alt-RAM. Ranges confirmed by Hatari src/scu_vme.c, which cites the Atari TT030 Hardware Reference Manual (June 1990) and the Atari Profibuch ST-STE-TT chapter 9 (1991), and independently by the Atari Compendium. This is separate from TT RAM on the TT and Falcon, which lives at $01000000 and is reported through the ramtop system variable at $000005A4, validated by ramvalid at $000005A8. Known to be used by: FLASHY CLOCK, SEC BOOSTER.
...........|RW| - |............ |* $00DFFFFF.B|RW|ALT_END|Alt-RAM END, largest fit seen |* ===========#==#=======#===============================================#===== ----------------------|VME Bus Address Space |----- ===========#==#=======#===============================================#=====
$00A00000.B|RW|VME_A24|VMEbus A24:D16 addressable area TOP |ME
$00A00000 onward VME Bus Address Space The VME bus is fitted to the Mega STE and TT only. Two address windows are provided on each, one for 24 bit VME addressing and a smaller one for 16 bit. Mega STE: $00A00000 to $00DEFFFF VMEbus A24:D16 $00DF0000 to $00DFFFFF VMEbus A16:D16 TT: $FE000000 to $FEFEFFFF VMEbus A24:D16 $FEFF0000 to $FEFFFFFF VMEbus A16:D16, shadow image All transfers are word based, D16. The Mega STE window is the more limited of the two. IMPORTANT: on the Mega STE this space overlaps the range used by alt-RAM boards of 8MB and larger. See the alt-RAM entry above. The VME control registers are separate and live in the I/O area at $FFFF8E01 to $FFFF8E0F, documented on the MFP, RTC and anything else page. Those cover the interrupt mask, interrupt state and the two forced interrupt registers, alongside the SCU general purpose registers. From the TT hardware reference, VME SYSFAIL generates a motherboard IRQ7 to the processor but does not generate an IRQ7 back onto the VME bus. SCU generated IRQ1 and IRQ3 are always auto vectored; only interrupts 5 and 6 have external IACK pins and can produce vectored interrupts. Ranges and interrupt behaviour from Hatari src/scu_vme.c, citing the Atari TT030 Hardware Reference Manual (June 1990) and the Atari Profibuch ST-STE-TT chapter 9 (1991). Cross-checked against the Atari Compendium.
...........|RW| - |............................... |ME $00DEFFFF.B|RW| - |VMEbus A24:D16 addressable area END |ME $00DF0000.B|RW|VME_A16|VMEbus A16:D16 addressable area TOP |ME ...........|RW| - |............................... |ME $00DFFFFF.B|RW| - |VMEbus A16:D16 addressable area END |ME $FE000000.B|RW|VME_T24|VMEbus A24:D16 addressable area TOP |TT ...........|RW| - |............................... |TT $FEFEFFFF.B|RW| - |VMEbus A24:D16 addressable area END |TT $FEFF0000.B|RW|VME_T16|VMEbus A16:D16 area TOP, shadow image |TT ...........|RW| - |............................... |TT $FEFFFFFF.B|RW| - |VMEbus A16:D16 area END |TT ===========#==#=======#===============================================#===== ----------------------|TT RAM (Fast RAM) |----- ===========#==#=======#===============================================#=====
$01000000.B|RW|TTR_TOP|TT Fast RAM TOP |TT,F
$01000000 onward TT RAM (Fast RAM) Present on the TT and Falcon. Physically separate from ST RAM and connected directly to the processor rather than through the video and DMA hardware. $01000000 to $01FFFFFF TT Fast RAM, up to 16MB $02000000 to $FDFFFFFF Reserved IMPORTANT: TT RAM is UNSUITABLE for direct DMA and Shifter transfers. It cannot be used for screen memory, and it cannot be the target or source of a DMA transfer. Anything going to or from disk, or being displayed, has to live in ST RAM. This is the single most important thing to know about it. What it is good for is code and data, where the lack of contention with the video hardware makes it appreciably faster than ST RAM. The top of installed TT RAM is reported in the system variable ramtop at $000005A4, validated by ramvalid at $000005A8 holding $1357BD13. A zero ramtop means no TT RAM is fitted. GEMDOS tracks it through a second memory descriptor chained from themd at $0000048E, which is why Malloc can hand out either kind. Mxalloc lets a program ask for one specifically. CONFLICT on the extent: the Atari Compendium gives the range as $01000000 to $01FFFFFF, 16MB. The older Hardware Register Listing page gives $01000000 to $013FFFFF, 4MB. The larger figure is most likely the architectural maximum and the smaller one a common fitted size, but this has not been confirmed. Note this is entirely separate from alt-RAM on add-on boards for the ST and STE, which lives at $00400000. See the alternative RAM entry above. Range and the DMA restriction from the Atari Compendium.
...........|RW| - |............... |TT,F $01FFFFFF.B|RW|TTR_END|TT Fast RAM END |TT,F $02000000.B|--| - |Reserved | ...........|--| - |........ | $FDFFFFFF.B|--| - |Reserved | | | | CHECK: was annotated "14MB". $00CFFFFF is | | | | 13MB. For 14MB, RAM should end at $00DFFFFF. | | | | Either the address or the size is wrong. | ===========#==#=======#===============================================#===== ----------------------|1MB System Read Only Memory |----- ===========#==#=======#===============================================#=====
$00E00000.B|R-|ROM_TOP|1MB ROM TOP |F
$00E00000 onward System ROM $00E00000 to $00EFFFFF 1MB ROM area, Falcon and TT $00FC0000 to $00FEFFFF 192KB ROM area, ST and STE The ST and STE map their 192KB ROM at $00FC0000. The TT and Falcon use a larger 1MB region starting at $00E00000. ADD-ON BOARDS: ROM expansion boards commonly claim $00E00000 to $00E3FFFF for their own 256KB ROM, and some add a flash area at $00E40000 to $00E7FFFF. Known to be used by FLASHY CLOCK, TRUDIE and SEC BOOSTER. Such boards also take the reset vectors at $00000000 to $00000007 and the 192KB region at $00FC0000 to $00FEFFFF. CHECK: the wiki listing gives the 1MB ROM area as ending at $00F0003F, which is 1MB plus 64 bytes. For exactly 1MB the end would be $00EFFFFF. Extended bit information is not currently available for the add-on ROM and flash areas.
...........|R-| - |........... |F $00F0003F.B|R-|ROM_END|1MB ROM END |F
$00E40000.B|R-|FLA_TOP|Flash space TOP, add-on boards |*
$00E40000 to $00E7FFFF Flash space, add-on boards Not present on stock Atari hardware. 256KB of flash memory fitted by some ROM expansion boards, sitting immediately above the add-on ROM area at $00E00000 to $00E3FFFF. Known to be used by: FLASHY CLOCK. Extended bit information is not currently available.
...........|R-| - |............... |* $00E7FFFF.B|R-|FLA_END|Flash space END |* | | | CHECK: $00E00000 to $00F0003F is 1MB plus 64 | | | | bytes. For exactly 1MB the end would be | | | | $00EFFFFF. | ===========#==#=======#===============================================#===== $00F00040.B|--| - |Illegal Address Space | ...........|--| - |..................... | $00F9FFFF.B|--| - |Illegal Address Space | ===========#==#=======#===============================================#===== ----------------------|128KB Expansion Cartridge Port |----- ===========#==#=======#===============================================#=====
$00FA0000.L|R-|ROM_PRT|Cartridge Magic($FA52235F=Diag,$ABCDEF42=User*)|
$00FA0000 to $00FBFFFF Cartridge port, 128KB $00FA0000 longword, cartridge magic $00FA0004 longword, entry point for a diagnostic cartridge Two magic values are recognised, and Atari's own TOS source tests both: $FA52235F diagnostic cartridge. Tested very early in bios/startup.S, before RAM is even sized, and jumped to immediately if found. $ABCDEF42 normal application cartridge. Tested later, once the system is up. A diagnostic cartridge therefore takes control before almost anything else, which is what makes it useful for hardware fault finding on a machine that will not boot. Magic values confirmed in Atari TOS bios/startup.S, which compares against both.
$00FA0004.L|R-|ROM_CAL|Call Diagnostic Cartridge | ...........|R-| - |............ | $00FBFFFF.B|R-| - |ROM Port END | ===========#==#=======#===============================================#===== ----------------------|192KB System Read Only Memory |----- ===========#==#=======#===============================================#===== $00FC0000.B|--| - |192KB ROM TOP |ST ...........|--| - |............. |ST $00FEFFFF.B|--| - |192KB ROM END |ST



Back to Memory Map for Atari ST,STE,TT and Falcon

System variables and low RAM

Maintained at System variables and low RAM

===========#==#=======#===============================================#===== ----------------------|TT MFP Vectors |----- ===========#==#=======#===============================================#===== $00000140.L|RW|TTMFP00|GPI 0 |TT $00000144.L|RW|TTMFP01|GPI 1 |TT $00000148.L|RW|TTMFP02|SCC-DMA Controller |TT $0000014C.L|RW|TTMFP03|Ring Indicator SCC B |TT $00000150.L|RW|TTMFP04|Timer D (RS232 baud rate generator) |TT $00000154.L|RW|TTMFP05|Timer C (SCC TRxCB) |TT $00000158.L|RW|TTMFP06|Reserved, GPI 4 |TT $0000015C.L|RW|TTMFP07|SCSI DMA Controller |TT $00000160.L|RW|TTMFP08|Timer B |TT $00000164.L|RW|TTMFP09|Send Error |TT $00000168.L|RW|TTMFP10|Send buffer empty |TT $0000016C.L|RW|TTMFP11|Receive error |TT $00000170.L|RW|TTMFP12|Receive buffer full |TT $00000174.L|RW|TTMFP13|Timer A |TT $00000178.L|RW|TTMFP14|TT Clock (MC146818A) |TT $0000017C.L|RW|TTMFP15|TT-SCSI Drive Controller NCR 5380 |TT ===========#==#=======#===============================================#===== ----------------------|SCC Interrupt Vectors |----- ===========#==#=======#===============================================#===== $00000180.L|RW| - |SCC Port B Transmit Buffer Empty |SCC $00000184.L|RW| - |Unused |SCC $00000188.L|RW| - |SCC Port B External Status Change |SCC $0000018C.L|RW| - |Unused |SCC $00000190.L|RW| - |SCC Port B Receive Character Available |SCC $00000194.L|RW| - |Unused |SCC $00000198.L|RW| - |SCC Port B Special Receive Condition |SCC $0000019C.L|RW| - |Unused |SCC $000001A0.L|RW| - |SCC Port A Transmit Buffer Empty |SCC $000001A4.L|RW| - |Unused |SCC $000001A8.L|RW| - |SCC Port A External Status Change |SCC $000001AC.L|RW| - |Unused |SCC $000001B0.L|RW| - |SCC Port A Receive Character Available |SCC $000001B4.L|RW| - |Unused |SCC $000001B8.L|RW| - |SCC Port A Special Receive Condition |SCC $000001BC.L|RW| - |Unused |SCC | | | CORRECTED: this table was previously built |SCC | | | densely (4 consecutive different meanings per |SCC | | | channel). The real layout is sparse, every |SCC | | | other slot unused, confirmed by the Atari |SCC | | | Compendium AND Atari's own TOS 2.06/3.06 |SCC | | | source (tos3x bios/chardev.S, sccvect: table).|SCC ===========#==#=======#===============================================#===== ----------------------|Exception Crash Save Area |----- ===========#==#=======#===============================================#=====
$00000380.L|RW|PRCLIVE|Validates crash page, if $12345678 |
$00000380 to $000003CC Processor state save area When TOS survives a crash it saves the processor state here before displaying the bombs, so a debugger can recover it. $380 proc_lives set to $12345678 if the save succeeded $384 proc_dregs saved D0-D7, 32 bytes $3A4 proc_aregs saved A0-A7, 32 bytes $3C4 proc_enum the exception number that caused the crash $3C8 proc_usp saved user stack pointer $3CC proc_stk top 16 words from the exception stack frame Only valid when proc_lives holds the magic value. TOS clears it once the state has been read. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000384. |RW|PRCDREG|Saved registers D0-D7 (32 bytes) | $000003A4. |RW|PRCAREG|Saved registers A0-A7 (32 bytes) | $000003C4.L|RW|PRCENUM|Vector number of crash exception | $000003C8.L|RW|PRC_USP|Saved user stack pointer | $000003CC. |RW|PRC_STK|16 words from exception stack (32 bytes) | ===========#==#=======#===============================================#===== ----------------------|GEM Vectors |----- ===========#==#=======#===============================================#===== $00000400.L|RW|ETVTIMR|etv_timer - GEM event timer vector | $00000404.L|RW|ETVCRIT|etv_critic - GEM critical error handler | $00000408.L|RW|ETVTERM|etv_term - GEM program termination vector | $0000040C.L|RW|ETVXTRA|etv_xtra - 5 additional vectors, unused | ===========#==#=======#===============================================#===== ----------------------|System Variables |----- ===========#==#=======#===============================================#=====
$00000420.L|RW|MEMVALD|memvalid - memory conf valid if $752019F3 |
$00000420 memvalid Memory configuration valid flag Longword. Holds $752019F3 when the memory configuration is valid. Checked together with memval2 at $0000043A ($237698AA) and memval3 at $0000051A ($5555AAAA). If all three match, TOS trusts the existing memory setup and performs a warm start. If any is wrong it runs the full memory sizing routine, which is slower and clears RAM. Clearing these is how a program forces a cold start. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000424.B|RW|MEMCTRL|memcntlr - copy of $FFFF8001 %____xxxx | | | | Bank 0 size 00:128k,01:512k,10:2Mb-------+||| | | | | Bank 1 size 00:128k,01:512k,10:2Mb---------+| |
$00000426.L|RW|RESVALD|resvalid - resvector valid if $31415926 |
$00000426 and $0000042A resvalid and resvector $426 resvalid longword, magic number $31415926 $42A resvector longword, address to jump to If resvalid holds $31415926 at reset time, TOS jumps through resvector very early in the reset sequence, before most of the system is initialised. This is the standard hook for reset-resident code. The routine must be extremely careful: almost nothing is set up yet. From the Atari Compendium and Atari TOS common/tosvars.inc.
$0000042A.L|RW|RESVECT|resvector - system reset bailout vector |
$0000042E.L|RW|PHYSTOP|phystop - physical top of ST RAM |
$0000042E to $00000436 Memory extent variables $42E phystop longword, physical top of ST RAM $432 _membot longword, lowest address available to the heap $436 _memtop longword, highest address available to the heap phystop is the real end of ST RAM as found by the memory sizing routine. _membot and _memtop bracket the area GEMDOS will allocate from, so they exclude the screen buffer and any memory TOS has reserved for itself. Alternative RAM (TT RAM, fast RAM) is tracked separately by ramtop at $000005A4 and ramvalid at $000005A8. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000432.L|RW|_MEMBOT|_membot - bottom of TPA (user memory) | $00000436.L|RW|_MEMTOP|_memtop - top of TPA (user memory) | $0000043A.L|RW|MEMVAL2|memval2 - validates memcntlr if $237698AA |
$0000043E.W|RW|_FLOCK |flock - if <>0, VBL floppy routine is off |
$0000043E flock Floppy and DMA lock Word. Set to a non-zero value before touching the DMA or FDC registers directly, and clear it again afterwards. While flock is non-zero the vertical blank floppy routine leaves the hardware alone. If it is left clear, the VBL can deselect the drive or disturb a transfer part way through. This is the single most important variable to get right when writing directly to the floppy hardware. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000440.W|RW|SEEKRAT|seekrate - floppy step rate %______xx | | | | 0:6ms 1:12ms 2:2ms 3:3ms (WD1772)----------+| |
$00000440 seekrate Floppy drive step rate Word. Sets the step rate for BOTH floppy drives. 0 = 6 ms 1 = 12 ms 2 = 2 ms 3 = 3 ms (default) These values are written straight into the low two bits of a WD1772 Type I command, so they are the chip's own encoding. IMPORTANT: these are WD1772 values. The WD1770 uses 6, 12, 20 and 30 ms for the same four encodings, so values must never be carried between the two chips. On the Atari 3 ms is the normal setting. 2 ms works but gives less reliable seeks in practice. TOS declares this as _seekrate at $440 in common/tosvars.inc. Values from the Atari Compendium, cross-checked against the WD1772 command encoding.
$00000442.W|RW|TIMR_MS|_timr_ms - system timer calibration, ms |
$00000442 _timr_ms System timer period Word. The interval between system timer ticks, in milliseconds. Normally 20, giving the 50 Hz tick that drives the GEM event timer. Not the same as the 200 Hz counter at $000004BA, which is driven directly by MFP Timer C. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000444.W|RW|FVERIFY|_fverify - if <>0, verify floppy writes |
$00000444 _fverify Floppy write verify flag Word. When non-zero, every floppy write is read back and compared. When zero, no verification is done. Verification roughly doubles write time. TOS defaults it on. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000446.W|RW|BOOTDEV|_bootdev - default boot drive |
$00000446 _bootdev Boot device Word. The device the system was booted from. 0 = A: 1 = B: 2 = C: and so on Hatari writes this directly during machine setup (src/stMemory.c: STMemory_WriteWord(0x446, nBootDrive)), commented "Boot up on A(0) or C(2)". TOS declares it as _bootdev at $446 in common/tosvars.inc. Meaning from the Atari Compendium.
$00000448.W|RW|PALMODE|palmode - 0:NTSC(60Hz), else PAL(50Hz) |
$00000448 palmode Video standard flag Word. Zero indicates NTSC (60 Hz) video, any other value indicates PAL (50 Hz). Reflects the state of the sync mode register at $FFFF820A bit 1, which is set from the country code in the OS header. From the Atari Compendium and Atari TOS common/tosvars.inc.
$0000044A.B|RW|DEFSHFT|defshiftmd - default video resolution |
$0000044C.B|RW|SSHIFTM|sshiftmd - copy of $FFFF8260 %_____xxx | | | | 0:low 1:medium 2:high resolution----------+|| |
$0000044C sshiftmd Shifter mode shadow Byte. A copy of the hardware shift mode register at $FFFF8260, kept so software can read the current resolution without touching the hardware. 0 = low 320x200, 4 planes 1 = medium 640x200, 2 planes 2 = high 640x400, 1 plane The related variable defshiftmd at $0000044A holds the resolution to use at the next reset. From the Atari Compendium and Atari TOS common/tosvars.inc.
$0000044E.L|RW|V_BAS_A|_v_bas_ad - screen base address |
$0000044E _v_bas_ad Logical screen address Longword. The address of the logical screen, the buffer that drawing operations write into. Before TOS 1.06 this had to be on a 256 byte boundary, since the ST video base register has no low byte. From TOS 1.06 and on an STE or later it can be any even address. The physical screen, the one the shifter is actually reading, is set by the video base registers at $FFFF8201, $FFFF8203 and $FFFF820D. The two can point at different buffers, which is how double buffering works. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000452.W|RW|_VBLSEM|vblsem - if >0, VBL routine is executed |
$00000452 to $0000045E Vertical blank control $452 vblsem word, 0 disables all VBL processing, 1 enables $454 nvbls word, number of slots in the VBL handler list $456 _vblqueue longword, pointer to the list of handlers $45A colorptr longword, palette to load at the next VBL $45E screenpt longword, screen base to set at the next VBL The VBL queue is an array of nvbls longword pointers. A zero entry is skipped, so installing a handler means finding a free slot and writing your routine's address into it. colorptr and screenpt are one-shot: if non-zero at VBL time, the value is used and the variable is cleared. That gives a tear-free way to change palette or screen base. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000454.W|RW|_NVBLS |nvbls - number of VBL routines | $00000456.L|RW|VBLQUEU|_vblqueue - pointer to list of VBL routines | $0000045A.L|RW|COLORPT|colorptr - palette to load at next VBL | $0000045E.L|RW|SCREENP|screenpt - video RAM base for next VBL |
$00000462.L|RW|VBCLOCK|_vbclock - count of VBL interrupts |
$00000462 and $00000466 Vertical blank counters $462 _vbclock longword, VBLs actually processed $466 frclock longword, VBLs that occurred frclock counts every vertical blank. _vbclock counts only those where processing was allowed to run, so the difference between them is the number of VBLs blocked by vblsem. Note the wiki label FRCLOCK matches Atari's own name; the Atari Compendium calls the same variable _frlock. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000466.L|RW|FRCLOCK|frclock - count of unblocked VBL interrupts |
$0000046A.L|RW|HDVINIT|hdv_init - hard disk initialisation vector |
$0000046A to $0000047E Hard disk vectors $46A hdv_init initialisation routine $46E swv_vec called on a monitor resolution change $472 hdv_bpb used by Getbpb() $476 hdv_rw used by Rwabs() $47A hdv_boot JSRed through to boot from hard disk $47E hdv_mediach used by Mediach() All longwords. A value of zero means no hard disk driver is installed for that function. These are the standard hook points a hard disk driver patches during boot. swv_vec is the odd one out: it is called when the system detects the monitor has been changed between colour and monochrome. From the Atari Compendium and Atari TOS common/tosvars.inc.
$0000046E.L|RW|SWV_VEC|swv_vec - resolution change vector | $00000472.L|RW|HDV_BPB|hdv_bpb - hard disk Getbpb vector | $00000476.L|RW|HDV_RW |hdv_rw - hard disk read/write vector | $0000047A.L|RW|HDVBOOT|hdv_boot - hard disk boot vector | $0000047E.L|RW|HDVMEDC|hdv_mediach- hard disk media change vector |
$00000482.W|RW|CMDLOAD|_cmdload - if <>0, load COMMAND.PRG at boot |
$00000482 _cmdload Command shell load flag Word. If non-zero at boot, the system attempts to load and run COMMAND.PRG from the root of the boot drive instead of going straight to the desktop. Set by a boot sector or an AUTO folder program that wants to replace the shell. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000484.B|RW|CONTERM|conterm - console attributes %____SBRK | | | | Bconin returns shift status--------------+||| | | | | System bell 0:off,1:on--------------------+|| | | | | Key repeat 0:off,1:on----------------------+| | | | | Key click 0:off,1:on------------------------+ |
$00000484 conterm Console attribute bits Byte. A bit array controlling several console behaviours: Bit 3 Cause Bconin() to return the shift status in the high word of its return value Bit 2 Enable system bell Bit 1 Enable key repeat Bit 0 Enable key click Bit 3 is the useful one for anything reading the keyboard directly: with it set, Bconin() returns the state of the shift, control and alternate keys alongside the character. The byte at $00000485 immediately after is reserved. TOS declares this as _conterm at $484 in common/tosvars.inc, described there as the attribute vector for console output. Bit meanings from the Atari Compendium.
$00000485.B|RW| - |Reserved | $00000486.L|RW|TRP14RT|trp14ret - trap #14 return address, unused | $0000048A.L|RW|CRITRET|criticret - critical error handler return |
$0000048E. |RW|_THEMD |themd - first memory descriptor (16 bytes)|
$0000048E and $0000049E Memory descriptors $48E themd first memory descriptor, 16 bytes $49E _md longword, space for an additional descriptor A memory descriptor block describes one contiguous region GEMDOS may allocate from: long m_link pointer to the next descriptor, 0 if last long m_start start address of the region long m_length length in bytes long m_own owner process, 0 if free On a machine with alternative RAM there are two descriptors, one for ST RAM and one for TT RAM, chained through m_link. From the Atari Compendium and Atari TOS common/tosvars.inc.
$0000049E.L|RW|___MD |_md - space for additional descriptor |
$000004A2.L|RW|SAVPTR |savptr - pointer to BIOS register save area|
$000004A2 savptr BIOS register save area pointer Longword. Points to the buffer the BIOS uses to save its internal registers when re-entered. Because the BIOS is not re-entrant, a routine that calls BIOS functions from inside an interrupt must give it a separate save area: allocate /2 bytes/, point savptr at it, make the call, then restore savptr. Otherwise the interrupted call's saved state is overwritten. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000004A6.W|RW|_NFLOPS|nflops - number of floppy drives attached |
$000004A6 _nflops Number of floppy drives Word. The number of floppy drives actually connected, 0, 1 or 2. This is the variable to test for a second physical drive. _drvbits at $000004C2 always shows both A and B set when any floppy is present, because of virtual drive swapping. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000004A8.L|RW|CONSTAT|con_state - vector for screen output |
$000004A8 and $000004AC Console state $4A8 con_state longword, vector to the current console output routine $4AC save_row word, temporary store for the cursor row con_state is switched between several internal routines as the console works through a VT-52 escape sequence, so its value depends on how much of a sequence has been received. save_row holds the cursor row while an ESC-Y cursor positioning sequence is being decoded, since the row arrives before the column. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000004AC.W|RW|SAVEROW|save_row - temporary cursor line storage | $000004AE.L|RW|SAVCTXT|sav_context- exception processing save area |
$000004B2. |RW|_BUFL |bufl - 2 GEMDOS buffer list heads(8bytes)|
$000004B2 bufl GEMDOS buffer list heads Two longwords, 8 bytes total. $4B2 pointer to the data sector buffer list $4B6 pointer to the FAT and directory sector buffer list Each points to a chain of buffer control blocks GEMDOS uses to cache disk sectors. Walking these chains is how disk cache utilities find and flush TOS's own buffers. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000004BA.L|RW|_HZ_200|hz_200 - 200 Hz system clock counter |
$000004BA _hz_200 200 Hz system counter Longword. Increments 200 times a second, driven directly by MFP Timer C. Free running from power on. The most useful timing reference available without touching hardware: read it, do the work, read it again and subtract. Resolution is 5 ms. Also commonly used as a random number seed. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000004BE.L|RW|THE_ENV|the_env - default environment string |
$000004C2.L|RW|DRVBITS|_drvbits - bit map of mounted drives |
$000004C2 _drvbits Connected drive bitmap Longword. One bit per drive letter: Bit 0 = A:, bit 1 = B:, through to bit 25 = Z: A set bit means that drive exists. Note: if at least ONE floppy drive is connected, BOTH the A and B bits are always set. This is because of virtual drive swapping, where a single physical drive answers as both A and B with a disk change prompt. Testing bit 1 does not tell you whether a second physical drive is fitted; use nflops at $000004A6 for that. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000004C6.L|RW|DSKBUFP|_dskbufp - pointer to 1K disk buffer |
$000004C6 and $000004CA Disk buffer and autoexec path $4C6 _dskbufp longword, pointer to a 1K disk buffer $4CA _autopath longword, pointer to the AUTO folder path The 1K buffer at _dskbufp is used by TOS for disk operations and is also borrowed by some graphics routines. It is safe to use as scratch space between disk calls, but not across one. _autopath points to the GEMDOS path specification of the directory programs are loaded from at boot. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000004CA.L|RW|AUTOPAT|_autopath - pointer to autoexec path | $000004CE. |RW|VBLLIST|_vbl_list - 8 VBL routine pointers (32 bytes) |
$000004EE.W|RW|DUMPFLG|_dumpflg - screen dump flag |
$000004EE and $000004F0 Screen dump control $4EE _dumpflg word, screen dump flag $4F0 prtabt word, printer abort flag _dumpflg is initialised to $FFFF. The ALT-HELP screen dump code sets it to 0 while a dump is in progress and back to $FFFF when finished, so setting it to 0 yourself prevents a dump starting. Note: the Atari Compendium calls the variable at $4EE _prt_cnt. Atari's own TOS source calls it _dumpflg, which is the name used here. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000004F0.W|RW|_PRTABT|prtabt - printer abort flag |
$000004F2.L|R-|SYSBASE|_sysbase - pointer to start of OS |
$000004F2 _sysbase Pointer to the operating system Longword. Points to the start of TOS in memory, which begins with the OS header structure: Offset Size Field Meaning $00 word os_entry BRA.S to the reset handler $02 word os_version TOS version number $04 long reseth pointer to the reset handler $08 long os_beg base address of the OS $0C long os_end end of ST-RAM used by the OS $10 long os_rsv1 reserved, default UI entry point $14 long os_magic GEM memory usage parameter block $18 long os_date TOS date $1C word os_conf PAL flag and country code $1E word os_dosdate TOS date in GEMDOS format $20 long os_root BDOS quick pool pointer (1.2+) $24 long os_kbshift pointer to the shift state (1.2+) $28 long os_run pointer to current basepage(1.2+) $2C long reserved (1.2+) The last four fields only exist from TOS 1.2 onward. Check os_version before reading them. os_version is BCD: $0102 is TOS 1.02, $0404 is TOS 4.04. CONFLICT on os_date format: the Atari Compendium gives it as $YYYYMMDD. EmuTOS include/biosdefs.h comments it as BCD MMDDYYYY. Not resolved here. EmuTOS note: EmuTOS puts the ASCII signature 'ETOS' in the final longword at offset $2C, where real TOS leaves it reserved. That is a reliable way to detect EmuTOS. Structure from the Atari Compendium and EmuTOS include/biosdefs.h. Hatari reads this variable at src/gemdos.c to locate the OS.
$000004F6.L|RW|SHELL_P|_shell_p - pointer to shell |
$000004F6 to $000004FE OS pointers $4F6 _shell_p longword, shell process pointer $4FA end_os longword, end of the OS in RAM $4FE exec_os longword, OS entry point _shell_p allows a shell process to be installed which is entered when the current program terminates. Normally unused. exec_os is jumped through once operating system initialisation is complete, normally pointing at the AES startup. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000004FA.L|R-|_END_OS|end_os - pointer to end of OS in RAM | $000004FE.L|R-|EXEC_OS|exec_os - pointer to OS entry point |
$00000502.L|RW|SCR_DMP|scr_dump - pointer to screen dump routine |
$00000502 to $00000512 Printer and auxiliary vectors $502 scr_dump called when ALT-HELP is pressed $506 prt_stat check status of the PRN: device $50A prt_vec output a byte to the PRN: device $50E aux_stat check status of the AUX: device $512 aux_vec output a byte to the AUX: device All longwords. The four printer and auxiliary vectors are used by Prtblk(), so replacing them redirects printer output without patching GEMDOS. Atari's own source names the last four prv_lsto, prv_lst, prv_auxo and prv_aux. From the Atari Compendium and Atari TOS common/tosvars.inc.
$00000506.L|RW|PRTSTAT|prt_stat - pointer to prv_lsto | $0000050A.L|RW|PRT_VEC|prt_vec - pointer to prv_lst | $0000050E.L|RW|AUXSTAT|aux_stat - pointer to prv_auxo | $00000512.L|RW|AUX_VEC|aux_vec - pointer to prv_aux |
$00000516.L|RW|PUN_PTR|pun_ptr - pointer to pun_info if AHDI |
$00000516 pun_ptr AHDI partition information Longword. Points to a PUN_INFO structure maintained by AHDI, Atari's hard disk driver, describing the mounted partitions. The structure begins: word puns number of drives supported, including floppies (maximum 16) then pun[16] one byte per drive: bits 0-2 physical ACSI unit bit 7 set if the drive is not present then start[16] longword starting sector of each partition A null pointer means AHDI is not loaded. This is a driver structure rather than hardware, so its exact layout depends on the AHDI version in use. Treat the above as indicative. TOS declares it as _pun_ptr at $516 in common/tosvars.inc with the comment "if AHDI, pointer to pun_info". Structure from the Atari Compendium.
$0000051A.L|RW|MEMVAL3|memval3 - memory conf valid if $5555AAAA |
$0000051E. |RW|BCONSTA|bconstat_vec - 8 input status vectors(32 bytes)|
$0000051E to $0000057E BIOS device vector tables Four tables of eight longwords each: $51E bconstat_vec input status routines $53E bconin_vec input routines $55E bcostat_vec output status routines $57E bconout_vec output routines Indexed by BIOS device number: 0 = PRT printer 1 = AUX RS-232 2 = CON console (screen and keyboard) 3 = MIDI 4 = IKBD keyboard controller 5 = RAW console without VT-52 processing 6 and 7 unused on most machines Replacing an entry redirects that device's I/O. This is how serial port drivers and screen accelerators hook in. From the Atari Compendium and Atari TOS common/tosvars.inc.
$0000053E. |RW|BCONIN |bconin_vec - 8 input vectors (32 bytes) | $0000055E. |RW|BCOSTAT|bcostat_vec - 8 output status vectors(32bytes)| $0000057E. |RW|BCONOUT|bconout_vec - 8 output vectors (32 bytes) |
$0000059E.W|R-|LNGFRAM|_longframe - if <>0, CPU uses long stack frames|
$0000059E _longframe Processor stack frame format Word. Zero means the processor uses short (68000) exception stack frames; any other value means long (68010 and above) frames. This matters to any exception handler that inspects the stack: the offset to the saved PC differs between the two formats. Testing this variable is the correct way to handle both, rather than assuming the CPU type. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000005A0.L|R-|P_COOKI|_p_cookie - pointer to cookie jar |1.06+
$000005A0 _p_cookie Cookie jar pointer Longword. Points to the cookie jar, a table of longword pairs describing installed hardware and software features. Each entry is two longwords: a four character tag and a value. The list ends with an entry whose tag is zero, where the value gives the total number of slots allocated. Common tags include _CPU, _FPU, _SND, _MCH, _VDO, _FLK and _IDT. A null pointer means no cookie jar exists, which is the case before TOS 1.06. Present from TOS 1.06 onward. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000005A4.L|RW|_RAMTOP|ramtop - top of alternative (Fast) RAM |TT,F $000005A8.L|RW|RAMVALD|ramvalid - validates ramtop if $1357BD13 |TT,F
$000005AC.L|RW|BELHOOK|bell_hook - vector for system bell |1.06+
$000005AC and $000005B0 Sound hooks $5AC bell_hook vector jumped through to sound the bell $5B0 kcl_hook vector jumped through for key clicks Both longwords. The key click routine is entered with the scancode of the key just pressed, so a replacement can vary the click by key. Replacing these is the supported way to change or silence the system sounds without patching the BIOS. Present from TOS 1.06 onward. From the Atari Compendium and Atari TOS common/tosvars.inc.
$000005B0.L|RW|KCLHOOK|kcl_hook - vector for keyclick |1.06+ ===========#==#=======#===============================================#===== ----------------------|STBook |----- ===========#==#=======#===============================================#===== $00000889.B|RW|LCDPSHD|Shadow of LcdPowerControl ($FFFF827F) |STB ===========#==#=======#===============================================#=====
Magic validation values, collected for reference: memvalid $420 = $752019F3 resvalid $426 = $31415926 memval2 $43A = $237698AA memval3 $51A = $5555AAAA ramvalid $5A8 = $1357BD13 proc_lives $380 = $12345678 flock ($43E) must be non-zero before any direct FDC or DMA access, so the VBL floppy routine does not deselect the drive or disturb the DMA mid-transfer. Clear it again afterwards. Sources: addresses and labels from Atari's own TOS source (th-otto/tos1x, common/tosvars.inc), cross-checked against Hatari, EmuTOS (bios/tosvars.S) and The Atari Compendium Appendix B. Sizes are inferred from address spacing and the Compendium; the byte-versus-word calls on memcntlr, defshiftmd and sshiftmd are judgement rather than documented. Read-only marks reflect convention, not hardware enforcement.



Back to Memory Map for Atari ST,STE,TT and Falcon

IDE, Memory control & video

Maintained at 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. CONFLICT: 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. Every other Compendium IDE entry agrees with EmuTOS, so $FFF0001D is the more likely value, but neither has been checked on hardware. 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.
$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 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 The Atari Compendium marks all three read only, though the wiki listing shows them as Rw. Writing them is not useful. 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. From the Atari Compendium.
$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. Bit assignments from the Atari Compendium.
$FFFF820D.B|RW|VDL_VBL|Video Base Lo %xxxxxxx_ |STE,F
$FFFF820E.B|RW|VDL_LOF|Line Offset |STE,F
$FFFF820E and $FFFF820F Line Offset and Line Width $FFFF820E Line Offset. Number of extra words to skip at the end of each scanline. STE and Falcon. $FFFF820F Line Width, in words, minus one. Together these let the shifter display a window onto a screen buffer wider than the visible display, which is how the STE does hardware horizontal scrolling. On the Falcon the line width is a word value at $FFFF8210 instead, and is NOT minus one. Note: writing the horizontal scroll low byte at $FFFF8265 clears the line width register. Set the width after the scroll, not before. $FFFF820E is not listed in the Atari Compendium; $FFFF820F is, described as scanline width in words minus one.
$FFFF820F.B|RW| - |Line Width-1 |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. Bit assignments from the Atari Compendium and Atari TOS bios/startup.S.
===========#==#=======#===============================================#=====
$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 Special video mode Bit 4 Special video 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. The two special video mode bits are named Smear Mode and Hyper Mono Mode by the Atari Compendium. CHECK: which name goes with which bit is not certain from the available sources. Hatari masks both together as 0x90 without naming them individually. 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 Hi %____xxxx |F
$FFFF8264 and $FFFF8265 Horizontal Scroll $FFFF8264 Bits 3-0, scroll amount, no side effect $FFFF8265 Bits 3-0, scroll amount, ALSO clears line width Both hold a pixel scroll offset of 0 to 15. Writing $FFFF8265 additionally clears the line width register at $FFFF820F, so the two must be written in the right order: scroll first, then width. $FFFF8264 exists to allow the scroll to be changed without disturbing the width. It is Falcon only. $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 - clears Line Width %____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. 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. Bit meanings from the Atari Compendium, confirmed against Atari TOS 4.04 and EmuTOS.
$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. UNVERIFIED: Atari Compendium only. 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 are only used when bit 3 of the video control register is clear. 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:on,1:off------------------+|||| |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 CHECK: TOS 4.04 (tos3x vsetmode.c) and |F | | | EmuTOS write video_control to $82C2 and |F | | | video_clock to $82C0 - the reverse of these |F | | | two labels. Addresses/bits correct either way.|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 = on, 1 = off 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, and the bus width bit always set. NAMING CHECK: Atari TOS 4.04 (tos3x bios/vsetmode.c) writes video_control to $FFFF82C2 and video_clock to $FFFF82C0, and EmuTOS uses the same naming. That is the reverse of the labels used on this page. The addresses and bit layouts are confirmed correct by both sources; only the names may be swapped. This address is NOT listed in the Atari Compendium at all, which only documents $FFFF82C2. That may itself be a clue to the naming question. Bit assignments confirmed against Atari TOS 4.04 and EmuTOS bios/videl.c.
$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 VCO / 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 CHECK: Atari TOS 4.04 (tos3x bios/vsetmode.c) writes video_control to $FFFF82C2 and video_clock to $FFFF82C0, and EmuTOS uses the same naming. That is the reverse of the labels used on this page. The addresses and bit layouts are confirmed correct by both sources; only the register names may be the wrong way round. Bit assignments from the Atari Compendium, confirmed against Atari TOS 4.04 and EmuTOS.
===========#==#=======#===============================================#===== ----------------------|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 $FFFF98FC 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. Falcon only. Ignored entirely in truecolor mode, where the pixel value goes straight to the DAC. Layout from the Atari Compendium.
...........|RW| - |.................... ________ BBBBBB__ |F $FFFF98FC.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.



Back to Memory Map for Atari ST,STE,TT and Falcon

DMA & SCSI

Maintained at DMA & SCSI

===========#==#=======#===============================================#===== ----------------------|DMA, WD1772 Disk Controller |----- ===========#==#=======#===============================================#=====
$FFFF8604.W|RW|WDC_SEC|FDC/HDC Access/Sector Count |
$FFFF8604 WDC_SEC FDC/HDC Access / Sector Count The FDC is NOT in the 68000 address space. Its four registers sit behind the DMA chip and are reached through this word. Select which one with the mode register at $FFFF8606, then read or write here. Only the low 8 bits are used; the upper byte is ignored on write and reads back as all ones. Mode register values to select each FDC register: DMA read mode DMA write mode FDC Command (W)/Status(R) $0080 $0180 FDC Track Register $0082 $0182 FDC Sector Register $0084 $0184 FDC Data Register $0086 $0186 DMA sector count (W only) $0090 $0190 WD1772 command encodings written to the Command Register: Type Command b7 b6 b5 b4 b3 b2 b1 b0 Base I Restore 0 0 0 0 h v r1 r0 $00 I Seek 0 0 0 1 h v r1 r0 $10 I Step 0 0 1 u h v r1 r0 $20 I Step-in 0 1 0 u h v r1 r0 $40 I Step-out 0 1 1 u h v r1 r0 $60 II Read Sector 1 0 0 m h e 0 0 $80 II Write Sector 1 0 1 m h e p a0 $A0 III Read Address 1 1 0 0 h e 0 0 $C0 III Read Track 1 1 1 0 h e 0 0 $E0 III Write Track 1 1 1 1 h e p 0 $F0 IV Force Interrupt 1 1 0 1 i3 i2 i1 i0 $D0 Base is the opcode with all flags clear, not the only byte the command can take. Read Track can appear as $E0, $E4, $E8 or $EC depending on h and e. Match on the top nibble. Flags: u bit 4 update Track Register m bit 4 multiple sector h bit 3 0 = enable spin-up sequence, 1 = disable v bit 2 verify destination track e bit 2 add settling delay p bit 1 0 = ENABLE write precompensation, 1 = disable a0 bit 0 0 = normal data mark, 1 = deleted data mark Step rates (r1,r0), WD1772 values at 8MHz: 00 = 6ms 01 = 12ms 10 = 2ms 11 = 3ms These are WD1772 specific. The WD1770 uses 6, 12, 20 and 30ms for the same encodings. On the Atari 3ms is the normal setting and h must always be 0, since MO is wired straight to the drive. Sources: Western Digital's own WD1772 data sheet, cross-checked against EmuTOS bios/fdc.h. Read Track being 1110 confirmed by both, correcting a misprint in DrCoolZic's edition.
$FFFF8606.W|R-|WDC_DMA|DMA Status %________ _____DSE | | | | Data request condition--------------------+|| | | | | Sector count 0:zero,1:not zero-------------+| | | | | DMA 0:error,1:no error----------------------+ | |-W| |DMA Mode %_______W FD_SHAA_ | | | | 0:read,1:write---------------------+ || |||| | | | | 0:HDC,1:FDC access-------------------+| |||| | | | | DMA 0:on,1:off (ignored STF/STE)----+ |||| | | | | 0:FDC/HDC register 1:sector count-------+||| | | | | 0:FDC,1:HDC access-----------------------+|| | | | | A1/A0 pin 0:low,1:high--------------------++ |
$FFFF8606 WDC_DMA DMA Status (read) / DMA Mode (write) READ - status, bits 2-0: Bit 2 state of the FDC DRQ signal Bit 1 sector count: 0 = reached zero, 1 = not zero Bit 0 DMA error: 1 = NO error, 0 = error Bit 0 is inverted from the obvious reading. It was documented the wrong way round here and in the widely mirrored Dan Hollis listing for many years. Atari's own TOS tests it as: move.w #$0090,(a6) examine DMA status register move.w (a6),d0 btst #0,d0 bit zero indicates DMA ERROR beq.s floprd6 (when its zero -- retry) EmuTOS agrees: DMA_OK is 0x0001, commented 1=ok, 0=error. Confirmed by ijor, July 2026. WRITE - mode control: Bit 8 direction, 1 = memory to controller (write) Toggling this bit RESETS the DMA, flushing both FIFOs and clearing the sector count register. Bit 7 1 = acknowledge FDC DRQ, 0 = acknowledge HDC DRQ Bit 6 nominally DMA enable, but IGNORED on STF and STE Bit 4 0 = external controller registers, 1 = sector count Bit 3 0 = assert FDCS*, 1 = assert HDCS* Bit 2 CA2 output, drives FDC A1 Bit 1 CA1 output, drives FDC A0 Bit 0 unused, set 0 The DMA FIFOs are 16 bytes and are never flushed automatically, so data only reaches memory in multiples of 16 bytes. A single Read Address moves 6 bytes and therefore reaches memory not at all; issue it repeatedly to push data through. Do not poll this status register during a transfer, it can disrupt it. Poll MFP GPIP bit 5 at $FFFFFA01 instead: mask with $20, result zero means the FDC has interrupted.
$FFFF8609.B|RW|WDC_BSH|DMA Base and Counter Hi | $FFFF860B.B|RW|WDC_BSM|DMA Base and Counter Mi | $FFFF860D.B|RW|WDC_BSL|DMA Base and Counter Lo |
$FFFF860E.B|RW|WDC_FDN|Frequency and Density control %______FD |STE,F | | |Frequency 0:8MHz,1:16MHz--------------------+| | | | |Density 0:DD,1:HD----------------------------+ |
$FFFF860E WDC_FDN Frequency and Density control Bit 1 Frequency 0 = 8MHz, 1 = 16MHz Bit 0 Density 0 = DD (double), 1 = HD (high) STE and Falcon only. Was previously labelled WDC_BSL here, duplicating the label on $FFFF860D.
===========#==#=======#===============================================#===== ----------------------|DMA SCSI |----- ===========#==#=======#===============================================#===== $FFFF8701.B|RW|SCS_DA0|DMA Address Pointer (Highest byte) |TT $FFFF8703.B|RW|SCS_DA1|DMA Address Pointer (High byte) |TT $FFFF8705.B|RW|SCS_DA2|DMA Address Pointer (Low byte) |TT $FFFF8707.B|RW|SCS_DA3|DMA Address Pointer (Lowest byte) |TT $FFFF8709.B|RW|SCS_BC0|DMA Byte Counter (Highest byte) |TT $FFFF870B.B|RW|SCS_BC1|DMA Byte Counter (High byte) |TT $FFFF870D.B|RW|SCS_BC2|DMA Byte Counter (Low byte) |TT $FFFF870F.B|RW|SCS_BC3|DMA Byte Counter (Lowest byte) |TT $FFFF8710.W|Rw|SCC_RD0|Rest data (High Word) |TT $FFFF8712.W|Rw|SCC_RD1|Rest data (Low Word) |TT $FFFF8714.W|Rw|SCS_CTL|DMA SCSI Control Register %________ BZ____DW |TT | | | Bus Error 0:no,1:yes-----------------+| || |TT | | | Byte Counter Zero 0:no,1:yes----------+ || |TT | | | DMA 0:off,1:on-----------------------------+| |TT | | | DMA 0:read,1:write--------------------------+ |TT ===========#==#=======#===============================================#===== ----------------------|5380 SCSI Drive Controller |----- ===========#==#=======#===============================================#=====
$FFFF8781.B|RW|SCS_CDB|Contents of SCSI-Data Buses |TT
NCR 5380 SCSI CONTROLLER - REGISTER MAP IMPORTANT: the register names on this page were wrong for five of the eight registers and have been corrected. The old names are noted below so anyone who finds them elsewhere knows why they differ. The 5380 is a standard part with a well known register map; several registers do different things on read and on write, which is the likely source of the confusion. Addr Reg Read Write $FFFF8781 0 Current SCSI Data Output Data $FFFF8783 1 Initiator Command Initiator Command $FFFF8785 2 Mode Register Mode Register $FFFF8787 3 Target Command Target Command $FFFF8789 4 Current SCSI Bus Status Select Enable $FFFF878B 5 Bus and Status Start DMA Send $FFFF878D 6 Input Data Start DMA Target Receive $FFFF878F 7 Reset Parity/Interrupt Start DMA Initiator Recv Old names on this page, now corrected: $8785 was 'Transfer Start Register' -> Mode Register $8789 was 'Bus Status Register' -> ID Select / Bus Status $878B was 'Device Status Register' -> DMA Send / Bus+Status $878D was 'SCSI-Bus Command Data' -> DMA Target Rx / Input $878F was 'Reset Interrupts, Parity error, Start DMA-Action' -> DMA Init Rx / Reset Address to register number mapping, per Hatari src/ncr5380.c: register = (address / 2) & 7 so $FFFF8781 is register 0, $FFFF8783 register 1, and so on. Only odd addresses respond; even addresses are ignored. CONFLICT NOTE: the Atari Compendium lists this block starting at $00FF8780 with OB (odd byte) markers, which resolves to the same odd addresses shown here. Its names match the standard 5380 map and therefore agree with Hatari. This wiki's earlier names matched neither. If you find a listing using the old names, it most likely descends from the same source as this page did. Verified against Hatari src/ncr5380.c and the Atari Compendium.
$FFFF8783.B|RW|SCS_ICR|Init Command Register |TT $FFFF8785.B|RW|SCS_MR |Mode Register |TT $FFFF8787.B|RW|SCS_TCR|Target Command Register |TT
$FFFF8789.B|RW|SCS_SEL|ID Select / Current SCSI Bus Status |TT
$FFFF8789 Register 4 READ - Current SCSI Bus Status: Bit 7 RST Bit 6 BSY Bit 5 REQ Bit 4 MSG Bit 3 C/D (command/data) Bit 2 I/O (input/output) Bit 1 SEL Bit 0 DBP (data bus parity) Bits 4-2 together give the current bus phase: 000 Data Out 011 Status 001 Data In 110 Message Out 010 Command 111 Message In WRITE - Select Enable Register: sets which SCSI ID the controller responds to when selected as a target. Verified against Hatari src/ncr5380.c, which builds this value from the live bus signals and shifts the bus phase into bits 4-2 exactly as above.
$FFFF878B.B|RW|SCS_DMA|Start DMA Send / Bus and Status Register |TT
$FFFF878B Register 5 READ - Bus and Status Register: Bit 7 End of DMA Bit 6 DMA Request Bit 5 Parity Error Bit 4 Interrupt Request active Bit 3 Phase Match (bus phase equals Target Command bits) Bit 2 Busy Error Bit 1 ATN Bit 0 ACK WRITE - Start DMA Send: writing here begins a DMA transfer from memory to the SCSI bus. Verified against Hatari src/ncr5380.c.
$FFFF878D.B|RW|SCS_TRG|Start DMA Target Rx / Input Data Register |TT $FFFF878F.B|RW|SCS_INI|Start DMA Initiator Rx / Reset Parity-Interrupt|TT





Back to Memory Map for Atari ST,STE,TT and Falcon

YM, DSP & DMA Sound

Maintained at YM, DSP & DMA Sound

===========#==#=======#===============================================#===== ----------------------|YM2149/AY-3-8910 Sound Chip |----- ===========#==#=======#===============================================#=====
$FFFF8800.B|R-|PSG_SEL|Read Data | |-W| |Register Select |
$FFFF8800 PSG_SEL YM2149 register select (W) / read data (R) Write a register number 0-15 here, then read or write the value at $FFFF8802. The register set: 0 Channel A tone period, fine (8 bits) 1 Channel A tone period, coarse (4 bits) 2 Channel B tone period, fine 3 Channel B tone period, coarse 4 Channel C tone period, fine 5 Channel C tone period, coarse 6 Noise generator period (5 bits) 7 Mixer control and I/O port direction 8 Channel A amplitude 9 Channel B amplitude 10 Channel C amplitude 11 Envelope period, fine 12 Envelope period, coarse 13 Envelope shape (4 bits) 14 I/O Port A (floppy select, printer, RS232) 15 I/O Port B (Centronics data) Register 7, mixer control: Bit 7 Port B direction, 1 = output Bit 6 Port A direction, 1 = output Bit 5 Noise off, channel C Bit 4 Noise off, channel B Bit 3 Noise off, channel A Bit 2 Tone off, channel C Bit 1 Tone off, channel B Bit 0 Tone off, channel A Note the enable bits are inverted: a 0 enables that source. Registers 8-10, amplitude: Bits 3-0 fixed volume level 0-15 Bit 4 1 = use envelope instead of fixed volume Register 13, envelope shape, bits 3-0: Bit 3 CONT continue after first cycle Bit 2 ATT attack, 1 = rising Bit 1 ALT alternate direction each cycle Bit 0 HOLD hold at final level YM2149 versus AY-3-8910 The YM2149 is Yamaha's licensed version of General Instrument's earlier AY-3-8910. The two are register compatible: same 16 registers, same layout, same writes. There are no extra registers on either part. The differences are internal: - The envelope counter is 5 bit on the YM2149 (32 steps) against 4 bit on the AY (16 steps), giving smoother volume ramps. The envelope clock is divided by 8 rather than 16 to keep the cycle time the same across twice the steps. The volume registers stay 4 bit on both, so there is nothing extra to write. - The YM reads registers back exactly as written. The AY returns 0 for unused bits regardless of what was written. - The YM has a 2V DC offset on all outputs; the AY has 0.2V on a channel only while an envelope is active. This is why the AY sounds louder. Nothing in TOS depends on any of this. AY documentation applies to the ST unchanged as far as the register interface goes. Register names verified against Hatari src/includes/psg.h. Mixer and port-direction bit masks verified against EmuTOS bios/psg.h (PSG_PORTB_OUTPUT 0x80, PSG_PORTA_OUTPUT 0x40, PSG_NOISE_MASK 0x38, PSG_TONE_MASK 0x07).
$FFFF8802.B|rW|PSG_DAT|Write Data | | | | PSG Register 14 - Port A %RICDPBAS | | | | Reset IDE 0:no,1:reset (slow down)---+||||||| |F | | | Internal Speaker 0:on,1:off-----------+|||||| |F | | | Centronics Strobe----------------------+||||| | | | | Reset DSP 0:no,1:reset------------------+|||| |F | | | Printer Select In------------------------+||| | | | | Drive B select 0:on,1:off-----------------+|| | | | | Drive A select 0:on,1:off------------------+| | | | | Side select 0:side1,1:side0-----------------+ | | | | PSG Register 15 - Port B %xxxxxxxx | | | | Centronics Data Port-----------------++++++++ |
$FFFF8802 PSG_DAT YM2149 data register Reads or writes the register previously selected at $FFFF8800. PORT A, register 14, is the one that matters on the ST. It carries the floppy drive and side select lines: Bit 7 Reset IDE 0 = no, 1 = reset Falcon Bit 6 Internal speaker 0 = on, 1 = off Falcon Bit 5 Centronics strobe Bit 4 Reset DSP 0 = no, 1 = reset Falcon Bit 3 Printer select in Bit 2 Drive B select 0 = selected Bit 1 Drive A select 0 = selected Bit 0 Side select 1 = side 0, 0 = side 1 Note the side select polarity: the bit SET selects side 0. This is not a typo in the listing, it is how the hardware works. Bits 3-7 carry RS232 RTS and DTR, the Centronics strobe and a general purpose output. Always read the port, modify only the bits you need and write it back. Writing a whole byte will disturb the serial and printer lines. Disable interrupts around any access to this register, or the floppy VBL routine can deselect the drive underneath you. Set flock at $0000043E to a non-zero value first. Register layout verified against Hatari and EmuTOS.
$FFFF8804.B|RW| - |Add-on sound, not present on stock hardware |*
$FFFF8804 to $FFFF8808 Add-on sound registers Not present on stock Atari hardware. $FFFF8800 and $FFFF8802 are the YM2149 select and data registers; some add-on boards extend the decoded range upward to $FFFF8808 for their own sound hardware. Known to be used by: SEC Booster. IMPORTANT, FALCON: these addresses do NOT behave this way on a Falcon. On that machine the PSG registers are fixed at $FFFF8800 and $FFFF8802 only, and every other address in the range is masked out. Any write to the shadow registers $FFFF8804 to $FFFF88FF will cause a BUS ERROR. So an add-on using this range works on the ST and STE, where the PSG address decoding is incomplete and the registers repeat through the range, but the same code will bus error on a Falcon. Anything writing here should check the machine type first. Source: the Atari F030 and CT60 Hardware Register Listing, which states the shadow registers are masked out and warns game and demo coders specifically. Extended bit information is not currently available for these registers. The addresses are documented; what each bit does is not.
$FFFF8806.B|RW| - |Add-on sound, not present on stock hardware |* $FFFF8808.B|RW| - |Add-on sound, not present on stock hardware |* ===========#==#=======#===============================================#===== ----------------------|DMA, CODEC, ADC, DAC, DSP-Transmit/Receive |----- ===========#==#=======#===============================================#=====
$FFFF8900.W|RW|SND_DMA|Sound-DMA-Control %____RPRP F_EL__EL |F,STE | | | Timer A after Record/Play-------++|| | || || |F | | | MFP I/O 7 after Record/Play-------++ | || || |F | | | Frame Registers 0:play,1:record------+ || || |F | | | DMA record Enable/Loop-----------------++ || |F | | | DMA play Enable/Loop-----------------------++ |F,STE
$FFFF8900 SND_DMA Sound DMA control Bits 1-0, DMA play: Bit 1 loop: 0 = play once, 1 = repeat from frame start Bit 0 enable: 0 = stop, 1 = start playback Bits 5-4, DMA record (Falcon only), same enable/loop pair. Bit 7 frame register select: 0 = play frame, 1 = record Bits 11-8 and 15-12 select what happens at the end of a record or play frame: Timer A event and MFP I/O 7 event. On the STE only bits 1-0 exist. The record path and the event bits are Falcon additions. Playback reads from the frame start address at $FFFF8903-07 and continues to the frame end at $FFFF890F-13. The current position can be read from $FFFF8909-0D while playing.
$FFFF8903.B|RW|SND_FSH|Frame Start Hi |F,STE
$FFFF8903 / $FFFF8905 / $FFFF8907 Frame Start address Three byte registers holding a 24 bit address: $FFFF8903 bits 23-16, high $FFFF8905 bits 15-8, middle $FFFF8907 bits 7-0, low The address of the first byte of sample data. Bit 0 of the low byte is ignored: the DMA fetches on even addresses only, so the frame must start word aligned. On the Falcon, bit 7 of $FFFF8900 selects whether these registers address the play frame or the record frame. Loaded into the DMA counter when playback starts, and reloaded from here on each repeat if the loop bit is set.
$FFFF8905.B|RW|SND_FSM|Frame Start Mi |F,STE $FFFF8907.B|RW|SND_FSL|Frame Start Lo |F,STE
$FFFF8909.B|RW|SND_FCH|Frame Count Hi |F,STE
$FFFF8909 / $FFFF890B / $FFFF890D Frame Count Three byte registers holding the current 24 bit DMA address: $FFFF8909 bits 23-16, high $FFFF890B bits 15-8, middle $FFFF890D bits 7-0, low Read these while playing to find how far through the sample the DMA has reached. The value advances from the frame start toward the frame end. Reading the three bytes is not atomic, so the counter can move between reads. Read high, middle then low and re-read if the high byte changed, or read with interrupts disabled. Hatari tracks this internally as frameCounterAddr, refilling its FIFO from that address as playback advances.
$FFFF890B.B|RW|SND_FCM|Frame Count Mi |F,STE $FFFF890D.B|RW|SND_FCL|Frame Count Lo |F,STE
$FFFF890F.B|RW|SND_FEH|Frame End Hi |F,STE
$FFFF890F / $FFFF8911 / $FFFF8913 Frame End address Three byte registers holding a 24 bit address: $FFFF890F bits 23-16, high $FFFF8911 bits 15-8, middle $FFFF8913 bits 7-0, low The address one past the last byte of sample data. Playback stops when the frame counter reaches this value. If the loop bit in $FFFF8900 is set, the counter reloads from the frame start registers and playback continues. If not, playback stops and the enable bit clears. As with the start address, bit 0 of the low byte is ignored.
$FFFF8911.B|RW|SND_FEM|Frame End Mi |F,STE $FFFF8913.B|RW|SND_FEL|Frame End Lo |F,STE
$FFFF8920.W|RW|SND_SMC|Sound Mode Control %__SS__PP MB____FF |F,STE | | | DAC to track %SS--------------++ || || || |F | | | Play %PP+1 tracks-----------------++ || || |F | | | 0:Stereo,1:Mono----------------------+| || |F | | | 0:8bit,1:16bit------------------------+ || |F | | | Falcon:(unused)--STE: 6258 Hz--------------00 |F,STE | | | Falcon:12292 Hz--STE:12517 Hz--------------01 |F,STE | | | Falcon:19668 Hz--STE:25033 Hz--------------10 |F,STE | | | Falcon:49170 Hz--STE:50066 Hz--------------11 |F,STE
$FFFF8920 SND_SMC Sound mode control This is a word register, but the two halves are separate: $FFFF8920 is the track control byte and $FFFF8921 the mode control byte. Hatari and EmuTOS treat them separately. $FFFF8921, mode control: Bit 7 0 = stereo, 1 = mono Bit 6 0 = 8 bit, 1 = 16 bit Bits 1-0 sample rate: Falcon: 00 unused, 01 12292Hz, 10 19668Hz, 11 49170Hz STE: 00 6258Hz, 01 12517Hz, 10 25033Hz, 11 50066Hz $FFFF8920, track control (Falcon only): Bits 5-4 which track the DAC monitors Bits 1-0 number of tracks to play, minus one The mono/stereo bit was previously printed on this page with both states as 0. Corrected from EmuTOS bios/dmasound.c, which does modectrl |= 0x80 with the comment 'Select mono', and from Hatari src/falcon/crossbar.c, which reads isStereo as the inverse of bit 7 and is16Bits from bit 6.
$FFFF8922.B|RW| - |Microwire Data Register |STE
$FFFF8922 Microwire Data Register (with $FFFF8924 Mask) The STE and TT use a Microwire serial link to control an LMC1992 audio processor, which handles master volume, left and right balance, bass, treble, and the mix between DMA sound and the YM2149 output. Write the command word here; $FFFF8924 is the mask that clocks it out. Command format: 10 CCC DDD DDD 10 chipset address, always this value CCC command DDD DDD data Commands: 000 XXX XDD Mixing 00 DMA sound only 01 DMA sound + YM2149, full frequency range 10 DMA sound + YM2149 through a low pass filter -> gives DMA sound only 11 input 3, not connected -> DMA only 001 XXD DDD Bass 0 000 = -12dB, 0 110 = 0dB, 1 100 = +12dB, 2dB steps 010 XXD DDD Treble same scale as bass 011 DDD DDD Master volume 000 000 = -80dB, 010 100 = -40dB, 101 XXX = 0dB, 2dB steps 100 XDD DDD Right channel volume 00 000 = -40dB, 01 010 = -20dB, 10 1XX = 0dB 101 XDD DDD Left channel volume, same scale as right Any other command value is undefined. THE STE MIXING BUG Note the arrows on mixing modes 10 and 11 above. Mode 10 is supposed to mix the YM2149 in through a low pass filter, which would attenuate it relative to the DMA sound. On the STE it does not work: input 2 is not wired, so selecting it drops the YM output entirely and you get DMA sound only. Mode 11 selects input 3, which is not connected at all. The practical effect is that the STE gives you only two useful choices, DMA alone or DMA plus YM at full volume, with no way to balance the two in software. In games such as Xenon the YM sound ends up considerably louder than the DMA samples. A hardware fix for this was worked out by P. Putnik and is documented here, along with the rest of the STE DAC work: exxosforum.co.uk STE DAC fix, LMC section Command set verified against Hatari src/dmaSnd.c, which documents the same non-functional mixing modes and carries the full LMC1992 volume tables.
$FFFF8924.B|RW| - |Microwire Mask Register |STE
$FFFF8924 Microwire Mask Register Works with the data register at $FFFF8922. The mask marks which bits of the data word are the command; the hardware shifts both registers out together over the Microwire serial link to the LMC1992. The usual value is $07FF, an 11 bit command window matching the 10 CCC DDD DDD command format described at $FFFF8922. Behaviour during a transfer, per Hatari src/dmaSnd.c: - The data register shifts left one bit per step. - The mask register ROTATES left rather than shifting, so after a complete transfer it reads back as it started. - One shift takes 8 CPU cycles, so a full 16 step transfer takes 128 cycles. Because the mask rotates back to its original value, reading it is not a reliable way to tell whether a transfer has finished. The data register shifting to zero is the usable indicator. Verified against Hatari src/dmaSnd.c.
===========#==#=======#===============================================#===== ----------------------|Falcon Sound Matrix and CODEC |----- ===========#==#=======#===============================================#=====
$FFFF8930.W|RW|SND_CBO|Crossbar Output Select Controller |F
$FFFF8930 SND_CBO Crossbar source (input) select Word register, four 4-bit fields, one per source device. Bit layout from Hatari src/falcon/crossbar.c: Bits 15-12 A/D Converter Bits 13-12 clock: 00 = 25.175MHz, 01 = external, 10 = 32MHz (do not use) Bits 11-8 External Input Bit 11 0 = DSP IN, 1 = all others Bits 10-9 clock, as above Bit 8 0 = handshake on, 1 = handshake off Bits 7-4 DSP transmit Bit 7 0 = tristate and disconnect DSP (external SSI use only), 1 = connect DSP to multiplexer Bits 6-5 clock, as above Bit 4 0 = handshake on, 1 = handshake off Bits 3-0 DMA playback Bit 3 0 = handshaking on, destination DSP receive 1 = destination is not DSP receive Bits 2-1 clock, as above Bit 0 0 = handshake on, 1 = handshake off Verified against Hatari src/falcon/crossbar.c.
$FFFF8932.W|RW|SND_CBI|Crossbar Input Select Controller |F
$FFFF8932 SND_CBI Crossbar destination (output) select Word register, four 4-bit fields, one per destination. Bit layout from Hatari src/falcon/crossbar.c: In each field the two-bit source selector means: 00 = DMA output 01 = DSP output 10 = External input 11 = ADC input Bits 15-12 D/A Converter Bits 13-12 source, as above Bits 11-8 External output Bit 11 0 = DSP out, 1 = all others Bits 10-9 source, as above Bit 8 0 = handshake on, 1 = handshake off Bits 7-4 DSP receive Bit 7 0 = tristate and disconnect DSP (external SSI use only), 1 = connect DSP to multiplexer Bits 6-5 source, as above Bit 4 0 = handshake on, 1 = handshake off Bits 3-0 DMA record Bit 3 0 = handshaking on, destination DSP transmit 1 = all Bits 2-1 source, as above Bit 0 0 = handshake on, 1 = handshake off Verified against Hatari src/falcon/crossbar.c.
$FFFF8934.B|RW|SND_FDE|Frequency Divider, External Sync |F
$FFFF8934 SND_FDE Frequency Divider, External Sync Clock divider used when the crossbar is set to take an external clock. Hatari accepts writes here but the value only matters when an external clock source is actually connected, which on a standard Falcon it is not. See $FFFF8930 and $FFFF8932 for the clock and source selection that decides whether this register is used at all.
$FFFF8935.B|RW|SND_FDI|Frequency Divider, Internal Sync |F
$FFFF8935 SND_FDI Frequency Divider, Internal Sync Bits 3-0 clock divider, 0-15 Bits 7-4 unused Divides the selected internal clock (25.175MHz or 32MHz, chosen per device in $FFFF8930) down to the sample rate. Together with the clock choice and the number of active tracks this sets the actual playback frequency. Verified against Hatari src/falcon/crossbar.c, which masks the written value with 0x0F and recalculates the clock cycles.
$FFFF8936.B|RW|SND_RTS|Record Tracks Select |F
$FFFF8936 SND_RTS Record Tracks Select Bits 1-0 number of tracks to record 0 = 1 track 1 = 2 tracks 2 = 3 tracks 3 = 4 tracks Bits 7-2 unused Verified against Hatari src/falcon/crossbar.c.
$FFFF8937.B|RW|SND_CIS|CODEC Input Source |F
$FFFF8937 SND_CIS CODEC Input Source Bit 1 source = multiplexer (the crossbar) Bit 0 source = A/D converter Bits 7-2 unused Selects what feeds the CODEC's 16 bit adder. Both bits can be set, which sums the two sources. Verified against Hatari src/falcon/crossbar.c.
$FFFF8938.B|RW|SND_CAD|CODEC ADC Input |F
$FFFF8938 SND_CAD CODEC ADC Input Bit 1 Left channel 0 = microphone, 1 = PSG (YM2149) Bit 0 Right channel 0 = microphone, 1 = PSG (YM2149) Bits 7-2 unused This is how the Falcon routes the YM2149 output into the ADC so it can be mixed digitally, rather than through the analogue path the STE uses. Verified against Hatari src/falcon/crossbar.c.
$FFFF8939.B|RW|SND_GAI|Gain settings %LLLLRRRR |F
$FFFF8939 SND_GAI Gain settings, input amplifier Bits 7-4 Left channel gain, 0-15 Bits 3-0 Right channel gain, 0-15 Amplification for the ADC input, in +1.5dB steps per increment. Verified against Hatari src/falcon/crossbar.c, which indexes its ADC volume table with (value >> 4) for left and (value & 15) for right.
$FFFF893A.W|RW|SND_ATT|Attenuation settings %LLLLRRRR |F
$FFFF893A SND_ATT Attenuation settings, output reduction Word register: Bits 11-8 Left channel attenuation, 0-15 Bits 7-4 Right channel attenuation, 0-15 Bits 15-12 and 3-0 unused Reduction for the DAC output, in -1.5dB steps per increment. Note the field positions: this is not the same layout as the gain register at $FFFF8939. Hatari reads left from (value >> 8) & 0x0F and right from (value >> 4) & 0x0F. Verified against Hatari src/falcon/crossbar.c.
$FFFF893C.W|R-|SND_CST|CODEC Status |F
$FFFF893C SND_CST CODEC Status Bit 1 Left channel overflow Bit 0 Right channel overflow Bits 15-2 unused Overflow flags set when the CODEC input clips. Read only in practice, though Hatari accepts writes. This register is absent from the Atari Compendium listing and was found in Hatari and EmuTOS. EmuTOS bios/dmasound.c sets it to $003F on reset. Verified against Hatari src/falcon/crossbar.c.
$FFFF8940.W|RW|SND_GPD|GPIO Data Direction |F
$FFFF8940 SND_GPD GPIO Data Direction Bits 2-0 direction for the three general purpose I/O pins 0 = input, 1 = output Bits 15-3 unused Three GPIO pins are brought out on the Falcon's DSP connector. They are not used by TOS and are free for expansion hardware. UNVERIFIED: address confirmed by the Atari Compendium, but the bit detail here is not corroborated by Hatari or EmuTOS, neither of which implements these pins.
$FFFF8942.W|RW|SND_GPI|GPIO Data |F
$FFFF8942 SND_GPI GPIO Data Bits 2-0 data for the three general purpose I/O pins Bits 15-3 unused Reads the pin state for pins set as inputs at $FFFF8940, and drives the pin for those set as outputs. UNVERIFIED: address confirmed by the Atari Compendium, but the bit detail here is not corroborated by Hatari or EmuTOS.





Back to Memory Map for Atari ST,STE,TT and Falcon

MFP, RTC & anything else

Maintained at MFP, RTC & anything else

===========#==#=======#===============================================#===== ----------------------|Realtime Clock Chip, Non Volatile Memory |----- ===========#==#=======#===============================================#=====
$FFFF8961.B|RW|NVM_CTL|Register Select |TT,F
$FFFF8961 and $FFFF8963 Real Time Clock / NVRAM $FFFF8961 Address register: write the location to access $FFFF8963 Data register: read or write that location TT and Falcon. The NVRAM holds 50 bytes of user settings (language, keyboard, boot preferences) plus the real time clock registers, in a battery backed MC146818 compatible part. Access is indirect: write an address to $FFFF8961, then read or write $FFFF8963. EmuTOS bios/nvram.c wraps this in the NVMaccess XBIOS call rather than exposing the registers. From the Atari Compendium.
$FFFF8963.B|RW|NVM_DAT|Data of selected Register |TT,F
$FFFF8964.B|RW| - |Add-on control, not present on stock hardware |*
$FFFF8964, $FFFF896A, $FFFF896C, $FFFF8970 Add-on control Not present on stock Atari hardware. These addresses sit in the gap above the TT and Falcon real time clock registers and below the reserved area at $FFFF8A00. Known to be used by: $FFFF8964 FLASHY CLOCK $FFFF896A SEC BOOSTER $FFFF896C FLASHY CLOCK $FFFF8970 FLASHY CLOCK FLASHY CLOCK also uses $FFFF89F0 and $FFFF89F2 for its real time clock, and $FFFFFFFF as a control register. Extended bit information is not currently available for these registers. The addresses are documented; what each bit does is not. No conflict found: neither EmuTOS nor Hatari references any address in the $FFFF8964 to $FFFF8970 range.
$FFFF896A.B|RW| - |Add-on control, not present on stock hardware |* $FFFF896C.B|RW| - |Add-on control, not present on stock hardware |* $FFFF8970.B|RW| - |Add-on control, not present on stock hardware |*
$FFFF89F0.B|RW| - |Add-on real time clock |*
$FFFF89F0 and $FFFF89F2 Add-on real time clock Not present on stock Atari hardware. Known to be used by: FLASHY CLOCK. Extended bit information is not currently available for these registers. No conflict found: neither EmuTOS nor Hatari references either address.
$FFFF89F2.B|RW| - |Add-on real time clock |* ===========#==#=======#===============================================#===== ----------------------|DMA SCC |----- ===========#==#=======#===============================================#===== $FFFF8C01.B|RW|SCC_DA0|DMA Address Pointer (Highest byte) |TT $FFFF8C03.B|RW|SCC_DA1|DMA Address Pointer (High byte) |TT $FFFF8C05.B|RW|SCC_DA2|DMA Address Pointer (Low byte) |TT $FFFF8C07.B|RW|SCC_DA3|DMA Address Pointer (Lowest byte) |TT $FFFF8C09.B|RW|SCC_BC0|DMA Byte Counter (Highest byte) |TT $FFFF8C0B.B|RW|SCC_BC1|DMA Byte Counter (High byte) |TT $FFFF8C0D.B|RW|SCC_BC2|DMA Byte Counter (Low byte) |TT $FFFF8C0F.B|RW|SCC_BC3|DMA Byte Counter (Lowest byte) |TT $FFFF8C10.W|Rw|SCC_RD0|Rest data (High Word) |TT $FFFF8C12.W|Rw|SCC_RD1|Rest data (Low Word) |TT $FFFF8C14.W|Rw|SCC_CTL|DMA SCC Control Register %________ BZ____DW |TT | | | Bus Error 0:no,1:yes-----------------+| || |TT | | | Byte Counter Zero 0:no,1:yes----------+ || |TT | | | DMA 0:off,1:on-----------------------------+| |TT | | | 0:DMA read,1:DMA write----------------------+ |TT ===========#==#=======#===============================================#===== ----------------------|SCC Y8530 - Serial Communication Controller |----- ===========#==#=======#===============================================#=====
$FFFF8C81.B|RW|SCA_CTL|Channel A Control (select/read/write Register) |SCC
$FFFF8C81 to $FFFF8C87 SCC 8530 Serial Controller $FFFF8C81 Channel A control $FFFF8C83 Channel A data $FFFF8C85 Channel B control $FFFF8C87 Channel B data The 8530 has far more internal registers than the four addresses above suggest. Access is indirect: write a register number to the control address, then read or write the control address again to reach that register. Register 0 is reached directly without a preceding select. The data addresses map to internal register 8. The SCC generates interrupts through the vector table at $00000180 to $000001BC. That table is SPARSE: only every other longword is a real vector, alternating with an unused slot. See the System variables and low RAM page. TT, Mega STE and Falcon.
$FFFF8C83.B|RW|SCA_DAT|Channel A Data (read/write Register 8) |SCC $FFFF8C85.B|RW|SCB_CTL|Channel B Control (select/read/write Register) |SCC $FFFF8C87.B|RW|SCB_DAT|Channel B Data (read/write Register 8) |SCC ===========#==#=======#===============================================#===== ----------------------|VME Bus |----- ===========#==#=======#===============================================#===== $FFFF8E01.B|RW|VME_MR0|VME Mask Register 0 |TT,ME $FFFF8E03.B|RW|VME_SR0|VME Status Register 0 %EMSV_HS_ |TT,ME | | | Error 0:no,1:yes---------------------+||| || |TT,ME | | | MFP-----------------------------------+|| || |TT,ME | | | SCC------------------------------------+| || |TT,ME | | | VBL-------------------------------------+ || |TT,ME | | | HBL---------------------------------------+| |TT,ME | | | Software Interrupt-------------------------+ |TT,ME $FFFF8E05.B|RW|VME_IN0|Force Interrupt on Level 1 %_______F |TT,ME $FFFF8E07.B|RW|VME_IN1|Force Interrupt on Level 3 %_______F |TT,ME $FFFF8E09.B|RW|SCU_GP1|SCU General Purpose Register 1 |TT,ME | | | Verified: EmuTOS bios/machine.h (SCU_GPR1 | | | | 0xffff8e09) and Atari TOS 3.06 bios/startup.S,| | | | which uses bit 0 as a memory-config-valid | | | | flag. | $FFFF8E0B.B|RW|SCU_GP2|SCU General Purpose Register 2 |TT,ME | | | UNVERIFIED: Atari Compendium only. GPR1 next | | | | door is confirmed twice, so this is very | | | | likely real, but no source touches it. | $FFFF8E0D.B|RW|VME_MR1|VME Mask Register 1 |TT,ME $FFFF8E0F.B|RW|VME_SR1|VME Status Register 1 %7654321_ |TT,ME | | | VME Interrupt 1-7 0:on,1:off---------+++++++ | ===========#==#=======#===============================================#===== $FFFF8E21.B|RW|M_E_CAC|Mega STe Cache/Processor Control |ME | | | $FF 16MHz with cache |ME | | | $FE 16MHz, cache off |ME | | | $F4 8MHz |ME | | | CORRECTED: was listed at $FFFF8E0F, which | | | | belongs to VME_SR1. Verified at $FFFF8E21 by | | | | Atari TOS 3.06 bios/startup.S: ori.b | | | | #3,($ffff8e21).w with the comment "turn on | | | | 16MHz and cache". Value table from the Atari | | | | Compendium. | ===========#==#=======#===============================================#===== ----------------------|Paddle Ports |----- ===========#==#=======#===============================================#===== $FFFF9200.W|RW|PAD_BUT|Paddle/Joy Buttons %xxxxxxxx ____3210 |STE,F | | | Switches--------------------++++++++ |,TT | | | On Falcon at U47: MSB on the right, closed=0 | $FFFF9202.W|RW|PAD_MOV|Paddle/Joy Move |STE,F $FFFF9210.W|RW|PAD_PD0|Pad0 Position |STE,F $FFFF9212.W|RW|PAD_PD1|Pad1 Position |STE,F $FFFF9214.W|RW|PAD_PD2|Pad2 Position |STE,F $FFFF9216.W|RW|PAD_PD3|Pad3 Position |STE,F $FFFF9220.W|RW|PAD_LPX|Lightpen X |STE,F $FFFF9222.W|RW|PAD_LPY|Lightpen Y |STE,F ===========#==#=======#===============================================#===== ----------------------|DSP 56001 Host - Digital Signal Processor |----- ===========#==#=======#===============================================#=====
$FFFFA200.B|RW|DSP_ICR|Interrupt Control Register (%IMMHH_TR) |DSP
$FFFFA200 DSP_ICR Interrupt Control Register (DSP X:$FFE9) Bit 7 INIT setting this forces initialisation of the host interface Bits 6-5 DMA mode control: 00 interrupt mode, DMA off 01 24 bit DMA mode 10 16 bit DMA mode 11 8 bit DMA mode Bit 4 HF1 host flag 1 Bit 3 HF0 host flag 0 Bit 2 unused Bits 1-0 Data transfer mode The host flags are general purpose signalling bits readable by the DSP; they carry no fixed meaning in hardware. Falcon only. From the Atari Compendium.
$FFFFA201.B|RW|DSP_CVR|Command Vector Register (%I__VVVVV) |DSP
$FFFFA201 DSP_CVR Command Vector Register (DSP X:$FFE9) Bit 7 Host command bit Bits 6-5 unused Bits 4-0 Host vector, 0 to 31 Writing a vector with the command bit set causes the DSP to take an interrupt to that vector, which is how the host asks the DSP to run a routine. Falcon only. From the Atari Compendium.
$FFFFA202.B|RW|DSP_ISR|Interrupt Status Register (%ID_HHETR) |DSP
$FFFFA202 and $FFFFA203 DSP Status and Vector $FFFFA202 Interrupt Status Register (DSP X:$FFE8) $FFFFA203 Interrupt Vector Register The status register reports the state of the host interface, including whether the transmit register is empty and the receive register is full, plus the two host flags coming back from the DSP. The vector register holds the 680x0 exception vector number used when the DSP raises an interrupt to the host. The wiki summary line gives the status register bit pattern as %ID_HHETR: I = interrupt, D = DMA, HH = host flags, E = transmit empty, T = transmit, R = receive. Falcon only. The Atari Compendium names both registers but gives no bit breakdown for the status register.
$FFFFA203.B|RW|DSP_IVR|Interrupt Vector Register (Vector Number) |DSP
$FFFFA204.B|RW|DSP_TR0|Transfer Highest Byte (DSP56003 32bit) |DSP32
$FFFFA204 to $FFFFA207 DSP Transfer Registers $FFFFA204 Transfer byte, highest (DSP56003 32 bit only) $FFFFA205 Transfer byte, high $FFFFA206 Transfer byte, middle $FFFFA207 Transfer byte, low The DSP56001 fitted to the Falcon is a 24 bit part, so only the low three bytes are used. $FFFFA204 exists for the 32 bit DSP56003, which the Falcon does not have. Reading or writing $FFFFA207 is what actually triggers the transfer; the other bytes are staged first. Falcon only.
$FFFFA205.B|RW|DSP_TR1|Transfer Hi |DSP $FFFFA206.B|RW|DSP_TR2|Transfer Mi |DSP $FFFFA207.B|RW|DSP_TR3|Transfer Lo |DSP ===========#==#=======#===============================================#===== ----------------------|MFP 68901 - Multi Function Peripheral |----- ===========#==#=======#===============================================#=====
$FFFFFA01.B|RW|MFP_PDR|Parallel Port Data Register %SRFKBRDC |
$FFFFFA01 MFP_PDR General Purpose I/O Port Bit 7 Monochrome monitor detect Bit 6 RS-232 ring indicator Bit 5 FDC / HDC interrupt Bit 4 Keyboard / MIDI interrupt Bit 3 Blitter done Bit 2 RS-232 clear to send Bit 1 RS-232 carrier detect Bit 0 Centronics busy All eight are inputs on a standard ST, set by the data direction register at $FFFFFA05. Bit 5 is the one to poll for floppy and hard disk completion: read the byte, mask with $20, and a result of ZERO means the controller has interrupted. This is what TOS itself does. Bit 7 is how machines before the Falcon detect a monochrome monitor. The Falcon uses $FFFF8006 instead. From the Atari Compendium.
$FFFFFA03.B|RW|MFP_AER|Active Edge Register %SRFKBRDC | | | | Interrupt on 0:High-Low,1:Low-High |||||||| |!F | | | Interrupt on 0:Low-High,1:High-Low |||||||| |F
$FFFFFA03 MFP_AER Active Edge Register One bit per GPIO pin, same order as $FFFFFA01: Bit 7 Monochrome monitor detect Bit 6 RS-232 ring indicator Bit 5 FDC / HDC interrupt Bit 4 Keyboard / MIDI interrupt Bit 3 Blitter done Bit 2 RS-232 clear to send Bit 1 RS-232 carrier detect Bit 0 Centronics busy Selects which edge on that pin causes an interrupt: On the ST and STE: 0 = high to low, 1 = low to high On the Falcon: 0 = low to high, 1 = high to low The polarity is inverted on the Falcon, which is why the wiki summary carries two lines for this register with !F and F tags. Note: on a Falcon the MFP is not actually used for serial communications, so the RS-232 bits are not meaningful there. From the Atari Compendium.
$FFFFFA05.B|RW|MFP_DIR|Data-direction %SRFKBRDC | | | | I/O-7 Mono Detect/Sound--------------+||||||| | | | | I/O-6 RS232 Ring Indicator------------+|||||| | | | | I/O-5 FDC/HDC--------------------------+||||| | | | | I/O-4 IKBD/MIDI-------------------------+|||| | | | | I/O-3 Blitter Done-----------------------+||| | | | | I/O-2 RS232 CTS---------------------------+|| | | | | I/O-1 RS232 DCD----------------------------+| | | | | I/O-0 Centronics Busy-----------------------+ |
$FFFFFA05 MFP_DIR Data Direction Register One bit per GPIO pin, same order as $FFFFFA01. Each bit is individually programmed: 0 = input, 1 = output. On a standard ST all eight pins are inputs, so this register reads as zero. Changing it without knowing what is wired to the pin can drive a line that something else is also driving. From the Atari Compendium.
$FFFFFA07.B|RW|MFP_IEA|Interrupt Enable A %76AbebeB |
$FFFFFA07 MFP_IEA Interrupt Enable Register A Bit 7 Monochrome monitor detect Bit 6 RS-232 ring indicator Bit 5 Timer A (STE and TT sound) Bit 4 Receive buffer full Bit 3 Receive error Bit 2 Transmit buffer empty Bit 1 Transmit error Bit 0 Timer B Setting a bit enables that interrupt source. The same bit layout applies to all four register A pairs: $FFFFFA07 Interrupt Enable A $FFFFFA0B Interrupt Pending A $FFFFFA0F Interrupt In-Service A $FFFFFA13 Interrupt Mask A Enable decides whether the source can interrupt at all; mask decides whether an enabled and pending interrupt is passed to the processor. Pending is set by the hardware and cleared by writing a ZERO to that bit, not a one. On a Falcon the MFP is not used for serial communications. From the Atari Compendium.
$FFFFFA09.B|RW|MFP_IEB|Interrupt Enable B %54CD3210 |
$FFFFFA09 MFP_IEB Interrupt Enable Register B Bit 7 FDC / HDC Bit 6 Keyboard / MIDI Bit 5 Timer C (200 Hz system clock) Bit 4 Timer D (USART baud rate) Bit 3 Blitter done Bit 2 RS-232 clear to send Bit 1 RS-232 carrier detect Bit 0 Centronics busy The same bit layout applies to all four register B pairs: $FFFFFA09 Interrupt Enable B $FFFFFA0D Interrupt Pending B $FFFFFA11 Interrupt In-Service B $FFFFFA15 Interrupt Mask B Timer C at bit 5 is the one driving the 200 Hz system clock counter at $000004BA and the VBL queue. Disabling it stops large parts of TOS working. From the Atari Compendium.
$FFFFFA0B.B|RW|MFP_IPA|Interrupt Pending A %76AbebeB | $FFFFFA0D.B|RW|MFP_IPB|Interrupt Pending B %54CD3210 | $FFFFFA0F.B|RW|MFP_ISA|Interrupt In-Service A %76AbebeB | $FFFFFA11.B|RW|MFP_ISB|Interrupt In-Service B %54CD3210 | $FFFFFA13.B|RW|MFP_IMA|Interrupt Mask A %76AbebeB | | | | I/O 7 Mono Detect/Sound--------------+||||||| | | | | I/O 6 RS232 Ring----------------------+|||||| | | | | Timer A--------------------------------+||||| | | | | Receive Buffer full---------------------+|||| | | | | Receive Error----------------------------+||| | | | | Transmit Buffer empty---------------------+|| | | | | Transmit Error-----------------------------+| | | | | Timer B-------------------------------------+ | $FFFFFA15.B|RW|MFP_IMB|Interrupt Mask B %54CD3210 | | | | I/O 5 FDC/HDC------------------------+||||||| | | | | I/O 4 IKBD/MIDI-----------------------+|||||| | | | | Timer C--------------------------------+||||| | | | | Timer D---------------------------------+|||| | | | | I/O 3 Blitter Done-----------------------+||| | | | | I/O 2 RS232 CTS---------------------------+|| | | | | I/O 1 RS232 DCD----------------------------+| | | | | I/O 0 Centronics Busy-----------------------+ |
$FFFFFA17.B|RW|MFP_VCR|Vector Register %xxxxI___ |0100 | | | End of Interrupt 0:software, 1:auto------+ |1000 | | | VCR should contain------------------%0100?000 |*
$FFFFFA17 MFP_VCR Vector Register Bits 7-4 Interrupt vector base, upper nibble Bit 3 End of interrupt mode: 1 = software end of interrupt 0 = automatic end of interrupt Bits 2-0 Supplied by the MFP as the interrupt number On the Atari the base is set to $40, so MFP interrupts use vectors $40 to $4F, which are addresses $00000100 to $0000013C in the exception vector table. In software end of interrupt mode the handler must clear the corresponding bit in the in-service register itself, otherwise no further interrupt of that or lower priority is delivered. The wiki summary notes the register should contain %0100?000. From the Atari Compendium.
$FFFFFA19.B|RW|MFP_TAC|Timer A Control %____EAAA |
$FFFFFA19 and $FFFFFA1B Timer A and Timer B Control Bits 3-0 (Timer A) and bits 3-0 (Timer B): 0000 Timer stop 0001 Delay mode, divide by 4 0010 Delay mode, divide by 10 0011 Delay mode, divide by 16 0100 Delay mode, divide by 50 0101 Delay mode, divide by 64 0110 Delay mode, divide by 100 0111 Delay mode, divide by 200 1000 Event count mode 1xxx Pulse extension mode, divider as above The MFP clock is 2.4576 MHz. With a divide by 10 prescale the timer ticks at 245.76 kHz, a period of about 4.069 microseconds, which is the usual choice for measuring short intervals. Timer A is normally free on an STF and is the usual pick for user timing. On an STE and TT it is used for DMA sound, so save and restore the control register there. Event count mode counts pulses on a GPIO pin rather than the internal clock, which is how the Timer B display-line counting trick works. From the Atari Compendium.
$FFFFFA1B.B|RW|MFP_TBC|Timer B Control %____EBBB | | | | Event Count Mode-------------------------1000 | | | | Pulse Extension--------------------------1xxx | | | | Delay------------------------------------0xxx |
$FFFFFA1D.B|RW|MFP_TDC|Timer C+D Control %_CCC_DDD | | | | Timer C Control-----------------------+++ ||| | | | | Timer D Control---------------------------+++ | | | | Stop Timer--------------------------------000 | | | | Delay,Clockdivide 4 3200Hz--------------001 | | | | Delay,Clockdivide 10 1280Hz--------------010 | | | | Delay,Clockdivide 16 800Hz--------------011 | | | | Delay,Clockdivide 50 256Hz--------------100 | | | | Delay,Clockdivide 64 200Hz--------------101 | | | | Delay,Clockdivide 100 128Hz--------------110 | | | | Delay,Clockdivide 200 64Hz--------------111 |
$FFFFFA1D MFP_TDC Timer C and D Control Bits 6-4 Timer C control Bits 2-0 Timer D control Bits 7 and 3 unused Both fields use the same encoding: 000 Timer stop 001 Delay mode, divide by 4 010 Delay mode, divide by 10 011 Delay mode, divide by 16 100 Delay mode, divide by 50 101 Delay mode, divide by 64 110 Delay mode, divide by 100 111 Delay mode, divide by 200 Timers C and D have no event count or pulse extension mode, which is why they take three bits rather than four. Timer C drives the 200 Hz system clock. Timer D is the USART baud rate generator. Neither should be stopped by application code. From the Atari Compendium.
$FFFFFA1F.B|RW|MFP_TAD|Timer A Data |
$FFFFFA1F to $FFFFFA25 Timer Data Registers $FFFFFA1F Timer A data $FFFFFA21 Timer B data $FFFFFA23 Timer C data $FFFFFA25 Timer D data Writing loads the timer's reload value. Reading returns the current count, which decrements from the reload value toward zero at the rate set by the prescale in the control register. When the count reaches zero the timer raises its interrupt and reloads automatically. A written value of 0 means 256. Reading a running timer is how short intervals are measured: note the value, do the work, read again and subtract. From the Atari Compendium.
$FFFFFA21.B|RW|MFP_TBD|Timer B Data | $FFFFFA23.B|RW|MFP_TCD|Timer C Data | $FFFFFA25.B|RW|MFP_TDD|Timer D Data |
$FFFFFA27.B|RW|MFP_SYC|Synchronous Character |
$FFFFFA27 MFP_SYC Synchronous Character Register Holds the character the USART searches for when running in synchronous mode, selected by the stop bit field in the USART control register at $FFFFFA29 being set to 00. Not used on a standard Atari, which runs the RS-232 port asynchronously.
$FFFFFA29.B|RW|MFP_UCR|Usart Control %DBBSSPE_ | | | | Divider 0:div1(sync),1:div16---------+|||||| | | | | Databits 00:8,01:7,10:6,11:5----------++|||| | | | | 00:sync,01:1stop,10:1.5stop,11:2stop----++|| | | | | Parity 0:off,1:on-------------------------+| | | | | Parity 0:odd,1:even------------------------+ |
$FFFFFA29 MFP_UCR USART Control Register Bit 7 Clock divide: if set, divide by 16 Bits 6-5 Data bits: 00 = 8 bits 01 = 7 bits 10 = 6 bits 11 = 5 bits Bits 4-3 Start and stop bits: 00 = synchronous 01 = 1 start, 1 stop 10 = 1 start, 1.5 stop 11 = 1 start, 2 stop Bit 2 Parity enable: if clear, parity is ignored Bit 1 Parity: 1 = even, 0 = odd Bit 0 unused Note the wiki summary line labels bits 4-3 as stop bits only; the Compendium describes them as the combined start and stop configuration. From the Atari Compendium.
$FFFFFA2B.B|RW|MFP_RES|Receiver Status %BOPFSCPR | | | | Buffer full--------------------------+||||||| | | | | Overrun Error-------------------------+|||||| | | | | Parity Error---------------------------+||||| | | | | Frame Error-----------------------------+|||| | | | | SCR found/Break--------------------------+||| | | | | SCR received/Startbit detected------------+|| | | | | Synchronous Strip Enable-------------------+| | | | | Receiver Enable-----------------------------+ |
$FFFFFA2B MFP_RES Receiver Status Register Bit 7 Buffer full Bit 6 Overrun error Bit 5 Parity error Bit 4 Frame error Bit 3 Search / break detected Bit 2 Match / character in progress Bit 1 Synchronous strip enable Bit 0 Receiver enable Bit 0 must be set before anything is received. Bits 7-4 are status and are cleared by reading the data register. From the Atari Compendium.
$FFFFFA2D.B|RW|MFP_TRS|Transmitter Status %BUAEBHLT | | | | Buffer Empty-------------------------+||||||| | | | | Underrun Error (char sent)------------+|||||| | | | | Auto Turnaround------------------------+||||| | | | | EOT End of Transmission-----------------+|||| | | | | Break------------------------------------+||| | | | | 00:High,01:Low,10:High,11:loopback,High---++| | | | | Transmitter Enable--------------------------+ |
$FFFFFA2D MFP_TRS Transmitter Status Register Bit 7 Buffer empty Bit 6 Underrun error Bit 5 Auto turnaround Bit 4 End of transmission Bit 3 Break Bit 2 High bit Bit 1 Low bit Bit 0 Transmitter enable Bits 2-1 together set the idle state of the transmit line: 00 = high, 01 = low, 10 = high, 11 = loopback, high Bit 0 must be set before anything is sent. Wait for bit 7 to be set before writing the next byte to $FFFFFA2F. From the Atari Compendium.
$FFFFFA2F.B|RW|MFP_UAD|Usart Data | ===========#==#=======#===============================================#===== ----------------------|FPC - Floating Point Coprocessor |----- ===========#==#=======#===============================================#===== $FFFFFA40.W|RW|FPC_STA|Status Register |ME $FFFFFA42.W|RW|FPC_CTL|Control Register |ME $FFFFFA44.W|RW|FPC_SAV|Save Register |ME $FFFFFA46.W|RW|FPC_RES|Restore Register |ME $FFFFFA48.W|RW|FPC_OPW|Operation Word Register |ME $FFFFFA4A.W|RW|FPC_CMD|Command Register |ME $FFFFFA4C.W|RW| - |Reserved |ME $FFFFFA4E.W|RW|FPC_CCR|Condition Code Register |ME $FFFFFA50.L|RW|FPC_OPR|Operand Register |ME $FFFFFA54.W|RW|FPC_SEL|Register Select |ME $FFFFFA56.W|RW| - |Reserved |ME $FFFFFA58.L|RW|FPC_IAR|Instruction Address Register |ME $FFFFFA5C.L|RW|FPC_OAR|Operand Address Register |ME ===========#==#=======#===============================================#===== ----------------------|MFP 68901 number 2 |----- ===========#==#=======#===============================================#===== $FFFFFA81.B|RW|MF2_PDR|Parallel Port Data Register |TT ...........| | |........................... |TT $FFFFFAAF.B|RW|MF2_UAD|USART Data Register |TT ===========#==#=======#===============================================#===== ----------------------|ACIA 6850 (Midi/Keyboard) |----- ===========#==#=======#===============================================#=====
$FFFFFC00.B|R-|KBD_CTL|IKBD Status %IPOFCDTR |
$FFFFFC00 KBD_CTL IKBD ACIA Status (read) / Control (write) READ - status: Bit 7 Interrupt request Bit 6 Parity error Bit 5 Receiver overrun Bit 4 Frame error Bit 3 Clear to send Bit 2 Data carrier detect Bit 1 Transmit data register full Bit 0 Receive data register full WRITE - control: Bit 7 Enable receive interrupts Bits 6-5 Transmitter interrupt configuration: 00 RTS low, interrupts disabled 01 RTS low, interrupts enabled 10 RTS high, interrupts disabled 11 RTS low, interrupts disabled, send break Bits 4-2 Word format, data bits - parity - stop bits: 000 7-E-2 001 7-O-2 010 7-E-1 011 7-O-1 100 8-N-2 101 8-N-1 110 8-E-1 111 8-O-1 Bits 1-0 Clock divide: 00 divide by 1 (500000 cps) 01 divide by 16 (31250 cps, MIDI standard) 10 divide by 64 (7812.5 cps, IKBD) 11 master reset The IKBD is set to $96: 7 bits, no parity, 1 stop, divide by 64, RTS low, receive interrupts on. The MIDI ACIA at $FFFFFC04 uses the same register layout and is set to $95, the same but divide by 16. From the Atari Compendium.
" |-W|KBD_CTL|IKBD Control %ITTBSPDD | | | | 7N1,7812.5,RTS low,Rec on,Send off= %10010110 |* $FFFFFC02.B|RW|KBD_DAT|IKBD Data | $FFFFFC04.B|R-|MID_CTL|MIDI Status %IPOFCDTR | | | | Interrupt Request--------------------+||||||| | | | | Parity Error--------------------------+|||||| | | | | Receiver Overrun-----------------------+||||| | | | | Frame Error-----------------------------+|||| | | | | CTS Clear to Send------------------------+||| | | | | DCD Data Carrier Detect-------------------+|| | | | | Transmitter Data Register full-------------+| | | | | Receiver Data Register full-----------------+ | " |-W|MID_CTL|MIDI Control %ITTBSPDD | | | | 7N1,31250,RTS low,Rec on,Send off = %10010101 |* | | | Interrupt 0:off,1:on-----------------+||||||| | | | | RTS low, TransmitIRQ off--------------00||||| | | | | RTS low, TransmitIRQ on---------------01||||| | | | | RTS high,TransmitIRQ off--------------10||||| | | | | RTS low, TransmitIRQ off,send break---11||||| | | | | 8 Databits,2 Stopbits,Parity even-------000|| | | | | 8 Databits,2 Stopbits,Parity odd--------001|| | | | | 8 Databits,1 Stopbits,Parity even-------010|| | | | | 8 Databits,1 Stopbits,Parity odd--------011|| | | | | 7 Databits,2 Stopbits,Parity off--------100|| | | | | 7 Databits,1 Stopbits,Parity off--------101|| | | | | 7 Databits,1 Stopbits,Parity even-------110|| | | | | 7 Databits,1 Stopbits,Parity odd--------111|| | | | | Clockdivide 1 - 500000.0cps---------------00 | | | | Clockdivide 16 - 31250.0cps (MIDI Std)----01 | | | | Clockdivide 64 - 7812.5cps (IKBD!)-------10 | | | | Master Reset-------------------------------11 | $FFFFFC06.B|RW|MID_DAT|MIDI Data | ===========#==#=======#===============================================#===== ----------------------|RP5C15 Real Time Clock |----- ===========#==#=======#===============================================#=====
$FFFFFC21.B|RW| - |Seconds mod 10 %____xxxx |MST
$FFFFFC21 to $FFFFFC39 RP5C15 Clock Registers, Bank 0 and Bank 1 IMPORTANT: this chip has TWO banks of registers at the same addresses. Bit 0 of the mode register at $FFFFFC3B selects which bank is visible. The wiki listing documents only Bank 0. Address Bank 0 Bank 1 $FFFFFC21 Seconds ones (0-9) Clock output frequency $FFFFFC23 Seconds tens (0-5) Reset seconds (see below) $FFFFFC25 Minutes ones (0-9) Alarm minutes ones $FFFFFC27 Minutes tens (0-5) Alarm minutes tens $FFFFFC29 Hours ones (0-9) Alarm hours ones $FFFFFC2B Hours tens (0-2) Alarm hours tens $FFFFFC2D Day of week (0-6) Alarm day of week $FFFFFC2F Date ones (0-9) Alarm date ones $FFFFFC31 Date tens (0-3) Alarm date tens $FFFFFC33 Month ones (0-9) not used $FFFFFC35 Month tens (0-1) 12/24 hour select $FFFFFC37 Year ones (0-9) Leap year register (0-3) $FFFFFC39 Year tens (0-9) not used All values are BCD digits, one digit per register, low nibble only. Bank 0 notes: Day of week: 0 = Sunday. Hours tens in 12 hour mode is 0-1, with bit 1 set for PM. Year is stored as (year - 1980). Bank 1 notes: $FFFFFC21 clock output frequency: 0 = open collector CLKOUT 4 = 16 Hz 1 = 16384 Hz 5 = 1 Hz 2 = 1024 Hz 6 = 1/60 Hz 3 = 128 Hz 7 = open collector CLKOUT $FFFFFC23: setting bit 0 resets the seconds register to zero, and if seconds were between 30 and 59 it also increments the minutes register. This is the "round to nearest minute" function. $FFFFFC35: bit 1 set = 24 hour mode, clear = 12 hour mode. $FFFFFC37 leap year register: 0 = this is a leap year. Mega ST only. From the Atari Compendium.
$FFFFFC23.B|RW| - |Seconds div 10 %____xxxx |MST $FFFFFC25.B|RW| - |Minutes mod 10 %____xxxx |MST $FFFFFC27.B|RW| - |Minutes div 10 %____xxxx |MST $FFFFFC29.B|RW| - |Hours mod 10 %____xxxx |MST $FFFFFC2B.B|RW| - |Hours div 10 %____xxxx |MST $FFFFFC2D.B|RW| - |Weekday %____xxxx |MST $FFFFFC2F.B|RW| - |Day mod 10 %____xxxx |MST $FFFFFC31.B|RW| - |Day div 10 %____xxxx |MST $FFFFFC33.B|RW| - |Month mod 10 %____xxxx |MST $FFFFFC35.B|RW| - |Month div 10 %____xxxx |MST $FFFFFC37.B|RW| - |Year mod 10 %____xxxx |MST $FFFFFC39.B|RW| - |Year div 10 %____xxxx |MST
$FFFFFC3B.B|RW| - |Clock mode %____xxxx |MST
$FFFFFC3B Mode Register Bit 3 Timer enable: 0 = clock stopped Bit 2 Alarm enable: 0 = alarm off Bits 1-0 Bank select Bit 0 is the one that matters: it chooses whether the register block at $FFFFFC21 to $FFFFFC39 shows Bank 0 (the clock) or Bank 1 (the alarm and configuration). See $FFFFFC21. Stopping the clock with bit 3 is how a consistent multi register read is done, since the counters would otherwise roll over mid read. Mega ST only. From the Atari Compendium.
$FFFFFC3D.B|RW| - |Clock test %____xxxx |MST
$FFFFFC3D Test Register Lower nibble must read as zero for the chip to be considered working correctly. Used for factory test. Mega ST only. From the Atari Compendium.
$FFFFFC3F.B|RW| - |Clock reset %____xxxx |MST
$FFFFFC3F Reset Register Bit 3 1 Hz alarm pulse: 0 = enabled Bit 2 16 Hz alarm pulse: 0 = enabled Bit 1 Alarm reset: 1 = reset the alarm registers Bit 0 Clock reset: 1 = reset the clock registers Writing the reset bits clears the corresponding register bank to zero. Mega ST only. From the Atari Compendium.
===========#==#=======#===============================================#===== ----------------------|Add-on and expansion area |----- ===========#==#=======#===============================================#=====
$FFFFFE00.W|RW| - |Add-on control / MonSTer register |*
$FFFFFE00 and $FFFFFE0E Add-on control Not present on stock Atari hardware. Known to be used by: SEC BOOSTER. CONFLICT: EmuTOS uses this same address block for the MonSTer expansion board. From EmuTOS source: bios/machine.h MONSTER_REG $FFFFFE00 bios/clock.c MONSTER_I2C_DIR $FFFFFE02 bios/clock.c MONSTER_I2C_SCL $FFFFFE04 bios/clock.c MONSTER_I2C_SDA $FFFFFE06 MonSTer's main register is at exactly the same address as the first SEC BOOSTER control register, and its I2C bus lines occupy $FFFFFE02 to $FFFFFE06 immediately above. EmuTOS only touches these when built with CONF_WITH_MONSTER enabled, which is off by default. A stock EmuTOS build will not write here. A MonSTer-enabled build will. Anyone fitting both boards, or running a MonSTer-enabled EmuTOS alongside a SEC BOOSTER, should expect trouble. EmuTOS also carries CONF_WITH_MAGNUM and CONF_WITH_NOVA for two further add-on boards; their address usage has not yet been checked against this listing. Extended bit information is not currently available for the SEC BOOSTER side of these registers.
$FFFFFE0E.W|RW| - |Add-on control |* ===========#==#=======#===============================================#===== $FFFFFF82.W|RW| - |No label or description recorded | | | | CHECK: this entry has never carried a | | | | description. Purpose unknown. Either identify | | | | it or remove it. | ===========#==#=======#===============================================#=====
$FFFF820D.B|RW|VDL_VBL|Video Base Lo %xxxxxxx_ |STE,F ----+---- | +- ---+--- ------------------+---------------------------- --+-- | | | | | | | | | | | Computer Type---------------+ | | | | +---Description | | | +--------------------------Label | | +--------------------------------Read/Write Access | +----------------------------------Type (Byte,Word,Long) +----------------------------------------Address (extended to 32 Bit) Computer Type: * |Software defined Standard !xxx|all except xxx 0x0 |MC680x0 only 0x0+|MC680x0 or higher BLT |Standard on TT,STE,ME,F (Blitter) SCC |Standard on TT,ME,F VME |Standard on TT,ME ST |Atari ST (260/520/1040) STE |Atari STE (520/1040) TT |Atari TT MST |Atari Mega ST (1/2) ME |Atari Mega STE F |Atari Falcon Read/Write Access: R/-|Read only (read register) -/W|Write only (write register) R/?|Read access allowed ?/W|Write access allowed r/?|Read access allowed but not sensible ?/w|Write access allowed but not sensible Source precedence when documents disagree: 1. Live TOS source (th-otto/tos1x, th-otto/tos3x) and EmuTOS source. Executable and hardware-validated; TOS is Atari's own code. 2. The Atari Compendium. Broad and careful, but not perfect. 3. Everything else, including this wiki's own history and the Dan Hollis hardware register listing. Entries marked UNVERIFIED rest on a single source only.





Back to Memory Map for Atari ST,STE,TT and Falcon