xBIOS Documentation BETA DOCUMENT: The accuracy of this document is not guaranteed. Use with care!
Document Version: 0.4.0 Published on: Monday 11th January 2016 Authors: Krzysztof Dudek - “XXL” - Code examples, xBIOS author and lots of input. Steve Nicklin - “snicklin” - Main document.
Known Issues with Document: Incomplete, not enough examples. Google translation of code examples needs refining. Incomplete Initial version. Only a handful of peer reviews conducted. Some code examples use V3 code. May or may not work with v4.3
Likely Priorities for Next Major Version of Document: Fill out with content. Correct errors and English. Mention more about the xBIOS menu. Mention using other devices. Mention how to switch off / not use Atari I/O. Add a “directories” usage example. Formatting needs improving for some code examples.
Document Scope: This document is only intended to cover xBIOS versions 4.1 and above. Code examples will use MADS syntax/formatting.
Disclaimer: The author of this document is not an expert in xBIOS. This document is being used to collate information for personal knowledge gain. Errors may occur and not all supplied routines have been tested by the author. Technical queries should be addressed to Krzysztof and feedback given to Steve. This document is intended to represent the latest version of xBIOS, which is currently v4.3. It is however appreciated that a lot of information in the document may have been provided for older versions of xBIOS, but in all likeliness, they will still work with the latest xBIOS.
Software download location and original documentation: http://xxl.atari.pl
Document Amendments with Feedback Person Listed v0.2.0 : Heaven/TQA@AA : Added xBOOT section. v0.3.0 : Kyle22@AA : Extension of ‘Practical Usage’ section. v0.3.1 : Kyle22@AA, Heaven/TQA@AA : Update code start advice. v0.3.2 : MaPa@AA : Re-update code start advice with additional information. v.0.4.0 : XXL@AA: Practical usage info and directory size information.
xBIOS Overview
xBIOS is like a programmers version of DOS. With it you can easily access files from your programs without using Atari DOS. It is smaller than DOS and therefore saves memory in your programs. You can even run programs from as low as $0200, however $0800 or $2000 are more common.
General Notes
In this section you will find some general notes about xBIOS and how it functions.
Autorun To allow an executable to auto run on bootup, have it named as “XAUTORUN”. If no such file exists on the disk, the xBIOS loader menu will appear.
Filename Format The filenames are in 8.3 format but without the dot. FIlenames are padded out to 11 characters and are converted to uppercase. Therefore, “file.txt” will become: ‘FILE TXT’ 4 letters, 4 spaces and and a 3 character extension xBIOS is case insensitive.
xBIOS Limitations
New files cannot be created. Existing files cannot be extended in length. New directories cannot be created.
Default Memory Layout
$0000-$00FF Free $0200-$06FF Free $0700-$07FF xBIOS I/O buffer $0800-$0BFF xBIOS $0C00-$CFFF Free $D000-$D7FF Atari H/W $D800-$FFFF Free
Disk Images Disk images (.atr files) need to be prepared in advance for xBIOS to work. A disk image is a file which simulates a disk. It will contain 1 or more files which can be used by your programs.
In order to prepare them, an external tool needs to be used.
‘dir2atr’ : http://www.horus.com/~hias/atari A tool for creating an ATR file from a folder.
‘franny’ : http://atariage.com/forums/topic/159325-program-to-add-to-and-extract-files-from-atr/ Allows the additional of individual files to an ATR file.
Practical Usage
In order to have a disk which is usable, a project build system should complete the following steps:
a) Make a copy of the xBIOS.atr file, renaming the new file to something relevant for your project. b) Add all the new files to the file. ‘franny’ and ‘dir2atr’ are good tools for this. Ensure that the program which you want to initially run is named ‘XAUTORUN’.
Example Windows batch file:
mads myProg.asm copy /Y myProg.obx myatr\XAUTORUN dir2atr -md -B xboot.obx myatr.atr myatr pause
xBIOS now also needs adding into the development project which is being created. The following code needs to be pasted into a project:
(Valid for xBIOS v4.3) xBIOS equ $800 xBIOS_VERSION equ xBIOS+$02 xBIOS_RENAME_ENTRY equ xBIOS+$03 xBIOS_LOAD_FILE equ xBIOS+$06 xBIOS_OPEN_FILE equ xBIOS+$09 xBIOS_LOAD_DATA equ xBIOS+$0c xBIOS_WRITE_DATA equ xBIOS+$0f xBIOS_OPEN_CURRENT_DIR equ xBIOS+$12 xBIOS_GET_BYTE equ xBIOS+$15 xBIOS_PUT_BYTE equ xBIOS+$18 xBIOS_FLUSH_BUFFER equ xBIOS+$1b xBIOS_SET_LENGTH equ xBIOS+$1e xBIOS_SET_INIAD equ xBIOS+$21 xBIOS_SET_FILE_OFFSET equ xBIOS+$24 xBIOS_SET_RUNAD equ xBIOS+$27 xBIOS_SET_DEFAULT_DEVICE equ xBIOS+$2a xBIOS_OPEN_DIR equ xBIOS+$2d xBIOS_LOAD_BINARY_FILE equ xBIOS+$30 xBIOS_OPEN_DEFAULT_DIR equ xBIOS+$33 xBIOS_SET_DEVICE equ xBIOS+$36 xBIOS_RELOCATE_BUFFER equ xBIOS+$39 xBIOS_GET_ENTRY equ xBIOS+$3c xBIOS_OPEN_DEFAULT_FILE equ xBIOS+$3f xBIOS_READ_SECTOR equ xBIOS+$42 xBIOS_FIND_ENTRY equ xBIOS+$45 xBIOS_SET_BUFFER_SIZE equ xBIOS+$48
xDIRSIZE equ xBIOS+$3e5 ; current directory size in sectors (1 byte) xSPEED equ xBIOS+$3e6 ; STANDARD SPEED (1 byte) xHSPEED equ xBIOS+$3e7 ; ULTRA SPEED (1 byte) xIRQEN equ xBIOS+$3e8 ; User IRQ (1 byte) xAUDCTL equ xBIOS+$3e9 ; AUDCTL xFILE equ xBIOS+$3ea ; File handle (2 bytes) xDIR equ xBIOS+$3ec ; Root directory handle (2 bytes) xIOV equ xBIOS+$3ee ; I/O module entry (2 bytes) xBUFFERH equ xBIOS+$3f0 ; Buffer adr hi byte (1 byte) xBUFSIZE equ xBIOS+$3f1 ; Buffer size lo byte $100-SIZE (1 byte) xDAUX3 equ xBIOS+$3f2 ; Buffer offset (1 byte) xSEGMENT equ xBIOS+$3f3 ; Bytes to go in binary file segment (2 bytes) xNOTE equ xBIOS+$3f5 ; File pointer (3 bytes) xDEVICE equ xBIOS+$3fc ; Device ID xDCMD equ xBIOS+$3fd ; CMD (1 byte) xDAUX1 equ xBIOS+$3fe ; Sector lo byte (1 byte) xDAUX2 equ xBIOS+$3ff ; Sector hi byte (1 byte)
Each entry in this jump table specifies where in memory that the code for each function resides. Replace the $xxxx at the start with a starting address. $0800 should a be safe address for all purposes. If you ever wish to start from a different address, simply change the value for ‘xBIOS’.
Now that the above exists, the following examples can be used to access files in the ATR file.
Examples
Here are some of the examples taken from http://xxl.atari.pl and other online sources, but with a few extra / modified comments in English.
xBIOS_RENAME_ENTRY This function allows you to rename a file or directory. There is no limit to the characters used in the filename apart from that they must fit a case insensitive “8.3” format without the dot. If your filename is not 8 characters long, pad it out with spaces.
ldy <fname ldx >fname JSR xBIOS_RENAME_ENTRY fname .byte c'FILENAMESRC '; 11 char ATASCII (8.3 without the dot, space padded) .byte c'FILENAMEDST '; 11 char ATASCII (8.3 without the dot, space padded)
xBIOS_LOAD_FILE Load and run the file, INIT and RUN headers are supported. Boot Loader has an analogous function xBOOT_LOAD_FILE. In the case of the boot loader if the file does not have a defined block RUN will be launched from the beginning of the first block.
ldy <fname ldx >fname JSR xBIOS_LOAD_FILE fname .byte c'MYFILE COM'; 11 characters ATASCII (8.3 without the dot, space padded)
xBIOS_OPEN_FILE Open a file in order to carry out subsequent I / O operations.
ldy <fname ldx >fname JSR xBIOS_OPEN_FILE fname .byte c'MYFILE COM'; 11 characters ATASCII (8.3 without the dot, space padded)
xBIOS_LOAD_DATA Load data from file to a specified address. You can set the file offset (FILE_OFFSET) and the amount of data to be loaded (SET_LENGTH). If you do not define these values, data will be loaded from the current position of the file pointer to the end of the file. If you want to load a binary file using the headers defined in it or use the functions xBIOS_BINARY_LOAD or xBIOS_LOAD_FILE. ldy <dest ldx >dest JSR xBIOS_LOAD_DATA
xBIOS_WRITE_DATA Data starting from the given address in the memory, save to a file, you can set the file pointer offset current (FILE_OFFSET) and the amount of data to be saved (SET_LENGTH). If you do not define these values in the file are stored data from the current file position to the end of the file. ldy <src ldx >src JSR xBIOS_WRITE_DATA
xBIOS_OPEN_CURRENT_DIR Opens the current directory. JSR xBIOS_OPEN_CURRENT_DIR
xBIOS_GET_BYTE The next byte of an open file is loaded into the register A (accumulator). JSR xBIOS_GET_BYTE
xBIOS_PUT_BYTE The byte value in the accumulator is written to a file at it’s current pointer location. lda BYTE JSR xBIOS_PUT_BYTE
xBIOS_FLUSH_BUFFER All write operations are cached, use this to flush the buffer to the current file. JSR xBIOS_FLUSH_BUFFER
xBIOS_SET_LENGTH Defines the amount of data processed while reading or writing. If your OPEN_FILE value is not defined this operation will be carried out until the end of the file. ldy <len ldx >len JSR xBIOS_SET_LENGTH
xBIOS_SET_INIAD Allows you to change the vector location INITAD ($ 2E2) loaded binary files.
ldy <addr ldx >addr JSR xBIOS_SET_INIAD
xBIOS_SET_FILE_OFFSET Sets the current position of the read / write file on a value stored in the A, X, Y. This item is calculated relative to the beginning of the file. Number of byte that will be read or written. In DOS operation is called POINT. ldy <pos ldx >pos lda ^pos JSR xBIOS_SET_FILE_OFFSET
xBIOS_SET_RUNAD Allows you to change the vector location RUNAD ($ 2E0) loaded binary files. ldy <addr ldx >addr JSR xBIOS_SET_RUNAD
xBIOS_SET_DEFAULT_DEVICE Restores the standard I / O controller external device. JSR xBIOS_SET_DEFAULT_DEVICE
xBIOS_OPEN_DIR Allows you to change the current directory. ldy <fname ldx >fname JSR xBIOS_OPEN_DIR
Note that the directory cannot be created by xBIOS and therefore must be created with an external tool such as ‘franny’. xBIOS_LOAD_BINARY_FILE Load and run the binary file from the current position of the read / write. INIT and RUN headers are supported. JSR xBIOS_LOAD_BINARY_FILE
xBIOS_OPEN_DEFAULT_DIR Opens the default directory. JSR xBIOS_OPEN_DEFAULT_DIR
xBIOS_SET_DEVICE Change the I / O controller external device. ldy <dev ldx >dev JSR xBIOS_SET_DEVICE
xBIOS_RELOCATE_BUFFER Change address I / O buffer. If before the call to set the marker C = 1, the relocation can be carried out even during I / O. The data will not be lost. If the marker before calling C = 0, buffer contents will not be copied to a new location. ldx >buffer JSR xBIOS_RELOCATE_BUFFER
xBIOS_GET_ENTRY Gets another entry in the directory. In the registry X returns the index to the filename or folder (byte of buffer address is stored in the variable xBUFFERH) A registry is transmitted status byte entry. C is set to mark the end of the directory. JSR xBIOS_GET_ENTRY
xBIOS_OPEN_DEFAULT_FILE To open the default file. The function does not search the directory file handle is taken from the variable Xfile. JSR xBIOS_OPEN_DEFAULT_FILE
xBIOS_READ_SECTOR Load a sector into a buffer. lda >sector ; High byte of the sector number ldy <sector ; Low byte of the sector number JSR xBIOS_READ_SECTOR
xBIOS_FIND_ENTRY Function allows you to find the specified directory entry. In the registry X returns the index to the filename or folder (byte of buffer address is stored in the variable xBUFFERH). A registry is transmitted status byte entry. Set marker C is an entry not found. ldy <fname ldx >fname JSR xBIOS_FIND_ENTRY
xBIOS_SET_BUFFER_SIZE Feature allows you to set the buffer size for I / O operations. Buffer Size - byte - is also stored in the variable xBUFSIZE. lda # $ 100-SIZE JSR xBIOS_SET_BUFFER_SIZE
Counters During I/O Please note that this example originates from xBios v3 FORMATTING requires cleanup xIRQEN equ xBIOS+$3ea ; User IRQ (1 byte) xSEGMENT equ xBIOS+$3f4 ; Bytes to go in binary file segment (2 bytes) xNOTE equ xBIOS+$3f6 ; File pointer (3 bytes)
PUPBT1 equ $033D ;power-up validation byte 1
icl 'atarihw.ah'
opt h+o+l+
org $c00 start_sio sei lda #$00 sta nmien sta irqen sta xIRQEN sta dmactl lda #$fe sta portb lda <MyNMI sta nmiv lda >MyNMI sta nmiv+1 lda <mydlist sta dlistl lda >mydlist sta dlisth jsr xBIOS_SET_DEFAULT_DEVICE ; SIO drive ldx >RESETV ldy <RESETV jmp xBIOS_SET_RUNAD ; new runad vector ini start_sio
org RESETV .word run_adr ; RUN
org PUPBT1 .byte d'xxl' ; let the RESET key works as RESET key
org $0000
run_adr lda #$74 sta colbak _stop jmp _stop ; endless loop
mydlist :12 .byte $70 .byte $46,<counter,>counter .byte $06 .byte $41,<mydlist,>mydlist counter .byte d'SEGMENT: ' .byte d'FILE OFFSET: '
start sei ldx #3 ldy #0 @ inc PORTB lda $e000,y _csrc equ *-1 dec PORTB sta (_csrc-1),y _cdst equ *-1 dey bne @- inc _csrc dex bpl @- @ lda vcount bne @- lda #$22 sta dmactl lda #$40 sta nmien rts MyNMI sta nmiA sty nmiY
inc licz lda #0 licz equ *-1 lsr @ bcc secondnmi firstnmi ldy #16 lda xSEGMENT+1 jsr puthex lda xSEGMENT jsr puthex jmp endnmi secondnmi ldy #20+14 lda xNOTE+2 jsr puthex lda xNOTE+1 jsr puthex lda xNOTE jsr puthex
endnmi lda #0 nmiA equ *-1 ldy #0 nmiY equ *-1 rti
puthex pha lsr @ lsr @ lsr @ lsr @ jsr nibble pla and #$0f nibble cmp #$0a sed adc #$10 cld sta counter,y iny rts ini start
org $0c00 :$c300 .byte $ff
Playing Music During I/O Please note this example originates from xBios v3 Formatting requires cleanup opt h+o+l+
org PUPBT1 .byte d'xxl' ; let the RESET key works as RESET key
org $c00 start_sio sei lda #$00 sta nmien sta irqen sta xIRQEN sta dmactl lda #$fe sta portb lda <MyNMI sta nmiv lda >MyNMI sta nmiv+1 lda #$40 sta nmien jmp xBIOS_SET_DEFAULT_DEVICE ; SIO drive
MyNMI sta vbisaveA+1 stx vbisaveX+1 speed lda #0 bne wp loadpat ldx #0 lda pat,x bmi pass asl @ asl @ asl @ asl @ sta wp+1 pass inx lda #$3f sax loadpat+1 wp ldx #0 lda ins,x sta audc1 lda frq,x sta audf1 inc wp+1 dec speed+1 bpl pass2 lda #5 sta speed+1 wp1 lda #$20 sta pass2+1 eor #$60 sta wp1+1 pass2 ldx #0 lda ins,x sta audc2 inc pass2+1
vbisaveA lda #0 vbisaveX ldx #0 rti
ins .byte $0F,$AF,$AC,$A7,$A2,$00,$04,$A3 .byte $22,$21,$A1,$00,$00,$00,$00,$00 .byte $AF,$AF,$09,$07,$05,$04,$04,$03 .byte $03,$03,$02,$02,$02,$01,$01,$00 .byte $87,$84,$83,$82,$81,$00,$00,$00 .byte $00,$00,$00,$00,$00,$00,$00,$00 .byte $84,$84,$84,$84,$84,$84,$83,$83 .byte $83,$83,$82,$82,$81,$81,$00,$00 .byte $83,$82,$81,$81,$81,$00,$00,$00 .byte $00,$00,$00,$00,$00,$00,$00,$00
frq .byte $04,$C0,$D0,$E0,$F0,$00,$04,$C0 .byte $D0,$E0,$F0,$00,$00,$00,$00,$00 .byte $98,$A8,$03,$03,$03,$03,$03,$03 .byte $03,$03,$03,$03,$03,$03,$03,$03 .byte $00,$00,$00,$00,$00,$00,$00,$00 .byte $00,$00,$00,$00,$00,$00,$00,$00 .byte $00,$00,$00,$00,$00,$00,$00,$00 .byte $00,$00,$00,$00,$00,$00,$00,$00
pat .byte $00,$80,$00,$80,$01,$80,$00,$00 .byte $80,$00,$00,$80,$01,$80,$03,$80 .byte $00,$80,$00,$80,$01,$80,$02,$02 .byte $00,$80,$01,$01,$80,$00,$03,$80 .byte $00,$80,$00,$80,$01,$80,$00,$00 .byte $80,$00,$00,$80,$01,$80,$03,$80 .byte $00,$00,$00,$80,$01,$00,$00,$80 .byte $00,$80,$01,$01,$80,$00,$01,$00
ini start_sio
org $1000 :$C000 .byte $ff org $D800 :$2700 .byte $ff
run_adr lda #$74 sta colbak _stop jmp _stop ; endless loop
run run_adr
Indexed Data within File - LZ4 Graphics De/compression Please note this example originates from xBios v3 Formatting requires cleanup xFILE equ xBIOS+$3ec ; file handle xDAUX3 equ xBIOS+$3f3 ; buffer offset if AtariDOS FS xDAUX2 equ xBIOS+$3fd ; sektor hi if AtariDOS FS xDAUX1 equ xBIOS+$3fe ; sektor lo if AtariDOS FS PUPBT1 equ $033D ;power-up validation byte 1 myscr equ $8150 myscr1 equ $9000 colour equ myscr+$1e01 fhandle equ $80
org PUPBT1 .byte d'xxl' ; let the RESET key works as RESET key
org $c00
Mydlist .byte $70,$70,$70 .byte $4e,a(myscr) :93 .byte $0e .byte $4e,a(myscr1) :97 .byte $0e .byte $41,a(Mydlist)
myinit lda #$00 sta DMACTLS lda <Mydlist sta DLISTLS lda >Mydlist sta DLISTHS lda #%00100010 sta DMACTLS
load_index ldx load_gfx+1 lda xDAUX1 sta fhandle,x lda xDAUX2 sta fhandle+1,x lda xDAUX3 sta fhandle+2,x cpx #$0c bne skip lda #$100-(ldgfx+2-load_gfx) sta ldgfx+1 bne skip load_gfx ldx #0 lda fhandle,x sta xFILE lda fhandle+1,x sta xFILE+1 jsr xBIOS_OPEN_DEFAULT_FILE ldx load_gfx+1 lda fhandle+2,x sta xDAUX3 skip lda #%1111 sbx #$100-$04 sax load_gfx+1 lda <myscr sta dest lda >myscr sta dest+1 jsr unlz4 ldx #$02 @ lda colour,x sta COLPF0S,x dex bpl @- ldgfx bmi load_index
unlz4 icl 'unlz4.asm'
ini myinit
opt h- ins 'DRUID.LZ4',$0b,.FILESIZE 'DRUID.LZ4'-$0b-$06 ins 'LOADING.LZ4',$0b,.FILESIZE 'LOADING.LZ4'-$0b-$06 ins 'SHPOON2.LZ4',$0b,.FILESIZE 'SHPOON2.LZ4'-$0b-$06 ins 'POTATERR.LZ4',$0b,.FILESIZE 'POTATERR.LZ4'-$0b-$06
Use of High Speed Devices When you first load xBIOS, you can complete a check to see if your disk drive is ultraspeed (see next example). If so, save a value to xHSPEED. When loading data, copy the value of xHSPEED to xSPEED and use the following code:
lda xHSPEED bmi no_hispeed sta xSPEED
This works in conjunction with: "jsr xBIOS_SET_DEFAULT_DEVICE" If you are using the AtariOS I/O module, speed control is not possible. Detecting High Speed Devices Needs clean-up If you want to detect if the user’s disk drive has high speed capabilities, you can detect it’s high speed status using this code. xBIOS_SET_DEFAULT_DEVICE equ xBIOS+$2A xBUFSIZE equ xBIOS+$3f1 ; Buffer size lo byte $100-SIZE (1 byte) xDEVICE equ xBIOS+$3fc ; Device ID xIOV equ xBIOS+$3ee ; I/O module entry (2 bytes) xBSIO jmp (xIOV) start jsr xBIOS_SET_DEFAULT_DEVICE ; I want to use xB SIO I/O lda #$100-$01 ; set buffer size sta xBUFSIZE lda #'1' ; AtariOS device '1' = DOS device D1: sta xDEVICE ; you can use '2', '3' and so for D2: D3: ... ldx #$3F ; set command GET HI SPEED FROM DRIVE jsr xBSIO bcs DRIVE_HAS_NO_HIGH_SPEED_FUNCTIONS lda $7ff ; get HiSpeedIndex byte from buffer ; (xBUFSIZE = lo byte,xBUFFERH = hi byte)
Remember to preserve old xBUFSIZE and xDEVICE values if these are required later in your code. Using Alternative Disk Drives If you are using disk drives other than the default D1:, you can save values into xDEVICE in order to refer to the other disk drives. xDEVICE equ xBIOS+$3fc ; Device ID
lda #2 ; Use disk drive number 2 sta xDEVICE
Varying Directory Sizes - Needs checking and cleaning up - xBIOS can handle directories of varying sizes as per the directories of different versions of DOS. ‘xDIRSIZE’ (xBIOS+$3e5 in xBIOS 4.3) is used as a read only way to find out the current directory size in sectors. It is one byte in length and is read-only. A directory entry within Atari DOS 2 / MyDOS and similar DOS’s uses up 16 bytes and looks like this: .byte status ; Byte 1 .word size; - in standard directories always $08 ; Bytes 2 and 3 .word first_sector ; Bytes 4 and 5 .byte c'FILENAMEEXT' ; Byte 6 to 16
A standard directory uses 8 sectors (size = $08) which means 8 sectors * 8 entry = 64 max. Top DOS / Bibo DOS with sector sizes of 256 bytes may looks like 8 sectors * 16 entry = 128 maximum. You can make subdirectories of differing sizes eg. size=$02 (16/32 entry) or size = $ff (2040 / 4080 entry). There is no tool to make different size catalogues, if at any time such a tool appears, xBIOS will handle it. xBOOT This isn’t xBIOS as such but a related loader mechanism which is simpler than xBIOS. Simply download xBOOT from http://xxl.atari.pl and add it to your disk using an external tool such as ‘franny’. Name the first file to load ‘AUTORUN’. This will auto-load. Within this executable, have the following code to load the next file in a chain. xBOOT_LOAD_FILE equ $5f1
ldy <fname ldx >fname jmp xBOOT_LOAD_FILE fname .byte c'NEXTPARTCOM' ; 11 chars ATASCII