Amiga 600 video encoder upgrade
For those of you who, just as me, are bothered with the bad composite video output of the Amiga 600/1200 I may have found a very effective upgrade. For some time I have wondered why the output lately seemed to be getting significantly worse as years went by. At first I thought it was just never monitors that had bad analog video circuitry compared to older ones but recently I definitely noticed a significant degrading in video output on my machines. The big plague that is tormenting all of these machines are the leaking electrolytic capacitors. They have come to an age now where generally all of hem are affected and must be dealt with as soon as possible to no be destroyed from within! The replacement of capacitors are an absolute necessity but it's something I won't cover in this article. There are plenty of existing guides out there already. At first a thought that this whole capacitor situation was to blame for the picture degradation but after re-capping two PAL Amiga 600 machines without any obvious improvement in the video output, in fact the re-capping actually made things worse, I began to wonder what was really going on. Both machines eventually started having problem with the reg/green color phase and color flickering. A common problem when the color delay is acting up. Remember, PAL inverts the color phase on every other line and if that phase is unstable it will result in color flickering. This red/green flickering situation got me wondering about how the video encoder chip in the Amiga 600 actually worked. It uses the CXA1145 chip by Sony. The same chip is used in many other consumer equipment and video game consoles from around that time. The CXA1145 design relies on two specifically delicate external components. One delay line and one band pass filter. Those were my primary suspects. In the Amiga 600 design they are called Z221 and Z222. The datasheet is pretty vague regarding these components. It mentions that the BPF should be centered around 4.43MHz for PAL and 3.58 MHz for NTSC, the color carrier frequencies, and the delay line should be 180ns in both cases. This is a picture over the area covering the video encoder circuit of an Amiga 600. Commodore did not use the filter and delay line mentioned in the CXA1145 datasheet but instead some other ones (the rectangular shaped RF cans on the left side of the picture). Actually the delay line consists of three cans connected together in serial and the band pass filter is a single can. I have not managed to properly identify them nor source new ones and they are pretty tricky to de-solder so I would rather avoid that. On both the Amiga 600 I recently restored I had to clean the area around Z221 and Z222 thoroughly to get rid of the leaked-out and corrosive capacitor electrolyte. In the picture above the area has been cleaned and all electrolytic capacitors replaced. I suspect my thorough cleaning is part of what quickly worsened my video problems. My theory is that Z221 and Z222 cans are sensitive to various cleaning detergents. In my case I think my use of isopropyl alcohol in the area is to blame. I could clearly see the picture degrading after cleaning. The components Commodore used for Z221 and Z222 filter and delay line may not be aging gracefully and are not robust enough to survive a leaky capacitor and cleanup. In fact I suspect the leaking capacitor electrolyte itself may even deteriorate the Z221 and Z222. They have a typical RF can style construction with an open bottom against the PCB. Any fluids on the PCB will effectively move up into the can because of the capillary force. This got me thinking about a possible replacement for the Amiga 600/1200 analog video section. Preferably a solution that would fit inside the case and one that also had to be fully reversible. This turned out to be easier than I initially thought! The diagram above is taken from the CXA1145 datasheet and shows the example circuit suggested by Sony and is basically the same design used by Commodore in the Amiga 600/1200. The bandpass filter and delay line are marked with red. Sony made an updated video encoder chip named CXA1645 that is almost pin-compatible with the CXA1145 and it does not depend on external bandpass filter and delay line! Instead those pins are used to provide a real S-video output. This is the suggested CXA1645 circuit from the datasheet. Very similar to the CXA1145. I have color coded the main differences. Red - pins with new function compared to existing circuit Blue - new or altered components Green - S-video output The changes required compared to the original circuit is pretty small. What I did was to remove the old CXA1145, replace it with a new CXA1645 and piggy-back the new and changed components around it. Worth mentioning in this case is that the CXA1145 has an audio buffer between pins 8 and 9. Those pins have other functions on the CXA1645, thus the audio to the RF modulator is lost by doing this mod. To me that was no issue but if you really want to keep the RF modulator audio working you could probably just bridge pins 8 and 9 together on the back of the PCB in order to restore that function. DISCLAIMER: This is NOT a beginners modification. It requires proper equipment and good surface mounted soldering skills. Make sure you know what you are doing and if in any doubt, leave it to someone who have the proper skills and tools. These computers are not made any more and are only getting fewer and fewer. Do not take any chances. This is only a documentation of what I did. I can not be held responsible for any eventual damages you may cause by performing this modification yourself. Step one - Removal of the CXA1145. Step two - Isolate changed pins with kapton tape. Placement of tape marked in red. Step three - Solder the new CXA1645 on top. Step four - Add components. The 1% 16k resistor between pin 18 and ground sets the color signal amplitude. I only had 5% resistors so I used one 15k and one 1k i series and measured a few samples using a calibrated LCR mater until I got well within the 1% mark. Step five - Annoy cat with fine picture and colorful mouse pointer. This has been a very successful modification. The picture is really good now. Better than I can remember it ever was and this is only composite video. Next step is to explore the possibilities with the CXA1645 S-video output. This modification was performed on an Amiga 600 but should be more or less the same for Amiga 1200 as well.
Native assembler and line editor
This article is updated 2022-08-28! To me, a big milestone when designing a computer is that very moment when the computer is capable of editing and compiling its very own source code. One might ague that a BASIC interpreter is a way to do this but I wanted to take this even further. This is a big event in my MC3 development. After completing the first really usable version of my file system MCFS2 I began working on two crucial accompanying applications, a line editor and an assembler. These two have now reached a level where they are actually usable.

