Ruud's Commodore Site: Template Home Email

CBM-DOS


or

How I developed my own Operating System: CBM-DOS






What is it?

I hoped to present you a manual how to build your own Operating System (OS) but I soon found out that it was too difficult to present you something that was not too coloured by my own ideas. I still hope you can learn something from it.

CBM-DOS is an Operating System meant to run on (more or less IBM PC compatible) computers equipped with an 8088 CPU or better. This page also tells you how I did it and why I made certain decissions.


First: what is what

Operating System
According Wikipedia: "An Operating System is system software that manages computer hardware, software resources, and provides common services for computer programs." In my words: a program that enables a user to load, run and save programs or data on a computer and handle specific computer hardware.

File System
To be able to load data from a storage device, a program is just a special kind of data, an Operating System needs to know in some way where and how this data has been stored on this device. If it wants to store data, it needs to know where free space can be found for this purpose. A File System (FS) is a method and data structure that provides the OS with the means.


Background

At one time I was just curious how an OS could be programmed and run. I also wanted to use my own FS that was loosely based on the one used by various 6502 based Commodore drives like the 1541 and 8250 and that I wanted to use with my 1541IDE8 project. This and the goal to run it on my various Commodore PCs was the main reason to call it CBM-DOS. Just in case you don't know it, CBM stands for Commodore Business Machines.

After some time I decided that it could come in handy to have a FAT version as well. But I soon found out that it was quite some work to maintain two versions. But there was an advantage: it learned me to keep the calls to the file system to a minimum to avoid extra work. Yet at a given moment I dropped the FAT version. But I still have the idea to revive it again once Version one of CBM-DOS seems to work.

Then Michał Pleban managed to run MS-DOS 3.21 on a CBM 720 equipped with the so called Intel 8088 card. This card was developed by Commodore but never sold. There were not many cards around but I had one. Because I was interested, Michał and I decided to create a new board with Eagle so one could produce more real PCBs from it. Having such a card was a good reason to try to port CBM-DOS to the CBM 720/8088 combination as well.

Before even thinking about creating a new 8088 board, I also had the idea about creating the PC-Box. The idea for this piece of hardware was based on the SSE SoftBox: a small Z80 computer, no drives but equipped with an IEEE interface that enabled the Commodore CBM series to run CP/M 2.2 more or less. "More or less" because the CBM only acts as a terminal for the Softbox that does the actual computing.
The PC-Box can be as small as a PC board with just one LPT and COM port that, combined with two buffer ICs, can act as an IEEE interface. But the PC board has to be told in one or another way how to act like a PC-Box and the idea is to use an external ROM. The advantage of an external ROM: it can be used on almost any PC board. For more info about the PC-Box, please visit this page.

So my DOS should be able to run at least on:
- any more or less IBM PC compatible computer ranging from 8088 and up. Called PC from now on.
- a CBM-II with an 8088 card.
- PC-Box: a stand alone PC with no video and keyboard and any CBM with an IEEE interface. The CBM will then serve as terminal.

Rereading the above I found that something was missing. One could think that ANY 8088 machine can be used but that is not the case. What the above machines have in common is that they all have a more or less compatible IBM PC/XT BIOS. An IBM BIOS enables the user to handle the video of a system using INT 10h and using the floppy disk drive using INT 13h. In other words: the BIOS of a system that CBM-DOS should run on must, more or less, follow the structure of the original IBM BIOS.
In case of the CBM-II: if an 8088 program is running and sends a request to the CPU to output data to the screen, INT 10h of an IBM PC makes sure the data is displayed on the screen. In case of the CBM-II, the 8088 forwards the request to the 6509 of the CBM-II and that CPU then takes care of displaying the data. A program shouldn't even notice this difference.
Will any program that runs on an IBM PC run on a CBM-II? Unfortunately, no. But the CBM-II is not to be blamed but the programmer. The original idea of the BIOS was that, when handling video, the BIOS always should be used. But programmers found out that displaying text on the screen went much faster if you wrote it directly to the video memory instead of using INT 10h. And that was certainly the case when in graphical mode. The 8088 of the CBM-II cannot access the video memory directly so any attempt of such a program to write data directly to the video memory will end up in Limbo and nothing will appear on the screen. This was the reason that non-IBM PCs had to be "IBM compatible" otherwise text wouldn't appear on the screen or printers could not be used.


