From b00fbfb38cd55c60380656580363a9efed962355 Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Sun, 29 Dec 2019 23:03:57 +0200 Subject: [PATCH] gpu: refactor: Big refactor preparations 1) Decouple SysBus from Gpu 2) Split Gpu rendering function into separate modules 3) Cleanup Former-commit-id: 0435ad1c9c1de72ed50769fabfea7c5f33b670e0 --- Cargo.toml | 2 +- src/core/arm7tdmi/arm/exec.rs | 2 +- src/core/arm7tdmi/cpu.rs | 7 +- src/core/arm7tdmi/mod.rs | 4 +- src/core/arm7tdmi/thumb/exec.rs | 2 +- src/core/arm7tdmi/thumb/mod.rs | 3 +- src/core/{arm7tdmi => }/bus.rs | 2 +- src/core/cartridge.rs | 3 +- src/core/dma.rs | 3 +- src/core/gba.rs | 5 +- src/core/gpu/mod.rs | 268 +++++++++++-------------------- src/core/gpu/render.rs | 3 + src/core/gpu/render/bitmap.rs | 38 +++++ src/core/gpu/{ => render}/obj.rs | 142 ++++++++-------- src/core/gpu/render/text.rs | 94 +++++++++++ src/core/gpu/rgb15.rs | 74 ++++----- src/core/gpu/sfx.rs | 58 +++---- src/core/iodev.rs | 10 +- src/core/mod.rs | 8 +- src/core/sysbus.rs | 26 +-- src/debugger/command.rs | 4 +- src/debugger/mod.rs | 7 +- src/disass.rs | 3 +- 23 files changed, 389 insertions(+), 379 deletions(-) rename src/core/{arm7tdmi => }/bus.rs (95%) create mode 100644 src/core/gpu/render.rs create mode 100644 src/core/gpu/render/bitmap.rs rename src/core/gpu/{ => render}/obj.rs (73%) create mode 100644 src/core/gpu/render/text.rs diff --git a/Cargo.toml b/Cargo.toml index c0738d9..5af9b44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" default-run= "rba-sdl2" [dependencies] -byteorder = "*" +byteorder = "1" num = "0.2.0" num-traits = "0.2" enum-primitive-derive = "^0.1" diff --git a/src/core/arm7tdmi/arm/exec.rs b/src/core/arm7tdmi/arm/exec.rs index c067bc2..c4d6b6e 100644 --- a/src/core/arm7tdmi/arm/exec.rs +++ b/src/core/arm7tdmi/arm/exec.rs @@ -1,11 +1,11 @@ use crate::bit::BitIndex; use super::super::alu::*; -use crate::core::arm7tdmi::bus::Bus; use crate::core::arm7tdmi::cpu::{Core, CpuExecResult}; use crate::core::arm7tdmi::psr::RegPSR; use crate::core::arm7tdmi::{Addr, CpuError, CpuMode, CpuResult, CpuState, REG_LR, REG_PC}; use crate::core::sysbus::SysBus; +use crate::core::Bus; use super::*; diff --git a/src/core/arm7tdmi/cpu.rs b/src/core/arm7tdmi/cpu.rs index 8cfe193..992d210 100644 --- a/src/core/arm7tdmi/cpu.rs +++ b/src/core/arm7tdmi/cpu.rs @@ -4,11 +4,12 @@ use ansi_term::{Colour, Style}; pub use super::exception::Exception; use super::{ - arm::*, bus::Bus, psr::RegPSR, reg_string, thumb::ThumbInstruction, Addr, CpuMode, CpuResult, - CpuState, DecodedInstruction, InstructionDecoder, + arm::*, psr::RegPSR, reg_string, thumb::ThumbInstruction, Addr, CpuMode, CpuResult, CpuState, + DecodedInstruction, InstructionDecoder, }; -use super::super::sysbus::{ +use crate::core::bus::Bus; +use crate::core::sysbus::{ MemoryAccess, MemoryAccessType, MemoryAccessType::*, MemoryAccessWidth::*, SysBus, }; diff --git a/src/core/arm7tdmi/mod.rs b/src/core/arm7tdmi/mod.rs index cfafbeb..3f1a928 100644 --- a/src/core/arm7tdmi/mod.rs +++ b/src/core/arm7tdmi/mod.rs @@ -12,8 +12,6 @@ pub mod cpu; pub use cpu::*; pub mod alu; pub use alu::*; -pub mod bus; -pub use bus::*; pub mod exception; pub mod psr; @@ -21,7 +19,7 @@ pub const REG_PC: usize = 15; pub const REG_LR: usize = 14; pub const REG_SP: usize = 13; -pub type Addr = u32; +pub(self) use crate::core::{Addr, Bus}; #[derive(Debug, PartialEq, Copy, Clone)] pub enum DecodedInstruction { diff --git a/src/core/arm7tdmi/thumb/exec.rs b/src/core/arm7tdmi/thumb/exec.rs index 773adf2..56399da 100644 --- a/src/core/arm7tdmi/thumb/exec.rs +++ b/src/core/arm7tdmi/thumb/exec.rs @@ -1,7 +1,7 @@ -use crate::core::arm7tdmi::bus::Bus; use crate::core::arm7tdmi::cpu::{Core, CpuExecResult}; use crate::core::arm7tdmi::*; use crate::core::sysbus::SysBus; +use crate::core::Bus; use crate::bit::BitIndex; diff --git a/src/core/arm7tdmi/thumb/mod.rs b/src/core/arm7tdmi/thumb/mod.rs index 89af391..6c96886 100644 --- a/src/core/arm7tdmi/thumb/mod.rs +++ b/src/core/arm7tdmi/thumb/mod.rs @@ -343,9 +343,10 @@ impl ThumbInstruction { #[cfg(test)] /// All instructions constants were generated using an ARM assembler. mod tests { + use super::super::Core; use super::*; - use crate::core::arm7tdmi::{Bus, Core}; use crate::core::sysbus::BoxedMemory; + use crate::core::Bus; #[test] fn mov_low_reg() { diff --git a/src/core/arm7tdmi/bus.rs b/src/core/bus.rs similarity index 95% rename from src/core/arm7tdmi/bus.rs rename to src/core/bus.rs index eff414f..3a2dc0b 100644 --- a/src/core/arm7tdmi/bus.rs +++ b/src/core/bus.rs @@ -1,4 +1,4 @@ -use super::Addr; +pub type Addr = u32; pub trait Bus { fn read_32(&self, addr: Addr) -> u32; diff --git a/src/core/cartridge.rs b/src/core/cartridge.rs index 06e3da3..3ac6a0d 100644 --- a/src/core/cartridge.rs +++ b/src/core/cartridge.rs @@ -8,8 +8,7 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use zip::ZipArchive; use super::super::util::read_bin_file; -use super::arm7tdmi::{bus::Bus, Addr}; -use super::{GBAError, GBAResult}; +use super::{Addr, Bus, GBAResult}; /// From GBATEK /// diff --git a/src/core/dma.rs b/src/core/dma.rs index 012fdea..2d795f9 100644 --- a/src/core/dma.rs +++ b/src/core/dma.rs @@ -2,10 +2,9 @@ extern crate bit_set; use bit_set::BitSet; -use super::arm7tdmi::{Addr, Bus}; use super::iodev::consts::{REG_FIFO_A, REG_FIFO_B}; use super::sysbus::SysBus; -use super::{Interrupt, IrqBitmask}; +use super::{Addr, Bus, Interrupt, IrqBitmask}; use num::FromPrimitive; diff --git a/src/core/gba.rs b/src/core/gba.rs index 21138b7..489399e 100644 --- a/src/core/gba.rs +++ b/src/core/gba.rs @@ -29,8 +29,8 @@ impl GameBoyAdvance { audio_device: Rc>, input_device: Rc>, ) -> GameBoyAdvance { - let gpu = Gpu::new(video_device.clone()); - let sound_controller = SoundController::new(audio_device.clone()); + let gpu = Box::new(Gpu::new(video_device.clone())); + let sound_controller = Box::new(SoundController::new(audio_device.clone())); let io = IoDevices::new(gpu, sound_controller); GameBoyAdvance { cpu: cpu, @@ -48,6 +48,7 @@ impl GameBoyAdvance { pub fn frame(&mut self) { self.key_poll(); + self.sysbus.io.gpu.clear(); while self.sysbus.io.gpu.vcount != DISPLAY_HEIGHT { self.step(); } diff --git a/src/core/gpu/mod.rs b/src/core/gpu/mod.rs index 143ecf5..fdd3b72 100644 --- a/src/core/gpu/mod.rs +++ b/src/core/gpu/mod.rs @@ -1,38 +1,48 @@ use std::cell::RefCell; -use std::rc::Rc; use std::fmt; +use std::rc::Rc; -use super::arm7tdmi::{Addr, Bus}; -use super::*; -use crate::VideoInterface; +use super::super::VideoInterface; +use super::interrupt::IrqBitmask; +use super::sysbus::{BoxedMemory, SysBus}; +use super::Bus; use crate::bitfield::Bit; use crate::num::FromPrimitive; +mod render; + mod mosaic; -mod obj; -use obj::ObjInfo; -mod sfx; mod rgb15; +mod sfx; pub use rgb15::Rgb15; pub mod regs; pub use regs::*; -pub const VRAM_ADDR: Addr = 0x0600_0000; -pub const DISPLAY_WIDTH: usize = 240; -pub const DISPLAY_HEIGHT: usize = 160; -pub const VBLANK_LINES: usize = 68; +#[allow(unused)] +pub mod consts { + pub const VIDEO_RAM_SIZE: usize = 128 * 1024; + pub const PALETTE_RAM_SIZE: usize = 1 * 1024; + pub const OAM_SIZE: usize = 1 * 1024; -const CYCLES_PIXEL: usize = 4; -const CYCLES_HDRAW: usize = 960; -const CYCLES_HBLANK: usize = 272; -const CYCLES_SCANLINE: usize = 1232; -const CYCLES_VDRAW: usize = 197120; -const CYCLES_VBLANK: usize = 83776; + pub const VRAM_ADDR: u32 = 0x0600_0000; + pub const DISPLAY_WIDTH: usize = 240; + pub const DISPLAY_HEIGHT: usize = 160; + pub const VBLANK_LINES: usize = 68; -pub const TILE_SIZE: u32 = 0x20; + pub(super) const CYCLES_PIXEL: usize = 4; + pub(super) const CYCLES_HDRAW: usize = 960; + pub(super) const CYCLES_HBLANK: usize = 272; + pub(super) const CYCLES_SCANLINE: usize = 1232; + pub(super) const CYCLES_VDRAW: usize = 197120; + pub(super) const CYCLES_VBLANK: usize = 83776; + pub const TILE_SIZE: u32 = 0x20; +} +pub use self::consts::*; + +pub type FrameBuffer = [T; DISPLAY_WIDTH * DISPLAY_HEIGHT]; #[derive(Debug, Primitive, Copy, Clone)] pub enum PixelFormat { @@ -146,6 +156,23 @@ pub struct BgAffine { pub y: i32, } +#[derive(Debug, Copy, Clone)] +pub struct ObjBufferEntry { + pub(super) color: Rgb15, + pub(super) priority: u16, + pub(super) window: bool, +} + +impl Default for ObjBufferEntry { + fn default() -> ObjBufferEntry { + ObjBufferEntry { + window: false, + color: Rgb15::TRANSPARENT, + priority: 4, + } + } +} + type VideoDeviceRcRefCell = Rc>; #[derive(DebugStub)] @@ -173,11 +200,15 @@ pub struct Gpu { pub bldalpha: BlendAlpha, pub bldy: u16, + pub palette_ram: BoxedMemory, + pub vram: BoxedMemory, + pub oam: BoxedMemory, + #[debug_stub = "Sprite Buffer"] - pub obj_buffer: [ObjInfo; DISPLAY_WIDTH], + pub obj_buffer: FrameBuffer, #[debug_stub = "Frame Buffer"] - pub frame_buffer: [u32; DISPLAY_WIDTH * DISPLAY_HEIGHT], + pub(super) frame_buffer: FrameBuffer, } impl Gpu { @@ -201,210 +232,95 @@ impl Gpu { state: HDraw, vcount: 0, cycles: 0, - obj_buffer: [Default::default(); DISPLAY_WIDTH], + + palette_ram: BoxedMemory::new(vec![0; PALETTE_RAM_SIZE].into_boxed_slice()), + vram: BoxedMemory::new(vec![0; VIDEO_RAM_SIZE].into_boxed_slice()), + oam: BoxedMemory::new(vec![0; OAM_SIZE].into_boxed_slice()), + + obj_buffer: [Default::default(); DISPLAY_WIDTH * DISPLAY_HEIGHT], frame_buffer: [0; DISPLAY_WIDTH * DISPLAY_HEIGHT], } } /// helper method that reads the palette index from a base address and x + y - pub fn read_pixel_index( - &self, - sb: &SysBus, - addr: Addr, - x: u32, - y: u32, - format: PixelFormat, - ) -> usize { + pub fn read_pixel_index(&self, addr: u32, x: u32, y: u32, format: PixelFormat) -> usize { let ofs = addr - VRAM_ADDR; match format { PixelFormat::BPP4 => { - let byte = sb.vram.read_8(ofs + index2d!(Addr, x / 2, y, 4)); + let byte = self.vram.read_8(ofs + index2d!(u32, x / 2, y, 4)); if x & 1 != 0 { (byte >> 4) as usize } else { (byte & 0xf) as usize } } - PixelFormat::BPP8 => sb.vram.read_8(ofs + index2d!(Addr, x, y, 8)) as usize, + PixelFormat::BPP8 => self.vram.read_8(ofs + index2d!(u32, x, y, 8)) as usize, } } - pub fn get_palette_color( - &self, - sb: &SysBus, - index: u32, - palette_index: u32, - offset: u32, - ) -> Rgb15 { + pub fn get_palette_color(&self, index: u32, palette_index: u32, offset: u32) -> Rgb15 { if index == 0 || (palette_index != 0 && index % 16 == 0) { return Rgb15::TRANSPARENT; } Rgb15( - sb.palette_ram + self.palette_ram .read_16(offset + 2 * index + 0x20 * palette_index), ) } - fn render_pixel(&mut self, x: i32, y: i32, p: Rgb15) { + pub(super) fn obj_buffer_get(&self, x: usize, y: usize) -> &ObjBufferEntry { + &self.obj_buffer[index2d!(x, y, DISPLAY_WIDTH)] + } + + pub(super) fn obj_buffer_get_mut(&mut self, x: usize, y: usize) -> &mut ObjBufferEntry { + &mut self.obj_buffer[index2d!(x, y, DISPLAY_WIDTH)] + } + + pub(super) fn render_pixel(&mut self, x: i32, y: i32, p: Rgb15) { self.frame_buffer[index2d!(usize, x, y, DISPLAY_WIDTH)] = p.to_rgb24(); } - fn scanline_reg_bg(&mut self, bg: usize, sb: &mut SysBus) { - let (h_ofs, v_ofs) = (self.bg[bg].bghofs as u32, self.bg[bg].bgvofs as u32); - let tileset_base = self.bg[bg].bgcnt.char_block(); - let tilemap_base = self.bg[bg].bgcnt.screen_block(); - let (tile_size, pixel_format) = self.bg[bg].bgcnt.tile_format(); - - let (bg_width, bg_height) = self.bg[bg].bgcnt.size_regular(); - - let screen_y = self.vcount as u32; - let mut screen_x = 0; - - // calculate the bg coords at the top-left corner, including wraparound - let bg_x = (screen_x + h_ofs) % bg_width; - let bg_y = (screen_y + v_ofs) % bg_height; - - // calculate the initial screen entry index - // | (256,256) | (512,256) | (256,512) | (512,512) | - // |-----------|-----------|-------------|-----------| - // | | | [1] | [2][3] | - // | [0] | [0][1] | [0] | [0][1] | - // |___________|___________|_____________|___________| - // - let mut sbb = match (bg_width, bg_height) { - (256, 256) => 0, - (512, 256) => bg_x / 256, - (256, 512) => bg_y / 256, - (512, 512) => index2d!(u32, bg_x / 256, bg_y / 256, 2), - _ => unreachable!(), - } as u32; - - let mut se_row = (bg_x / 8) % 32; - let se_column = (bg_y / 8) % 32; - - // this will be non-zero if the h-scroll lands in a middle of a tile - let mut start_tile_x = bg_x % 8; - let tile_py = (bg_y % 8) as u32; - - loop { - let mut map_addr = - tilemap_base + SCREEN_BLOCK_SIZE * sbb + 2 * index2d!(u32, se_row, se_column, 32); - for _ in se_row..32 { - let entry = TileMapEntry(sb.vram.read_16(map_addr - VRAM_ADDR)); - let tile_addr = tileset_base + entry.tile_index() * tile_size; - - for tile_px in start_tile_x..8 { - let index = self.read_pixel_index( - sb, - tile_addr, - if entry.x_flip() { 7 - tile_px } else { tile_px }, - if entry.y_flip() { 7 - tile_py } else { tile_py }, - pixel_format, - ); - let palette_bank = match pixel_format { - PixelFormat::BPP4 => entry.palette_bank() as u32, - PixelFormat::BPP8 => 0u32, - }; - let color = self.get_palette_color(sb, index as u32, palette_bank, 0); - self.bg[bg].line[screen_x as usize] = color; - screen_x += 1; - if (DISPLAY_WIDTH as u32) == screen_x { - return; - } - } - start_tile_x = 0; - map_addr += 2; - } - se_row = 0; - if bg_width == 512 { - sbb = sbb ^ 1; - } - } - } - - fn scanline_aff_bg(&mut self, bg: usize, sb: &mut SysBus) { - // TODO - self.bg[bg].line = Scanline::default(); - } - - fn scanline_mode3(&mut self, bg: usize, sb: &mut SysBus) { - let y = self.vcount; - - for x in 0..DISPLAY_WIDTH { - let pixel_index = index2d!(u32, x, y, DISPLAY_WIDTH); - let pixel_ofs = 2 * pixel_index; - let color = Rgb15(sb.vram.read_16(pixel_ofs)); - self.bg[bg].line[x] = color; - } - } - - fn scanline_mode4(&mut self, bg: usize, sb: &mut SysBus) { - let page_ofs: u32 = match self.dispcnt.display_frame() { - 0 => 0x0600_0000 - VRAM_ADDR, - 1 => 0x0600_a000 - VRAM_ADDR, - _ => unreachable!(), - }; - - let y = self.vcount; - - for x in 0..DISPLAY_WIDTH { - let bitmap_index = index2d!(x, y, DISPLAY_WIDTH); - let bitmap_ofs = page_ofs + (bitmap_index as u32); - let index = sb.vram.read_8(bitmap_ofs as Addr) as u32; - let color = self.get_palette_color(sb, index, 0, 0); - self.bg[bg].line[x] = color; - } - } - - pub fn render_scanline(&mut self, sb: &mut SysBus) { - // TODO - also render objs + pub fn render_scanline(&mut self) { match self.dispcnt.mode() { 0 => { for bg in 0..4 { if self.dispcnt.disp_bg(bg) { - self.scanline_reg_bg(bg, sb); + self.render_reg_bg(bg); } } } 1 => { if self.dispcnt.disp_bg(2) { - self.scanline_aff_bg(2, sb); + self.render_aff_bg(2); } if self.dispcnt.disp_bg(1) { - self.scanline_reg_bg(1, sb); + self.render_reg_bg(1); } if self.dispcnt.disp_bg(0) { - self.scanline_reg_bg(0, sb); + self.render_reg_bg(0); } } 2 => { if self.dispcnt.disp_bg(3) { - self.scanline_aff_bg(3, sb); + self.render_aff_bg(3); } if self.dispcnt.disp_bg(2) { - self.scanline_aff_bg(2, sb); + self.render_aff_bg(2); } } 3 => { - self.scanline_mode3(2, sb); + self.render_mode3(2); } 4 => { - self.scanline_mode4(2, sb); + self.render_mode4(2); } _ => panic!("{:?} not supported", self.dispcnt.mode()), } if self.dispcnt.disp_obj() { - self.render_objs(sb); + self.render_objs(); } self.mosaic_sfx(); - let post_sfx_line = self.composite_sfx(sb); - for x in 0..DISPLAY_WIDTH { - self.frame_buffer[x + self.vcount * DISPLAY_WIDTH] = post_sfx_line[x].to_rgb24(); - } - } - - pub fn get_framebuffer(&self) -> &[u32] { - &self.frame_buffer + self.composite_sfx_to_framebuffer(); } fn update_vcount(&mut self, value: usize, irqs: &mut IrqBitmask) { @@ -418,6 +334,13 @@ impl Gpu { } } + // Clears the gpu internal buffer + pub fn clear(&mut self) { + for x in self.obj_buffer.iter_mut() { + *x = Default::default(); + } + } + // Returns the new gpu state pub fn step(&mut self, cycles: usize, sb: &mut SysBus, irqs: &mut IrqBitmask) { self.cycles += cycles; @@ -443,7 +366,7 @@ impl Gpu { self.update_vcount(self.vcount + 1, irqs); if self.vcount < DISPLAY_HEIGHT { - self.render_scanline(sb); + self.render_scanline(); self.state = HDraw; } else { self.state = VBlank; @@ -465,7 +388,7 @@ impl Gpu { } else { self.update_vcount(0, irqs); self.dispstat.set_vblank_flag(false); - self.render_scanline(sb); + self.render_scanline(); self.state = HDraw; } } @@ -473,12 +396,3 @@ impl Gpu { } } } - -bitfield! { - struct TileMapEntry(u16); - u16; - u32, tile_index, _: 9, 0; - x_flip, _ : 10; - y_flip, _ : 11; - palette_bank, _ : 15, 12; -} diff --git a/src/core/gpu/render.rs b/src/core/gpu/render.rs new file mode 100644 index 0000000..2a6c06e --- /dev/null +++ b/src/core/gpu/render.rs @@ -0,0 +1,3 @@ +pub(super) mod bitmap; +pub(super) mod obj; +pub(super) mod text; diff --git a/src/core/gpu/render/bitmap.rs b/src/core/gpu/render/bitmap.rs new file mode 100644 index 0000000..34e310a --- /dev/null +++ b/src/core/gpu/render/bitmap.rs @@ -0,0 +1,38 @@ +//! Rendering for modes 4-5 + +use super::super::consts::*; +use super::super::Gpu; +use super::super::Rgb15; + +use crate::core::Bus; + +impl Gpu { + pub(in super::super) fn render_mode3(&mut self, bg: usize) { + let y = self.vcount; + + for x in 0..DISPLAY_WIDTH { + let pixel_index = index2d!(u32, x, y, DISPLAY_WIDTH); + let pixel_ofs = 2 * pixel_index; + let color = Rgb15(self.vram.read_16(pixel_ofs)); + self.bg[bg].line[x] = color; + } + } + + pub(in super::super) fn render_mode4(&mut self, bg: usize) { + let page_ofs: u32 = match self.dispcnt.display_frame() { + 0 => 0x0600_0000 - VRAM_ADDR, + 1 => 0x0600_a000 - VRAM_ADDR, + _ => unreachable!(), + }; + + let y = self.vcount; + + for x in 0..DISPLAY_WIDTH { + let bitmap_index = index2d!(x, y, DISPLAY_WIDTH); + let bitmap_ofs = page_ofs + (bitmap_index as u32); + let index = self.vram.read_8(bitmap_ofs) as u32; + let color = self.get_palette_color(index, 0, 0); + self.bg[bg].line[x] = color; + } + } +} diff --git a/src/core/gpu/obj.rs b/src/core/gpu/render/obj.rs similarity index 73% rename from src/core/gpu/obj.rs rename to src/core/gpu/render/obj.rs index a65372d..40b23ff 100644 --- a/src/core/gpu/obj.rs +++ b/src/core/gpu/render/obj.rs @@ -1,6 +1,5 @@ -use super::super::SysBus; -use super::regs::*; -use super::*; +use super::super::regs::*; +use super::super::*; const OVRAM: u32 = 0x0601_0000; const PALRAM_OFS_FG: u32 = 0x200; @@ -10,21 +9,6 @@ struct ObjAttrs(Attribute0, Attribute1, Attribute2); const AFFINE_FILL: u32 = 2 * 3; -impl AffineMatrix { - fn from_index(sb: &SysBus, index: u32) -> AffineMatrix { - let mut offset = AFFINE_FILL + index * 16 * 2; - let pa = sb.oam.read_16(offset) as i16 as i32; - offset += 2 + AFFINE_FILL; - let pb = sb.oam.read_16(offset) as i16 as i32; - offset += 2 + AFFINE_FILL; - let pc = sb.oam.read_16(offset) as i16 as i32; - offset += 2 + AFFINE_FILL; - let pd = sb.oam.read_16(offset) as i16 as i32; - - AffineMatrix { pa, pb, pc, pd } - } -} - impl ObjAttrs { fn size(&self) -> (i32, i32) { match (self.1.size(), self.0.shape()) { @@ -71,22 +55,11 @@ impl ObjAttrs { let attr1 = (self.1).0; ((attr1 >> 9) & 0x1f) as u32 } - fn affine_matrix(&self, sb: &SysBus) -> AffineMatrix { - AffineMatrix::from_index(sb, self.affine_index()) - } fn is_hidden(&self) -> bool { self.0.objtype() == ObjType::Hidden } } -fn read_obj_attrs(sb: &SysBus, obj: usize) -> ObjAttrs { - let addr = ATTRS_SIZE * (obj as u32); - let attr0 = Attribute0(sb.oam.read_16(addr + 0)); - let attr1 = Attribute1(sb.oam.read_16(addr + 2)); - let attr2 = Attribute2(sb.oam.read_16(addr + 4)); - ObjAttrs(attr0, attr1, attr2) -} - impl Gpu { fn obj_tile_base(&self) -> u32 { match self.dispcnt.mode() { @@ -95,7 +68,28 @@ impl Gpu { } } - fn render_affine_obj(&mut self, sb: &SysBus, obj: ObjAttrs, _obj_num: usize) { + fn get_affine_matrix(&self, affine_index: u32) -> AffineMatrix { + let mut offset = AFFINE_FILL + affine_index * 16 * 2; + let pa = self.oam.read_16(offset) as i16 as i32; + offset += 2 + AFFINE_FILL; + let pb = self.oam.read_16(offset) as i16 as i32; + offset += 2 + AFFINE_FILL; + let pc = self.oam.read_16(offset) as i16 as i32; + offset += 2 + AFFINE_FILL; + let pd = self.oam.read_16(offset) as i16 as i32; + + AffineMatrix { pa, pb, pc, pd } + } + + fn read_obj_attrs(&self, obj: usize) -> ObjAttrs { + let addr = ATTRS_SIZE * (obj as u32); + let attr0 = Attribute0(self.oam.read_16(addr + 0)); + let attr1 = Attribute1(self.oam.read_16(addr + 2)); + let attr2 = Attribute2(self.oam.read_16(addr + 4)); + ObjAttrs(attr0, attr1, attr2) + } + + fn render_affine_obj(&mut self, obj: ObjAttrs, _obj_num: usize) { let screen_y = self.vcount as i32; let (ref_x, ref_y) = obj.coords(); @@ -131,7 +125,7 @@ impl Gpu { } }; - let affine_matrix = obj.affine_matrix(sb); + let affine_matrix = self.get_affine_matrix(obj.affine_index()); let half_width = bbox_w / 2; let half_height = bbox_h / 2; @@ -145,7 +139,11 @@ impl Gpu { if screen_x >= screen_width { break; } - if self.obj_buffer[screen_x as usize].priority <= obj.2.priority() { + if self + .obj_buffer_get(screen_x as usize, screen_y as usize) + .priority + <= obj.2.priority() + { continue; } @@ -159,25 +157,16 @@ impl Gpu { let tile_addr = tile_base + index2d!(u32, texture_x / 8, texture_y / 8, tile_array_width) * (tile_size as u32); - let pixel_index = self.read_pixel_index( - sb, - tile_addr, - tile_x as u32, - tile_y as u32, - pixel_format, - ); + let pixel_index = + self.read_pixel_index(tile_addr, tile_x as u32, tile_y as u32, pixel_format); let pixel_color = - self.get_palette_color(sb, pixel_index as u32, palette_bank, PALRAM_OFS_FG); - if pixel_color != Rgb15::TRANSPARENT { - let mut current_obj = &mut self.obj_buffer[screen_x as usize]; - current_obj.color = pixel_color; - current_obj.priority = obj.2.priority(); - } + self.get_palette_color(pixel_index as u32, palette_bank, PALRAM_OFS_FG); + self.write_obj_pixel(screen_x as usize, screen_y as usize, pixel_color, &obj); } } } - fn render_normal_obj(&mut self, sb: &SysBus, obj: ObjAttrs, _obj_num: usize) { + fn render_normal_obj(&mut self, obj: ObjAttrs, _obj_num: usize) { let screen_y = self.vcount as i32; let (ref_x, ref_y) = obj.coords(); @@ -217,7 +206,11 @@ impl Gpu { if screen_x >= screen_width { break; } - if self.obj_buffer[screen_x as usize].priority <= obj.2.priority() { + if self + .obj_buffer_get(screen_x as usize, screen_y as usize) + .priority + <= obj.2.priority() + { continue; } let mut sprite_y = screen_y - ref_y; @@ -237,46 +230,39 @@ impl Gpu { let tile_addr = tile_base + index2d!(u32, sprite_x / 8, sprite_y / 8, tile_array_width) * (tile_size as u32); let pixel_index = - self.read_pixel_index(sb, tile_addr, tile_x as u32, tile_y as u32, pixel_format); + self.read_pixel_index(tile_addr, tile_x as u32, tile_y as u32, pixel_format); let pixel_color = - self.get_palette_color(sb, pixel_index as u32, palette_bank, PALRAM_OFS_FG); - if pixel_color != Rgb15::TRANSPARENT { - let mut current_obj = &mut self.obj_buffer[screen_x as usize]; - current_obj.color = pixel_color; - current_obj.priority = obj.2.priority(); - } + self.get_palette_color(pixel_index as u32, palette_bank, PALRAM_OFS_FG); + self.write_obj_pixel(screen_x as usize, screen_y as usize, pixel_color, &obj); } } - pub fn render_objs(&mut self, sb: &SysBus) { - // reset the scanline - self.obj_buffer = [Default::default(); DISPLAY_WIDTH]; - for obj_num in 0..128 { - let obj = read_obj_attrs(sb, obj_num); - match obj.0.objtype() { - ObjType::Hidden => continue, - ObjType::Normal => self.render_normal_obj(sb, obj, obj_num), - ObjType::Affine | ObjType::AffineDoubleSize => { - self.render_affine_obj(sb, obj, obj_num) + fn write_obj_pixel(&mut self, x: usize, y: usize, pixel_color: Rgb15, attrs: &ObjAttrs) { + let mut current_obj = self.obj_buffer_get_mut(x, y); + match attrs.0.objmode() { + ObjMode::Normal | ObjMode::Sfx => { + if pixel_color != Rgb15::TRANSPARENT { + current_obj.color = pixel_color; + current_obj.priority = attrs.2.priority(); } } + ObjMode::Window => { + current_obj.window = true; + } + ObjMode::Forbidden => { + panic!("Forbidden sprite mode!"); + } } } -} -#[derive(Debug, Copy, Clone)] -pub struct ObjInfo { - pub(super) color: Rgb15, - pub(super) priority: u16, - pub(super) mode: ObjMode, -} - -impl Default for ObjInfo { - fn default() -> ObjInfo { - ObjInfo { - mode: ObjMode::Normal, - color: Rgb15::TRANSPARENT, - priority: 4, + pub(in super::super) fn render_objs(&mut self) { + for obj_num in 0..128 { + let obj = self.read_obj_attrs(obj_num); + match obj.0.objtype() { + ObjType::Hidden => continue, + ObjType::Normal => self.render_normal_obj(obj, obj_num), + ObjType::Affine | ObjType::AffineDoubleSize => self.render_affine_obj(obj, obj_num), + } } } } diff --git a/src/core/gpu/render/text.rs b/src/core/gpu/render/text.rs new file mode 100644 index 0000000..1b1f4c9 --- /dev/null +++ b/src/core/gpu/render/text.rs @@ -0,0 +1,94 @@ +//! Rendering for modes 0-3 + +use super::super::consts::*; +use super::super::{Gpu, PixelFormat, Scanline, SCREEN_BLOCK_SIZE}; + +use crate::core::Bus; + +impl Gpu { + pub(in super::super) fn render_reg_bg(&mut self, bg: usize) { + let (h_ofs, v_ofs) = (self.bg[bg].bghofs as u32, self.bg[bg].bgvofs as u32); + let tileset_base = self.bg[bg].bgcnt.char_block(); + let tilemap_base = self.bg[bg].bgcnt.screen_block(); + let (tile_size, pixel_format) = self.bg[bg].bgcnt.tile_format(); + + let (bg_width, bg_height) = self.bg[bg].bgcnt.size_regular(); + + let screen_y = self.vcount as u32; + let mut screen_x = 0; + + // calculate the bg coords at the top-left corner, including wraparound + let bg_x = (screen_x + h_ofs) % bg_width; + let bg_y = (screen_y + v_ofs) % bg_height; + + // calculate the initial screen entry index + // | (256,256) | (512,256) | (256,512) | (512,512) | + // |-----------|-----------|-------------|-----------| + // | | | [1] | [2][3] | + // | [0] | [0][1] | [0] | [0][1] | + // |___________|___________|_____________|___________| + // + let mut sbb = match (bg_width, bg_height) { + (256, 256) => 0, + (512, 256) => bg_x / 256, + (256, 512) => bg_y / 256, + (512, 512) => index2d!(u32, bg_x / 256, bg_y / 256, 2), + _ => unreachable!(), + } as u32; + + let mut se_row = (bg_x / 8) % 32; + let se_column = (bg_y / 8) % 32; + + // this will be non-zero if the h-scroll lands in a middle of a tile + let mut start_tile_x = bg_x % 8; + let tile_py = (bg_y % 8) as u32; + + loop { + let mut map_addr = + tilemap_base + SCREEN_BLOCK_SIZE * sbb + 2 * index2d!(u32, se_row, se_column, 32); + for _ in se_row..32 { + let entry = TileMapEntry(self.vram.read_16(map_addr - VRAM_ADDR)); + let tile_addr = tileset_base + entry.tile_index() * tile_size; + + for tile_px in start_tile_x..8 { + let index = self.read_pixel_index( + tile_addr, + if entry.x_flip() { 7 - tile_px } else { tile_px }, + if entry.y_flip() { 7 - tile_py } else { tile_py }, + pixel_format, + ); + let palette_bank = match pixel_format { + PixelFormat::BPP4 => entry.palette_bank() as u32, + PixelFormat::BPP8 => 0u32, + }; + let color = self.get_palette_color(index as u32, palette_bank, 0); + self.bg[bg].line[screen_x as usize] = color; + screen_x += 1; + if (DISPLAY_WIDTH as u32) == screen_x { + return; + } + } + start_tile_x = 0; + map_addr += 2; + } + se_row = 0; + if bg_width == 512 { + sbb = sbb ^ 1; + } + } + } + + pub(in super::super) fn render_aff_bg(&mut self, bg: usize) { + // TODO + self.bg[bg].line = Scanline::default(); + } +} + +bitfield! { + struct TileMapEntry(u16); + u16; + u32, tile_index, _: 9, 0; + x_flip, _ : 10; + y_flip, _ : 11; + palette_bank, _ : 15, 12; +} diff --git a/src/core/gpu/rgb15.rs b/src/core/gpu/rgb15.rs index 93b1e1a..9e999c0 100644 --- a/src/core/gpu/rgb15.rs +++ b/src/core/gpu/rgb15.rs @@ -1,37 +1,37 @@ -//! Helper type to deal with the GBA's 15bit color - -bitfield! { - #[repr(transparent)] - #[derive(Copy, Clone, Default, PartialEq)] - pub struct Rgb15(u16); - impl Debug; - pub r, set_r: 4, 0; - pub g, set_g: 9, 5; - pub b, set_b: 14, 10; -} - -impl Rgb15 { - pub const BLACK: Rgb15 = Rgb15(0); - pub const WHITE: Rgb15 = Rgb15(0x7fff); - pub const TRANSPARENT: Rgb15 = Rgb15(0x8000); - - pub fn to_rgb24(&self) -> u32 { - ((self.r() as u32) << 19) | ((self.g() as u32) << 11) | ((self.b() as u32) << 3) - } - - pub fn from_rgb(r: u16, g: u16, b: u16) -> Rgb15 { - let mut c = Rgb15(0); - c.set_r(r); - c.set_g(g); - c.set_b(b); - c - } - - pub fn get_rgb(&self) -> (u16, u16, u16) { - (self.r(), self.g(), self.b()) - } - - pub fn is_transparent(&self) -> bool { - self.0 == 0x8000 - } -} \ No newline at end of file +//! Helper type to deal with the GBA's 15bit color + +bitfield! { + #[repr(transparent)] + #[derive(Copy, Clone, Default, PartialEq)] + pub struct Rgb15(u16); + impl Debug; + pub r, set_r: 4, 0; + pub g, set_g: 9, 5; + pub b, set_b: 14, 10; +} + +impl Rgb15 { + pub const BLACK: Rgb15 = Rgb15(0); + pub const WHITE: Rgb15 = Rgb15(0x7fff); + pub const TRANSPARENT: Rgb15 = Rgb15(0x8000); + + pub fn to_rgb24(&self) -> u32 { + ((self.r() as u32) << 19) | ((self.g() as u32) << 11) | ((self.b() as u32) << 3) + } + + pub fn from_rgb(r: u16, g: u16, b: u16) -> Rgb15 { + let mut c = Rgb15(0); + c.set_r(r); + c.set_g(g); + c.set_b(b); + c + } + + pub fn get_rgb(&self) -> (u16, u16, u16) { + (self.r(), self.g(), self.b()) + } + + pub fn is_transparent(&self) -> bool { + self.0 == 0x8000 + } +} diff --git a/src/core/gpu/sfx.rs b/src/core/gpu/sfx.rs index 6bca754..ef6540a 100644 --- a/src/core/gpu/sfx.rs +++ b/src/core/gpu/sfx.rs @@ -1,5 +1,4 @@ use std::cmp; -use std::ops::Sub; use super::regs::*; use super::*; @@ -42,20 +41,20 @@ struct Layer { impl Gpu { fn get_top_layer( &self, - sb: &SysBus, screen_x: usize, bflags: BlendFlags, wflags: WindowFlags, ) -> Option { // priorities are 0-4 when 0 is the highest 'outer: for priority in 0..4 { + let obj = self.obj_buffer_get(screen_x, self.vcount); if bflags.contains(BlendFlags::OBJ) && wflags.contains(WindowFlags::OBJ) - && !self.obj_buffer[screen_x].color.is_transparent() - && self.obj_buffer[screen_x].priority == priority + && !obj.color.is_transparent() + && obj.priority == priority { return Some(Layer { - color: self.obj_buffer[screen_x].color, + color: obj.color, blend_flag: BlendFlags::OBJ, }); } @@ -75,7 +74,7 @@ impl Gpu { } } } - let backdrop = sb.palette_ram.read_16(0); + let backdrop = self.palette_ram.read_16(0); if bflags.contains(BlendFlags::BACKDROP) { return Some(Layer { color: Rgb15(backdrop), @@ -110,17 +109,11 @@ impl Gpu { } } - fn sfx_blend_alpha( - &self, - sb: &SysBus, - x: usize, - _y: usize, - wflags: WindowFlags, - ) -> Option { + fn sfx_blend_alpha(&self, x: usize, _y: usize, wflags: WindowFlags) -> Option { let top_layers = self.bldcnt.top(); let bottom_layers = self.bldcnt.bottom(); - if let Some(top_layer) = self.get_top_layer(sb, x, top_layers, wflags) { - if let Some(bot_layer) = self.get_top_layer(sb, x, bottom_layers, wflags) { + if let Some(top_layer) = self.get_top_layer(x, top_layers, wflags) { + if let Some(bot_layer) = self.get_top_layer(x, bottom_layers, wflags) { let eva = self.bldalpha.eva(); let evb = self.bldalpha.evb(); return Some(top_layer.color.blend_with(bot_layer.color, eva, evb)); @@ -133,7 +126,6 @@ impl Gpu { fn sfx_blend_bw( &self, - sb: &SysBus, fadeto: Rgb15, x: usize, _y: usize, @@ -142,21 +134,19 @@ impl Gpu { let top_layers = self.bldcnt.top(); let evy = self.bldy; - if let Some(layer) = self.get_top_layer(sb, x, top_layers, wflags) { + if let Some(layer) = self.get_top_layer(x, top_layers, wflags) { return Some(layer.color.blend_with(fadeto, 16 - evy, evy)); } None } - pub fn composite_sfx(&self, sb: &SysBus) -> Scanline { - let mut line: Scanline = Scanline::default(); + pub fn composite_sfx_to_framebuffer(&mut self) { let y = self.vcount; + for x in 0..DISPLAY_WIDTH { let window = self.get_active_window_type(x, y); let wflags = self.get_window_flags(window); - let toplayer = self - .get_top_layer(sb, x, BlendFlags::all(), wflags) - .unwrap(); + let toplayer = self.get_top_layer(x, BlendFlags::all(), wflags).unwrap(); let bldmode = if wflags.sfx_enabled() { self.bldcnt.mode() @@ -164,41 +154,37 @@ impl Gpu { BldMode::BldNone }; - match bldmode { + let pixel = match bldmode { BldMode::BldAlpha => { if self.bldcnt.top().contains(toplayer.blend_flag) || self.bldcnt.bottom().contains(toplayer.blend_flag) { - line[x] = self - .sfx_blend_alpha(sb, x, y, wflags) - .unwrap_or(toplayer.color); + self.sfx_blend_alpha(x, y, wflags).unwrap_or(toplayer.color) } else { - line[x] = toplayer.color; + toplayer.color } } BldMode::BldWhite => { let result = if self.bldcnt.top().contains(toplayer.blend_flag) { - self.sfx_blend_bw(sb, Rgb15::WHITE, x, y, wflags) + self.sfx_blend_bw(Rgb15::WHITE, x, y, wflags) .unwrap_or(toplayer.color) } else { toplayer.color }; - line[x] = result; + result } BldMode::BldBlack => { let result = if self.bldcnt.top().contains(toplayer.blend_flag) { - self.sfx_blend_bw(sb, Rgb15::BLACK, x, y, wflags) + self.sfx_blend_bw(Rgb15::BLACK, x, y, wflags) .unwrap_or(toplayer.color) } else { toplayer.color }; - line[x] = result; + result } - BldMode::BldNone => { - line[x] = toplayer.color; - } - } + BldMode::BldNone => toplayer.color, + }; + self.render_pixel(x as i32, y as i32, pixel); } - line } } diff --git a/src/core/iodev.rs b/src/core/iodev.rs index f231239..beb4dd5 100644 --- a/src/core/iodev.rs +++ b/src/core/iodev.rs @@ -1,4 +1,3 @@ -use super::arm7tdmi::{Addr, Bus}; use super::dma::DmaController; use super::gpu::regs::WindowFlags; use super::gpu::*; @@ -7,8 +6,9 @@ use super::keypad; use super::sound::SoundController; use super::sysbus::BoxedMemory; use super::timer::Timers; +use super::{Addr, Bus}; -use consts::*; +use self::consts::*; #[derive(Debug, Clone, Copy, PartialEq)] pub enum HaltState { @@ -19,8 +19,8 @@ pub enum HaltState { pub struct IoDevices { pub intc: InterruptController, - pub gpu: Gpu, - pub sound: SoundController, + pub gpu: Box, + pub sound: Box, pub timers: Timers, pub dmac: DmaController, pub keyinput: u16, @@ -32,7 +32,7 @@ pub struct IoDevices { } impl IoDevices { - pub fn new(gpu: Gpu, sound_controller: SoundController) -> IoDevices { + pub fn new(gpu: Box, sound_controller: Box) -> IoDevices { IoDevices { gpu: gpu, sound: sound_controller, diff --git a/src/core/mod.rs b/src/core/mod.rs index f1f97a3..4c10b16 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -10,18 +10,18 @@ pub use interrupt::Interrupt; pub use interrupt::IrqBitmask; pub mod gba; pub use gba::GameBoyAdvance; +pub mod bus; pub mod dma; pub mod keypad; pub mod timer; +pub use bus::*; + +pub use super::{AudioInterface, InputInterface, VideoInterface}; use crate::debugger; use zip; -pub trait SyncedIoDevice { - fn step(&mut self, cycles: usize, sb: &mut SysBus, irqs: &mut IrqBitmask); -} - #[derive(Debug)] pub enum GBAError { IO(::std::io::Error), diff --git a/src/core/sysbus.rs b/src/core/sysbus.rs index 730b9bc..9bb1879 100644 --- a/src/core/sysbus.rs +++ b/src/core/sysbus.rs @@ -3,17 +3,13 @@ use std::ops::Add; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use super::arm7tdmi::bus::Bus; -use super::arm7tdmi::Addr; use super::cartridge::Cartridge; -use super::gpu::GpuState; +use super::gpu::{GpuState, VIDEO_RAM_SIZE}; use super::iodev::IoDevices; +use super::{Addr, Bus}; -const VIDEO_RAM_SIZE: usize = 128 * 1024; const WORK_RAM_SIZE: usize = 256 * 1024; const INTERNAL_RAM_SIZE: usize = 32 * 1024; -const PALETTE_RAM_SIZE: usize = 1 * 1024; -const OAM_SIZE: usize = 1 * 1024; pub const BIOS_ADDR: u32 = 0x0000_0000; pub const EWRAM_ADDR: u32 = 0x0200_0000; @@ -144,9 +140,6 @@ pub struct SysBus { bios: BoxedMemory, onboard_work_ram: BoxedMemory, internal_work_ram: BoxedMemory, - pub palette_ram: BoxedMemory, - pub vram: BoxedMemory, - pub oam: BoxedMemory, gamepak: Cartridge, dummy: DummyBus, @@ -161,9 +154,6 @@ impl SysBus { bios: BoxedMemory::new(bios_rom.into_boxed_slice()), onboard_work_ram: BoxedMemory::new(vec![0; WORK_RAM_SIZE].into_boxed_slice()), internal_work_ram: BoxedMemory::new(vec![0; INTERNAL_RAM_SIZE].into_boxed_slice()), - palette_ram: BoxedMemory::new(vec![0; PALETTE_RAM_SIZE].into_boxed_slice()), - vram: BoxedMemory::new(vec![0; VIDEO_RAM_SIZE].into_boxed_slice()), - oam: BoxedMemory::new(vec![0; OAM_SIZE].into_boxed_slice()), gamepak: gamepak, dummy: DummyBus([0; 4]), @@ -190,15 +180,15 @@ impl SysBus { ofs & 0x7ff } }), - PALRAM_ADDR => (&self.palette_ram, ofs & 0x3ff), - VRAM_ADDR => (&self.vram, { + PALRAM_ADDR => (&self.io.gpu.palette_ram, ofs & 0x3ff), + VRAM_ADDR => (&self.io.gpu.vram, { let mut ofs = ofs & ((VIDEO_RAM_SIZE as u32) - 1); if ofs > 0x18000 { ofs -= 0x8000; } ofs }), - OAM_ADDR => (&self.oam, ofs & 0x3ff), + OAM_ADDR => (&self.io.gpu.oam, ofs & 0x3ff), GAMEPAK_WS0_ADDR | GAMEPAK_MIRROR_WS0_ADDR | GAMEPAK_WS1_ADDR | GAMEPAK_WS2_ADDR => { (&self.gamepak, addr & 0x01ff_ffff) } @@ -220,15 +210,15 @@ impl SysBus { ofs & 0x7ff } }), - PALRAM_ADDR => (&mut self.palette_ram, ofs & 0x3ff), - VRAM_ADDR => (&mut self.vram, { + PALRAM_ADDR => (&mut self.io.gpu.palette_ram, ofs & 0x3ff), + VRAM_ADDR => (&mut self.io.gpu.vram, { let mut ofs = ofs & ((VIDEO_RAM_SIZE as u32) - 1); if ofs > 0x18000 { ofs -= 0x8000; } ofs }), - OAM_ADDR => (&mut self.oam, ofs & 0x3ff), + OAM_ADDR => (&mut self.io.gpu.oam, ofs & 0x3ff), GAMEPAK_WS0_ADDR | GAMEPAK_MIRROR_WS0_ADDR | GAMEPAK_WS1_ADDR | GAMEPAK_WS2_ADDR => { (&mut self.gamepak, addr & 0x01ff_ffff) } diff --git a/src/debugger/command.rs b/src/debugger/command.rs index 472460f..095c6ab 100644 --- a/src/debugger/command.rs +++ b/src/debugger/command.rs @@ -3,10 +3,10 @@ use std::sync::Arc; use std::time; use crate::core::arm7tdmi::arm::ArmInstruction; -use crate::core::arm7tdmi::bus::Bus; use crate::core::arm7tdmi::thumb::ThumbInstruction; -use crate::core::arm7tdmi::{Addr, CpuState}; +use crate::core::arm7tdmi::CpuState; use crate::core::GBAError; +use crate::core::{Addr, Bus}; use crate::disass::Disassembler; use crate::{AudioInterface, InputInterface, VideoInterface}; diff --git a/src/debugger/mod.rs b/src/debugger/mod.rs index f382196..1f51cd1 100644 --- a/src/debugger/mod.rs +++ b/src/debugger/mod.rs @@ -1,6 +1,6 @@ extern crate ctrlc; use std::fs::File; -use std::io::{self, prelude::*, BufReader}; +use std::io::{prelude::*, BufReader}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -9,10 +9,9 @@ use rustyline::Editor; use colored::*; -use super::core::arm7tdmi::{Addr, Bus, CpuError}; +use super::core::arm7tdmi::CpuError; use super::core::GameBoyAdvance; - -use super::{AudioInterface, InputInterface, VideoInterface}; +use super::core::{Addr, Bus}; mod parser; use parser::{parse_expr, DerefType, Expr, Value}; diff --git a/src/disass.rs b/src/disass.rs index 11b8c8c..f6300a8 100644 --- a/src/disass.rs +++ b/src/disass.rs @@ -1,6 +1,7 @@ use std::marker::PhantomData; -use super::core::arm7tdmi::{Addr, InstructionDecoder, InstructionDecoderError}; +use super::core::arm7tdmi::{InstructionDecoder, InstructionDecoderError}; +use super::core::Addr; use std::io::ErrorKind; pub struct Disassembler<'a, D>