Compare commits
1 Commits
c4a2a1a865
...
d750027831
Author | SHA1 | Date |
---|---|---|
Rekai Nyangadzayi Musuka | d750027831 |
56
src/ppu.zig
56
src/ppu.zig
|
@ -8,7 +8,6 @@ const Bit = @import("bitfield").Bit;
|
||||||
const Bitfield = @import("bitfield").Bitfield;
|
const Bitfield = @import("bitfield").Bitfield;
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const log = std.log.scoped(.PPU);
|
|
||||||
|
|
||||||
pub const width = 240;
|
pub const width = 240;
|
||||||
pub const height = 160;
|
pub const height = 160;
|
||||||
|
@ -77,12 +76,12 @@ pub const Ppu = struct {
|
||||||
self.bg[n + 1].cnt.raw = @truncate(u16, word >> 16);
|
self.bg[n + 1].cnt.raw = @truncate(u16, word >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search OAM for Sprites that might be rendered on this scanline
|
// Search OAM for Sprites that might be rendered on this scanline
|
||||||
fn fetchSprites(self: *Self) void {
|
fn fetchSprites(self: *Self) void {
|
||||||
const y = self.vcount.scanline.read();
|
const y = self.vcount.scanline.read();
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
search: while (i < self.oam.buf.len) : (i += 8) {
|
outer: while (i < self.oam.buf.len) : (i += 8) {
|
||||||
// Attributes in OAM are 6 bytes long, with 2 bytes of padding
|
// Attributes in OAM are 6 bytes long, with 2 bytes of padding
|
||||||
// Grab Attributes from OAM
|
// Grab Attributes from OAM
|
||||||
const attr0 = @bitCast(Attr0, self.oam.get16(i));
|
const attr0 = @bitCast(Attr0, self.oam.get16(i));
|
||||||
|
@ -102,12 +101,9 @@ pub const Ppu = struct {
|
||||||
for (self.scanline_sprites) |*maybe_sprite| {
|
for (self.scanline_sprites) |*maybe_sprite| {
|
||||||
if (maybe_sprite.* == null) {
|
if (maybe_sprite.* == null) {
|
||||||
maybe_sprite.* = sprite;
|
maybe_sprite.* = sprite;
|
||||||
continue :search;
|
continue :outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.err("Found more than 128 sprites in OAM Search", .{});
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,31 +138,57 @@ pub const Ppu = struct {
|
||||||
} else break;
|
} else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // TODO: Scanning OAM for every single pixel is insanely expensive
|
||||||
|
// // This should be done once per scanline (and then check for X bounds every pixel)
|
||||||
|
// var j: u32 = 0;
|
||||||
|
// while (j < self.oam.buf.len) : (j += 8) {
|
||||||
|
// // Attributes in OAM are 6 bytes long, with 2 bytes of padding
|
||||||
|
// // Grab Attributes from OAM
|
||||||
|
// const attr0 = @bitCast(Attr0, self.oam.get16(j));
|
||||||
|
// const attr1 = @bitCast(Attr1, self.oam.get16(j + 2));
|
||||||
|
// const attr2 = @bitCast(Attr2, self.oam.get16(j + 4));
|
||||||
|
|
||||||
|
// // Only consider enabled sprites on the current priority
|
||||||
|
// if (attr0.disabled.read() or attr2.rel_prio.read() != prio) continue;
|
||||||
|
|
||||||
|
// // Determine sprite bounds
|
||||||
|
// const d = spriteDimensions(attr0.shape.read(), attr1.size.read());
|
||||||
|
// const sy = attr0.y.read();
|
||||||
|
// const sx = attr1.x.read();
|
||||||
|
// const sx_end = sx + d[0];
|
||||||
|
// const sy_end = sy + d[1];
|
||||||
|
|
||||||
|
// // If sprite is in range
|
||||||
|
// if (sy < y and sy_end > y and sx < x and sx_end > x) {
|
||||||
|
// maybe_sprite = Sprite.init(attr0, attr1, attr2);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// If we didn't find a sprite, progress to the next pixel
|
// If we didn't find a sprite, progress to the next pixel
|
||||||
const sprite: Sprite = if (maybe_sprite) |s| s else continue;
|
const sprite: Sprite = if (maybe_sprite) |s| s else continue;
|
||||||
const is_8bpp = sprite.is_8bpp();
|
const is_8bpp = sprite.is_8bpp();
|
||||||
|
|
||||||
// Y and X coordinates within the context of a singular 8x8 tile
|
// Y and X coordinates within the context of a singular 8x8 tile
|
||||||
const tile_y: u16 = (y - sprite.y()) ^ if (sprite.v_flip()) (sprite.height - 1) else 0;
|
const tile_y = y - sprite.y();
|
||||||
const tile_x = (x - sprite.x()) ^ if (sprite.h_flip()) (sprite.width - 1) else 0;
|
const tile_x = x - sprite.x();
|
||||||
|
|
||||||
const tile_id: u32 = sprite.tile_id();
|
const tile_id: u32 = sprite.tile_id();
|
||||||
const tile_row_offset: u32 = if (is_8bpp) 8 else 4;
|
const tile_row_offset: u32 = if (is_8bpp) 8 else 4;
|
||||||
const tile_len: u32 = if (is_8bpp) 0x40 else 0x20;
|
const tile_len: u32 = if (is_8bpp) 0x40 else 0x20;
|
||||||
|
|
||||||
const row = tile_y % 8;
|
const row = if (sprite.v_flip()) 7 - (tile_y % 8) else tile_y % 8;
|
||||||
const col = tile_x % 8;
|
const col = if (sprite.h_flip()) 7 - (tile_x % 8) else tile_x % 8;
|
||||||
|
|
||||||
const tile_base: u32 = char_base + (0x20 * tile_id) + (tile_row_offset * row) + if (is_8bpp) col else col / 2;
|
const tile_base: u32 = char_base + (0x20 * tile_id) + (tile_row_offset * row) + if (is_8bpp) col else col / 2;
|
||||||
|
|
||||||
var tile_offset = (tile_x / 8) * tile_len;
|
var tile_offset = (tile_x >> 3) * tile_len;
|
||||||
if (self.dispcnt.obj_mapping.read()) {
|
if (self.dispcnt.obj_mapping.read()) {
|
||||||
// One Dimensional
|
// One Dimensional
|
||||||
tile_offset += (tile_y / 8) * tile_len * (sprite.width / 8);
|
tile_offset += (tile_y / 8) * tile_len * (sprite.width >> 3);
|
||||||
} else {
|
} else {
|
||||||
// Two Dimensional
|
// Two Dimensional
|
||||||
// TODO: This doesn't work
|
tile_offset += (@as(u32, tile_y) >> 3) * tile_len * 0x20;
|
||||||
tile_offset += (tile_y / 8) * tile_len * 0x20;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const tile = self.vram.buf[tile_base + tile_offset];
|
const tile = self.vram.buf[tile_base + tile_offset];
|
||||||
|
@ -539,7 +561,7 @@ const Sprite = struct {
|
||||||
return self.attr2.tile_id.read();
|
return self.attr2.tile_id.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pal_bank(self: *const Self) u4 {
|
fn pal_bank(self: *const Self) u3 {
|
||||||
return self.attr2.pal_bank.read();
|
return self.attr2.pal_bank.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,7 +604,7 @@ const Attr1 = extern union {
|
||||||
const Attr2 = extern union {
|
const Attr2 = extern union {
|
||||||
tile_id: Bitfield(u16, 0, 10),
|
tile_id: Bitfield(u16, 0, 10),
|
||||||
rel_prio: Bitfield(u16, 10, 2),
|
rel_prio: Bitfield(u16, 10, 2),
|
||||||
pal_bank: Bitfield(u16, 12, 4),
|
pal_bank: Bitfield(u16, 12, 3),
|
||||||
};
|
};
|
||||||
|
|
||||||
fn spriteDimensions(shape: u2, size: u2) [2]u16 {
|
fn spriteDimensions(shape: u2, size: u2) [2]u16 {
|
||||||
|
|
Loading…
Reference in New Issue