4 Low level file

entry points

This chapter details the filing system entry points as well as some OSWORD and OSBYTE calls provided by HADFS.

OSFILE

Entry address: &FFDD File and directory information

On entry: A function code On exit: A object type XY pointer to control block XY preserved control block updated

Control block: &00 Address of filename &02 Load address &06 Execution address &0A Length, or start address for SAVE &0E Attributes, or end address for SAVE, or start sector for &FD &12

Functions: &FC Write an object's extra catalogue information from the control block. 02/03 - main account if XY+3 bit 7 is zero 04/05 - auxilary account if XY+5 bit 7 is zero 06/07/08 - modification time 09/10 - creation date 11/12/13 - creation time &FD Read an object's extra catalogue information into the control block. 02/03 - main account 04/05 - auxilary account 06/07/08 - modification time 09/10 - creation date 11/12/13 - creation time if XY+13<&80, otherwise size in sectors 14/15/16/17 - Start sector and drive &FE Verify a file. Unsupported, returns A=&FE. &FF Load a file into memory. If the low byte of the execution address is zero, it loads to the supplied load address, else it loads to the file's own load address. If the filename does not exist, or is a directory, or an execute-only file, or does not have read access, then an error is generated. &00 Save a file. If a file already exists with the same name, it is overwritten. If the file is locked, or a directory exists with the same name, then an error is generated. &01 Write a file's reload address, execution address and attributes. &02 Write a file's reload address. &03 Write a file's execution address. &04 Write a file's attributes. &05 Read object's catalogue information into the control block. &06 Delete object. If the object does not exist, A returned as &00. If the object is locked, or is not owned, then an error is generated. &07 Create an empty file of defined length. Block as for SAVE. &08 Create a directory. If a directory already exists, there is no error. If a file already exists, an error is generated. &09

Object types are a bitmap returned in the A register as: &FF Execute-only file &00 Object not found &01 File found &02 Directory found, the length field holds the amount of disk space that the directory's catalogue takes up. &03 Image file &04 Symbolic link

When reading information on $, then A returns 0 if the specified drive does not exist, or 2 if it does exist. The disk size in bytes is returned at XY+2-5, the disk ID at XY+6-7 and the disk flags at XY+8-9. The date the disk was created is returned in the date field of the attributes.

File attributes are returned in four bytes as follows: Byte &0E bit 7 Private 6 Executable by others 5 Writable by others 4 Readable by others 3 Locked 2 Executable by owner 1 Writable by owner 0 Readable by owner Byte &0F bits 0-4 Date: day of month 5-7 Date: years since 1981, bits 4-6 Byte &10 bits 0-3 Date: month of year 4-7 Date: years since 1981, bits 0-3 Byte &11 bits 0-3 Undefined (zero) 4-7 Undefined (zero)

The default file access of WR/WR is an access byte of &33. A file is executable with *RUN, */, *command if the relevant R or E bit is set. If the relevant R bit is clear then the file can only be executed, it cannot be loaded or opened.

All the calls update the control block with the catalogue information and return the object type in A. If a call is unsupported, then A is returned preserved.

OSARGS

Entry address: &FFDA Attribute of open object

On entry: A function code On exit: A usually preserved X points to zero page location X preserved Y file handle or 0 Y preserved

Functions: Y=0 &FD Return HADFS version*10 in A and version and capability flags in zero page. The flags show what code is available in the HADFS ROM: zp+0, b7: Random access output b3: Time provided b6: Fast OSGBPB b2: *COMPACT and *BACKUP in ROM b5: Full *INSTALL b1: Passwords used b4: Date provided b0: *COPY in ROM zp+1: b7: - b3: - b6: Hard disk supported b2: - b5: 16-bit/24-bit disks b1: Workspace at &0E00/&1000 b4: - b0: Scattered workspace zp+2: BCD version number x of x.yy zp+3: BCD version number yy of x.yy &FE Return last drive used to zero page. &FF Update all files to media, zero page ignored. &00 Return filing system number in A, zero page ignored: 0 No current filing system 12 RAM filing system 1 1200 baud cassette 13 2 300 baud cassette 14 3 ROM filing system 15 4 Disk filing system 16 Harston ADFS 5 Econet filing system 17 6 Teletext/Prestel telesoftware 7 IEEE filing system 29 DOS filing system 8 Acorn ADFS 45 Nexus filing system 9 Host filing system 71 BeebItFS 10 Videodisk filing system 92 LinkFS 11 Coprocessor filing system The filing system number in HADFS can be changed using *OPT 2 to any value between 5 and 16.

