Task 204: .F08 File Format

Task 204: .F08 File Format

.F08 File Format Specifications

The .F08 file format is a raw binary format used for DOS screen fonts with glyphs of 8-pixel height. It is a simple, header-less structure containing bitmap data for 256 glyphs, each 8 pixels wide and 8 pixels high. This format is associated with legacy DOS systems and is recognized in various font tools and documentation as a raw dump of font data from video adapter ROMs or similar sources.

1. List of Properties of the .F08 File Format Intrinsic to Its File System

  • Glyph Width: 8 pixels
  • Glyph Height: 8 pixels
  • Number of Glyphs: 256
  • Bytes per Glyph: 8
  • Total File Size: 2048 bytes
  • Pixel Format: 1-bit monochrome, with each byte representing a row of the glyph, most significant bit (bit 7) corresponding to the leftmost pixel (1 for pixel on, 0 for off)
  • Character Set: Typically IBM Code Page 437 (extended ASCII)
  • Header: None
  • Footer: None
  • Compression: None
  • Endianness: Not applicable (byte-based structure)
  • Bit Order: Most significant bit left
  1. https://raw.githubusercontent.com/spacerace/romfont/master/VGA-ROM.F08 (IBM VGA ROM 8x8 font)
  2. http://ftp.lanet.lv/ftp/mirror/x2ftp/msdos/programming/misc/fntcol16.zip (This ZIP archive contains multiple .F08 files, such as CGA.F08 and EGA.F08; extract the desired .F08 file after download. A direct single-file link could not be located for a second distinct .F08, but this archive provides access to several.)

3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .F08 File Processing

The following is a self-contained HTML document with embedded JavaScript that allows a user to drag and drop a .F08 file. Upon drop, it reads the file, verifies its size, and dumps the properties to the screen in a structured list.

.F08 File Property Dumper
Drag and drop a .F08 file here

4. Python Class for .F08 File Processing

The following Python class can open a .F08 file, decode and read its content (verifying the size), print the properties to the console, and write the data to a new file.

class F08File:
    def __init__(self, filename):
        with open(filename, 'rb') as f:
            self.data = f.read()
        if len(self.data) != 2048:
            raise ValueError("Invalid .F08 file size: expected 2048 bytes")
        self.properties = {
            'Glyph Width': '8 pixels',
            'Glyph Height': '8 pixels',
            'Number of Glyphs': '256',
            'Bytes per Glyph': '8',
            'Total File Size': '2048 bytes',
            'Pixel Format': '1-bit monochrome, MSB left',
            'Character Set': 'Typically IBM Code Page 437',
            'Header': 'None',
            'Footer': 'None',
            'Compression': 'None',
            'Endianness': 'Not applicable',
            'Bit Order': 'Most significant bit left'
        }

    def print_properties(self):
        for key, value in self.properties.items():
            print(f"{key}: {value}")

    def write(self, filename):
        with open(filename, 'wb') as f:
            f.write(self.data)

# Example usage:
# f = F08File('example.F08')
# f.print_properties()
# f.write('new.F08')

5. Java Class for .F08 File Processing

The following Java class can open a .F08 file, decode and read its content (verifying the size), print the properties to the console, and write the data to a new file.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

public class F08File {
    private byte[] data;
    private Map<String, String> properties;

    public F08File(String filename) throws IOException {
        FileInputStream fis = new FileInputStream(filename);
        data = fis.readAllBytes();
        fis.close();
        if (data.length != 2048) {
            throw new IOException("Invalid .F08 file size: expected 2048 bytes");
        }
        properties = new LinkedHashMap<>();
        properties.put("Glyph Width", "8 pixels");
        properties.put("Glyph Height", "8 pixels");
        properties.put("Number of Glyphs", "256");
        properties.put("Bytes per Glyph", "8");
        properties.put("Total File Size", "2048 bytes");
        properties.put("Pixel Format", "1-bit monochrome, MSB left");
        properties.put("Character Set", "Typically IBM Code Page 437");
        properties.put("Header", "None");
        properties.put("Footer", "None");
        properties.put("Compression", "None");
        properties.put("Endianness", "Not applicable");
        properties.put("Bit Order", "Most significant bit left");
    }