What to do about possible differences?

The CBM-II, a PC and PC-Box are too different from each other to hope that I can run CBM-DOS out-of-the-box on all three systems. One of the main differences is how a PC and a CBM handle files: a PC has to do everything itself and a CBM just asks a drive for a file and then gets it. And I don't think that can be tackled by tweaking INT 13h.
Displaying the directory is another difference. MS-DOS' DIR handles all things it self: it loads the various sectors, reads and handles their contents and displays the result. In case of a Commodore, again the drive does the major work. So should I write a DIR program for every system? And next, what about formatting a disk?

I already wrote that Michał Pleban managed to run MS-DOS 3.21 on his CBM 720. He did this by tweaking the BIOS of the 8088 card. But that is not always possible. CP/M solved this by supplying a file called BIOS. This file took care of accesing the hardware in case the ROM didn't cover it. This file is machine specific and it was the one and only file that is different within a set of CP/M files meant for another CP/M machine. Microsoft tackled this problem with the file IO.SYS. Remark: Michał knew this as well but it was a change of a few bytes and that was much easier to do than changing IO.SYS.

The idea is now to use the same trick as used by CP/M and MS-DOS: one, and only one file handles all matters that concerns the possible differences in hardware. What ever system is mentioned above (or not mentioned yet) and is going to run CBM-DOS, this system dependent file is loaded in some way into memory and executed.
I already mentioned creating a FAT version again. The FAT/BAM and directory structures are completely different and I think it will be a huge challenge to tackle these different structures with only one file. I already have a working DIR command for the CBM version but I think I have to redesign that one if I want to stick to one program for both the CBM and FAT version. Now DIR reads a directory entry and saves it in memory to handle it later. But an entry of a FAT directory is completely different. As I said, a challenge!


How to start

It was obvious that I want to develop all needed software on my laptop first. But I also needed a platform to test the results on, a platform that is easy to handle. The most easy solution is to use a virtual platform. The CBM-II has been virtualized but not its 8088 card. The PC-Box itself is just a PC but it has to be combined with a virtual Commodore and I have no idea how that can be done. But there are several PC emulators and I just had to pick the right one.
I chose for PCE - PC Emulator. This emulator only supports the 8086 but it has one major advantage on several other, more well known emulators: it doesn't waist any time to start up the BIOS. All other BIOSes emulate a PC from the moment you power it up and this means you will see the BIOS doing its things like counting the amount of RAM inside the system. PCE doesn't do this and within seconds it starts to boot and run the OS I wrote.


The File System in general

First a remark: this FS will only be used by a PC for the simple reason that the CBM-II and PC-Box get their files from Commodore drives (or compatibles) and don't have to deal with a FS at all.

From the very first IBM PC on in August 1981, the PC loads the data from the very first sector from a drive into the memory at address 0000:7C00h and starts to execute the loaded code. Forty years later, PCs with the 64-bit Core i7 still do exactly the same.
What also didn't change in those forty years was the size of a sector: 512 bytes. That is not enough to start up a real program but enough for two things:
- One: to provide the BIOS with some data about the drive, the so called "drive parameters". This is necessary because the number of tracks, the number of heads, the number of sectors on a track (in short: CHS) and therefore the size of a hard or floppy disk drive can vary. Remark: modern Solid State Drives don't have tracks and heads anymore but pure out of compatibility they make the PC think they have.
- Two: to load the very first multi-sectored program into memory and to execute it. But to be able to do so, already at this point a FS is a must.

