[img] Devices in Filenames
 MDFS::Info.Comp.Spectrum.Code.Filing.device/htm Search  

Programs such as Tasword and HiSoft Devpac allow you to save and load data to and and from tape and microdrive.
They allow you to specify what device to use in the filename by using a colon as the second character. So, 1:DATA
specifies the file DATA on microdrive 1 and T:DATA specifies a file on tape. A filename without a device specifier
uses a previously set default device.

I found this such a useful concept that I built it into many of the Spectrum programs that I wrote. In fact, it is such a
sensible concept I wish it had been implemented natively in the Interface 1, but that is another story. Programs where
this is used include:
The program fragments here provide the code to load, save and catalogue with microdrives 1 to 8, tape or a remote
server connected by the serial port. The code is shown on lines 9000 onwards, but it does not reference any line
numbers itself and can be renumbered to anywhere convenient.

This code will also work with any device that uses the Interface 1 microdrive syntax. Unless the same Interface 1
variables are used at 23734 and 23766 the initialisation will default to drive "T" for Tape.

You can download the routines as plain text in device.txt (2K) and Spectrum Tapefile in device.tap (2K). See
also fsfile.asm (9K) for machine code equivalent.

Initialise file interface

The following code should be called at the beginning of the program. It sets int1 to non-zero if the Interface 1
is present, otherwise int1 is set to zero. If the Interface 1 is present, then drive is set to the character code of the
most recently used microdrive, CODE"1" to CODE"8". Otherwise, drive is set to CODE"T" to indicate tape.
If the Interface 1 is present, then stream 9 is opened to the serial port for serial access to a remote file server.
9000 REM Initialise file interface
9010 REM Sets drive=current device, int1=Interface 1 present
9020 LET drive=CODE"0"+PEEK 23766:CLOSE#0:LET int1=(PEEK 23734<>244)
9030 IF drive<CODE"1" OR drive>CODE"8" OR int1=0 THEN LET drive=CODE"T"
9040 IF int1 THEN IF PEEK 23769=66 THEN LET drive=CODE"S"
9050 IF int1 THEN CLEAR#:OPEN#9,"b":POKE 23769,drive-17:POKE 23766,drive-CODE"0"
9060 RETURN

Saving data

Calling the save code saves data to the current device specified in drive. or to the device specified in the filename
in f$. The data is saved from start with length length. On return a$="" or holds an error message.
9100 REM Save data
9110 REM drive=default drive, f$=filename, start+length=>data, int1=Interface 1 present
9120 LET a$="":IF f$="" THEN RETURN
9130 IF f$(2)<>":" THEN LET f$=CHR$drive+":"+f$
9140 IF f$(1)>"0" AND f$(1)<"9" THEN SAVE*"m";VALf$(1);f$(3 TO)CODE start,length:RETURN
9150 IF f$(1)<>"S" THEN SAVE f$(3 TO)CODE start,length:RETURN
9160 IF int1=0 THEN RETURN
9170 INPUT#9;"S";(f$(3 TO))'a$;#2;(a$(2 TO))':IF a$<>"" THEN RETURN
9180 SAVE*"b"CODE start,length:RETURN

Loading data

Calling this code loads data from the current device specified in drive. or from the device specified in
the filename in f$. If start is negative, then the data is loaded to its own load address. If start is positive
then the code is loaded to the address it specifies. On return a$="" or holds an error message.
9200 REM Load data
9210 REM drive=default drive, f$=filename, start=-1 or load address, int1=Interface 1 present
9220 LET a$="":IF f$="" THEN RETURN
9230 IF f$(2)<>":" THEN LET f$=CHR$drive+":"+f$
9240 IF start<0 THEN IF f$(1)>"0" AND f$(1)<"9" THEN LOAD*"m";VALf$(1);f$(3 TO)CODE:RETURN
9250 IF f$(1)>"0" AND f$(1)<"9" THEN LOAD*"m";VALf$(1);f$(3 TO)CODE start:RETURN
9260 IF start<0 THEN IF f$(1)<>"S" THEN LOAD f$(3 TO)CODE:RETURN
9270 IF f$(1)<>"S" THEN LOAD f$(3 TO)CODE start:RETURN
9280 IF int1=0 THEN RETURN
9285 INPUT#9;"L";(f$(3 TO))'a$;#2;(a$(2 TO))':IF a$<>"" THEN RETURN
9290 IF start<0 THEN LOAD*"b"CODE:RETURN
9295 LOAD*"b"CODE start:RETURN

Cataloging

The code will catalogue the current device specified in drive. There is no native tape catalogue function on
the Spectrum, so if Tape is specified, the routine just exits. If your program provides a tape catalogue routine
you would call it here. On return a$="" or holds an error message.
9300 REM Catalogue
9310 REM drive=default drive
9320 LET a$="":IF CHR$drive>"0" AND CHR$drive<"9" THEN CAT VALCHR$drive:RETURN
9330 IF CHR$drive="S" THEN IF int1=0 THEN RETURN
9340 IF CHR$drive="S" THEN INPUT#9;"C"'a$;#2;(a$(2 TO)):RETURN
9350 REM If a tape catalogue routine available, call it here
9360 REM Eg: LET bc=USR cat
9370 RETURN

Set Drive

Call the following routine with f$ set to the device to default to in future if a filename does not specify
a drive explicitly.
9400 REM Set default drive
9410 REM f$=drive character
9420 IF f$<>"" THEN LET drive=CODE f$(1)
9430 RETURN

Notes

The initialisation code tests for an Interface 1 by using:
CLOSE#0:LET int1=(PEEK 23734<>244)
CLOSE#0 resets stream zero to its default setting. With the Interface 1 the Shadow ROM is also paged in to
check for closing Interface 1 channels. On an unexpanded Spectrum location 23734 will be the first byte of
the CHANS area and contain &F4. With the Interface 1 initialised it will be be FLAGS3 and will never contain
&F4 while BASIC is operating correctly, and will normally hold zero.

Best viewed with Any Browser Valid HTML 4.0! Authored by J.G.Harston
Last update: 17-Oct-2004