Pixel write

This commit is contained in:
Reid 'arrdem' McKenzie 2023-01-02 00:46:19 -07:00
parent 7bd08d65de
commit a731616146

View file

@ -1,3 +1,5 @@
use std::{cell::RefCell, rc::Rc};
use crate::{ use crate::{
device::{Device, DeviceError}, device::{Device, DeviceError},
vm::Uxn, vm::Uxn,
@ -26,13 +28,14 @@ pub struct Sdl2VideoDevice {
pixels: Vec<u32>, pixels: Vec<u32>,
width: u16, width: u16,
height: u16, height: u16,
fg: Layer, fg: Rc<RefCell<Layer>>,
bg: Layer, bg: Rc<RefCell<Layer>>,
mono: u8, mono: bool,
x_cur: u16, // x8, x9 x_cur: u16, // x8, x9
y_cur: u16, // xa, xb y_cur: u16, // xa, xb
auto: bool, // x6 auto_x: bool, // x6
auto_y: bool, // x6
sprite_addr: u16, // xc, xd sprite_addr: u16, // xc, xd
} }
@ -42,10 +45,17 @@ impl Sdl2VideoDevice {
} }
fn clear(&mut self) { fn clear(&mut self) {
{
let fg = self.fg.borrow_mut();
for i in 0..(self.width * self.height) as usize { 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. fg.pixels[i] = 0x00;
self.fg.pixels[i] = 0x00; }
self.bg.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. * 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) { 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 { if x < self.width && y < self.height {
let idx = (x + (y * self.height)) as usize; let idx = (x + (y * self.height)) as usize;
if color != layer.pixels[idx] { if color != layer.pixels[idx] {
@ -121,8 +135,8 @@ impl Sdl2VideoDevice {
} }
// Both layers are now dirty // Both layers are now dirty
self.fg.changed |= true; self.fg.borrow_mut().changed |= true;
self.bg.changed |= true; self.bg.borrow_mut().changed |= true;
} }
fn redraw(&mut self) { fn redraw(&mut self) {
@ -132,22 +146,36 @@ impl Sdl2VideoDevice {
let idx = if (i >> 2) != 0 { i >> 2 } else { i & 3 }; let idx = if (i >> 2) != 0 { i >> 2 } else { i & 3 };
palette[i] = self.palette[idx]; palette[i] = self.palette[idx];
} }
if self.mono != 0 { if self.mono {
for i in 0..size as usize { for i in 0..size as usize {
let idx = (if self.fg.pixels[i] != 0 { let idx = (if self.fg.borrow().pixels[i] != 0 {
self.fg.pixels[i] self.fg.borrow().pixels[i]
} else { } else {
self.bg.pixels[i] self.bg.borrow().pixels[i]
}) & 0x1; }) & 0x1;
self.pixels[i] = PALETTE_MONO[idx as usize]; self.pixels[i] = PALETTE_MONO[idx as usize];
} }
} else { } else {
for i in 0..size as usize { 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.fg.borrow_mut().changed = false;
self.bg.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 { match slot {
0x0 => Ok((self.vector >> 8) as u8), 0x0 => Ok((self.vector >> 8) as u8),
0x1 => Ok((self.vector & 0xFF) as u8), 0x1 => Ok((self.vector & 0xFF) as u8),
0x2 => Ok((self.width >> 8) as u8), 0x2 => Ok((self.width >> 8) as u8),
0x3 => Ok((self.width & 0xFF) as u8), 0x3 => Ok((self.width & 0xFF) as u8),
0x4 => Ok((self.height >> 8) as u8), 0x4 => Ok((self.height >> 8) as u8),
0x5 => Ok((self.height & 0xFF) 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), _ => Ok(0),
} }
} }
@ -177,18 +216,40 @@ impl Device for Sdl2VideoDevice {
0x1 => self.vector = self.vector & 0xFF00 | (val as u16), 0x1 => self.vector = self.vector & 0xFF00 | (val as u16),
// Writing to the device width port. // Writing to the device width port.
// Note that the reference implementation triggers resizing on the lower byte // 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 // Writing to the device height port
// Note that the reference implementation triggers resizing on the lower byte // 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) // 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 // 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 // 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.
}
_ => (), _ => (),
} }