Compare commits
2 Commits
c0e026b9a8
...
d5443d9c2f
Author | SHA1 | Date |
---|---|---|
Rekai Nyangadzayi Musuka | d5443d9c2f | |
Rekai Nyangadzayi Musuka | f0ce39230b |
32
src/Bus.zig
32
src/Bus.zig
|
@ -9,8 +9,8 @@ const Io = @import("bus/io.zig").Io;
|
||||||
const Iwram = @import("bus/Iwram.zig");
|
const Iwram = @import("bus/Iwram.zig");
|
||||||
const Ppu = @import("ppu.zig").Ppu;
|
const Ppu = @import("ppu.zig").Ppu;
|
||||||
const Apu = @import("apu.zig").Apu;
|
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 TimerTuple = @import("bus/timer.zig").TimerTuple;
|
||||||
const Scheduler = @import("scheduler.zig").Scheduler;
|
const Scheduler = @import("scheduler.zig").Scheduler;
|
||||||
const FilePaths = @import("util.zig").FilePaths;
|
const FilePaths = @import("util.zig").FilePaths;
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ const io = @import("bus/io.zig");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const log = std.log.scoped(.Bus);
|
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 rotr = @import("util.zig").rotr;
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
@ -25,8 +27,8 @@ pak: GamePak,
|
||||||
bios: Bios,
|
bios: Bios,
|
||||||
ppu: Ppu,
|
ppu: Ppu,
|
||||||
apu: Apu,
|
apu: Apu,
|
||||||
dma: DmaControllers,
|
dma: DmaTuple,
|
||||||
tim: Timers,
|
tim: TimerTuple,
|
||||||
iwram: Iwram,
|
iwram: Iwram,
|
||||||
ewram: Ewram,
|
ewram: Ewram,
|
||||||
io: Io,
|
io: Io,
|
||||||
|
@ -42,8 +44,8 @@ pub fn init(alloc: Allocator, sched: *Scheduler, paths: FilePaths) !Self {
|
||||||
.apu = Apu.init(sched),
|
.apu = Apu.init(sched),
|
||||||
.iwram = try Iwram.init(alloc),
|
.iwram = try Iwram.init(alloc),
|
||||||
.ewram = try Ewram.init(alloc),
|
.ewram = try Ewram.init(alloc),
|
||||||
.dma = DmaControllers.init(),
|
.dma = createDmaTuple(),
|
||||||
.tim = Timers.init(sched),
|
.tim = createTimerTuple(sched),
|
||||||
.io = Io.init(),
|
.io = Io.init(),
|
||||||
.cpu = null,
|
.cpu = null,
|
||||||
.sched = sched,
|
.sched = sched,
|
||||||
|
@ -64,18 +66,18 @@ pub fn attach(self: *Self, cpu: *Arm7tdmi) void {
|
||||||
|
|
||||||
pub fn handleDMATransfers(self: *Self) void {
|
pub fn handleDMATransfers(self: *Self) void {
|
||||||
while (self.isDmaRunning()) {
|
while (self.isDmaRunning()) {
|
||||||
if (self.dma._1.step(self)) continue;
|
if (self.dma[1].step(self)) continue;
|
||||||
if (self.dma._0.step(self)) continue;
|
if (self.dma[0].step(self)) continue;
|
||||||
if (self.dma._2.step(self)) continue;
|
if (self.dma[2].step(self)) continue;
|
||||||
if (self.dma._3.step(self)) continue;
|
if (self.dma[3].step(self)) continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn isDmaRunning(self: *const Self) bool {
|
inline fn isDmaRunning(self: *const Self) bool {
|
||||||
return self.dma._0.active or
|
return self.dma[0].active or
|
||||||
self.dma._1.active or
|
self.dma[1].active or
|
||||||
self.dma._2.active or
|
self.dma[2].active or
|
||||||
self.dma._3.active;
|
self.dma[3].active;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debugRead(self: *const Self, comptime T: type, address: u32) T {
|
pub fn debugRead(self: *const Self, comptime T: type, address: u32) T {
|
||||||
|
@ -173,7 +175,7 @@ pub fn write(self: *Self, comptime T: type, address: u32, value: T) void {
|
||||||
0x07 => self.ppu.oam.write(T, align_addr, value),
|
0x07 => self.ppu.oam.write(T, align_addr, value),
|
||||||
|
|
||||||
// External Memory (Game Pak)
|
// 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 => {
|
0x0E...0x0F => {
|
||||||
const rotate_by = switch (T) {
|
const rotate_by = switch (T) {
|
||||||
u32 => address & 3,
|
u32 => address & 3,
|
||||||
|
|
|
@ -263,12 +263,12 @@ pub const Apu = struct {
|
||||||
|
|
||||||
if (@boolToInt(self.dma_cnt.chA_timer.read()) == tim_id) {
|
if (@boolToInt(self.dma_cnt.chA_timer.read()) == tim_id) {
|
||||||
self.chA.updateSample();
|
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) {
|
if (@boolToInt(self.dma_cnt.chB_timer.read()) == tim_id) {
|
||||||
self.chB.updateSample();
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,25 +3,12 @@ const std = @import("std");
|
||||||
const DmaControl = @import("io.zig").DmaControl;
|
const DmaControl = @import("io.zig").DmaControl;
|
||||||
const Bus = @import("../Bus.zig");
|
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);
|
const log = std.log.scoped(.DmaTransfer);
|
||||||
|
|
||||||
pub const DmaControllers = struct {
|
pub fn create() DmaTuple {
|
||||||
const Self = @This();
|
return .{ DmaController(0).init(), DmaController(1).init(), DmaController(2).init(), DmaController(3).init() };
|
||||||
|
|
||||||
_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(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
/// Function that creates a DMAController. Determines unique DMA Controller behaiour at compile-time
|
/// Function that creates a DMAController. Determines unique DMA Controller behaiour at compile-time
|
||||||
fn DmaController(comptime id: u2) type {
|
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 {
|
pub fn pollBlankingDma(bus: *Bus, comptime kind: DmaKind) void {
|
||||||
bus.dma._0.pollBlankingDma(kind);
|
bus.dma[0].pollBlankingDma(kind);
|
||||||
bus.dma._1.pollBlankingDma(kind);
|
bus.dma[1].pollBlankingDma(kind);
|
||||||
bus.dma._2.pollBlankingDma(kind);
|
bus.dma[2].pollBlankingDma(kind);
|
||||||
bus.dma._3.pollBlankingDma(kind);
|
bus.dma[3].pollBlankingDma(kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Adjustment = enum(u2) {
|
const Adjustment = enum(u2) {
|
||||||
|
|
136
src/bus/io.zig
136
src/bus/io.zig
|
@ -46,16 +46,16 @@ 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,
|
0x0400_0006 => @as(T, bus.ppu.bg[0].cnt.raw) << 16 | bus.ppu.vcount.raw,
|
||||||
|
|
||||||
// DMA Transfers
|
// DMA Transfers
|
||||||
0x0400_00B8 => @as(T, bus.dma._0.cnt.raw) << 16,
|
0x0400_00B8 => @as(T, bus.dma[0].cnt.raw) << 16,
|
||||||
0x0400_00C4 => @as(T, bus.dma._1.cnt.raw) << 16,
|
0x0400_00C4 => @as(T, bus.dma[1].cnt.raw) << 16,
|
||||||
0x0400_00D0 => @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_00DC => @as(T, bus.dma[3].cnt.raw) << 16,
|
||||||
|
|
||||||
// Timers
|
// Timers
|
||||||
0x0400_0100 => @as(T, bus.tim._0.cnt.raw) << 16 | bus.tim._0.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_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_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_010C => @as(T, bus.tim[3].cnt.raw) << 16 | bus.tim[3].counter(),
|
||||||
|
|
||||||
// Serial Communication 1
|
// Serial Communication 1
|
||||||
0x0400_0128 => unimplementedRead("Read {} from SIOCNT and SIOMLT_SEND", .{T}),
|
0x0400_0128 => unimplementedRead("Read {} from SIOCNT and SIOMLT_SEND", .{T}),
|
||||||
|
@ -86,20 +86,20 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T {
|
||||||
0x0400_0088 => bus.apu.bias.raw,
|
0x0400_0088 => bus.apu.bias.raw,
|
||||||
|
|
||||||
// DMA Transfers
|
// DMA Transfers
|
||||||
0x0400_00BA => bus.dma._0.cnt.raw,
|
0x0400_00BA => bus.dma[0].cnt.raw,
|
||||||
0x0400_00C6 => bus.dma._1.cnt.raw,
|
0x0400_00C6 => bus.dma[1].cnt.raw,
|
||||||
0x0400_00D2 => bus.dma._2.cnt.raw,
|
0x0400_00D2 => bus.dma[2].cnt.raw,
|
||||||
0x0400_00DE => bus.dma._3.cnt.raw,
|
0x0400_00DE => bus.dma[3].cnt.raw,
|
||||||
|
|
||||||
// Timers
|
// Timers
|
||||||
0x0400_0100 => bus.tim._0.counter(),
|
0x0400_0100 => bus.tim[0].counter(),
|
||||||
0x0400_0102 => bus.tim._0.cnt.raw,
|
0x0400_0102 => bus.tim[0].cnt.raw,
|
||||||
0x0400_0104 => bus.tim._1.counter(),
|
0x0400_0104 => bus.tim[1].counter(),
|
||||||
0x0400_0106 => bus.tim._1.cnt.raw,
|
0x0400_0106 => bus.tim[1].cnt.raw,
|
||||||
0x0400_0108 => bus.tim._2.counter(),
|
0x0400_0108 => bus.tim[2].counter(),
|
||||||
0x0400_010A => bus.tim._2.cnt.raw,
|
0x0400_010A => bus.tim[2].cnt.raw,
|
||||||
0x0400_010C => bus.tim._3.counter(),
|
0x0400_010C => bus.tim[3].counter(),
|
||||||
0x0400_010E => bus.tim._3.cnt.raw,
|
0x0400_010E => bus.tim[3].cnt.raw,
|
||||||
|
|
||||||
// Serial Communication 1
|
// Serial Communication 1
|
||||||
0x0400_0128 => unimplementedRead("Read {} from SIOCNT", .{T}),
|
0x0400_0128 => unimplementedRead("Read {} from SIOCNT", .{T}),
|
||||||
|
@ -199,25 +199,25 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
||||||
0x0400_00A8, 0x0400_00AC => {}, // Unused
|
0x0400_00A8, 0x0400_00AC => {}, // Unused
|
||||||
|
|
||||||
// DMA Transfers
|
// DMA Transfers
|
||||||
0x0400_00B0 => bus.dma._0.writeSad(value),
|
0x0400_00B0 => bus.dma[0].writeSad(value),
|
||||||
0x0400_00B4 => bus.dma._0.writeDad(value),
|
0x0400_00B4 => bus.dma[0].writeDad(value),
|
||||||
0x0400_00B8 => bus.dma._0.writeCnt(value),
|
0x0400_00B8 => bus.dma[0].writeCnt(value),
|
||||||
0x0400_00BC => bus.dma._1.writeSad(value),
|
0x0400_00BC => bus.dma[1].writeSad(value),
|
||||||
0x0400_00C0 => bus.dma._1.writeDad(value),
|
0x0400_00C0 => bus.dma[1].writeDad(value),
|
||||||
0x0400_00C4 => bus.dma._1.writeCnt(value),
|
0x0400_00C4 => bus.dma[1].writeCnt(value),
|
||||||
0x0400_00C8 => bus.dma._2.writeSad(value),
|
0x0400_00C8 => bus.dma[2].writeSad(value),
|
||||||
0x0400_00CC => bus.dma._2.writeDad(value),
|
0x0400_00CC => bus.dma[2].writeDad(value),
|
||||||
0x0400_00D0 => bus.dma._2.writeCnt(value),
|
0x0400_00D0 => bus.dma[2].writeCnt(value),
|
||||||
0x0400_00D4 => bus.dma._3.writeSad(value),
|
0x0400_00D4 => bus.dma[3].writeSad(value),
|
||||||
0x0400_00D8 => bus.dma._3.writeDad(value),
|
0x0400_00D8 => bus.dma[3].writeDad(value),
|
||||||
0x0400_00DC => bus.dma._3.writeCnt(value),
|
0x0400_00DC => bus.dma[3].writeCnt(value),
|
||||||
0x0400_00E0...0x0400_00FC => {}, // Unused
|
0x0400_00E0...0x0400_00FC => {}, // Unused
|
||||||
|
|
||||||
// Timers
|
// Timers
|
||||||
0x0400_0100 => bus.tim._0.writeCnt(value),
|
0x0400_0100 => bus.tim[0].writeCnt(value),
|
||||||
0x0400_0104 => bus.tim._1.writeCnt(value),
|
0x0400_0104 => bus.tim[1].writeCnt(value),
|
||||||
0x0400_0108 => bus.tim._2.writeCnt(value),
|
0x0400_0108 => bus.tim[2].writeCnt(value),
|
||||||
0x0400_010C => bus.tim._3.writeCnt(value),
|
0x0400_010C => bus.tim[3].writeCnt(value),
|
||||||
0x0400_0110...0x0400_011C => {}, // Unused
|
0x0400_0110...0x0400_011C => {}, // Unused
|
||||||
|
|
||||||
// Serial Communication 1
|
// Serial Communication 1
|
||||||
|
@ -310,43 +310,43 @@ 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),
|
0x0400_0090...0x0400_009F => bus.apu.ch3.wave_dev.write(T, bus.apu.ch3.select, address, value),
|
||||||
|
|
||||||
// Dma Transfers
|
// Dma Transfers
|
||||||
0x0400_00B0 => bus.dma._0.writeSad(bus.dma._0.sad & 0xFFFF_0000 | 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_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_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_00B6 => bus.dma[0].writeDad(bus.dma[0].dad & 0x0000_FFFF | (@as(u32, value) << 16)),
|
||||||
0x0400_00B8 => bus.dma._0.writeWordCount(value),
|
0x0400_00B8 => bus.dma[0].writeWordCount(value),
|
||||||
0x0400_00BA => bus.dma._0.writeCntHigh(value),
|
0x0400_00BA => bus.dma[0].writeCntHigh(value),
|
||||||
|
|
||||||
0x0400_00BC => bus.dma._1.writeSad(bus.dma._1.sad & 0xFFFF_0000 | 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_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_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_00C2 => bus.dma[1].writeDad(bus.dma[1].dad & 0x0000_FFFF | (@as(u32, value) << 16)),
|
||||||
0x0400_00C4 => bus.dma._1.writeWordCount(value),
|
0x0400_00C4 => bus.dma[1].writeWordCount(value),
|
||||||
0x0400_00C6 => bus.dma._1.writeCntHigh(value),
|
0x0400_00C6 => bus.dma[1].writeCntHigh(value),
|
||||||
|
|
||||||
0x0400_00C8 => bus.dma._2.writeSad(bus.dma._2.sad & 0xFFFF_0000 | 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_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_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_00CE => bus.dma[2].writeDad(bus.dma[2].dad & 0x0000_FFFF | (@as(u32, value) << 16)),
|
||||||
0x0400_00D0 => bus.dma._2.writeWordCount(value),
|
0x0400_00D0 => bus.dma[2].writeWordCount(value),
|
||||||
0x0400_00D2 => bus.dma._2.writeCntHigh(value),
|
0x0400_00D2 => bus.dma[2].writeCntHigh(value),
|
||||||
|
|
||||||
0x0400_00D4 => bus.dma._3.writeSad(bus.dma._3.sad & 0xFFFF_0000 | 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_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_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_00DA => bus.dma[3].writeDad(bus.dma[3].dad & 0x0000_FFFF | (@as(u32, value) << 16)),
|
||||||
0x0400_00DC => bus.dma._3.writeWordCount(value),
|
0x0400_00DC => bus.dma[3].writeWordCount(value),
|
||||||
0x0400_00DE => bus.dma._3.writeCntHigh(value),
|
0x0400_00DE => bus.dma[3].writeCntHigh(value),
|
||||||
|
|
||||||
// Timers
|
// Timers
|
||||||
0x0400_0100 => bus.tim._0.setReload(value),
|
0x0400_0100 => bus.tim[0].setReload(value),
|
||||||
0x0400_0102 => bus.tim._0.writeCntHigh(value),
|
0x0400_0102 => bus.tim[0].writeCntHigh(value),
|
||||||
0x0400_0104 => bus.tim._1.setReload(value),
|
0x0400_0104 => bus.tim[1].setReload(value),
|
||||||
0x0400_0106 => bus.tim._1.writeCntHigh(value),
|
0x0400_0106 => bus.tim[1].writeCntHigh(value),
|
||||||
0x0400_0108 => bus.tim._2.setReload(value),
|
0x0400_0108 => bus.tim[2].setReload(value),
|
||||||
0x0400_010A => bus.tim._2.writeCntHigh(value),
|
0x0400_010A => bus.tim[2].writeCntHigh(value),
|
||||||
0x0400_010C => bus.tim._3.setReload(value),
|
0x0400_010C => bus.tim[3].setReload(value),
|
||||||
0x0400_010E => bus.tim._3.writeCntHigh(value),
|
0x0400_010E => bus.tim[3].writeCntHigh(value),
|
||||||
0x0400_0114 => {}, // TODO: Gyakuten Saiban writes 0x8000 to 0x0400_0114
|
0x0400_0114 => {}, // TODO: Gyakuten Saiban writes 0x8000 to 0x0400_0114
|
||||||
0x0400_0110 => {}, // Not Used,
|
0x0400_0110 => {}, // Not Used,
|
||||||
|
|
||||||
|
|
|
@ -6,25 +6,12 @@ const Scheduler = @import("../scheduler.zig").Scheduler;
|
||||||
const Event = @import("../scheduler.zig").Event;
|
const Event = @import("../scheduler.zig").Event;
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
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);
|
const log = std.log.scoped(.Timer);
|
||||||
|
|
||||||
pub const Timers = struct {
|
pub fn create(sched: *Scheduler) TimerTuple {
|
||||||
const Self = @This();
|
return .{ Timer(0).init(sched), Timer(1).init(sched), Timer(2).init(sched), Timer(3).init(sched) };
|
||||||
|
|
||||||
_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),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
fn Timer(comptime id: u2) type {
|
fn Timer(comptime id: u2) type {
|
||||||
return struct {
|
return struct {
|
||||||
|
@ -94,7 +81,6 @@ fn Timer(comptime id: u2) type {
|
||||||
pub fn handleOverflow(self: *Self, cpu: *Arm7tdmi, late: u64) void {
|
pub fn handleOverflow(self: *Self, cpu: *Arm7tdmi, late: u64) void {
|
||||||
// Fire IRQ if enabled
|
// Fire IRQ if enabled
|
||||||
const io = &cpu.bus.io;
|
const io = &cpu.bus.io;
|
||||||
const tim = &cpu.bus.tim;
|
|
||||||
|
|
||||||
if (self.cnt.irq.read()) {
|
if (self.cnt.irq.read()) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
@ -114,17 +100,17 @@ fn Timer(comptime id: u2) type {
|
||||||
|
|
||||||
// Perform Cascade Behaviour
|
// Perform Cascade Behaviour
|
||||||
switch (id) {
|
switch (id) {
|
||||||
0 => if (tim._1.cnt.cascade.read()) {
|
0 => if (cpu.bus.tim[1].cnt.cascade.read()) {
|
||||||
tim._1._counter +%= 1;
|
cpu.bus.tim[1]._counter +%= 1;
|
||||||
if (tim._1._counter == 0) tim._1.handleOverflow(cpu, late);
|
if (cpu.bus.tim[1]._counter == 0) cpu.bus.tim[1].handleOverflow(cpu, late);
|
||||||
},
|
},
|
||||||
1 => if (tim._2.cnt.cascade.read()) {
|
1 => if (cpu.bus.tim[2].cnt.cascade.read()) {
|
||||||
tim._2._counter +%= 1;
|
cpu.bus.tim[2]._counter +%= 1;
|
||||||
if (tim._2._counter == 0) tim._2.handleOverflow(cpu, late);
|
if (cpu.bus.tim[2]._counter == 0) cpu.bus.tim[2].handleOverflow(cpu, late);
|
||||||
},
|
},
|
||||||
2 => if (tim._3.cnt.cascade.read()) {
|
2 => if (cpu.bus.tim[3].cnt.cascade.read()) {
|
||||||
tim._3._counter +%= 1;
|
cpu.bus.tim[3]._counter +%= 1;
|
||||||
if (tim._3._counter == 0) tim._3.handleOverflow(cpu, late);
|
if (cpu.bus.tim[3]._counter == 0) cpu.bus.tim[3].handleOverflow(cpu, late);
|
||||||
},
|
},
|
||||||
3 => {}, // There is no Timer for TIM3 to "cascade" to,
|
3 => {}, // There is no Timer for TIM3 to "cascade" to,
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,10 +45,10 @@ pub const Scheduler = struct {
|
||||||
},
|
},
|
||||||
.TimerOverflow => |id| {
|
.TimerOverflow => |id| {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
0 => cpu.bus.tim._0.handleOverflow(cpu, late),
|
0 => cpu.bus.tim[0].handleOverflow(cpu, late),
|
||||||
1 => cpu.bus.tim._1.handleOverflow(cpu, late),
|
1 => cpu.bus.tim[1].handleOverflow(cpu, late),
|
||||||
2 => cpu.bus.tim._2.handleOverflow(cpu, late),
|
2 => cpu.bus.tim[2].handleOverflow(cpu, late),
|
||||||
3 => cpu.bus.tim._3.handleOverflow(cpu, late),
|
3 => cpu.bus.tim[3].handleOverflow(cpu, late),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.ApuChannel => |id| {
|
.ApuChannel => |id| {
|
||||||
|
|
Loading…
Reference in New Issue