68000 Assembly programming for
the Atari ST
The Atari ST completely passed me by
in the 80's... While it has the same CPU as the Amiga, it has
inferior graphics and sound , with no hardware graphics layers, and
only AY sound...
These days the ST has one major advantage... it's much easier to
emulate! Often getting Amiga games working requires messing with
different configurations, whereas the Atari ST version will run
instantly and while usually has inferior sound, will otherwise
typically be identical to the Amiga version!
|
|
|
|
Specs:
Cpu |
8mhz |
Ram |
512k |
Resolution |
320x200 @ 16 colorr |
Sprites |
Software Only |
Palette |
16 colors onscreen from 512 colors |
Sound chip |
AY |
|
|
ChibiAkumas Tutorials
Memory Map
Address |
Purpose |
000000 |
512k ram |
07FFFF |
|
FA0000 |
128K Rom |
FC0000 |
System Rom |
FEFFF |
|
FF8000 |
Io Area |
FF8200 |
Io Area |
FF8400 |
Io Area |
FF8600 |
Io Area |
FF8800 |
Io Area SOUND AY-3-8910 |
FFFA00 |
Io Area MFP 68901 |
FFFC00 |
Io Area 2 ACIA:s 6580 |
Registers
Because the 68000 uses a 24 bit address bus, These can also be addressed at
$FFFFxxxx - for example $FF8004 is the same as $FFFF8004
Address |
Mode |
Bits |
Purpose |
FF8004 |
RW |
----xxxx |
Memory
Config |
FF8201 |
RW |
HHHHHHHH |
Video
Base
H |
FF8202 |
EW |
LLLLLLLL |
Video
Base
L |
FF8205 |
R |
HHHHHHHH |
Video
Counter
H (current drawing line)
|
FF8207 |
R |
MMMMMMMM |
Video
Counter
M |
FF8209 |
R |
LLLLLLLL |
Video
Counter
L |
FF820A |
RW |
------SR |
Sync
Mode |
FF8240 |
RW |
-----RRR
-GGG-BBB |
Palette
Color
0 |
FF8242 |
RW |
-----RRR
-GGG-BBB |
Palette
Color
1 |
FF8244 |
RW |
-----RRR
-GGG-BBB |
Palette
Color
2 |
FF8246 |
RW |
-----RRR
-GGG-BBB |
Palette
Color
3 |
FF8248 |
RW |
-----RRR
-GGG-BBB |
Palette
Color
4 |
FF824A |
RW |
-----RRR
-GGG-BBB |
Palette
Color
5 |
FF824C |
RW |
-----RRR
-GGG-BBB |
Palette
Color
6 |
FF824E |
RW |
-----RRR
-GGG-BBB |
Palette
Color
7 |
FF8250 |
RW |
-----RRR
-GGG-BBB |
Palette
Color
8 |
FF8252 |
RW |
-----RRR
-GGG-BBB |
Palette
Color
9 |
FF8254 |
RW |
-----RRR
-GGG-BBB |
Palette
Color
10 |
FF8256 |
RW |
-----RRR
-GGG-BBB |
Palette
Color
11 |
FF8258 |
RW |
-----RRR
-GGG-BBB |
Palette
Color
12 |
FF825A |
RW |
-----RRR
-GGG-BBB |
Palette
Color
13 |
FF825C |
RW |
-----RRR
-GGG-BBB |
Palette
Color
14 |
FF825E |
RW |
-----RRR
-GGG-BBB |
Palette
Color
15 |
FF8260 |
RW |
------SS |
Screen
Mode
(00=320x240x4bpp) |
FF8400 |
|
|
Reserved |
FF8600 |
|
|
Reserved |
FF8602 |
|
|
Reserved |
FF8604 |
|
--------
XXXXXXXX |
Disk
controler
data access |
FF8606 |
R |
--------
-----DSE |
DMA
Status
Mode control |
FF8606 |
W |
-------W
FD0RGAB |
DMA
Mode
Control |
FF8609 |
RW |
HHHHHHHH |
Dna
Base
& Counter H |
FF860B |
RW |
MMMMMMMM |
Dna
Base
& Counter M |
FF860D |
RW |
LLLLLLLL |
Dna
Base
& Counter L |
FF8800 |
R |
DDDDDDDD |
IO
Port
B Data |
FF8800 |
W |
RRRRRRRR |
PSG
Register
Select |
FF8802 |
W |
RGCDRFGH |
PSG
Write
Data � IO Port A |
FF8802 |
RW |
DDDDDDDD |
IO
Port
B Data |
FFFA01 |
|
M-IW---P |
MFP
GP
IO |
FFFA03 |
|
DDDDDDDD |
MFP
Active
Edge |
FFFA05 |
|
DDDDDDDD |
MFP
Data
Direction |
FFFA07 |
|
DDDDDDDD |
MFP
Interrupt
Enable A |
FFFA09 |
|
DDDDDDDD |
MFP
Interrupt
Enable B |
FFFA0B |
|
DDDDDDDD |
MFP
Interrupt
Pending A |
FFFA0D |
|
DDDDDDDD |
MFP
Interrupt
Pending B |
FFFA0F |
|
DDDDDDDD |
MFP
Interrupt
Interrupt In Service A |
FFFA11 |
|
DDDDDDDD |
MFP
Interrupt
Interrupt In Service B |
FFFA13 |
|
DDDDDDDD |
MFP
Interrupt
Mask A |
FFFA15 |
|
DDDDDDDD |
MFP
Interrupt
Mask B |
FFFA17 |
|
DDDDDDDD |
MFP
Vector
Base |
FFFA19 |
|
DDDDDDDD |
MFP
Timer
A Control |
FFFA1B |
|
DDDDDDDD |
MFP
Timer
B Control |
FFFA1D |
|
DDDDDDDD |
MFP
Timers
C & D Control |
FFFA1F |
|
DDDDDDDD |
MFP
Timer
A data |
FFFA21 |
|
DDDDDDDD |
MFP
Timer
B data |
FFFA23 |
|
DDDDDDDD |
MFP
Timer
C data |
FFFA25 |
|
DDDDDDDD |
MFP
Timer
D data |
FFFA27 |
|
DDDDDDDD |
MFP
Sync
Character |
FFFA29 |
|
DDDDDDDD |
MFP
USART
control reg |
FFFA2B |
|
DDDDDDDD |
MFP
receiver
status |
FFFA2D |
|
DDDDDDDD |
MFP
Transmitter
status |
FFFA2F |
|
DDDDDDDD |
MFP
USART
Data |
FFFC00 |
|
DDDDDDDD |
Keyboard
ACIA
Control |
FFFC02 |
|
DDDDDDDD |
Keyboard
Data |
FFFC04 |
|
DDDDDDDD |
Midi
ACIA
Control |
FFFC06 |
|
DDDDDDDD |
Midi
Data |
Aline commands
Aline commands are defined by DW $A0xx - these are handled by the vectors of
the 68000 like an RST command on the Z80... see Anatomy
of
the Atari St for more details
Command |
Command |
Detail |
$A000 |
Initialize |
Determine address of required variable range |
$A001 |
Put Pixel |
Set point on the screen |
$A002 |
Get Pixel |
Determine color of a screen point |
$A003 |
Line |
Draw a line on the screen |
$A004 |
Horizontal Line |
Draw a horizontal line (fast) |
$A005 |
Filled Rectangle |
Fill a rectangele wit color |
$A006 |
Filled Polygon |
Fill a polygon line by line |
$A007 |
BitBlt |
Bit block transfer |
$A008 |
TextBlt |
Text block transfer |
$A009 |
Show Mouse |
enable mouse cursor |
$A00A |
Hide Cursor |
Disable mouse cursor |
$A00B |
Transform Mouse |
Change mouse cursor form |
$A00C |
Undraw Sprite |
Clear sprite |
$A00D |
Draw Sprite |
Enable sprite |
$A00E |
Copy Raster From |
Copy raster form |
Vblank!
It's possible to 'Wait for Vblank' by using the line counter at
$FF8205/7/9.
First we calculate the address of the last line of our 32k screen,
in this case by adding 320*200/2 to 'ScreenBase'
Next we wait for the line counter to point to this line - at this
point the bottom of the screen is being drawn,
Here is an example of a possible solution - this assumes memory
address 'ScreenBase' has a long pointer of the address of the first
line of the screen.
|
waitVBlank:
moveM.l d0-d1,-(sp)
move.l ScreenBase,d1
;Get screen pointer
add.l
#(320*200/2),d1 ;Add one full screen
WaitVblankAgain:
jsr VblankGetLine
cmp.l d1,d0
blt
WaitVblankAgain ;Wait for
last line to be drawn
WaitVblankAgain2:
jsr VblankGetLine
cmp.l d0,d1
beq
WaitVblankAgain2 ;Wait for line to end
moveM.l (sp)+,d0-d1
rts
VblankGetLine:
clr.l d0
or.b $FF8205,d0
;Get current drawing line
lsl.l #8,d0
;from
hardware regs
or.b $FF8207,d0
lsl.l #8,d0
or.b $FF8209,d0
rts
|
Joystick reading
I'm not a fan of using the firmware
for doing things, but I can't find any other way to read the
joystick on the Atari ST
The Atari ST joystick is connected as part of the keyboard... to
read it we have to install a Joystick event interrupt handler...
Shown to the right is the simplest joystick handler I have
working...
we store the two joystick bytes to a temporary variable called
"Joydata" |
move.w
#$14,-(sp) ;IKBD command $14
- set joystick event reporting
move.w
#4,-(sp) ;Device no 4
(keyboard - Joystick is part of keyboard)
move.w #3,-(sp) ;Bconout (send cmd to keyboard)
trap #13
;BIOS
Trap
addq.l
#6,sp ;Fix
the stack
move.w #34,-(sp)
;return IKBD vector table (KBDVBASE)
trap
#14
;XBIOS trap
addq.l #2,sp
;Fix the stack
move.l d0,ikbd_vec
; store IKBD vectors address for later
move.l d0,a0
; A0
points to IKBD vectors
move.l 24(a0),old_joy
; backup old joystick vector so we can restore it
move.l #JoystickHandler,24(a0);
Set our Joystick Handler
rts
JoystickHandler:
move.b (1,a0),joydata
; store
joy 0 data
move.b (2,a0),joydata+1
; store joy 1 data
rts
ikbd_vec: dc.l 0
; old IKBD vector storage
old_joy: dc.l
0
; old joy vector storage
joydata: ds.b
2
;Joypad bytes F----RLDU |
AY Sound Chip:
The AY uses a series of 8 bit registers to control the 3 sound channels.
To set a register, we must first select the register number by writing a
byte to $FF8800, then send the byte of
data to $FF8802
Register |
Meaning |
Bit Meaning |
Details |
0 |
Tone Pitch L - Channel A |
LLLLLLLL |
Lower value = Higher pitch |
1 |
Tone Pitch H - Channel A |
----HHHH |
Lower value = Higher pitch |
2 |
Tone Pitch L - Channel B |
LLLLLLLL |
Lower value = Higher pitch |
3 |
Tone Pitch H - Channel B |
----HHHH |
Lower value = Higher pitch |
4 |
Tone Pitch L - Channel C |
LLLLLLLL |
Lower value = Higher pitch |
5 |
Tone Pitch H - Channel C |
----HHHH |
Lower value = Higher pitch |
6 |
Noise Generator |
---NNNNN |
Higer = Faster noise |
7 |
Mixer |
--NNNTTT |
N=Noise T=Tone (Channel --CBACBA 1=mute 0=normal) |
8 |
Amplitude - Channel A |
---EVVVV |
E=Envelope (1=Enabled) VVVV=Volume |
9 |
Amplitude - Channel B |
---EVVVV |
E=Envelope (1=Enabled) VVVV=Volume |
10 |
Amplitude - Channel C |
---EVVVV |
E=Envelope (1=Enabled) VVVV=Volume |
11 |
Envelope L (Volume over time) |
LLLLLLLL |
Lower=Faster Envelope |
12 |
Envelope H (Volume over time) |
HHHHHHHH |
Lower=Faster Envelope |
13 |
Envelope Selection |
----EEEE |
Envelope number (See PDF) |
For more details, please see the AY
sound chip PDF
Traps
Traps are used for firmware and OS functions... commands need to be
pushed onto the stack before the call... see Anatomy
of
the Atari St for more details
Trap |
Num |
Command |
Details |
#1 (Gemdos) |
$00 |
Term |
|
|
$01 |
ConIn |
|
|
$02 |
ConOut |
|
|
$03 |
Auxilliary
Input |
|
|
$04 |
Auxilliary
Output |
|
|
$05 |
Printer
Output |
|
|
$06 |
RawConIO |
|
|
$07 |
Direct ConIn
Without Echo |
|
|
$08 |
ConIn Without
Echo |
|
|
$09 |
Print Line |
|
|
$0A |
ReadLine |
|
|
$0B |
ConStat |
|
|
$0E |
SetDrv |
|
|
$10 |
ConOut Stat |
|
|
$11 |
PrtOut Stat |
|
|
$12 |
AuxIn Stat |
|
|
$13 |
AuxOut Stat |
|
|
$19 |
Current Disk |
|
|
$1A |
Set Disk
Transfer Access |
|
|
$20 |
Super |
|
|
$2A |
Get Date |
|
|
$2B |
Set Date |
|
|
$2C |
Get Time |
|
|
$2D |
Set Time |
|
|
$2F |
Get DTA |
|
|
$30 |
Get Version
Number |
|
|
$31 |
Keep Process |
|
|
$36 |
Get Free Disk
Space |
|
|
$39 |
MKDir |
|
|
$3A |
RmDir |
|
|
$3B |
ChDir |
|
|
$3C |
Create |
|
|
$3D |
Open |
|
|
$3E |
Close |
|
|
$3F |
Read |
|
|
$40 |
Write |
|
|
$41 |
Unlink |
|
|
$42 |
Lseek |
|
|
$43 |
Change Mode
(ChMod) |
|
|
$45 |
Dup |
|
|
$46 |
Force |
|
|
$47 |
GetDir |
|
|
$48 |
Malloc |
|
|
$49 |
Mfree |
|
|
$4A |
SetBlock |
|
|
$4B |
Exec |
|
|
$4C |
Term |
|
|
$4E |
Sfirst |
|
|
$4F |
Snext |
|
|
$56 |
Rename |
|
|
$57 |
GSDTOF |
|
#13 (Bios) |
0 |
getmpb |
Get Memory
Parameter Block |
|
1 |
bconstat |
Return input
device status |
|
2 |
conin |
Read
character from device |
|
3 |
bconout |
Write
character to device |
|
4 |
rwabs |
Read and
write disk sector |
|
5 |
setexec |
set exception
vectors |
|
6 |
tickcal |
return
millisecond per tick |
|
7 |
get bpb |
get BIOS
parameter block |
|
8 |
bcostat |
return output
device status |
|
9 |
mediach |
inquire media
change |
|
10 |
drvmap |
inquire drive
status |
|
11 |
kbshift |
inquire/change
keyboard
status |
#14 (xbios) |
0 |
initmous |
initialize
mouse |
|
1 |
ssbrk |
save memory
space |
|
2 |
physbase |
return screen
RAM base address |
|
3 |
logbase |
set logical
screen base |
|
4 |
getrez |
return screen
resolution |
|
5 |
setscreen |
Set Screen
parameters |
|
6 |
setpalette |
set color
palette |
|
7 |
setcolor |
set color
palette |
|
8 |
floprd |
read diskette
sector |
|
9 |
flopwr |
write disk
sector |
|
10 |
flopfmt |
format
diskette |
|
12 |
midiws |
write string
to midi interface |
|
13 |
mfpint |
initilize MFP
format |
|
14 |
iorec |
return record
buffer |
|
15 |
rsconf |
set rs232
configuration |
|
16 |
keytbl |
set keyboard
table |
|
17 |
random |
return random
number |
|
18 |
protobt |
produce boot
sector |
|
19 |
flopver |
verify
diskette sector |
|
20 |
scrdmp |
output screen
dump |
|
21 |
cursconf |
set cursor
configuration |
|
22 |
settime |
set clock
time and date |
|
23 |
gettime |
return clock
time and date |
|
24 |
bioskeys |
restore
keyboard table |
|
25 |
ikbdws |
intelligent
keyboard send |
|
26 |
jdisint |
disable
interrupts on MFP |
|
27 |
jenabint |
enable
interrupts on MFP |
|
28 |
giaaccess |
access GI
sound chip |
|
29 |
offgibit |
reset Port A
GI sound chip |
|
30 |
ongibit |
cleart port A
of GI sound chip |
|
31 |
xbtimer |
start MFP
timer |
|
32 |
dosound |
Set sound
parameters |
|
33 |
setprt |
Set printer
config |
|
34 |
kbdvbase |
return
keyboard vector table |
|
35 |
kbrate |
set keyboard
repeat rate |
|
36 |
prtblk |
output block
to printer |
|
37 |
wvbl |
wait for
video |
|
38 |
supexec |
set
supervisor execution |
|
39 |
puntaes |
disable AES |
KbdvBase
Xbios trap #34 returns the Keyboard vector table, this contains
7 Long addresses
Offset |
Value
(Long) |
Purpose |
0 |
MidiVec |
Midi Input |
4 |
VkbdErr |
Keyboard Error |
8 |
VmidErr |
Midi Error |
12 |
StatVec |
IKBD Status |
16 |
MouseVec |
Mouse Routines |
20 |
CockVec |
Clock Time Routines |
24 |
JoyVec |
Joystick Routines |
IKBD commands
See page 74 of Atari-ST-Internals.pdf
Number |
Purpose
|
$07 |
Returns the result of pressing one of the two
mouse button |
$08 |
Returns the relative mouse position from now
on. |
$09 |
Returns the absolute mouse position from now on |
$0A |
With this command it is possible to get the key
numbers of the cursor keys instead of the coordinates. |
$0B |
This command sets the trigger threshold, above
which movements will be announced. |
$0C |
Scale mouse. |
$0D |
Read absolute mouse position. |
$0E |
Set the internal coordinate counter |
$0F |
Set the origin for the Y-axis is down (next to
the user) |
$10 |
Set the origin for the Y-axis is up. |
$11 |
The data transfer to the main processor is
permitted again (see $13). |
$12 |
Turn mouse off. |
$13 |
Stop data transfer to main processor |
$14 |
Every joystick movement is automatically
returned. |
$15 |
End the automatic-return mode for the joystick.
|
$16 |
Read joystick. |
$17 |
Joystick duration message. |
$18 |
Fire button duration message. |
$19 |
Cursor key simulation mode for joystick 0 (!). |
$1A |
Turn off joysticks. |
$1B |
Set clock time. |
$1C |
Read clock time. |
$20 |
Load memory. |
$21 |
Read memoiy. |
$22 |
Execute routine. |
| |
Buy my Assembly programming book on Amazon in Print or Kindle!
Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
|