diff --git a/src/Bus.zig b/src/Bus.zig index d05d30a..c9a4b96 100644 --- a/src/Bus.zig +++ b/src/Bus.zig @@ -9,7 +9,7 @@ const Io = @import("bus/io.zig").Io; const Iwram = @import("bus/Iwram.zig"); const Ppu = @import("ppu.zig").Ppu; const Apu = @import("apu.zig").Apu; -const DmaControllers = @import("bus/dma.zig").DmaControllers; +const DmaTuple = @import("bus/dma.zig").DmaTuple; const Timers = @import("bus/timer.zig").Timers; const Scheduler = @import("scheduler.zig").Scheduler; const FilePaths = @import("util.zig").FilePaths; @@ -18,6 +18,7 @@ const io = @import("bus/io.zig"); const Allocator = std.mem.Allocator; const log = std.log.scoped(.Bus); +const createDmaTuple = @import("bus/dma.zig").create; const rotr = @import("util.zig").rotr; const Self = @This(); @@ -25,7 +26,7 @@ pak: GamePak, bios: Bios, ppu: Ppu, apu: Apu, -dma: DmaControllers, +dma: DmaTuple, tim: Timers, iwram: Iwram, ewram: Ewram, @@ -42,7 +43,7 @@ pub fn init(alloc: Allocator, sched: *Scheduler, paths: FilePaths) !Self { .apu = Apu.init(sched), .iwram = try Iwram.init(alloc), .ewram = try Ewram.init(alloc), - .dma = DmaControllers.init(), + .dma = createDmaTuple(), .tim = Timers.init(sched), .io = Io.init(), .cpu = null, @@ -64,18 +65,18 @@ pub fn attach(self: *Self, cpu: *Arm7tdmi) void { pub fn handleDMATransfers(self: *Self) void { while (self.isDmaRunning()) { - if (self.dma._1.step(self)) continue; - if (self.dma._0.step(self)) continue; - if (self.dma._2.step(self)) continue; - if (self.dma._3.step(self)) continue; + if (self.dma[1].step(self)) continue; + if (self.dma[0].step(self)) continue; + if (self.dma[2].step(self)) continue; + if (self.dma[3].step(self)) continue; } } inline fn isDmaRunning(self: *const Self) bool { - return self.dma._0.active or - self.dma._1.active or - self.dma._2.active or - self.dma._3.active; + return self.dma[0].active or + self.dma[1].active or + self.dma[2].active or + self.dma[3].active; } pub fn debugRead(self: *const Self, comptime T: type, address: u32) T { @@ -173,7 +174,7 @@ pub fn write(self: *Self, comptime T: type, address: u32, value: T) void { 0x07 => self.ppu.oam.write(T, align_addr, value), // External Memory (Game Pak) - 0x08...0x0D => self.pak.write(T, self.dma._3.word_count, align_addr, value), + 0x08...0x0D => self.pak.write(T, self.dma[3].word_count, align_addr, value), 0x0E...0x0F => { const rotate_by = switch (T) { u32 => address & 3, diff --git a/src/apu.zig b/src/apu.zig index c130ef7..176eece 100644 --- a/src/apu.zig +++ b/src/apu.zig @@ -263,12 +263,12 @@ pub const Apu = struct { if (@boolToInt(self.dma_cnt.chA_timer.read()) == tim_id) { self.chA.updateSample(); - if (self.chA.len() <= 15) cpu.bus.dma._1.enableSoundDma(0x0400_00A0); + if (self.chA.len() <= 15) cpu.bus.dma[1].enableSoundDma(0x0400_00A0); } if (@boolToInt(self.dma_cnt.chB_timer.read()) == tim_id) { self.chB.updateSample(); - if (self.chB.len() <= 15) cpu.bus.dma._2.enableSoundDma(0x0400_00A4); + if (self.chB.len() <= 15) cpu.bus.dma[2].enableSoundDma(0x0400_00A4); } } diff --git a/src/bus/dma.zig b/src/bus/dma.zig index a891bd6..565a569 100644 --- a/src/bus/dma.zig +++ b/src/bus/dma.zig @@ -3,25 +3,12 @@ const std = @import("std"); const DmaControl = @import("io.zig").DmaControl; const Bus = @import("../Bus.zig"); +pub const DmaTuple = std.meta.Tuple(&[_]type{ DmaController(0), DmaController(1), DmaController(2), DmaController(3) }); const log = std.log.scoped(.DmaTransfer); -pub const DmaControllers = struct { - const Self = @This(); - - _0: DmaController(0), - _1: DmaController(1), - _2: DmaController(2), - _3: DmaController(3), - - pub fn init() Self { - return .{ - ._0 = DmaController(0).init(), - ._1 = DmaController(1).init(), - ._2 = DmaController(2).init(), - ._3 = DmaController(3).init(), - }; - } -}; +pub fn create() DmaTuple { + return .{ DmaController(0).init(), DmaController(1).init(), DmaController(2).init(), DmaController(3).init() }; +} /// Function that creates a DMAController. Determines unique DMA Controller behaiour at compile-time fn DmaController(comptime id: u2) type { @@ -228,10 +215,10 @@ fn DmaController(comptime id: u2) type { } pub fn pollBlankingDma(bus: *Bus, comptime kind: DmaKind) void { - bus.dma._0.pollBlankingDma(kind); - bus.dma._1.pollBlankingDma(kind); - bus.dma._2.pollBlankingDma(kind); - bus.dma._3.pollBlankingDma(kind); + bus.dma[0].pollBlankingDma(kind); + bus.dma[1].pollBlankingDma(kind); + bus.dma[2].pollBlankingDma(kind); + bus.dma[3].pollBlankingDma(kind); } const Adjustment = enum(u2) { diff --git a/src/bus/io.zig b/src/bus/io.zig index 0880613..d038329 100644 --- a/src/bus/io.zig +++ b/src/bus/io.zig @@ -46,10 +46,10 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T { 0x0400_0006 => @as(T, bus.ppu.bg[0].cnt.raw) << 16 | bus.ppu.vcount.raw, // DMA Transfers - 0x0400_00B8 => @as(T, bus.dma._0.cnt.raw) << 16, - 0x0400_00C4 => @as(T, bus.dma._1.cnt.raw) << 16, - 0x0400_00D0 => @as(T, bus.dma._1.cnt.raw) << 16, - 0x0400_00DC => @as(T, bus.dma._3.cnt.raw) << 16, + 0x0400_00B8 => @as(T, bus.dma[0].cnt.raw) << 16, + 0x0400_00C4 => @as(T, bus.dma[1].cnt.raw) << 16, + 0x0400_00D0 => @as(T, bus.dma[1].cnt.raw) << 16, + 0x0400_00DC => @as(T, bus.dma[3].cnt.raw) << 16, // Timers 0x0400_0100 => @as(T, bus.tim._0.cnt.raw) << 16 | bus.tim._0.counter(), @@ -86,10 +86,10 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T { 0x0400_0088 => bus.apu.bias.raw, // DMA Transfers - 0x0400_00BA => bus.dma._0.cnt.raw, - 0x0400_00C6 => bus.dma._1.cnt.raw, - 0x0400_00D2 => bus.dma._2.cnt.raw, - 0x0400_00DE => bus.dma._3.cnt.raw, + 0x0400_00BA => bus.dma[0].cnt.raw, + 0x0400_00C6 => bus.dma[1].cnt.raw, + 0x0400_00D2 => bus.dma[2].cnt.raw, + 0x0400_00DE => bus.dma[3].cnt.raw, // Timers 0x0400_0100 => bus.tim._0.counter(), @@ -199,18 +199,18 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void { 0x0400_00A8, 0x0400_00AC => {}, // Unused // DMA Transfers - 0x0400_00B0 => bus.dma._0.writeSad(value), - 0x0400_00B4 => bus.dma._0.writeDad(value), - 0x0400_00B8 => bus.dma._0.writeCnt(value), - 0x0400_00BC => bus.dma._1.writeSad(value), - 0x0400_00C0 => bus.dma._1.writeDad(value), - 0x0400_00C4 => bus.dma._1.writeCnt(value), - 0x0400_00C8 => bus.dma._2.writeSad(value), - 0x0400_00CC => bus.dma._2.writeDad(value), - 0x0400_00D0 => bus.dma._2.writeCnt(value), - 0x0400_00D4 => bus.dma._3.writeSad(value), - 0x0400_00D8 => bus.dma._3.writeDad(value), - 0x0400_00DC => bus.dma._3.writeCnt(value), + 0x0400_00B0 => bus.dma[0].writeSad(value), + 0x0400_00B4 => bus.dma[0].writeDad(value), + 0x0400_00B8 => bus.dma[0].writeCnt(value), + 0x0400_00BC => bus.dma[1].writeSad(value), + 0x0400_00C0 => bus.dma[1].writeDad(value), + 0x0400_00C4 => bus.dma[1].writeCnt(value), + 0x0400_00C8 => bus.dma[2].writeSad(value), + 0x0400_00CC => bus.dma[2].writeDad(value), + 0x0400_00D0 => bus.dma[2].writeCnt(value), + 0x0400_00D4 => bus.dma[3].writeSad(value), + 0x0400_00D8 => bus.dma[3].writeDad(value), + 0x0400_00DC => bus.dma[3].writeCnt(value), 0x0400_00E0...0x0400_00FC => {}, // Unused // Timers @@ -310,33 +310,33 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void { 0x0400_0090...0x0400_009F => bus.apu.ch3.wave_dev.write(T, bus.apu.ch3.select, address, value), // Dma Transfers - 0x0400_00B0 => bus.dma._0.writeSad(bus.dma._0.sad & 0xFFFF_0000 | value), - 0x0400_00B2 => bus.dma._0.writeSad(bus.dma._0.sad & 0x0000_FFFF | (@as(u32, value) << 16)), - 0x0400_00B4 => bus.dma._0.writeDad(bus.dma._0.dad & 0xFFFF_0000 | value), - 0x0400_00B6 => bus.dma._0.writeDad(bus.dma._0.dad & 0x0000_FFFF | (@as(u32, value) << 16)), - 0x0400_00B8 => bus.dma._0.writeWordCount(value), - 0x0400_00BA => bus.dma._0.writeCntHigh(value), + 0x0400_00B0 => bus.dma[0].writeSad(bus.dma[0].sad & 0xFFFF_0000 | value), + 0x0400_00B2 => bus.dma[0].writeSad(bus.dma[0].sad & 0x0000_FFFF | (@as(u32, value) << 16)), + 0x0400_00B4 => bus.dma[0].writeDad(bus.dma[0].dad & 0xFFFF_0000 | value), + 0x0400_00B6 => bus.dma[0].writeDad(bus.dma[0].dad & 0x0000_FFFF | (@as(u32, value) << 16)), + 0x0400_00B8 => bus.dma[0].writeWordCount(value), + 0x0400_00BA => bus.dma[0].writeCntHigh(value), - 0x0400_00BC => bus.dma._1.writeSad(bus.dma._1.sad & 0xFFFF_0000 | value), - 0x0400_00BE => bus.dma._1.writeSad(bus.dma._1.sad & 0x0000_FFFF | (@as(u32, value) << 16)), - 0x0400_00C0 => bus.dma._1.writeDad(bus.dma._1.dad & 0xFFFF_0000 | value), - 0x0400_00C2 => bus.dma._1.writeDad(bus.dma._1.dad & 0x0000_FFFF | (@as(u32, value) << 16)), - 0x0400_00C4 => bus.dma._1.writeWordCount(value), - 0x0400_00C6 => bus.dma._1.writeCntHigh(value), + 0x0400_00BC => bus.dma[1].writeSad(bus.dma[1].sad & 0xFFFF_0000 | value), + 0x0400_00BE => bus.dma[1].writeSad(bus.dma[1].sad & 0x0000_FFFF | (@as(u32, value) << 16)), + 0x0400_00C0 => bus.dma[1].writeDad(bus.dma[1].dad & 0xFFFF_0000 | value), + 0x0400_00C2 => bus.dma[1].writeDad(bus.dma[1].dad & 0x0000_FFFF | (@as(u32, value) << 16)), + 0x0400_00C4 => bus.dma[1].writeWordCount(value), + 0x0400_00C6 => bus.dma[1].writeCntHigh(value), - 0x0400_00C8 => bus.dma._2.writeSad(bus.dma._2.sad & 0xFFFF_0000 | value), - 0x0400_00CA => bus.dma._2.writeSad(bus.dma._2.sad & 0x0000_FFFF | (@as(u32, value) << 16)), - 0x0400_00CC => bus.dma._2.writeDad(bus.dma._2.dad & 0xFFFF_0000 | value), - 0x0400_00CE => bus.dma._2.writeDad(bus.dma._2.dad & 0x0000_FFFF | (@as(u32, value) << 16)), - 0x0400_00D0 => bus.dma._2.writeWordCount(value), - 0x0400_00D2 => bus.dma._2.writeCntHigh(value), + 0x0400_00C8 => bus.dma[2].writeSad(bus.dma[2].sad & 0xFFFF_0000 | value), + 0x0400_00CA => bus.dma[2].writeSad(bus.dma[2].sad & 0x0000_FFFF | (@as(u32, value) << 16)), + 0x0400_00CC => bus.dma[2].writeDad(bus.dma[2].dad & 0xFFFF_0000 | value), + 0x0400_00CE => bus.dma[2].writeDad(bus.dma[2].dad & 0x0000_FFFF | (@as(u32, value) << 16)), + 0x0400_00D0 => bus.dma[2].writeWordCount(value), + 0x0400_00D2 => bus.dma[2].writeCntHigh(value), - 0x0400_00D4 => bus.dma._3.writeSad(bus.dma._3.sad & 0xFFFF_0000 | value), - 0x0400_00D6 => bus.dma._3.writeSad(bus.dma._3.sad & 0x0000_FFFF | (@as(u32, value) << 16)), - 0x0400_00D8 => bus.dma._3.writeDad(bus.dma._3.dad & 0xFFFF_0000 | value), - 0x0400_00DA => bus.dma._3.writeDad(bus.dma._3.dad & 0x0000_FFFF | (@as(u32, value) << 16)), - 0x0400_00DC => bus.dma._3.writeWordCount(value), - 0x0400_00DE => bus.dma._3.writeCntHigh(value), + 0x0400_00D4 => bus.dma[3].writeSad(bus.dma[3].sad & 0xFFFF_0000 | value), + 0x0400_00D6 => bus.dma[3].writeSad(bus.dma[3].sad & 0x0000_FFFF | (@as(u32, value) << 16)), + 0x0400_00D8 => bus.dma[3].writeDad(bus.dma[3].dad & 0xFFFF_0000 | value), + 0x0400_00DA => bus.dma[3].writeDad(bus.dma[3].dad & 0x0000_FFFF | (@as(u32, value) << 16)), + 0x0400_00DC => bus.dma[3].writeWordCount(value), + 0x0400_00DE => bus.dma[3].writeCntHigh(value), // Timers 0x0400_0100 => bus.tim._0.setReload(value),