Why are these drive parameters needed? The BIOS needs these parameters to determine where it can find for example the first directory and the BAM. The most important parameters of a drive are:
- the number tracks / cylinders
- the number of sectors on each track
- the number of heads
- the number of bytes on each sector (fixed to 512 in this case, as said before)
Other parameters given by the first sector could be, in case of FAT12 as used by MS-DOS, the size and number of FAT tables, and the number of hidden sectors.

Remark: a PC controls more or less where the head of a floppy disk drive (FDD) has to go to. In modern hard disk drives (HDD), the drive itself takes care placing the head and which head will used. The PC only has to provide the number of the sector where the data has to be written to or read from. But still the above information has to be provided for compatibility reasons.
Remark: all the info above is a bit outdated. Modern PCS use LBA = Logical Block Addressing. For this reason I use LBA inside my programs but when dealing with old XTs, I have to start with CHS. Reason: the BIOS of the first PCs doesn't know anything about LBA or even hard disk drives and only works with tracks, heads and sectors. And as my DOS has to run on these PCs, it is "When in Rome, do as the Romans do".

What information needs to be stored on a drive?
- In case of my FS, data will be stored in the form of files. Every file will have a name and that name is stored in a (sub)directory in an entry. Within a directory that name is unique. An entry also stores the information like where the first sector of a file can be found, what type of file it is and when it was created.
- If we want to store a file on the disk, we first have to know where we can store it. So we need an administration of what sector on the disk is free to use or not. In MS-DOS the FAT tables perform this function. In this case I will give this table the name of the one that performs this function in a Commodore drives: BAM, Block Availabilty Map.
- If it is a file made out of multiple sectors, we not only want to know which sectors are used but also in what order. The BAM will deal with this as well.

What sector is going to be used for what? Compared with FAT I kept it quite simple:
- The very first sector is going to be the boot and partition sector. How this boot/partition sector looks like, see later.
- The second sector is going to be the sector of the root directory.
- From the third sector on some sectors are reserved for the BAM. The number of sectors depends purely on the size of the drive. In numbers: one BAM sector is needed for every 64 sectors of the drive. So for a 5.25 inch 360 KB floppy with 720 sectors we will need 12 BAM sectors.


Master Boot Record

Under MS-DOS (and compatibles), Linux and Windows the Master Boot Record (MBR) is the very first sector of an HDD. It tells the system how many partitions are available and which one is the active one i.e. where to boot from. If the first partition is the active one, then the second sector is the boot sector of this partition.
I decided to combined both the MBR and the boot sector into one sector, also called "boot sector". Better, I'm going to use such a sector with floppies as well and, theoretically, I could create partitions on a floppy disk.


The boot sector CBM version)

A boot sector is located at the very first sector of a FDD or a partition on an HDD. As said before, it provides the BIOS with some data about the drive/the active partition and it provides the program that enables the BIOS to load a multi-sector program what starts the proces that enables te user to do what ever he/she wants the computer to do.
First sector:

*   jmp Start                                                    2 bytes
* version identifier like "CBM-DOS1    "                        12 bytes
* disk type, FDD or HDD, CHS or LBA                              1 byte
* the CHS / LBA parameters
  - cylinders                                                    4 bytes
  - heads                                                        2 bytes
  - sectors                                                      2 bytes
* number of BAM sectors                                          4 bytes
* boot drive, logical number					 1 byte
* logical sector of first program to be executed		 4 bytes
* volume ID (time stamp)                                         4 bytes
* active partition	                                         1 byte
* number of partions on this disk	                         1 byte
* logical sector of next partition            			 4 bytes

* executable code                                              454 bytes

The last 16 bytes of the sector:
* disk label                                                    16 bytes
As said, the loaded data from the boot sector will be treated as a piece of executable code so the very first bytes should an instruction. In this case the very first two bytes create a short jump to the actual code.

The version identifier tells us with what FS we are dealing. MS-DOS started with FAT12, then went to FAT16, FAT32 and to NTFS for Windows.

