gpu: refactor: Move Rgb15 to its own module

Former-commit-id: d83748802435594573255171ae888efd6f406ad3
This commit is contained in:
Michel Heily 2019-12-29 21:27:51 +02:00
parent 615515fcea
commit 118beeb4b7
6 changed files with 145 additions and 207 deletions

View file

@ -10,6 +10,8 @@ mod mosaic;
mod obj; mod obj;
use obj::ObjInfo; use obj::ObjInfo;
mod sfx; mod sfx;
mod rgb15;
pub use rgb15::Rgb15;
pub mod regs; pub mod regs;
pub use regs::*; pub use regs::*;
@ -28,41 +30,6 @@ const CYCLES_VBLANK: usize = 83776;
pub const TILE_SIZE: u32 = 0x20; pub const TILE_SIZE: u32 = 0x20;
// TODO - remove the one in palette.rs
bitfield! {
#[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
}
}
#[derive(Debug, Primitive, Copy, Clone)] #[derive(Debug, Primitive, Copy, Clone)]
pub enum PixelFormat { pub enum PixelFormat {

37
src/core/gpu/rgb15.rs Normal file
View file

@ -0,0 +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
}
}

View file

@ -12,7 +12,6 @@ pub mod gba;
pub use gba::GameBoyAdvance; pub use gba::GameBoyAdvance;
pub mod dma; pub mod dma;
pub mod keypad; pub mod keypad;
pub mod palette;
pub mod timer; pub mod timer;
use crate::debugger; use crate::debugger;

View file

@ -1,65 +0,0 @@
use std::fmt;
use byteorder::{LittleEndian, ReadBytesExt};
use std::io::Cursor;
#[derive(Debug, Copy, Clone, Default)]
pub struct Rgb15 {
pub r: u8,
pub g: u8,
pub b: u8,
}
impl From<u16> for Rgb15 {
fn from(v: u16) -> Rgb15 {
use bit::BitIndex;
Rgb15 {
r: v.bit_range(0..5) as u8,
g: v.bit_range(5..10) as u8,
b: v.bit_range(10..15) as u8,
}
}
}
impl fmt::Display for Rgb15 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Rgb15({:#x},{:#x},{:#x})", self.r, self.g, self.b)
}
}
impl Rgb15 {
/// Convert 15-bit high color to a 24-bit true color.
pub fn get_rgb24(&self) -> (u8, u8, u8) {
(self.r << 3, self.g << 3, self.b << 3)
}
}
#[derive(Debug, Primitive, Copy, Clone)]
pub enum PixelFormat {
BPP4 = 0,
BPP8 = 1,
}
pub struct Palette {
pub bg_colors: [Rgb15; 256],
pub fg_colors: [Rgb15; 256],
}
impl From<&[u8]> for Palette {
fn from(bytes: &[u8]) -> Palette {
let mut rdr = Cursor::new(bytes);
let mut bg_colors: [Rgb15; 256] = [0.into(); 256];
for i in 0..256 {
bg_colors[i] = rdr.read_u16::<LittleEndian>().unwrap().into();
}
let mut fg_colors: [Rgb15; 256] = [0.into(); 256];
for i in 0..256 {
fg_colors[i] = rdr.read_u16::<LittleEndian>().unwrap().into();
}
Palette {
bg_colors,
fg_colors,
}
}
}

View file

