4 Low level fileentry 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:
 &FD Read an object's extra catalogue information into the control block. The load field returns the account
     numbers, main account in XY+2,3 and auxillary account in XY+4,5, currently set identically to the main account
     number. The contents of the execution field is currently undefined. The length field returns the length. The
     attributes field returns holding the start sector and drive of the object. A is returned holding the object type.
 &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 returned in the A register are:
	&FF Execute-only file
	&00 Object not found
	&01 File found
	&02 Directory found, the length field holds the disk space that the directory's catalogue takes up.

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, 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   Privatised
		       6   Execute only by others
		       5   Writable by others
		       4   Readable by others
		       3   Locked
		       2   Execute only for 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)

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*100 in A and version and capability flags in zero page. The flags show what code is
	available in the HADFS rom:
	zp+0, b0: *Copy in Rom		b4: Date provided
	           b1: Passwords used		b5: Full INSTALL
	           b2: COMPACT/BACKUP		b6: Fast OSGBPB
	           b3: Time provided		b7: Random access output
	zp+1: b0: -				b4: Mouse driver provided
	           b1: -				b5: -
	           b2: -				b6: Hard disk supported
	           b3: -				b7: FRED/JIM ramdisk supported
	zp+2: version number x of x.yy
	zp+3: BCD version number yy of x.yy
 &FE Return last drive used in A, zero page ignored.
 &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 		18
	 7 IEEE filing system
	 8 Acorn ADFS			 29 DOS filing system
	 9 Host filing system			 45 Nexus filing system
	10 Videodisk filing system		 65 Co-processor filing system
	11
     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 Read/write system parameters to zero page. Y=&01..&0F reads the values and Y=&81..&8F writes the
	values:
	   Y=&81/&01 \
	   Y=&82/&02  } Do not use - these clash with CFS and RFS
	   Y=&83/&03 /
	   Y=&84/&04 OPTFLG/00/USERNUM/PRIV flags	* These flags are subject
	   Y=&85/&05 OPTNUM/00/OWNER/IAMFLG flags	*   to change.
	   Y=&86/&06 CURR - current directory in memory
	   Y=&87/&07 DRVTMP/00/VFLG/DRIVE	    	* Subject to change
	   Y=&88/&08 CSD - Currently Selected Directory disk address
	   Y=&89/&09 LIB - Current library disk address
	   Y=&8A/&0A URD - User Root Directory disk address
	   Y=&8B/&0B to &8F/&0F currently unused

 &FE Unsupported, zero page ignored.
 &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 work/login filename or entries from specified directory. If XY+0 is zero, reads command line
   parameters after a Basic bootstrap:
	    &00	length of text string (n)
	    &01	Any command line parameters
	  &02+n
   If XY+0 is a channel number of an open directory, reads a null-terminated list of directory entries. The function is
   called as for OSGBPB 8, but XY+5 returns the number of filenames read.
 &0A  Read entries and information from the opened directory whose channel number is in XY+0. 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. 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	Five zeros (reserved for centisecond time since 1900)
	    &1D	Object name, null terminated
	    xxx	next record
 &0C Note: Calls with A=&09, &0A, &0B are only available from version 0.49 onwards.

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 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).

A=&0E  Read real-time clock
     If there is no on-board clock provided (such as in the Master), then the *HSETDATE 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.

     On entry XY=0 - read time and date string.
     On exit:	The time and date is returned in the format:
			Mon,25 Oct 1987.12:24:30
		The time part can be set from Basic using:
		     TIME=((hours*60+minutes)*60+seconds)*100
		From version 0.49 onwards, the 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 extry XY=1 - read time and date in BCD format.
     On exit:
	XY+0	year		(&00-&99)
	XY+1	month		(&01-&12)
	XY+2	day of month	(&01-&31)
	XY+3	day of week	(&01-&07, Sun-Sat)
	XY+4	hours		(&00-&23)
	XY+5	minutes		(&00-&59)
	XY+6	seconds		(&00-&59)

      A year value of >&80 means a century number of &19, a year value of <&81 means a century number of &20.

     On entry XY=2 - convert BCD time and date to string.
	The BCD time and date is at XY+1 to XY+7, as for call with XY=1.
     On exit:  The time and date returned as a string as with XY=0.

A= &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.
Control block:
 &00  0 \ These two values
 &01  6 / 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:
	&12	Drive read only
	&14	Track zero not found
	&18	Sector not found
	&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

Osbyte 90 - General
All the roms that I write conform to my rom selection standard that allows interrogation of the roms in a uniform manner. This is the Osbyte 90 call, used to enable and disable the rom, and to ask for status information about it. The arrangement of the Osbyte 90 call is:

	On entry:	A=90
		X=ID number, or zero
		Y=call number

	On exit:	A=90
		X=b7-b6 rom status, b5-b0 other specific info.
		Y=other info.

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 to rom, Y=1 to disable to rom and Y=255 to request the rom's status, eg:

	>*FX90,9,1

will disable the rom with program ID 9, ie Z80 BASIC. On return from calls 0, 1 and 255, the top two bits of X hold information about whether the rom is present, and whether it is enabled or not. Bit 7 holds if the rom is enabled or disabled, and bit 6 holds if the rom is actually present of not. This is summarised as:

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

If the rom is enabled (ie bit 7 is zero), then it must also be present, so bit 6 is an implied zero. This allows bit 6 to be used to return information on other things. The other six bits of X can be used to return specific information about the rom.

The top two bits of X hold the status of the rom before the call, so if the rom is disabled, and you enable it with Y=0, then X will return %10xxxxxx. 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 re-disable a rom found to be actually disabled.

Some of the program IDs that I have 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	 - BBCBASIC(Z80) with BBC file i/o
	10:
	11: Dissem Rom	 - Various disassembly routines
	12:
	13:
	14:
	15:
	16: NFS Front End

If anyone else wants to adhere to this method for a rom that they are writing, write to me, and I will assign you a number and give you the routine I use for service call 7 to provide the Osbyte 90 call.

Osbyte 90 - In the HADFS
The HADFS rom has program ID 6, and by default it is enabled. To disable it, you can use *FX90,6,1. The rom will re-enable itself on a power-on reset or a memory-clear reset. The X register returns the following information:

	bit6:	HADFS owns workspace from &E00
	bit5,4:	Number of channels - 2
	bit3-0:	Private workspace pointer - &14

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
	Calls from 64 to 127 are only used from version 0.49 onwards.