&01 Return address of any parameters after a filename to zero page. &02 Return version number in A, zero page ignored. &03 Return libfs number in A, zero page ignored. &04 Read disk space used to zero page. &05 Read disk free space to zero page. &06

Y<>0 &80 Read information about an open file to zero page (unimplemented). &FD Write filing system context from zero page. Y=25 CSD - Currently Selected Directory disk address Y=26 LIB - Current library disk address Y=27 URD - User Root Directory disk address Y=28 USERNUM/OPTFLG/ENABLE Y=29 CURR - current directory in memory &FE Read filing system context to zero page. Y=25 CSD - Currently Selected Directory disk address Y=26 LIB - Current library disk address Y=27 URD - User Root Directory disk address Y=28 USERNUM/OPTFLG/ENABLE Y=29 CURR - current directory in memory &FF Update file on channel Y to media, zero page ignored. &00 Read PTR for channel Y to zero page. &01 Write PTR for channel Y from zero page. If the PTR is moved past the end of the file, the file is extended with zeros* and zero is returned in A. &02 Read EXT for channel Y to zero page. &03 Write EXT for channel Y from zero page. If the length of the file is reduced, the end disappears. If the length is increased, the file is extended* as with &01 and zero is returned in A. &04 Read size allocated to file on channel Y to zero page. &05 Read EOF status of file on channel Y. If PTR=EXT then zero page is set to -1, else zero page is set to 0. &06 Ensure file size of file on channel Y of at least the value in zero page. Actual size allocated is returned in zero page.

Where zero page is ignored X is ignored and so can be left set to anything on entry. *Currently, extending a file does not pad it with zeros. The extra length of file will contain whatever was originally on the disk.

OSBGET

Entry address: &FFD7 Read (get) a byte

On entry: Y channel number On exit: A byte read Y preserved Cy EOF status.

If the byte read is after the end of file, the carry flag is set on exit. After the EOF byte has been read, the next read produces an error.

OSBPUT

Entry address: &FFD4 Write (put) a byte

On entry: A byte to be written On exit: All preserved Y channel number

OSGBPB

Entry address: &FFD1 Read or write multiple bytes

On entry: A function code On exit: A 0 if call supported XY pointer to control block <>0 if unsupported XY preserved control block updated Control block: &00 Channel number/cycle number &01 Data address &05 Number of bytes/filenames to transfer &09 PTR for transfer/directory pointer &0D

Functions: &01 Write bytes to media using new PTR &02 Write bytes to media ignoring new PTR &03 Read bytes from media using new PTR &04 Read bytes from media ignoring new PTR On exit from calls &01 to &04 the 'number of bytes' field holds the number of bytes not transfered. The 'data address' field is updated to point to the next location for data transfer. The PTR for the file is updated by the number of bytes transfered and placed in the 'PTR' field. In functions &01 and &03 the PTR is first set to the supplied value before transfering data. The carry flag is returned set if EOF was met. The EOF-error-flag is reset. &05 Get media title of CSD disk and boot option into data block: &00 length of title (n) &01 title in ASCII characters &01+n startup option &02+n drive number &03+n &06 Get currently selected directory name into data block: &00 length of drive identity (n) &01 ASCII drive identity (drive number) &01+n length of directory name (m) &02+n directory name in ASCII characters &02+n+m ownership: &00 - owner, &FF - public &03+n+m &07 Get current library name into data block: &00 length of drive identity (n) &01 ASCII drive identity (drive number) &01+n length of library name (m) &02+n library name in ASCII characters &02+n+m ownership: &00 - owner, &FF - public &03+n+m &08 Read filenames from current directory into data block: &00 length of filename 1 (n) &01 filename 1 in ASCII characters &01+n length of filename 2 (m) &02+n filename 2 in ASCII characters &02+n+m etc... The first call to function &08 should be made with the directory pointer set to zero. This will read the first filename, and the pointer will be updated so that the next call will read the next filename. On exit, the 'number of filenames' field holds the number of filenames not returned. When no filenames are left, the call returns with the 'number of filenames' left unchanged and the carry flag set.