The "Disk type" will store information like it is removable or not, floppy disk drive ot hard disk drive, using CHS or ising LBA already from the start, etc..

The CHS parameters speak for them self. Although "heads" and "sectors" only need one byte, I reserved two for each. Main reason: it simplifies various calculations, mainly divisions by these bytes; I can use words now.

The number of BAM sectors could be calculated from the CHS parameters but this will save code at the cost of just two bytes.

When using FATxx and inspecting the data of the boot sector, you can clearly read the name of the first file that has to be loaded by MS-DOS. But that means you need code to find that file on the disk. Why not saving your self that trouble by pointing directly to the sector where the file can be found? An advantage of this method: if you want another program to be loaded first, you only have to change this pointer. Unfortunately there is also a disadvantage: if someone removes that particular file, there is a big chance that the PC ends up into Limbo.

The Volume ID enables the system to see if a disk has been changed. OK, there is a chance that two drives have been formatted at the same time, certainly on systems with no Real Time Clock, but I will take that chance.

The disk label enables the user to give the disk its own name.


Partitions

What are partitions? Partitioning a storage device is dividing it in sections where each section can be treated as a separate drive under MS-DOS, Linux and Windows. Such a section is called a partition. On a PC the Master Boot Record enables a user to boot from any partition of its choice (if bootable at all of course). This enables a user to choose, for example, between booting Windows or Linux.
I have thought about not using partions at all, why should I use them? Having more drives has its advantages like using one drive as a safety copy of another one. I decided to build in the possibility to use partitions: at least it won't hurt to have this feature for the future.
You may have noticed that I didn't use a parameter for the size of the momentary partition. The idea is that the momentary partition ends where the new one starts.
How to start up another partition? The idea is that the first partition is just big enough to hold a boot manager. Using the boot manager an user can choose which partition to boot. The user can even choose to boot this partition all the time by setting the "active partition" parameter. Make sure that there is a tool available to set this parameter to zero, activating the boot manager again.


The Directory

The root directory starts at the second sector of a disk or partition and is only one sector long. The reason for this is that in my experience any choice in size is always wrong: the dedicated directory is either too big or too small. My solution: if there is another sector needed for the directory then just allocate a free one and chain it to the last directory sector in the row.

The structure of a directory sector should look like this:
* future use                                                     32 bytes
   will be used for debugging purposes for the moment
* 10 entries of 48 bytes each                                   480 bytes
*                                                            + ----
*                                                               512 bytes
An entry should look like this:
    
* file type                                                       1 byte
* file name                                                      26 bytes
* always zero    						  1 byte
* future use                                                      1 byte
* user extension                                                  3 bytes
* pointer to first sector, LBA                                    4 bytes
* length of file                                                  4 bytes
* icon type                                                       1 byte
* date/timestamp, YYYYMMDDHHMISS                                  7 bytes
                                                              + ----
                                                                 48 bytes

Further specifications of the file type:
HEX      File type                 Directory shows 
---      ---------                 ---------------
$00      Deleted                         DEL
$x1      Text                            TXT
$x2      Executable program              EXE
$x3      Binary                          BIN
$x4      Batch file                      BAT
$x5      Directory                       DIR
$x6      BASIC file                      PRG 
$x7      Pascal file                     PAS
$x8      a user defined extension
$x9..xE  future use
$xF      ignore this file                IGN

The four bits of the highest nibble:
  value:      1           0
* bit 7: read only / read write 
* bit 6: future use
* bit 5: future use
* bit 4: future use
For this moment I don't see any use in providing the other attributes "hidden", "system" and "archived" as used by MS-DOS. Hidden files still can be shown by the DIR command so why bother to hide a file? And I never saw the added value of "system" and "archived" so why use them? A good argument is alway welcome of course!

