Programming guidelines I. Intro(duction) Yes, don't smile... There are such things as general programming guidelines for Atari XL/XE software. Of course, you (programmer) aren't obligated to keep in mind all of them, or, furthermore, even any of them... But they've been collected to help you to write programs those are supposed to run on as much Ataris as possible. Remember, that people rather rarely run the same configuration as you do. Their computers have various hardware upgrades, as various RAM expansions, various types of disk drives (not always serial ones), hard drives, different processors, additional custom chips, different types of operating system ROM kernels. They also like to use their favourite DOSes and favourite disk filesystems. So, it would be the best, if you took these into consideration writing a program, especially if it is supposed to be a piece of (possibly useful) system or application software. II. Legal vs. illegal system calls Don't use illegal system calls. The ROM kernel provides a set of system calls, RAM- and ROM vectors to support you with all necessary functions you could exspect. You can't save much processing power or memory space calling the kernel illegally, it is also very doubtful if you could find any useful kernel function that would be unreachable legal way. At the other side, if you use illegal kernel functions, it is more likely your program will fail on a reasonable number of existing computers. There are several revisions of ROM kernel and some of them differ internal addresses. Only some of these addresses are fixed and are the same in all kernel revisions. That is just because they've been proved by Atari Corp. as legal. Here's the list of legal addresses for using XL OS functions: a) Character sets $CC00 - CHR2 - International Character Set (charset 2) $E000 - CHR1 - Standard Character Set (charset 1) Charset 2 does not exist in Atari OS revision A (400/800 series). b) Floating Point Library These addresses are available all the time with except for the exact time when data are being transferred from or to a hard disk drive or another parallel bus device. $D800 - AFP - ASCII to Floating Point conversion $D8E6 - FASC - Floating Point to ASCII conversion $D9AA - IFP - Integer to Floating Point conversion $D9D2 - FPI - Floating Point to Integer conversion $DA60 - FSUB - Floating Point Subtraction $DA66 - FADD - Floating Point Addition $DADB - FMUL - Floating Point Multiplication $DB28 - FDIV - Floating Point Division $DD28 - FMOV12 - Move FR1 to FR2 $DD34 - FMOV0E - Move FR0 to FRE $DD89 - FLD0R - Load FR0 using registers $DD8D - FLD0P - Load FR0 using pointer $DD98 - FLD1R - Load FR1 using registers $DD9C - FLD1P - Load FR1 using pointer $DDA7 - FST0R - Store FR0 using registers $DDAB - FST0P - Store FR0 using pointer $DDB6 - FMOV01 - Move FR0 to FR1 $DDC0 - EXP - Exponentation $DDCC - EXP10 - Decimal Exponentation $DECD - LOG - Natural logarithm $DED1 - LOG10 - Decimal logarithm c) Parallel bus device ROM These addresses are not available until the system does a request of a data transfer from/to a hard disk drive or another parallel bus device. They're always invisible for application software, so you may never be interested on them unless you're going to write a ROM driver for a parallel bus device. WARNING! This 2k ROM may appear here EVEN IF YOU HAVE DISABLED the ROM kernel (see below: Memory usage limitations). $D803 - DEVID1 - Device Identifier 1 (byte) $D805 - PDIOR - Parallel Device I/O Routine (entry point) $D808 - PDVINT - Parallel Device Interrupt Service Routine (entry point) $D80B - DEVID2 - Device Identifier 2 (byte) $D80D - PDVOPNV - Parallel Device Open Vector (word pointer) $D80F - PDVCLV - Parallel Device Close Vector (word pointer) $D811 - PDVGBV - Parallel Device Get Byte Vector (word pointer) $D813 - PDVPBV - Parallel Device Put Byte Vector (word pointer) $D815 - PDVSTV - Parallel Device Status Vector (word pointer) $D817 - PDVSPV - Parallel Device Special Vector (word pointer) $D819 - PDVINIT - Parallel Device Initialization (entry point) d) I/O vector table This consists of six subsets containing vectors to the six ROM device drivers. Usage of the first five subsets is allowed, discouraged however, because there's no chance for soft-loaded device drivers to intercept them. The sixth subset indirectly points to the PIO vector table within one of parallel bus device ROMs. Using that last you needn't to know where the handler is physically located. The system will do all this for you. $E400 - EDTVEC - Editor (system console) $E410 - SCRVEC - Screen (graphic display driver) $E420 - KBDVEC - Keyboard $E430 - PRTVEC - Printer $E440 - CASVEC - Cassette Recorder $E48F - CALTAB - Parallel Device driver The general scheme of each subset is as follows: +$00 OPENVEC - open the device +$02 CLSVEC - close the device +$04 GETBYT - get byte from the device +$06 PUTBYT - put byte to the device +$08 STATUS - get status +$0A SPECIAL - call special functions +$0C JMPINIT - entry point to the init routine. +$0F - - unused byte e) Jump table Notes: - "initialization" and "enable" jumps are used by the system and PIO ROM drivers at bootup time. - for disk accesses, use JSIOINT rather than JDSKINT (more flexibility) - JTESTST does not enable the Self Test memory (it is a call to $5000) - JLINK/JUNLINK had been provided for use with a PIO device, that hasn't been ever released. $E450 - JDSKINIT - Disk Interface Initialization $E453 - JDSKINT - Disk I/O Interface $E456 - JCIOMAIN - Central I/O $E459 - JSIOINT - Sector I/O Interface $E45C - JSETVBV - Set Vertical Blank Vectors $E45F - JSYSVBL - System VBL Service Routine $E462 - JXITVBL - Exit VBL Service Routine $E465 - JSIOINIT - Sector I/O Initialization $E468 - JSNDENB - I/O Sound Enable $E46B - JNMIEN - NMI Enable $E46E - JCIOINIT - Central I/O Initialization $E471 - JTESTROM - Self Test ROM, system entry. $E474 - JRESETWM - Reset Warm $E477 - JRESETCD - Reset Cold $E47A - JCASRDBL - Cassette Read Block $E47D - JCASOPIN - Cassette Open for Input $E480 - JTESTROM - Self Test ROM, user entry $E483 - JTESTST - Self Test Start $E486 - JNEWDEVC - Install New CIO Device $E489 - JUNLINK - Unlink Linear List Element $E48C - JLINK - Link Linear List Element $E49B - NEWINITC - Parallel device initialization III. Memory usage limitations Atari 130XE has 128k system RAM, 24k system ROM, 2k hardware I/O space. Additionally, 8k ROM cartridge may be present and up to 8 parallel bus device ROMs, 2k each. This makes up to 182272 (178k) different memory locations in a system with 64k address space! This condition enforces memory banking, which means that only a part of these resources are present and available at a time. So... a) It is strongly discouraged to keep interrupt routines in some RAM areas, where bank switching may occur, especially because modern and more sophisticated system software may perform such switches at any time, completely out of the main application's control. If the main application keeps interrupt service routines there, a very bad crash (tm) will occur. Area Switch condition ---- ---------------- $4000-$7FFF any disk access; it may be a ramdisk or a DOS keeping its code in the bank select RAM. $A000-$BFFF any DOS function; SpartaDOS X will switch its ROM here to access CAR: device and ICD Disk Formatter. $D800-$DFFF any external device access; PIO ROM may appear here while talking with the device. b) It is strongly discouraged to use some RAM locations to keep data for application software. For better compatibility between various types of system software, it is better to keep the following scheme: Area Used by ---- ------- $0000-$007F ROM kernel, DOS, resident system extensions $0080-$00D3 Application software $00D4-$00FF Floating Point Package (if used) $0100-$01FF CPU stack $0200-$047F ROM kernel, DOS, resident system extensions $0480-$057F DOS (optionally) $0580-$05FF ROM kernel, DOS $0600-$06FF Application software $0700-(MEMLO-1) DOS, resident system extensions Everything else (i.e. from the location pointed to by MEMLO to the location pointed to by MEMTOP and the RAM shadowing ROM kernel at $C000-$CFFF/$D800-$FFFF) may be used by application software with limitations specified above. Note that application software may really need only some zero page addresses to keep time critical variables and pointers into. If zero page addressing mode is not needed, data may be kept within the TPA (i.e. the same area where the code is loaded). NOTE: Built-in Atari BASIC interpreter is considered as "application software". c) Lowest TPA address - for software that uses DOS it is assumed, that the MEMLO value is not lower and should never be higher than $2000. - for software that does not use DOS it is assumed that the lowest available TPA address is not lower than $0B00. That last value is provided to avoid conflicts with so called "file loaders" supporting binary file execution in absence of DOS. IV. Illegal CPU instructions. Don't use them. You can never know which day you upgrade to 65c816. Any program containing illegal instructions will fail then. V. PAL/NTSC If your program doesn't really depend on a TV system properties (like Paint 256 is based on some property of PAL), please take care on your program to run on both PAL and NTSC types of Atari. Otherwise, if your program is any useful, you may be sure Americans will try to fix your code. And you don't like anybody "improving" your code, do you? ;) VI. "Unused" hardware registers The area $D000-$D7FF contains four "unused" pages. In fact, some of them are more useful than you could suspect: $D100-$D1FF - reserved for eight parallel I/O devices. Don't use. $D500-$D5FF - reserved for 8k ROM cartridges. Don't use. $D600-$D6FF - free, may be used for various expansions. $D700-$D7FF - free, see below. Due to some property of 6502 CPU (esp. superfluous memory accesses while executing conditional branches), it is strongly discouraged to put any read-write sensitive I/O register at any address higher than $D780. Generally, I/O area must be separated from executable code with at least 128 byte area containing nothing. VII. Disk drives a) PERCOM data This is a block of 12 bytes describing drive's type and its abilities. Meaning is as follows: 0 - number of tracks 1 - seek rate 2 - number of sectors per track, high byte 3 - number of sectors per track, low byte 4 - number of heads 5 - additional information 6 - number of bytes per sector, high byte 7 - number of bytes per sector, low byte 8 - obsolete, always $FF 9 - specific 10 - specific 11 - specific Byte 5 (additional information) contains bits which mean as follows (if set): bit 3 - IDE hard drive bit 2 - double density drive (set also if bit 3 = 1) bit 1 - 8 inch floppy drive (obsolete) There are some exceptions from above rules: - If the disk is a ramdisk or a hard drive partition, the number of tracks is ALWAYS REPORTED AS 1. - the number of sectors per track mean the total number of sectors on the disk then. This number may be the number of sectors + 1 (old Supra bug became standard) or equal to the exact number of existing sectors (some developers ignore stupid standards). It doesn't matter, because DOS doesn't use this last sector at all. - 4th byte contains number of heads for SCSI drives (it should be ignored) or, for IDE drives, the highest byte of total number of sectors. - 8th byte is valid only for old PERCOM drives. - bytes 9, 10 and 11 have values $49, $44, $45 for IDE drives, otherwise $00, $00, $00. b) Don't measure the time your program is loaded or the time a sector can be accessed on the disk. This time may vary on various floppy drives, hard drives or ramdisks. Some floppies rotate at 288 RPM, other at 300 RPM, hard drives at 3600 RPM, ramdisks don't rotate at all ;) Furthermore, this time may depend on a specific interleave (floppies) or on the handler performance (hard drives and ramdisks). c) You may believe or not, but SpartaDOS is quite popular. Additionally, it has a completely different filesystem than AtariDOS clones do. Don't assume, that the directory is at the sector $0169, believe me, DOS will know better - so call the DOS ;)
Last changes: 09 jul 1997
Feel free to contact me for any legal reason!