diff --git a/src/peripherals/genesis/ym7101.rs b/src/peripherals/genesis/ym7101.rs index e4e8489..1c9eb52 100644 --- a/src/peripherals/genesis/ym7101.rs +++ b/src/peripherals/genesis/ym7101.rs @@ -53,7 +53,10 @@ const MODE1_BF_HSYNC_INTERRUPT: u8 = 0x10; const MODE2_BF_V_CELL_MODE: u8 = 0x08; const MODE2_BF_VSYNC_INTERRUPT: u8 = 0x20; +const MODE3_BF_EXTERNAL_INTERRUPT: u8 = 0x08; + const MODE4_BF_H_CELL_MODE: u8 = 0x01; +const MODE4_BF_SHADOW_HIGHLIGHT: u8 = 0x08; @@ -188,6 +191,11 @@ impl Ym7101State { (self.regs[REG_MODE_SET_2] & MODE2_BF_VSYNC_INTERRUPT) != 0 } + #[inline(always)] + fn external_int_enabled(&self) -> bool { + (self.regs[REG_MODE_SET_3] & MODE3_BF_EXTERNAL_INTERRUPT) != 0 + } + pub fn get_vram_scroll_a_addr(&self) -> u32 { ((self.regs[REG_SCROLL_A_ADDR] as u16) << 10) as u32 } @@ -282,24 +290,51 @@ impl Ym7101State { } } - pub fn draw_sprites(&mut self, frame: &mut Frame) { - let sprite_table = (self.regs[REG_SPRITES_ADDR] as u32) << 9; - let (scroll_h, scroll_v) = self.get_scroll_size(); + pub fn build_link_list(&mut self, sprite_table: usize, links: &mut [usize]) -> usize { + links[0] = 0; + let mut i = 0; + loop { + let link = self.vram[sprite_table + (links[i] * 8) + 3]; + if link == 0 || link > 80 { + break; + } + i += 1; + links[i] = link as usize; + } + i + } + + pub fn draw_sprites(&mut self, frame: &mut Frame) { + let sprite_table = (self.regs[REG_SPRITES_ADDR] as usize) << 9; + let (cells_h, cells_v) = self.get_screen_size(); + let (pos_limit_h, pos_limit_v) = (if cells_h == 32 { 383 } else { 447 }, if cells_v == 28 { 351 } else { 367 }); + + let mut links = [0; 80]; + let lowest = self.build_link_list(sprite_table, &mut links); + + for i in (0..lowest + 1).rev() { + let sprite_data = &self.vram[(sprite_table + (links[i] * 8))..]; - for i in 0..(scroll_h as u32 * 2) { - let sprite_data = &self.vram[((sprite_table + (i * 8)) as usize)..]; let v_pos = read_beu16(&sprite_data[0..]); let size = sprite_data[2]; - let link = sprite_data[3]; let pattern_name = read_beu16(&sprite_data[4..]); let h_pos = read_beu16(&sprite_data[6..]); - let (size_h, size_v) = (((size >> 2) & 0x03) as u16, (size & 0x03) as u16); + let (size_h, size_v) = (((size >> 2) & 0x03) as u16 + 1, (size & 0x03) as u16 + 1); + let h_rev = (pattern_name & 0x0800) != 0; + let v_rev = (pattern_name & 0x1000) != 0; +println!("i: {} ({} {}) {:x} ({}, {}) {:x}", i, h_pos, v_pos, size, size_h, size_v, pattern_name); - for h in 0..size_h { - for v in 0..size_v { - let iter = self.get_pattern_iter(pattern_name + (h * size_v) + v); - frame.blit((h_pos + (h * 8)) as u32, (v_pos + (v * 8)) as u32, iter, 8, 8); + for ih in 0..size_h { + for iv in 0..size_v { + let (h, v) = (if !h_rev { ih } else { size_h - ih }, if !v_rev { iv } else { size_v - iv }); + let (x, y) = (h_pos + h * 8, v_pos + v * 8); + if x > 128 && x < pos_limit_h && y > 128 && y < pos_limit_v { + let iter = self.get_pattern_iter(pattern_name + (h * size_v) + v); + + println!("{}: ({} {}), {:x}", i, x, y, pattern_name + (h * size_v) + v); + frame.blit(x as u32 - 128, y as u32 - 128, iter, 8, 8); + } } } } @@ -408,7 +443,7 @@ impl Steppable for Ym7101 { let diff = (system.clock - self.state.last_clock) as u32; self.state.last_clock = system.clock; - if self.external_interrupt.get() { + if self.state.external_int_enabled() && self.external_interrupt.get() { self.external_interrupt.set(false); system.get_interrupt_controller().set(true, 2, 26)?; } @@ -549,7 +584,7 @@ impl Addressable for Ym7101 { } } self.state.transfer_addr += self.state.regs[REG_AUTO_INCREMENT] as u32; - info!("{}: data port read {} bytes from {:?}:{:x} returning {:x},{:x}", DEV_NAME, data.len(), self.state.transfer_target, addr, data[0], data[1]); + debug!("{}: data port read {} bytes from {:?}:{:x} returning {:x},{:x}", DEV_NAME, data.len(), self.state.transfer_target, addr, data[0], data[1]); }, // Read from Control Port @@ -573,7 +608,7 @@ impl Addressable for Ym7101 { self.state.transfer_fill = if data.len() >= 2 { read_beu16(data) } else { data[0] as u16 }; self.state.set_dma_mode(DmaType::Fill); } else { - info!("{}: data port write {} bytes to {:?}:{:x} with {:?}", DEV_NAME, data.len(), self.state.transfer_target, self.state.transfer_addr, data); + debug!("{}: data port write {} bytes to {:?}:{:x} with {:?}", DEV_NAME, data.len(), self.state.transfer_target, self.state.transfer_addr, data); { let addr = self.state.transfer_addr as usize;