Implement MODE4 rendering, ArmWrestler renders now!

Former-commit-id: 4910a63b454ae9309abc0aa584a7d0bc96143538
This commit is contained in:
Michel Heily 2019-07-15 20:49:47 +03:00
parent 1084be52b8
commit 876cdfdcb3
3 changed files with 84 additions and 39 deletions

View file

@ -1,3 +1,5 @@
use std::time::Duration;
use sdl2::event::Event; use sdl2::event::Event;
use sdl2::pixels::Color; use sdl2::pixels::Color;
use sdl2::rect::Point; use sdl2::rect::Point;
@ -20,21 +22,6 @@ pub fn create_render_view(gba: &GameBoyAdvance) {
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.clear();
for y in 0..Lcd::DISPLAY_HEIGHT {
for x in 0..Lcd::DISPLAY_WIDTH {
let index = (x as usize) + (y as usize) * (256 as usize);
let color = gba.lcd.pixeldata[index];
let rgb24: Color = color.into();
canvas.set_draw_color(rgb24);
canvas.draw_point(Point::from((x as i32, y as i32)));
}
}
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() {
@ -46,5 +33,22 @@ pub fn create_render_view(gba: &GameBoyAdvance) {
_ => {} _ => {}
} }
} }
canvas.set_draw_color(Color::RGB(0xfa, 0xfa, 0xfa));
canvas.clear();
for y in 0..Lcd::DISPLAY_HEIGHT {
for x in 0..Lcd::DISPLAY_WIDTH {
let index = (x as usize) + (y as usize) * (256 as usize);
let color = gba.lcd.pixeldata[index];
let rgb24: Color = color.into();
canvas.set_draw_color(rgb24);
canvas.draw_point(Point::from((x as i32, y as i32)));
}
}
canvas.present();
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
} }
} }

View file

@ -1,3 +1,5 @@
use std::time::Duration;
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};
@ -48,6 +50,9 @@ fn draw_tile(
} }
} }
const TILESET_INITIAL_X: i32 = 0x20;
const TILESET_INITIAL_Y: i32 = 0x20;
pub fn create_tile_view(bg: u32, gba: &GameBoyAdvance) { pub fn create_tile_view(bg: u32, gba: &GameBoyAdvance) {
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();
@ -60,9 +65,6 @@ pub fn create_tile_view(bg: u32, gba: &GameBoyAdvance) {
let mut canvas = window.into_canvas().build().unwrap(); let mut canvas = window.into_canvas().build().unwrap();
canvas.set_draw_color(Color::RGB(00, 00, 00));
canvas.clear();
let bgcnt = BgControl::from(gba.sysbus.ioregs.read_reg(REG_BG0CNT + 2 * bg)); let bgcnt = BgControl::from(gba.sysbus.ioregs.read_reg(REG_BG0CNT + 2 * bg));
let palette = Palette::from(gba.sysbus.get_bytes(0x0500_0000)); let palette = Palette::from(gba.sysbus.get_bytes(0x0500_0000));
@ -73,33 +75,53 @@ pub fn create_tile_view(bg: u32, gba: &GameBoyAdvance) {
let num_tiles = 0x4000 / tile_size; let num_tiles = 0x4000 / tile_size;
println!("tileset: {:#x}, tilemap: {:#x}", tileset_addr, tilemap_addr); println!("tileset: {:#x}, tilemap: {:#x}", tileset_addr, tilemap_addr);
let mut tile_x = 0x20;
let mut tile_y = 0x20;
for t in 0..num_tiles {
let tile_addr = tileset_addr + t * tile_size;
if t != 0 && t % tiles_per_row == 0 {
tile_y += 10;
tile_x = 0x20;
}
tile_x += 10;
draw_tile(
gba,
tile_addr,
pixel_format,
Point::from((tile_x, tile_y)),
&mut canvas,
);
}
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, .. } => {
let click_point = Point::new(x, y);
let mut tile_x = TILESET_INITIAL_X;
let mut tile_y = TILESET_INITIAL_Y;
for t in 0..num_tiles {
let tile_addr = tileset_addr + t * tile_size;
if t != 0 && t % tiles_per_row == 0 {
tile_y += 10;
tile_x = TILESET_INITIAL_Y;
}
tile_x += 10;
if Rect::new(tile_x, tile_y, 8, 8).contains_point(click_point) {
println!("tile #{:#x}, addr={:#x}", t, tile_addr);
}
}
}
_ => {} _ => {}
} }
} }
canvas.set_draw_color(Color::RGB(00, 00, 00));
canvas.clear();
let mut tile_x = TILESET_INITIAL_X;
let mut tile_y = TILESET_INITIAL_Y;
for t in 0..num_tiles {
let tile_addr = tileset_addr + t * tile_size;
if t != 0 && t % tiles_per_row == 0 {
tile_y += 10;
tile_x = TILESET_INITIAL_Y;
}
tile_x += 10;
draw_tile(
gba,
tile_addr,
pixel_format,
Point::from((tile_x, tile_y)),
&mut canvas,
);
}
canvas.present();
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
} }
} }

View file

@ -313,9 +313,25 @@ impl Lcd {
} }
} }
fn scanline_mode4(&mut self, bg: u32, dispcnt: &DisplayControl, sysbus: &mut SysBus) {
let page: u32 = match dispcnt.display_frame {
0 => 0x0600_0000,
1 => 0x0600_a000,
_ => unreachable!()
};
let y = self.current_scanline;
for x in 0..Self::DISPLAY_WIDTH {
let bitmap_index = x + y * Self::DISPLAY_WIDTH;
let bitmap_addr = page + (bitmap_index as u32);
let index = sysbus.read_8(bitmap_addr as Addr) as u32;
self.pixeldata[x + y * 256] = self.get_palette_color(sysbus, index, 0);
}
}
pub fn scanline(&mut self, sysbus: &mut SysBus) { pub fn scanline(&mut self, sysbus: &mut SysBus) {
let dispcnt = DisplayControl::from(sysbus.ioregs.read_reg(REG_DISPCNT)); let dispcnt = DisplayControl::from(sysbus.ioregs.read_reg(REG_DISPCNT));
let dispstat = DisplayStatus::from(sysbus.ioregs.read_reg(REG_DISPSTAT));
match dispcnt.bg_mode { match dispcnt.bg_mode {
BGMode::BGMode0 | BGMode::BGMode2 => { BGMode::BGMode0 | BGMode::BGMode2 => {
@ -325,6 +341,9 @@ impl Lcd {
} }
} }
} }
BGMode::BGMode4 => {
self.scanline_mode4(2, &dispcnt, sysbus);
}
_ => panic!("{:?} not supported", dispcnt.bg_mode), _ => panic!("{:?} not supported", dispcnt.bg_mode),
} }
} }