Line editor

Before there were video terminals the only real teminal-like way of interacting with a computer was through a paper teleprinter, commonly known as a "teletype". Without a video terminal there is no way to move a cursor around. You can only enter commands one line at a time and the result will be printed line by line on a roll of paper. A line editor is a way to edit a text file using this environment. It's a bit like writing a BASIC program actually. Every line of the text file has a number and lines are altered by replacing the entire line. I'm not using a teleprinter but the principle is quite easy to implement and the neat thing is that it will work regardless of the terminal used since no special control codes are needed (unlike a modern editor like emacs or vim). My line editor is very simple. The editor can be started without arguments to create an empty file or with a file name argument to load a file into memory for editing. The editor have two modes. A command mode and a text entry mode. When started it enters the command mode indicated by a "::" prompt. Typing "help" and <enter> shows the available commands. Commands are not case sensitive and can be shortened by typing only its first letter. For example the command "s" is the same as "save". At any point, pressing ESC ($1b) will put the editor back in command mode ("::" prompt). /devel/ # edit myfile.asm :: help Line editor v1.2 Daniel Tufvesson 2017-2022 Insert <line number> Delete <line number> Print <starting line number> Replace <line number> Save Help Numbers (on/off) Quit :: There are currently two ways of manipulating text. By inserting a line and by deleting a line. Below is an example of entering a few lines of text. For clarity, I have also typed in the line-ending key strokes. :: insert 0 : This is a line of text <enter> 1 : This is another line of text <enter> 2 : Third line of text <ESC> :: The insert command can also be followed by a line number to insert a line number to insert lines at a specific place in the file. :: insert 2 2 : Text squeezed in between existing lines <enter> 3 : Another line <ESC> :: The replace can be used to replace a line. Existing line will be printed and the new line contents can be entered. :: replace 0 0 : This is a line of text 0 : This is the first line of text <enter> :: The print command will print the current file to screen. It's somewhat like the "list" command in BASIC. :: print 0 : This is the first line of text 1 : This is another line of text 2 : Text squeezed in between existing lines 3 : Another line 4 : Third line of text :: It will print a page of up to 20 lines at once and pressing <enter> will print another 20 line page of text. Pressing <ESC> will abort printout and return to command input. The print command can be followed by a line number to begin printing at a specific point of the file. The save command will prompt the user for a filename and save he file to the current directory. If the editor was used edit an existing file, the suggested filename will be the same as the opened file. Saving will always overwrites existing files so some care must be taken when naming files. The number command will turn line number display on and off. Download the MC3 line editor: - source - listing - s19


This really is a core piece of software in the MC3 project. I tried to make the code simple to follow rather than effective so it will not win any prizes for speed but it works really well. I wanted to make an assembler that I could use instead of the cross assembler on my PC. It had to be useful and reliable and I think I managed to achieve that. The assembler is made for 6301/6303 CPUs but can be used for the 6800 as well if only 6800 opcodes are used. This is the quick help that the assembler prints out if no arguments are given. /devel/ # asm 6301/6303 assembler v1.0.2 Daniel Tufvesson 2017 Syntax: asm [files] [-l] [-e] [-d] [-tXXXX] Options: -l Generate listing -e Hide errors -d Assemble directly to memory -tXXXX Move symbol table to address $XXXX (default $0100) /devel/ # The basic principle of operation of the assembler is that it sequentially assembles the files given on the command line in two passes. Only a small part of the source is kept in memory at once to make room for as much generated program code as possible. This results in a lot of small file system reads and slows down the process substantially but enables assembly of large source files that would not normally fit in memory, I think it's a reasonable compromise. The first pass identifies all labels and builds up the symbol table in memory. The second pass completes the final assembly. Source files must be defined before any options. Example:/devel/ # asm file1.asm file2.asm file3.asm -l -d -t4000 Without any options the assembler only builds up the symbol table and verifies the assembly. No program listing or machine code is generated. Good for verifying source code without using up unnecessary memory. Errors are reported and printed to the screen. To actually generate anything, an option must be given. See explanation of options below. Generate listing (option -l) This option prints out the program listing. It will show the filename, line number, assembly line and generated data. When the assembly is complete it will end with printing the symbol table. Assemble directly to memory (option -d) This option will tell the assembler to write the generated machine code and data directly to memory. Move symbol table (option -tXXXX) When assembling code to memory there is a risk that the symbol table will collide with the generated data. Therefore this option allows for moving the start of the symbol table to another place in memory rather than the default $0100. This is the only option that takes an argument. A four character 16 bit hexadecimal address must follow directly after the "-t". Hide errors (option -e) This option will hide all errors from the printout. They will however still show up in the error counter. As you see from the options, the assembler generates machine code directly to memory. Right now it was the easiest and yet most flexible method to implement. It leaves the program directly executable in memory directly after assembly for fast turn-around time when developing. In the future I will probably extend the functionality to generate S19 files directly. Right now the easiest way to save an executable program back to the file system is to assemble to memory and then save the generated memory range to file. This method also memory efficient since S19 data takes up a lot of space.

Assembler specifications

- Source file size limited only by the file system - Number of source files limited only by the command line length - Length of labels is limited only by memory space (longer labels consumes more memory) - Machine code generated and written directly to memory - Symbol tale can be moved to any unused memory area - Direct memory addressing can be controlled by the "<" character as in 6809 assembler I hope you find this interesting. I've never seen a native 6303/6301 assembler out there in the wild before. This is probably my most serious software project for the MC3 and I will keep improving it in the future. Download the MC3 native assembler: - source - listing - s19
Calixto Island Adventure
In my ever ongoing hunt for 6800 software I came across an old FLEX disk with this program on it that looked interesting. adventur.cmd An executable file and by the name it looked like some kind of adventure. It immediately caught my attention but it crashed when I tried running it on my MC3 computer. Still, I was curious about it. Using my cmd2bin converter I was able to extract one continuous chunk of binary data from the CMD file. adventur.bin - load address $0100-$32F1 A quick look with a hex editor revealed ASCII contents that definitely looked like a classic text based adventure game. Now this was getting exciting. Further digging and disassembly revealed a quite elaborate program that definitely was a game. A game called "Calixto Island Adventure" made by Mark Data Products in 1981. The text only version of the game was created by Ron Krebs. I believe that may be the one I'm having here. The 6809 and 8086/8088 source has been released to the public by Bob Withers and Steve O'Dea, creators of the CoCo and IBM/PC versions of the game, so I figured it would be okay to distribute this one as well. This is the first and only 6800 release of the game I've ever seen. Below is my disassembled version. I've translated the external FLEX labels. The program relies heavily on jump tables that I have not translated to proper labels so the code can not be re-located as it is right now but I did not need to do that. The code loads and begins at $0100 which is pretty standard for most 6800 programs. Digging into the code too much might also spoil the game play for me so I did not want to risk that! adventur_disasm.asm The use of the zero page made it clear why the code did not run on my MC3. The 6303 CPU I use have the first 32 bytes of zero page reserved by internal registers and the Calixto Island code had variables starting at $0000 and up. Relocating them 32 ($20) bytes up was the only thing needed to get the game running on my system! I'M IN PROFESSOR LAGARTO'S COMFORTABLE STUDY. VISIBLE ITEMS HERE ARE: A FLIGHT OF STAIRS. A ROLLTOP DESK. AN ORIENTAL RUG. AN ANTIQUE TABLE. WELCOME TO THE CALIXTO ISLAND ADVENTURE TELL ME WHAT TO DO ! The game it self is a classic VERB+NOUN text adventure. User give commands like "OPEN DOOR", "GO PASSAGE", "GET OBJECT" or "PRESS BUTTON". There is also the possibility to save the current progress to a FLEX file which is a really nice feature. The user can choose the file name of the saved game to load or save. It's also possible to change the save file name during the game. To save a game simply give the command "SAVE GAME". To stop playing say "QUIT". To see what items you are carrying use the command "TAKE INVENTORY". The file access is based on FLEX 2.0 routines so I have converted my MC3 version of the game to use my MCFS2 instead for file access. It was a good practice run for this type of conversion. adventure_mc3.asm Above is the MC3 version of Calixto Island Adventure. I have located the FLEX LOAD and SAVE routines and added new ones. This file should be a good start if you want to convert the game for your own system. Happy adventuring!
MCFS 2.0.2
Not long ago MCFS 2.0.1 was released and it's time for an upgrade. This is version 2.0.2 with fixes for the built-in "cd" command and separation of the source code into multiple files for easier read and conversion to other hardware.

