chore: small changes to normal background drawing code

This commit is contained in:
Rekai Nyangadzayi Musuka 2022-06-04 09:59:47 -03:00
parent ce2271100b
commit 4eb0d469b3
2 changed files with 44 additions and 60 deletions

View File

@ -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}),

View File

@ -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,