diff --git a/src/Bus.zig b/src/Bus.zig index c9a4b96..47bc644 100644 --- a/src/Bus.zig +++ b/src/Bus.zig @@ -10,7 +10,7 @@ const Iwram = @import("bus/Iwram.zig"); const Ppu = @import("ppu.zig").Ppu; const Apu = @import("apu.zig").Apu; const DmaTuple = @import("bus/dma.zig").DmaTuple; -const Timers = @import("bus/timer.zig").Timers; +const TimerTuple = @import("bus/timer.zig").TimerTuple; const Scheduler = @import("scheduler.zig").Scheduler; const FilePaths = @import("util.zig").FilePaths; @@ -19,6 +19,7 @@ const Allocator = std.mem.Allocator; const log = std.log.scoped(.Bus); const createDmaTuple = @import("bus/dma.zig").create; +const createTimerTuple = @import("bus/timer.zig").create; const rotr = @import("util.zig").rotr; const Self = @This(); @@ -27,7 +28,7 @@ bios: Bios, ppu: Ppu, apu: Apu, dma: DmaTuple, -tim: Timers, +tim: TimerTuple, iwram: Iwram, ewram: Ewram, io: Io, @@ -44,7 +45,7 @@ pub fn init(alloc: Allocator, sched: *Scheduler, paths: FilePaths) !Self { .iwram = try Iwram.init(alloc), .ewram = try Ewram.init(alloc), .dma = createDmaTuple(), - .tim = Timers.init(sched), + .tim = createTimerTuple(sched), .io = Io.init(), .cpu = null, .sched = sched, diff --git a/src/bus/io.zig b/src/bus/io.zig index d038329..6b885cb 100644 --- a/src/bus/io.zig +++ b/src/bus/io.zig @@ -52,10 +52,10 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T { 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(), - 0x0400_0104 => @as(T, bus.tim._1.cnt.raw) << 16 | bus.tim._1.counter(), - 0x0400_0108 => @as(T, bus.tim._2.cnt.raw) << 16 | bus.tim._2.counter(), - 0x0400_010C => @as(T, bus.tim._3.cnt.raw) << 16 | bus.tim._3.counter(), + 0x0400_0100 => @as(T, bus.tim[0].cnt.raw) << 16 | bus.tim[0].counter(), + 0x0400_0104 => @as(T, bus.tim[1].cnt.raw) << 16 | bus.tim[1].counter(), + 0x0400_0108 => @as(T, bus.tim[2].cnt.raw) << 16 | bus.tim[2].counter(), + 0x0400_010C => @as(T, bus.tim[3].cnt.raw) << 16 | bus.tim[3].counter(), // Serial Communication 1 0x0400_0128 => unimplementedRead("Read {} from SIOCNT and SIOMLT_SEND", .{T}), @@ -92,14 +92,14 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T { 0x0400_00DE => bus.dma[3].cnt.raw, // Timers - 0x0400_0100 => bus.tim._0.counter(), - 0x0400_0102 => bus.tim._0.cnt.raw, - 0x0400_0104 => bus.tim._1.counter(), - 0x0400_0106 => bus.tim._1.cnt.raw, - 0x0400_0108 => bus.tim._2.counter(), - 0x0400_010A => bus.tim._2.cnt.raw, - 0x0400_010C => bus.tim._3.counter(), - 0x0400_010E => bus.tim._3.cnt.raw, + 0x0400_0100 => bus.tim[0].counter(), + 0x0400_0102 => bus.tim[0].cnt.raw, + 0x0400_0104 => bus.tim[1].counter(), + 0x0400_0106 => bus.tim[1].cnt.raw, + 0x0400_0108 => bus.tim[2].counter(), + 0x0400_010A => bus.tim[2].cnt.raw, + 0x0400_010C => bus.tim[3].counter(), + 0x0400_010E => bus.tim[3].cnt.raw, // Serial Communication 1 0x0400_0128 => unimplementedRead("Read {} from SIOCNT", .{T}), @@ -214,10 +214,10 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void { 0x0400_00E0...0x0400_00FC => {}, // Unused // Timers - 0x0400_0100 => bus.tim._0.writeCnt(value), - 0x0400_0104 => bus.tim._1.writeCnt(value), - 0x0400_0108 => bus.tim._2.writeCnt(value), - 0x0400_010C => bus.tim._3.writeCnt(value), + 0x0400_0100 => bus.tim[0].writeCnt(value), + 0x0400_0104 => bus.tim[1].writeCnt(value), + 0x0400_0108 => bus.tim[2].writeCnt(value), + 0x0400_010C => bus.tim[3].writeCnt(value), 0x0400_0110...0x0400_011C => {}, // Unused // Serial Communication 1 @@ -339,14 +339,14 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void { 0x0400_00DE => bus.dma[3].writeCntHigh(value), // Timers - 0x0400_0100 => bus.tim._0.setReload(value), - 0x0400_0102 => bus.tim._0.writeCntHigh(value), - 0x0400_0104 => bus.tim._1.setReload(value), - 0x0400_0106 => bus.tim._1.writeCntHigh(value), - 0x0400_0108 => bus.tim._2.setReload(value), - 0x0400_010A => bus.tim._2.writeCntHigh(value), - 0x0400_010C => bus.tim._3.setReload(value), - 0x0400_010E => bus.tim._3.writeCntHigh(value), + 0x0400_0100 => bus.tim[0].setReload(value), + 0x0400_0102 => bus.tim[0].writeCntHigh(value), + 0x0400_0104 => bus.tim[1].setReload(value), + 0x0400_0106 => bus.tim[1].writeCntHigh(value), + 0x0400_0108 => bus.tim[2].setReload(value), + 0x0400_010A => bus.tim[2].writeCntHigh(value), + 0x0400_010C => bus.tim[3].setReload(value), + 0x0400_010E => bus.tim[3].writeCntHigh(value), 0x0400_0114 => {}, // TODO: Gyakuten Saiban writes 0x8000 to 0x0400_0114 0x0400_0110 => {}, // Not Used, diff --git a/src/bus/timer.zig b/src/bus/timer.zig index cabc4a6..6111fda 100644 --- a/src/bus/timer.zig +++ b/src/bus/timer.zig @@ -6,25 +6,12 @@ const Scheduler = @import("../scheduler.zig").Scheduler; const Event = @import("../scheduler.zig").Event; const Arm7tdmi = @import("../cpu.zig").Arm7tdmi; +pub const TimerTuple = std.meta.Tuple(&[_]type{ Timer(0), Timer(1), Timer(2), Timer(3) }); const log = std.log.scoped(.Timer); -pub const Timers = struct { - const Self = @This(); - - _0: Timer(0), - _1: Timer(1), - _2: Timer(2), - _3: Timer(3), - - pub fn init(sched: *Scheduler) Self { - return .{ - ._0 = Timer(0).init(sched), - ._1 = Timer(1).init(sched), - ._2 = Timer(2).init(sched), - ._3 = Timer(3).init(sched), - }; - } -}; +pub fn create(sched: *Scheduler) TimerTuple { + return .{ Timer(0).init(sched), Timer(1).init(sched), Timer(2).init(sched), Timer(3).init(sched) }; +} fn Timer(comptime id: u2) type { return struct { @@ -94,7 +81,6 @@ fn Timer(comptime id: u2) type { pub fn handleOverflow(self: *Self, cpu: *Arm7tdmi, late: u64) void { // Fire IRQ if enabled const io = &cpu.bus.io; - const tim = &cpu.bus.tim; if (self.cnt.irq.read()) { switch (id) { @@ -114,17 +100,17 @@ fn Timer(comptime id: u2) type { // Perform Cascade Behaviour switch (id) { - 0 => if (tim._1.cnt.cascade.read()) { - tim._1._counter +%= 1; - if (tim._1._counter == 0) tim._1.handleOverflow(cpu, late); + 0 => if (cpu.bus.tim[1].cnt.cascade.read()) { + cpu.bus.tim[1]._counter +%= 1; + if (cpu.bus.tim[1]._counter == 0) cpu.bus.tim[1].handleOverflow(cpu, late); }, - 1 => if (tim._2.cnt.cascade.read()) { - tim._2._counter +%= 1; - if (tim._2._counter == 0) tim._2.handleOverflow(cpu, late); + 1 => if (cpu.bus.tim[2].cnt.cascade.read()) { + cpu.bus.tim[2]._counter +%= 1; + if (cpu.bus.tim[2]._counter == 0) cpu.bus.tim[2].handleOverflow(cpu, late); }, - 2 => if (tim._3.cnt.cascade.read()) { - tim._3._counter +%= 1; - if (tim._3._counter == 0) tim._3.handleOverflow(cpu, late); + 2 => if (cpu.bus.tim[3].cnt.cascade.read()) { + cpu.bus.tim[3]._counter +%= 1; + if (cpu.bus.tim[3]._counter == 0) cpu.bus.tim[3].handleOverflow(cpu, late); }, 3 => {}, // There is no Timer for TIM3 to "cascade" to, } diff --git a/src/scheduler.zig b/src/scheduler.zig index c3cb707..8b9a4e4 100644 --- a/src/scheduler.zig +++ b/src/scheduler.zig @@ -45,10 +45,10 @@ pub const Scheduler = struct { }, .TimerOverflow => |id| { switch (id) { - 0 => cpu.bus.tim._0.handleOverflow(cpu, late), - 1 => cpu.bus.tim._1.handleOverflow(cpu, late), - 2 => cpu.bus.tim._2.handleOverflow(cpu, late), - 3 => cpu.bus.tim._3.handleOverflow(cpu, late), + 0 => cpu.bus.tim[0].handleOverflow(cpu, late), + 1 => cpu.bus.tim[1].handleOverflow(cpu, late), + 2 => cpu.bus.tim[2].handleOverflow(cpu, late), + 3 => cpu.bus.tim[3].handleOverflow(cpu, late), } }, .ApuChannel => |id| {