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::{
device::{Device, DeviceError},
vm::Uxn,
@ -26,13 +28,14 @@ pub struct Sdl2VideoDevice {
pixels: Vec<u32>,
width: u16,
height: u16,
fg: Layer,
bg: Layer,
mono: u8,
fg: Rc<RefCell<Layer>>,
bg: Rc<RefCell<Layer>>,
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.
}
_ => (),
}