dont asplode stack

This commit is contained in:
Alex Janka 2023-10-26 15:45:01 +11:00
parent 5d61d4466a
commit e0e7634aec
2 changed files with 38 additions and 17 deletions

View file

@ -321,12 +321,16 @@ where
0x0..0xFF40 | 0xFF4C..=0xFFFF => unreachable!(), 0x0..0xFF40 | 0xFF4C..=0xFFFF => unreachable!(),
}, },
IoAddress::Cgb(address) => { IoAddress::Cgb(address) => {
if let WramBanks::Cgb { banks: _, selected } = &self.ram.banks && let Some(cgb_peripherals) = &self.cgb_peripherals { if let WramBanks::Cgb { banks: _, selected } = &self.ram.banks
&& let Some(cgb_peripherals) = &self.cgb_peripherals
{
match address { match address {
CgbIoAddress::CompatMode => self.gpu.get_compat_byte(), CgbIoAddress::CompatMode => self.gpu.get_compat_byte(),
CgbIoAddress::PrepareSpeed => cgb_peripherals.double_speed.get(), CgbIoAddress::PrepareSpeed => cgb_peripherals.double_speed.get(),
CgbIoAddress::VramBank => self.gpu.vram.get_vram_bank(), CgbIoAddress::VramBank => self.gpu.vram.get_vram_bank(),
CgbIoAddress::VramDma(address) => cgb_peripherals.vram_dma.get_register(address), CgbIoAddress::VramDma(address) => {
cgb_peripherals.vram_dma.get_register(address)
}
CgbIoAddress::Infrared => cgb_peripherals.infrared.get(), CgbIoAddress::Infrared => cgb_peripherals.infrared.get(),
CgbIoAddress::Palette(address) => self.gpu.get_cgb_palette(address), CgbIoAddress::Palette(address) => self.gpu.get_cgb_palette(address),
CgbIoAddress::ObjPriority => self.gpu.get_obj_priority(), CgbIoAddress::ObjPriority => self.gpu.get_obj_priority(),
@ -380,18 +384,22 @@ where
0x0..0xFF40 | 0xFF4C..=0xFFFF => unreachable!(), 0x0..0xFF40 | 0xFF4C..=0xFFFF => unreachable!(),
}, },
IoAddress::Cgb(address) => { IoAddress::Cgb(address) => {
if let WramBanks::Cgb { banks: _, selected } = &mut self.ram.banks && let Some(cgb_peripherals) = &mut self.cgb_peripherals { if let WramBanks::Cgb { banks: _, selected } = &mut self.ram.banks
&& let Some(cgb_peripherals) = &mut self.cgb_peripherals
{
match address { match address {
CgbIoAddress::CompatMode => self.gpu.set_compat_byte(data), CgbIoAddress::CompatMode => self.gpu.set_compat_byte(data),
CgbIoAddress::PrepareSpeed => cgb_peripherals.double_speed.set(data), CgbIoAddress::PrepareSpeed => cgb_peripherals.double_speed.set(data),
CgbIoAddress::VramBank => self.gpu.vram.set_vram_bank(data), CgbIoAddress::VramBank => self.gpu.vram.set_vram_bank(data),
CgbIoAddress::VramDma(address) => cgb_peripherals.vram_dma.set_register(address, data), CgbIoAddress::VramDma(address) => {
cgb_peripherals.vram_dma.set_register(address, data)
}
CgbIoAddress::Infrared => cgb_peripherals.infrared.set(data), CgbIoAddress::Infrared => cgb_peripherals.infrared.set(data),
CgbIoAddress::Palette(address) => self.gpu.set_cgb_palette(address, data), CgbIoAddress::Palette(address) => self.gpu.set_cgb_palette(address, data),
CgbIoAddress::ObjPriority => self.gpu.set_obj_priority(data), CgbIoAddress::ObjPriority => self.gpu.set_obj_priority(data),
CgbIoAddress::WramBank => *selected = (data & 0b111).max(1) as usize, CgbIoAddress::WramBank => *selected = (data & 0b111).max(1) as usize,
CgbIoAddress::Pcm12 => {}, CgbIoAddress::Pcm12 => {}
CgbIoAddress::Pcm34 => {}, CgbIoAddress::Pcm34 => {}
CgbIoAddress::Unused(v) => { CgbIoAddress::Unused(v) => {
eprintln!("attempt to set 0x{v:0>4X} to 0x{data:0>2X}") eprintln!("attempt to set 0x{v:0>4X} to 0x{data:0>2X}")
} }

View file

@ -25,11 +25,13 @@ mod types;
const TILE_WINDOW_WIDTH: usize = 16 * 8; const TILE_WINDOW_WIDTH: usize = 16 * 8;
const TILE_WINDOW_HEIGHT: usize = 24 * 8; const TILE_WINDOW_HEIGHT: usize = 24 * 8;
type Buffer<ColourFormat, const SIZE: usize> = Box<[ColourFormat; SIZE]>;
pub struct Gpu<ColourFormat> pub struct Gpu<ColourFormat>
where where
ColourFormat: From<Colour> + Copy, ColourFormat: From<Colour> + Copy,
{ {
pub buffer: [ColourFormat; WIDTH * HEIGHT], pub buffer: Buffer<ColourFormat, { WIDTH * HEIGHT }>,
pub vram: Vram, pub vram: Vram,
pub oam: Oam, pub oam: Oam,
pub window: Sender<RendererMessage<ColourFormat>>, pub window: Sender<RendererMessage<ColourFormat>>,
@ -43,7 +45,7 @@ where
tile_window: Option<TileWindow<ColourFormat>>, tile_window: Option<TileWindow<ColourFormat>>,
layer_window: Option<( layer_window: Option<(
Sender<RendererMessage<ColourFormat>>, Sender<RendererMessage<ColourFormat>>,
[ColourFormat; WIDTH * HEIGHT * 3], Buffer<ColourFormat, { WIDTH * HEIGHT * 3 }>,
)>, )>,
window_lc: u8, window_lc: u8,
has_window_been_enabled: bool, has_window_been_enabled: bool,
@ -71,7 +73,12 @@ where
let tile_window = tile_window_renderer let tile_window = tile_window_renderer
.map(|tile_window_renderer| TileWindow::new(tile_window_renderer, cgb)); .map(|tile_window_renderer| TileWindow::new(tile_window_renderer, cgb));
let buffer = [get_blank_colour(cgb); WIDTH * HEIGHT]; let buffer = {
let mut v: Vec<ColourFormat> = Vec::new();
v.resize(WIDTH * HEIGHT, get_blank_colour(cgb));
let temp = v.into_boxed_slice();
unsafe { Box::from_raw(Box::into_raw(temp) as *mut [ColourFormat; WIDTH * HEIGHT]) }
};
let layer_window = layer_window_renderer.map(|layer_window_renderer| { let layer_window = layer_window_renderer.map(|layer_window_renderer| {
layer_window_renderer layer_window_renderer
@ -80,10 +87,14 @@ where
height: HEIGHT * 3, height: HEIGHT * 3,
}) })
.expect("message error"); .expect("message error");
( (layer_window_renderer, {
layer_window_renderer, let mut v: Vec<ColourFormat> = Vec::new();
[get_blank_colour(cgb); WIDTH * HEIGHT * 3], v.resize(WIDTH * HEIGHT * 3, get_blank_colour(cgb));
) let temp = v.into_boxed_slice();
unsafe {
Box::from_raw(Box::into_raw(temp) as *mut [ColourFormat; WIDTH * HEIGHT * 3])
}
})
}); });
Self { Self {
@ -224,7 +235,9 @@ where
self.window_lc = 0; self.window_lc = 0;
self.has_window_been_enabled = false; self.has_window_been_enabled = false;
let is_cgb_mode = self.is_cgb_mode(); let is_cgb_mode = self.is_cgb_mode();
if let Some(tile_window) = &mut self.tile_window && output { if let Some(tile_window) = &mut self.tile_window
&& output
{
tile_window.draw_sprite_window(self.bg_palette, &self.vram, is_cgb_mode); tile_window.draw_sprite_window(self.bg_palette, &self.vram, is_cgb_mode);
} }
} }
@ -493,19 +506,19 @@ where
fn render_window(&mut self) { fn render_window(&mut self) {
let mut buffer = Vec::new(); let mut buffer = Vec::new();
buffer.extend_from_slice(&self.buffer); buffer.extend_from_slice(self.buffer.as_ref());
self.window self.window
.send(RendererMessage::display_message(buffer)) .send(RendererMessage::display_message(buffer))
.expect("message error"); .expect("message error");
if let Some((ref mut window, ref mut buffer)) = self.layer_window { if let Some((ref mut window, ref mut buffer)) = self.layer_window {
let mut new_buffer = Vec::new(); let mut new_buffer = Vec::new();
new_buffer.extend_from_slice(buffer); new_buffer.extend_from_slice(buffer.as_ref());
window window
.send(RendererMessage::display_message(new_buffer)) .send(RendererMessage::display_message(new_buffer))
.expect("message error"); .expect("message error");
for val in buffer { for val in buffer.iter_mut() {
*val = get_blank_colour(self.cgb_data.is_some()); *val = get_blank_colour(self.cgb_data.is_some());
} }
} }