In contrary to Windows or Commodore, CBM-DOS won't allow spaces in the names. If spaces are still used to create a name, then the OS will replace them with an underscore. The reason: although Microsoft Windows allows it, in DOS mode various programs, commands and parameters encounter problems with those spaces. And using an underscore is IMHO the way to avoid this kind of trouble on forehand.

CBM-DOS allows the use of one or more dots in a name. It has to because CBM-DOS is used as base for RB-BASIC. I want RB-BASIC to be compatible to the BASIC used on the Commodore 128 and that basic allows the use of more than one dot.
Like MS-DOS, CBM-DOS has a DIR command. How should it handle dots? Like in Windows, the last dot is always meant to specify the extension. So if you want find files that have a dot in the name, something like "DIR *.*" has to be used.
Remark: the above is still a work in progress.....

As you can see, I will use four bytes to point to the first sector of a drive. LBA uses four bytes as well but uses the four highest bits for internal purposes. As so, LBA can support drives up to 128 GB. When using those first four bits as well, CBM-DOS can support drives up to 2 TB.

When a file is deleted, the complete train of links in the BAM is deleted as well. This simply means that an UNDELETE, as possible under MS-DOS 5.0+, is not possible. If you want to know how MS-DOS does it: it keeps track of the state of a sector using a bit map table, just like the BAM in a Commodore drive does.
I gave it a thought if I should do this as well. First: it means we loose sectors to store this bit map. OK, only one for every 4096 sectors, but still. Second: we will loose time because of the extra software overhead. What will we gain: we can undelete a file but only if nothing else has changed in the mean time. IMHO not worth the trouble.
Another idea: what we can do is deleting a file in two steps. In the first step the file type is set DEL to tell the system that the file has been deleteted. Nothing else is done. Only a special command or a parameter for the DIR command will show these files. Another command will delete one, more or all these files and will set the file type to IGN and delete the pointers in the BAM. But for the moment this will be a future feature.


The BAM

First: the BAM, "Block Allocation Map", is used by the Commodore drives to store the information whether a sector on a disk is used or not. And onlt this information, nothing else. And only a single bit is used to store this information for every sector.
The first idea was to use an extended version of the link system as used by various Commodore floppy drives: the first two bytes of a sector point to the next track/sector. In case of CBM-DOS the idea was to use four bytes so the FS would be able to handle drives larger than 16 MB. An additional idea was not only using four bytes to point to the next sector but also four bytes to point to the previous one. Could come in handy in case of errors or looking for accidently deleted files.

But while programming the boot sector I realized that this idea had one disadvantage: it would be very time consuming. I first had to load the sector in a reserved part of the memory so I could copy the last 504 bytes of real data to their final destination. Whether it can be done with using DMA or not, the extra operation would cost valuable time. And then the same for saving a file.
The data of a MS-DOS sector only holds data and therefore can be copied to its final destination in one go; no time consuming extra copy actions needed anymore.
Realizing this I decided to turn the BAM into a kind of FAT: the table reserves eight bytes for every sector: four for the next record, four for the previous one. Although the BAM became in fact a FAT table, I decided to keep it calling BAM.

The BAM always starts at the third sector of a partition, after the boot sector and the first directory sector. The number of needed sectors depends on the size of the used disk. As said above: for every sector eight bytes are reserved: four bytes point to the next sector, four to the previous one. If a sector is free, all bytes are zero. The first four bytes of the last sector in the chain, are filled with $FF.

MS-DOS maintains a copy of the FAT table on every disk. The reason: if one table becomes corrupted, the other one can save the day. (ehhh, how will you know that that one has not be corrupted as well?) I decided to keep just one table. If times proofs that a copy is needed, I will add one.


Clusters

