Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scrolling logo!!!! #40

Merged
merged 2 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions fpt-egui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,14 +307,14 @@ impl FPT {
});

let lcdc = self.gb().bus().lcdc();
let gb_map_area = match bitwise::test_bit8::<3>(lcdc) {
let bg_map_area = match bitwise::test_bit8::<3>(lcdc) {
false => 0x9800..0x9C00,
true => 0x9C00..0xA000
};
let bg_map_iter = gb_map_area.map(|addr| self.gb.borrow().bus().read(addr));
let bg_map_iter = bg_map_area.map(|addr| self.gb.borrow().bus().read(addr));

for (i, tile_address) in bg_map_iter.enumerate() {
let tile = self.get_tile(tile_address as usize);
for (i, tile_i) in bg_map_iter.enumerate() {
let tile = self.get_tile(tile_i as usize);
for y in 0..TILE_SIZE {
let yy = y + (i / BMV_TILES_PER) * TILE_SIZE + BMV_BORDER_SIZE;
for x in 0..TILE_SIZE {
Expand Down Expand Up @@ -359,7 +359,7 @@ impl FPT {
});
texture.set(self.bg_map.clone(), TextureOptions::NEAREST);
ui.vertical(|ui| {
ui.label("Tilemap 0");
ui.label("BG Map");
ui.image((texture.id(), BMV_TEXTURE_SCALE * texture.size_vec2()));
});
});
Expand Down
59 changes: 23 additions & 36 deletions fpt/src/ppu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ pub mod tile;

pub const WIDTH: usize = 160;
pub const HEIGHT: usize = 144;
pub type Frame = [u8; WIDTH * HEIGHT];
pub type Frame = [u8; WIDTH * HEIGHT]; // TODO: wasteful, each pixel is 2 bits only

//#[derive(Clone, PartialEq)]
#[allow(unused)]
pub struct Ppu {
bus: Bus,
frame: Frame,
dots_this_frame: u32,
counter: u32,
frame_counter: u32,
mode: Mode,
tilemap: VRamContents,
}
Expand Down Expand Up @@ -59,7 +59,7 @@ impl Ppu {
bus,
frame: [0b00; WIDTH * HEIGHT],
dots_this_frame: 0,
counter: 0,
frame_counter: 0,
mode: Mode::OamScan,
tilemap: VRamContents::default(),
}
Expand All @@ -76,39 +76,30 @@ impl Ppu {
}

fn oam_scan(&mut self) {
if self.dots_this_frame % 456 == 79 {
if self.dots_this_frame % 456 == (80 - 1) {
self.tilemap = VRamContents::load(&self.bus.vram());
self.set_mode(Mode::PixelTransfer);
}
}

/// Currently only draws the background pixels, not the window or sprites
#[allow(clippy::format_collect)]
fn pixel_transfer(&mut self) {
if self.dots_this_frame % 456 == 238 {
if self.dots_this_frame % 456 == (80 + 160) as u32 {
self.set_mode(Mode::HBlank);
return;
}

let current_pixel = ((self.dots_this_frame % 456) - 80) as usize; // TODO I'm pretending the PPU never stalls
let address = WIDTH * self.bus.ly() as usize + current_pixel;
if address >= WIDTH * HEIGHT {
dbg!(self.bus.ly());
}

let column = address % WIDTH;
let line = address / WIDTH;

let tile_address = 32 * line / 8 + column / 8;

let tile_data_address = self.tilemap.tile_map0[tile_address];

let tile_x = column % 8;
let tile_y = line % 8;

// TODO: LCDC.3
let x = ((self.dots_this_frame % 456) - 80) as usize; // TODO I'm pretending the PPU never stalls
let y = self.bus.ly() as usize;
let xx = ((x as u8 + self.bus.scx()) as u16 % 256u16) as usize;
let yy = ((self.bus.ly() + self.bus.scy()) as u16 % 256u16) as usize;
// TODO: LCDC.4
let tile_i = xx / 8 + yy / 8 * 32;
let tile_data_address = self.tilemap.tile_map0[tile_i];
let tile = self.tilemap.tile_data[tile_data_address as usize];
let pixel = tile.get_pixel(tile_y, tile_x);

self.frame[address] = pixel;
let pixel = tile.get_pixel(yy % 8, xx % 8);
self.frame[WIDTH * y + x] = pixel;
}

fn h_blank(&mut self) {
Expand All @@ -125,15 +116,6 @@ impl Ppu {
}
}

fn state_machine(&mut self) {
match self.mode {
Mode::OamScan => self.oam_scan(),
Mode::PixelTransfer => self.pixel_transfer(),
Mode::HBlank => self.h_blank(),
Mode::VBlank => self.v_blank(),
};
}

/// Simulates a "dot", as described in https://gbdev.io/pandocs/Rendering.html.
/// A "dot" either draws a single pixel (in Mode 3) or is stalled for $REASONS.
/// A "dot" = one 2^22 Hz time unit, so there's 4 dots per machine cycle,
Expand All @@ -158,7 +140,12 @@ impl Ppu {
// Mode::VBlank // Mode 1
//};

self.state_machine();
match self.mode {
Mode::OamScan => self.oam_scan(),
Mode::PixelTransfer => self.pixel_transfer(),
Mode::HBlank => self.h_blank(),
Mode::VBlank => self.v_blank(),
};

// Update "LYC == LY" and "PPU mode" flags in STAT register
self.bus.set_stat(
Expand All @@ -172,7 +159,7 @@ impl Ppu {
// Advance one "dot"
self.dots_this_frame = (self.dots_this_frame + 1) % DOTS_IN_ONE_FRAME;
if self.dots_this_frame == 0 {
self.counter += 1;
self.frame_counter += 1;
}
}

Expand Down
2 changes: 2 additions & 0 deletions fpt/src/ppu/tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ impl Tile {
Tile { bytes: *data }
}

// Returns the color of the pixel - a byte with only the last two bits set
// TODO: should return a bitfield
pub fn get_pixel(&self, y: usize, x: usize) -> u8 {
let low_bit = (self.bytes[2 * y] >> (7 - x)) & 1;
let high_bit = (self.bytes[2 * y + 1] >> (7 - x)) & 1;
Expand Down