The file system for 1541IDE and C64IDE
What is itI have several projects using a hard disk drive:
- 1541IDE: an IDE hard disk drive for your 1541
- 1541IDE: an 8-bits IDE hard disk drive for your 1541
- 1541IDE: an IDE hard disk drive for your C64/128
This is a proposal for a file system and some proposals for handling it. The goal is to stay independent of the way how the HD is connected to the system and what kind of system it is.
Personal comment: I favour the system using a 1541-board. So it is possible that the idea is 'coloured' by this favouritism.
The size of a sectora hard disk drive sector normally contains 512 bytes. Any Commodore drive is used to work with 256 bytes sized sectors (the 1581 uses a trick). Developing a new file system also means writing a new Kernal. Why not writing a Kernal that is able to handle bigger sectors?
The problem is that all existing software is only used to 256 bytes sized sectors. So for example if a program wants to read the data on a sector, it will read 256 bytes and nothing more. So even if we really want it, we have to stick to 256 bytes/sector for the moment.
The boot sectorThe only function of the boot sector is to provide the Kernal of the drive with some data. This is necessary as the size of a hard disk drive can vary. The boot sector is located at the very first sector of a drive.
* identifier like "CBM-HD00" 8 bytes * version like "00.00.01" 8 bytes | | |---> enhancement | |------> sub version |---------> main version * number of sectors in LBA mode 4 bytes * pointer to the root directory 4 bytes * pointer to the Boot-PRG, all 0 when none. See: Boot-PRG 4 bytes
The BAM tableThe BAM table starts at sector 2. The 1541 reserves 4 bytes for every track: one byte is used for the number of free sectors, the other three for marking the used sectors. But using the LBA mode means we don't have tracks anymore. So my idea is to reserve as many bits as needed; one bit for every sector. So no "free sectors" bytes as this number can be calculated anyway.
The DirectoryThe root directory starts at the first sector after the BAM table. Except this particular sector, I've no plans of dedicating other sectors to directories or files. The reason for this is that in my experience the root directory tends to remain relatively small.
The structure of a directory sector should look like this:
* pointer to next sector 4 bytes * pointer to previous sector 4 bytes * 6 entries of 41 bytes each 246 bytesAn entry should look like this:
* file type 1 byte * 00 = DELeted * 01 = SEQuential * 02 = PRoGram * 03 = USeR * 04 = RELative * 05 = DIRectory (1581 compatibility, not used) * 06 = DIRectory * 07 = SYStem * 08 = UEX, User EXtension * 09 = EXE * 0A = image (D64, D71, D80, D81, D82 etc.) * 0B = ICOn * 0C..0F = future use The four bits of the highnibble are used as the 1541 uses them: value: 1 0 * bit 7: file is closed / not closed * bit 6: file is locked / not locked * bit 5: used by 1541 for ??? * bit 4: used by 1541 for ???File type 7, SYStem, is meant to enable the host (= C64/128, 1541-board) to create a swap file or whatever you want.
File type 8 enables a user to supply a file with its own extension. When listing such a file, the 1541 will send these three chars to the host instead of a predefined one. This feature also enables us to store well known Commodore images on the disk and to mark them as so. This on its turn can be used to let the HD emulate a specific Commodore drive. These three chars themselves can be found a little bit further in the list.
File type 9, EXEcutable: The first two bytes of a PRG describe the loading address. But the 65816 can handle 16 MB ie. needs 3 bytes and the new 65GZ032 even needs four bytes. The idea is to use this file type for these types of PRGs. The first four bytes describe the 32 bits loading address. If the EXE is meant to run on a 65816 equipped machine, the first byte is $00.
* name, 1541-format 16 bytes * pointer to first sector 4 bytes * number of sectors 4 bytes * entry side-sector-block relative file / icon 4 bytes * record length relative file 2 bytes * user supplied extension / image type 3 bytes * date/timestamp, YYYYMMDDHHMISS 7 bytes + --- 41 bytesAs you can see the four bytes for pointing to the entry of the side-sector-block of a relative file can be used for pointing to an icon. This can be useful in a graphical orientated OS. If the file is not a REL file then these bytes point to the location of the icon file. If not used, they should be zero.
Then what about an icon for a REL file? My proposal: place it in the root and name it "REL.ICO".
Real Time ClockAs you can see, some bytes are reserved for a timestamp. This will only be possible if a Real Time Clock IC is installed in the drive. For the moment I favour the Motorola (or the compatible Dallas) one used in PCs for the simple reason I have quite some lying around, scrapped from old PCs.
The link systemI have chosen for using for the link system as used by Commodore and not for the FAT system as used by PCs. The idea is simple: the first four bytes of a sector are reserved for pointing to the next sector in the link. An extra addition to the original system is that next four bytes point to the previous sector. This doesn't only come in handy when searching backwards, but also gives one an extra mean of restoring links after a crash. The remaining 248 bytes are data.
The reasons for choosing the link system above the FAT system:
- The link system is more robust. If you loose a FAT sector, you can loose a lot of files. MS-DOS has good reasons for maintaining a copy of the FAT table on every disk.
- The link system is faster when loading a file. With FAT I have to read the FAT table every time to find out where to find the next sector. In case of a heavily fragmented file, I have to read a different FAT sector for every sector I want to load.
- The FAT system isn't able to track a file backwards.
- Last, but not least: sentimental reasons :)
ImagesThe idea behind supporting images is to remain as compatible as possible to the original Commodore drives. At least we should support D64 and D71 images but IMHO it should also be possible to support D81 (1581), D80 (8050), D82 (8250), D40 (3040) and D16/CMD in the future. The D16-image is "my own" invention and can be seen as a 1541-alike floppy with 255 tracks with each 256 sectors. As the original BAM is not big enough, it has one of his own. To remain a little bit compatible with the 1541, track 18/sector 1 is reserved for the directory but from then on the system is free to use any free sector. Of course D16 supports subdirectories but not like the 1581 does. A subdirectory is an ordinary file but its contents happen to have the same structure as a directory.
Somebody told me that this is exactly as how CMD does it on their hard disk drives. Once I know more about how a CMD partition looks like, I could use that instead of my own D16-image.
How do we store images? Storing the contents of the file as regular data means splitting the original sectors inside the image as we can only store 248 bytes in a regular sector. My idea is to store an image as one unfragmented file with _NO_ link-bytes. The directory tells us where to find the first sector. A "simple" calculation should tell us where to find any desired track/sector within the image.
I can imagine that creating a 16 MB sized D16/CMD image on a hard disk drive already in use for some time, can cause problems. This simply means we have to provide tools to defragment a hard disk drive.
To be able to handle an images the same commands as known by the original system must be implemented, if possible, or adapted to the HD. Example: Commands regarding the MFM mode of the 1571 are in fact impossible on a 1541-board and have to be "translated" or neglected.
Remark: I have no idea yet how to handle CP/M floppies. But I fear that it will cost a lot of ROM due to the number of formats. Don't forget, the ROM of a 1571 is 32 KB !!!
To be able to handle subdirectories and other HD related matters, I propose to add some commands:
command : ab.: function: CHANGEDIR:directory CD change directory DEFRAG DF defragments the drive. DELETE:name DEL same as SCRATCH DELTREE:directory DT like the MS-DOS command 'deltree': deletes complete directory incl. subdirectories FORMAT FO format hard disk drive HIDE:name HI makes a file invisible for listings LOCK LO locks a file MAKEDIR MD make subdirectory REMOVEDIR RD remove empty (!) directory SETTIME ST set the time/date of the internal RTC START SA start hard disk drive STOP SO stop hard disk drive TIMEDATE TD supplies date and time to host through the error message: "0, 2005-02-27 15:23:13, 0, 0" UNHIDE:name UH makes file visible again UNLOCK:name UL unlocks a file XCOPY:new=old XC like MS-DOS command 'xcopy': copies complete directories and subdirectories
The boot programThe old 1540 and early 1541 had a way to load and execute a program by manipulating the data and CLOCK line of the IEC bus. You can see this as executing the &-command immediately after a Reset. The 4 bytes in the very first sector can point to such an & file. If not used they are $00.
I'm thinking of using this feature to enable one to make patches to the original Kernal by loading software in the extra RAM and changing the RAM vectors. To avoid the problem that the drive keeps loading a faulty patch after every reset, the pointer in the boot sector is cleared after loading the software.
You can email me here.