Using "clusters" is a technique used in MS-DOS and Windows. In case of CBM-DOS, every pointer in the BAM points to one sector. In case of MS-DOS or Windows a pointer in the FAT table points to a group of sectors. The first advantage was that the FAT table was much smaller than when pointing to every sector. The disadvantage: every file smaller than 512 bytes (and thus would fit on just one sector) would soup up the number of sectors allocated to a cluster.
In time the size of a FAT stayed the same but disk sizes increased. This was solved by increasing the size of a cluster. Under Windows 95 and 98 a cluster could be 32 KB big. That was changed by using NTFS under Windows NT, Windows XP and their successors.
I decided not to use clusters. Nowadays disk drives are so big that a relative big BAM won't hurt IMHO.


How does CBM-DOS operate?

It already starts with the boot sector. Its program first checks what partition should be used. If it is another then the very first one, the first sector of the next partition is loaded in memory. This sector is just another boot sector. If this was the partition we wanted to start, it would have been nice if we could start it like that. But a boot sector is meant to start from 0000:7C00h in memory and because it is loaded somewhere else in memory, that is not possible (at least not for the moment). What I do is copying the vector of the first program to be executed, add the offset of the parttition, and then execute the rest of the boot program. That will load that particular program and execute it. How this program will handle partitions, see later.
If this was not the partiotion we wanted to use, the pointer to the next partition is copied and used to load that partition in memory.
Why this "next partition" pointer only? Linux and Windows use a MBR that enables them to select from four partitions. And I already read that it was not enough for some people. My way takes a bit more time because of the extra sectors that have to be loaded, but with a limit of 255 partitions (for the moment) much better than those meager four :)

The first and only file to be loaded and executed by the boot sector (PC), internal ROM (new 8088 card with 64 KB EPROM) or external ROM (PC-Box) is the file COMMON.EXE. The few things it does is:
- Setting various variables and pointers to some tables.
- Installing new or changed interrupts when needed by CBM-DOS.
- Loading the file CONTROL.EXE, just loading, not executing it.
- Checking if the file AUTOSTART.BAT exists and if so, run it using the program BAT.EXE. BAT.EXE on its turn starts the already loaded CONTROL.EXE when AUTOSTART.BAT has been finished.
- If AUTOSTART.BAT does not exist, COMMON.EXE starts CONTROL.EXE.

Three remarks about AUTOSTART.BAT
- It can be used to load drivers by the user. So, like the ones loaded by CONFIG.SYS in MS-DOS, they are loaded before any other command is executed.
- It is possible to start a program by AUTOSTART.BAT that won't return to the original prompt and can run for ever.
- One of the programs run by AUTOSTART.BAT can replace CONTROL.EXE with an alternative one. The Memory Management Table can tell the program where the original CONTROL.EXE resides.

CONTROL.EXE can only be compared partly with MS-DOS' COMMAND.COM. Like COMMAND.COM, it accepts commands from the command line but the main difference is how they are handled. COMMAND.COM has several internal commands like DIR, VER and TIME. In CBM-DOS these are external commands, just like in Linux. The advantage: CONTROL.EXE is a much smaller program than COMMAND.COM. The disadvantage: when using subdirectories, using a PATH is a must otherwise these now external programs can not be found and started.
Remark: directories are not supported yet.


COMMON.EXE

By the time I figured out the above I already had a file named COMMON.EXE. This is a binary file that contains a lot of useful routines that are not only used by the various system programs but also can be used by any programmer. Consider it as an equivalent of Windows' DLL, Linux's Shared Objects or MS-DOS' INT 21h. It is loaded at 0140:0000h and that is where the rest of every bit of other software think it will be. Its structure is simple: it starts with a jump table and after that table you will find the actual routines.
Why this file? Two of its subroutines are LookForFile and LoadFile. They make use of INT 13h and that makes them sector dependent. My first idea was to change INT 13h but I soon found out that INT 13h it self is already sector oriented and could not be used for loading files or subdirectories: that has to be done at an higher level. So I had to change COMMON.EXE at a higher level as well.
When taking LookForFile as example, this routine needs to check = read the directory. The program DIR needs to read the directory as well. So it is very logical to use a common routine for it. This means that in these two cases I have to adapt COMMON.EXE at only one place instead of two.

