Added hackish H/V counter for YM7101

This commit is contained in:
transistor 2022-01-02 15:44:41 -08:00
parent ba1dc78ff1
commit c6eeed03ff
3 changed files with 41 additions and 12 deletions

View File

@ -90,7 +90,7 @@ pub fn build_genesis<H: Host>(host: &mut H, options: SegaGenesisOptions) -> Resu
system.add_device("coproc", wrap_transmutable(coproc))?; system.add_device("coproc", wrap_transmutable(coproc))?;
let controllers = genesis::controllers::GenesisController::create(host)?; let controllers = genesis::controllers::GenesisControllers::create(host)?;
let interrupt = controllers.get_interrupt_signal(); let interrupt = controllers.get_interrupt_signal();
system.add_addressable_device(0x00a10000, wrap_transmutable(controllers)).unwrap(); system.add_addressable_device(0x00a10000, wrap_transmutable(controllers)).unwrap();

View File

@ -85,9 +85,9 @@ impl GenesisControllerPort {
} }
} }
pub struct GenesisControllerUpdater(HostData<u16>, HostData<bool>); pub struct GenesisControllersUpdater(HostData<u16>, HostData<bool>);
impl ControllerUpdater for GenesisControllerUpdater { impl ControllerUpdater for GenesisControllersUpdater {
fn update_controller(&mut self, event: ControllerEvent) { fn update_controller(&mut self, event: ControllerEvent) {
let (mask, state) = match event { let (mask, state) = match event {
ControllerEvent::ButtonA(state) => (0x0040, state), ControllerEvent::ButtonA(state) => (0x0040, state),
@ -112,7 +112,7 @@ impl ControllerUpdater for GenesisControllerUpdater {
pub struct GenesisController { pub struct GenesisControllers {
port_1: GenesisControllerPort, port_1: GenesisControllerPort,
port_2: GenesisControllerPort, port_2: GenesisControllerPort,
expansion: GenesisControllerPort, expansion: GenesisControllerPort,
@ -120,9 +120,9 @@ pub struct GenesisController {
reset_timer: Clock, reset_timer: Clock,
} }
impl GenesisController { impl GenesisControllers {
pub fn new() -> Self { pub fn new() -> Self {
GenesisController { Self {
port_1: GenesisControllerPort::new(), port_1: GenesisControllerPort::new(),
port_2: GenesisControllerPort::new(), port_2: GenesisControllerPort::new(),
expansion: GenesisControllerPort::new(), expansion: GenesisControllerPort::new(),
@ -132,11 +132,11 @@ impl GenesisController {
} }
pub fn create<H: Host>(host: &mut H) -> Result<Self, Error> { pub fn create<H: Host>(host: &mut H) -> Result<Self, Error> {
let controller = GenesisController::new(); let controller = GenesisControllers::new();
let controller1 = Box::new(GenesisControllerUpdater(controller.port_1.buttons.clone(), controller.interrupt.clone())); let controller1 = Box::new(GenesisControllersUpdater(controller.port_1.buttons.clone(), controller.interrupt.clone()));
host.register_controller(ControllerDevice::A, controller1)?; host.register_controller(ControllerDevice::A, controller1)?;
let controller2 = Box::new(GenesisControllerUpdater(controller.port_2.buttons.clone(), controller.interrupt.clone())); let controller2 = Box::new(GenesisControllersUpdater(controller.port_2.buttons.clone(), controller.interrupt.clone()));
host.register_controller(ControllerDevice::B, controller2)?; host.register_controller(ControllerDevice::B, controller2)?;
Ok(controller) Ok(controller)
@ -147,7 +147,7 @@ impl GenesisController {
} }
} }
impl Addressable for GenesisController { impl Addressable for GenesisControllers {
fn len(&self) -> usize { fn len(&self) -> usize {
0x30 0x30
} }
@ -197,7 +197,7 @@ impl Addressable for GenesisController {
} }
} }
impl Steppable for GenesisController { impl Steppable for GenesisControllers {
fn step(&mut self, system: &System) -> Result<ClockElapsed, Error> { fn step(&mut self, system: &System) -> Result<ClockElapsed, Error> {
let duration = 100_00; // Update every 100us let duration = 100_00; // Update every 100us
@ -211,7 +211,7 @@ impl Steppable for GenesisController {
} }
} }
impl Transmutable for GenesisController { impl Transmutable for GenesisControllers {
fn as_addressable(&mut self) -> Option<&mut dyn Addressable> { fn as_addressable(&mut self) -> Option<&mut dyn Addressable> {
Some(self) Some(self)
} }

View File

@ -311,9 +311,13 @@ pub struct Ym7101State {
pub sprites_by_line: Vec<Vec<usize>>, pub sprites_by_line: Vec<Vec<usize>>,
pub last_clock: Clock, pub last_clock: Clock,
pub p_clock: u32,
pub h_clock: u32, pub h_clock: u32,
pub v_clock: u32, pub v_clock: u32,
pub h_scanlines: u8, pub h_scanlines: u8,
pub current_x: i32,
pub current_y: i32,
} }
impl Ym7101State { impl Ym7101State {
@ -342,9 +346,13 @@ impl Ym7101State {
sprites_by_line: vec![], sprites_by_line: vec![],
last_clock: 0, last_clock: 0,
p_clock: 0,
h_clock: 0, h_clock: 0,
v_clock: 0, v_clock: 0,
h_scanlines: 0, h_scanlines: 0,
current_x: 0,
current_y: 0,
} }
} }
@ -608,12 +616,22 @@ impl Steppable for Ym7101 {
system.get_interrupt_controller().set(true, 2, 26)?; system.get_interrupt_controller().set(true, 2, 26)?;
} }
let clocks_per_pixel = 63_500 / (self.state.screen_size.0 as u32 * 8 + 88);
self.state.p_clock += diff;
if self.state.p_clock >= clocks_per_pixel {
let pixels = self.state.p_clock / clocks_per_pixel;
self.state.p_clock -= pixels * clocks_per_pixel;
self.state.current_x += pixels as i32;
}
self.state.h_clock += diff; self.state.h_clock += diff;
if (self.state.status & STATUS_IN_HBLANK) != 0 && self.state.h_clock >= 2_340 && self.state.h_clock <= 61_160 { if (self.state.status & STATUS_IN_HBLANK) != 0 && self.state.h_clock >= 2_340 && self.state.h_clock <= 61_160 {
self.state.status &= !STATUS_IN_HBLANK; self.state.status &= !STATUS_IN_HBLANK;
self.state.current_x = 0;
} }
if (self.state.status & STATUS_IN_HBLANK) == 0 && self.state.h_clock >= 61_160 { if (self.state.status & STATUS_IN_HBLANK) == 0 && self.state.h_clock >= 61_160 {
self.state.status |= STATUS_IN_HBLANK; self.state.status |= STATUS_IN_HBLANK;
self.state.current_y += 1;
self.state.h_scanlines = self.state.h_scanlines.wrapping_sub(1); self.state.h_scanlines = self.state.h_scanlines.wrapping_sub(1);
if self.state.hsync_int_enabled() && self.state.h_scanlines == 0 { if self.state.hsync_int_enabled() && self.state.h_scanlines == 0 {
@ -628,6 +646,7 @@ impl Steppable for Ym7101 {
self.state.v_clock += diff; self.state.v_clock += diff;
if (self.state.status & STATUS_IN_VBLANK) != 0 && self.state.v_clock >= 1_205_992 && self.state.v_clock <= 15_424_008 { if (self.state.status & STATUS_IN_VBLANK) != 0 && self.state.v_clock >= 1_205_992 && self.state.v_clock <= 15_424_008 {
self.state.status &= !STATUS_IN_VBLANK; self.state.status &= !STATUS_IN_VBLANK;
self.state.current_y = 0;
} }
if (self.state.status & STATUS_IN_VBLANK) == 0 && self.state.v_clock >= 15_424_008 { if (self.state.status & STATUS_IN_VBLANK) == 0 && self.state.v_clock >= 15_424_008 {
self.state.status |= STATUS_IN_VBLANK; self.state.status |= STATUS_IN_VBLANK;
@ -692,6 +711,7 @@ impl Ym7101 {
REG_MODE_SET_2 => { REG_MODE_SET_2 => {
self.state.mode_2 = data; self.state.mode_2 = data;
self.state.update_screen_size(); self.state.update_screen_size();
self.swapper.set_size(self.state.screen_size.0 as u32 * 8, self.state.screen_size.1 as u32 * 8);
}, },
REG_SCROLL_A_ADDR => { self.state.scroll_a_addr = (data as usize) << 10; }, REG_SCROLL_A_ADDR => { self.state.scroll_a_addr = (data as usize) << 10; },
REG_WINDOW_ADDR => { self.state.window_addr = (data as usize) << 10; }, REG_WINDOW_ADDR => { self.state.window_addr = (data as usize) << 10; },
@ -703,6 +723,7 @@ impl Ym7101 {
REG_MODE_SET_4 => { REG_MODE_SET_4 => {
self.state.mode_4 = data; self.state.mode_4 = data;
self.state.update_screen_size(); self.state.update_screen_size();
self.swapper.set_size(self.state.screen_size.0 as u32 * 8, self.state.screen_size.1 as u32 * 8);
}, },
REG_HSCROLL_ADDR => { self.state.hscroll_addr = (data as usize) << 10; }, REG_HSCROLL_ADDR => { self.state.hscroll_addr = (data as usize) << 10; },
REG_AUTO_INCREMENT => { self.state.memory.transfer_auto_inc = data as u32; }, REG_AUTO_INCREMENT => { self.state.memory.transfer_auto_inc = data as u32; },
@ -776,6 +797,14 @@ impl Addressable for Ym7101 {
} }
}, },
// Read from H/V Counter
0x08 | 0x0A => {
data[0] = self.state.current_y as u8;
if data.len() > 1 {
data[1] = (self.state.current_x >> 1) as u8;
}
},
_ => { println!("{}: !!! unhandled read from {:x}", DEV_NAME, addr); }, _ => { println!("{}: !!! unhandled read from {:x}", DEV_NAME, addr); },
} }
Ok(()) Ok(())