Change Directory command

This command now behaves more like it's UNIX equivalent. It's now possible to enter paths with multiple directories like "cd games/adventure". Paths starting with "/" refers to an absolute path beginning from the root. It's also now possible to go up one directory by "cd .." as commonly available on other systems.

Source code for MCFS 2.0.2

The source is now a little more structured than the previous version and has been divided into four files. mcfs2.asm - main code mcfs2_rtc.asm - driver for the real-time clock mcfs2_storage.asm - driver for flash card storage mcfs2_ram.asm - variables in RAM format.asm - flash card format routine (use with caution)


The source files need to be combined in order to compile MCFS2. Either the assembler have the ability to read all files sequentially or they can simply be concatenated before compiling. Example 1 - all files at once # as1h mcfs2.asm mcfs2_rtc.asm mcfs2_storage.asm mcfs2_ram.asm # as1h format.asm mcfs2_storage.asm Example 2 - concatenation # cat mcfs2.asm mcfs2_rtc.asm mcfs2_storage.asm mcfs2_ram.asm > combined_mcfs2.asm # as1h combined_mcfs2.asm # cat format.asm mcfs2_storage.asm > combined_format.asm # as1h combined_format.asm Care must be taken to read the files in the right order. As a reference I have included my resulting S19-files. mcfs2.s19 format.s19
MCFS2 - A file system!
This is quite a big upgrade to the MC3 computer. I have had this idea of creating my own disk operating system in the back of my head for a long time. The most common and widely available disk operating system for the 6800 is FLEX. The source code is available and relatively well documented. I struggled with FLEX for quite some time and wrote a compact flash driver for it that gave me four 16MB drives. Huge amount of data actually for this kind of system. Shortly thereafter I realized the biggest limitation with FLEX is that it does not handle directories. All files resides in the root of the drives. That is absolutely fine when you are dealing with floppy disks (as originally intended) but as soon as you connect a set of fixed large drives of many megabytes, that in theory could store thousands of files, this will become quite a severe problem. FLEX is also not very good at deleting files. There is no sector allocation table for example so after a while your file systems will begin wasting space. This led me into this project of designing a new and more modern disk operating system for my MC3 computer.

Introducing MCFS2

The MCFS2 is designed with small 8-bit computers in mind while still keeping it relatively modern. It's not intended to store data efficiently. It's made to be simple. Connecting a modern flash storage device, such as a Compact Flash card, to a small 8-bit computer provides practically endless amount of storage space.

MCFS2 basic design criterias

- Designed for flash storage - Easy to implement on an 8-bit system - Directories and sub-directories - Allow long file names - UNIX like file attributes ("r w x") - Case sensitive (like UNIX) - Automatic time stamps - API for user programs - Kernel in ROM - Custom system commands stored on file system

The hardware

