Mapamiga
Mapamiga
Mapamiga
A comprehensive
guide to the inner world of the Amiga. Covers libraries and hardware
registers. Examples in C, Assembly Language, and Modula 2.
Preface
There are so many programming books for the Amiga. Why should there be
another one?
Frankly, we wrote this book for ourselves. When we sit down to program,
we find that no single book is enough. The typical Amiga programmer may
have Commodore's official reference manuals, several Sybex, Abacus, and
COMPUTE! books, the complete set of Amiga Transactor magazines, and even
several printouts of downloaded programming information and source code, all
scattered across desks, chairs, and, of course, the floor. As you know, program-
ming the Amiga is a tough job. You might spend an hour just tracking down
the right source. What is the solution to this problem?
We turned for inspiration to two books that helped us in the past: Mapping
the Atari by Ian Chadwick (1983, COMPUTE! Books) and Mapping the Commo-
dore 64 by Sheldon Leemon (1984, COMPUTE! Books). These books had it
all-explanations of how the respective machines organized memory, detailed
listings of what various memory locations were and how to use them, descrip-
tions of input/output registers, and discussions of the functions of various
ROM routines.
These books were so detailed a programmer could literally write a program
without putting fingerprints on a single other book.
But of course you can't really do the same thing for the Amiga. The above-
mentioned books were slightly over 200 pages. This book is more than twice as
large and comes nowhere near to saying everything that can be said about the
Amiga. If the Apple II's built-in software and hardware is an apartment, and the
Commodore 64's is a townhouse, then the Amiga's is a Manhattan city block.
And the problem is not just a matter of scale. Unlike earlier computers, the
Amiga doesn't set aside areas of memory for this or that purpose. Instead, the
Amiga has libraries of routines, which can show up virtually anywhere in the
RAM space of the machine. These routines aren't even all in ROM; some are
loaded from disk. The screen is not in a fixed location. Commodore even
threatens that the locations of the memory-mapped custom chips may change
at any time. The Amiga doesn't go through all these contortions to be contrary.
Instead, this level of indirection provides the Amiga with prodigious flexibility.
Libraries and devices are easily upgraded and added. Peripherals and input de-
vices are easily accommodated.
You might also be able to find us on your favorite online service, such as
CompuServe, PLink, or GEnie. Ask your friendly local sysop.
As Bill Wilkinson said in the introduction to Mapping the Atari, good luck
and happy mapping.
Notes from BSI: It took about eight hours to scan and fix the majority of
the typos caused by the scanner (HP ScanJet+) reading bold text incorrect-
ly. For that reason, I have not scanned the "Structures" part of the book.
You can use you include files for DevPac2 instead. (Or with Lattice, or
with...) However, I have included the "hardware" part since I manually
typed that up when I first got my Amiga so I could learn where all the
hardware registers are. Enjoy the text. Any questions can be left to me
(Bansai) on Motherboard East 1.5 at 1(215)792-0167. Slates!
-------------------------
Library Functions
The Amiga is an incredibly capable machine. It has so much to offer, from digi-
tized sounds and dazzling color graphics to a window-based user interface and
a true multitasking operating system. Library functions are the key to accessing
these features.
The Amiga's library functions are similar to the Commodore 64's ROM
Kernal subroutines, the IBM PC's BIOS interrupt calls, and the Apple Macin-
tosh's Toolbox procedures-they are a collection of routines that allow you to
control almost every aspect of your computer. They're called functions because
the majority of them were written in the C programming language. In C, all
user-defined commands are referred to as functions.
Linked Libraries
There are really two types of libraries on the Amiga: linked libraries and shared
libraries. (Note: Amiga Basic and Modula-2 do not use linked libraries.)
Linked libraries are a collection of external functions that you make part of
your program. When you link your program with Alink or Blink, each linked li-
brary function you use is brought in from one of the specified .lib files and
stuffed into your program. The Lattice C file lc.lib and the Manx C file c.lib are
both examples of linked libraries.
The functions offered by a linked library are dependent upon your compil-
er or assembler. However, one linked library is common-amiga.lib. The
amiga.lib library offers common functions such as printf( ), atoi( ), and
BeginIO( ). Only amiga.lib is documented in this chapter. Language-specific
linked libraries are explained in the manual that came with your compiler or
assembler.
Using an amiga.lib function in C is incredibly easy: Simply call the func-
tion by name and then link your program with amiga.lib. For Lattice C users,
linking with amiga.lib is automatic when you use the compiler's -L option.
Other compilers simply have you provide the amiga.lib filename as one of the
library parameters in the Alink or Blink command sequence.
Accessing amiga.lib from machine language is a bit tougher. First you must
declare that function with an XREF statement, preceding the function name with
an underline character (xref _CreateExtIO, for example). Second, you must
push the function arguments onto the stack, not place them into registers. To
actually call the function you simply JSR to the function name, as in JSR
_CreateExtIO. Finally, you must remove the function arguments from the
stack- the function does not do this for you. A simple addq.l #8,sp would suf-
fice for CreateExtIO( ) since this function accepts two long words (eight bytes)
worth of arguments.
All of the amiga.lib functions are described in the function tables found at
the end of this chapter. Here's the entry for amiga.lib's printf( ) function:
-------------------------
printf
Description: prints a formatted string to the standard output (Lattice
and Manx
users: if you link with lc.lib or c.lib, this is not the function
you're
calling)
Library: amiga.lib (linked library)
Modula-2 Module: none
Syntax: printf(string, values...)
C: void printf(char *, long...)
Machine Language: move.l #value,-(sp) ;may have several values
pea string
jsr _printf
add.l #8,sp ;(2 arguments * 4 bytes = 8)
Modula-2: not available
Arguments:string = pointer to string containing optional C formatting com-
mands (%); if you're passing longword values on the stack (as
shown above), be sure to follow the percent symbol with a lower-
case L
values = values or addresses of strings to print; this routine
knows how many values are on the stack by checking the number
of formatting commands in the string argument
Result: none
-------------------------
The Machine Language entry in this table illustrates how you might call
the printf( ) function from machine language. Specifically, it shows the order in
which you must push the function's arguments onto the stack. In all cases, the
arguments are pushed onto the stack in the order opposite to that shown in the
Syntax entry (right to left instead of left to right).
In these crude machine language examples, all pointer arguments are
placed onto the stack using a PEA instruction. In actual use, the argument's ad-
dress may be contained in a register or a memory location, in which case you
would MOVE it onto the stack. The examples shown here use PEA simply so
you understand that the function expects an address and not an actual value. If
the argument is supposed to be a value, we place it onto the stack via a MOVE
instruction.
* Machine language example for using the printf( ) linked library function
* -Be sure to link with amiga.lib
SECTION code,CODE
* Call printf( ) to print the addition result in decimal and in hex format
move.l d0,-(sp) ;Push result onto stack for hex output
move.l d0,-(sp) ;Push result onto stack for decimal output
move.l Num2,-(sp) ;Push Num2 value on stack
move.l Num1,-(sp) ;Push Num1 value on stack
pea formatString ;Push address of formatString onto stack
jsr printf ;Call printf( )
add.l #20,sp ;Remove arguments from stack-
;(5 arguments * 4 bytes = 20 bytes)
* Exit program
Abort2:
clr.l d0 ;Set return code
rts ;Drop out of program
SECTION data,DATA
Num1:
SysBase:
dc.l 0 ;Location to hold ExecBase pointer
DOSBase:
dc.l 0 ;Location to hold DOSBase pointer
stdout:
dc.l 0 ;Location to hold output handle
DOSName:
dc.b 'dos.library',0 ;Name of dos library
END
-------------------------
Shared Libraries
When someone refers to an Amiga library, they're usually talking about a
shared library. The same is true of this book.
As the name implies, a shared library is accessible to all Amiga programs.
When you use a shared library function, its code does not become part of your
program on disk; shared libraries are located in ROM (writable control memory
on the Amiga 1000) or loaded into RAM from the libs directory of your Work-
bench disk.
Shared libraries are more memory conservative than linked libraries. Every
program that accesses a function from a linked library must contain its own
copy of that function. Only one copy of a shared library function ever needs to
be in memory because all programs have access to it.
At this writing, there are 15 libraries available with Kickstart/Workbench
1.3, each one covering a different aspect of the Amiga. For graphics program-
ming, you use the graphics.library; for creating windows, requesters, and pull-
down menus, you use the intuition.library; for disk access, you use the
dos.library.
The clist.library has been removed from Kickstart 1.2 and 1.3, but it is
available with Kickstart 1.1 and is documented here for the sake of complete-
ness. Two special libraries-romboot.library and version.library-are not cov-
ered in this chapter since the functions they contain are private to the Amiga's
system software and cannot be called by the user.
-------------------------
Opening and Closing Libraries
A library must be opened before you can access its functions. Like your local
Seven-Eleven store, the Exec library is always open. This works out rather well
considering OpenLibrary( ), the one function required to open other libraries, is
contained in Exec. When you link with startup code such as Lattice's c.o, the
DOS library is opened for you as well. If you program with M2Sprint, you'll
find that several libraries are automatically opened for you.
You open a library using the aptly named OpenLibrary( ) function.
OpenLibrary( ) expects two arguments: the library name and the library version
number. (See Table 1-2 for a complete list of available libraries.) The sample
code below shows the C, machine language, and Modula-2 syntax for using the
OpenLibrary( ) function.
In C:
libBase = OpenLibrary(libraryName,version);
In machine language:
move.l ExecBase,a6 ;Pointer to ExecBase
lea libraryName,a1 ;Pointer to the library's name goes in a1
moveq #version,d0 ;Version number goes in d0
jsr OpenLibrary(a6) ;Open library and return libBase in d0
move.l d0,libBase ;Save library base pointer
In Modula-2:
libBase := OpenLibrary(libraryName,version);
where libBase is the name of the library's base pointer, libraryName is the
name of the library, and version is the lowest acceptable version of the library
you require. In most cases, you should use a version number of 0 or 33. The
following table explains all the possible version numbers you can use:
If you specify a version that is higher than what is available on the Amiga
you run your program, OpenLibrary( ) will fail and return a NULL value. If the
library is opened successfully, the base address of the library is returned in
libBase.
Table 1-2 shows the library base pointer names (libBase) and their corre-
sponding library names (libraryName) that you should use when opening a li-
brary. In machine language, you can use practically any name you choose, as
long as you define an area in memory to store the pointer and label that loca-
tion using the name you select. By convention, it's recommended you use the
library base pointer name provided in Table 1-2 and precede it with an under-
line character, as in the name _DOSBase. In Lattice C, you must use the names
given below. If you don't, your program will compile and link correctly, and
then happily guru when it is run.
When your program is finished, you must be sure to close all of the librar-
ies you opened. To accomplish this you use yet another aptly named Exec
function, CloseLibrary( ). The only argument that the CloseLibrary( ) function
requires is the base address of the library you wish to close. This is the same
base address that was returned by OpenLibrary( ). Here are some examples on
using CloseLibrary( ):
In machine language:
move.l libBase,a1 ;libBase goes in register a1
move.l ExecBase,a6 ;Pointer to ExecBase goes in a6
jsr CloseLibrary(a6) ;Close the library
If you neglect to close a library, you run the risk of wasting memory since
the system will not know if it can throw out an unused, RAM-based library.
-------------------------
Calling Functions
The end of this chapter contains an alphabetical listing of every user-accessible
Amiga library function. Each table entry gives the function's name; a brief de-
scription of that function; the library in which the function is contained; its
negative offset from the library base (useful to the "take charge" machine lan-
guage programmer); the Modula-2 module in which it is contained; its syntax;
its C, machine language, and Modula-2 usage; a description of its arguments
(sometimes referred to as parameters); and a description of the value (if any)
that is returned by the function. For example, here's the entry for Intuition's
OpenWindow( ) function:
OpenWindow
Description: opens an Intuition window
Library: intuition.library
Offset: -$00CC (-204)
Modula-2 Module: Intuition
Syntax: window = OpenWindow(newWindow)
C: struct Window *OpenWindow(struct NewWindow *)
Machine Language: d0 = OpenWindow(a0)
Modula-2: OpenWindow(VAR newWindow: NewWindow): WindowPtr
Arguments: newWindow = NewWindow structure that describes window to
open
Result: window = pointer to Window structure; NULL if
unsuccessful
The Syntax section gives you a general idea of what the function expects
and what it returns. If you look at the C description, you can see that
OpenWindow( ) expects a pointer to a NewWindow structure and returns a
pointer to a Window structure. The Machine Language description shows that
the Window pointer should be placed in a0 and the pointer to the opened Win-
dow is returned in d0 (all functions that return values return them in d0). For
Modula-2, you can see you must pass the function a NewWindow structure
and the value it returns is of type WindowPtr. The following C, machine lan-
guage, and Modula-2 programs are examples of how you can use this infor-
mation to open a window. Five library functions are used in these program:
OpenLibrary( ), OpenWindow( ), Wait( ), CloseWindow( ), and CloseLibrary( ).
-------------------------
Program 1-2. C Window
void main()
/* Open intuition.library */
if ((IntuitionBase=(struct IntuitionBase *)
OpenLibrary("intuition.library",0))==NULL)
exit(0);
/* Open window */
if ((MyWindow=(struct Window *)OpenWindow(&MyNewWindow))==NULL) (
CloseLibrary(IntuitionBase);
exit(0);
SECTION code,CODE
*Open intuition.library
movea.l #IntuitionName,a1 ;Library name in a1
move.l #0,d0 ;Version number in d0
movea.l ExecBase,a6 ;Pointer to ExecBase in a6
jsr OpenLibrary(a6) ;Call OpenLibrary( )
move.l d0, IntuitionBase ;Save intuition.library base
beq.s Abort2 ;Exit program if OpenLibrary fails
*Open a window
movea.l #MyNewWindow,a0 ;Pointer to NewWindow in a0
move.l IntuitionBase,a6 ;Pointer to IntuitionBase in a6
jsr OpenWindow(a6) ;Call OpenWindow( )
move.l d0,MyWindow ;Save pointer to newly opened window
beq.s Abort1 ;Exit program in OpenWindow fails
*Close intuition.library
Abort1:
move.l IntuitionBase,a1 ;Pointer to IntuitionBase in a1
movea.l ExecBase,a6 ;Pointer to ExecBase in a6
jsr CloseLibrary(a6) ;Call CloseLibrary( )
SECTION data,DATA
*NewWindow structure
MyNewWindow:
dc.w 0,12
dc.w 200,100
dc.b -1,-1
dc.l CLOSEWINDOW
dc.l WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG|WINDOWSIZING|ACTIVATE
dc.l 0
dc.l 0
dc.l WindowTitle
dc.l 0
dc.l 0
dc.w 80,24
dc.w -1,-1
dc.w WBENCHSCREEN
IntuitionName:
dc.b 'intuition.library',0 ;Library name
WindowTitle:
dc.b 'Close Me',0 ;Text to appear in window's drag bar
SECTION mem,BSS
_IntuitionBase:
ds.l l ;Place to store IntuitionBase
MyWindow
ds.l l ;Place to store Window pointer
END
-------------------------
Program 1-4. Modula-2 Window
MODULE SharedLibExample;
(* Modula-2 code that opens a window and waits for you to close it *)
VAR
newWindow: NewWindow;
myWindowPtr: WindowPtr;
dummy: ADDRESS;
BEGIN
WITH newWindow DO
LeftEdge := 0; TopEdge := 12;
Width := 200; Height := 100;
DetailPen := BYTE(0); BlockPen := BYTE(l);
Title := ADR("Close Me");
Flags := WindowFlagSet{Activate,WindowClose,WindowDepth,
WindowDrag,WindowSizing};
IDCMPFlags := IDCMPFlagSet{CloseWindowFlag};
Type := WBenchScreen;
FirstGadget := NIL;
CheckMark := NIL;
Screen := NIL;
BitMap := NIL;
MinWidth := 80; MinHeight := 24;
MaxWidth := -1; MaxHeight
END;
myWindowPtr := OpenWindow(ADR(newWindow));
The MOVE instruction puts the base address of the Intuition library in reg-
ister a6. The label OpenWindow contains the offset of OpenWindow( ) function
from the base address of Intuition. The JSR instruction combines the base ad-
dress with the offset to produce an actual destination address. By putting the
base address in a6, we also tell OpenWindow( ) where its current library base is.
To tell you the truth, our machine language program is breaking a few
rules because it hard codes the library offsets in the beginning of the program
using EQU directives. Purists obtain their function offsets using XREF state-
ments. If we were to program this "by the book," the above lines would read
xref _LVOOpenLibrary
Result: none
-------------------------
FlushCList
Description: clears a character list
Library: clist.library
Offset: -$0030 (-48)
Modula-2 Module: none
Syntax: FlushCList(cList)
C: void FlushCList(long)
Machine Language: FlushCList(a0)
Modula-2: not available
Arguments: cList = CList header-as returned by AllocCList( )
or StrToCL( )-used to manage character list to clear
Result: none
-------------------------
Forbid
Description: prevents task rescheduling
Library: exec.library
Offset: -$0084 (-132)
Modula-2 Module: Interrupts
Syntax: Forbid( )
C: void Forbid(void)
Machine Language: Forbid( )
Modula-2: Forbid( )
Arguments: none
Result: none
-------------------------
fpa
Description: converts a fast floating point number into an ASCII string
Library: amiga.lib (linked library)
Modula-2 Module: none
Syntax: exp = fpa(fnum, string)
C: long fpa(float, char *)
Machine Language: pea string
move.l fnum,-(sp)
jsr _fpa ;exp returned in d0 and string equals fnum
addq.l #8,sp
Modula-2: not available
Arguments: fnum = floating point number to convert
string = address of string to receive ASCII equivalent of fnum
argument
Result: exp = integer exponent of fnum
-------------------------
fpbcd
Description: converts a fast floating point number into BCD format
Library: amiga.lib (linked library)
Modula-2 Module: none
Syntax: fpbcd(fnum, string)
C: void fpbcd(float, char *)
Machine Language: pea string
move.l fnum,-(sp)
jsr _fpbcd ;BCD equivalent of fnum returned in string
addq.l #8,sp
Modula-2: not available
Arguments: fnum = floating point number to convert
string = address of five-byte string to receive BCD equivalent of
fnum argument
Result: string argument receives the BCD equivalent of fnum
argument
-------------------------
FreeBoardMem
Description: frees expansion board memory (opposite of AllocBoardMem( )
Library: expansion.library
Offset: -$004E (-78)
Modula-2 Module: Expansion
Syntax: FreeBoardMem(startSlot, slotSpec)
C: void FreeBoardMem(long, long)
Machine Language: d0 = FreeBoardMem(d0, d1)
Modula-2: FreeBoardMem(startslot, slotSpeC: INTEGER)
Arguments: startSlot = slot number as returned by AllocBoardMem( )
slotSpec = number of slots to free
Result: none
-------------------------
Modula-2: FreeMem(memoryBlock: ADDRESS: byteSize: LONGCARD)
Arguments: memoryBlock = pointer to memory block to free
byteSize = size of block in bytes
Result: none
-------------------------
FreeCList
Description: releases character list descriptor and any resources it
uses
Library: clist.library
Offset: -$002A (-42)
Modula-2 Module: none
Syntax: FreeCList(cList)
C: void FreeCList(long)
Machine Language: FreeCList(a0)
Modula-2: not available
Arguments: cList = descriptor of character list to free
Result: none
-------------------------
FreeColorMap
Description: returns memory used by a ColorMap structure
Library: graphics.library
Offset: -$0240 (-576)
Modula-2 Module: Views
Syntax: FreeColorMap(colorMap)
C: void FreeColorMap(struct ColorMap *)
Machine Language: FreeColorMap(a0)
Modula-2: FreeColorMap(colorMap: ColorMapPtr)
Arguments: colorMap = ColorMap structure to free
Result: none
-------------------------
FreeConfigDev
Description: frees a ConfigDev structure
Library: expansion.library
Offset: -$0054 (-84)
Modula-2 Module: ConfigVars
Syntax: FreeConfigDev(configDev)
C: void FreeConfigDev(struct ConfigDev *)
Machine Language: FreeConfigDev(a0)
Modula-2: FreeConfigDev(configDev: ConfigDevPtr)
Arguments: configDev = ConfigDev structure as returned by
AllocConfigDev( )
Result: none
-------------------------
FreeCopList
Description: returns memory allocated for an intermediate copper list
Library: graphics.library
Offset: -$0222 (-546)
Modula-2 Module: Copper
Syntax: FreeCopList(copList)
C: void FreeCopList(struct CopList *)
Machine Language: FreeCopList(a0)
Modula-2: FreeCopList(copList: CopListPtr)
Arguments: copList = CopList structure to free
Result: none
-------------------------
FreeCprList
Description: returns memory allocated for a hardware copper list
Library: graphics.library
Offset: -$0234 (-564)
Modula-2 Module: Copper
Syntax: FreeCprList(cprlist)
C: void FreeCprList(struct cprlist *)
Machine Language: FreeCprList(a0)
Modula-2: FreeCprList(cprlist: cprlistPtr)
Arguments: cprlist = cprlist structure to free
Result: none
-------------------------
FreeDiskObject
Description: frees memory allocated for a Workbench disk object
Library: icon.library
Offset: -$005A (-90)
Modula-2 Module: Icon
Syntax: FreeDiskObject(diskObj)
C: void FreeDiskObject(struct DiskObject *)
Machine Language: FreeDiskObject(a0)
Modula-2: FreeDiskObject(diskObj: DiskObjectPtr)
Arguments: diskObj = DiskObject structure to free
Result: none
-------------------------
FreeEntry
Description: frees many regions of memory
Library: exec.library
Offset: -$00E4 (-228)
Modula-2 Module: Memory
Syntax: FreeEntry(memList)
C: void FreeEntry(struct MemList *)
Machine Language: FreeEntry(a0)
Modula-2: FreeEntry(memList: MemListPtr)
Arguments: memList = MemList structure
Result: none
-------------------------
FreeExpansionMem
Description: frees expansion memory
Library: expansion.library
Offset: -$005A (-90)
Modula-2 Module: Expansion
Syntax: FreeExpansionMem(startSlot, numSlots)
C: void FreeExpansionMem(long, long)
Machine Language: FreeExpansionMem(d0, d1)
Modula-2: FreeExpansionMem(startSlot, numSlots: INTEGER)
Arguments: startSlot = slot number as returned by AllocExpansionMem( )
slotSpec = number of slots to free
Result: none
-------------------------
FreeFreeList
Description: frees all memory in a free list
Library: icon.library
Offset: -$0036 (-54)
Modula-2 Module: Icon
Syntax: FreeFreeList(freeList)
C: void FreeFreeList(struct FreeList *)
Machine Language: FreeFreeList(a0)
Modula-2: FreeFreeList(freeList: FreeListPtr)
Arguments: memList = FreeList structure
Result: none
-------------------------
FreeGBuffers
Description: frees memory allocated by GetGBuffers( )
Library: graphics.library
Offset: -$0258 (-600)
Modula-2 Module: Gels
Syntax: FreeGBuffers(animOb, rastPort, dBuffer)
C: void FreeGBuffers(struct AnimOb *, struct RastPort *, long)
Machine Language: FreeGBuffers(a0, a1, d0)
Modula-2: FreeGBuffers(animOb: AnimObPtr; rastPort: RastPortPtr; dBuffer:
BOOLEAN)
Arguments: animOb = AnimOb structure
rastPort = Rastport structure
dBuffer = double-buffer flag-TRUE for double-buffering
Result: none
-------------------------
FreeMem
Description: frees memory allocated by GetGBuffers( )
Library: exec.library
Offset: -$00D2 (-210)
Modula-2 Module: Memory
Syntax: FreeMem(memoryBlock, byteSize)
C: void FreeMem(void *, long)
Machine Language: FreeMem(a1, d0)
Modula-2: FreeMem(memoryBlock: ADDRESS: byteSize: LONGCARD)
Arguments: memoryBlock = pointer to memory block to free
byteSize = size of block in bytes
Result: none
-------------------------
FreeRaster
Description: frees memory allocated by AllocRaster( )
Library: graphics.library
Offset: -$01F2 (-498)
Modula-2 Module: Rasters
Syntax: FreeRaster(p, width, height)
C: void FreeRaster(PLANEPTR, long, long)
Machine Language: FreeRaster(a0, d0, d1)
Modula-2: FreeRaster(p: PlanePtr; width, height: CARDINAL)
Arguments: p = memory block returned by AllocRaster( )
width = width of bitplanes in pixels
height = height of bitplanes in pixels
Result: none
-------------------------
FreeRemember
Description: frees memory allocated by AllocRemember( )
Library: intuition.library
Offset: -$0198 (-408)
Modula-2 Module: Intuition
Syntax: FreeRemember(rememberKey, reallyForget)
C: void FreeRemember(struct Remember *, long)
Machine Language: FreeRemember(a0, d0)
Modula-2: FreeRemember(rememberKey: RememberPrt; reallyForget:
BOOLEAN)
Arguments: rememberKey = address of pointer to Remember structure
reallyForget = TRUE to free memory and link nodes; FALSE to
free only link nodes
Result: none
-------------------------
FreeSignal
Description: frees a signal bit
Library: exec.library
Offset: -$0150 (-336)
Modula-2 Module: Tasks
Syntax: FreeSignal(signalNum)
C: void FreeSignal(long)
Machine Language: FreeSignal(d0)
Modula-2: FreeSignal(signalNum: SIGNAL)
Arguments: signalNum = signal number to free (0-31)
Result: none
-------------------------
FreeSprite
Description: makes sprite available for others to use
Library: graphics.library
Offset: -$019E (-414)
Modula-2 Module: Sprites
Syntax: FreeSprite(pick)
C: void FreeSprite(long)
Machine Language: FreeSprite(d0)
Modula-2: FreeSprite(pick: INTEGER)
Arguments: pick = number of sprite to free (0-7)
Result: none
-------------------------
FreeSysRequest
Description: frees memory allocated by BuildSysRequest( )
Library: intuition.library
Offset: -$0174 (-372)
Modula-2 Module: Intuition
Syntax: FreeSysRequest(window)
C: void FreeSysRequest(struct Window *)
Machine Language: FreeSysRequest(a0)
Modula-2: FreeSysRequest(window: WindowPtr)
Arguments: window = Window structure as returned by BuildSysRequest( )
Result: none
-------------------------
FreeTrap
Description: frees a processor trap
Library: exec.library
Offset: -$015C (-348)
Modula-2 Module: Tasks
Syntax: FreeTrap(trapNum)
C: void FreeTrap(long)
Machine Language: FreeTrap(d0)
Modula-2: FreeTrap(trapNum: TRAP)
Arguments: trapNum = trap number to free (0-15)
Result: none
-------------------------
FreeVPortCoplists
Description: frees all intermediate copper lists and their headers from
a
ViewPort
Library: graphics.library
Offset: -$021C (-540)
Modula-2 Module: Views
Syntax: FreeVPortCopLists(viewPort)
C: void FreeVPortCopLists(struct ViewPort *)
Machine Language: FreeVPortCopLists(a0)
Modula-2: FreeVPortCopLists(viewPort: ViewPortPtr)
Arguments: viewPort = ViewPort structure containing copper lists
Result: none
-------------------------
FreeWBObject
Description: frees memory allocated for a Workbench object
Library: icon.library
Offset: -$003C (-60)
Modula-2 Module: none
Syntax: FreeWBObject(object)
C: void FreeWBObject(struct WBObject *)
Machine Language: FreeWBObject(a0)
Modula-2: not available
Arguments: object = WBObject structure to free
Result: none
--------------------------
GetCC
Description: gets 68000/68010 condition codes
Library: exec.library
Offset: -$0210 (-528)
Modula-2 Module: Exec
Syntax: condition = GetCC( )
C: long GetCC(void)
Machine Language: d0 = GetCC( )
Modula-2: GetCC( ): BITSET
Arguments: none
Result: condition = 68000/68010 condition code
-------------------------
GetCLBuf
Description: converts character list into contiguous data
Library: clist.library
Offset: -$0072 (-114)
Modula-2 Module: none
Syntax: length = GetCLBuf(cList, buffer, maxLength)
C: long GetCLBuf(long, char *, long)
Machine Language: d0 = GetCLBuf(a0, a1, d1)
Modula-2: not available
Arguments: cList = character list descriptor, as returned by AllocCList( )
or
StrToCL( )
buffer = buffer to hold data
maxLength = maximum size of buffer in bytes
Result: length = number of bytes copied into buffer
-------------------------
GetCLChar
Description: gets a byte from the beginning of a character list
Library: clist.library
Offset: -$0042 (-66)
Modula-2 Module: none
Syntax: byte = GetCLChar(cList)
C: long GetCLChar(long)
Machine Language: d0 = GetCLChar(a0)
Modula-2: not available
Arguments: cList = character list descriptor, as returned by AllocCList( )
or
StrToCL( )
Result: byte = byte from beginning of character list; -1 if no data
-------------------------
GetCLWord
Description: gets a word from the beginning of a character list
Library: clist.library
Offset: -$005A (-90)
Modula-2 Module: none
Syntax: word = GetCLWord(cList)
C: long GetCLWord(long)
Machine Language: d0 = GetCLWord(a0)
Modula-2: not available
Arguments: cList = character list descriptor, as returned by AllocCList( )
or
StrToCL( )
Result: word = word from beginning of character list; -1 if no data
-------------------------
GetColorMap
Description: allocates and initializes a ColorMap structure
Library: graphics.library
Offset: -$023A (-570)
Modula-2 Module: Views
Syntax: colorMap = GetColorMap(entries)
C: struct ColorMap *GetColorMap(long)
Machine Language: d0 = GetColorMap(d0)
Modula-2: GetColorMap(colorMap: LONGINT): ColorMapPtr
Arguments: entries = number of entries for this color map
Result: colorMap = pointer to ColorMap structure; O if unsuccessful
-------------------------
GetCurrentBinding
Description: sets static board configuration area
Library: expansion.library
Offset: -$008A (-138)
Modula-2 Module: none
Syntax: actual = GetCurrentBinding(currentBinding, size)
C: long GetCurrentBinding(long, long)
Machine Language: d0 = GetCurrentBinding(a0, d0)
Modula-2: not available
Arguments: currentBinding = CurrentBinding structure
size = size of user's BindDriver structure
Result: actual = actual size of the CurrentBinding structure
-------------------------
GetDefPrefs
Description: gets a copy of the default Preferences
Library: intuition.library
Offset: -$007E (-126)
Modula-2 Module: Preferences
Syntax: prefBuffer = GetDefPrefs(prefBuffer, size)
C: struct Preferences *GetDefPrefs(struct Preferences *, long)
Machine Language: d0 = GetDefPrefs(a0, d0)
Modula-2: GetDefPrefs(prefBuffer: ADDRESS; size: INTEGER): ADDRESS
Arguments: prefBuffer = buffer to receive copy of default Preferences
size = size of buffer in bytes
Result: prefBuffer = pointer to your buffer
-------------------------
GetDiskObject
Description: reads a Workbench DiskObject (.info file) from disk
Library: icon.library
Offset: -$004E (-78)
Modula-2 Module: Icon
Syntax: diskObj = GetDiskObject(name)
C: struct DiskObject *GetDiskObject(char *)
Machine Language: d0 = GetDiskObject(a0)
Modula-2: GetDiskObject(name: STRPTR): DiskObjectPtr
Arguments: name = name of Workbench object (.info file)
Result: diskObj = pointer to DiskObject structure; 0 if
unsuccessful
-------------------------
GetGBuffers
Description: attempts to allocate all buffers of an enter AnimOb
Library: graphics.library
Offset: -$00A8 (-168)
Modula-2 Module: Gels
Syntax: success = GetGBuffers(animOb, rastPort, dBuffer)
C: long GetGBuffers(struct AnimOb *, struct RastPort *, long)
Machine Language: d0 = GetGBuffers(a0, a1, d0)
Modula-2: GetGBuffers(animOb: AnimObPtr; rastPort: RastPortPtr; dBuffer:
BOOLEAN): BOOLEAN
Arguments: animOb = AnimOb structure
rastPort = Rastport structure
dBuffer = double-buffer flag-TRUE for double-buffering
Result: success = TRUE if successful; FALSE if unsuccessful
-------------------------
GetIcon
Description: reads a DiskObject structure from disk
Library: icon.library
Offset: -$002A (-42)
Modula-2 Module: none
Syntax: status = GetIcon(name, icon, free)
C: long GetIcon(char *, struct DiskObject *, struct FreeList *)
Machine Language: d0 = GetIcon(a0, a1, a2)
Modula-2: not available
Arguments: name = name of icon (.info file)
icon = DiskObject structure
free = FreeList structure
Result: status = nonzero if successful
-------------------------
GetMsg
Description: gets next message from a message port
Library: exec.library
Offset: -$0174 (-372)
Modula-2 Module: Ports
Syntax: message = GetMsg(port)
C: struct Message *GetMsg(struct MsgPort *)
Machine Language: d0 = GetMsg(a0)
Modula-2: GetMsg(port: MsgPortPtr): ADDRESS
Arguments: port = receiving message port
Result: message = pointer to first message; NULL if no message
-------------------------
GetPrefs
Description: gets Preferences' current settings
Library: intuition.library
Offset: -$0084 (-132)
Modula-2 Module: Preferences
Syntax: prefBuffer = GetDefPrefs(prefBuffer, size)
C: struct Preferences *GetDefPrefs(struct Preferences *, long)
Machine Language: d0 = GetDefPrefs(a0, d0)
Modula-2: GetDefPrefs(prefBuffer: ADDRESS; size: INTEGER): ADDRESS
Arguments: prefBuffer = buffer to receive copy of Preferences
size = size of buffer in bytes
Result: prefBuffer = pointer to your buffer
-------------------------
GetRGB4
Description: gets the value of an entry in a ColorMap structure
Library: graphics.library
Offset: -$0246 (-582)
Modula-2 Module: Views
Syntax: value = GetRGB4(colorMap, entry)
C: long GetRGB4(struct ColorMap *, long)
Machine Language: d0 = GetRGB4(a0, d0)
Modula-2: GetRGB4(colorMap: ColorMapPtr; entry: LONGINT): INTEGER
Arguments: colorMap = ColorMap structure
entry = index into color table, specifying desired entry
Result: value = two-byte, right-justified RGB value with four bits
per
color-red, green, blue; -1 if no valid entry
-------------------------
GetSereenData
Description: copies all or part of a Screen structure into buffer; opens
specifled
screen if not already open
Library: intuition.library
Offset: -$01AA (-426)
Modula-2 Module: Intuition
Syntax: success = GetScreenData(buffer, size, type, screen)
C: long GetScreenData(char *, long, long, struct Screen *)
Machine Language: d0 = GetScreenData(a0, d0, d1, a1)
Modula-2: GetScreenData(buffer: ADDRESS; size: CARDINAL; type:
ScreenFlagSet; screen: ScreenPtr): BOOLEAN
Arguments: buffer = buffer in which data will be placed
size = size of buffer in bytes
type = screen type-CUSTOMSCREEN, WORKBENCHSCREEN
screen = custom Screen structure; ignored if type argument
equals WORKBENCHSCREEN
Now that you realize how the bit operations work, here are the custon chip
register addresses and explanations:
----------------------------------------------------------------------------
$DFF000 BLTDDAT Blitter Destination Data (early read dummy address)
Status: DMA Only Agnus
Just before a word of data is moved into RAM by the
blitter, it's stored here. This register cannot be
accessed by the 68K or the copper. It's used
exclusively by the blitter DMA. Writing to it does
nothing. Reading returns a seemingly random number
----------------------------------------------------------------------------
$DFF002 DMACONR DMA Enable Read
Status: *R Agnus/Paula
0 AUD0EN 1 = Audio channel 0 DMA enabled
1 AUD1EN
2 AUD2EN
3 AUD3EN
4 DSKEN 1 = Disk DMA enabled
5 SPREN 1 = Sprite DMA enabled
6 BLTEN 1 = Blitter DMA enabled
7 COPEN 1 = Copper DMA enabled
8 BPLEN 1 = Bit-plane DMA enabled
9 DMAEN 0 = DMA for all channels disabled
10 BLTPRI 1 = Blitter has full priority over 68K
0 = Blitter has partial priority
11 UNUSED
12 UNUSED
13 BZERO 1 = If the last blitter operation output
zeroes only. No bits were set in
destination RAM.
14 BBUSY 1 = Blitter is busy ("blitting") See note
15 SETCLR UNUSED
Note: Because of timing problems with 68020/68030 processors, you must wait
a short while before testing BBUSY. A "btst #14,DMACONR" before the test
will provide the appropriate delay. (i.e.: BTST twice)
----------------------------------------------------------------------------
$DFF004 VPOSR Vertical Beam Position Read
Status: *R Agnus
0 V8 The high bit of the vertical beam position
(1 = pos > 255)
1-14 UNUSED
15 LOF Interlace Long Frame Flag (1 = a long frame
is being drawn (even), 0 = a short frame
(odd))
----------------------------------------------------------------------------
$DFF006 VHPOSR Vertical/Horizontal Beam Position Read
Status: *R Agnus
0-7 H1-H8 Video beam's horizontal position in
increments of two lo-res pixels
8-15 V0-V7 Low 8 bits of video beam's horizontal pos
Note: If bit 3 in register BPLCON0 ($DFF100) is set, the Amiga returns the
light pen position and NOT the raster position! Also, the location and size
of the visible screen area changes accordingly with the DIWSTRT and DIWSTOP
(Display Window Start/Stop @ $DFF08E / $DFF090). These registers are
changed by Preferences each time you adjust the display-centering gadget.
Normal Visible Screen area is - horizontal : $40 - $E0
vertical : $2C - $F4
----------------------------------------------------------------------------
$DFF008 DSKDATR Disk Data Read (early read dummy address -Disk DMA)
SEE $DFF000 (BLTDDAT) for explanation.
----------------------------------------------------------------------------
$DFF00A JOY0DAT Joystick/Mouse Port 0 Data
$DFF00C JOY1DAT Port 1 Data
Status: *R Denise
For Mouse Use:
0-7 Horizontal Position Counter
8-15 Vertical Position Counter
For Joystick Use:
0 EOR BIT 1 Down (1 = stick down)
1 Right(1 = stick right)
8 EOR BIT 9 Up (1 = stick up)
9 Left (1 = stick left)
For Paddle Use:
1 Right paddle fire button (1 = fire)
9 Left paddle fire button (1 = fire)
----------------------------------------------------------------------------
$DFF00E CLXDAT Collision Data
Status: *R Denise
if set to one... 0 Even bit plane collided with odd bit plane
1 Odd plane collided with sprite 0 or 1
2 with sprite 2 or 3
3 4 or 5
4 6 or 7
5 Even plane collide with sprite 0 or 1
6 2 or 3
7 4 or 5
8 6 or 7
9 Sprite 0 or 1 collide with 2 or 3
10 0 or 1 4 or 5
11 0 or 1 6 or 7
12 2 or 3 4 or 5
13 2 or 3 6 or 7
14 4 or 5 6 or 7
15 UNUSED
Note: When you read this register, all bits are cleared, so be sure to save
it if you need it's contents if you want to check for more than one type of
collision. Bitplane collisions are extremely flexible. See CLXCON
($DFF098) for more info.D
----------------------------------------------------------------------------
$DFF010 ADKCONR Audio/Disk Control Read
Status: *R Paula
0 ATVOL0 1 = Audio channel 0 modulates channel 1 volume
1 ATVOL1 1 = 1 2
2 ATVOL2 1 = 2 3
3 ATVOL3 1 = Output of audio channel 3 disabled
4 ATPER0 1 = Audio channel 0 modulates channel 1 period
5 ATPER1 1 = 1 2
6 ATPER2 1 = 2 3
7 ATPER3 1 = Output of audio channel 3 disabled
8 FAST 1 = MFM:2 us per bit disk operation (normDOS)
0 = GCR:4 us per bit disk op (double density)
9 MSBSYNC 1 = GCR-format synchronization for disk
operations enabled (not used by DOS)
10 WORDSYNC 1 = Disk Controller is synchronizing on
the data word found in the DSKSYNC
register ($DFF07E) typically set to
$4489 for MFM.
11 UARTBRK 1 = RS232 break-signal is occuring on the
serial TxD line.
12 MFMPREC 1 = MFM selected
0 = GCR selected
13-14 PRECOMP Disk precompensation time (00=none,
01=140 nsec, 10=280 nsec, 11=560 nsec)
15 SETCLR UNUSED
Note: ADKCONR is a read version of ADKCON ($DFF09E). See that register for
a complete explanation of each bit.
----------------------------------------------------------------------------
$DFF012 POT0DAT Pot (Paddle/Proportional Joystick) Port 0/1 Data Read
$DFF014 POT1DAT
Status: *R Paula
For Paddle Use:
0-7 Left Paddle Counter (0 = completely CCW)
8-15 Right Paddle Counter(0 = completely CCW)
For Proportional Joystick Use:
0-7 Horizontal Counter (0 = stick pushed left)
8-15 Vertical Counter (0 = stick pushed down)
----------------------------------------------------------------------------
$DFF016 POTGOR Pot Port Data Read
Status: *R Paula
0 START Trigger bit for starting pot counters
(always reads zero)
1-7 UNUSED Reserved for Chip ID
8 DATLX Current state of pin 9 on game port 1 (0/1)
9 OUTLX Output enable for pin 9 on game port 1 (zero)
10 DATLY Current state of pin 5 on game port 1 (0/1)
11 OUTLY Output enable for pin 5 on game port 1 (zero)
12 DTARX Current state of pin 9 on game port 0 (0/1)
13 OUTRX Output enable for pin 9 on game port 0 (zero)
14 DATRY Current state of pin 5 on game port 0 (0/1)
15 OUTRY Output enable for pin 5 on game port 0 (zero)
Notes: This is the read address for the POTGO register ($DFF034). Most of
the bits in this register are write-only and always return a zero when read.
Only bits 8, 10, 12, and 14 return valid data. The remaining bits are
controlled via the POTGO register. (See for more info on these bits)
The Amiga's game ports are quite versatile. Pins 5 and 9 of either port
can be programmed to receive and send digital data. This register allows
you to read the current high-low state of these pins.
Simply read the desired pin's DATxx bit to determine its status. (0 =
0v, 1 = +5v) The positive voltage sent to these pins should never exceed 5
volts or 400 mA. ONLY THE VOLTAGE FROM PIN 7 SHOULD BE CONNECTED TO PIN 5
OR 9. PIN 7 CARRIES +5 VOLTS FROM THE AMIGA'S OWN POWER SUPPLY.
The right mouse button is wired to game port pins 8 and 9. When the
button is pressed, these two pins connect. Pin 8 is grounded, so any
voltage that 9 carries gets shorted to ground.
To sense whether the right mouse button is being pressed on a mouse
plugged into game port 0, you must first set pin 9 to output. (i.e.:
OUTLY = 1 or write $0C00 to POTGO. For a mouse plugged into port 1, use
OUTRY and DATRY instead.) Finally, wait about 300 msec for the voltage to
reach the game port - and then read the status of pin 9 via the DATLY bit in
POTGOR. If this bit equals one, the pin is not grounded, thus the button is
not pressed. If it equals zero, the pin is grounded, and the button has
been pressed.
Because Intuition automatically handles game port 0 mouse events, you'll
have to turn off multitasking if you wish to control this port directly via
the hardware. Even accessing port 1 may cause problems since any
manipulation of POTGO affects all of the bits. Such confusion usually
results in the Amiga thinking that the right mouse button is being clicked
when it really isn't.
Rather than calculate a 300 msec delay, you may write a #$C000 to POTGO
and wait for one vertical blanking period with the following:
WaitVertB:
move.l VPOSR,d0
and.l #$0001FF00,d0
bne WaitVertB
rts
----------------------------------------------------------------------------
$DFF018 SERDATR Serial Data Input and Status Read
Status: *R Paula
0-7 DB0-DB7 Byte of data read from serial port
8 DB8/STP Ninth data bit or stop bit
9 STP Stop bit if set up for 9 data bits
10 UNUSED
11 RxD Current status of serial port's RxD line
12 TSRE Transmit shift register empty (if 1)
13 TBE Transmit buffer empty (if 1)
14 RBF Receive buffer is full(if 1)
15 OVRUN Receive buffer overrun (if 1)
----------------------------------------------------------------------------
$DFF01A DSKBYTR Disk Data Byte and Disk Status Read
Status: *R Paula
0-7 DATA Byte of data read from disk
8-11 UNUSED
12 WORDEQUAL Disk Sync pattern found (if 1)
13 DISKWRITE Disk controller writing (if 1)
Disk controller reading (if 0)
14 DMAOEN Disk DMA is active (if 1)
15 BYTEREADY Bits 0-7 of this register will hold new
data if bit 15 is set.
Notes: Considering the fact that disk data can be transferred to and from
memory automatically through DMA, it is neither necessary nor recommended
that you read data one byte at a time via 0-7, and 15.
Bit 12: WORDEQUAL holds a one for only 2 usec! (The time for one MFM bit
to pass under the head.) AmigaDos uses $4489 for the sync.
----------------------------------------------------------------------------
$DFF01C INTENAR Interrupt Enable Read
Status: *R Paula
0 TBE 1 = Serial transmit buffer empty interrupt
enabled (level 1)
1 DSKBLK 1 = Disk block done int enabled (level 1)
2 SOFT 1 = Software interrupts enabled (level 1)
3 PORTS 1 = CIA-A and expansion port interrupts
enabled (level 2)
4 COPER 1 = Copper interrupt enabled (level 3)
5 VERTB 1 = Vertical Blank Int enabled (level 3)
6 BLIT 1 = Blitter ready int enabled (level 4)
7 AUD0 1 = Audio channel 1 int enabled (level 4)
8 AUD1 2
9 AUD2 3
10 AUD3 4
11 DBF 1 = Serial receive buffer full interrupt
enabled (level 5)
12 DSKSYN 1 = Disk sync pattern found int enab (lev 5)
13 EXTER 1 = CIA-B and expansion port int enab(lev 6)
14 INTEN Master interrupt off switch (0 = All
ints listed above disabled)
15 SETCLR UNUSED by INTENAR
Notes: You must write the same value TWICE in a row in order for the value
to take effect. This double write rule was incorporated to safeguard
against accidental disk activity - programs that lose control and start
trashing memory can't just shove a number into this register and initiate
potentially harmful disk activity.
Since the length must be stored in 14 bits, the data cannot be longer
than 32766 bytes. The DMA hardware uses this length value as a counter.
Every time a word of data is transferred to or from disk, this counter is
decremented, and the address in the DSKPT register incremented. Transfer
stops when this value reaches zero.
Because of a bug in the Amiga Hardware, the last three bits of data are
missing. To remedy this, save one more word than necessary.
Before and after doing any disk operations, set this register to #$0000
to enable read mode and disable disk DMA.
Bit 15: Setting this bit initiates disk DMA. It will not start, however,
until the DMAENA bit in the ADKCON register ($DFF09E) is also set. You'll
have to set both of these bits in order to perform any DMA-controlled disk
operations. NEVER start disk DMA unless a previous operation is complete or
you may wind up trashing the data on the disk! To find out when a read or
write operation is complete, use the disk block done interrupt, which can be
detected through the use of the DSKBLK bit (1) in the INTEQR register at
$DFF01E.
----------------------------------------------------------------------------
$DFF026 DSKDAT Disk DMA Write
Status: *W Paula
This is the data buffer used by the disk DMA when
transferring data. It is the write address of the
DSKDATR register ($DFF008).
----------------------------------------------------------------------------
$DFF028 REFPTR Refresh Pointer
Status: *W Agnus
The Amiga uses this register as a RAM refresh address
register. Do not modify the value there or you may
corrupt the contents of RAM! It is for diagnostic
purposes only.
----------------------------------------------------------------------------
$DFF02A VPOSW Vertical Beam Position Write
Status: *W Agnus
This is the write address of the VPOSR register
located at $DFF004. Note the warnings that apply for
the refresh pointer as they also apply.
----------------------------------------------------------------------------
$DFF02C VHPOSW Vertical/Horizontal Beam Position Write
Status: *W Agnus
This is the write address of the VHPOSR register
located at $DFF006. Note the warnings that apply for
the refresh pointer as they also apply.
----------------------------------------------------------------------------
$DFF02E COPCON Coprocessor Control
Status: *W Agnus
0 UNUSED
1 CDANG Copper Danger Bit (1 = Copper can access
blitter registers 0 = Copper cannot.)
2-15 UNUSED
Notes: A one value allows access to $DFF040+, and a zero value $DFF080+.
For instructions on the copper and its instruction set, see locations
$DFF080-$DFF08C.
----------------------------------------------------------------------------
$DFF030 SERDAT Serial Data Output
Status: *W Paula
0-7 DB0-DB7 Byte of data to be output
8 DB8/STP Ninth data bit or stop bit
9 STP Stop Bit if sending nine data bits
10-15 UNUSED (See below)
Notes: To send data out the serial port, simply store it here. Upon
receiving a nonzero value, the contents of the register are shifted out the
serial port - low bit first, high bit last until its contents are empty
(equal zero). Since the start bit is sent automatically, DO NOT include it
as part of your data. Because you must send at least one stop bit, SERDAT
should never equal zero.
By convention, only 8 or 9 data bits should be stored in this register at
any on time. However, because this is a true 16 bit register, up to 15 data
bits and one stop bit can be output in just one shot - an interesting, if
questionably useful feature.
----------------------------------------------------------------------------
$DFF032 SERPER Serial Period (Transfer Rate) and Data Bit Control
Status: *W Paula
0-14 RATE Bit transfer rate specified in increments of
279.4 nsec.
15 LONG Number of data bits to expect when receiving
data (1 = nine 0 = eight data bits)
Notes: The value stored in bits 0-14 determine how many bus cycles occur
between each bit sent or received through the serial port. So, if one bit
is to be sent every X bus cycles, use X-1. Serial transfer rates are
usually specified in baud rates, not bus cycles. Use this formula to
translate the baud rate into the period value this regiester expects:
Period = (3579546 / Baudrate) - 1
The period value for the six most common baud rates are:
Baud Rate Period
--------- ------
300 11931
600 5965
1200 2982
2400 1490
4800 745
9600 372
Bit 15: Affects incoming, not outgoing data length.
----------------------------------------------------------------------------
$DFF034 POTGO Pot Port Data
Status: *W Paula
See POTGOR at $DFF016 for an explanation on how this
write register works.
----------------------------------------------------------------------------
$DFF036 JOYTEST JOY0DAT and JOY1DAT Write
Status: *W Denise
This register allows you to set the contents of the
JOY0DAT and JOY1DAT registers at $DFF00A / $DFF00C.
The value stored here affects both registers,
allowing you to reset the mouse position counters for
both ports with just one instruction.
----------------------------------------------------------------------------
$DFF038 STREQU Short Frame Vertical Blank Strobe
$DFF03A STRVBL Normal Vertical Blank Strobe
$DFF03C STRHOR Horizontal Sync Strobe
$DFF03E STRLONG Long Raster Strobe
Status: Strobe Denise (Denise/Paula on STRHOR)
Do not read to or write from any of these registers.
Doing so would falsely trigger the strobe and confuse
the Amiga.
----------------------------------------------------------------------------
Location Range: $DFF040-$DFF074 The Blitter Registers
The blitter takes care of almost all of the Amiga's bitmapped graphics
manipulation, from drawing lines to moving objects and filling outlined
areas. Intuition, for example, uses the blitter for such things as drawing
gadgets and printing text. And one of the best things about the blitter is
that it executes independently, allowing the Amiga to animate objects while
the uP is hard at work executing program instructions.
Copy Mode: The blitter's main task is to copy data from one area of
memory to another. This operation is specified as a blit. The blitter was
specifically designed to copy bitmap data, however, you can use the blitter
to copy whatever type of data you choose.
Data to be copied may come from up to three different locations in
memory, but you can have only one destination address. The blitter refers
to the source addresses as A, B, and C. The destination area is called D.
When using more than one source address, the blitter must combine the
data from the different sources before it can be written back out. To do
this, it performs any combination of eight different logic operations called
miniterms. Miniterms allow you to combine the bits from A, B, and C in 256
different ways before they reach their destination. This provides the
programmer with great flexibility when copying bitmapped images. Shapes can
be inverted, merged, "cookie cut", and so on. Bits 0-7 in the BLTCON0
register at $DFF040 control the miniterm settings.
The most common use for the blitter is to move rectangular areas of a
bitmapped screen. Because of the way screen bitmaps are laid out, it would
be impractical if all you could do was to copy consecutive bytes in memory.
Instead, you must be able to skip several bytes between each horizontal
screen line. That way, you don't have to copy objects that take up the
entire width of the screen.
The BLTAMOD-BLTDMOD registers ($DFF060-$DFF066) allow you to specify the
difference between the width of the object being copied and the width of the
bitmap. The BLTSIZE register at $DFF058 defines width and height of the
source and destination area. Together these registers allow the blitter to
copy any rectangular area of a bitmap.
The memory addresses of A, B, and C go in registers BLTAPT, BLTBPT, and
BLTCPT ($DFF050, $DFF04C, and $DFF048) respectively, and the D address goes
in register BLTDPT ($DFF054). When specifying A, B, C, or D, you must
provide the blitter with an even, word aligned address.
Because bitmapped objects don't always begin on a word aligned address,
and their width isn't always an even multiple of 16 (16 bits = 1 word), the
blitter can mask out certain bits in the first and last word of each
horizontal line copied from source A. This way, you can copy an area that
starts at any pixel location and is of any pixel width you desire. The
first word mask for source A goes in register BLTAFWM ($DFF044). The last
word mask goes in register BLTALWM ($DFF046). In effect, the first word of
each line is ANDed with BLTAFWM and the last word of each line is ANDed with
BLTALWM before they are written to destination RAM.
To move bitmapped images horizontally with pixel accuracy, it is
necessary to shift the image's data one bit at a time. Using bits 12-15 in
the BLTCON0 and BLTCON1 registers ($DFF040 and $DFF042), you can tell the
blitter to shift source A and/or source B data right 0-15 bits before it's
transferred to it's destination. The shifting takes place within the
blitter so it does not affect the area of memory actually being copied.
Shifting is not restricted by word boundaries; a word's low bit is
shifted into the high bit of the following word. If there is no previous
word of data being copied (i.e. if the current word is the very first word
of data being copied), zeroes are shifted into the word's high bits.
What happens when you need to shift something left, say a pixel? Well,
simply shift it right (16-x) times. The only difference is that your data
is one word further to the right. Optionaly, you could also run the blitter
in descending mode. In this mode, data is shifted left by the value stored
in bits 12-15 of the BLTCON0 and BLTCON1 registers. Here's another reason
for operating the blitter in descending mode:
The blitter is usually called upon to move objects around the screen.
Generally, a programmer will do this by copying an object's data from a
special buffer area in memory to the screen's bitmap. (Since the blitter
can only copy to one destination area at a time, you'll have to do a blitter
operation for each bit plane.) Next, a copy of the screen's background is
copied to the screen to erase the object. Finally, the object is copied to
a different location on the screen, thus making in move.
In the previous example, data was copied from two separate areas of
memory. Sometimes it's desirable to copy to and from areas that overlap.
However, this may cause problems because the blitter may copy a piece of
data into a memory location that hasn't been read yet, thus destroying it.
(i.e. If the destination and source overlap, and the destination is higher
in memory, bye-bye data!)
To avoid the problem of overlapping data, the blitter can be run in two
modes: ascending and descending. When should you use descendong mode?
Well, if the end of the source overlaps the start of the destination, use
descending mode. If the start of the source overlaps the end of the
destination, use ascending mode. If the source and destination don't
overlap, it doesn't matter what you use. The DESC bit (1) in the BLTCON1
register at $DFF042 determines the blitter's current mode.
To initiate a blitter copy operation, you should first select the blitter
copy mode by NOT setting the LINE bit (0) in the BLTCON1 register at
$DFF042. Second, tell the computer the address of your source data using
the BLTAPT, BLTBPT, BLTCPT, and the destination data at BLTDPT. (These
addresses should specify the starting or ending addresses of the data
depending on whether the blitter is running in ascending or descending mode,
respectively.) Third, use BLTCON0 to select the desired miniterms and tell
the computer which sources you're using (A, B, and/or C) and enable the
blitter's D destination channel. (If you don't enable D, data isn't going
anywhere!) Fourth, set up any other options you want such as shifting or
masking of data. Finally, write the width and height of the area to be
copied into the BLTSIZE register at $DFF058. Writing to BLTSIZE
automatically starts the blitter, so it SHOULD BE THE VERY LAST THING YOU
SET! During the blitter operation, the BBUSY bit (14) in the DMACONR
register is set equal to one. When the blitter is finished, this bit is
cleared.
The following happens during a blitter copy operation: Data is copied one
word at a time from the memory address specified by the BLTxPT registers to
the address found in BLTDPT. Every time a word is copied, the BLTxPT
registers are incremented (or decremented if in descending mode). When the
number of words to b copied matches the width in the BLTSIZE register, the
modulation value found in the BLTxMOD registers is added to the BLTxPT
registers and the copying continues on the next line. When the number of
lines copied equals the height in BLTSIZE, the operation is complete and the
blitter stops.
Fill Mode: The blitter offers a crude area-fill option that works in
tandem with the data-copy operation described above. Fill mode is activated
by BLTCON1's IFE (Inclusive Fill Enable) bit or EFE (Exclusive Fill Enable)
bit prior to turning on the blitter. After the blitter reads data from
memory and manipulates it according to the miniterm settings, the specified
fill operation is performed on the data before it is written to destination
memory. Fill operations work IN DESCENDING MODE ONLY! The figure below
illustrates the effect of each type of fill operation has on data:
After:
Before FCI = 0 FCI = 1
In all fills, the blitter evaluates data one bit at a time, starting at
the rightmost edge and moving to the left. Before the fill begins, however,
the blitter takes note of the FCI bit (2) of the BLTCON1 register. The
value of this bit becomes the initial fill value of the blitter's fill bit.
For the sake of clarity, let's assume FCI starts at zero.
Here's how inclusive fill works: As the blitter moves left, it changes
all zero bits to zero, because zero is the current value of the fill bit.
When the blitter encounters a 1 bit, it toggles the fill bit, changing it to
a one. Now the blitter changes the following 0 bits to 1, because that is
the current value of the fill bit. Every time the blitter encounters a 1
bit in the data, the fill bit changes value. The figure above illustrates
the difference between fills that start with FCI = 0 or FCI = 1.
Exclusive fills take one extra step when they encounter a 1 bot. In
addition to toggling the fill bit, the blitter replaces that 1 bit with the
new fill-bit value.
Both types of fills expect borders to be defined by a single 1 bit - one
bit to tell the blitter that it's inside an area, and the other to tell it
that it's outside. When the blitter encounters two one bits in a row, it
assumes that there is no space to be filled since there is no zero bit
between pixels. If the blitter encounters three 1 bits in a row, the
blitter assumes that it has gone in, out, then back in to an area to be
filled. (The fill bit has been toggled three times.) This happens when the
blitter runs across an odd number of adjacent bits.
To execute a fill operation, simply set up the blitter registers for a
standard copy operation, set either the IFE or EFE bit, set the FCI bit to
the desired value, set the DESC to put the blitter in descending mode, then
start the blitter by writing the area size to the BLTSIZE register. By
setting the blitter's source address equal to the destination address, you
can fill an area without having to copy data from one separate location to
another.
Line Mode: Besides copying data and filling areas, the blitter has one
more talent: drawing lines. In line mode, almost all of the blitter
registers change their functions.
The blitter draws lines at incredible speeds, much faster than the 68000.
Unfortunately, you can't just give the blitter two points and then tell it
to connect the dots. You need to perform some calculations first.
Let's say that you want to draw a line from point (x1,y1) to (x2,y2).
From these coordinates you need to figure out the horizontal and vertical
distance between the line's two end points. This is easily calculated using
the following two formulae:
dx = abs(x1-x2)
dy = abs(y1-y2)
Now you're ready to give the BLTCON1 register at $DFF042 some information
about the physical orientation of the line.
If (dx >= dy) and (x1 >= x2) set bit 2.
If (dx < dy) and (y1 >= y2) set bit 2.
If (dx >= dy) and (y1 >= y2) set bit 3.
If (dx < dy) and (x1 >= x2) set bit 3.
If (dx >=dy) set bit 4.
Together, these bits define the octant (position relative to the line's
starting position) in which the line will appear. The following shows how
the Amiga divides the screen into octants:
\ | / * = x1,y1
\ 3 | 1 / Note: The numbers shown in this figure
7 \ | / 6 represent the combined value of BLTCON1's
\ | / bits 2-4. If the line appears on the border
-----*----- of two octants, it does not matter which of
/ | \ the two octants you select.
5 / | \ 4
/ 2 | 0 \
/ | \
Next, you need to determine which value is larger: dx or dy. Let dmax
equal the greater value, and dmin the lesser value. Now use these values to
set the following registers:
dmax = max(dx,dy)
dmin = min(dx,dy)
BLTBMOD = 4* dmin
BLTAMOD = 4 * (dmax-dmin)
BLTAPTL = (4 * dmin) - (2 * dmax)
These formulae define the line's slope. If the result of the last
calculation BLTAPTL is negative, you must store a 1 in the SIGN bit (6) of
the BLTCON1 register.
Besides holding the line's octant number and the negative/positive status
of the line's slope, BLTCON1 affects the line's physical appearance. If
you're drawing lines to enclose an area that you plan to fill later using
blitter fill mode, you should set the ONEDOT bit (1) equal to one. This
tells the blitter to draw lines using only one pixel per raster, thus
providing a single pixel border for your object.
To create textured lines, BLTCON1's bits 12-15 work in conjunction with
the BLTBDAT register ($DFF072). The bit pattern found in BLTBDAT defines
the pixel pattern used to draw lines. For normal solid lines, set all of
BLTBDAT's bits to one. (i.e. $FFFF) Other values create dotted or dashed
lines. Bits 12-15 in BLTCON1 allow you to specify which bit in BLTBDAT,
0-15, defines the status of the first pixel in the line. For most practical
purposes, BLTCON1's bits 12-15 should be set equal to the value of x1's
lower 4 bits. (i.e. x1 AND $0F) This informs the blitter to start the line
off with the value found in BLTBDAT's MSB (15). IMPORTANT: ALWAYS SET
BLTCON1 PRIOR TO BLTBDAT!
BLTCON1's bit 5 should always be set to zero, as should bits 7 through
11. To tell the blitter that you want to draw lines instead of copy data,
the LINE bit (0) must be set to 1.
The Amiga needs certain information about the size and location of the
screen's bitmap before it can draw a line. First, store the byte-width
(number of pixels divided by 8) of the bitmap in the BLTCMOD and BLTDMOD
registers ($DFF060 and $DFF066). Next, you must put the address of the word
containing the starting point of the line into the BLTCPT and BLTDPT
registers. ($DFF048 and $DFF054)
Only one bitplane can be written to during a single blitter operation.
So, to draw a line of a particular color on a multiple bitplane screen, it
may be necessary to perform two or more line blits. In these cases, you set
the registers up for the first bitplane as usual, and perform the blit; then
for subsequent bitplanes, you simply reinitialize the registers with the
same values EXCEPT for the registers BLTCPT and BLTDPT, which must contain
the address of the line's starting point within the new bitplane.
As with blitter copy mode, you must set bits 0-7 in the BLTCON0 register
($DFF040) to choose a miniterm. Usually, you should store $CA here, but if
you prefer to XOR your line onto the screen (invert all the pixels found on
the line), store a $4A here.
BLTCON0's bits 8-11 should be set equal to $B. (This activates blitter
source A and C, and destination D.) Store x1's lower four bits (x1 AND $0F)
into BLTCON0's bits 12-15. The blitter uses this value to determine the bit
position of the line's starting point within the bitplane memory location
specified by registers BLTCPT and BLTDPT.
Now, set BLTADAT ($DFF074) equal to $8000. (Set this register only AFTER
you've set BLTCON0) Only two more registers must be set before you can
activate the blitter: BLTAFWM and BLTALWM. ($DFF044 and $DFF046) Store a
$FFFF into both.
Finally, you're ready to start the blitter by writing to the BLTSIZE
register ($DFF058). Use the following formula to determine the value that
you should store into this register:
BLTSIZE = (dmax * 64) + 66
Because writing to BLTSIZE turns on the blitter, this should be the last
register that you set.
Note: Even if you try to set the lower four bits of a graphics.library
miniterm, the system will zero them out before actually writing this value
to the register's LFx bits.
If you set the blitter's sources the same way that the
graphics.library does - A points to a mask (usually $FFFF), B points to the
source data, and C points to the Destination data - you can use this table
to determine the miniterm settings for your own blitter routines.
When blitting with only one or two sources active, choose miniterms that
aren't affected by the value of the unused source(s).
Now the cheat: Here's a quick and easy formula for calculating the value
that you must store in BLTCON0 when drawing lines:
3018 + ((x1 and #$0F) * 4096)
This specifies the miniterm value for a normal line and provides the
blitter with the bit position of x1 within the memory location found in
registers BLTCPT and BLTDPT. ($DFF048 and $DFF054) To XOR a line onto the
screen (invert any of the bits located within the line), subtract 128 from
the result of the above calculation.
----------------------------------------------------------------------------
$DFF042 BLTCON1 Blitter Control Register 1
Status: *W Agnus
For Blitter Moves and Fills:
0 LINE 1 = activate line draw mode, 0 = normal copy
1 DESC 1 = descending operation, 1 = ascending op.
2 FCI Starting bit for fill mode
3 IFE Enables inclusive fill mode
4 EFE Enables exclusive fill mode
5-11 UNUSED Always set to zero.
12-15 BSH0-3 Preshift value for source B
Line Mode: To activate line mode, set bit zero of this register equal to
one. Setting the ONEDOT bit (1) tells the blitter to draw lines that have
only one pixel on each horizontal row. For clear, clean lines, you should
set this bit equal to zero. But if you are drawing objects that you plan to
fill later using the blitter fill operation, this bit should be set to one.
This way, the area to be filled in will be enclosed by single pixel walls,
just as the blitter expects them to be. Bit 5, and bits 7-11 should be set
to zero. The value of the remaining bits depends on the line's coordinates.
You might be interested to know that this register's TEXTURE bits are
actually used as a shift value, as they are in blitter copy mode. You see,
blitter source B is used as a mask for creating textured lines. Because a
line may start at any pixel position, it is necessary to shift the mask
found in BLTBDAT to align its high bit with the line's starting point. As
with bits 12-15 in the BLTCON0 register, the shift value for source B is
calculated from the lower four bits of x1.
----------------------------------------------------------------------------
$DFF044 BLTAFWM Source A First Word Mask
Status: *W Agnus
This register allows you to mask out the bits found on the left edge of
the bitplane area specified for blitter source A. The first word of each
horizontal line is ANDed with the value stored in this register before it is
shifted, applied to the miniterm, and copied to memory. For example, to
ensure that the two leftmost pixels of an area are always set to zero, store
a $3FFF in this register. In descending mode, this and the following
register swap functions.
Line Mode: In line mode, you should always store a $FFFF here.
Otherwise, your line may appear broken.
----------------------------------------------------------------------------
$DFF046 BLTALWM Source A Last Word Mask
Status: *W Agnus
This register allows you to mask out the bits found on the right edge of
the bitplane area specified for blitter source A. The last word of each
horizontal line is ANDed with the value stored in this register before it is
shifted, applied to the miniterm, and copied to memory. For example, to
ensure that the two rightmost pixels of an are are always set to zero, store
a $FFFC in this register. In descending mode, this and the previous
register swap functions.
Line mode: In line mode, you should always store a $FFFF here.
Otherwise, your line may appear broken.
----------------------------------------------------------------------------
$DFF048 BLTCPTH Blitter Source C Pointer
$DFF04A BLTCPTL
Status: *W Agnus
This is where you store the address of source C's bitmap data prior to
activating the blitter. If you're blitting in ascending order, this address
should specify the starting address of your data. If you're blitting in
descending order, this address should specify the ending address of your
data - the address of the last word of data.
The low bit of this 32 bit register is always interpreted as zero, so
blitter bitmap data must begin on an even word boundary address. (Using
BLTxFWM and BLTxLWM mask registers, however, you can specify bitmapped areas
with pixel accuracy.) And, unless your Amiga has a 1MB Agnus, your data
cannot be located above $7FFF. (1MB Agnus, use $FFFFF)
Line mode: This register, as well as the BLTDPT register ($DFF054), must
contain the starting address of the line to be drawn. (i.e. the address of
the word that contains the first point of the line.) Using standard (x1,y1)
coordinates where (0,0) is the upper left corner of the bitplane, you can
calculate this address using the following formula:
Address = Bitplane + (y1 * BytesPerLine) + (2 * (x1/16))
where Bitplane is the starting address of the destination bitplane and Bytes
Per Line is the width of the bitplane in bytes (number of pixels divided by
eight). So, to draw a line in a 320 x 200 pixel bitplane found in memory at
16384 starting at coordinate (10,20), you would store a 17185 into this
register because 16384+(20*(320/8))+(2*(10/16)) equals 17185.
----------------------------------------------------------------------------
$DFF04C BLTBPTH Blitter Source B Pointer
$DFF04E BLTBPTL
Status: *W Agnus
This is where you store the source B's bitmap data prior to activating
the blitter. See register BLTCPT ($DFF048) for details.
Line Mode: This register is not used in blitter line mode.
----------------------------------------------------------------------------
$DFF050 BLTAPTH Blitter Source A Pointer
$DFF052 BLTAPTL
Status: *W Agnus
This is where you store the address of source A's bitmap data prior to
activating the blitter. See register BLTCPT ($DFF048) for details.
Line Mode: Only the low word of this register, BLTAPTL, us used in line
mode. Its value determines the slope of the line. Use the following
formula to calculate the value of this register:
BLTAPTL = (4 * dmin) - (2 * dmax)
where dmin equals min(abs(x1-x2),abs(y1-y2)) and dmax equals
max(abs(x1-x2),abs(y1-y2)). If this formula produces a negative number, you
must write a 1 to the SIGN bit (6) of the BLTCON1 register at $DFF042.
----------------------------------------------------------------------------
$DFF054 BLTDPTH Blitter Destination Pointer
$DFF056 BLTDPTL
Status: *W Agnus
This is where you store the address of the chip RAM you're blitting into
(usually, this is a location within a bitmap). If you're blitting in
ascending order, this address should reflect the starting address of your
data. If you're blitting in descending order, it should reflect the ending
address of the destination data. This register has the same limitations as
the BLTAPT-BLTCPT registers. See location $DFF048 for details.
Line Draw Mode: This register, as well as the BLTCPT register at $DFF048
must contain the starting address of the line to be drawn - that is, the
address of the word that contains the first point in the line. See $DFF048
for more information.
----------------------------------------------------------------------------
$DFF058 BLTSIZE Blitter Start and Size
Status: *W Agnus
For Blitter Moves and Fills:
0-5 W0-W5 Width of destination area in words
6-15 H0-H9 Height of destination area in pixels
The value stored in this register tells the blitter how large your
destination area is. The lower six bits specify the width of this area in
words - pixels divided by 16. If these bits are set to zero, the blitter
assumes a width of 64 words, or 1024 pixels. The height of the area in
pixels goes into the upper nine bits. A 0 specifies a height of 1024
pixels. You can use the following formula to calculate the value of this
register:
BLTSIZE = (Height * 64) + (Pixelwidth / 16)
The maximum width or height is 1024 pixels. The minimum width is 16
pixels and the minimum height is one pixel.
Writing to this register activates the blitter. As a result, it should
be the last blitter register that you write to.
If you are shifting source A or source B data, you must specify a
horizontal width that is one greater than normal.
Line Mode: In line mode, the lower six bits must hold the value 2 while
the upper 9 bits must hold the value of dmax + 1. Use the following formula
to determine the value that you should store in this register:
BLTSIZE = (dmax * 64) + 66
where dmax equals max(abs(x1-x2),abs(y1-y2)).
Because writing to BLTSIZE turns on the blitter, it should be the last
register that you set.
----------------------------------------------------------------------------
$DFF05A - $DFF05E Currently Unused
----------------------------------------------------------------------------
$DFF060 BLTCMOD Blitter Source C Modulo
Status: *W Agnus
Whenever the blitter finishes writing data to the last word in a
horizontal line, the contents of this register are added to the BLTCPT
register so that it points to the start of the next line. This allows the
blitter to copy areas within a bitmap that are smaller than the width of the
bitmap itself. If you're copying an area that is the same width of the
bitplane it is contained in or if you're copying consecutive bytes in
memory, simply write a zero to this register. Otherwise, this register
should contain the difference between the byte width of the bitplane
containing the area to be copied and the byte width of the area. Here's a
formula for determining the value that should be stored in this register:
BLTCMOD = (BitMapWidth / 8) - (2 * (AreaWidth / 16))
where BitMapWidth and AreaWidth are the pixel widths of the source bitmap
and the area to be copied respectively. Note that this register specifies
width in bytes whereas the BLTSIZE register specifies width in words. Also,
although this register reflects the bitmap's width in bytes, its low bit is
ignored, so the value here must specify an even number of bytes.
With a separate BLTxMOD register for each source, it's possible to
combine the data from three bitmaps of different widths.
Line Mode: For drawing lines, store the byte width (pixel width divided
by 8) of your bitmap in this register.
----------------------------------------------------------------------------
$DFF062 BLTBMOD Blitter Source B Modulo
Status: *W Agnus
Copy Mode: See BLTCMOD above.
Line Mode: This register should contain the value 4 * dmin, where dmin
equals min(abs(x1-x2),abs(y1-y2)).
----------------------------------------------------------------------------
$DFF064 BLTAMOD Blitter Source A Modulo
Status: *W Agnus
Copy mode: See BLTCMOD above.
Line Mode: This register should contain the value 4 * (dmin - dmax) with
dmin and dmax defined as above.
----------------------------------------------------------------------------
$DFF066 BLTDMOD Blitter Destination Modulo
Status: *W Agnus
Copy mode: See BLTCMOD above.
Line Mode: For drawing lines, store the byte width (pixel width divided
by 8) of your bitmap in this register. This is the same value you must
store in the BLTCMOD register.
----------------------------------------------------------------------------
$DFF068 - $DFF06E Currently Unused
----------------------------------------------------------------------------
$DFF070 BLTCDAT Blitter C Source Data
Status: *W Agnus
The blitter uses this register as the data register for blitter source C
Line Mode: Store the bit pattern with which you wish you5r line to be
drawn in this register. For normal solid lines, store a $FFFF here. Other
values produce dotter or dashed lines.
----------------------------------------------------------------------------
$DFF074 BLTADAT Blitter Source A Data
Status: *W Agnus
This is the data register for blitter source A.
Line Mode: This register should be initialized with the value of $8000
for line mode.
----------------------------------------------------------------------------
$DFF076 - $DFF07C Currently Unused
----------------------------------------------------------------------------
$DFF07E DSKSYNC Disk Sync Pattern
Status: *W Paula
Before reading data from a disk, it's often necessary to sync the
drive's heads on a particular bit pattern. This register allows you to do
just that.
When the WORDSYNC bit (10) in the ADKCON register ($DFF09E) is set, the
disk controller's DMA is enabled and the controller prepares to search the
disk for the sync pattern found in this register. The disk controller
doesn't start searching until this register is written to. When the sync
pattern is found, it is set to one for two or four usec (Depending on the
format selected: MFM or GCR) as soon as the sync pattern is located.
This event can also be used to trigger a level 6 interrupt.
In MFM format (the disk format used by AmigaDos), the sync pattern should
be a value that is impossible to create using MFM data coding. This way, it
can't be confused with actual data. AmigaDos uses the number $4489 as its
sync pattern. Here's how you might initiate the search for this value using
machine language:
For more information on low-level disk access, see the CIA-B's PRB
register at $BFD100.
----------------------------------------------------------------------------
Copper Registers:
The copper is designed to free the 680x0 from display tasks. It has
three instructions: WAIT, MOVE, and SKIP. It doesn't seem like you can do
much with only three instructions, but by using a variety of tricks and
subterfuges, a copper list can perform loops, take over the blitter, and
even generate an interrupt for the 68000.
WAIT. Wait mimics a loop structure which waits for a certain condition
to occur. Specifically, Wait waits for the x,y coordinates of the raster to
meet or exceed the coordinates you specify. Thus, wait allows you to
synchronize actions with the video. (i.e.: Color changes, raster
interrupts, etc.) Since a typical copper list executes every time the
screen is drawn, the color change will be rock steady.
The x,y coordinates are not simple pixel coordinates, but beam position
coordinates. See the descriptions of VPOSR ($DFF004), VHPOSR ($DF006),
VPOSW ($DFF02a), and VHPOSW ($DFF02C).
Here is what a Wait instruction looks like:
0 Always set to 0
1-7 horizontal compare enable bits
8-14 vertical compare enable bits
15 the blitter finished disable bit (usually 1)
16 Always set to 1
17-23 horizontal beam position
24-31 vertical beam position
Bits 1-7 describe which bits of the horizontal beam counter will be
compared with an x position for which you choose to wait. Normally, you
should set all of these bits to one.
Bits 8-14 describe the same for the y position.
Bit 15 should normally be set to one. If you set it to zero, the copper
Wait instruction will wait until the beam position meets or exceeds the
given position and the blitter has finished its operation.
Bits 17-23 indicate the horizontal beam position for which the wait is
waiting. Note that bits 1-7 are used to decide which bits are actually used
for the comparison.
Bits 24-31 indicate the same for the vertical - uses 8-14.
Bits 0-15 are a word of data that you wish to transfer to the hardware
register. If you want to transfer a long word, you must use 2 move
instructions.
Bits 17-24 specify the offset from $DFF000 which you would like to
modify. The CDANG bit of the COPCON register determines which values are
considered legal by the copper.
SKIP. Most copper lists are composed only of WAIT and MOVE instructions.
The Skip command allows for conditional branching. It is a command that has
quite a bit of potential that has rarely been tapped.
Skip is a close relative of WAIT. As is the case with Wait, Skip decides
what to do based on the position of the video beam. Instead of waiting for
a beam position though, it alters copper list program flow based on the beam
position.
The Skip instruction looks like this:
0 Set to 1
1-7 horizontal compare enable bits
8-14 vertical compare enable bits
15 blitter-finished-disable bit
16 set to 1
17-23 horizontal beam position
24-31 vertical position
The Skip command skips the instruction that immediately follows it if the
beam counter meets or exceeds the value you specify. The instruction that
follows skip is typically a strobe to the COPJMP1 or COPJMP2 registers.
Writing to these registers causes a jump to the address in the COP1LC or
COP2LC registers, respectively.
----------------------------------------------------------------------------
$DFF080 COP1LCH Copper Program Counter 1
$DFF082 COP1LCL
$DFF084 COP2LCH Copper Program Counter 2
$DFF086 COP2LCL
Status: *W Agnus
The above registers are the copper location registers. COP1LC is the
default copper PC. Either of the above are loaded when the COPJMP registers
are strobed.
----------------------------------------------------------------------------
$DFF088 COPJMP1 Copper Jump Strobes
$DFF08A COPJMP2
Status: Strobe Agnus
These locations, when written to, cause the respective copper PC (1 or 2)
to be loaded into the copper program counter. The operation system strobes
COPJMP1 during a vertical blank interrupt.
----------------------------------------------------------------------------
$DFF08C COPINS Copper Instruction Identity
Status: *W Agnus
This location is of questionable use to the programmer. It is written to
by the hardware and is used to identify the current copper instruction.
----------------------------------------------------------------------------
Location Range: $DFF08E - $DFF094 Position of the screen display
These four registers define the position of the Amiga's screen. DIWSTRT
(Display Window Start) defines the screen's upper left corner while DIWSTOP
(Display Window Stop) defines the window's lower right corner. Anything
outside of this area is considered border area.
Before explaining how the next two registers, DDFSTRT and DDFSTOP, affect
the display, a brief explanation of bitplane DMA is in order. Bitplane data
describes what to draw, but it's the responsibility of bitplane DMA to grab
that data from chip RAM and give it to the video hardware via registers
BPL1DAT - BPL6DAT ($DFF110 - $DFF11A). Shortly after the video hardware
receives new data, it draws that data at the cirrent video beam position.
So where graphics appear onscreen is determined by when bitplane DMA gives
the video hardware its information. (Anytime bitplane DMA is inactive and
the BPLxDAT registers are empty, the Amiga displays the color specified by
the COLOR00 register.)
Vertically, bitplane DMA starts the moment it reaches the Y coordinate
found in DIWSTOP. Horizontal start and stop locations are a bit more
complicated, however, as the computer needs some more time before it can
display fetched data. On a lo-res display, it takes 8.5 color clocks. (A
color clock is equal to one memory access cycle, ehich is approximately 280
nsec in duration. The Amiga can output two lo-res pixels per color clock.)
Each horizontal line on the computer screen can be thought of as a time
line. Where along this line bitplane DMA is allowed to start is determined
by the DDFSTRT (Display Data Fetch Start) register. The DDFSTOP (Display
Data Fetch Stop) register tells the Amiga when the bitplane DMA should stop.
As you can imagine, unless these registers correspond with the horizontal
coordinates found in the DIW registers, your display will appear cropped
and/or garbled.
Finding the proper value for the DDFSTRT based on the horizontal
coordinate found in DIWSTRT is easy. Because the DIWSTRT register specifies
coordinates in lo-res pixels, and the DDFSTRT register is accurate to only
two lo-res pixels, you must first divide DIWSTRT's horizontal coordinate by
two; then, simply subtract the number of color clocks that you need - 4.5
for hi-res, and 8,5 for lo-res. Here oare the formulae you should use to
calculate the correct value for the DDFSTRT register:
DDFSTRT = HSTART / 2 - 4.5 for hi-res screens, and
DDFSTRT = HSTART / 2 - 8.5 for lo-res.
HSTART refers to bits 0-7 of the DIWSTRT register (its horizontal
coordinate).
Since the default value for HSTART is $81, DDFSTRT defaults to $3C for
hi-res, and $38 for lo-res.
Calculating the value for DDFSTOP is also easy. Its value depends on the
screen's width:
DDFSTOP = DDFSTRT + (4 * ((Width / 16) - 1)) for hi-res screens, and
DDFSTOP = DDFSTRT + (* * ((Width / 16) - 1)) for lo-res.
Width is the width of the screen in pixels. So, on a standard 640 pixel
hi-res screen, where DDFSTRT equals $3C, DDFSTOP should be set to $D4.
----------------------------------------------------------------------------
$DFF08E DIWSTRT Display Window Start
Status: *W Agnus
0-7 HSTART Horizontal coord. of upper left corner
8-15 VSTART Vertical coordinate of lower right corner
Notes: Bits 0-7 default to $81, and 8-15 default to $2C.
----------------------------------------------------------------------------
$DFF090 DIWSTOP Display Window Stop
Status: *W Agnus
0-7 HSTOP Horizontal coord. of lower right corner
8-15 VSTOP Vertical coord. of lower right corner.
Notes: For bits 0-7, the minimum HSTOP position in $100, which is 1/3 across
the screen. The value stored here represents an offset from this position.
So, the actual horizontal coordinate of the lower right corner of the screen
is $100 PLUS HSTOP! You can think of HSTOP as being a nine bit register
with bit 8 always set. The Default is $C1, which specifies a value of $1C1.
For bits 8-15, these bits hold the vertical coordinate of the lower right
corner of the screen. The minimum VSTOP position in $80. If the value here
is less than $80, VSTOP equals $100 PLUS your VSTOP value. Simply put,
whatever the state of bit 8 is, bit nine will be opposite! The default for
NTSC is $F4, and the PAL default is $2C which actually is $12C. VSTOP
always specifies the vertical position in noninterlace lines, no matter what
mode the computer is in.
----------------------------------------------------------------------------
$DFF092 DDFSTRT Display Data Fetch Start
Status: *W Agnus
This register specifies the horizontal position that the video beam must
reach in order for bitplane DMA to start. It's value depends on your screen
resolution, and what you store in the HSTART bits (0-7) in the DIWSTRT
register at $DFF09E.
In hi-res, only bits 2-7 are active. (specifies an even multiple of 4)
In lo-res, only bits 3-7 are active (an even multiple of 8). Because of
certain hardware limitations, do not use DDFSTRT values less than $18. Ans,
because sprite DMA relies on color clocks that occur during raster positions
$16-$34, using DDFSTRT values below $38 will disable certain sprites. The
lower the number, the more sprites are disabled. Higher numbered sprites
will be disabled first.
----------------------------------------------------------------------------
$DFF094 DDFSTOP Display Data Fetch Stop
Status: *W Agnus
This register specifies the horizontal position the video beam must reach
in order for bitplane DMA to stop. The bits used are the same as for
DDFSTRT. Because of certain hardware limitations, do not use values greater
than $D8.
----------------------------------------------------------------------------
$DFF096 DMACON DMA Control
Status: *W Angus/Denise/Paula
This is the write register for DMACONR. The only difference is that
SET/CLR is active. Note that activating audio channel DMA starts the sound
on the specified channel. (See DMACONR at $DFF002)
----------------------------------------------------------------------------
$DFF098 CLXCON Collision Control
Status: *W Denise
0 MVP1 Match value for bitplane 1 collisions
1 MVP2 2
2 MVP3 3
3 MVP4 4
4 MVP5 5
5 MVP6 6
6 ENBP1 Enable collision detection for bitplane 1
7 ENBP2 2
8 ENBP3 3
9 ENBP4 4
10 ENBP5 5
11 ENBP6 6
12 ENSP1 Enable collision detection for sprite 1
13 ENSP3 3
14 ENSP5 5
15 ENSP7 7
The Amiga can detect three types of graphic collisions: sprite - sprite,
sprite - bitplane, and bitplane - bitplane. The match value in bits 0-5
determine exactly what constitutes a collision: either a 0 or 1.
Through creative use of 0-5 and 6-11, you can specify that collision
takes place with only a certain color or within a range of colors.
Bits 6-11. These bits determine which bit planes are used in collision
detection. Oddly, the Amiga always seems to think that a bitplane collision
is taking place when all of these bits are set to zero.
Bits 12-15. Setting these bits allows you to check for collisions
between the specified sprite, and the next lower one.
----------------------------------------------------------------------------
$DFF09A INTENA Interrupt Enable
Status: *W Paula
This is the write register for INTENAR at $DFF01C. Note that SET/CLR is
active, and that you must CLEAR the appropriate bit after servicing the
interrupt!
----------------------------------------------------------------------------
Location Range: $DFF09E - $DFF0DE Audio Registers
Once you have a waveform sample loaded into chip RAM, turning that data
into sound is relatively simple. Just tell the computer where is, the
length in words, how fast to play the sound, set the volume, and then signal
that DMA for the desired sound. The Amiga will continue to play and repeat
your sound until you tell it to stop.
----------------------------------------------------------------------------
$DFF09E ADKCON Audio/Disk Control (see ADKCONR at $DFF010)
Status: *W Paula
Notes on bit 12: MFM vs. GCR formatting:
Briefing put, MFM format inserts clock bits between each data bit written
to disk. If two consecutive data bits are zero, a 1 clock bit is inserted
between them. If either of two consecutive bits is a 1, a 0 clock pulse in
put between them. Using this coding method, the amount of data written to a
disk is doubled, but the accuracy of reading the data is increased. You
see, the disk controller has an easier time synchronizing on data that
changes states rather than data that repeats such as a long string of 1's or
0's.
GCR format handles synchronization problems by encoding every four bits
od data into five bits. The result is a binary number with no more than two
adjacent 0 bits and no more than eight adjacent 1 bits. (This format is
used on the Commodore 1541 drives on the C64.) The following table shows
the 5 bit GCR equivalents of the binary numbers 0000-1111.
Binary GCR
------ ---
0000 01010 Note that with GCR, no more than 8 on bits or
0001 01011 2 off bits are possible.
0010 10010
0011 10011
0100 01110
0101 01111
0110 10110
0111 10111
1000 01001
1001 11001
1010 11010
1011 11011
1100 01101
1101 11101
1110 11110
1111 10101
Notes on bit 13: These set the disk disk controller's precompensation
time, which directly affects the density of the data written to disk. The
faster the precompensation time, the higher the density. With AmigaDos,
density is highest on the inside tracks, probably due to the fact that these
is less physical space for these tracks.
----------------------------------------------------------------------------
$DFF0A0 AUD0LCH Channel 0 Waveform Address
$DFF0A2 AUD0LCL
Status: *W Agnus
The low byte of this register is always interpreted as zero, so your data
must begin on a word boundary. For a 512K Agnus, max address is $7FFFF, and
for a 1MB Agnus, it is $FFFFF.
----------------------------------------------------------------------------
$DFF0A4 AUD0LEN Channel 0 Waveform Length
Status: *W Paula
The length of your data in words is stored here. So, your data must be
an even number of bytes, and may not exceed 131,070 bytes. (i.e. 65536
times two.)
However, it is possible to play waveforms longer than 131,070 bytes due
to the fact that the Amiga buffers the contents of the AUDxLC and AUDxLEN
registers by using backup registers. So, you may change the AUDxLC and
AUDxLEN registers while the Amiga is playing a sound, and when it is
finished, it will start with the new data! Any of the Amiga's audio
channels can cause a level 4 interrupt just before your sound starts a new
waveform cycle. When this interrupt occurs, you know it's safe to change
the registers. One warning however: Interrupts caused by high-frequency
waveforms can occur quite rapidly. Even more rapidly than the operating
system can keep up! It's best to leave the audio interrupts alone, unless
you actually need them. Just wait a little while before changing the AUDxLC
and AUDxLEN registers and all will work fine.
----------------------------------------------------------------------------
$DFF0A6 AUD0PER Channel 0 Period
Status: *W Paula
A sound's frequency is determined by the value stored here. The lowest
value you should use is 124, since this is about as fast as the Amiga can
go. The highest value is 65535.
How you determine the period depends on how you get your waveform data.
If you use a digitizer and the frequency is in Samples-per-second, use this
equation: AUDxPER = 3579546 / Samples-per-second
If you have a group of data that you want played as an "instrument", use
this: AUDxPER = 3579546 / (Bytes-Length * Frequency to be played)
Of course, the frequency for a given note may be calculated by the old
standby: Frequency = Base * 2 ^ (1/12)
Which calculates the frequency for the next note once given a frequency.
Middle C comes in at 261.4 Hz.
If you don't want your sound to repeat, you should consider one more
thing: when to stop the sound. You see, the faster you play the sound, the
faster its going to finish. To figure out how long to let it play, use the
following equation:
uSec = .279365 * Period * Length
Where uSec, is of course, the time in microseconds it takes to play your
sound once.
----------------------------------------------------------------------------
$DFF0A8 AUD0VAL Channel 0 Volume
Status: *W Paula
This volume register can accept values between 0 and 64, where 0 is the
lowest setting (at -infinity dB), and 64 is loudest (at -0 dB).
----------------------------------------------------------------------------
$DFF0AA AUD0DAT Channel 0 Data
Status: *W Paula
This is the data buffer used by channel 0. It's purpose is to output
sounds at a rate higher than the DMA can. To use it, you must disable
channel 0 DMA and shove the data in onw word at a time.
----------------------------------------------------------------------------
Location Range: $DFF0AC - $DFF0AE Unused
The Amiga reserves enough space for eight word-long addresses for each
channel, but uses only six. The remaining addresses are unused.
----------------------------------------------------------------------------
$DFF0B0/2 AUD1LCH/L These registers function exactly the same as
$DFF0B4 AUD1LEN channel 0's. To Find channel 2's, add $20 to
$DFF0B6 AUD1PER the AUD0xxx value, and $30 for channel 3.
$DFF0B8 AUD1VOL
$DFF0BA AUD1DAT
$DFF0BC/E UNUSED
----------------------------------------------------------------------------
Location Range: $DFF0E0 - $DFF0F6 Bitplane pointer registers
Status: *W Agnus
These registers point to the current word of data that is being displayed
from each bitplane. They are set up by the programmer, but increment as
each word of data is fetched from memory. Therefore, these registers must
be reset for each screen. This is usually done by the copper list, but may
also be written directly to by the programmer during the vertical blank
interrupt. The initial value stored here should be the starting address of
the bitplane. The value stored here must begin on a word boundary, and all
notes about 512K / 1MB Agnus chips apply here.
Dual Playfield Mode: In this mode, the odd numbered bitplanes are grouped
into one playfield (1), and the even numbered bitplanes into the other. (2)
One playfield has priority over the other, which means that the backgroup's
playfield shows through only when the foreground's pixels color is 0.
Extra HalfBrite: In EHB, pixels may have any value in the range of 0-63.
Pixels in the range of 0-31 use the normal 32 color registers. Pixels 32-63
use the lower 32 color registers with the RGB values each shifter one bit
right. Thus, 32-63 are half as bright.
Genlock: This is a method of combining computer graphics with an external
video source. The external source shows through where pixel color 0 is.
Hold and Modify (HAM): In HAM mode, 16 color registers (4 bits) are used
normally. In 5 bitplane HAM mode, a bit set in the 5th bitplane signifies
that the pixel should use the color of the pixel immediately to the left,
but with the blue value corresponding to the value of the lower four
bitplanes. In 6 bitplane mode, the bits in the 5th and 6th bitplanes are
used to specify whether the lower sixteen color registers should be used
normally, or whether the pixel should be based on the pixel immediately to
the left, with the red, green, or blue intensity altered. HAM images are
the most photographic available on the Amiga. Six bitplane HAM is typical,
with five bitplane HAM a rarity.
Interlace: This is a method of doubling vertical resolution by displaying
alternating lines on alternating scans. See VPOSR at $DFF004.
Playfield: This is the name for the non-sprite graphics that appear on
the screen as a result of bitplane DMA. The name is a carryover from the
old Atari VCS. (gasp!)
----------------------------------------------------------------------------
$DFF100 BPLCON0 Bitplane Control Register 0
Status: *W Agnus/Denise
0 UNUSED
1 ERSY External sync. (1 = external, genlocked
0 = internal, normal)
2 LACE 1 = interlace enable
3 LPEN 1 = light pen enable
4-7 UNUSED
8 GAUD 1 = Genlock audio enable
9 COLOR 1 = Composite color enable on Amiga 1000,
0 = Monochrome display.
10 DBLPF 1 = Double (dual) playfield mode
11 HOMOD 1 = HAM active
12-14 BPU Number of bitplanes used. Zero = no bitplanes
You cannot use more than 4 for hi-res, and six
activates EHB mode.
15 HIRES 1 = Hi-res mode 0 = Lo-res mode.
Notes on bit 8: It has been alleged that audio data can be multiplexed on
the BKGD pen during vertical blanking, and bit 8 enables this feature. In
reality, however, this bit simply goes out on the pixel switch ZD during
blanking periods.
----------------------------------------------------------------------------
$DFF102 BPLCON1 Bitplane Control Register 1
Status: *W Denise
0-3 PF1H Playfield 1 horizontal scroll
4-7 PF2H Playfield 2 horizontal scroll
This register allows you to fine scroll the screen horizontally.
Vertical scrolling is trivial. Simply increment or decrement the starting
address of each bitplane by the width of a screen line in bytes. Horizontal
scrolling is trickier. You can perform a coarse 16 pixel scroll by simply
incrementing or decrementing the starting address of the bitplane pointers
by one word, but to scroll at the pixel level, use this register.
In lo-res, the scrolling is in one pixel increments, and in hi-res, it is
two pixels. To set up a screen for horizontal scrolling, the screen must be
one word wider than normal. Do, you must add 2 to DDFSTRT's ($DFF030)
normal value. You must set the modulo registers (BPLxMOD $DFF108) to the
number of "extra" bytes in each line (those that would not exist if you
weren't doing horizontal scrolling) minus two. For example, if you're
displaying 40 bytes of an 80 byte wide screen, place the number 38 into the
appropriate BPLxMOD register.
----------------------------------------------------------------------------
$DFF104 BPLCON2 Bitplane Control Register 2
Status: *W Denise
This register allows you to determine priorities between the graphic
elements that make up an Amiga screen, namely the eight sprites and two
playfields.
Notes: Bits 0-5 allow you to specify whether sprites should pass in front of
or behind a given set of bitplanes. The table below shows the allowable
values.
Repeat this format for each occurrance of the sprite on the screen. For
instance, you might have the same sprite engine used in three different
vertical areas of the screen. In this case, you'd have the above format
three times. At the end of the data, store a $00000000.
Here is a sample adapted from the Amiga Hardware Reference Manual:
SPRITE:
DC.L $6D607200 ; VSTART, HSTART, and VSTOP
DC.L $099007E0 ; Sprite data... $6D
DC.L $13C80FF0 ; $6E
DC.L $23C41FF8 ; $70
DC.L $13C80FF0 ; $71
DC.L $099007E0 ; $72
DC.L $00000000 ; End of structure.
The Amiga is often said to have reusable sprite engines. This means that
the Amiga can display the same sprite in several different places. There is
one significant limitation to this ability: You must ensure that there is at
least one blank line vertically between the two instances of the same
sprite. For example, if you have a sprite that stops displaying on line 25,
you may display a second one on line 27 or greater.
----------------------------------------------------------------------------
$DFF124 SPR1PTH/L Sprite Pointers 1-7
$DFF128 SPR2PTH/L
$DFF12C SPR3PTH/L
$DFF130 SPR4PTH/L
$DFF134 SPR5PTH/L
$DFF138 SPR6PTH/L
$DFF13C SPR7PTH/L
----------------------------------------------------------------------------
$DFF140 SPR0POS Sprite Position 0 & Control 0
$DFF142 SPR0CTL
Status: *W Agnus/Denise
These two 16-bit registers can be thought of as a single 32 bit register
which holds information about how sprite 0 is to be displayed. Info
included is vertical and horizontal starting locations, vertical stopping
location, and whether the sprite should be attached to its companion (0 and
1, 2 and 3, 4 and 5, 6 and 7).
The sprite control value consists of the following bits, the number of
which should be stored in the:
0 HSTART lowest bit
1 VSTOP highest bit
2 VSTART highest bit
3-6 Always 0
7 ATTACHMENT 1 = attached, 0 = not
8-15 VSTOP lowest 8 bits
16-23 HSTART highest 8 bits
24-31 VSTART lowest 8 bits
Notes:
Bit 0: After moving the drive's head, it is important that you wait 3
microseconds before performing any other disk activities. Since software
timing loops will be shorter on accelerated Amigas, use the CIA timers.
Bit 1: You can check if the drive head of a selected drive is on track
0 by reading bit 4 of the CIA-A chip's PRA register located at $BFE001.
Bit 2: When you select the head, the value of this bit affects only
the currently selected drives.
Bits 3-6: You may select more than one drive at a time. Thus, you can
move the heads on more than one drive simultaneously.
Bit 7: This bit turns the motors on and off. The drive LED is
directly wired to the motor power. This bit should be set before you select
a drive. If a drive is already selected and you wish to change the state of
its motor, deselect the drive, set this bit, and then reselect the desired
drive.
When turning on the motor, you must wait for the motor to reach its
full rotation speed before performing any other disk activities. Bit 5 of
the CIA-A's PRA ($BFE001) is set equal to 0 whenever the drive has reached
full speed and is ready to receive another command.
Note that all of this assumes that you have disabled multitasking and
have taken full control of the computer.
----------------------------------------------------------------------------
$BFD200 DDRA Data Direction Register A
Status: R/W CIA-B
A bit set in this register causes the corresponding bit in PRA to be
defined as output. A bit clear causes it to be defined as input. Note that
bits 0-5 are normally clear, and bits 6-7 are set.
----------------------------------------------------------------------------
$BFD300 DDRB Data Direction Register B
Status: R/W CIA-B
This register controls the I/O of PRB. All bits MUST be set to 1.
----------------------------------------------------------------------------
Location Range: $BFD400 - $BFD700 CIA-B Timers A & B L/H Bytes
According to some early Commodore-Amiga manuals, Timer A is reserved for
Commodore 8-bit serial bus communications - the bus system used by the C64
to talk to the 1541, 1571, 1581, as well as C64 compatible printers. For
all practical purposes, the Amiga has no use for these timers. Timer B is
also unused by the operating system. Feel free to use them yourself. For
more details, see the entry for the CIA-A Timer A & B registers at $BFE401
through $BFE701.
This register is used to control the 5 interrupt sources on the 8520 CIA
chip. For details on its operation, see $BFED01.
The main difference between the two CIA chips pertaining to this register
is that on CIA-B, the FLAG line is connected to the disk controller's
DSKINDEX line. And in order for the Amiga to recognize a CIA-B chip
interrupt, bit 13 or the INTENA register must be set to 1. See registers
INTENA and INTENAR at $DFF09A and $DFF01C for more information on Amiga
interrupts.
----------------------------------------------------------------------------
Location Range $BFDE00 - $BFDF00 CIA Control Registers A & B
See locations $BFEE01 and $BFEF01 for details.
----------------------------------------------------------------------------
$BFDE00 CRA Control Register A
Status: R/W CIA-B
0 START Start Timer A (1 = start, 0 = stop)
1 PBON Select Timer A output on Data Port B (1 = Timer B
output appears on bit 6 for Data Port B)
2 OUTMODE Data Port B output mode (1 = toggle bit 6, 0 = pulse
bit 6 every 10 microprocessor cycles)
3 RUNMODE Timer A run mode (1 = one shot, 0 = continuous)
4 LOAD Force latched value to be loaded to Timer A counter
(1 = force load strobe)
5 INMODE Timer A input mode (1 = count signals on CNT line at
pin 1 of keyboard port, 0 = count every 10 uP cycles)
6 SPMODE Serial Port ($BFEC01) mode (1 = output, 0 = input)
7 UNUSED
----------------------------------------------------------------------------
$BFDF00 CRB Control Register B
Status: R/W CIA-B
0 START Start Timer B (1 = start, 0 = stop)
1 PBON Select Timer B output on Data Port B (1 = Timer B
output appears on bit 7 for Data Port B)
2 OUTMODE Data Port B output mode (1 = toggle bit 7, 0 = pulse
bit 7 every 10 microprocesor cycles(
3 RUNMODE Timer B run mode (1 = one shot, 0 = continuous)
4 LOAD Force latched value to be loaded to Timer B counter
(1 = force load strobe)
5-6 INMODE Timer B input mode
00 = count every 10 uP cycles
01 Count cycles on CNT line at pin 1 of keyboard port
10 Count each time that Timer A counts down to 0.
11 Count Timer A 0's when CNT pulses are present
7 ALARM Select TOD write status (1 = writing to TOD registers
sets counter, 0 = writing to TOD registers sets alarm)
----------------------------------------------------------------------------
Location Range $BFE001-$BFE301 CIA Data Ports A and B
These registers allow the Amiga to communicate with the outside world.
Bits of data written to the PRA and PRB registers ($BFE001 and $BFE101) can
be sent to external devices, while bits of data those devices send can be
read here.
A bit can be set up for only input or output, not both at once. To
define the I/O status of a bit, you use the Data Direction Registers.
Register DDRA ($BFE201) controls data port A, and register DDRB ($BFE301)
controls data port B. 1 = output mode, and 0 = input mode. Note that DDRA
is preset by the Amiga on power up. Modifying the contents may cause the
computer to lock up.
----------------------------------------------------------------------------
$BFE001 PRA Peripheral Data Register for Data Port A
Status: R/W CIA-A
0 OVL Memory overlay bit (Dont change! Keep 0)
1 LED Power LED/Cutoff filter (1 = LED dimmed and
cutoff filter inactive, 0 = LED/filter normal)
2 CHNG Disk Change (1 = no change, 0 = disk has
been removed)
3 WPRO 1 = Disk Write Protected 0 = Unprotected
4 TK0 1 = head not on trk 0, 0 = head on track 0.
5 RDY 1 = currently selected drive is ready for
commands, 0 = not ready.
6 FIR0 Fire button on port 1, pin 6 (0 = pressed)
7 FIR1 Fire button on port 2, pin 6 (0 = pressed)
Notes: On bits 6-7, you may also output data through pin 6 on either
game port. Simply set bit 6 or 7 (depending on which port you wish to
output data o) in the DDRA register to 1 for output and then toggle the same
bit in the PRA register. Setting the PRA bit to one outputs approximately 5
volts on that line. Setting the PRA bit equal to zero oulls the line low to
zero volts. It is common courtesy to set the data direction registers back
to their original value after using them.
----------------------------------------------------------------------------
$BFE101 PRB Peripheral Data Register for Data Port B
Status: R/W CIA-A
0 D0 Parallel port pin 2
1 D1 Parallel port pin 3
2 D2 Parallel port pin 4
3 D3 Parallel port pin 5
4 D4 Parallel port pin 6
5 D5 Parallel port pin 7
6 D6 Parallel port pin 8
7 D7 Parallel port pin 9
----------------------------------------------------------------------------
$BFED01 ICR Interrupt Control Register
Status: R/W CIA-A
Notes: Bit layout is the same as the ICR at $BFDD00. This register is
used to control the five interrupt sources on the 8520 CIA chip. These
sources are Timer A, Timer B, the TOD clock, the SDR, and the chip's FLAG
line. Timer's A & B cause an interrupt when they count down to zero. The
TOD clock generates an alarm when it reaches the alarm time. The SDR
generates an interrupt when it compiles 8 bits of input or output. An
external signal pulling the CIA chip's FLAG line low will also cause an
interrupt (on CIA-A, the FLAG line is connected to the ACK line - pin 10 of
the parallel port).
Even if the conditions for an interrupt are satisfied, the interrupt must
still be enabled for the interrupt to occur. This is done by writing to the
ICR. What happens when you write to this register depends on the way you
set bit 7. If it is set to 0, any bit you write to with a 1 is cleared. If
it is set to a 1, any bit that you write to with a 1 is set, and the
corresponding interrupt is enabled. In either case, any bits written to
with a zero will be unaffected.
For example, to disable all interrupts from machine language, you could
MOVE.B #$7F,$BFED01. Don't try this with multitasking turned on, as it will
turn off Timer B, which handles task switching.
To turn on a Timer B interrupt, a program could MOVE.B #$82,$BFED01. Bit
7 is set to 1, and so is bit 1, so the interrupt which corresponds with bit
1 (Timer B) is enabled.
When you read this register, you can tell if any of the conditions for a
CIA interrupt were satisfied because the corresponding bit will be set to a
one. For example, if Timer A counter down to zero, you would read a #$01
from this register. If in addition the enable bit that corresponds to that
interrupt source is set to 1 and an interrupt occurs, bit 7 will also be
set. This allows a multi-interrupt system to read one bit and see if the
source of a particular interrupt is CIA-A. You should note, however, that
reading this register clears it, so you should preserve its contents if you
want to test more than one bit. In order for the Amiga to recognize a CIA-A
chip interrupt, bit 3 of the INTENA register must be set to 1. See
registers INTENA and INTENAR ($DFF09A, $DFF01C) for more information.
----------------------------------------------------------------------------
$BFEE01 CRA Control Register A
$BFEF01 CRB Control Register B
Status: R/W CIA-A
See $BFDE00 and $BFDF00 for information on the bit layout.
----------------------------------------------------------------------------
This completes "Mapping the Amiga" from Compute! Books. For information
on system structures, examine your C and assembler Include files. They
have much better information than the book.
Slates from Bansai
05/26/91
----------------------------------------------------------------------------
Want more cool warez call Spectral Forces 203.327.4104 <<<SPELLJAMMER WHQ>>>