Pixel write
This commit is contained in:
parent
7bd08d65de
commit
a731616146
1 changed files with 83 additions and 22 deletions
|
@ -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.
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue