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))?;
let controllers = genesis::controllers::GenesisController::create(host)?;
let controllers = genesis::controllers::GenesisControllers::create(host)?;
let interrupt = controllers.get_interrupt_signal();
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) {
let (mask, state) = match event {
ControllerEvent::ButtonA(state) => (0x0040, state),
@ -112,7 +112,7 @@ impl ControllerUpdater for GenesisControllerUpdater {
pub struct GenesisController {
pub struct GenesisControllers {
port_1: GenesisControllerPort,
port_2: GenesisControllerPort,
expansion: GenesisControllerPort,
@ -120,9 +120,9 @@ pub struct GenesisController {
reset_timer: Clock,
}
impl GenesisController {
impl GenesisControllers {
pub fn new() -> Self {
GenesisController {
Self {
port_1: GenesisControllerPort::new(),
port_2: GenesisControllerPort::new(),
expansion: GenesisControllerPort::new(),
@ -132,11 +132,11 @@ impl GenesisController {
}
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)?;
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)?;
Ok(controller)
@ -147,7 +147,7 @@ impl GenesisController {
}
}
impl Addressable for GenesisController {
impl Addressable for GenesisControllers {
fn len(&self) -> usize {
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> {
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> {
Some(self)
}

View File

@ -311,9 +311,13 @@ pub struct Ym7101State {
pub sprites_by_line: Vec<Vec<usize>>,
pub last_clock: Clock,
pub p_clock: u32,
pub h_clock: u32,
pub v_clock: u32,
pub h_scanlines: u8,
pub current_x: i32,
pub current_y: i32,
}
impl Ym7101State {
@ -342,9 +346,13 @@ impl Ym7101State {
sprites_by_line: vec![],
last_clock: 0,
p_clock: 0,
h_clock: 0,
v_clock: 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)?;
}
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;
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.current_x = 0;
}
if (self.state.status & STATUS_IN_HBLANK) == 0 && self.state.h_clock >= 61_160 {
self.state.status |= STATUS_IN_HBLANK;
self.state.current_y += 1;
self.state.h_scanlines = self.state.h_scanlines.wrapping_sub(1);
if self.state.hsync_int_enabled() && self.state.h_scanlines == 0 {
@ -628,6 +646,7 @@ impl Steppable for Ym7101 {
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 {
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 {
self.state.status |= STATUS_IN_VBLANK;
@ -692,6 +711,7 @@ impl Ym7101 {
REG_MODE_SET_2 => {
self.state.mode_2 = data;
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_WINDOW_ADDR => { self.state.window_addr = (data as usize) << 10; },
@ -703,6 +723,7 @@ impl Ym7101 {
REG_MODE_SET_4 => {
self.state.mode_4 = data;
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_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); },
}
Ok(())