&09 Reads a null-terminated list of directory entries from the opened directory whose channel number is in XY+0 or the CSD if XY+0 contains zero. The function is called as for OSGBPB 8, but XY+5 returns the number of filenames read. &00 Object name, null terminated xxx next object name &0A Read entries and information from the opened directory whose channel number is in XY+0 or the CSD if XY+0 contains zero. This function is called as for OSGBPB 8, but XY+5 returns the number of filenames read. Each record is a whole multiple of four bytes long: &00 Load address &04 Execution address &08 Length &0C Attributes &10 Object type (1=file, 2=directory) &14 Object name, null terminated xxx next record &0B Read entries and information from the opened directory whose channel number is in XY+0 or the CSD if XY+0 contains zero. This function is called as for OSGBPB 8, but XY+5 returns the number of filenames read. Each record is a whole multiple of four bytes long: &00 Load address &04 Execution address &08 Length &0C Attributes &10 Object type (1=file, 2=directory) &14 Sector start address &18 Centisecond time since 1900 &1D Object name, null terminated xxx next record &0C

OSFIND

Entry address: &FFCE Open or close a file

On entry: A function code On exit: A channel number, or Y channel number for A=0 or 0 if no file opened XY pointer to filename XY preseved If function not supported, A is returned as zero.

Functions: &00 Close the file on channel in Y. If Y=0 then close all files. &4X Open file for input. If no file exists, A is returned as 0. &8X Open file for output. If file already exists, tries to delete it first. If no file exists, a file is created with load and execution addresses set to &FFFFFFFF. &CX Open file for update. If no file exists, A is returned as 0.

The bottom four bits of A control how the file is opened: If b3 is set, returns an error if file not found, instead of zero handle. If b2 is set, error is generated if attempt to open a directory.

File attributes determine how a file can be opened. Directories can be opened for input, but the open channel can only be used for reading information. Trying to do a BGET will close the channel and return an error.

FSCV

Vectored Filing system control

This vector is only called by the operating system, and should not be called directly. This list just shows the calls implemented in HADFS.

Functions: &00 *OPT command. X and Y hold parameters &01 EOF being checked with OSBYTE &7F. On exit, X=&FF if at EOF, X=&00 otherwise. &02 */ command. XY points to the command text. HADFS tries to run the command from the CSD or the LIB. &03 Unrecognised OSCLI. XY points to the command text. HADFS checks the command against its own commands, then tries to run it from disk as with function &02. &04 *RUN command. XY points to filename. HADFS tries to run this from the CSD only. &05 *CAT command. XY points to any pathname. &06 A new filing system is about to take over. This call is generated by filing systems themselves before they start their initialisation. &07 File handle range request. Lowest returned in X, highest in Y. HADFS uses handles 25 to 29. &08 OSCLI command being processed. This is used to facilitate the *ENABLE command. &09 *EX command. XY points to any pathname. &0A *INFO command. XY points to the filename. &0B *RUN from library. Currently not implemented. &0C *RENAME command. XY points to the filenames after the command. &0D

OSWORD

Entry address: &FFF1 OSWORD functions

On entry: A function code On exit: A,X,Y usually preserved XY pointer to control block

HADFS provides two OSWORD functions, 14 (&0E) and 90 (&5A).

&0E Read real-time clock If there is no on-board clock provided (such as in the Master), then the *SETDATE command can be used to set a date. This date is then used by HADFS to date-stamp files, and can be read using the standard RTC call. The time part can be set from BASIC using:

TIME=((hours*60+minutes)*60+seconds)*100

TIME is preserved over Ctrl-Break. There may be a few seconds' discrepency depending on when the last ROM service call or HADFS filing system call was made.

On entry: XY+&00 &00 - read time and date string. On exit: XY+&00 Time and date is returned in the format: Mon,25 Oct 1987.12:24:30

On entry: XY+&00 &01 - read time and date in BCD format. On exit: XY+&00 year (&00-&99) &01 month (&01-&12) &02 day of month (&01-&31) &03 day of week (&01-&07, Sun-Sat) &04 hours (&00-&23) &05 minutes (&00-&59) &06 seconds (&00-&59) A year value of >&80 implies a century number of &19, a year value of <&81 implies a century number of &20.

