fix: replace affine bg register bitfields with signed integers
This commit is contained in:
parent
2dc3864dca
commit
b6f5517c89
|
@ -184,12 +184,12 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
||||||
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.raw = value,
|
0x0400_0028 => bus.ppu.aff.bg[0].x = @bitCast(i32, value),
|
||||||
0x0400_002C => bus.ppu.aff.bg[0].y.raw = 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.raw = value,
|
0x0400_0038 => bus.ppu.aff.bg[1].x = @bitCast(i32, value),
|
||||||
0x0400_003C => bus.ppu.aff.bg[1].y.raw = 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.raw = value,
|
0x0400_0020 => bus.ppu.aff.bg[0].pa = @bitCast(i16, value),
|
||||||
0x0400_0022 => bus.ppu.aff.bg[0].pb.raw = value,
|
0x0400_0022 => bus.ppu.aff.bg[0].pb = @bitCast(i16, value),
|
||||||
0x0400_0024 => bus.ppu.aff.bg[0].pc.raw = value,
|
0x0400_0024 => bus.ppu.aff.bg[0].pc = @bitCast(i16, value),
|
||||||
0x0400_0026 => bus.ppu.aff.bg[0].pd.raw = value,
|
0x0400_0026 => bus.ppu.aff.bg[0].pd = @bitCast(i16, value),
|
||||||
0x0400_0028 => bus.ppu.aff.bg[0].x.raw = bus.ppu.aff.bg[0].x.raw & 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.raw = bus.ppu.aff.bg[0].x.raw & 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.raw = bus.ppu.aff.bg[0].y.raw & 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.raw = bus.ppu.aff.bg[0].y.raw & 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.raw = value,
|
0x0400_0030 => bus.ppu.aff.bg[1].pa = @bitCast(i16, value),
|
||||||
0x0400_0032 => bus.ppu.aff.bg[1].pb.raw = value,
|
0x0400_0032 => bus.ppu.aff.bg[1].pb = @bitCast(i16, value),
|
||||||
0x0400_0034 => bus.ppu.aff.bg[1].pc.raw = value,
|
0x0400_0034 => bus.ppu.aff.bg[1].pc = @bitCast(i16, value),
|
||||||
0x0400_0036 => bus.ppu.aff.bg[1].pd.raw = value,
|
0x0400_0036 => bus.ppu.aff.bg[1].pd = @bitCast(i16, value),
|
||||||
0x0400_0038 => bus.ppu.aff.bg[1].x.raw = bus.ppu.aff.bg[1].x.raw & 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.raw = bus.ppu.aff.bg[1].x.raw & 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.raw = bus.ppu.aff.bg[1].y.raw & 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.raw = bus.ppu.aff.bg[1].y.raw & 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}),
|
||||||
|
@ -561,20 +561,6 @@ pub const BackgroundOffset = extern union {
|
||||||
raw: u16,
|
raw: u16,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const BackgroundRefPoint = extern union {
|
|
||||||
fractional: Bitfield(u32, 0, 8),
|
|
||||||
integer: Bitfield(u32, 8, 19),
|
|
||||||
sign: Bit(u32, 27),
|
|
||||||
raw: u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const BackgroundRotScaleParam = extern union {
|
|
||||||
fractional: Bitfield(u16, 0, 8),
|
|
||||||
integer: Bitfield(u16, 8, 7),
|
|
||||||
sign: Bit(u32, 15),
|
|
||||||
raw: u16,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Read / Write
|
/// Read / Write
|
||||||
const InterruptRequest = extern union {
|
const InterruptRequest = extern union {
|
||||||
vblank: Bit(u16, 0),
|
vblank: Bit(u16, 0),
|
||||||
|
|
55
src/ppu.zig
55
src/ppu.zig
|
@ -201,6 +201,14 @@ pub const Ppu = struct {
|
||||||
if (pal_id != 0) self.scanline_buf[@bitCast(u9, x)] = self.palette.read(u16, 0x200 + pal_id * 2);
|
if (pal_id != 0) self.scanline_buf[@bitCast(u9, x)] = self.palette.read(u16, 0x200 + pal_id * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn drawAffineBackground(self: *Self, comptime n: u3) void {
|
||||||
|
comptime std.debug.assert(n == 2 or n == 3); // Only BG2 and BG3 can be affine
|
||||||
|
|
||||||
|
// Update BG?X/Y
|
||||||
|
self.aff.bg[n - 2].x_latch += self.aff.bg[n - 2].pb >> 8;
|
||||||
|
self.aff.bg[n - 2].y_latch += self.aff.bg[n - 2].pc >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
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 charblock_len: u32 = 0x4000;
|
||||||
|
@ -458,6 +466,9 @@ pub const Ppu = struct {
|
||||||
cpu.handleInterrupt();
|
cpu.handleInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.aff.bg[0].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);
|
||||||
}
|
}
|
||||||
|
@ -656,33 +667,45 @@ const AffineBackground = struct {
|
||||||
const AffineBackgroundRegisters = struct {
|
const AffineBackgroundRegisters = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
x: io.BackgroundRefPoint,
|
x: i32,
|
||||||
y: io.BackgroundRefPoint,
|
y: i32,
|
||||||
|
|
||||||
pa: io.BackgroundRotScaleParam,
|
pa: i16,
|
||||||
pb: io.BackgroundRotScaleParam,
|
pb: i16,
|
||||||
pc: io.BackgroundRotScaleParam,
|
pc: i16,
|
||||||
pd: io.BackgroundRotScaleParam,
|
pd: i16,
|
||||||
|
|
||||||
|
x_latch: ?i32,
|
||||||
|
y_latch: ?i32,
|
||||||
|
|
||||||
fn init() Self {
|
fn init() Self {
|
||||||
return .{
|
return .{
|
||||||
.x = .{ .raw = 0 },
|
.x = 0,
|
||||||
.y = .{ .raw = 0 },
|
.y = 0,
|
||||||
.pa = .{ .raw = 0 },
|
.pa = 0,
|
||||||
.pb = .{ .raw = 0 },
|
.pb = 0,
|
||||||
.pc = .{ .raw = 0 },
|
.pc = 0,
|
||||||
.pd = .{ .raw = 0 },
|
.pd = 0,
|
||||||
|
|
||||||
|
.x_latch = null,
|
||||||
|
.y_latch = null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writePaPb(self: *Self, value: u32) void {
|
pub fn writePaPb(self: *Self, value: u32) void {
|
||||||
self.pa.raw = @truncate(u16, value);
|
self.pa = @bitCast(i16, @truncate(u16, value));
|
||||||
self.pb.raw = @truncate(u16, value >> 16);
|
self.pb = @bitCast(i16, @truncate(u16, value >> 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writePcPd(self: *Self, value: u32) void {
|
pub fn writePcPd(self: *Self, value: u32) void {
|
||||||
self.pc.raw = @truncate(u16, value);
|
self.pc = @bitCast(i16, @truncate(u16, value));
|
||||||
self.pd.raw = @truncate(u16, value >> 16);
|
self.pd = @bitCast(i16, @truncate(u16, value >> 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Vblank BG?X/Y registers are latched
|
||||||
|
fn latchRefPoints(self: *Self) void {
|
||||||
|
self.x_latch = self.x;
|
||||||
|
self.y_latch = self.y;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue