tile window draws all tiles + is optional
This commit is contained in:
parent
3b2a07c264
commit
0a75b58732
10
src/main.rs
10
src/main.rs
|
@ -57,6 +57,10 @@ struct Args {
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
cycle_count: bool,
|
cycle_count: bool,
|
||||||
|
|
||||||
|
/// Show tile window
|
||||||
|
#[arg(short, long)]
|
||||||
|
tile_window: bool,
|
||||||
|
|
||||||
/// Step emulation by...
|
/// Step emulation by...
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
step_by: Option<usize>,
|
step_by: Option<usize>,
|
||||||
|
@ -117,7 +121,11 @@ fn main() {
|
||||||
|
|
||||||
window.topmost(true);
|
window.topmost(true);
|
||||||
|
|
||||||
let mut cpu = CPU::new(Memory::init(bootrom, args.run_bootrom, rom), window);
|
let mut cpu = CPU::new(
|
||||||
|
Memory::init(bootrom, args.run_bootrom, rom),
|
||||||
|
window,
|
||||||
|
args.tile_window,
|
||||||
|
);
|
||||||
|
|
||||||
if !args.run_bootrom {
|
if !args.run_bootrom {
|
||||||
cpu.reg.pc = 0x0100;
|
cpu.reg.pc = 0x0100;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use self::tile_window::TileWindow;
|
||||||
use crate::{
|
use crate::{
|
||||||
processor::{as_signed, get_bit, set_bit, set_or_clear_bit, CPU},
|
processor::{as_signed, get_bit, set_bit, set_or_clear_bit, CPU},
|
||||||
FACTOR, HEIGHT, WIDTH,
|
FACTOR, HEIGHT, WIDTH,
|
||||||
|
@ -117,8 +118,10 @@ struct Object {
|
||||||
flags: ObjectFlags,
|
flags: ObjectFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
const TILE_WINDOW_EDGE_LENGTH: usize = 16 * 8;
|
const TILE_WINDOW_WIDTH: usize = 16 * 8;
|
||||||
const TILE_WINDOW_EDGE_LENGTH_SCALED: usize = TILE_WINDOW_EDGE_LENGTH * FACTOR;
|
const TILE_WINDOW_HEIGHT: usize = 24 * 8;
|
||||||
|
const TILE_WINDOW_WIDTH_SCALED: usize = TILE_WINDOW_WIDTH * FACTOR;
|
||||||
|
const TILE_WINDOW_HEIGHT_SCALED: usize = TILE_WINDOW_HEIGHT * FACTOR;
|
||||||
|
|
||||||
pub struct GPU {
|
pub struct GPU {
|
||||||
pub buffer: Vec<u32>,
|
pub buffer: Vec<u32>,
|
||||||
|
@ -126,39 +129,36 @@ pub struct GPU {
|
||||||
mode: DrawMode,
|
mode: DrawMode,
|
||||||
mode_clock: usize,
|
mode_clock: usize,
|
||||||
scanline: u8,
|
scanline: u8,
|
||||||
sprite_buffer: Vec<u32>,
|
tile_window: Option<TileWindow>,
|
||||||
sprite_buffer_scaled: Vec<u32>,
|
|
||||||
sprite_window: Window,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GPU {
|
impl GPU {
|
||||||
fn default() -> Self {
|
pub(super) fn new(enable_tile_window: bool) -> Self {
|
||||||
let mut window = Window::new(
|
let tile_window = if enable_tile_window {
|
||||||
"Tiles",
|
let mut window = Window::new(
|
||||||
TILE_WINDOW_EDGE_LENGTH_SCALED,
|
"Tiles",
|
||||||
TILE_WINDOW_EDGE_LENGTH_SCALED,
|
TILE_WINDOW_WIDTH_SCALED,
|
||||||
WindowOptions::default(),
|
TILE_WINDOW_HEIGHT_SCALED,
|
||||||
)
|
WindowOptions::default(),
|
||||||
.unwrap_or_else(|e| {
|
)
|
||||||
panic!("{}", e);
|
.unwrap_or_else(|e| {
|
||||||
});
|
panic!("{}", e);
|
||||||
|
});
|
||||||
|
|
||||||
window.set_position((550 + (WIDTH * FACTOR)) as isize, 50);
|
window.set_position((550 + (WIDTH * FACTOR)) as isize, 50);
|
||||||
|
window.topmost(true);
|
||||||
|
Some(TileWindow::new(window))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
window.topmost(true);
|
|
||||||
Self {
|
Self {
|
||||||
buffer: vec![0; WIDTH * HEIGHT],
|
buffer: vec![0; WIDTH * HEIGHT],
|
||||||
scaled_buffer: vec![0; WIDTH * HEIGHT * 4],
|
scaled_buffer: vec![0; WIDTH * HEIGHT * 4],
|
||||||
mode: DrawMode::Mode2,
|
mode: DrawMode::Mode2,
|
||||||
mode_clock: 0,
|
mode_clock: 0,
|
||||||
scanline: 0,
|
scanline: 0,
|
||||||
sprite_buffer: vec![0; TILE_WINDOW_EDGE_LENGTH * TILE_WINDOW_EDGE_LENGTH],
|
tile_window,
|
||||||
sprite_buffer_scaled: vec![
|
|
||||||
0;
|
|
||||||
TILE_WINDOW_EDGE_LENGTH_SCALED
|
|
||||||
* TILE_WINDOW_EDGE_LENGTH_SCALED
|
|
||||||
],
|
|
||||||
sprite_window: window,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,10 +259,9 @@ impl CPU {
|
||||||
fn exit_vblank(&mut self) {
|
fn exit_vblank(&mut self) {
|
||||||
self.gpu.mode = DrawMode::Mode2;
|
self.gpu.mode = DrawMode::Mode2;
|
||||||
self.gpu.scanline = 0;
|
self.gpu.scanline = 0;
|
||||||
self.draw_sprite_window(
|
if let Some(tile_window) = &mut self.gpu.tile_window {
|
||||||
TiledataArea::D8000,
|
tile_window.draw_sprite_window(byte_to_palette(self.memory.get(0xFF47)), &self.memory);
|
||||||
byte_to_palette(self.memory.get(0xFF47)),
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_lcd_status(&mut self) {
|
fn set_lcd_status(&mut self) {
|
||||||
|
|
|
@ -1,51 +1,94 @@
|
||||||
|
use minifb::Window;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
processor::{
|
processor::{
|
||||||
get_bit,
|
get_bit,
|
||||||
gpu::{
|
gpu::{
|
||||||
bits_to_mapped_colour, scale_buffer, Palette, TiledataArea, TILE_WINDOW_EDGE_LENGTH,
|
bits_to_mapped_colour, scale_buffer, Palette, TiledataArea, TILE_WINDOW_HEIGHT,
|
||||||
TILE_WINDOW_EDGE_LENGTH_SCALED,
|
TILE_WINDOW_HEIGHT_SCALED, TILE_WINDOW_WIDTH, TILE_WINDOW_WIDTH_SCALED,
|
||||||
},
|
},
|
||||||
CPU,
|
memory::Memory,
|
||||||
},
|
},
|
||||||
FACTOR,
|
FACTOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl CPU {
|
pub(super) struct TileWindow {
|
||||||
pub(super) fn draw_sprite_window(&mut self, area: TiledataArea, palette: Palette) {
|
sprite_buffer: Vec<u32>,
|
||||||
for tile_y in 0..16 {
|
sprite_buffer_scaled: Vec<u32>,
|
||||||
for tile_x in 0..16 {
|
sprite_window: Window,
|
||||||
let tile_num = (tile_y * 16) + tile_x;
|
}
|
||||||
let data_begin = area.get_addr(tile_num);
|
|
||||||
for px_y in 0..8 {
|
|
||||||
let lsbs = self.memory.get((px_y * 2) + data_begin);
|
|
||||||
let msbs = self.memory.get((px_y * 2) + data_begin + 1);
|
|
||||||
for px_x in 0..8 {
|
|
||||||
let real_px_y = (tile_y as usize * 8) + px_y as usize;
|
|
||||||
let real_px_x = (tile_x as usize * 8) + px_x as usize;
|
|
||||||
let lsb = get_bit(lsbs, 7 - px_x);
|
|
||||||
let msb = get_bit(msbs, 7 - px_x);
|
|
||||||
let colour = bits_to_mapped_colour(lsb, msb, palette);
|
|
||||||
|
|
||||||
self.gpu.sprite_buffer[real_px_x + (real_px_y * TILE_WINDOW_EDGE_LENGTH)] =
|
impl TileWindow {
|
||||||
colour.to_rgb();
|
pub(super) fn new(window: Window) -> Self {
|
||||||
}
|
Self {
|
||||||
}
|
sprite_buffer: vec![0; TILE_WINDOW_WIDTH * TILE_WINDOW_HEIGHT],
|
||||||
}
|
sprite_buffer_scaled: vec![0; TILE_WINDOW_WIDTH_SCALED * TILE_WINDOW_HEIGHT_SCALED],
|
||||||
|
sprite_window: window,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TileWindow {
|
||||||
|
pub(super) fn draw_sprite_window(&mut self, palette: Palette, memory: &Memory) {
|
||||||
|
for tile_y in 0..16 {
|
||||||
|
self.draw_row(
|
||||||
|
tile_y,
|
||||||
|
tile_y as usize,
|
||||||
|
TiledataArea::D8000,
|
||||||
|
palette,
|
||||||
|
memory,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for tile_y in 0..8 {
|
||||||
|
self.draw_row(
|
||||||
|
tile_y,
|
||||||
|
(tile_y as usize) + 16,
|
||||||
|
TiledataArea::D9000,
|
||||||
|
palette,
|
||||||
|
memory,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.gpu.sprite_buffer_scaled = scale_buffer(
|
self.sprite_buffer_scaled = scale_buffer(
|
||||||
&self.gpu.sprite_buffer,
|
&self.sprite_buffer,
|
||||||
TILE_WINDOW_EDGE_LENGTH,
|
TILE_WINDOW_WIDTH,
|
||||||
TILE_WINDOW_EDGE_LENGTH,
|
TILE_WINDOW_HEIGHT,
|
||||||
FACTOR,
|
FACTOR,
|
||||||
);
|
);
|
||||||
self.gpu
|
self.sprite_window
|
||||||
.sprite_window
|
|
||||||
.update_with_buffer(
|
.update_with_buffer(
|
||||||
&self.gpu.sprite_buffer_scaled,
|
&self.sprite_buffer_scaled,
|
||||||
TILE_WINDOW_EDGE_LENGTH_SCALED,
|
TILE_WINDOW_WIDTH_SCALED,
|
||||||
TILE_WINDOW_EDGE_LENGTH_SCALED,
|
TILE_WINDOW_HEIGHT_SCALED,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_row(
|
||||||
|
&mut self,
|
||||||
|
tile_y: u8,
|
||||||
|
display_y: usize,
|
||||||
|
area: TiledataArea,
|
||||||
|
palette: Palette,
|
||||||
|
memory: &Memory,
|
||||||
|
) {
|
||||||
|
for tile_x in 0..16 {
|
||||||
|
let tile_num = (tile_y * 16) + tile_x;
|
||||||
|
let data_begin = area.get_addr(tile_num);
|
||||||
|
for px_y in 0..8 {
|
||||||
|
let lsbs = memory.get((px_y * 2) + data_begin);
|
||||||
|
let msbs = memory.get((px_y * 2) + data_begin + 1);
|
||||||
|
for px_x in 0..8 {
|
||||||
|
let real_px_y = (display_y * 8) + px_y as usize;
|
||||||
|
let real_px_x = (tile_x as usize * 8) + px_x as usize;
|
||||||
|
let lsb = get_bit(lsbs, 7 - px_x);
|
||||||
|
let msb = get_bit(msbs, 7 - px_x);
|
||||||
|
let colour = bits_to_mapped_colour(lsb, msb, palette);
|
||||||
|
|
||||||
|
self.sprite_buffer[real_px_x + (real_px_y * TILE_WINDOW_WIDTH)] =
|
||||||
|
colour.to_rgb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,14 +38,14 @@ const SPEEDUP: f64 = 1.;
|
||||||
const FF04_SPEED: f64 = 16384.;
|
const FF04_SPEED: f64 = 16384.;
|
||||||
|
|
||||||
impl CPU {
|
impl CPU {
|
||||||
pub fn new(memory: Memory, window: Window) -> Self {
|
pub fn new(memory: Memory, window: Window, enable_tile_window: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
memory,
|
memory,
|
||||||
reg: Registers::default(),
|
reg: Registers::default(),
|
||||||
last_instruction: 0x0,
|
last_instruction: 0x0,
|
||||||
last_instruction_addr: 0x0,
|
last_instruction_addr: 0x0,
|
||||||
window,
|
window,
|
||||||
gpu: GPU::default(),
|
gpu: GPU::new(enable_tile_window),
|
||||||
halted: false,
|
halted: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue