311 lines
12 KiB
Plaintext
311 lines
12 KiB
Plaintext
X-NEWS: hylka comp.sys.cbm: 9773
|
|
Path: klaava!news.funet.fi!news.tele.fi!uunet!pipex!uknet!warwick!not-for-mail
|
|
From: stuce@csv.warwick.ac.uk (Peter Weighill)
|
|
Newsgroups: comp.sys.cbm
|
|
Subject: 1541 disk drive commands.
|
|
Date: 25 Sep 1993 19:20:47 +0100
|
|
Organization: Commodore 64 Services, University of Warwick, UK
|
|
Lines: 122
|
|
Message-ID: <28225v$1s3@tansy.csv.warwick.ac.uk>
|
|
|
|
|
|
TWO RARELY USED 1541 DISK DRIVE FUNCTIONS
|
|
|
|
|
|
1. The Utility Loader '&' command.
|
|
|
|
INTRODUCTION
|
|
|
|
A little known and little used command on the 1541 disk drive is the
|
|
"&" command. This is probably due to the fact that there is no mention of it
|
|
in the "1541 DISK DRIVE users guide". Many other books about the disk drive
|
|
also fail to mention it. As to a use for the command, I have not found one
|
|
yet. Perhaps someone could think of one. I would expect that the 1570/1571
|
|
and 1581 drive will also contain the "&" command as well, since they are
|
|
based on the 1541.
|
|
|
|
UTILITY LOADER ("&" command)
|
|
|
|
The utility loader is the command which will load a USR file from
|
|
disk into disk drive memory where it will then execute. The format for
|
|
the command is as follows:
|
|
OPEN15,8,15:PRINT#15,"&filename":CLOSE15
|
|
|
|
USR FILES
|
|
|
|
A user file has to follow certain guidlines. It is limited to just
|
|
one sector and this sector is constructed as below;
|
|
|
|
Byte
|
|
0 Start address low order
|
|
1 Start address high order
|
|
2 Number of bytes in program
|
|
3+ Program code bytes
|
|
last Checksum
|
|
|
|
This means that the maximum size of program code is 251 bytes. The
|
|
checksum byte is calculated by adding all the values of the bytes, starting
|
|
at the low order start address (byte 0), while adding you subtract 255 from
|
|
the total every time it exceeds 255. Thus the checksum byte can range from
|
|
1-255.
|
|
One final constraint is that the filename must begin with an "&".
|
|
Below is a program which will make it easier for you to create a USR
|
|
file in the required format, so that it can be executed by the utility
|
|
loader command. The program automatically calculates the length of the code
|
|
and also the checksum at the end. All you need to do is add your own code
|
|
to the data statements between 210 and 300 and specify a filename in line 10.
|
|
|
|
10 OPEN2,8,2,"0:&filename,U,W"
|
|
20 READLO,HI:C=LO+HI:IFC>255THENC=C-255
|
|
30 PRINT#2,CHR$(LO)CHR$(HI);
|
|
40 T$=""
|
|
50 READD:IFD=-1THEN100
|
|
60 C=C+D:IFC>255THENC=C-255
|
|
70 T$=T$+CHR$(D)
|
|
80 GOTO50
|
|
100 L=LEN(T$)
|
|
110 C=C+L:IFC>255THENC=C-255
|
|
120 PRINT#2,CHR$(L)T$CHR$(C);
|
|
130 CLOSE2
|
|
140 END
|
|
170 :
|
|
200 DATA 0,5 :REM lo/hi start address
|
|
210 : REM program code
|
|
220 DATA 173,0,28,41,16,201,16,208,11
|
|
230 DATA 169,247,45,0,28,141,0,28,76
|
|
240 DATA 0,5,32,24,193,76,0,5
|
|
300 DATA -1 :REM program data finished
|
|
|
|
The example code in the program is not that useful, it is just there
|
|
to show how the utility loader works. It just switches the drives light on
|
|
and off depending on if the write protect sensor is covered or not.
|
|
If you can think of something which could be done with the utility
|
|
loader then I would love to hear of it.
|
|
|
|
ERRORS THAT CAN OCCUR
|
|
|
|
39, 'file not found'
|
|
This occurs if the file you specified using the utility loader
|
|
command does not exist or is not a USR file.
|
|
|
|
50, 'record not present'
|
|
The checksum calculated by the disk drive and the checksum at the
|
|
end of the file differ.
|
|
|
|
51, 'overflow in record'
|
|
Either: 1. The end of the file was reached before the checksum
|
|
byte was read.
|
|
or 2. The file contains extra bytes of data after the checksum
|
|
byte.
|
|
Check the length byte in the usr file (position 3, after lo/hi.)
|
|
|
|
|
|
|
|
2. Checking that a file is on the disk.
|
|
|
|
INTRODUCTION
|
|
|
|
If you wrote a program which needed to check that a particular file
|
|
existed on a disk then you would probably open the file for a read, then
|
|
check the error channel for 62, FILE NOT FOUND.
|
|
|
|
Thus:
|
|
10 OPEN15,8,15
|
|
20 OPEN2,8,2,"filename,P,R"
|
|
30 INPUT#15,E,E$
|
|
40 IFE>0THENPRINTE$:GOTO60
|
|
50 PRINT"FILE EXISTS"
|
|
60 CLOSE2:CLOSE15
|
|
|
|
Another way to check if a file exists is to try to rename it as itself.
|
|
|
|
Thus:
|
|
10 OPEN15,8,15,"R:filename=filename"
|
|
20 INPUT#15,E,E$
|
|
30 CLOSE15
|
|
40 PRINTE$
|
|
|
|
If the file exists then the error created is 63, FILE EXISTS,
|
|
otherwise it is 62, FILE NOT FOUND. Judge for yourself which works better.
|
|
|
|
|
|
Written, September 93, by Peter Weighill. email: stuce@warwick.csv.ac.uk
|
|
|
|
|
|
|
|
From: Nicholas.Cull@comp.vuw.ac.nz (Nicholas Cull)
|
|
Newsgroups: comp.sys.cbm
|
|
Subject: Re: 1541 disk drive commands.
|
|
Date: 30 Sep 1993 00:00:20 GMT
|
|
Organization: Dept. of Comp. Sci., Victoria Uni. of Wellington, New Zealand.
|
|
Originator: ncull@comp.vuw.ac.nz
|
|
|
|
|
|
In article <28225v$1s3@tansy.csv.warwick.ac.uk>, stuce@csv.warwick.ac.uk
|
|
(Peter Weighill) writes:
|
|
|>
|
|
|> 1. The Utility Loader '&' command.
|
|
|
|
...
|
|
|
|
|> A user file has to follow certain guidlines. It is limited to just
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|> one sector and this sector is constructed as below;
|
|
^^^^^^^^^^
|
|
|
|
This is incorrect. The user file may be more than one sector long, although the
|
|
maximum size of the program code is limited to 256 bytes. To obtain this, byte
|
|
2 (the number of bytes in program) should be set to 0. A formula for this
|
|
would be
|
|
|
|
(NB AND 255)
|
|
|
|
where NB is the number of bytes. Remember that the checksum has to be updated
|
|
in a similar way too, eg
|
|
|
|
C = C+(NB AND 255): IF C>255 THEN C=C-255
|
|
|
|
The number of bytes in a Block-Execute command is limited to a single sector,
|
|
which is 256 bytes, although these can be all data bytes. Maybe you were
|
|
confusing the two commands?
|
|
|
|
|>
|
|
|> Byte
|
|
|> 0 Start address low order
|
|
|> 1 Start address high order
|
|
|> 2 Number of bytes in program
|
|
|> 3+ Program code bytes
|
|
|> last Checksum
|
|
|>
|
|
|
|
In fact there can be more than one block of this construction per file. To do
|
|
this, simply repeat the construction. For example, if you wanted to have a
|
|
program which sat in drive locations $0300 to $0400, and $0480 to $0500, the
|
|
construction would be as follows:
|
|
|
|
Byte
|
|
0 Low byte start address of first block (0)
|
|
1 High byte start address of first block (3)
|
|
2 Number of bytes in this block (0) [= 256 AND 255]
|
|
3 - 259 Program code for first block (data goes in here...)
|
|
260 Checksum for first block (whatever this may be)
|
|
|
|
261 Low byte start address of second block (128)
|
|
262 High byte start address of second block (4)
|
|
263 Number of bytes in this block (128)
|
|
264 - 392 Program code for second block (second lot of data here)
|
|
393 Checksum for second block (whatever)
|
|
|
|
Okay, so this may not be the best description in the world, but hopefully you
|
|
get the general idea. There may be as many blocks of this type as you need,
|
|
and theycan all be any size from 1 to 256 bytes long. Once the file has been
|
|
completely loaded into the drive, execution starts from the start address of
|
|
the FIRST block be be transferred.
|
|
|
|
|> the total every time it exceeds 255. Thus the checksum byte can range from
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|> 1-255.
|
|
^^^^^^
|
|
|
|
The checksum could be 0 if all the data bytes were 0 :-)
|
|
|
|
Seriously though, the point of having the checksum calculated in this way is to
|
|
make use of the carry bit in machine code addition if a carry is generated. The
|
|
point can be made more clearly in the following code fragment:
|
|
|
|
[accumulator holds current data byte]
|
|
clc ;Clear carry bit for first add
|
|
adc $87 ;Add byte to current checksum
|
|
adc #$00 ;Add carry bit to checksum
|
|
sta $87 ;Save checksum to memory
|
|
|
|
If the sum of the accumulator and the contents of location $87 is greater than
|
|
#$FF then the carry flag will be set, in order to do multi-byte addition
|
|
correctly. Instead of adding this to a second byte however, it is added to the
|
|
same byte which generated the carry. This causes the value in the accumulator
|
|
to be incremented by 1 - the same as if #$FF had been subtracted from it.
|
|
|
|
If the sum is of the accumulator and the contents of location $87 is less than
|
|
or equal to #$FF, then no carry is generated and no further addition or
|
|
subtractionis needed.
|
|
|
|
|> Below is a program which will make it easier for you to create a USR
|
|
|> file in the required format, so that it can be executed by the utility
|
|
|> loader command...
|
|
|
|
Here is a new version the the program, modified to handle multiple data blocks,
|
|
and a maximum program size of 256 bytes per block:
|
|
|
|
10 OPEN2,8,2,"0:&filename,U,W"
|
|
20 READNB
|
|
30 READLO,HI,LN:C=LO+HI:C=C+(C>255)*255
|
|
40 C=C+(LNAND255):C=C+(C>255)*255
|
|
50 PRINT#2,CHR$(LO);CHR$(HI);CHR$(LNAND255);
|
|
60 READD:PRINT#2,CHR$(D);
|
|
70 C=C+D:C=C+(C>255)*255
|
|
80 LN=LN-1:IFLN>0THEN60
|
|
90 PRINT#2,CHR$(C);
|
|
100 NB=NB-1:IFNB>0THEN30
|
|
110 CLOSE2
|
|
120 END
|
|
190 :
|
|
200 DATA2 :REM number of data blocks
|
|
210 DATA128,3 :REM lo/hi start address of first block
|
|
220 DATA6 :REM length of first block
|
|
230 : REM program code
|
|
240 DATA32,71,198,76,0,3
|
|
300 DATA0,3 :REM lo/hi start address of second block
|
|
310 DATA26 :REM length of second block
|
|
320 : REM rest of program code
|
|
330 DATA173,0,28,41,16,201,16,208,11
|
|
340 DATA169,247,45,0,28,141,0,28,76
|
|
350 DATA0,3,32,24,193,76,0,3
|
|
|
|
The example code here is just a minor extension to the original code. It
|
|
re-initializes the drive before jumping to the original code. This is just to
|
|
demonstrate that both parts of the code are being loaded and executed
|
|
correctly.
|
|
|
|
|> ERRORS THAT CAN OCCUR
|
|
|>
|
|
|> 51, 'overflow in record'
|
|
|> Either: 1. The end of the file was reached before the checksum
|
|
|> byte was read.
|
|
|> or 2. The file contains extra bytes of data after the checksum
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|> byte.
|
|
^^^^^
|
|
|> Check the length byte in the usr file (position 3, after lo/hi.)
|
|
|
|
The second condition is not quite accurate. If end-of-file is reached before
|
|
the drive expects to read the checksum, then this error will occur. If extra
|
|
bytes appear after the checksum, the drive assumes these to be the start of a
|
|
new block of data and will try to interpret these as address bytes, length
|
|
byte, data bytes etc as above. When end-of-file appears, the drive will report
|
|
this error, since it is expecting another block of data to appear and cannot
|
|
complete the transfer of this into memory. Hence the definition of this error
|
|
should be:
|
|
|
|
The end of the file was encountered unexpectedly. May indicate an
|
|
incorrect length byte, or additional data written after the end of the
|
|
last data block.
|
|
|
|
Note the semicolon at the end of line 90 of the program. If this were omitted,
|
|
a carriage return byte would be sent by the computer after the checksum byte
|
|
and may be the cause of this message.
|
|
|
|
One caution should be added at this point. Although data may be transferred to
|
|
any address in the RAM of the drive, it should be remembered that part of the
|
|
memory will be allocated to buffering the file as it comes off the disk. Thus
|
|
it may be possible to overwrite incoming data being buffered in memory before
|
|
it can be transferred correctly to its new location. Experimentation may be
|
|
the best way of determining which areas are "safe" and which ones have
|
|
problems. I found that the file seemed to be buffered in locations $0600 to
|
|
$0700, but this would depend on how may files you had open, etc.
|
|
|
|
Nick.
|
|
|
|
----
|
|
email: ncull@comp.vuw.ac.nz Victoria University of Wellington, New Zealand.
|
|
|