Skip to content

Commit

Permalink
feat: hacky scrolling (horiz only)
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanleiby committed Dec 19, 2024
1 parent c258fa9 commit 48a1978
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ fn main() -> Result<(), Box<dyn Error>> {
move |ppu: &Ppu, gamepad1: &mut GamepadRegister, _gamepad2: &mut GamepadRegister| {
// compute the screen's content from the PPU
let mut frame = Frame::new();
ppu.draw_background(&mut frame);
ppu.draw_scrollable_background(&mut frame);
ppu.draw_sprites(&mut frame);

// redraw the screen
Expand Down
58 changes: 55 additions & 3 deletions src/ppu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,60 @@ impl Ppu {
let tile_n = self.vram[self.mirror_vram_addr((nt_start + offset) as u16) as usize];
let bgp_idx = self.palette_for_bg_tile((x, y), nt_start);
let palette = self.lookup_palette(bgp_idx);
frame.draw_bg_tile(pattern_table, tile_n as usize, (x, y), palette);
frame.draw_bg_tile(pattern_table, tile_n as usize, (x, y), 0, palette);
}
}
}

/// Draws the entire possible background of 2 frames, but it gets filtered within, which you can then filter by applying a windowed viewport
pub fn draw_scrollable_background(&self, frame: &mut Frame) {
let bank = self.get_background_pattern_bank();
let pattern_table =
&self.chr_rom[bank * PATTERN_TABLE_SIZE..(bank + 1) * PATTERN_TABLE_SIZE];

// In horizontal scrolling, this is the nametable at the LEFT of the screen
let which_nametable = self
.registers
.control
.intersection(ControlRegister::NAMETABLE)
.bits() as usize;
assert!(which_nametable <= 3);
let nt_start = which_nametable * 0x400;

// self.registers.control.

// Determine which nametable is on the left
let nts = if nt_start == 0 {
[0, 0x400]
} else {
[0x400, 0x800]
};

let x_scroll: usize = self.registers.scroll.x_scroll as usize;
let y_scroll: usize = self.registers.scroll.y_scroll as usize;
// TODO
// if self.registers.control.contains(ControlRegister::X_SCROLL) {
// x_scroll += 256;
// }

let rows = 30;
let cols = 32;
for tile_y in 0..rows {
for (nt_idx, &nt_start) in nts.iter().enumerate() {
for tile_x in 0..cols {
let offset = tile_y * cols + tile_x;
let tile_n =
self.vram[self.mirror_vram_addr((nt_start + offset) as u16) as usize];
let bgp_idx = self.palette_for_bg_tile((tile_x, tile_y), nt_start);
let palette = self.lookup_palette(bgp_idx);
frame.draw_bg_tile(
pattern_table,
tile_n as usize,
(tile_x + cols * (nt_idx), tile_y),
x_scroll,
palette,
);
}
}
}
}
Expand Down Expand Up @@ -477,8 +530,7 @@ impl Ppu {
let sprite0 = self.parse_sprite_from_oam_data(&self.oam_data[0..4]);
let (scanline_y, scanline_x) = self.get_tick_status();

scanline_y >= sprite0.y as usize
&& (scanline_x % CYCLES_PER_SCANLINE) >= sprite0.x as usize
scanline_y >= sprite0.y as usize && (scanline_x % CYCLES_PER_SCANLINE) >= sprite0.x as usize
}
}

Expand Down
21 changes: 14 additions & 7 deletions src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl Frame {

pub fn new() -> Self {
Self {
// TODO: Consider a 'double-sized' frame with a viewport() function
data: vec![0; Frame::WIDTH * Frame::HEIGHT * 3],
}
}
Expand All @@ -68,18 +69,24 @@ impl Frame {
pattern_table: &[u8],
tile_n: usize,
pos: (usize, usize),
x_scroll: usize,
// y_scroll: usize,
palette: [u8; 4],
) {
let tile = get_tile(pattern_table, tile_n);
let (tile_x, tile_y) = pos;
for (row, row_data) in tile.iter().enumerate() {
for (col, &palette_idx) in row_data.iter().enumerate() {
let color = SYSTEM_PALETTE[palette[palette_idx as usize] as usize];
self.set_pixel(
(tile_x * TILE_SIZE_PIXELS) + col,
(tile_y * TILE_SIZE_PIXELS) + row,
color,
);
let left_x = (tile_x * TILE_SIZE_PIXELS) + col;
// only draw pixels within the screen width
if x_scroll <= left_x && left_x - x_scroll <= 256 {
self.set_pixel(
(tile_x * TILE_SIZE_PIXELS) + col - x_scroll,
(tile_y * TILE_SIZE_PIXELS) + row,
color,
);
}
}
}
}
Expand Down Expand Up @@ -156,7 +163,7 @@ mod test {

let mut f = Frame::new();
assert_eq!(f.data[0], 0);
f.draw_bg_tile(&pattern_table, tile_n, pos, palette);
f.draw_bg_tile(&pattern_table, tile_n, pos, 0, palette);
assert_eq!(f.data[0], 128);
assert_eq!(f.data[1], 128);
assert_eq!(f.data[2], 128);
Expand All @@ -175,7 +182,7 @@ mod test {
let palette = [65, 65, 65, 3]; // 65 should crash if read, since it's OOB the palette with 64 colors

let mut f = Frame::new();
f.draw_bg_tile(&pattern_table, tile_n, pos, palette);
f.draw_bg_tile(&pattern_table, tile_n, pos, 0, palette);

// verify we drew the entire tile in the one selected color
for row in 0..8 {
Expand Down

0 comments on commit 48a1978

Please sign in to comment.