FPGABee v3.0

FBFS File System

Up until now, FPGABee supported only a single virtual disk image at block 0 on the SD card. The first step in supporting multiple disk images and multiple drives is to design a file system format to store those images and a implement a utility for manipulating the file system.

The FBFS File System

FBFS (for FpgaBee File System) is a simple file system that supports storing multiple files and guarantees that files are stored in a contiguous, non-fragmented way. It doesn't support directories but it does support a mechanism for store which disk is in which drive.

The basic structure of the file system is this:

  • Block 0 - the config sector
  • Block 1-N - a set of directory entries
  • Block N+1 to end of disk - file data.

The config sector stores a single FBFS_CONFIG record:

#define NUM_DRIVE_SLOTS		7
#define NUM_ROM_SLOTS		3

struct CONFIG
{
	uint32_t	signature;			// Signature identifying file system - "fbfs"
	uint16_t	version;			// fbfs version - 0x0100
	uint32_t	dir_block;			// first directory block
	uint16_t	dir_block_count;	// directory block count
	uint16_t	system_image;		// dirid the system image
	uint16_t	rom_images[NUM_ROM_SLOTS];		// dirid to 3 rom images (pak A, B, C)
	uint16_t	disk_images[NUM_DRIVE_SLOTS];	// dirids to selected disk images
};

The signature and version fields are self explanatory. The fields dir_block and dir_block_count specify the range of blocks that hold the directory entries. The last field disk_images specifies the index of the directory entry for the disk images that are selected for each of the disk controller's 7 possible drives. The remaining two fields system_image and rom_images aren't used yet but are placeholders for things that will be needed later.

A directory entry is defined as follows:

struct DIRENTRY
{
	uint32_t	block;				// Starting block number
	uint16_t	block_count;		// Block count
	uint32_t	resvd;				// Reserved
	char		filename[22];		// File name, space padded
};			

It's a simple structure and is self explanatory - a range of blocks that the file's data occupies and a null-terminated filename - a filename can be a maximum of 21 characters plus the null.

A directory entry is exactly 32 bytes in length and each directory block therefore can store 16 directory entries. Deleted files are indicated by a non-zero block number and a zero-length filename. The first directory entry after all used directory entries has the block field set to 0 - to indicate no further entries will be found and processing need not continue.

The fbfs Utility

To manipulate this file system I wrote a simple command line tool - fbfs:

C:\>fbfs --help
fbfs v1.0 - FPGABee File System Utility
Copyright (C) 2013 Topten Software.  All Rights Reserved

Usage: fbfs <fsimage> <command> [args]

    fsimage            image of the fbfs file system to work with
    command            see commands below
    args               additional command argument

Commands:

    format                          create a new fbfs file system
    ls [<spec>]                     list files in fsimage
    add <file> [newname]            add file to fsimage
    extract <file> [<diskimage>]    extract file from fsimage
    mv <oldfile> <newfile>          rename file in fsimage
    rm <file>                       remove file from fsimage
    select system <file>            specify file containing PCU sys image
    select disk <drive> <file>      insert disk image into drive
    select rom <pak> <file>         insert rom into pak slot
    select                          display selected system, rom and disks
    transfer <newimage>             transfer entire file system to newimage

fbfs can work with either a physical SD card drive, or a normal file system file to create an image. To create a new file system use the format command:

c:\>fbfs f: format

or if working with an image file:

c:\>fbfs c:\fbgabee\my_sd_image.fbfs format

Most of the commands are self explanatory, but here's an example of how a typical image would be created:

fbfs myfs.fbfs format
fbfs myfs.fbfs add hd.hd0
fbfs myfs.fbfs add HDPREM1.ds40
fbfs myfs.fbfs add HDPREM2.ds40
fbfs myfs.fbfs select disk 1 hd.hd0
fbfs myfs.fbfs select disk 3 HDPREM1.ds40
fbfs myfs.fbfs select disk 4 HDPREM2.ds40
fbfs myfs.fbfs ls
fbfs myfs.fbfs select

The other useful feature of fbfs is that it can copy to/from the physical SD card, avoiding the need for other raw-write tools. For example:

fbfs myfs.fbfs transfer k:    

The transfer command creates a new image, copies files within the source image and then sets up the same selected images - effectively removing holes caused by deleted files.

Currently fbfs only runs on Windows, but was implemented in standard C++ and should port easily to other platforms.

Accessing Multiple Disks in FPGABee

Before adding full support for multiple disks to FPGABee, I decided to test what I had so far by hard-coding the offsets to three files (1 HDD image and 2 FDD images) into the disk controller. The ls command lists the block number of each file:

C:\retro\ubee512\disks>fbfs myimage.fbfs ls
    blk#     blks     size filename
----------------------------------------------------
       9    20808 10653696 hd.hd0
   20817      800   409600 HDPREMD1.DS40
   21617      800   409600 HDPREMD2.DS40

Total 3 files

I converted the block numbers to hex and updating the disk controller:

case reg_drive is

	when "001" =>
		-- HDD1
		geo_disk_type <= DISK_HD0;
		diskimage_base_cluster <= x"00000009";

	when "100" =>
		-- FDD 1
		geo_disk_type <= DISK_DS40;
		diskimage_base_cluster <= x"00005151"; -- 20817

	when "101" =>
		-- FDD 1
		geo_disk_type <= DISK_DS40;
		diskimage_base_cluster <= x"00005471"; -- 21617

and multiple disk support was basically working.

The next step is to figure out a mechanism for configuring the disk controller based on what's on the SD card and providing a way for the user to switch floppy drive images.