But what if the basic interrupts given by the BIOS have to be changed? In MS-DOS this is one of the main purposes of IO.SYS: alter an interrupt vector when needed. COMMON.EXE is started by the binary on the boot sector and the first thing it can do is changing interrupt vectors when needed. Other possibilitiy is using AUTOSTART.BAT, see next part.

How is COMMON.EXE started? Quite simple in fact. As said, COMMON.EXE starts with a jump table. Every CBM-DOS executable starts at address zero and COMMON.EXE is no exception. In this case the first instruction is the first jump of the jump table. This far jump jumps to the actual program that does all the things described above.
Why a far jump? Originally it all were all three-bytes jumps, just like the Commodore ones. The idea was that if somebody wanted to use its own routine, this person only had to change the related jump. During a discussion with Michał I realized that this construction forced the user to stay within the same 64 KB segment. And what if all this memory is souped up by a program? A far jump can point to any part of the available memory.
But the change caused a problem: the original routines ended with RET and it is not a matter of just replacing them with RETF. The reason for this is that a lot of routines call other routines inside COMMON and then a RETF cannot work. So I decided to let all those new far jumps point to a small routine that only calls the original routine and ends with the needed RETF. Advantage: the extra routines were created using a little macro within a few minutes. A possible disadvantage: it surely made COMMON.EXE longer.


The usage of the memory

0000 - 03FF:  interrupt vectors
0400 - 0501:  BIOS variables
0600 - 07FF:  memory reserved to save a directory sector
0800 - 09FF:  memory reserved to save a BAM sector
0A00 - 0BFF:  memory reserved to save any other sector
0C00 - 0FFF:  Memory Management Table (MMT)
1000 - 13FF:  File ACcess Table (FACT)
1400 - 7BFF:  COMMON.EXE
7C00 - 7E00:  boot sector, 

The "File ACcess Table" wil be used for storing information what or who is using this file and how it is used. I have no ideas yet how to use it.

As you can see, the boot sector is loaded at $7C00. This is a fixed number inside the BIOS and cannot be changed. This limits the size of COMMON.EXE to 26 KB. But only initially. If there is ever a need for a COMMON.EXE bigger than 26 KB, the solution is to create a loader that is loaded by the boot sector. This loader is not loaded at $1400 but somewhere higher in memory and then loads this bigger COMMON.EXE. As the boot sector is out of the scope now, overwriting it will be no problem.


Memory management

CBM-DOS has to keep track of what piece of memory is used by which program. Here comes the Memory Management Table (MMT) in view. It is 1 KB of memory where each byte represents 1 KB of memory. The possible values of this byte:
- 00 = used by CBM-DOS
- 01..F9 = used by program, value = ID
- FA = Open File Tables (OFT) - FB = variables - FC = process table - FD = known ROM
- FE = not existing or unknown
- FF = known free to use memory

Remark: the 8086/8088 has no memory protection of any kind. So any program can disregard this table and overwrite or use any piece of memory as it likes to.


Processes

CBM-DOS keeps track of the processes that are running. Again memory is needed. Having no idea at all how much is needed, I decided to reserve 1 KB at the top of the memory with the possibility to extend it with more memory when needed. The last entry inside the block will not point to a process but to the segment of this next 1 KB block.
The structure of this table, 15 entries of 32 bytes:
- 0..27   zero ended string with the name of the program/process
- 28      parent process
- 29      future high byte
- 30/31	  segment where program is loaded	
The 16th entry is reserved for pointing to the next 1 KB block, if needed.

Handling files

I didn't give this section much attention until I needed to when programming my Pascal compiler. I already was able to load and execute programs with CONTROL.EXE by using one of the routines in COMMON.EXE. But it loads a complete file and it is not able to handle it byte by byte, if needed. The Pascal compiler made me realize that I needed more routines like one for opening a file, closing one, etc.
Where to store this information? MS-DOS does it in memory, the Commodores store the state of a file in the file type byte of the entry for this file inside the directory of the disk. The last read directory sector is stored in RAM and we could use that one but there is a good chance that, when a program wants to access a file, this file will be on another directory sector. This does not only mean we have to load this sector to check if the wanted file is already in use but it is possible that we have to save the contents of the buffer to the disk first. Another approach was needed.

