Support hypothetical big-endian users
This commit is contained in:
parent
b888d1140a
commit
f7cf960b62
|
@ -39,11 +39,12 @@ impl MemoryClient {
|
||||||
MemoryView { region }
|
MemoryView { region }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write<T: bytemuck::NoUninit>(&self, sim: SimId, address: u32, data: &T) {
|
pub fn write<T: MemoryValue>(&self, sim: SimId, address: u32, data: &T) {
|
||||||
let data = bytemuck::bytes_of(data).to_vec();
|
let mut buffer = vec![];
|
||||||
|
data.to_bytes(&mut buffer);
|
||||||
let (tx, _) = oneshot::channel();
|
let (tx, _) = oneshot::channel();
|
||||||
self.client
|
self.client
|
||||||
.send_command(EmulatorCommand::WriteMemory(sim, address, data, tx));
|
.send_command(EmulatorCommand::WriteMemory(sim, address, buffer, tx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,17 +75,87 @@ pub struct MemoryRef<'a> {
|
||||||
inner: RwLockReadGuard<'a, BoxBytes>,
|
inner: RwLockReadGuard<'a, BoxBytes>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemoryRef<'_> {
|
pub trait MemoryValue {
|
||||||
pub fn read<T: bytemuck::AnyBitPattern>(&self, index: usize) -> T {
|
fn from_bytes(bytes: &[u8]) -> Self;
|
||||||
let from = index * size_of::<T>();
|
fn to_bytes(&self, buffer: &mut Vec<u8>);
|
||||||
let to = from + size_of::<T>();
|
|
||||||
*bytemuck::from_bytes(&self.inner[from..to])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn range<T: bytemuck::AnyBitPattern>(&self, start: usize, count: usize) -> &[T] {
|
macro_rules! primitive_memory_value_impl {
|
||||||
|
($T:ty, $L: expr) => {
|
||||||
|
impl MemoryValue for $T {
|
||||||
|
#[inline]
|
||||||
|
fn from_bytes(bytes: &[u8]) -> Self {
|
||||||
|
let bytes: [u8; std::mem::size_of::<$T>()] = std::array::from_fn(|i| bytes[i]);
|
||||||
|
<$T>::from_le_bytes(bytes)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn to_bytes(&self, buffer: &mut Vec<u8>) {
|
||||||
|
buffer.extend_from_slice(&self.to_le_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
primitive_memory_value_impl!(u8, 1);
|
||||||
|
primitive_memory_value_impl!(u16, 2);
|
||||||
|
primitive_memory_value_impl!(u32, 4);
|
||||||
|
|
||||||
|
impl<const N: usize, T: MemoryValue> MemoryValue for [T; N] {
|
||||||
|
#[inline]
|
||||||
|
fn from_bytes(bytes: &[u8]) -> Self {
|
||||||
|
std::array::from_fn(|i| {
|
||||||
|
T::from_bytes(&bytes[i * std::mem::size_of::<T>()..(i + 1) * std::mem::size_of::<T>()])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn to_bytes(&self, buffer: &mut Vec<u8>) {
|
||||||
|
for item in self {
|
||||||
|
item.to_bytes(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MemoryIter<'a, T> {
|
||||||
|
bytes: &'a [u8],
|
||||||
|
index: usize,
|
||||||
|
_phantom: std::marker::PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> MemoryIter<'a, T> {
|
||||||
|
fn new(bytes: &'a [u8]) -> Self {
|
||||||
|
Self {
|
||||||
|
bytes,
|
||||||
|
index: 0,
|
||||||
|
_phantom: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: MemoryValue> Iterator for MemoryIter<'_, T> {
|
||||||
|
type Item = T;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.index >= self.bytes.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let bytes = &self.bytes[self.index..self.index + std::mem::size_of::<T>()];
|
||||||
|
self.index += std::mem::size_of::<T>();
|
||||||
|
Some(T::from_bytes(bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryRef<'_> {
|
||||||
|
pub fn read<T: MemoryValue>(&self, index: usize) -> T {
|
||||||
|
let from = index * size_of::<T>();
|
||||||
|
let to = from + size_of::<T>();
|
||||||
|
T::from_bytes(&self.inner[from..to])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn range<T: MemoryValue>(&self, start: usize, count: usize) -> MemoryIter<T> {
|
||||||
let from = start * size_of::<T>();
|
let from = start * size_of::<T>();
|
||||||
let to = from + (count * size_of::<T>());
|
let to = from + (count * size_of::<T>());
|
||||||
bytemuck::cast_slice(&self.inner[from..to])
|
MemoryIter::new(&self.inner[from..to])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -239,30 +239,26 @@ impl BgMapRenderer {
|
||||||
let brightness = self.brightness.borrow();
|
let brightness = self.brightness.borrow();
|
||||||
let palettes = self.palettes.borrow();
|
let palettes = self.palettes.borrow();
|
||||||
|
|
||||||
let brts = brightness.range::<u8>(0, 8);
|
let brts = brightness.read::<[u8; 8]>(0);
|
||||||
let colors = if generic_palette {
|
let colors = if generic_palette {
|
||||||
[utils::generic_palette(Color32::RED); 4]
|
[utils::generic_palette(Color32::RED); 4]
|
||||||
} else {
|
} else {
|
||||||
[0, 2, 4, 6].map(|i| utils::parse_palette(palettes.read(i), brts, Color32::RED))
|
[0, 2, 4, 6].map(|i| utils::parse_palette(palettes.read(i), &brts, Color32::RED))
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i, cell) in bgmaps
|
for (i, cell) in bgmaps.range::<u16>(bgmap_index * 4096, 4096).enumerate() {
|
||||||
.range::<u16>(bgmap_index * 4096, 4096)
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
{
|
|
||||||
let CellData {
|
let CellData {
|
||||||
char_index,
|
char_index,
|
||||||
vflip,
|
vflip,
|
||||||
hflip,
|
hflip,
|
||||||
palette_index,
|
palette_index,
|
||||||
} = CellData::parse(*cell);
|
} = CellData::parse(cell);
|
||||||
let char = chardata.range::<u16>(char_index * 8, 8);
|
let char = chardata.read::<[u16; 8]>(char_index);
|
||||||
let palette = &colors[palette_index];
|
let palette = &colors[palette_index];
|
||||||
|
|
||||||
for row in 0..8 {
|
for row in 0..8 {
|
||||||
let y = row + (i / 64) * 8;
|
let y = row + (i / 64) * 8;
|
||||||
for (col, pixel) in utils::read_char_row(char, hflip, vflip, row).enumerate() {
|
for (col, pixel) in utils::read_char_row(&char, hflip, vflip, row).enumerate() {
|
||||||
let x = col + (i % 64) * 8;
|
let x = col + (i % 64) * 8;
|
||||||
image.write((x, y), palette[pixel as usize]);
|
image.write((x, y), palette[pixel as usize]);
|
||||||
}
|
}
|
||||||
|
@ -276,7 +272,7 @@ impl BgMapRenderer {
|
||||||
let brightness = self.brightness.borrow();
|
let brightness = self.brightness.borrow();
|
||||||
let palettes = self.palettes.borrow();
|
let palettes = self.palettes.borrow();
|
||||||
|
|
||||||
let brts = brightness.range::<u8>(0, 8);
|
let brts = brightness.read::<[u8; 8]>(0);
|
||||||
|
|
||||||
let cell = bgmaps.read::<u16>(index);
|
let cell = bgmaps.read::<u16>(index);
|
||||||
|
|
||||||
|
@ -286,15 +282,15 @@ impl BgMapRenderer {
|
||||||
hflip,
|
hflip,
|
||||||
palette_index,
|
palette_index,
|
||||||
} = CellData::parse(cell);
|
} = CellData::parse(cell);
|
||||||
let char = chardata.range::<u16>(char_index * 8, 8);
|
let char = chardata.read::<[u16; 8]>(char_index);
|
||||||
let palette = if generic_palette {
|
let palette = if generic_palette {
|
||||||
utils::generic_palette(Color32::RED)
|
utils::generic_palette(Color32::RED)
|
||||||
} else {
|
} else {
|
||||||
utils::parse_palette(palettes.read(palette_index * 2), brts, Color32::RED)
|
utils::parse_palette(palettes.read(palette_index * 2), &brts, Color32::RED)
|
||||||
};
|
};
|
||||||
|
|
||||||
for row in 0..8 {
|
for row in 0..8 {
|
||||||
for (col, pixel) in utils::read_char_row(char, hflip, vflip, row).enumerate() {
|
for (col, pixel) in utils::read_char_row(&char, hflip, vflip, row).enumerate() {
|
||||||
image.write((col, row), palette[pixel as usize]);
|
image.write((col, row), palette[pixel as usize]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,8 +221,8 @@ impl CharacterDataWindow {
|
||||||
};
|
};
|
||||||
let palette = self.palettes.borrow().read(offset);
|
let palette = self.palettes.borrow().read(offset);
|
||||||
let brightnesses = self.brightness.borrow();
|
let brightnesses = self.brightness.borrow();
|
||||||
let brts = brightnesses.range(0, 8);
|
let brts = brightnesses.read(0);
|
||||||
utils::parse_palette(palette, brts, Color32::RED)
|
utils::parse_palette(palette, &brts, Color32::RED)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_chardata(&mut self, ui: &mut Ui) {
|
fn show_chardata(&mut self, ui: &mut Ui) {
|
||||||
|
@ -321,7 +321,7 @@ impl CharDataRenderer {
|
||||||
let palette = self.load_palette(palette);
|
let palette = self.load_palette(palette);
|
||||||
let chardata = self.chardata.borrow();
|
let chardata = self.chardata.borrow();
|
||||||
let character = chardata.range::<u16>(index * 8, 8);
|
let character = chardata.range::<u16>(index * 8, 8);
|
||||||
for (row, pixels) in character.iter().enumerate() {
|
for (row, pixels) in character.enumerate() {
|
||||||
for col in 0..8 {
|
for col in 0..8 {
|
||||||
let char = (pixels >> (col * 2)) & 0x03;
|
let char = (pixels >> (col * 2)) & 0x03;
|
||||||
image.write((col, row), palette[char as usize]);
|
image.write((col, row), palette[char as usize]);
|
||||||
|
@ -332,7 +332,7 @@ impl CharDataRenderer {
|
||||||
fn render_character_data(&self, image: &mut VramImage, palette: VramPalette) {
|
fn render_character_data(&self, image: &mut VramImage, palette: VramPalette) {
|
||||||
let palette = self.load_palette(palette);
|
let palette = self.load_palette(palette);
|
||||||
let chardata = self.chardata.borrow();
|
let chardata = self.chardata.borrow();
|
||||||
for (row, pixels) in chardata.range::<u16>(0, 8 * 2048).iter().enumerate() {
|
for (row, pixels) in chardata.range::<u16>(0, 8 * 2048).enumerate() {
|
||||||
let char_index = row / 8;
|
let char_index = row / 8;
|
||||||
let row_index = row % 8;
|
let row_index = row % 8;
|
||||||
let x = (char_index % 16) * 8;
|
let x = (char_index % 16) * 8;
|
||||||
|
@ -350,7 +350,7 @@ impl CharDataRenderer {
|
||||||
};
|
};
|
||||||
let palette = self.palettes.borrow().read(offset);
|
let palette = self.palettes.borrow().read(offset);
|
||||||
let brightnesses = self.brightness.borrow();
|
let brightnesses = self.brightness.borrow();
|
||||||
let brts = brightnesses.range(0, 8);
|
let brts = brightnesses.read(0);
|
||||||
utils::parse_palette(palette, brts, Color32::RED)
|
utils::parse_palette(palette, &brts, Color32::RED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,7 +282,7 @@ impl ObjectRenderer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let brts = brightness.range::<u8>(0, 8);
|
let brts = brightness.read::<[u8; 8]>(0);
|
||||||
let (x, y) = if use_pos {
|
let (x, y) = if use_pos {
|
||||||
let x = match eye {
|
let x = match eye {
|
||||||
Eye::Left => obj.x - obj.parallax,
|
Eye::Left => obj.x - obj.parallax,
|
||||||
|
@ -298,11 +298,11 @@ impl ObjectRenderer {
|
||||||
Eye::Right => params.right_color,
|
Eye::Right => params.right_color,
|
||||||
};
|
};
|
||||||
|
|
||||||
let char = chardata.range::<u16>(obj.data.char_index * 8, 8);
|
let char = chardata.read::<[u16; 8]>(obj.data.char_index);
|
||||||
let palette = if params.generic_palette {
|
let palette = if params.generic_palette {
|
||||||
utils::generic_palette(color)
|
utils::generic_palette(color)
|
||||||
} else {
|
} else {
|
||||||
utils::parse_palette(palettes.read(8 + obj.data.palette_index * 2), brts, color)
|
utils::parse_palette(palettes.read(8 + obj.data.palette_index * 2), &brts, color)
|
||||||
};
|
};
|
||||||
|
|
||||||
for row in 0..8 {
|
for row in 0..8 {
|
||||||
|
@ -311,7 +311,7 @@ impl ObjectRenderer {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (col, pixel) in
|
for (col, pixel) in
|
||||||
utils::read_char_row(char, obj.data.hflip, obj.data.vflip, row).enumerate()
|
utils::read_char_row(&char, obj.data.hflip, obj.data.vflip, row).enumerate()
|
||||||
{
|
{
|
||||||
let real_x = x + col as i16;
|
let real_x = x + col as i16;
|
||||||
if !(0..384).contains(&real_x) {
|
if !(0..384).contains(&real_x) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub fn generic_palette(color: Color32) -> [Color32; 4] {
|
||||||
GENERIC_PALETTE.map(|brt| shade(brt, color))
|
GENERIC_PALETTE.map(|brt| shade(brt, color))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_palette(palette: u8, brts: &[u8], color: Color32) -> [Color32; 4] {
|
pub fn parse_palette(palette: u8, brts: &[u8; 8], color: Color32) -> [Color32; 4] {
|
||||||
let shades = [
|
let shades = [
|
||||||
Color32::BLACK,
|
Color32::BLACK,
|
||||||
shade(brts[0], color),
|
shade(brts[0], color),
|
||||||
|
@ -117,7 +117,7 @@ impl CellData {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_char_row(
|
pub fn read_char_row(
|
||||||
char: &[u16],
|
char: &[u16; 8],
|
||||||
hflip: bool,
|
hflip: bool,
|
||||||
vflip: bool,
|
vflip: bool,
|
||||||
row: usize,
|
row: usize,
|
||||||
|
|
Loading…
Reference in New Issue