1//! Sega CD font rendering / color calculation registers 2 3use bincode::{Decode, Encode}; 4use jgenesis_common::num::{GetBit, U16Ext}; 5 6#[derive(Debug, Clone, Default, Encode, Decode)] 7pub struct FontRegisters { 8 color_0: u8, 9 color_1: u8, 10 font_bits: u16, 11} 12 13impl FontRegisters { 14 pub fn new() -> Self { 15 Self::default() 16 } 17 18 pub fn read_color(&self) -> u8 { 19 (self.color_1 << 4) | self.color_0 20 } 21 22 pub fn write_color(&mut self, color_byte: u8) { 23 self.color_0 = color_byte & 0x0F; 24 self.color_1 = color_byte >> 4; 25 } 26 27 pub fn font_bits(&self) -> u16 { 28 self.font_bits 29 } 30 31 pub fn write_font_bits(&mut self, font_bits: u16) { 32 self.font_bits = font_bits; 33 } 34 35 pub fn write_font_bits_msb(&mut self, font_bits_msb: u8) { 36 self.font_bits.set_msb(font_bits_msb); 37 } 38 39 pub fn write_font_bits_lsb(&mut self, font_bits_lsb: u8) { 40 self.font_bits.set_lsb(font_bits_lsb); 41 } 42 43 pub fn read_font_data(&self, address: u32) -> u16 { 44 // Font data registers are mapped at $FF8050-$FF8057 45 // $FF8050-$FF8051: Bit 15-12 data 46 // $FF8052-$FF8053: Bit 11-8 data 47 // $FF8054-$FF8055: Bit 7-4 data 48 // $FF8056-$FF8057: Bit 3-0 data 49 let word_idx = (address & 0x07) >> 1; 50 let base_font_bit = ((3 - word_idx) << 2) as u8; 51 52 (0..16) 53 .map(|i| { 54 let font_bit_idx = base_font_bit + (i >> 2); 55 let font_color_idx = i & 0x03; 56 57 let bit = if self.font_bits.bit(font_bit_idx) { 58 self.color_1.bit(font_color_idx) 59 } else { 60 self.color_0.bit(font_color_idx) 61 }; 62 63 u16::from(bit) << i 64 }) 65 .reduce(|a, b| a | b) 66 .unwrap() 67 } 68}