1 KB of memory at the top of the memory is reserved for storing these accesses in a table: the File ACcess Table (FACT). Is this enough? I have no idea and again the idea is to make this table extendable, just like the Process Table, by reserving memory at the top of the memory. The last entry inside a block will point to the segment of this new 1 KB block.

The structure of this table:
- path/name of the file, 0FFh ended.
- ID of the proces using this file, 1 byte.
- state byte for this file, 1 byte.

Meaning of the state byte:
- 0 = file has only be opend
- 1 = only read access
- 2 = delete the file and write to it
- 3 = read and write (= replace) bytes of the file

As you can see, this block has no fixed structure. The number of entries it can contain purely depends on the lenght of the path/name combination of each enytry.


The needed routines to handle files

Open a file
This routine only notes down the name of the files and what program opened it. Nothing is done on any drive. The "type of access" byte is set to zero.
"Assign", as used by Pascal, would be a better definition but more leaning towards Commodore, specifically BASIC, I will use "open".

Read from a file
This routine enables a program to read one or more bytes from a file. The "type of access" byte is set to 3 = "read/write" by default. This disables any other program to at least read the file as well. By setting the "type of access" byte to 1 = "read only" enables orher programs to read this file as well.

Write to a file
This routine sets the "type of access" byte to 2 = "write only". If it exists, this routine will delete the file and create it again. Then bytes can be written to the file, one by one.

Create a file
This routine will create a new file. If the file already exists, an error will occur.

Delete a file
This routine deletes the entry of a file in the directory and will delete it from the BAM.

Load a file
This routine will load a file as a whole in one go into the memory.

Close a file
This routine will close a file and make it available to access it again.

Rename a file
This routine will give the file a new name.

Seek inside a file
This routine will set the work pointer somewhere inside the file so it can be read from or written to from that point on.


Variables

Like Linux and MS-DOS, CBM-DOS will be able to use variables. Functions will provide means to set and get them. Like with the FACT, 1 KB of memory at the top of the memory is reserved for storing the variables. And also this table is extendable by reserving another 1 KB block at the top of the memory. The last entry inside the a block will give you the segment of the next 1 KB one.


Versions

At the moment it is just version 1. The main goal is to get it running with as much tool as possible but this version 1 won't support subdirectories yet. I'm working on it but it is more complicated than I thought. Version 2 will support directories.

Then, what next? Networks come to my mind but that means drivers and I have no experience whatever with programming these things for network cards. OTOH I always prefered using the LPT port for exchanging data with other older PCs using UFO, a LapLink equivalent. So that is one tool I like to create. But I prefer to create an equivalent of MS-DOS' INTERLNK and INTERSVR.
And we also need things like an editor, assembler, compiler, etc, etc, etc. More than enough things to do.....


Hey, wait a moment, can one do without an Operating and/or File System?

Sounds weir but yes, one can! I have known games that started directly from floppy and were not recognized as a normal floppy by MS-DOS. I don't know how these games did that but I can give you my ideas. The boot sector just tells the PC to load a number of sectors located, for example, after the boot sector into memory and then the boot sector tells the CPU to start at a certain address. And that's all! If the game needs to store a score or what ever data, it can be done on sectors that are hardcoded in the program. No OS, FAT or directory needed at all.
Drive parameters are still needed but they can be hardcaoded in the program as well. In this era with multiple floppy types, it is just a matter of using compiler directives to tell the assembler for what type of floppy the program is meant. It can even be done with hard disk drives. IMHO it also can be done with CDROM, DVD or an USB stick but I have no idea how to program that.


To be continued.............





Having questions or comment? You want more information?
You can email me here.