Skip to main content

 ALL ABOUT XBIOS FUNCTIONS by Richard Karsmakers

Originally  published  in ST NEWS Volume 1 Issue  5,  launched  on 
October 5th 1986.

In  the  previous issues of ST NEWS we already had a  little  chat 
concerning  System Variables,  BIOS routines and GEMDOS  routines; 
this  time,  we'll  have  an  in-depth  look  at  XBIOS  routines, 
sometimes  called  EBIOS routines - it stands for  Extended  BIOS. 
These functions are there to enable the programmer to use specific 
hardware characteristics of the Atari ST. For MC68000 programmers, 
it  is  handy to know that TRAP #14 is needed  for  calling  these 
routines. Thereby, the function number must be put on the stack.
While  writing  this article,  we made use of  Data  Becker's  "ST 
Intern" (ISBN 3-89011-119-X,  Data Becker,  Merowingestr. 30, 4000 
Düsseldorf,  West  Germany;  in Holland:  Postbus 8411,  3503  RK, 
Utrecht,  Tel.  030-430254). If you want to know everything  about 
XBIOS functions,  you should buy that publication; it's a must for 
all serious ST programmers/users.  In this article,  we will  only 
have a look at how to program these routines from assembler. All C 
freaks will definately have to get "ST Intern", as will the people 
that want better examples....
In each example, you might wonder why we added the last line, that 
usually  includes  an  'add'  instruction.   This  instruction  is 
necessary  to  clear the stack (as far as  I've  understood).  The 
number that goes with it, can be calculated as follows:
Each .l you put on the stack: +4
Each .w you put on the stack: +2
Each .b you put on the stack: +1
See? Now, let's go on.....

0 initmous

Example: move.l vector,-(sp)
         move.l parameter,-(sp)
         move.w type,-(sp)
         move.w #0,-(sp)
         trap #14
         add.l#12,sp

This  function can be used to initialize all routines that  handle 
the mouse.

'vector'  is  the  address  of a routine that  is  called  by  the 
 keyboard processor when a mouse-report occurs.
'type' can choose one of the following alternatives:
         0        Disable Mouse
         1        Enable Mouse, Relative mode
         2        Enable Mouse, Absolute mode
         3        Unused
         4        enable Mouse, Keyboard mode
'parameter'  points  to a parameter block,  that is  built  up  as 
follows:
         char topmode
         char buttons
         char xparam
         char yparam
'topmode' can have on of the following values:
         0        Y=0 is located at the bottom corner
         1        Y=0 is located at the top corner
'buttons'  is a parameter for the 'Set Mouse Buttons'  command  of 
the  IKBD  (we  might publish an article about that  in  the  near 
future as well).

'xparam' & 'yparam' are factors for the mouse movement.  When  you 
have  choosen  'type' to be 2 (that means that you work  with  the 
mouse in absolute mode),  vier additional parameters are added  to 
the parameterblock:
         int xmax
         int ymax
         int xstart
         int ystart
These  are  the x-and y-coördinates of the maximal  value  of  the 
mouse,  and the other parameters specify the position at which the 
mouse should originally be put.

1 ssbrk

Example: move.w quantity,-(sp)
         move.w #1,-(sp)
         trap #14
         addq.l #4,sp

This function may be used to allocate (reserve) a piece of memory.

'quantity'  is the number of bytes that should be  reserved.  That 
chunk  of  memory will be allocated at the  top  of  memory.  This 
function  should  be  called before the  Operating  System  starts 
Initialization.

2 physbase

Example: move.w #2,-(sp)
         trap #14
         addq.l #2,sp

This function returns a longword,  that signifies the Base of  the 
physical screen. On a 512 K machine, this would result in $78000.

3 logbase

Example: move.w #3,-(sp)
         trap #14
         addq.l #2,sp

This  function  sets  the  logical  base  of  screen  memory.  All 
operations that use screen memory will be working on this part  of 
memory.  If physical and logical screen memory are the  same,  you 
will also be able to see what happens on the screen.  The function 
returns  a  longword,  which will be $78000 if you have  a  512  K 
machine.

4 getrez

Example: move.w #4,-(sp)
         trap #14
         addq.l #2,sp

The 'getrez' function returns the screen resolution,  which can be 
one of the following values:
         0        Low Resolution (320x200 pixels; 16 colors)
         1        Medium Resolution (640x200 pixels; 4 colors)
         2        High Resolution (640x400 pixels; 2 colors)

5 setscreen

Example: move.w res,-(sp)
         move.l physaddr,-(sp)
         move.l logaddr,-(sp)
         move.w #5,-(sp)
         trap #14
         add.l #12,sp

This function allows the user to change the screen parameters that 
could  be  read  using  one of  the  three  functions  we  already 
mentioned before. If one of those parameters should not be set, it 
is necessary to enter a negative value. The parameters will be set 
on the next Vertical Blank Interrupt (VBL).

6 setpalette

Example: move.l paletpntr,-(sp)
         move.w #6,-(sp)
         trap #14
         addq.l #6,sp

This function enables you to load a new color  palette.  Therefore 
you  must give a pointer to a table with color values (16  values, 
all words).  The address of the pointer should be even. The colors 
will  be loaded at the next VBL.  If you know how to  handle  this 
routine quite well,  it's possible to simulate more then 16 colors 
on  your screen at one time.  I think Magnetic Scrolls  used  this 
trick on the first picture of "The Pawn" (which is said to use 500 
colors!).  Examples:  $000 is black,  $777 is white,  $700 is red, 
$070 is green and $007 is blue.

7 setcolor

Example: move.w color,-(sp)
         move.w colnumber,-(sp)
         move.w #7,-(sp)
         trap #14
         addq.l #6,sp

This function makes it possible to change just one color at a time 
(just  like  "Press  '1' or '2' to Start"  with  Michtron's  "Time 
Bandit V2.0").
'colnumber' is the number of the color that should be changed.
'color' is the new value of that color, ranging from $000-$777.
If you enter -1 as color,  you will simply get the old color value 
of the color with the number 'colnumber'.

8 floprd

Example: move.w count,-(sp)
         move.w side,-(sp)
         move.w track,-(sp)
         move.w sector,-(sp)
         move.w device,-(sp)
         clr.l -(sp)
         move.l buffer,-(sp)
         move.w #8,-(sp)
         trap #14
         add.l #20,sp

This function enables the reading of one or several sectors from a 
disk.

'count' is the number of tracks that should be read  sequentially. 
Values  between 1 and 9 are normally possible (number  of  sectors 
per track),  but with maxi-formatted disks I see no reason why one 
shouldn't use '10' as well.
'side' selects the side that should be read from. 0 is side A, and 
1 is side B.  On single sided floppy-drives (like the one I have - 
snif, snif!) you can only use 0 - side A.
'track'  specifies the number of the track the sectors  should  be 
read from. This value can vary; it depends on the number of tracks 
per side.  Mostly,  this will be 80 (so the value can be from 0 to 
79),  but is can also be 40,  83,  or even another value (that  is 
because  of  the flexibility of the Disk format for  Atari  system 
disk drives).
'sector'  is the sector number of the sector that should  be  read 
first.  Normally, this can be from 0-9, but sometimes it can be 10 
as well (on maxi-formatted disks).
'device'  is  the number of the device the information  should  be 
read from. This can be 0 (for drive A) or 1 (for drive B).
The  line 'clr.l -(sp)' just puts an empty longword on the  stack. 
This is unused.
'buffer'  is the address of a piece of memory where the data  read 
should be put.  This should always be at a longword-boundary,  and 
there  should  be enough room to put to info in (512 bytes  x  the 
number of sectors you read).
The 'floprd' function returns an error code. This can be:
         0        OK
        -1        General Error
        -2        Drive not Ready
        -3        Unknown command
        -4        CRC Error
        -5        Bad Request
        -6        Seek Error
        -7        Unknown Media
        -8        Sector not Found
        -9        (No Paper)
       -10        Write Error
       -11        Read Error
       -12        General error
       -13        Disk is Writeprotected
       -14        Disk has been Changed
       -15        Unknown Device
       -16        Bad Sector
       -17        Put Disk in Drive

9 flopwr

Example: move.w count,-(sp)
         move.w side,-(sp)
         move.w track,-(sp)
         move.w sector,-(sp)
         move.w device,-(sp)
         clr.l -(sp)
         move.l buffer,-(sp)
         move.w #9,-(sp)
         trap #14
         add.l #20,sp

This function enables the user to write one or several sectors  to 
a  disk.  The parameters have the same meaning as those listed  at 
function  8 (floprd).  This function also returns an  error  code, 
which can also be one of those listed at the 'floprd' function.

10 flopfmt

Example: move.w virgin.-(sp)
         move.l magic,-(sp)
         move.w interleave,-(sp)
         move.w side,-(sp)
         move.w track,-(sp)
         move.w sectra,-(sp)
         move.w device,-(sp)
         clr.l -(sp)
         move.l buffer,-(sp)
         move.w #10,-(sp)
         trap #14
         add.l #26,sp

This routine can format one single track.  The parameters have the 
following meaning:
'virgin'  is  the value with which all sectors  of  the  specified 
track  will  be filled when formatted.  $E5E5 is mostly  used  for 
this.  You  must  look  out not to use $F as value  for  the  high 
nibble!

'magic'  is the magic number (the ST is crawling with them!)  that 
has  to  accompany the formatting.  In this case,  it  has  to  be 
$87654321 (I suppose the people at Atari had a lack of originality 
when  they used introduced this magic number;  some other  'magic' 
numbers are birth-dates, BIOS launch-dates, etc.).
'interleave'  specified the sequence in which sectors are  written 
to disk. Normally this is 1. I think the guy who designed Copystar 
at RDS software used this variable for his "fast-load disk"-bit.
'side'  determines  the side on which the track  is  located  that 
should be formatted. Ofcourse, one cannot select another value for 
this than 0 if one has a single sided disk drive.
'track'  is  the  number of the track that  should  be  formatted. 
Normally,  this will be 0-79,  but it can also be a higher  number 
(even upto 83!).  Watch out:  if you want the track to be used for 
program storage,  the boot sector must 'know' that there are  such 
high  tracks!  Also,  not all disk drives are able to read  tracks 
above number 79.  As a part of copy protection,  this function can 
cause quite a lot of grey hairs with certain people.
'sectra'  is the number of sectors on that  track.  Unless  you're 
designing  some hot-shot copy protection,  this should be  of  the 
same  value that all other tracks are formatted  with.  This  will 
normally be from 0 to 9, but it can also be 10.
'device'  is the device number (have a look at 'floprd' for  whihc 
numbers you may use).
'clr.l -(sp)' is here used to put an empty - unused - longword  on 
the stack,  just like its counterpart in the function 'floprd' and 
'flopwr'.
'buffer'  for  the complete trackdata.  If you use 9  sectors  per 
track, this must be at least 8 Kb in size.
The function returns an error code.  If it is -16,  bad sector, it 
means that the data couldn't be properly verified.  In that  case, 
the buffer will contain a list of bad sectors (seperated by  '0'). 
You  can try to format the track again,  or you can mark  the  bad 
sectors.
Just like the 'floprd' and 'flopwr' functions,  you can check  for 
an error with the following sequence:
         tst d0
         bmi error
         ....Rest of the program
   error ....Error handle routine

11 unused

12 midiws


Example: move.l pntr,-(sp)
         move.w count,-(sp)
         move.w #12,-(sp)
         trap #14
         addq.l #8,sp

With this function, it is possible to send a string of data to the 
MIDI OUT port.
'pntr' is the pointer to the memory address on which the string is 
located.
'count' is the number of bytes that should be sent -1.  So if  you 
want to send 12 bytes, that value should be 11.

13 mfpint

Example: move.l vector,-(sp)
         move.w number,-(sp)
         move.w #13,-(sp)
         trap #14
         addq.l #8,sp
This  function is used to initialize an Interrupt routine  in  the 
MFP.
'number' is the number of the MFP-Interrupt,  which can be from  0 
to 15.
'vector'  is the address on which the vector that belongs to  that 
Interrupt routine is located.

14 iorec

Example: move.w device,-(sp)
         move.w #14,-(sp)
         trap #14
         addq.l #4,sp

This routine is there to get the pointer to a buffer-data-line for 
an input device. The following input devices may be selected:
         0        RS232
         1        Keyboard
         2        MIDI

The buffer-data-line is built up as follows:
         long     ibuf       Pointer to input buffer
         int      ibufsize   Size of input buffer
         int      ibufhd     Head Index
         int      ibuftl     Tail Index
         int      ibuflow    Low water Mark
         int      ibufhi     High water Mark
For more specific information, I am afraid I must tell you to have 
a  look  at pages 200 and 201 of Data Becker's  "ST  Intern".  The 
specifications  and  examples mentioned there might  make  working 
with this XBIOS function more clear, whereas talking about them in 
this article would be too much of a hassle.

15 rsconf

Example: move.w scr,-(sp)
         move.w tsr,-(sp)
         move.w rsr,-(sp)
         move.w ucr,-(sp)
         move.w ctrl,-(sp)
         move.w baud,-(sp)
         move.w #15,-(sp)
         trap #14
         add.l #14,sp

This  XBIOS  function  configurates  the  RS232   Interface.   The 
parameters thereby have the following meaning:
'scr' is the Synchronous Character Register in the MFP.
'tsr' is the Transmitter Status Register in the MFP.
'rsr' is the Receiver Status Register in the MFP.
'ucr' is the USART Control Register in the MFP.
'ctrl' is a communication-parameter.
'baud' is the baudrate.

Whenever a parameter turns out to be -1,  the old value is kept on 
the MFP 68901.  You should have a look at some documentation about 
the MFP 68901 processor for the meaning of the MFP registers.
'ctrl' is used to specify the Handshake-Mode:

         0        No Handshake (that is default on power-up)
         1        XON/XOFF
         2        RTS/CTS
         3        XON/XOFF and RTS/CTS (not very useful)

'baud' can have one of the following values:

         0        19200
         1         9600
         2         4800
         3         3600
         4         2400
         5         2000
         6         1800
         7         1200
         8          600
         9          300
        10          200
        11          150
        12          134
        13          110
        14           75
        15           50

Disclaimer
The text of the articles is identical to the originals like they appeared in old ST NEWS issues. Please take into consideration that the author(s) was (were) a lot younger and less responsible back then. So bad jokes, bad English, youthful arrogance, insults, bravura, over-crediting and tastelessness should be taken with at least a grain of salt. Any contact and/or payment information, as well as deadlines/release dates of any kind should be regarded as outdated. Due to the fact that these pages are not actually contained in an Atari executable here, references to scroll texts, featured demo screens and hidden articles may also be irrelevant.