SD and CF cards in ATA mode have a fixed sector size of 512 bytes. That will work fine for this project. The 28bit LBA sector addressing is a bit more complicated. There are no 28 or 32 bit registers in my 8-bit 6303 CPU. Dealing with those big numbers will cause a performance penalty for sure. Also 512 * 2^28 = 128GB is an enormous amount of addressable space. I would never need that much in my system. Therefore I opted for a simple solution; keep all sector addresses 16 bit long. That would limit the file system size to 512 * 2^16 = 32MB but that is still a lot of space for this kind of system. Also, it would still be possible to have several 32MB partitions on a single storage device for even more space. By keeping partitions starting points on 32MB boundaries one could just simply set-and-forget the upper 12 bits and mask away the lower 16 bits for use within the partitions. Simple! Two things I realized I would need in order to make this a reliable disk operating system was a stable connection to the storage device(s) and a reliable RTC (real time clock). My MC3 had neither. To make this project go forward I would need to add hardware. I decided to design a single card containing the extra components needed to get MCFS2 running. I call it the OS-card. After deciding on Compact Flash as the primary storage of choice I began digging for a suitable RTC chip. I wanted something simple. My previous RTC interfacing attempts had resulted in a lot of code to get it going. This time I wanted my time stamp to be more or less just a part of the memory space. Back in the days there were a few suitable chips but most are difficult to come by today. One type of chips however that is quite common are 4-bit RTC chips. Several vendors make them. Basically they have 4 data pins and 4 address pins making them show up as sixteen 4-bit registers. In my design I used the RTC72421 from Epson. It even contains it own built-in high precision crystal oscillator. A similar chip is common in for example the Amiga. The RTC72421 register map can be seen below. The first 13 registers of the RTC72421 is common for most 4-bit RTC chips. From other vendors as well. There is however no century register so that will have to be handled separately. In addition to Compact Flash and RTC, I wanted to add some additional RAM. The main reason for this it to have some memory dedicated to the operating system. The old MIKBUG and FLEX implementations relies on RAM at address $A000 and up. My existing memory board contains plenty of RAM but it's all on other memory pages. Keeping the I/O devices and the operating system RAM on the same memory page would speed things up substantially. I found some 6264 8kB*8bit CMOS RAM chips that would be perfect. Since they are CMOS they are also well suited for battery backup. Backing up the RTC would be required anyway so backing up the RAM would require minimal extra effort. The battery backed up RAM could also solve the problem with a missing century register in the RTC72421. Features of the OS-card - Two Compact Flash sockets - RTC72421 - 8kB battery backed up RAM Schematic above is pretty straight forward. Signals to and from the bus are buffered through '244 and '245 drivers. Address decoding is performed using a few '00 gates and half of a '139. The battery backed up devices (RTC and RAM) needs to be write protected when system voltage is low to keep their contents from being corrupted when powering on and off the system. That is accomplished using a simple two resistor 1/2 voltage divider (R3 & R7) driving the active-high chip select inputs of the RTC and RAM. Theory is that the chip select signal will then be active late when powering up and inactive early when powering down. I know there are better solutions but for now this is good enough for my needs. Address map for the OS-card $9fc0-$9fcf: RTC $9fd0-$9fdf: Compact Flash socket 0 $9fe0-$9fef: Compact Flash socket 1 $9ff0-$9fff: (unused/spare) $a000-$bfff: RAM (8kB) In my MC3 the board is placed in I/O page 0 along with the other I/O devices on the I/O back plane. Even though the 8kB RAM is taking up half of the I/O page space there is still plenty of room for other devices both current and in the future. This is a picture of the board taken from the top. It's a standard euro board that fits nicely along with the other boards in my MC3 system. The Compact Flash cards are accessible from the long side of the board which is a bit unusual but since the MC3 boards are stacked and not placed in a frame they are accessible from all sides. When the picture was taken only one of the Compact Flash sockets was soldered in. It's pretty time consuming since the pins are so small and close together but the end result is pretty nice. The battery installation is more or less temporary. I've not yet found a solid socket solution that I like. The back side of the board. Same construction principle as the other MC3 boards. I'm beginning to like this soldered wire-wrap technique even more. It's pretty quick, solid and relatively easy to make changes since wires can be re-used instead of scrapped as often happen with regular wire-wrapping.

The software

