100 lines
2.3 KiB
Rust
100 lines
2.3 KiB
Rust
#![warn(
|
|
clippy::correctness,
|
|
clippy::nursery,
|
|
clippy::unnecessary_cast,
|
|
clippy::all,
|
|
clippy::suspicious,
|
|
clippy::perf,
|
|
rustdoc::missing_errors_doc,
|
|
rustdoc::missing_panics_doc
|
|
)]
|
|
|
|
use std::fs::File;
|
|
use std::io::{Read, Seek, SeekFrom};
|
|
|
|
use proc_macro::TokenStream;
|
|
use quote::quote;
|
|
use syn::{LitStr, parse_macro_input};
|
|
|
|
extern crate proc_macro;
|
|
|
|
#[proc_macro]
|
|
pub fn include_font(item: TokenStream) -> TokenStream {
|
|
let filename = parse_macro_input!(item as LitStr);
|
|
let file_path = filename.value();
|
|
|
|
println!("Loading font: [{}]", file_path);
|
|
|
|
let font_bytes = match load_file(file_path) {
|
|
Ok(bytes) => bytes,
|
|
Err(why) => panic!("{}", why),
|
|
};
|
|
|
|
let font_data = match Font::new(font_bytes) {
|
|
Ok(font) => font.0,
|
|
Err(why) => panic!("{}", why),
|
|
};
|
|
|
|
quote!(
|
|
[
|
|
#(
|
|
[#(#font_data),*]
|
|
),*
|
|
]
|
|
)
|
|
.into()
|
|
}
|
|
|
|
struct Font([[u8; 16]; 512]);
|
|
|
|
impl Font {
|
|
const MAGIC: u16 = 0x3604;
|
|
|
|
pub fn new(data: [u8; (32 + 2) * 512 + 4]) -> Result<Self, &'static str> {
|
|
let magic: u16 = (data[0] as u16) << 8 | data[1] as u16;
|
|
let mode = data[2];
|
|
let size = data[3];
|
|
|
|
if magic != Self::MAGIC {
|
|
return Err("Magic value is invalid!");
|
|
}
|
|
|
|
let has_512_glyphs = (mode & 0x01) != 0;
|
|
let mut glyphs = [[0; 16]; 512];
|
|
let glyph_count = if has_512_glyphs { 512 } else { 256 };
|
|
|
|
for i in 0..(glyph_count as usize) {
|
|
let mut buff: [u8; 16] = [0; 16];
|
|
for j in 0..(size as usize) {
|
|
buff[j] = data[4 + i * (size as usize) + j];
|
|
}
|
|
glyphs[i] = buff;
|
|
}
|
|
|
|
Ok(Self(glyphs))
|
|
}
|
|
}
|
|
|
|
type FileContents = [u8; (32 + 2) * 512 + 4];
|
|
fn load_file(filename: String) -> Result<FileContents, std::io::Error> {
|
|
let mut buf = [0; (32 + 2) * 512 + 4];
|
|
let mut f = File::open(filename).unwrap();
|
|
f.seek(SeekFrom::Start(0)).unwrap();
|
|
|
|
loop {
|
|
match f.read(&mut buf) {
|
|
Ok(read) => {
|
|
if read == 0 {
|
|
break;
|
|
}
|
|
}
|
|
Err(why) => {
|
|
eprintln!("Failed to read PS1 font file: {}", why);
|
|
return Err(why);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(buf)
|
|
}
|