On entry: XY+&00 &02 - convert BCD time and date to string. &01 BCD time and date as for call &01. &08 On exit: XY+&00 Time and date string as with &00.

&5A Read/Write sectors This call allows you to read and write sectors of a disk in an internal or external drive. HADFS translates this call into the required low-level calls with OSWORD &7F or OSWORD 90.

On entry: XY+&00 &00 \ These two values &01 &06 / identify this call &02 Address &06 Sector start \ Sector &09 Drive number / address &0A Number of sectors &0B Call number, and returned result byte &0C The call numbers are: &80 read sectors &81 write sectors

If the call was successful, then the return byte is zero. If not, then one of the following values is returned:

&06 Bad block &12 Drive read only &08 Clock error &14 Track zero not found &0A Late DMA &16 Write error &0C ID CRC error &18 Sector not found &0E Data CRC error &1A Media change request &10 reserved &1C Abort &FE Drive not present

HADFS low-level calls also use OSWORD 90, using call numbers 1-7.

OSBYTE

Entry address: &FFF4 OSBYTE functions

On entry: A function code On exit: A preserved X,Y any parameters X,Y any returned values

A=127 (&7F) - Read EOF status On entry: X=channel number On exit: X=0 if EOF has not been reached X<>0 if EOF has been reached A, Y preserved

If PTR=EXT on the channel specified, then EOF is returned true. This call is used to provide BASIC's EOF# function.

A=90 (&5A) - JGH sideways ROM service call On entry: X=ID number, or zero Y=call number On exit: X=b7-b6 ROM status, b5-b0 other specific info.

The HADFS ROM has program ID 6, and by default it is enabled. To disable it, you can use *FX90,6,1 or *DISABLE HADFS. The ROM will re-enable itself on a power-on reset or a memory-clear reset. The call values in Y used by HADFS are:

Y=0 Enable ROM Y=1 Disable ROM Y=2 Enable ROM, select HADFS, and do *I AM BOOT Y=3 As Y=2, but without *I AM BOOT Y=4..Y=63 Unused HADFS calls Y=64 Look for default drive, return drive in X Y=65 Look for default library drive, return drive in X Y=66 Look for default user drive, return drive in X Y=67..Y=127 Unused external HADFS calls Y=128..Y=254 Unused HADFS calls Y=255 Return status

The X register returns the following information:

b7: HADFS ROM is disabled b6: HADFS owns workspace from &E00 b5-b0: Private workspace pointer, offset from &0E00 or &C000

Using the OSBYTE 90 service call standard allows interrogation of ROMs in a uniform manner to enable and disable them and to ask for status information. All ROMs respond to X=0, Y=0 on entry (*FX90,0 or just *FX90) by displaying their ID number and their name, eg:

>*FX90
6: Harston ADFS
9: Z80 BASIC

With X set to non-zero, it is a specific call to a particular ROM, with Y containing the call number. All ROMs respond to calls with Y=0 to enable the ROM, Y=1 to disable the ROM and Y=255 to request the ROM's status, eg:

>*FX90,6,1

will disable the ROM with program ID 6, ie HADFS. On return from calls the top two bits of X hold information about whether the ROM is present, and whether it is enabled or not:

X=11xxxxxx ROM not present (X returned as &FF) X=10xxxxxx ROM present, but disabled X=0yxxxxxx ROM present and enabled

When calling from a second processor using the OSBYTE call the Y register is ignored and zero is used instead for calls below OSBYTE &80. This means that if you use a call with Y=255 to read the status and it returns saying that the ROM was disabled, the ROM will actually have been enabled, because Y=0 has been used instead. To get round this use something like:

A%=90:X%=number:Y%=255:S%=(USR&FFF4 AND&FF00)DIV256
IF (S% AND &C0)=&80 THEN OSCLI "FX90,"+STR$(number)+",1"

This will redisable a ROM found to be actually disabled.

Some of the program IDs used so far are: 1: CharROM - Character set ROM 2: NewMOS 3: 4: 5: Games Auto Boot ROM 6: HADFS - Harston Advanced Disk Filing System 7: Z80 Emulator - Emulates a Z80 CPU 8: 9: Z80 BASIC - BBC BASIC(Z80) with BBC file i/o 10: 11: Dissem ROM - Various disassembly routines 12: 13: 14: 15: 16: NFS Front End