From a73161614656eff0ff692027bf4893c0ec5fdeff Mon Sep 17 00:00:00 2001 From: Reid 'arrdem' McKenzie Date: Mon, 2 Jan 2023 00:46:19 -0700 Subject: [PATCH] Pixel write --- src/device/video_sdl2.rs | 105 +++++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 22 deletions(-) diff --git a/src/device/video_sdl2.rs b/src/device/video_sdl2.rs index c659213..6da48a8 100644 --- a/src/device/video_sdl2.rs +++ b/src/device/video_sdl2.rs @@ -1,3 +1,5 @@ +use std::{cell::RefCell, rc::Rc}; + use crate::{ device::{Device, DeviceError}, vm::Uxn, @@ -26,13 +28,14 @@ pub struct Sdl2VideoDevice { pixels: Vec, width: u16, height: u16, - fg: Layer, - bg: Layer, - mono: u8, + fg: Rc>, + bg: Rc>, + mono: bool, x_cur: u16, // x8, x9 y_cur: u16, // xa, xb - auto: bool, // x6 + auto_x: bool, // x6 + auto_y: bool, // x6 sprite_addr: u16, // xc, xd } @@ -42,10 +45,17 @@ impl Sdl2VideoDevice { } fn clear(&mut self) { - for i in 0..(self.width * self.height) as usize { - // FIXME: Is there some clear/set operation on vector? You can write your own seemingly, but it's this loop. - self.fg.pixels[i] = 0x00; - self.bg.pixels[i] = 0x00; + { + let fg = self.fg.borrow_mut(); + for i in 0..(self.width * self.height) as usize { + fg.pixels[i] = 0x00; + } + } + { + let bg = self.bg.borrow_mut(); + for i in 0..(self.width * self.height) as usize { + bg.pixels[i] = 0x00; + } } } @@ -53,7 +63,11 @@ impl Sdl2VideoDevice { * Update an entry in either the foreground or background buffers, marking the buffer as dirty. */ fn write_pixel(&mut self, layer: bool, x: u16, y: u16, color: u8) { - let layer = if layer { &mut self.fg } else { &mut self.bg }; + let layer = if layer { + self.fg.borrow_mut() + } else { + self.bg.borrow_mut() + }; if x < self.width && y < self.height { let idx = (x + (y * self.height)) as usize; if color != layer.pixels[idx] { @@ -121,8 +135,8 @@ impl Sdl2VideoDevice { } // Both layers are now dirty - self.fg.changed |= true; - self.bg.changed |= true; + self.fg.borrow_mut().changed |= true; + self.bg.borrow_mut().changed |= true; } fn redraw(&mut self) { @@ -132,22 +146,36 @@ impl Sdl2VideoDevice { let idx = if (i >> 2) != 0 { i >> 2 } else { i & 3 }; palette[i] = self.palette[idx]; } - if self.mono != 0 { + if self.mono { for i in 0..size as usize { - let idx = (if self.fg.pixels[i] != 0 { - self.fg.pixels[i] + let idx = (if self.fg.borrow().pixels[i] != 0 { + self.fg.borrow().pixels[i] } else { - self.bg.pixels[i] + self.bg.borrow().pixels[i] }) & 0x1; self.pixels[i] = PALETTE_MONO[idx as usize]; } } else { for i in 0..size as usize { - self.pixels[i] = palette[(self.fg.pixels[i] << 2 | self.bg.pixels[i]) as usize]; + self.pixels[i] = palette + [(self.fg.borrow().pixels[i] << 2 | self.bg.borrow().pixels[i]) as usize]; } } - self.fg.changed = false; - self.bg.changed = false; + self.fg.borrow_mut().changed = false; + self.bg.borrow_mut().changed = false; + } + + fn resize(&mut self) { + () + } + + fn auto_increment(&mut self, d: u8) { + if self.auto_x { + self.x_cur += d as u16; + } + if self.auto_y { + self.y_cur += d as u16; + } } } @@ -158,10 +186,21 @@ impl Device for Sdl2VideoDevice { match slot { 0x0 => Ok((self.vector >> 8) as u8), 0x1 => Ok((self.vector & 0xFF) as u8), + 0x2 => Ok((self.width >> 8) as u8), 0x3 => Ok((self.width & 0xFF) as u8), + 0x4 => Ok((self.height >> 8) as u8), 0x5 => Ok((self.height & 0xFF) as u8), + + 0x6 => Ok((if self.auto_y { 1 } else { 0 }) << 1 | (if self.auto_x { 1 } else { 0 })), + + 0x8 => Ok((self.x_cur >> 8) as u8), + 0x9 => Ok((self.x_cur & 0xFF) as u8), + + 0xa => Ok((self.y_cur >> 8) as u8), + 0xb => Ok((self.y_cur & 0xFF) as u8), + _ => Ok(0), } } @@ -177,18 +216,40 @@ impl Device for Sdl2VideoDevice { 0x1 => self.vector = self.vector & 0xFF00 | (val as u16), // Writing to the device width port. // Note that the reference implementation triggers resizing on the lower byte - 0x2 | 0x3 => (), + 0x2 => self.width = self.width & 0x00FF | ((val as u16) << 8), + 0x3 => { + self.width = self.width & 0xFF00 | (val as u16); + self.resize(); + } // Writing to the device height port // Note that the reference implementation triggers resizing on the lower byte - 0x4 | 0x5 => (), + 0x4 => self.height = self.height & 0x00FF | ((val as u16) << 8), + 0x5 => { + self.height = self.height & 0xFF00 | (val as u16); + self.resize(); + } // FIXME: Writing to all the settings words (auto, x, y, addr) + // Write the auto word + 0x6 => { + self.auto_x = val & 0x1 != 0; + self.auto_y = val & 0x2 != 0; + } + // Write a pixel word - 0xe => (), + 0xe => { + let layer = val & 0x40 != 0; + self.write_pixel(layer, self.x_cur, self.y_cur, val & 0x3); + self.auto_increment(1); + } // Write a sprite word - 0xf => (), + 0xf => { + let layer = val & 0x40 != 0; + let n = val & 0xF >> 4; + self.auto_increment(8); // sprites are always 8x8, although we may do many at once. + } _ => (), }