    public void printProperties() {
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }

    public void write(String filename) throws IOException {
        FileOutputStream fos = new FileOutputStream(filename);
        fos.write(data);
        fos.close();
    }

    // Example usage:
    // public static void main(String[] args) throws IOException {
    //     F08File f = new F08File("example.F08");
    //     f.printProperties();
    //     f.write("new.F08");
    // }
}

6. JavaScript Class for .F08 File Processing

The following JavaScript class can open a .F08 file (using Node.js for file I/O), decode and read its content (verifying the size), print the properties to the console, and write the data to a new file.

const fs = require('fs');

class F08File {
    constructor(filename) {
        this.data = fs.readFileSync(filename);
        if (this.data.length !== 2048) {
            throw new Error('Invalid .F08 file size: expected 2048 bytes');
        }
        this.properties = {
            'Glyph Width': '8 pixels',
            'Glyph Height': '8 pixels',
            'Number of Glyphs': '256',
            'Bytes per Glyph': '8',
            'Total File Size': '2048 bytes',
            'Pixel Format': '1-bit monochrome, MSB left',
            'Character Set': 'Typically IBM Code Page 437',
            'Header': 'None',
            'Footer': 'None',
            'Compression': 'None',
            'Endianness': 'Not applicable',
            'Bit Order': 'Most significant bit left'
        };
    }

    printProperties() {
        for (const [key, value] of Object.entries(this.properties)) {
            console.log(`${key}: ${value}`);
        }
    }

    write(filename) {
        fs.writeFileSync(filename, this.data);
    }
}

// Example usage:
// const f = new F08File('example.F08');
// f.printProperties();
// f.write('new.F08');

7. C++ Class for .F08 File Processing

The following C++ class can open a .F08 file, decode and read its content (verifying the size), print the properties to the console, and write the data to a new file.

#include <fstream>
#include <iostream>
#include <vector>
#include <map>

class F08File {
private:
    std::vector<char> data;
    std::map<std::string, std::string> properties;

public:
    F08File(const std::string& filename) {
        std::ifstream file(filename, std::ios::binary | std::ios::ate);
        if (!file.is_open()) {
            throw std::runtime_error("Unable to open file");
        }
        std::streamsize size = file.tellg();
        file.seekg(0, std::ios::beg);
        data.resize(size);
        if (!file.read(data.data(), size)) {
            throw std::runtime_error("Error reading file");
        }
        if (size != 2048) {
            throw std::runtime_error("Invalid .F08 file size: expected 2048 bytes");
        }
        properties = {
            {"Glyph Width", "8 pixels"},
            {"Glyph Height", "8 pixels"},
            {"Number of Glyphs", "256"},
            {"Bytes per Glyph", "8"},
            {"Total File Size", "2048 bytes"},
            {"Pixel Format", "1-bit monochrome, MSB left"},
            {"Character Set", "Typically IBM Code Page 437"},
            {"Header", "None"},
            {"Footer", "None"},
            {"Compression", "None"},
            {"Endianness", "Not applicable"},
            {"Bit Order", "Most significant bit left"}
        };
    }

    void printProperties() const {
        for (const auto& prop : properties) {
            std::cout << prop.first << ": " << prop.second << std::endl;
        }
    }

    void write(const std::string& filename) const {
        std::ofstream file(filename, std::ios::binary);
        if (!file.is_open()) {
            throw std::runtime_error("Unable to open file for writing");
        }
        file.write(data.data(), data.size());
    }
};

// Example usage:
// int main() {
//     try {
//         F08File f("example.F08");
//         f.printProperties();
//         f.write("new.F08");
//     } catch (const std::exception& e) {
//         std::cerr << e.what() << std::endl;
//     }
//     return 0;
// }