Actually parse bdf directly, emit rom to be used for george-emu

This commit is contained in:
2024-04-10 17:17:38 -04:00
parent 86a72fc2ea
commit ca598bd732
8 changed files with 4101 additions and 2068 deletions
+51 -45
View File
@@ -1,58 +1,64 @@
#![allow(clippy::println_empty_string)]
use std::{
fs::File,
io::{self, Write},
path::PathBuf,
io::{Read, Write},
ops::Neg,
u8,
};
extern crate png;
const MAX_ROWS: usize = 13;
const MAX_CHARS: u16 = 0x100; // Non inclusive, first char is 0x00
fn to_bitmap(path: &str, max_chars: u16, max_rows: usize) -> Result<Vec<u8>, io::Error> {
let decoder = png::Decoder::new(File::open(path)?);
let mut reader = decoder.read_info()?;
let mut buf = vec![0; reader.output_buffer_size()];
let info = reader.next_frame(&mut buf)?;
let bytes = &buf[..info.buffer_size()];
let compressed: Vec<u8> = bytes.iter().step_by(4).cloned().collect(); // We're not using color, so we skip duplicate color components
let mut finalbuf = Vec::new();
for (i, _bit) in compressed.iter().step_by(8).enumerate() {
let mut byte = 0u8;
for j in (0..8).rev() {
if compressed[i * 8 + j] == 255 {
byte |= 0x80 >> j;
}
}
finalbuf.push(byte);
// takes all charaters in bdf and returns a vec of each character row byte in order, normalized to
// width & height of the font (only works with 8 or fewer pixel wide fonts, should work for any height)
fn bdf_to_vec(path: &str) -> Vec<u8> {
let mut bdf_vec = Vec::new();
let file = File::open(path).unwrap();
let mut bdf_font_bytes = Vec::new();
for byte in file.bytes() {
bdf_font_bytes.push(byte.unwrap());
}
Ok(finalbuf)
}
let bdf_font = bdf_parser::BdfFont::parse(&bdf_font_bytes).unwrap();
for glyph in bdf_font.glyphs.iter() {
let glyph_offset_x = glyph.bounding_box.offset.x;
let glyph_offset_y = glyph.bounding_box.offset.y;
let glyph_height = glyph.bounding_box.size.y;
let font_height = bdf_font.metadata.bounding_box.size.y;
let font_offset_y = bdf_font.metadata.bounding_box.offset.y;
fn reorder_bitmap(bitmap: &[u8]) -> Vec<u8> {
let mut reordered: Vec<u8> = Vec::new();
for row in 0..MAX_ROWS {
for character in 0x00..MAX_CHARS {
let mut byte = 0u8;
for i in 0..8 {
// character number + row offset & bitmask = pixel
if bitmap[character as usize + (row * 0xFF)] & 0x80 >> i > 0 {
byte |= 0x80 >> i;
}
}
reordered.push(byte);
let top_space = font_height + font_offset_y - glyph_height - glyph_offset_y;
for _i in 0..top_space {
bdf_vec.push(0x00);
}
for bitmap in glyph.bitmap.iter() {
bdf_vec.push(bitmap >> glyph_offset_x);
}
let bottom_space = font_offset_y.neg() + glyph_offset_y;
for _i in 0..bottom_space {
bdf_vec.push(0x00);
}
}
reordered
bdf_vec
}
fn main() -> std::io::Result<()> {
let compressed = to_bitmap("./cozette.png", MAX_CHARS, MAX_ROWS)?;
let reordered = reorder_bitmap(&compressed);
let mut outfile = File::create("./cozette.bin")?;
outfile.set_len(0xFFFF)?;
outfile.write_all(&reordered)?;
Ok(())
// takes an vec of ordered characters and translates them for use with the character rom
// TODO: make this work for any arbitrary char rom pin format using some kinda interface
fn reorder_bitmap(bitmap: &[u8], font_height: usize) -> Vec<u8> {
let mut rom = vec![0; 0x8000]; // create vec the size of character rom
for row in 0..font_height {
for ascii_address in 0..u8::MAX {
// first 8 bits of address pick character
// next 5 bits pick row, and TODO: final 2 pick character set
let byte = bitmap[ascii_address as usize * font_height + row];
let rom_index: u16 = ((row as u16) << 8) + ascii_address as u16;
rom[rom_index as usize] = byte;
}
}
rom
}
fn main() {
let bits = bdf_to_vec("Cozette8-13.bdf");
let mut rom = File::create("./cozette.rom").unwrap();
let reordered = reorder_bitmap(&bits, 13);
rom.write_all(&reordered).unwrap();
}