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::{
|
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) {
|
||||||
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.
|
let fg = self.fg.borrow_mut();
|
||||||
self.fg.pixels[i] = 0x00;
|
for i in 0..(self.width * self.height) as usize {
|
||||||
self.bg.pixels[i] = 0x00;
|
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.
|
* 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.
|
||||||
|
}
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue