Refactor lcd -> gpu
Former-commit-id: c12be139770922bac55490c76348f5406fc00f07
This commit is contained in:
parent
876cdfdcb3
commit
1f074e20ad
|
@ -2,7 +2,7 @@ use crate::arm7tdmi::bus::Bus;
|
||||||
use crate::arm7tdmi::{Addr, CpuState};
|
use crate::arm7tdmi::{Addr, CpuState};
|
||||||
use crate::disass::Disassembler;
|
use crate::disass::Disassembler;
|
||||||
use crate::ioregs::consts::*;
|
use crate::ioregs::consts::*;
|
||||||
use crate::lcd::*;
|
use crate::gpu::*;
|
||||||
use crate::GBAError;
|
use crate::GBAError;
|
||||||
|
|
||||||
use super::palette_view::create_palette_view;
|
use super::palette_view::create_palette_view;
|
||||||
|
|
|
@ -5,10 +5,10 @@ use sdl2::pixels::Color;
|
||||||
use sdl2::rect::Point;
|
use sdl2::rect::Point;
|
||||||
|
|
||||||
use crate::gba::GameBoyAdvance;
|
use crate::gba::GameBoyAdvance;
|
||||||
use crate::lcd::Lcd;
|
use crate::gpu::Gpu;
|
||||||
|
|
||||||
const SCREEN_WIDTH: u32 = Lcd::DISPLAY_WIDTH as u32;
|
const SCREEN_WIDTH: u32 = Gpu::DISPLAY_WIDTH as u32;
|
||||||
const SCREEN_HEIGHT: u32 = Lcd::DISPLAY_HEIGHT as u32;
|
const SCREEN_HEIGHT: u32 = Gpu::DISPLAY_HEIGHT as u32;
|
||||||
|
|
||||||
pub fn create_render_view(gba: &GameBoyAdvance) {
|
pub fn create_render_view(gba: &GameBoyAdvance) {
|
||||||
let sdl_context = sdl2::init().unwrap();
|
let sdl_context = sdl2::init().unwrap();
|
||||||
|
@ -28,7 +28,7 @@ pub fn create_render_view(gba: &GameBoyAdvance) {
|
||||||
match event {
|
match event {
|
||||||
Event::Quit { .. } => break 'running,
|
Event::Quit { .. } => break 'running,
|
||||||
Event::MouseButtonDown { x, y, .. } => {
|
Event::MouseButtonDown { x, y, .. } => {
|
||||||
println!("({},{}) {:x}", x, y, x + y * (Lcd::DISPLAY_WIDTH as i32));
|
println!("({},{}) {:x}", x, y, x + y * (Gpu::DISPLAY_WIDTH as i32));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,10 @@ pub fn create_render_view(gba: &GameBoyAdvance) {
|
||||||
canvas.set_draw_color(Color::RGB(0xfa, 0xfa, 0xfa));
|
canvas.set_draw_color(Color::RGB(0xfa, 0xfa, 0xfa));
|
||||||
canvas.clear();
|
canvas.clear();
|
||||||
|
|
||||||
for y in 0..Lcd::DISPLAY_HEIGHT {
|
for y in 0..Gpu::DISPLAY_HEIGHT {
|
||||||
for x in 0..Lcd::DISPLAY_WIDTH {
|
for x in 0..Gpu::DISPLAY_WIDTH {
|
||||||
let index = (x as usize) + (y as usize) * (256 as usize);
|
let index = (x as usize) + (y as usize) * (256 as usize);
|
||||||
let color = gba.lcd.pixeldata[index];
|
let color = gba.gpu.pixeldata[index];
|
||||||
let rgb24: Color = color.into();
|
let rgb24: Color = color.into();
|
||||||
canvas.set_draw_color(rgb24);
|
canvas.set_draw_color(rgb24);
|
||||||
canvas.draw_point(Point::from((x as i32, y as i32)));
|
canvas.draw_point(Point::from((x as i32, y as i32)));
|
||||||
|
|
|
@ -8,7 +8,7 @@ use sdl2::render::Canvas;
|
||||||
use crate::arm7tdmi::bus::Bus;
|
use crate::arm7tdmi::bus::Bus;
|
||||||
use crate::gba::GameBoyAdvance;
|
use crate::gba::GameBoyAdvance;
|
||||||
use crate::ioregs::consts::*;
|
use crate::ioregs::consts::*;
|
||||||
use crate::lcd::*;
|
use crate::gpu::*;
|
||||||
use crate::palette::*;
|
use crate::palette::*;
|
||||||
use crate::sysbus::SysBus;
|
use crate::sysbus::SysBus;
|
||||||
|
|
||||||
|
@ -31,15 +31,15 @@ fn draw_tile(
|
||||||
let color = match pixel_format {
|
let color = match pixel_format {
|
||||||
PixelFormat::BPP4 => {
|
PixelFormat::BPP4 => {
|
||||||
let index =
|
let index =
|
||||||
gba.lcd
|
gba.gpu
|
||||||
.read_pixel_index(&gba.sysbus, tile_addr, x, y, 4, pixel_format);
|
.read_pixel_index(&gba.sysbus, tile_addr, x, y, 4, pixel_format);
|
||||||
gba.lcd.get_palette_color(&gba.sysbus, index as u32, 0)
|
gba.gpu.get_palette_color(&gba.sysbus, index as u32, 3)
|
||||||
}
|
}
|
||||||
PixelFormat::BPP8 => {
|
PixelFormat::BPP8 => {
|
||||||
let index =
|
let index =
|
||||||
gba.lcd
|
gba.gpu
|
||||||
.read_pixel_index(&gba.sysbus, tile_addr, x, y, 8, pixel_format);
|
.read_pixel_index(&gba.sysbus, tile_addr, x, y, 8, pixel_format);
|
||||||
gba.lcd.get_palette_color(&gba.sysbus, index as u32, 0)
|
gba.gpu.get_palette_color(&gba.sysbus, index as u32, 0)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let (r, g, b) = color.get_rgb24();
|
let (r, g, b) = color.get_rgb24();
|
||||||
|
|
16
src/gba.rs
16
src/gba.rs
|
@ -5,7 +5,7 @@ use super::cartridge::Cartridge;
|
||||||
use super::dma::DmaChannel;
|
use super::dma::DmaChannel;
|
||||||
use super::interrupt::*;
|
use super::interrupt::*;
|
||||||
use super::ioregs::consts::*;
|
use super::ioregs::consts::*;
|
||||||
use super::lcd::*;
|
use super::gpu::*;
|
||||||
use super::sysbus::SysBus;
|
use super::sysbus::SysBus;
|
||||||
|
|
||||||
use super::{EmuIoDev, GBAError, GBAResult};
|
use super::{EmuIoDev, GBAError, GBAResult};
|
||||||
|
@ -15,7 +15,7 @@ pub struct GameBoyAdvance {
|
||||||
pub sysbus: SysBus,
|
pub sysbus: SysBus,
|
||||||
|
|
||||||
// io devices
|
// io devices
|
||||||
pub lcd: Lcd,
|
pub gpu: Gpu,
|
||||||
pub dma0: DmaChannel,
|
pub dma0: DmaChannel,
|
||||||
pub dma1: DmaChannel,
|
pub dma1: DmaChannel,
|
||||||
pub dma2: DmaChannel,
|
pub dma2: DmaChannel,
|
||||||
|
@ -32,7 +32,7 @@ impl GameBoyAdvance {
|
||||||
cpu: cpu,
|
cpu: cpu,
|
||||||
sysbus: sysbus,
|
sysbus: sysbus,
|
||||||
|
|
||||||
lcd: Lcd::new(),
|
gpu: Gpu::new(),
|
||||||
dma0: DmaChannel::new(REG_DMA0SAD, REG_DMA0DAD, REG_DMA0DAD),
|
dma0: DmaChannel::new(REG_DMA0SAD, REG_DMA0DAD, REG_DMA0DAD),
|
||||||
dma1: DmaChannel::new(REG_DMA1SAD, REG_DMA1DAD, REG_DMA1DAD),
|
dma1: DmaChannel::new(REG_DMA1SAD, REG_DMA1DAD, REG_DMA1DAD),
|
||||||
dma2: DmaChannel::new(REG_DMA2SAD, REG_DMA2DAD, REG_DMA2DAD),
|
dma2: DmaChannel::new(REG_DMA2SAD, REG_DMA2DAD, REG_DMA2DAD),
|
||||||
|
@ -49,7 +49,7 @@ impl GameBoyAdvance {
|
||||||
self.cpu.step_one(&mut self.sysbus).unwrap();
|
self.cpu.step_one(&mut self.sysbus).unwrap();
|
||||||
let new_cycles = self.cpu.cycles - previous_cycles;
|
let new_cycles = self.cpu.cycles - previous_cycles;
|
||||||
|
|
||||||
self.lcd.step(new_cycles, &mut self.sysbus);
|
self.gpu.step(new_cycles, &mut self.sysbus);
|
||||||
cycles += new_cycles;
|
cycles += new_cycles;
|
||||||
|
|
||||||
if n <= cycles {
|
if n <= cycles {
|
||||||
|
@ -59,10 +59,10 @@ impl GameBoyAdvance {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame(&mut self) {
|
pub fn frame(&mut self) {
|
||||||
while self.lcd.state == LcdState::VBlank {
|
while self.gpu.state == GpuState::VBlank {
|
||||||
self.emulate();
|
self.emulate();
|
||||||
}
|
}
|
||||||
while self.lcd.state != LcdState::VBlank {
|
while self.gpu.state != GpuState::VBlank {
|
||||||
self.emulate();
|
self.emulate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ impl GameBoyAdvance {
|
||||||
let previous_cycles = self.cpu.cycles;
|
let previous_cycles = self.cpu.cycles;
|
||||||
self.cpu.step(&mut self.sysbus).unwrap();
|
self.cpu.step(&mut self.sysbus).unwrap();
|
||||||
let cycles = self.cpu.cycles - previous_cycles;
|
let cycles = self.cpu.cycles - previous_cycles;
|
||||||
self.lcd.step(cycles, &mut self.sysbus);
|
self.gpu.step(cycles, &mut self.sysbus);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interrupts_disabled(&self) -> bool {
|
fn interrupts_disabled(&self) -> bool {
|
||||||
|
@ -111,7 +111,7 @@ impl GameBoyAdvance {
|
||||||
// cycles += dma_cycles;
|
// cycles += dma_cycles;
|
||||||
|
|
||||||
/* let (_, irq) = */
|
/* let (_, irq) = */
|
||||||
self.lcd.step(cycles, &mut self.sysbus);
|
self.gpu.step(cycles, &mut self.sysbus);
|
||||||
// if let Some(irq) = irq {
|
// if let Some(irq) = irq {
|
||||||
// self.request_irq(irq);
|
// self.request_irq(irq);
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
use std::io::Cursor;
|
|
||||||
use std::io::{Seek, SeekFrom};
|
|
||||||
|
|
||||||
use super::arm7tdmi::{Addr, Bus};
|
use super::arm7tdmi::{Addr, Bus};
|
||||||
use super::ioregs::consts::*;
|
use super::ioregs::consts::*;
|
||||||
use super::palette::{Palette, PixelFormat, Rgb15};
|
use super::palette::{Palette, PixelFormat, Rgb15};
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::bit::BitIndex;
|
use crate::bit::BitIndex;
|
||||||
use crate::byteorder::{LittleEndian, ReadBytesExt};
|
|
||||||
use crate::num::FromPrimitive;
|
use crate::num::FromPrimitive;
|
||||||
|
|
||||||
const VRAM_ADDR: Addr = 0x0600_0000;
|
const VRAM_ADDR: Addr = 0x0600_0000;
|
||||||
|
@ -127,34 +123,34 @@ impl BgControl {
|
||||||
|
|
||||||
pub fn tile_format(&self) -> (u32, PixelFormat) {
|
pub fn tile_format(&self) -> (u32, PixelFormat) {
|
||||||
if self.palette256 {
|
if self.palette256 {
|
||||||
(2 * Lcd::TILE_SIZE, PixelFormat::BPP8)
|
(2 * Gpu::TILE_SIZE, PixelFormat::BPP8)
|
||||||
} else {
|
} else {
|
||||||
(Lcd::TILE_SIZE, PixelFormat::BPP4)
|
(Gpu::TILE_SIZE, PixelFormat::BPP4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
pub enum LcdState {
|
pub enum GpuState {
|
||||||
HDraw = 0,
|
HDraw = 0,
|
||||||
HBlank,
|
HBlank,
|
||||||
VBlank,
|
VBlank,
|
||||||
}
|
}
|
||||||
impl Default for LcdState {
|
impl Default for GpuState {
|
||||||
fn default() -> LcdState {
|
fn default() -> GpuState {
|
||||||
LcdState::HDraw
|
GpuState::HDraw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
use LcdState::*;
|
use GpuState::*;
|
||||||
|
|
||||||
pub struct Lcd {
|
pub struct Gpu {
|
||||||
cycles: usize,
|
cycles: usize,
|
||||||
pub pixeldata: [Rgb15; 256 * 256],
|
pub pixeldata: [Rgb15; 256 * 256],
|
||||||
pub state: LcdState,
|
pub state: GpuState,
|
||||||
pub current_scanline: usize, // VCOUNT
|
pub current_scanline: usize, // VCOUNT
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Lcd {
|
impl Gpu {
|
||||||
pub const DISPLAY_WIDTH: usize = 240;
|
pub const DISPLAY_WIDTH: usize = 240;
|
||||||
pub const DISPLAY_HEIGHT: usize = 160;
|
pub const DISPLAY_HEIGHT: usize = 160;
|
||||||
|
|
||||||
|
@ -167,8 +163,8 @@ impl Lcd {
|
||||||
|
|
||||||
pub const TILE_SIZE: u32 = 0x20;
|
pub const TILE_SIZE: u32 = 0x20;
|
||||||
|
|
||||||
pub fn new() -> Lcd {
|
pub fn new() -> Gpu {
|
||||||
Lcd {
|
Gpu {
|
||||||
state: HDraw,
|
state: HDraw,
|
||||||
current_scanline: 0,
|
current_scanline: 0,
|
||||||
cycles: 0,
|
cycles: 0,
|
||||||
|
@ -349,9 +345,9 @@ impl Lcd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// *TODO* Running the Lcd step by step causes a massive performance impact, so for now not treat it as an emulated IO device.
|
// *TODO* Running the Gpu step by step causes a massive performance impact, so for now not treat it as an emulated IO device.
|
||||||
|
|
||||||
impl EmuIoDev for Lcd {
|
impl EmuIoDev for Gpu {
|
||||||
fn step(&mut self, cycles: usize, sysbus: &mut SysBus) -> (usize, Option<Interrupt>) {
|
fn step(&mut self, cycles: usize, sysbus: &mut SysBus) -> (usize, Option<Interrupt>) {
|
||||||
self.cycles += cycles;
|
self.cycles += cycles;
|
||||||
|
|
||||||
|
@ -367,11 +363,11 @@ impl EmuIoDev for Lcd {
|
||||||
|
|
||||||
match self.state {
|
match self.state {
|
||||||
HDraw => {
|
HDraw => {
|
||||||
if self.cycles > Lcd::CYCLES_HDRAW {
|
if self.cycles > Gpu::CYCLES_HDRAW {
|
||||||
self.current_scanline += 1;
|
self.current_scanline += 1;
|
||||||
self.cycles -= Lcd::CYCLES_HDRAW;
|
self.cycles -= Gpu::CYCLES_HDRAW;
|
||||||
|
|
||||||
let (new_state, irq) = if self.current_scanline < Lcd::DISPLAY_HEIGHT {
|
let (new_state, irq) = if self.current_scanline < Gpu::DISPLAY_HEIGHT {
|
||||||
self.scanline(sysbus);
|
self.scanline(sysbus);
|
||||||
// HBlank
|
// HBlank
|
||||||
dispstat.hblank_flag = true;
|
dispstat.hblank_flag = true;
|
||||||
|
@ -396,8 +392,8 @@ impl EmuIoDev for Lcd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HBlank => {
|
HBlank => {
|
||||||
if self.cycles > Lcd::CYCLES_HBLANK {
|
if self.cycles > Gpu::CYCLES_HBLANK {
|
||||||
self.cycles -= Lcd::CYCLES_HBLANK;
|
self.cycles -= Gpu::CYCLES_HBLANK;
|
||||||
self.state = HDraw;
|
self.state = HDraw;
|
||||||
dispstat.hblank_flag = false;
|
dispstat.hblank_flag = false;
|
||||||
self.update_regs(dispstat, sysbus);
|
self.update_regs(dispstat, sysbus);
|
||||||
|
@ -405,8 +401,8 @@ impl EmuIoDev for Lcd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VBlank => {
|
VBlank => {
|
||||||
if self.cycles > Lcd::CYCLES_VBLANK {
|
if self.cycles > Gpu::CYCLES_VBLANK {
|
||||||
self.cycles -= Lcd::CYCLES_VBLANK;
|
self.cycles -= Gpu::CYCLES_VBLANK;
|
||||||
self.state = HDraw;
|
self.state = HDraw;
|
||||||
dispstat.vblank_flag = false;
|
dispstat.vblank_flag = false;
|
||||||
self.current_scanline = 0;
|
self.current_scanline = 0;
|
|
@ -15,6 +15,7 @@ extern crate ansi_term;
|
||||||
extern crate colored; // not needed in Rust 2018
|
extern crate colored; // not needed in Rust 2018
|
||||||
|
|
||||||
pub mod arm7tdmi;
|
pub mod arm7tdmi;
|
||||||
|
pub mod gpu;
|
||||||
pub mod cartridge;
|
pub mod cartridge;
|
||||||
pub mod debugger;
|
pub mod debugger;
|
||||||
pub mod disass;
|
pub mod disass;
|
||||||
|
@ -26,7 +27,6 @@ pub use interrupt::Interrupt;
|
||||||
pub mod gba;
|
pub mod gba;
|
||||||
pub use gba::GameBoyAdvance;
|
pub use gba::GameBoyAdvance;
|
||||||
pub mod dma;
|
pub mod dma;
|
||||||
pub mod lcd;
|
|
||||||
pub mod palette;
|
pub mod palette;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
|
|
Reference in a new issue