This is probably the biggest part of his project and the part that has taken up most of the time by far. Perhaps not in actual coding time but in time spent just plain thinking about it. I could do some early development using my old Compact Flash I/O card but when I got the OS-card ready the code pieces fell into place fairly quickly. The MCFS2 software can be divided into two parts; the file system on flash card and the kernel in ROM. Together they form the disk operating system. I want to keep the kernel in ROM for speed and reliability. That way the kernel will not be corrupted by a program going berserk and possibly destroying the file system in the process.

File system concept

The MCFS2 file system begins with a description sector. This sector identifies the file system and contains the parameters needed to access it. These parameters are set during formatting and is a way of making the file system adaptable. In general the description sector is unaltered during the life time of the file system. Following the description sector there can be three kinds of data areas. - Sector allocation table - Directory data - File data The description sector contain pointers to the allocation table and to the root directory. The sector allocation table is a map over all sectors in the file system beginning with the description sector and ends with the last addressable sector in the file system. The table contains one byte for each sector. First byte corresponds to sector 0000, second byte corresponds to sector 0001 and so on. Since the maximum size of an MCFS2 file system is 65536 sectors, the allocation table can be up to 128 sectors long. 65536 sectors / 512 bytes per sector = 128 The size of the sector allocation table is determined when formatting and the table must be placed in a continuous chain of consecutive sectors. It can not be fragmented. A zero value in the allocation table means that the sector is free unallocated and free to use. A non-zero value means that it's allocated and contains data. Right now I use the values $00 and $01 for this but in the future other values may represent different attributes to the sectors. A directory is also a continuous chain of consecutive sectors. Each sector contains eight directory entries. A directory entry is 64 bytes long. Each directory entry contains information about the file or directory (such as name and creation date) and a pointer to the actual data. Attributes are; R = readable, W = writable and X = executable. Directories can not be executable. Same thing goes for files. They are also a continuous chain of consecutive sectors. No fragmentation anywhere. That makes file operations fast and simple. Definition of volume header - first sector of file system 4 byte - file system magic ID = "MCFS" 1 byte - file system version = $02 2 byte - first sector of volume (this sector) 2 byte - last sector of volume 2 byte - volume ID 32 byte - volume label (zero terminated) 2 byte - first sector of allocation table 2 byte - last sector of allocation table 2 byte - first sector of root dir 2 byte - last sector of root dir Definition of directory entry - 8 entries per directory sector, 64 bytes each 1 byte - flags [INUSE DIR FILE 0 0 X W R] 2 byte - first sector 2 byte - last sector 4 byte - size 2 byte - date year (BCD) 1 byte - date month (BCD) 1 byte - date day (BCD) 1 byte - time hours (BCD) 1 byte - time minutes (BCD) 1 byte - time seconds (BCD) 32 byte - name (zero terminated) 16 byte - reserved for future use, set to zero Diagram trying to illustrate how the different data areas relates to each other That is really the only data structures used in the file system. The actual sizes and positions of the object on the storage medium is determined by the formatting software and the kernel itself. Directories can be created in various sizes. The standard size I have selected is 8 sectors. That gives 8*8 = 64 files in one directory but the only technical limit is the storage space. It is possible to, for example, create a directory that uses up all the storage space but that would be pretty useless. Very large directories will also have a quite big performance impact.

Formatting procedure

