diff --git a/src/bus/io.zig b/src/bus/io.zig index 0fdd28b..019c59d 100644 --- a/src/bus/io.zig +++ b/src/bus/io.zig @@ -172,14 +172,14 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void { 0x0400_0014 => bus.ppu.setBgOffsets(1, value), 0x0400_0018 => bus.ppu.setBgOffsets(2, value), 0x0400_001C => bus.ppu.setBgOffsets(3, value), - 0x0400_0020 => log.debug("Wrote 0x{X:0>8} to BG2PA and BG2PB", .{value}), - 0x0400_0024 => log.debug("Wrote 0x{X:0>8} to BG2PC and BG2PD", .{value}), - 0x0400_0028 => log.debug("Wrote 0x{X:0>8} to BG2X", .{value}), - 0x0400_002C => log.debug("Wrote 0x{X:0>8} to BG2Y", .{value}), - 0x0400_0030 => log.debug("Wrote 0x{X:0>8} to BG3PA and BG3PB", .{value}), - 0x0400_0034 => log.debug("Wrote 0x{X:0>8} to BG3PC and BG3PD", .{value}), - 0x0400_0038 => log.debug("Wrote 0x{X:0>8} to BG3X", .{value}), - 0x0400_003C => log.debug("Wrote 0x{X:0>8} to BG3Y", .{value}), + 0x0400_0020 => bus.ppu.aff.bg[0].writePaPb(value), + 0x0400_0024 => bus.ppu.aff.bg[0].writePcPd(value), + 0x0400_0028 => bus.ppu.aff.bg[0].x.raw = value, + 0x0400_002C => bus.ppu.aff.bg[0].y.raw = value, + 0x0400_0030 => bus.ppu.aff.bg[1].writePaPb(value), + 0x0400_0034 => bus.ppu.aff.bg[1].writePcPd(value), + 0x0400_0038 => bus.ppu.aff.bg[1].x.raw = value, + 0x0400_003C => bus.ppu.aff.bg[1].y.raw = 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_0048 => log.debug("Wrote 0x{X:0>8} to WININ and WINOUT", .{value}), @@ -260,22 +260,22 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void { 0x0400_001A => bus.ppu.bg[2].vofs.raw = value, 0x0400_001C => bus.ppu.bg[3].hofs.raw = value, 0x0400_001E => bus.ppu.bg[3].vofs.raw = value, - 0x0400_0020 => log.debug("Wrote 0x{X:0>4} to BG2PA", .{value}), - 0x0400_0022 => log.debug("Wrote 0x{X:0>4} to BG2PB", .{value}), - 0x0400_0024 => log.debug("Wrote 0x{X:0>4} to BG2PC", .{value}), - 0x0400_0026 => log.debug("Wrote 0x{X:0>4} to BG2PD", .{value}), - 0x0400_0028 => log.debug("Wrote 0x{X:0>4} to BG2X_L", .{value}), - 0x0400_002A => log.debug("Wrote 0x{X:0>4} to BG2X_H", .{value}), - 0x0400_002C => log.debug("Wrote 0x{X:0>4} to BG2Y_L", .{value}), - 0x0400_002E => log.debug("Wrote 0x{X:0>4} to BG2Y_H", .{value}), - 0x0400_0030 => log.debug("Wrote 0x{X:0>4} to BG3PA", .{value}), - 0x0400_0032 => log.debug("Wrote 0x{X:0>4} to BG3PB", .{value}), - 0x0400_0034 => log.debug("Wrote 0x{X:0>4} to BG3PC", .{value}), - 0x0400_0036 => log.debug("Wrote 0x{X:0>4} to BG3PD", .{value}), - 0x0400_0038 => log.debug("Wrote 0x{X:0>4} to BG3X_L", .{value}), - 0x0400_003A => log.debug("Wrote 0x{X:0>4} to BG3X_H", .{value}), - 0x0400_003C => log.debug("Wrote 0x{X:0>4} to BG3Y_L", .{value}), - 0x0400_003E => log.debug("Wrote 0x{X:0>4} to BG3Y_H", .{value}), + 0x0400_0020 => bus.ppu.aff.bg[0].pa.raw = value, + 0x0400_0022 => bus.ppu.aff.bg[0].pb.raw = value, + 0x0400_0024 => bus.ppu.aff.bg[0].pc.raw = value, + 0x0400_0026 => bus.ppu.aff.bg[0].pd.raw = value, + 0x0400_0028 => bus.ppu.aff.bg[0].x.raw = bus.ppu.aff.bg[0].x.raw & 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_002C => bus.ppu.aff.bg[0].y.raw = bus.ppu.aff.bg[0].y.raw & 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_0030 => bus.ppu.aff.bg[1].pa.raw = value, + 0x0400_0032 => bus.ppu.aff.bg[1].pb.raw = value, + 0x0400_0034 => bus.ppu.aff.bg[1].pc.raw = value, + 0x0400_0036 => bus.ppu.aff.bg[1].pd.raw = value, + 0x0400_0038 => bus.ppu.aff.bg[1].x.raw = bus.ppu.aff.bg[1].x.raw & 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_003C => bus.ppu.aff.bg[1].y.raw = bus.ppu.aff.bg[1].y.raw & 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_0040 => log.debug("Wrote 0x{X:0>4} to WIN0H", .{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}), @@ -551,6 +551,20 @@ pub const BackgroundOffset = extern union { 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 const InterruptRequest = extern union { vblank: Bit(u16, 0), diff --git a/src/ppu.zig b/src/ppu.zig index 1238dd9..06a4d4f 100644 --- a/src/ppu.zig +++ b/src/ppu.zig @@ -26,6 +26,7 @@ pub const Ppu = struct { // Registers bg: [4]Background, + aff: AffineBackground, dispcnt: io.DisplayControl, dispstat: io.DisplayStatus, @@ -58,6 +59,7 @@ pub const Ppu = struct { // Registers .bg = [_]Background{Background.init()} ** 4, + .aff = AffineBackground.init(), .dispcnt = .{ .raw = 0x0000 }, .dispstat = .{ .raw = 0x0000 }, .vcount = .{ .raw = 0x0000 }, @@ -679,6 +681,51 @@ const Background = struct { } }; +const AffineBackground = struct { + const Self = @This(); + + bg: [2]AffineBackgroundRegisters, + + fn init() Self { + return .{ + .bg = [_]AffineBackgroundRegisters{AffineBackgroundRegisters.init()} ** 2, + }; + } +}; + +const AffineBackgroundRegisters = struct { + const Self = @This(); + + x: io.BackgroundRefPoint, + y: io.BackgroundRefPoint, + + pa: io.BackgroundRotScaleParam, + pb: io.BackgroundRotScaleParam, + pc: io.BackgroundRotScaleParam, + pd: io.BackgroundRotScaleParam, + + fn init() Self { + return .{ + .x = .{ .raw = 0 }, + .y = .{ .raw = 0 }, + .pa = .{ .raw = 0 }, + .pb = .{ .raw = 0 }, + .pc = .{ .raw = 0 }, + .pd = .{ .raw = 0 }, + }; + } + + pub fn writePaPb(self: *Self, value: u32) void { + self.pa.raw = @truncate(u16, value); + self.pb.raw = @truncate(u16, value >> 16); + } + + pub fn writePcPd(self: *Self, value: u32) void { + self.pc.raw = @truncate(u16, value); + self.pd.raw = @truncate(u16, value >> 16); + } +}; + const ScreenEntry = extern union { tile_id: Bitfield(u16, 0, 10), h_flip: Bit(u16, 10),