Skip to content

Commit

Permalink
Merge pull request #40 from pineman/scrolling-logo
Browse files Browse the repository at this point in the history
scrolling logo!!!!
  • Loading branch information
pineman authored Apr 2, 2024
2 parents b8f0236 + 4f78f63 commit 686cfe4
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 41 deletions.
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

0 comments on commit 686cfe4

Please sign in to comment.