TI-99/4A FILE MANAGEMENT SYSTEM Logical Disk Structure by Brian Tristam Williams This is a description of the organisation of standard TI-99/4A system disks. [Author's note: I know this document is not perfectly written. That's what happens when I write things for my own understanding. Unfortunately, I have not had time to tidy it up for the benefit of the community, and I don't know if I ever will. However, it could probably be of use to some if released in this form, so, here it is.] Physically, each floppy disk is broken up into TRACKS (usually fixed at 40 for anything up to DSDD - but right now, the physical structure does not concern us, as the drive will take care of that. The only thing worth noting here is that each track is broken up into logical SECTORS, and the number of sectors is fixed at 9 per track for single density. The standard Texas Instruments Disk Controller Peripheral came in two flavours: the 'side-car' version, which could only handle single-sided single density diskettes, and the card for the Peripheral Expansion System, which could also handle double-sided (albeit also single density) diskettes. Each sector consists of 256 bytes, which makes the effective capacity of a SSSD diskette equal to (256 byte/sector * 9 sector/track * 40 track/disk). If you do the math, the words 'sector' and 'track' will cancel out during the division, and you'll be left with an answer of 92 160 byte/disk, or exactly 90kB. This is organised into 360 sectors, which are divided by 9 into 40 tracks. With a double-sided 40-track drive, obviously this capacity would be double that, or 180kB. So, we have 360 sectors available, now what? Well, firstly, in the standard TI File Management System, you can't use the first or the second sector, so that leaves us with 358 sectors for our use. Why? Because the TI uses these first two sectors right off the bat for disk information. Sector 0, after initializing the disk, contains information about the structure of the diskette, such as the capacity, name, number of sides, etc. We'll discuss this 'DISK INFORMATION' sector later (yes, I know - that doesn't seem like a very interesting title, but that's what I understand it to be called). Sector 1, after initializing the disk, contains all 0s. This area is for 'pointers-to-files,' or File Pointers. This aspect is hard to understand until more context is created, but stick with me until later - all I can tell you now is that this sector (256 bytes) contains a 2-byte pointer to the start of each file that exists on the disk. If the disk is blank, but formatted, this area is filled with >0000s. The pointers are 2 bytes each, and the sector they're in is 256 bytes long, so you can point to a maximum of 128 files, right? Right, up to a point. Actually, the practical limit is 126 files - I've tried. The File Management System refuses to create a 128th file - it insists on leaving the last pointer as >0000. And even when I create a 127th file, I get software errors when reading the disk catalog. TI Disk Manager II even crashes when I try to copy a disk containing 127 files. So 126 files/disk seems to be the practical limit for this format. The rest of the disk, when blank, contains >E5s. Don't ask me why, I just work here - when management decides to tell me why, I'll let you know. However, I suspect that it has something to do with making the MFM or FM modulation on the diskette easier to verify. But this is the physical side of things - I'm no expert, and it doesn't really matter - what we're looking at is the LOGICAL structure of the diskette. So, all that matters is that the remaining 358 sectors on a typical blank, formatted diskette are filled with >E5s. Now, what happens when we start writing to the disk? Well, with the FMS, it's not possible to just use any one byte of the disk. If you have a file which contains one byte, you still have to use a whole sector to store this byte. So, we want to create a file. The first thing the FMS does is find a blank space on the disk (from info in Sector 0, I think) to store the first sector of the file, and it places a pointer to this sector in the File Pointer sector. Now, remember I told you that the pointer points to the first sector of the file? I lied - but only for the sake of simplicity. What the pointer actually points to is the file's File Descriptor Record, a sector which contains information about the file, such as its name, size, etc. So, that's a third type of sector you need to know about - the File Descriptor Record. There is one of them for each file, and IT will point to the sector(s) on the disk occupied by your file, and it is in THOSE sectors that your file's data will be stored - the actual data sectors. So, by now, there are four types of sectors you should know about: -Sector 0, 'Disk Information' contains information about the diskette -Sector 1, 'File Pointers' contains pointers to each file's FDR -FDRs (File Descriptor Records) contain info about each file -finally, data sectors contain the actual information that you intended to store when you created the file in the first place, usually broken up into records. Before an in-depth examination of each of these sector types, it should be noted that, by default, on a blank disk, the FMS stores the first FDR in sector 2, meaning that the first File Pointer in sector 1 will be >0002. The actual file will be stored starting at sector >0022. You see what's happening here? The file could have been stored starting at sector >0003, but instead they've left sectors >0003 to >0021 open for the next 30 FDRs. This is just so that the disk catalogs quicker, I guess - it doesn't matter WHERE you put your FDRs, as long as they're somewhere on the disk and there are pointers to them. Case in point: if you have 31 files on the disk whose FDRs occupy sectors >0003 to >0021, then the FMS will find the first available blank sector in which to store the next FDR - it doesn't matter where this is. Case in point 2: if you have only one file on the disk, but it is so huge that is has already occupied all of the space from sector >0022 to the end of the disk, the FMS will 'grow' the file into the sectors reserved (rather weakly so) for the FDRs. This 'reservation' isn't one at all - it's just a vague border to politely work around - kind of like WKRP's Les Nessman's office. ----------------------------------------------------------------------------- SECTOR 0 - DISK INFORMATION This sector consists of the following data, in the following order: 10 bytes: Disk Name, ending filled with trailing spaces, if necessary 2 bytes: Number of sectors on the disk, MSB 1st. (Value often >0168 / 360) 1 byte: Number of sectors per track. (Usually >09) 3 bytes: Always >44,>53,>4B, or "DSK" (Emulator freaks: this can help to identify image files of these diskettes on your hard drive - if I'm doing the math correctly, the odds that a file containing these three bytes in those positions is NOT a disk image are 16777215:1, and the odds of the file being a disk image can be increased significantly by looking at other bytes in this sector!) 1 byte: Protected/Unprotected: >50 or >20 (I'm not sure if the rest of the bits in this byte have a use - I've never seen them used. - The following three bytes are often just left as >00, for example with TI's 'Disk Manager'. 'Disk Manager II' puts the right values in these three bytes (>28 >01 >01 for SSSD). I would guess that this is because the improved DMII was released for the double-sided disk controller. In fact, I'm probably one of very few people who owns the DM module, as I have a sidecar controller. 1 byte: Number of tracks on the disk (usually >28 / 40 or >50 / 80) 1 byte: Number of sides (>01 or >02 - what a waste of a byte) 1 byte: Single or Double density (>01 or >02) 36 bytes: Unused, as far as I know - set to 0 on format. 45 bytes: Disk bitmap for SSSD - size varies with the size of the diskette you're using, so it could be something other than 45. This is the final and most complicated part of this sector. Each bit of this area represents a sector on the diskette. If the bit is a 0, the sector is free. If the bit is a 1, the sector is used. That's pretty simple, actually - it would mean that the MSb of the first byte would point to sector 0, right? You're not far off if you understand that much, but what needs to be explained is that, in this bitmap, the 8 bits in each byte are, in fact, reversed. That is, the first bit of the first byte actually represents sector 7, and the last bit of the first byte represents sector 0. Then, the first bit of the second byte represents sector 15, and so on. This is probably a choice that has perplexed every enthusiast who has dug this far into the TI-99/4A. Except, of course the lucky few who actually know the reason for this apparently strange choice. With the above reference in mind, let's look at a sample diskette's Sector 0. I've chosen the TI Writer diskette as my sample. Gee, I hope TI doesn't sue me for copyright infringement, as these precious little bytes are probably copyrighted... Anyway, this is how that first sector looks: 000 00: 54 49 2D 57 52 49 54 45-52 20 01 68 09 44 53 4B TI-WRITER .h.DSK 000 10: 20 28 01 01 00 00 00 00-00 00 00 00 00 00 00 00 (.............. 000 20: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 000 30: 00 00 00 00 00 00 00 00-FF 01 00 00 FC FF FF FF ................ 000 40: FF FF FF FF FF FF FF FF-FF FF FF 03 00 00 00 00 ................ 000 50: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 000 60: 00 00 00 00 00 FF FF FF-FF FF FF FF FF FF FF FF ................ 000 70: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 000 80: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 000 90: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 000 A0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 000 B0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 000 C0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 000 D0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 000 E0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ 000 F0: FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................ The first three digits, on the left, represent the sector number - in this case 0. Then there is the hexadecimal offset of the byte which follows the colon. The colons are all followed by 16 bytes, with the hyphen serving merely to separate the bytes into groups of 8. On the right we see the same bytes when viewed as ASCII characters, (if relevant). This is how all sectors will be viewed in this document. Pretty meaningless so far, but let's break it down: The first ten bytes are ASCII for "TI-WRITER ", the disk name (note the trailing space): 54 49 2D 57 52 49 54 45-52 20 The next two bytes identify the diskette as having 360 sectors: 01 68 The following byte says that there are nine sectors on a track: 09 The next three bytes are the identifying "DSK": 44 53 4B On the next line, the first byte identifies an unprotected diskette: 20 Followed by the information that this is a 40-track diskette, 28 which happens to be single-sided, 01 and single density: 01 The next 36 bytes are not used: 00 00 00 00-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Now the disk bitmap (360/8=45 bytes), FF 01 00 00 FC FF FF FF FF FF FF FF FF FF FF FF-FF FF FF 03 00 00 00 00 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 00 00 00 00 00 tells us that the first 8 sectors (0-7) are definitely used, as is sector 8. But sectors 9-15 (>00), 16-23 (>00), 24-31 (>00) and 32-33 (>FC) are all free (that means sectors >09 to >21). This would be the 'weak' reservation that I told you about earlier - the FMS kept this area aside for future FDRs! One may hazard a guess that, if sectors >02 to >08 are occupied, then they probably contain an FDR each, and that there are, therefore, probably seven files on the disk. The bytes from and including the >FC tell us that sectors >22 to >9A are occupied, and that the rest of the disk is free. This second occupied block contains, most likely, the files themselves. This is just another educated guess - remember that the FDRs are allowed to be anywhere. For all I know there could be one large file or 64 little ones on the disk. If you want to push it, there could even be 126 FDRs all pointing to the same sector! The point is that we don't know for sure until we look at other parts of the disk. The final 155 bytes of TI-Writer's Sector 0 contain >FFs, and they don't count for anything, unless, of course if it were a double-sided diskette we were looking at. Then, the first 45 of these unused bytes would also be used for the bitmap. But in this case they're useless - you may as well store your social security number there for safekeeping... FF FF FF-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF Let's break Sector 0 down. Here are the assignments for the bytes in sector 0, with some examples in parentheses (you'll need 132 columns to print this): TI-99/4A 'DISKETTE INFORMATION' SECTOR 0 ------------------------------------------------------------------------------------------------------------------------------- | disk name | number of |sectors| | | | sectrs on disk|/ track| D S K | | (TELEVISION) | (0168) | (09) | | |-------------------------------------------------------------------------------------------------------------------------------| |Prot / | | | den- | | | unprot|tracks | sides | sity | | |(50/20)| (28) | (01) | (01) | | |-------------------------------- -| | | | unused area | | | |- ---------------------------------------------------------------| | | | | | (07) (00) (00) (00) (04) (00) (00) (00) | | | | |--------------------------------------------------------------- -| | | | | | | |- disk bitmap - 360 bits (45 bytes) for a SSSD disk - remember that each byte here is reversed | | | | | | | |- ---------------------------------------------------------------------------------------| | | | | | | | | | | | | | | (00) (00) (00) (00) (00) | | | | | |--------------------------------------- -| | | | | | | | | | | |- -| | | | | | | |- -| | | | | | | |- -| | | | | | | |- -| | | | unused - filled with >FF | | | |- -| | | | | | | |- -| | | | | | | |- -| | | | | | | |- -| | | | | | | | | | | | | | | | | | | | | | ------------------------------------------------------------------------------------------------------------------------------- I think that about covers Sector 0. ----------------------------------------------------------------------------- SECTOR 1 - FILE POINTERS Not much more to tell you about these, so let's just look at a sample. Again, we'll get it from TI-Writer: 001 00: 00 02 00 03 00 04 00 05-00 06 00 07 00 08 00 00 ................ 001 10: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 20: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 30: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 40: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 50: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 60: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 70: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 80: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 90: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 A0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 B0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 C0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 D0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 E0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 001 F0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ As you can see, I was right - 7 pointers are occupied, meaning that there are seven files on the disk. The first pointer tells us that the first file's FDR is stored in sector 2, the second in sector 3, and so on. The numbers are in numerical order - that means that the FDRs happen to be layed down on the disk in alphabetical order (which is usually the case if this disk was copied file-by-file by a program like 'Disk Manager'). If I had to create a new file with a name which came, alphabetically, before the other files on the disk (let's call it AARDVARK), although its FDR would be stored in sector >0009, it is important to know that the POINTERS would be re-sorted, so that the FDRs they point to are referenced alphabetically. What that means, in English, is that AARDVARK's >0009 FDR-pointer would come before all of the other pointers, like this: 00 09 00 02 00 03 00 04-00 05 00 06 00 07 00 08... (all of this made the untidy assumption that AARDVARK would be alphabetically before whatever the first file is called, but don't forget that we don't yet actually know the name of the first file - that we'll discover in the next section) In summary, all you've learned here is that the FMS stores pointers in the alphabetical order of the names of the files whose FDRs they point to. ----------------------------------------------------------------------------- THE FILE DESCRIPTOR RECORDS Well, now we need to examine a File Descriptor Record. This is the record which tells us all about the file we will be looking at. Where will we find such a thing? Why, on the TI-Writer diskette, of course. From the File Pointers, we can tell that there are seven files on the diskette (don't be confused by my AARDVARK example), and that the first file's FDR is stored in sector 2. Now, I don't have a clue where on the disk the actual file is stored - that's not what I meant by 'the first file' - I meant its name, alphabetically. In order to find out where it's stored, what its name is, etc., I'll have to look at its FDR in sector 2. So, without further ado, here it is: 002 00: 45 44 49 54 41 31 20 20-20 20 00 00 01 00 00 20 EDITA1 ..... 002 10: FE 00 00 00 00 00 00 00-00 00 00 00 22 F0 01 00 ............"... 002 20: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 30: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 40: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 50: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 60: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 70: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 80: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 90: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 A0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 B0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 C0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 D0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 E0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 002 F0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ Aha! As you can see, the first ten bytes represent the name of the file, including trailing spaces. So the file's name is EDITA1, which satisfies my assumption that AARDVARK would be alphabetically before this. Whew! (first rule of the scienific method: NEVER assume, you bad boy, you) The purpose of the rest of the bytes is by no means obvious to me as I look at them. All I can tell at a glance is that the file begins at sector >22, which is where I expected I'd find it. It also seems that the file will continue for another >1F sectors, meaning that it's >20 sectors in length. Anyhow, enough guessing - let me give you an official rundown of the purpose of each byte: As I said, the first ten bytes are the name, "EDITA1 ": 45 44 49 54 41 31 20 20-20 20 The next two bytes are 'reserved'. This means that they have absolutely no purpose whatsoever, and since the system has gone through over 20 years this way, they probably never will: 00 00 The byte to follow will consume mass quantities of space in this discussion - It is the type byte: 01 We will now devote a lot of time and effort to explain the purpose of this humble little '01'. Because it's a bitmapped byte, each bit will have to be looked at individually, like this: 00000001. bit 7: -FIXED/VARIABLE. The leftmost bit. What the minus sign means is that if the bit is a 0, the file is of type 'FIXED'. If the bit is a 1, the file is of type 'VARIABLE'. bit 6: I've never encountered its use. bit 5: I've never encountered its use. bit 4: This one confused me for a while. I found it set to '1' in a few files, even though it was never documented. In the end, it turned out that its use was never officially sanctioned by TI, but some programmers had decided to use it as something akin to the PC's 'Archive' file attribute. I guess TI hard drive users wanted an indication from each file as to whether it had already been backed up, or still needed to be. Anyhow, this bit serves no purpose on my PC, and if I find any files with this bit set, I kill it (the bit)! When it is set, it causes trouble with some software. bit 3: This is the write-protect bit. If it is set, it indicates that the file will not be overwritten, at least not by programs that follow the rules. The presence of this bit is indicated by a 'P' in most disk cataloguers. bit 2: I've never encountered its use. bit 1: -DISPLAY/INTERNAL. Indicates whether a file is of type 'DISPLAY' (bit is a 0) or 'INTERNAL' (bit is a 1). I've discovered that, whether you choose to open a new file as 'DISPLAY' or 'INTERNAL' makes no difference whatsoever to how the file is stored, record for record, on the disk. This confused me at first, I mean, why the distinction? But then I realised that what was different was what DATA would be written to each record, by TI BASIC, for example. If you write a number, such as 26, to a DISPLAY-type file, it will be written to the disk as >32,>36 - an ASCII representation that can be viewed on virtually any computer. However, if you write the same number to an INTERNAL-type file, the number will be stored in its floating-point representation, 40 1A 00 00 00 00 00 00 ! This number would probably not be recognisable by ANY other computer in the universe - it'd need to know the TI floating point encoding rules. Of course, if you're not running BASIC, how this bit is interpreted during file access is completely up to the software. bit 0: PROGRAM bit. The rightmost bit, it identifies whether the file is stored in memory-image 'PROGRAM' format. This bit overrides bits 1 and 7, so that they may be ignored. I have found, looking at 247 different 'PROGRAM' files that when this bit is set, bit 1 and bit 7 are both '0'. If, in a file, this is not the case, you probably have a nonstandard file on your hands. Phew! That's a lot of writing for a humble little '01'! Hopefully that will explain it fully, but what does it tell us about our file, EDITA1? It tells us that this is an unprotected 'PROGRAM' file. Bits 1 and 7 don't count in this instance. The next byte in the sequence, 00 tells us the maximum number of records stored (or to store) in a sector. This byte doesn't count in the case of 'PROGRAM' files, and I've never understood the purpose of it. It doesn't give me any information, I mean, simple arithmetic will tell me how many records can be stored in a sector, depending on the length of the record. Perhaps it's to tell the computer how many records IT may store in a sector? The next two bytes, 00 20 tell us how big the file is. In this case >20, or 32 sectors long. When you get a disk catalogue, however, you will normally be told that the file is 33 sectors in length. This is because the cataloguer normally cleverly includes the space taken up by the file's FDR. A PC, on the other hand, doesn't do that, which can be confusing when you see disk space disappearing faster than you're using it. The first byte on the next line, the 'End of File Offset', FE tells us how many bytes are used in the last sector of the file, and I'm told that this byte means nothing to a 'FIXED'-type file. The byte is here so that the loader of the file doesn't load unused superfluous data into memory. They tell me that only 'FIXED' files don't need this byte, but, as far as I'm concerned, 'VARIABLE' files wouldn't need it, either - any nutcase can tell when he's reached the end of either type file. A 'PROGRAM' file needs it because it has no other way to signal the end of a file. The funny thing is that 'FIXED'-type files actually seem more likely to need this information than 'VARIABLE' files, because they don't encode any characteristics such as length of record or end of file marker. In this case, however. we can see that the loader of this file is to load only the first 254 bytes of the last sector into memory. I'm not sure if that's an absolute value or a count value, or even if it makes a difference - be warned. ;) The next byte, 00 is not used for 'PROGRAM' files, but I'll explain its use anyway. In 'DISPLAY'- and 'INTERNAL'-type files, it specifies the length of the data. This length is either a fixed length for each record, or the maximum length of any record, depending, of course, on whether the file is of type 'FIXED' or 'VARIABLE'. 'PROGRAM' files don't use this byte because they are stored extremely efficiently - they use the entire sector for data storage, no questions asked, throughout their length, except for their final sector. The next two bytes, 00 00 are also not used by 'PROGRAM' files, but I'll have to discuss them here. They identify the number of RECORDS used by a 'FIXED' file, or the number of SECTORS used by a 'VARIABLE' file. Why the difference? Well, we know exactly how many records of a 'FIXED' file will fit into a sector - it depends on the length of the record. For example, in a DIS/FIX 80 file, the length of the record is 80, so there should be exactly three records per sector, with the final 16 bytes ignored. So, we don't need to know how many sectors are occupied, just how many records to fetch. With a 'VARIABLE' type file, however, we don't know how long each record will be, so we have no idea how many records will be stored per sector. Each record in a 'VARIABLE'-type file is 'chained' to the last, so it would probably be more useful to see how many sectors from which we need to retrieve this 'chain' of records. But now I've got my foot in my mouth, since I would not need these bytes merely for the purpose of loading the file - I could do without them. So then what REAL use could this information have? I know - 'FIXED' files can be opened for random-access... But that STILL doesn't tell me why you'd need to know how many records there are... Oh yes, it does - if you want to append to a 'FIXED' file, you need to know which record in the last sector you should start with. But then we could simply have used the byte before the last one, 'bytes used in last sector'. I give up. So, onto the next eight bytes, which are 'reserved' I think: 00 00 00 00-00 00 00 00 Sigh. The next three bytes are the final ones for consideration, but they will be complicated to explain: 22 F0 01 This is the information that tells the software where the file is stored. Now, obviously a file can get rather fragmented, that is, broken up into lots of pieces which reside all over the disk, we know that. Well, these three bytes will exist for every fragment. The fact that there are only three bytes here, and not 6, 9 or twelve, etc., means that this file is not at all fragmented. That is, the three bytes describing the fragment also describe the whole in this case. The bytes are unpacked as follows: take the LSN of the middle byte and place it to the left of first byte, then take the MSN of the middle byte and place it to the right of the last byte. You will now have: 022 01F The hexadecimal number on the left tells you in which sector this particular fragment (in this case, the entire file) starts, which in this case is >22 or sector 34. The number on the right tells you how many sectors to count from there until you've reached the last sector for this fragment. In this case, you will have to cound to >1F, or 31. Including zero, this gives you a fragment size of 31+1, or 32 sectors. Recall that the actual file is 32 sectors long (exluding FDR), so we now have the entire file's fragmentation information, and we're done here - all you do to load this file is: Go to sector >22, read it into memory and say that you now have sector 0 of the file. Move to the next sector on the disk, read it into memory and increase the count. Keep performing the last step until your count equals >01F. By now you will have realised that you've read >20 sectors, which is the actual file size, and that you're done with the file load. (Of course, not all the bytes of the last sector are to be placed in memory) That's the situation with this simple file - it occupies a block of >20 sectors, starting at sector >22. What if your disk is rather full and has files all over the place, due to an often-used and very fragmented disk. In this example, let's say we have to save the file in five pieces, as follows: 2 sectors starting at >22, 18 sectors starting at >40, 8 sectors starting at >64, 1 sector at >101, and 3 sectors starting at >111. The fragmentation information will be like this before you pack the bytes: 022 002, 040 012, 064 008, 101 001 and 111 003 The bytes will be packed onto the disk in the reverse of the order that they are unpacked: 22 20 00, 40 20 01, 64 80 00, 01 11 00, and 11 31 00 Simply write these 15 bytes to disk sequentially. Since this information starts at byte >1C in the FDR, and it takes a triplet to describe a fragment, it follows that any file may be fragmented into a maximum of 75 pieces, with one byte of the FDR remaining. I don't know what would happen if you tried to save a file of 76 sectors on a disk that had only single contiguous sectors available - I must try that someday. And that's the FDR! Herewith a summary (132 columns): TI-99/4A DISKETTE 'FILE DESCRIPTOR RECORDS' ------------------------------------------------------------------------------------------------------------------------------- | file name | reserved | file- | max | file-size | | | | type |rec/sec| in sectors | | (AARDVARK ) | (0000) | (80) | (03) | (20) | |-------------------------------------------------------------------------------------------------------------------------------| | EoF |record |#secs(VAR) | reserved | 1st fragment | 2nd| | offset|length |#recs(FIX) | | | | | (99) | (50) | n/a(PROG) (20)| (0000000000000000) | (22 F0 01) | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | |... | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | |-------------------------------------------------------------------------------------------------------------------------------| | | | | | | | | | | | | | | | | | | | | | ------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------- ACTUAL DATA SECTOR ORGANISATION Luckily, there's not that much to say about these sectors - let's go through it quickly. As far as the disk controller FMS is concerned, there are three ways of storing a file: 'FIXED', 'VARIABLE', and 'PROGRAM'. The FMS doesn't give a damn about whether the file is 'INTERNAL' or 'DISPLAY' (I think). And the three ways that it stores files are as follows: PROGRAM - Bytes are dumped from memory directly to disk, filling sectors one by one - there is no information stored in the data sectors other than exactly what came from memory, hence the term 'memory image format' - these files are snapshots of memory. The final sector of a PROGRAM file doesn't need to be used completely; the End of File offset is used to tell the loader when to stop. FIXED - Records of a predefined size are stored in a sector until there is no more space for a complete record (records are never broken up), after which the FMS moves to the beginning of the next sector available to the file, and continues. VARIABLE- Records may be of any length, up to a specified maximum, and the size of a record is determined by a preceding byte. So, right at the beginning of a file's first sector, a length byte will be recorded, followed by a record of that length, which is immediately followed by the next record's length byte, and so on, until there is no space to store the whole of the next record. Then, the next length byte is encoded onto the disk as 'FF', which tells the reader of the file to 'move to the next sector'. This continues in the next sector, and the reader of the file can tell when the final record of the final sector has arrived by the file size or the fragmentation information. Unfortunately, even though a length byte followed by 255 data bytes would exactly fill a sector, because >FF has special meaning as a length byte, it is not possible to have records larger than 'FE' or 254 bytes. On the flipside, believe it or not, a length of '00' IS valid (during reads, anyway). When the FMS reads a length of >00, it actually reads the next 0 bytes and then stops at the following length byte! Remember that DISPLAY and INTERNAL means nothing to the FMS - it simply stores the data that you tell it to, so what is written to the file is completely up to the programmer. - Brian Tristam Williams