@ -10,7 +10,7 @@ use crate::core::GBAError;
use crate::disass::Disassembler; use crate::disass::Disassembler;
use crate::{AudioInterface, InputInterface, VideoInterface}; use crate::{AudioInterface, InputInterface, VideoInterface};
use super::palette_view::create_palette_view; // use super::palette_view::create_palette_view;
// use super::tile_view::create_tile_view; // use super::tile_view::create_tile_view;
use super::{parser::Value, Debugger, DebuggerError, DebuggerResult}; use super::{parser::Value, Debugger, DebuggerError, DebuggerResult};
@ -54,7 +54,7 @@ pub enum Command {
Disass(DisassMode, Addr, u32), Disass(DisassMode, Addr, u32),
AddBreakpoint(Addr), AddBreakpoint(Addr),
DelBreakpoint(Addr), DelBreakpoint(Addr),
PaletteView, // PaletteView,
// TileView(u32), // TileView(u32),
ClearBreakpoints, ClearBreakpoints,
ListBreakpoints, ListBreakpoints,
@ -170,7 +170,7 @@ impl Debugger {
println!("[{}] 0x{:08x}", i, b) println!("[{}] 0x{:08x}", i, b)
} }
} }
PaletteView => create_palette_view(&self.gba.sysbus.palette_ram.mem), // PaletteView => create_palette_view(&self.gba.sysbus.palette_ram.mem),
// TileView(bg) => create_tile_view(bg, &self.gba), // TileView(bg) => create_tile_view(bg, &self.gba),
Reset => { Reset => {
println!("resetting cpu..."); println!("resetting cpu...");
@ -413,7 +413,7 @@ impl Debugger {
"breakdel [addr]", "breakdel [addr]",
))), ))),
}, },
"palette-view" => Ok(Command::PaletteView), // "palette-view" => Ok(Command::PaletteView),
// "tiles" => { // "tiles" => {
// if args.len() != 1 { // if args.len() != 1 {
// return Err(DebuggerError::InvalidCommandFormat("tile <bg>".to_string())); // return Err(DebuggerError::InvalidCommandFormat("tile <bg>".to_string()));

View file

