chore: small changes to normal background drawing code
This commit is contained in:
parent
4b4242df2a
commit
b18f488b01
|
@ -182,14 +182,14 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
||||||
0x0400_0014 => bus.ppu.setBgOffsets(1, value),
|
0x0400_0014 => bus.ppu.setBgOffsets(1, value),
|
||||||
0x0400_0018 => bus.ppu.setBgOffsets(2, value),
|
0x0400_0018 => bus.ppu.setBgOffsets(2, value),
|
||||||
0x0400_001C => bus.ppu.setBgOffsets(3, value),
|
0x0400_001C => bus.ppu.setBgOffsets(3, value),
|
||||||
0x0400_0020 => bus.ppu.aff.bg[0].writePaPb(value),
|
0x0400_0020 => bus.ppu.aff_bg[0].writePaPb(value),
|
||||||
0x0400_0024 => bus.ppu.aff.bg[0].writePcPd(value),
|
0x0400_0024 => bus.ppu.aff_bg[0].writePcPd(value),
|
||||||
0x0400_0028 => bus.ppu.aff.bg[0].x = @bitCast(i32, value),
|
0x0400_0028 => bus.ppu.aff_bg[0].x = @bitCast(i32, value),
|
||||||
0x0400_002C => bus.ppu.aff.bg[0].y = @bitCast(i32, value),
|
0x0400_002C => bus.ppu.aff_bg[0].y = @bitCast(i32, value),
|
||||||
0x0400_0030 => bus.ppu.aff.bg[1].writePaPb(value),
|
0x0400_0030 => bus.ppu.aff_bg[1].writePaPb(value),
|
||||||
0x0400_0034 => bus.ppu.aff.bg[1].writePcPd(value),
|
0x0400_0034 => bus.ppu.aff_bg[1].writePcPd(value),
|
||||||
0x0400_0038 => bus.ppu.aff.bg[1].x = @bitCast(i32, value),
|
0x0400_0038 => bus.ppu.aff_bg[1].x = @bitCast(i32, value),
|
||||||
0x0400_003C => bus.ppu.aff.bg[1].y = @bitCast(i32, value),
|
0x0400_003C => bus.ppu.aff_bg[1].y = @bitCast(i32, value),
|
||||||
0x0400_0040 => log.debug("Wrote 0x{X:0>8} to WIN0H and WIN1H", .{value}),
|
0x0400_0040 => log.debug("Wrote 0x{X:0>8} to WIN0H and WIN1H", .{value}),
|
||||||
0x0400_0044 => log.debug("Wrote 0x{X:0>8} to WIN0V and WIN1V", .{value}),
|
0x0400_0044 => log.debug("Wrote 0x{X:0>8} to WIN0V and WIN1V", .{value}),
|
||||||
0x0400_0048 => log.debug("Wrote 0x{X:0>8} to WININ and WINOUT", .{value}),
|
0x0400_0048 => log.debug("Wrote 0x{X:0>8} to WININ and WINOUT", .{value}),
|
||||||
|
@ -270,22 +270,22 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
||||||
0x0400_001A => bus.ppu.bg[2].vofs.raw = value,
|
0x0400_001A => bus.ppu.bg[2].vofs.raw = value,
|
||||||
0x0400_001C => bus.ppu.bg[3].hofs.raw = value,
|
0x0400_001C => bus.ppu.bg[3].hofs.raw = value,
|
||||||
0x0400_001E => bus.ppu.bg[3].vofs.raw = value,
|
0x0400_001E => bus.ppu.bg[3].vofs.raw = value,
|
||||||
0x0400_0020 => bus.ppu.aff.bg[0].pa = @bitCast(i16, value),
|
0x0400_0020 => bus.ppu.aff_bg[0].pa = @bitCast(i16, value),
|
||||||
0x0400_0022 => bus.ppu.aff.bg[0].pb = @bitCast(i16, value),
|
0x0400_0022 => bus.ppu.aff_bg[0].pb = @bitCast(i16, value),
|
||||||
0x0400_0024 => bus.ppu.aff.bg[0].pc = @bitCast(i16, value),
|
0x0400_0024 => bus.ppu.aff_bg[0].pc = @bitCast(i16, value),
|
||||||
0x0400_0026 => bus.ppu.aff.bg[0].pd = @bitCast(i16, value),
|
0x0400_0026 => bus.ppu.aff_bg[0].pd = @bitCast(i16, value),
|
||||||
0x0400_0028 => bus.ppu.aff.bg[0].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff.bg[0].x) & 0xFFFF_0000 | value),
|
0x0400_0028 => bus.ppu.aff_bg[0].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[0].x) & 0xFFFF_0000 | value),
|
||||||
0x0400_002A => bus.ppu.aff.bg[0].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff.bg[0].x) & 0x0000_FFFF | (@as(u32, value) << 16)),
|
0x0400_002A => bus.ppu.aff_bg[0].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[0].x) & 0x0000_FFFF | (@as(u32, value) << 16)),
|
||||||
0x0400_002C => bus.ppu.aff.bg[0].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff.bg[0].y) & 0xFFFF_0000 | value),
|
0x0400_002C => bus.ppu.aff_bg[0].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[0].y) & 0xFFFF_0000 | value),
|
||||||
0x0400_002E => bus.ppu.aff.bg[0].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff.bg[0].y) & 0x0000_FFFF | (@as(u32, value) << 16)),
|
0x0400_002E => bus.ppu.aff_bg[0].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[0].y) & 0x0000_FFFF | (@as(u32, value) << 16)),
|
||||||
0x0400_0030 => bus.ppu.aff.bg[1].pa = @bitCast(i16, value),
|
0x0400_0030 => bus.ppu.aff_bg[1].pa = @bitCast(i16, value),
|
||||||
0x0400_0032 => bus.ppu.aff.bg[1].pb = @bitCast(i16, value),
|
0x0400_0032 => bus.ppu.aff_bg[1].pb = @bitCast(i16, value),
|
||||||
0x0400_0034 => bus.ppu.aff.bg[1].pc = @bitCast(i16, value),
|
0x0400_0034 => bus.ppu.aff_bg[1].pc = @bitCast(i16, value),
|
||||||
0x0400_0036 => bus.ppu.aff.bg[1].pd = @bitCast(i16, value),
|
0x0400_0036 => bus.ppu.aff_bg[1].pd = @bitCast(i16, value),
|
||||||
0x0400_0038 => bus.ppu.aff.bg[1].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff.bg[1].x) & 0xFFFF_0000 | value),
|
0x0400_0038 => bus.ppu.aff_bg[1].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[1].x) & 0xFFFF_0000 | value),
|
||||||
0x0400_003A => bus.ppu.aff.bg[1].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff.bg[1].x) & 0x0000_FFFF | (@as(u32, value) << 16)),
|
0x0400_003A => bus.ppu.aff_bg[1].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[1].x) & 0x0000_FFFF | (@as(u32, value) << 16)),
|
||||||
0x0400_003C => bus.ppu.aff.bg[1].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff.bg[1].y) & 0xFFFF_0000 | value),
|
0x0400_003C => bus.ppu.aff_bg[1].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[1].y) & 0xFFFF_0000 | value),
|
||||||
0x0400_003E => bus.ppu.aff.bg[1].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff.bg[1].y) & 0x0000_FFFF | (@as(u32, value) << 16)),
|
0x0400_003E => bus.ppu.aff_bg[1].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[1].y) & 0x0000_FFFF | (@as(u32, value) << 16)),
|
||||||
0x0400_0040 => log.debug("Wrote 0x{X:0>4} to WIN0H", .{value}),
|
0x0400_0040 => log.debug("Wrote 0x{X:0>4} to WIN0H", .{value}),
|
||||||
0x0400_0042 => log.debug("Wrote 0x{X:0>4} to WIN1H", .{value}),
|
0x0400_0042 => log.debug("Wrote 0x{X:0>4} to WIN1H", .{value}),
|
||||||
0x0400_0044 => log.debug("Wrote 0x{X:0>4} to WIN0V", .{value}),
|
0x0400_0044 => log.debug("Wrote 0x{X:0>4} to WIN0V", .{value}),
|
||||||
|
|
56
src/ppu.zig
56
src/ppu.zig
|
@ -25,7 +25,7 @@ pub const Ppu = struct {
|
||||||
// Registers
|
// Registers
|
||||||
|
|
||||||
bg: [4]Background,
|
bg: [4]Background,
|
||||||
aff: AffineBackground,
|
aff_bg: [2]AffineBackground,
|
||||||
|
|
||||||
dispcnt: io.DisplayControl,
|
dispcnt: io.DisplayControl,
|
||||||
dispstat: io.DisplayStatus,
|
dispstat: io.DisplayStatus,
|
||||||
|
@ -58,7 +58,7 @@ pub const Ppu = struct {
|
||||||
|
|
||||||
// Registers
|
// Registers
|
||||||
.bg = [_]Background{Background.init()} ** 4,
|
.bg = [_]Background{Background.init()} ** 4,
|
||||||
.aff = AffineBackground.init(),
|
.aff_bg = [_]AffineBackground{AffineBackground.init()} ** 2,
|
||||||
.dispcnt = .{ .raw = 0x0000 },
|
.dispcnt = .{ .raw = 0x0000 },
|
||||||
.dispstat = .{ .raw = 0x0000 },
|
.dispstat = .{ .raw = 0x0000 },
|
||||||
.vcount = .{ .raw = 0x0000 },
|
.vcount = .{ .raw = 0x0000 },
|
||||||
|
@ -212,16 +212,16 @@ pub const Ppu = struct {
|
||||||
const px_width = tile_width << 3;
|
const px_width = tile_width << 3;
|
||||||
const px_height = px_width;
|
const px_height = px_width;
|
||||||
|
|
||||||
var aff_x = self.aff.bg[n - 2].x_latch.?;
|
var aff_x = self.aff_bg[n - 2].x_latch.?;
|
||||||
var aff_y = self.aff.bg[n - 2].y_latch.?;
|
var aff_y = self.aff_bg[n - 2].y_latch.?;
|
||||||
|
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
while (i < width) : (i += 1) {
|
while (i < width) : (i += 1) {
|
||||||
var ix = aff_x >> 8;
|
var ix = aff_x >> 8;
|
||||||
var iy = aff_y >> 8;
|
var iy = aff_y >> 8;
|
||||||
|
|
||||||
aff_x += self.aff.bg[n - 2].pa;
|
aff_x += self.aff_bg[n - 2].pa;
|
||||||
aff_y += self.aff.bg[n - 2].pc;
|
aff_y += self.aff_bg[n - 2].pc;
|
||||||
|
|
||||||
if (self.scanline_buf[@as(usize, i)] != null) continue;
|
if (self.scanline_buf[@as(usize, i)] != null) continue;
|
||||||
|
|
||||||
|
@ -244,17 +244,15 @@ pub const Ppu = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update BGxX and BGxY
|
// Update BGxX and BGxY
|
||||||
self.aff.bg[n - 2].x_latch.? += self.aff.bg[n - 2].pb; // PB is added to BGxX
|
self.aff_bg[n - 2].x_latch.? += self.aff_bg[n - 2].pb; // PB is added to BGxX
|
||||||
self.aff.bg[n - 2].y_latch.? += self.aff.bg[n - 2].pd; // PD is added to BGxY
|
self.aff_bg[n - 2].y_latch.? += self.aff_bg[n - 2].pd; // PD is added to BGxY
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drawBackround(self: *Self, comptime n: u3) void {
|
fn drawBackround(self: *Self, comptime n: u3) void {
|
||||||
// A Tile in a charblock is a byte, while a Screen Entry is a halfword
|
// A Tile in a charblock is a byte, while a Screen Entry is a halfword
|
||||||
const charblock_len: u32 = 0x4000;
|
|
||||||
const screenblock_len: u32 = 0x800;
|
|
||||||
|
|
||||||
const cbb: u2 = self.bg[n].cnt.char_base.read(); // Char Block Base
|
const char_base = 0x4000 * @as(u32, self.bg[n].cnt.char_base.read());
|
||||||
const sbb: u5 = self.bg[n].cnt.screen_base.read(); // Screen Block Base
|
const screen_base = 0x800 * @as(u32, self.bg[n].cnt.screen_base.read());
|
||||||
const is_8bpp: bool = self.bg[n].cnt.colour_mode.read(); // Colour Mode
|
const is_8bpp: bool = self.bg[n].cnt.colour_mode.read(); // Colour Mode
|
||||||
const size: u2 = self.bg[n].cnt.size.read(); // Background Size
|
const size: u2 = self.bg[n].cnt.size.read(); // Background Size
|
||||||
|
|
||||||
|
@ -263,10 +261,6 @@ pub const Ppu = struct {
|
||||||
const tile_len = if (is_8bpp) @as(u32, 0x40) else 0x20;
|
const tile_len = if (is_8bpp) @as(u32, 0x40) else 0x20;
|
||||||
const tile_row_offset = if (is_8bpp) @as(u32, 0x8) else 0x4;
|
const tile_row_offset = if (is_8bpp) @as(u32, 0x8) else 0x4;
|
||||||
|
|
||||||
// 0x0600_000 is implied because we can access VRAM without the Bus
|
|
||||||
const char_base: u32 = charblock_len * @as(u32, cbb);
|
|
||||||
const screen_base: u32 = screenblock_len * @as(u32, sbb);
|
|
||||||
|
|
||||||
const vofs: u32 = self.bg[n].vofs.offset.read();
|
const vofs: u32 = self.bg[n].vofs.offset.read();
|
||||||
const hofs: u32 = self.bg[n].hofs.offset.read();
|
const hofs: u32 = self.bg[n].hofs.offset.read();
|
||||||
|
|
||||||
|
@ -286,14 +280,15 @@ pub const Ppu = struct {
|
||||||
// Calculate the Address of the Tile in the designated Charblock
|
// Calculate the Address of the Tile in the designated Charblock
|
||||||
// We also take this opportunity to flip tiles if necessary
|
// We also take this opportunity to flip tiles if necessary
|
||||||
const tile_id: u32 = entry.tile_id.read();
|
const tile_id: u32 = entry.tile_id.read();
|
||||||
const row = if (entry.v_flip.read()) 7 - (y % 8) else y % 8; // Determine on which row in a tile we're on
|
|
||||||
const tile_addr = char_base + (tile_len * tile_id) + (tile_row_offset * row);
|
|
||||||
|
|
||||||
// Calculate on which column in a tile we're on
|
// Calculate row and column offsets. Understand that
|
||||||
// Similarly to when we calculated the row, if we're in 4bpp we want to account
|
// `tile_len`, `tile_row_offset` and `col` are subject to different
|
||||||
// for 1 byte consisting of two pixels
|
// values depending on whether we are in 4bpp or 8bpp mode.
|
||||||
|
const row = @truncate(u3, y) ^ if (entry.v_flip.read()) 7 else @as(u3, 0);
|
||||||
const col = @truncate(u3, x) ^ if (entry.h_flip.read()) 7 else @as(u3, 0);
|
const col = @truncate(u3, x) ^ if (entry.h_flip.read()) 7 else @as(u3, 0);
|
||||||
const tile = self.vram.buf[tile_addr + if (is_8bpp) col else col >> 1];
|
const tile_addr = char_base + (tile_id * tile_len) + (row * tile_row_offset) + if (is_8bpp) col else col >> 1;
|
||||||
|
|
||||||
|
const tile = self.vram.buf[tile_addr];
|
||||||
|
|
||||||
// If we're in 8bpp, then the tile value is an index into the palette,
|
// If we're in 8bpp, then the tile value is an index into the palette,
|
||||||
// If we're in 4bpp, we have to account for a pal bank value in the Screen entry
|
// If we're in 4bpp, we have to account for a pal bank value in the Screen entry
|
||||||
|
@ -432,6 +427,7 @@ pub const Ppu = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Comment this + get a better understanding
|
||||||
fn tilemapOffset(size: u2, x: u32, y: u32) u32 {
|
fn tilemapOffset(size: u2, x: u32, y: u32) u32 {
|
||||||
// Current Row: (y % PIXEL_COUNT) / 8
|
// Current Row: (y % PIXEL_COUNT) / 8
|
||||||
// Current COlumn: (x % PIXEL_COUNT) / 8
|
// Current COlumn: (x % PIXEL_COUNT) / 8
|
||||||
|
@ -506,8 +502,8 @@ pub const Ppu = struct {
|
||||||
cpu.handleInterrupt();
|
cpu.handleInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.aff.bg[0].latchRefPoints();
|
self.aff_bg[0].latchRefPoints();
|
||||||
self.aff.bg[1].latchRefPoints();
|
self.aff_bg[1].latchRefPoints();
|
||||||
|
|
||||||
// See if Vblank DMA is present and not enabled
|
// See if Vblank DMA is present and not enabled
|
||||||
pollBlankingDma(&cpu.bus, .VBlank);
|
pollBlankingDma(&cpu.bus, .VBlank);
|
||||||
|
@ -695,18 +691,6 @@ const Background = struct {
|
||||||
const AffineBackground = struct {
|
const AffineBackground = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
bg: [2]AffineBackgroundRegisters,
|
|
||||||
|
|
||||||
fn init() Self {
|
|
||||||
return .{
|
|
||||||
.bg = [_]AffineBackgroundRegisters{AffineBackgroundRegisters.init()} ** 2,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const AffineBackgroundRegisters = struct {
|
|
||||||
const Self = @This();
|
|
||||||
|
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue