Skip to content

Commit

Permalink
Fix sprites disappearing too early when sliding left off screen
Browse files Browse the repository at this point in the history
  • Loading branch information
twvd committed Dec 18, 2023
1 parent 0428387 commit fb90281
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 19 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod frontend;
pub mod snes;
pub mod tickable;
pub mod util;

#[cfg(test)]
pub mod test;
10 changes: 1 addition & 9 deletions src/snes/ppu/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ use super::*;

use crate::frontend::Renderer;
use crate::snes::bus::{Address, BusMember};

use num::traits::{WrappingShl, WrappingShr};
use num::Integer;
use std::mem::size_of_val;
use crate::util::sign_extend;

macro_rules! write_m7x {
($self:ident, $reg:ident, $val:expr) => {{
Expand All @@ -24,11 +21,6 @@ macro_rules! write_m7x_13b {
}};
}

fn sign_extend<T: Integer + WrappingShl + WrappingShr>(val: T, nbits: u32) -> T {
let notherbits = size_of_val(&val) as u32 * 8 - nbits;
val.wrapping_shl(notherbits).wrapping_shr(notherbits)
}

impl<TRenderer> BusMember<Address> for PPU<TRenderer>
where
TRenderer: Renderer,
Expand Down
28 changes: 20 additions & 8 deletions src/snes/ppu/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,23 +198,35 @@ where
}

if (e.y..(e.y + e.height)).contains(&scanline) {
for x in e.x..(e.x + e.width) {
if x >= state.idx.len() {
for x in e.x..(e.x + e.width as i32) {
if x >= state.idx.len() as i32 || x < 0 {
// Outside of visible area.
break;
continue;
}
if state.window.sprites[x] && state.windowlayermask & (1 << LAYER_SPRITES) != 0

if state.window.sprites[x as usize]
&& state.windowlayermask & (1 << LAYER_SPRITES) != 0
{
// Masked by window.
continue;
}

let t_x = (x - e.x) / TILE_WIDTH;
let t_y = (scanline - e.y) / TILE_HEIGHT;
// Coordinates within the tile
let (in_x, in_y) = (
((x - e.x) % TILE_WIDTH as i32) as usize,
((scanline - e.y) % TILE_HEIGHT) as usize,
);
// Sub-tile coordinates
let (t_x, t_y) = (
((x - e.x) / TILE_WIDTH as i32) as usize,
((scanline - e.y) / TILE_HEIGHT) as usize,
);
// Should be positive from here on
let x = x as usize;

let sprite = self.get_sprite_tile(&e, t_x, t_y);

let coloridx =
sprite.get_coloridx((x - e.x) % TILE_WIDTH, (scanline - e.y) % TILE_HEIGHT);
let coloridx = sprite.get_coloridx(in_x, in_y);
if coloridx == 0 || state.idx[x] != 0 {
continue;
}
Expand Down
5 changes: 3 additions & 2 deletions src/snes/ppu/sprites.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use super::*;
use crate::util::sign_extend;

pub const OAM_ENTRIES: usize = 128;

#[derive(Debug)]
pub struct OAMEntry {
pub x: usize,
pub x: i32,
pub y: usize,
pub priority: u8,
pub attr: u8,
Expand Down Expand Up @@ -107,7 +108,7 @@ where
};

OAMEntry {
x: usize::from(e[0]) | (usize::from(ext) & 0x01) << 8,
x: sign_extend(i32::from(e[0]) | (i32::from(ext) & 0x01) << 8, 9),
y: e[1].into(),
tileidx: e[2] as u16 | (e[3] as u16 & 0x01) << 8,
attr: e[3],
Expand Down
9 changes: 9 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use num::traits::{WrappingShl, WrappingShr};
use num::Integer;
use std::mem::size_of_val;

/// Sign-extend a value
pub fn sign_extend<T: Integer + WrappingShl + WrappingShr>(val: T, nbits: u32) -> T {
let notherbits = size_of_val(&val) as u32 * 8 - nbits;
val.wrapping_shl(notherbits).wrapping_shr(notherbits)
}

0 comments on commit fb90281

Please sign in to comment.