Three things needs to be set up in order to properly format an MCFS2 volume; the volume header, allocation table and root directory (the three leftmost objects in the diagram above). In my MC3 system I decided to create the biggest possible MCFS2 volume. 32MB! First thing to decide is where the volume should start. Since MCFS2 uses the 16 least significant bits of the 28 LBA bits it is important to make sure that those two last bytes does not wrap around within the volume. That will cause bad things to happen. Creating a 32MB volume means that the volume must start at LBA $xxx0000 and end at LBA $xxxFFFF. My current formatting program places the volume at LBA $0000000 up until LBA $000FFFF. That gives a total of 65536 addressable sectors. The first of these sectors must contain the volume header. Directly following the volume header I place the sector allocation table. Since there are 65536 sectors in the file system, the allocation table must hold 65536 bytes. That requires 128 sectors. Thus, the next 128 sectors will be allocated for the allocation table. After the allocation table follows the root directory. This can vary in size but I have selected 8 sectors. That gives room for 64 entries in the root directory. Layout after formatting Sector 0000-0000 : Volume header (1 sector) Sector 0001-0080 : Allocation table (128 sectors) Sector 0081-0088 : Root directory (8 sectors) When formatting like this, the first 137 sectors will be allocated. That have to be reflected in the allocation table. The first sector of the table must have the first 137 bytes set to non-zero to reflect the layout above (I use the value $01). Rest of the table must be set to zero. The sectors making up the root directory must also all be set to zero (empty directory). Content of volume header 4D 43 46 53 : Magic ID "MCFS" 02 : MCFS version $02 00 00 : First sector of volume FF FF : Last sector of volume 55 55 : Volume ID (not currently 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 : Volume name (not currently used) 00 01 : First sector of allocation table 00 80 : Last sector of allocation table 00 81 : First sector of root directory 00 88 : Last sector of root directory (rest of sector is set to zero) Formatting routine ($0100-$0328) - source - listing - s19

The kernel

This is the core of the MCFS2 operating system. The kernel is placed in ROM and handles all interactions with the file system. It also contain the user command line interface and a few built-in core commands. User interaction is through a shell. Common commands like 'ls', 'cd' and 'mkdir' operates on the current working directory. On load the working directory is set to the root directory, indicated with a "/" (just like UNIX).

Built-in commands

ls - List the contents of the current directory. Syntax: ls /utils/ # ls -rwx 01DD 01DE 00000249 2017-05-05 23:10:24 cftest -rwx 01DC 01DC 00000107 2017-05-05 23:10:29 i2c-map -rwx 01DA 01DB 00000327 2017-05-05 23:10:35 i2c-rtc -rwx 01D8 01D9 000002FB 2017-05-05 23:10:38 videoterminal -rwx 01D7 01D7 000000A7 2017-05-05 23:10:42 6850terminal -rwx 01D6 01D6 00000023 2017-05-05 23:10:46 keycode drw- 01AD 01B4 00001000 2017-05-05 23:10:48 rom/ -rwx 05B2 05B2 000000A9 2017-05-09 09:58:03 desemble /utils/ # Example printout from 'ls' command. Columns are, from left to right; attributes, start sector, end sector, size, date, time, name. Note that the directories have a special 'd' attribute set. Also they have a trailing slash in their names for easier reading. dir - Same as 'ls'. Syntax: dir cd - Change working directory. Syntax: cd <existing directory> mkdir - Creates a new directory. Syntax: mkdir <new directory> delete - Delete a file or directory. Only empty directories can be deleted. Syntax: delete <directory or file> rename - Rename file or directory. Syntax: rename <old name> <new name> save - Save memory contents to a new file. Syntax: save <new file> <sart address> <end address> load - Load file contents into memory. Syntax: save <file> <destination address> run - Load and execute an executable file. Syntax: run <file> attr - Change file or directory attributes. Attributes can be 'r', 'w', 'x' or, most commonly, a combination of all three. Syntax: attr <file or directory> <attributes> time - Show current system time. Syntax: time settime - Set system time. Syntax: settime <year> <month> <day> <hour> <minute> <second> touch - Update the time stamp of a file or a directory to the current time. Syntax: touch <file or directory> help - Display a list of available commands. Syntax: help

Executable files

In order to make files executable the X flag must be set and the file contents must begin with a program header. Program header structure 1 byte - Exec ID. Always set to $47. 1 byte - Architecture. Set to $00 for 6800/6801/6301/6303. 2 byte - Load address 2 byte - Entry address Directly following the executable headers is the program data that will be loaded to the address specified in the header. Execution will start at the address specified as the entry address. When a program is executed, the X and D registers will contain a pointer to the command line string used when executing. That way arguments can be passed to a program.

Custom commands

One key feature of the MCFS2 kernel is the ability to add custom commands without the need to alter the ROM. This is done by placing executable program files in a directory called "system" in the root directory. When giving the kernel a command it will first search the built-in commands for a match. If a match is not found it will check the /system directory (if it exists) for an executable program with a matching name. That way commands can easily and seamlessly be added to the system.

Kernel memory areas

As mentioned earlier, the kernel is placed in ROM. All the RAM variables used by the kernel is placed in the battery backed up RAM on the OS card. Variable area ends with a checksum. On every entry and exit to and from the kernel this checksum is verified or updated. That way the kernel has protection against memory corruption while other programs are executing. In the same battery backed up RAM is also a timestamp with its own checksum that is updated every time the RTC chip is used. That way the kernel can keep track of the last known time and century (since the century is not handled by the RTC chip). If the timestamp is RAM it not valid, the kernel will consider the time as unknown and prompt the user to set the current time.

Kernel ROM source code

This is the source for my current MCFS2 kernel. There are still a lot of improvements that needs to be done but I have been running it now for a few weeks without issues. Also included below is a minor patch release of the MC3 monitor. The only change is the default I/O page on startup is now 0 instead of 7. With the OS card in place and located in I/O page 0, this is more convenient. This change is not needed for the MCFS2 kernel to run. MCFS2 kernel 2.0.1 ($D000-$E36E) - source - listing - s19 MC3 Monitor 1.4.2 ($C000-$C7E8) - source - listing - s19

Program API

In order to be really useful, programs need a way to interact with the MCFS2 file system as well. In order to do that I created an API for accessing kernel file system functions. The kernel has three entry points. $d000 - Cold start. Initialize all variables and go to root directory. $d003 - Warm start. Verify integrity of RAM variables and if intact, go to last working directory. $d006 - System call. Verify integrity of RAM variables and if intact, execute requested system call. In general, the $d000 (cold start) is called from the monitor and the $d003 (warm start) is used as a program return function for giving control back to the user while staying in the same working directory. System calls use a specific data structure for communication. I call it FCB, the File Control Block. Before performing a system call, the calling program sets up an FCB in RAM that contains the parameters needed for the command. A system call is then called by loading a pointer to the FCB in X and then JSR $d006 (system call). The first byte of the FCB defines the command and the structure may be slightly different depending on the command in question. Below is a list of the current implemented File Control Blocks. Bold text indicates the the value is updated by the kernel upon completion of the command. Byte two in the FCB is one of those cases since it's the error code. If the system call is completed successfully the error code is zero. A non zero value indicates an error. Check file entry 1 byte - command $01 1 byte - error code 2 byte - pointer to null terminated file name 1 byte - file flags [INUSE DIR FILE 0 0 0 X W R] 2 byte - number of sectors 4 byte - file size 2 byte - entry date year 1 byte - entry date month 1 byte - entry date day 1 byte - entry time hours 1 byte - entry time minutes 1 byte - entry time seconds Rename file 1 byte - command $07 1 byte - error code 2 byte - pointer to null terminated file name - from 2 byte - pointer to null terminated file name - to Delete file 1 byte - command $08 1 byte - error code 2 byte - pointer to null terminated file name Load file 1 byte - command $10 1 byte - error code 2 byte - pointer to null terminated file name 2 byte - destination address Load file sector 1 byte - command $11 1 byte - error code 2 byte - pointer to null terminated file name 2 byte - destination address 2 byte - sector to load (from zero to end of file) Save file 1 byte - command $20 1 byte - error code 2 byte - pointer to null terminated file name 2 byte - begin address 2 byte - end address 1 byte - file flags [0 0 0 0 0 X W R]

System tools

Below are a few examples of programs using the API. These are tools suitable to place in the /system directory to extend the commands of the kernel. echo - Echo back all text to the console that is given as argument. - source s19store - Receive S19 data from console and store the contents as a file. Takes a file name as argument. - source rawstore - Receive raw data from console and store the contents as a file. Takes a file name as argument. - source dumphex - Dump the contents of a file to the console as a HEX dump. Takes a file name as argument. - source dumpascii - Dump the contents of a file to the console as an ASCII dump. Takes a file name as argument. - source type - Print a text file to the console. Takes a file name as argument. - source file - Display information about a file and try to guess what it is. Takes a file name as argument. - source list - List contents of current directory. Only names without all the other information seen using the built-in 'dir' command. - source fcopy - Copy file into memory. Takes a file name as argument. - source fpaste - Paste file from memory. Can take a file name as argument to save file under a new name. - source


This has been a big and rather complicated project and I did not manage to squeeze everything into this write-up. I will keep improving this system and make it even more useful. This is just an early first release but even now the usefulness of my MC3 is greatly improved thanks to MCFS2. I have been running my MCFS2 file system and kernel for a few months and so far it has been very stable. The MCFS2 can also be portable to other architectures as well. I plan to make a 6809 version as well. It should not be that difficult since the 6809 is source code compatible. This is a huge step towards my next goal; creating a functional editor and assembler so that the MC3 can edit and assemble its own code. Now that would be something!
[show older articles]