@ -1,120 +1,120 @@
use sdl2::event::Event; // use sdl2::event::Event;
use sdl2::pixels::Color; // use sdl2::pixels::Color;
use sdl2::rect::{Point, Rect}; // use sdl2::rect::{Point, Rect};
use sdl2::render::Canvas; // use sdl2::render::Canvas;
use crate::core::palette::{Palette, Rgb15}; // use crate::core::palette::{Palette, Rgb15};
const PALETTE_RECT_WIDTH: u32 = 20; // const PALETTE_RECT_WIDTH: u32 = 20;
const SCREEN_WIDTH: u32 = 900; // const SCREEN_WIDTH: u32 = 900;
const SCREEN_HEIGHT: u32 = 500; // const SCREEN_HEIGHT: u32 = 500;
struct ColoredRect { // struct ColoredRect {
index: usize, // index: usize,
rect: Rect, // rect: Rect,
color: Rgb15, // color: Rgb15,
} // }
impl ColoredRect { // impl ColoredRect {
fn new(index: usize, x: i32, y: i32, c: Rgb15) -> ColoredRect { // fn new(index: usize, x: i32, y: i32, c: Rgb15) -> ColoredRect {
ColoredRect { // ColoredRect {
index: index, // index: index,
rect: Rect::new(x, y, PALETTE_RECT_WIDTH, PALETTE_RECT_WIDTH), // rect: Rect::new(x, y, PALETTE_RECT_WIDTH, PALETTE_RECT_WIDTH),
color: c, // color: c,
} // }
} // }
fn draw(&self, canvas: &mut Canvas<sdl2::video::Window>) { // fn draw(&self, canvas: &mut Canvas<sdl2::video::Window>) {
canvas.set_draw_color(Color::RGB(0, 0, 0)); // canvas.set_draw_color(Color::RGB(0, 0, 0));
canvas // canvas
.fill_rect(Rect::new( // .fill_rect(Rect::new(
self.rect.x() - 1, // self.rect.x() - 1,
self.rect.y() - 1, // self.rect.y() - 1,
PALETTE_RECT_WIDTH + 2, // PALETTE_RECT_WIDTH + 2,
PALETTE_RECT_WIDTH + 2, // PALETTE_RECT_WIDTH + 2,
)) // ))
.unwrap(); // .unwrap();
let (r, g, b) = self.color.get_rgb24(); // let (r, g, b) = self.color.get_rgb24();
canvas.set_draw_color(Color::RGB(r, g, b)); // canvas.set_draw_color(Color::RGB(r, g, b));
canvas.fill_rect(self.rect).unwrap(); // canvas.fill_rect(self.rect).unwrap();
} // }
} // }
pub fn create_palette_view(palette_ram: &[u8]) { // pub fn create_palette_view(palette_ram: &[u8]) {
let palette = Palette::from(palette_ram); // let palette = Palette::from(palette_ram);
let sdl_context = sdl2::init().unwrap(); // let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap(); // let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem // let window = video_subsystem
.window("PaletteView", SCREEN_WIDTH, SCREEN_HEIGHT) // .window("PaletteView", SCREEN_WIDTH, SCREEN_HEIGHT)
.position_centered() // .position_centered()
.build() // .build()
.unwrap(); // .unwrap();
let mut canvas = window.into_canvas().build().unwrap(); // let mut canvas = window.into_canvas().build().unwrap();
canvas.set_draw_color(Color::RGB(0xfa, 0xfa, 0xfa)); // canvas.set_draw_color(Color::RGB(0xfa, 0xfa, 0xfa));
canvas.clear(); // canvas.clear();
let mut bg_colors: Vec<ColoredRect> = Vec::with_capacity(256); // let mut bg_colors: Vec<ColoredRect> = Vec::with_capacity(256);
let mut fg_colors: Vec<ColoredRect> = Vec::with_capacity(256); // let mut fg_colors: Vec<ColoredRect> = Vec::with_capacity(256);
let initial_x = 30u32; // let initial_x = 30u32;
let mut y = 20u32; // let mut y = 20u32;
let mut x = initial_x; // let mut x = initial_x;
for i in 0..256 { // for i in 0..256 {
bg_colors.push(ColoredRect::new( // bg_colors.push(ColoredRect::new(
i, // i,
x as i32, // x as i32,
y as i32, // y as i32,
palette.bg_colors[i], // palette.bg_colors[i],
)); // ));
fg_colors.push(ColoredRect::new( // fg_colors.push(ColoredRect::new(
i, // i,
x as i32 + 450, // x as i32 + 450,
y as i32, // y as i32,
palette.fg_colors[i], // palette.fg_colors[i],
)); // ));
x = if (i + 1) % 16 == 0 { // x = if (i + 1) % 16 == 0 {
y += 24; // y += 24;
initial_x // initial_x
} else { // } else {
x + PALETTE_RECT_WIDTH + 4 // x + PALETTE_RECT_WIDTH + 4
} // }
} // }
for bgc in &bg_colors { // for bgc in &bg_colors {
bgc.draw(&mut canvas); // bgc.draw(&mut canvas);
} // }
for fgc in &fg_colors { // for fgc in &fg_colors {
fgc.draw(&mut canvas); // fgc.draw(&mut canvas);
} // }
canvas.present(); // canvas.present();
let mut event_pump = sdl_context.event_pump().unwrap(); // let mut event_pump = sdl_context.event_pump().unwrap();
'running: loop { // 'running: loop {
for event in event_pump.poll_iter() { // for event in event_pump.poll_iter() {
match event { // match event {
Event::Quit { .. } => break 'running, // Event::Quit { .. } => break 'running,
Event::MouseButtonDown { x, y, .. } => { // Event::MouseButtonDown { x, y, .. } => {
for bgc in &bg_colors { // for bgc in &bg_colors {
if bgc.rect.contains_point(Point::new(x, y)) { // if bgc.rect.contains_point(Point::new(x, y)) {
println!("BG Color #{}: {}", bgc.index, bgc.color); // println!("BG Color #{}: {}", bgc.index, bgc.color);
} // }
} // }
for fgc in &fg_colors { // for fgc in &fg_colors {
if fgc.rect.contains_point(Point::new(x, y)) { // if fgc.rect.contains_point(Point::new(x, y)) {
println!("FG Color #{}: {}", fgc.index, fgc.color); // println!("FG Color #{}: {}", fgc.index, fgc.color);
} // }
} // }
} // }
_ => {} // _ => {}
} // }
} // }
} // }
} // }