style: improve code quality

This commit is contained in:
Rekai Nyangadzayi Musuka 2022-10-12 22:57:44 -03:00
parent 785135a074
commit 21eddac31e
9 changed files with 139 additions and 131 deletions

View File

@ -15,6 +15,9 @@ const Noise = @import("apu/Noise.zig");
const SoundFifo = std.fifo.LinearFifo(u8, .{ .Static = 0x20 }); const SoundFifo = std.fifo.LinearFifo(u8, .{ .Static = 0x20 });
const intToBytes = @import("../util.zig").intToBytes; const intToBytes = @import("../util.zig").intToBytes;
const setHi = @import("../util.zig").setHi;
const setLo = @import("../util.zig").setLo;
const log = std.log.scoped(.APU); const log = std.log.scoped(.APU);
pub const host_sample_rate = 1 << 15; pub const host_sample_rate = 1 << 15;
@ -24,28 +27,28 @@ pub fn read(comptime T: type, apu: *const Apu, addr: u32) ?T {
return switch (T) { return switch (T) {
u16 => switch (byte) { u16 => switch (byte) {
0x60 => apu.ch1.getSoundCntL(), 0x60 => apu.ch1.sound1CntL(),
0x62 => apu.ch1.getSoundCntH(), 0x62 => apu.ch1.sound1CntH(),
0x64 => apu.ch1.getSoundCntX(), 0x64 => apu.ch1.sound1CntX(),
0x68 => apu.ch2.getSoundCntL(), 0x68 => apu.ch2.sound2CntL(),
0x6C => apu.ch2.getSoundCntH(), 0x6C => apu.ch2.sound2CntH(),
0x70 => apu.ch3.select.raw & 0xE0, // SOUND3CNT_L 0x70 => apu.ch3.select.raw & 0xE0, // SOUND3CNT_L
0x72 => apu.ch3.getSoundCntH(), 0x72 => apu.ch3.sound3CntH(),
0x74 => apu.ch3.freq.raw & 0x4000, // SOUND3CNT_X 0x74 => apu.ch3.freq.raw & 0x4000, // SOUND3CNT_X
0x78 => apu.ch4.getSoundCntL(), 0x78 => apu.ch4.sound4CntL(),
0x7C => apu.ch4.getSoundCntH(), 0x7C => apu.ch4.sound4CntH(),
0x80 => apu.psg_cnt.raw & 0xFF77, // SOUNDCNT_L 0x80 => apu.psg_cnt.raw & 0xFF77, // SOUNDCNT_L
0x82 => apu.dma_cnt.raw & 0x770F, // SOUNDCNT_H 0x82 => apu.dma_cnt.raw & 0x770F, // SOUNDCNT_H
0x84 => apu.getSoundCntX(), 0x84 => apu.soundCntX(),
0x88 => apu.bias.raw, // SOUNDBIAS 0x88 => apu.bias.raw, // SOUNDBIAS
0x90...0x9F => apu.ch3.wave_dev.read(T, apu.ch3.select, addr), 0x90...0x9F => apu.ch3.wave_dev.read(T, apu.ch3.select, addr),
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, addr }), else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, addr }),
}, },
u8 => switch (byte) { u8 => switch (byte) {
0x60 => apu.ch1.getSoundCntL(), // NR10 0x60 => apu.ch1.sound1CntL(), // NR10
0x62 => apu.ch1.duty.raw, // NR11 0x62 => apu.ch1.duty.raw, // NR11
0x63 => apu.ch1.envelope.raw, // NR12 0x63 => apu.ch1.envelope.raw, // NR12
0x68 => apu.ch2.duty.raw, // NR21 0x68 => apu.ch2.duty.raw, // NR21
@ -54,7 +57,7 @@ pub fn read(comptime T: type, apu: *const Apu, addr: u32) ?T {
0x79 => apu.ch4.envelope.raw, // NR42 0x79 => apu.ch4.envelope.raw, // NR42
0x7C => apu.ch4.poly.raw, // NR43 0x7C => apu.ch4.poly.raw, // NR43
0x81 => @truncate(u8, apu.psg_cnt.raw >> 8), // NR51 0x81 => @truncate(u8, apu.psg_cnt.raw >> 8), // NR51
0x84 => apu.getSoundCntX(), 0x84 => apu.soundCntX(),
0x89 => @truncate(u8, apu.bias.raw >> 8), // SOUNDBIAS_H 0x89 => @truncate(u8, apu.bias.raw >> 8), // SOUNDBIAS_H
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, addr }), else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, addr }),
}, },
@ -68,14 +71,14 @@ pub fn write(comptime T: type, apu: *Apu, addr: u32, value: T) void {
switch (T) { switch (T) {
u32 => switch (byte) { u32 => switch (byte) {
0x60 => apu.ch1.setSoundCnt(value), 0x60 => apu.ch1.setSound1Cnt(value),
0x64 => apu.ch1.setSoundCntX(&apu.fs, @truncate(u16, value)), 0x64 => apu.ch1.setSound1CntX(&apu.fs, @truncate(u16, value)),
0x68 => apu.ch2.setSoundCntL(@truncate(u16, value)), 0x68 => apu.ch2.setSound2CntL(@truncate(u16, value)),
0x6C => apu.ch2.setSoundCntH(&apu.fs, @truncate(u16, value)), 0x6C => apu.ch2.setSound2CntH(&apu.fs, @truncate(u16, value)),
0x70 => apu.ch3.setSoundCnt(value), 0x70 => apu.ch3.setSound3Cnt(value),
0x74 => apu.ch3.setSoundCntX(&apu.fs, @truncate(u16, value)), 0x74 => apu.ch3.setSound3CntX(&apu.fs, @truncate(u16, value)),
0x78 => apu.ch4.setSoundCntL(@truncate(u16, value)), 0x78 => apu.ch4.setSound4CntL(@truncate(u16, value)),
0x7C => apu.ch4.setSoundCntH(&apu.fs, @truncate(u16, value)), 0x7C => apu.ch4.setSound4CntH(&apu.fs, @truncate(u16, value)),
0x80 => apu.setSoundCnt(value), 0x80 => apu.setSoundCnt(value),
// WAVE_RAM // WAVE_RAM
@ -85,19 +88,19 @@ pub fn write(comptime T: type, apu: *Apu, addr: u32, value: T) void {
else => util.io.write.undef(log, "Tried to write 0x{X:0>8}{} to 0x{X:0>8}", .{ value, T, addr }), else => util.io.write.undef(log, "Tried to write 0x{X:0>8}{} to 0x{X:0>8}", .{ value, T, addr }),
}, },
u16 => switch (byte) { u16 => switch (byte) {
0x60 => apu.ch1.setSoundCntL(@truncate(u8, value)), // SOUND1CNT_L 0x60 => apu.ch1.setSound1CntL(@truncate(u8, value)), // SOUND1CNT_L
0x62 => apu.ch1.setSoundCntH(value), 0x62 => apu.ch1.setSound1CntH(value),
0x64 => apu.ch1.setSoundCntX(&apu.fs, value), 0x64 => apu.ch1.setSound1CntX(&apu.fs, value),
0x68 => apu.ch2.setSoundCntL(value), 0x68 => apu.ch2.setSound2CntL(value),
0x6C => apu.ch2.setSoundCntH(&apu.fs, value), 0x6C => apu.ch2.setSound2CntH(&apu.fs, value),
0x70 => apu.ch3.setSoundCntL(@truncate(u8, value)), 0x70 => apu.ch3.setSound3CntL(@truncate(u8, value)),
0x72 => apu.ch3.setSoundCntH(value), 0x72 => apu.ch3.setSound3CntH(value),
0x74 => apu.ch3.setSoundCntX(&apu.fs, value), 0x74 => apu.ch3.setSound3CntX(&apu.fs, value),
0x78 => apu.ch4.setSoundCntL(value), 0x78 => apu.ch4.setSound4CntL(value),
0x7C => apu.ch4.setSoundCntH(&apu.fs, value), 0x7C => apu.ch4.setSound4CntH(&apu.fs, value),
0x80 => apu.psg_cnt.raw = value, // SOUNDCNT_L 0x80 => apu.psg_cnt.raw = value, // SOUNDCNT_L
0x82 => apu.setSoundCntH(value), 0x82 => apu.setSoundCntH(value),
@ -108,7 +111,7 @@ pub fn write(comptime T: type, apu: *Apu, addr: u32, value: T) void {
else => util.io.write.undef(log, "Tried to write 0x{X:0>4}{} to 0x{X:0>8}", .{ value, T, addr }), else => util.io.write.undef(log, "Tried to write 0x{X:0>4}{} to 0x{X:0>8}", .{ value, T, addr }),
}, },
u8 => switch (byte) { u8 => switch (byte) {
0x60 => apu.ch1.setSoundCntL(value), 0x60 => apu.ch1.setSound1CntL(value),
0x62 => apu.ch1.setNr11(value), 0x62 => apu.ch1.setNr11(value),
0x63 => apu.ch1.setNr12(value), 0x63 => apu.ch1.setNr12(value),
0x64 => apu.ch1.setNr13(value), 0x64 => apu.ch1.setNr13(value),
@ -119,7 +122,7 @@ pub fn write(comptime T: type, apu: *Apu, addr: u32, value: T) void {
0x6C => apu.ch2.setNr23(value), 0x6C => apu.ch2.setNr23(value),
0x6D => apu.ch2.setNr24(&apu.fs, value), 0x6D => apu.ch2.setNr24(&apu.fs, value),
0x70 => apu.ch3.setSoundCntL(value), // NR30 0x70 => apu.ch3.setSound3CntL(value), // NR30
0x72 => apu.ch3.setNr31(value), 0x72 => apu.ch3.setNr31(value),
0x73 => apu.ch3.vol.raw = value, // NR32 0x73 => apu.ch3.vol.raw = value, // NR32
0x74 => apu.ch3.setNr33(value), 0x74 => apu.ch3.setNr33(value),
@ -132,8 +135,8 @@ pub fn write(comptime T: type, apu: *Apu, addr: u32, value: T) void {
0x80 => apu.setNr50(value), 0x80 => apu.setNr50(value),
0x81 => apu.setNr51(value), 0x81 => apu.setNr51(value),
0x82 => apu.setSoundCntHL(value), 0x82 => apu.setSoundCntH(setLo(u16, apu.dma_cnt.raw, value)),
0x83 => apu.setSoundCntHH(value), 0x83 => apu.setSoundCntH(setHi(u16, apu.dma_cnt.raw, value)),
0x84 => apu.setSoundCntX(value >> 7 & 1 == 1), // NR52 0x84 => apu.setSoundCntX(value >> 7 & 1 == 1), // NR52
0x89 => apu.setSoundBiasH(value), 0x89 => apu.setSoundBiasH(value),
0x90...0x9F => apu.ch3.wave_dev.write(T, apu.ch3.select, addr, value), 0x90...0x9F => apu.ch3.wave_dev.write(T, apu.ch3.select, addr, value),
@ -194,12 +197,12 @@ pub const Apu = struct {
.is_buffer_full = false, .is_buffer_full = false,
}; };
sched.push(.SampleAudio, apu.sampleTicks()); sched.push(.SampleAudio, apu.interval());
sched.push(.{ .ApuChannel = 0 }, @import("apu/signal/Square.zig").interval); sched.push(.{ .ApuChannel = 0 }, @import("apu/signal/Square.zig").interval);
sched.push(.{ .ApuChannel = 1 }, @import("apu/signal/Square.zig").interval); sched.push(.{ .ApuChannel = 1 }, @import("apu/signal/Square.zig").interval);
sched.push(.{ .ApuChannel = 2 }, @import("apu/signal/Wave.zig").interval); sched.push(.{ .ApuChannel = 2 }, @import("apu/signal/Wave.zig").interval);
sched.push(.{ .ApuChannel = 3 }, @import("apu/signal/Lfsr.zig").interval); sched.push(.{ .ApuChannel = 3 }, @import("apu/signal/Lfsr.zig").interval);
sched.push(.FrameSequencer, ((1 << 24) / 512)); sched.push(.FrameSequencer, FrameSequencer.interval);
return apu; return apu;
} }
@ -217,18 +220,6 @@ pub const Apu = struct {
self.setSoundCntH(@truncate(u16, value >> 16)); self.setSoundCntH(@truncate(u16, value >> 16));
} }
/// SOUNDCNT_H_L
fn setSoundCntHL(self: *Self, value: u8) void {
const merged = (self.dma_cnt.raw & 0xFF00) | value;
self.setSoundCntH(merged);
}
/// SOUNDCNT_H_H
fn setSoundCntHH(self: *Self, value: u8) void {
const merged = (self.dma_cnt.raw & 0x00FF) | (@as(u16, value) << 8);
self.setSoundCntH(merged);
}
/// SOUNDCNT_H /// SOUNDCNT_H
pub fn setSoundCntH(self: *Self, value: u16) void { pub fn setSoundCntH(self: *Self, value: u16) void {
const new: io.DmaSoundControl = .{ .raw = value }; const new: io.DmaSoundControl = .{ .raw = value };
@ -260,7 +251,7 @@ pub const Apu = struct {
} }
/// NR52 /// NR52
pub fn getSoundCntX(self: *const Self) u8 { pub fn soundCntX(self: *const Self) u8 {
const apu_enable: u8 = @boolToInt(self.cnt.apu_enable.read()); const apu_enable: u8 = @boolToInt(self.cnt.apu_enable.read());
const ch1_enable: u8 = @boolToInt(self.ch1.enabled); const ch1_enable: u8 = @boolToInt(self.ch1.enabled);
@ -286,7 +277,7 @@ pub const Apu = struct {
} }
pub fn sampleAudio(self: *Self, late: u64) void { pub fn sampleAudio(self: *Self, late: u64) void {
self.sched.push(.SampleAudio, self.sampleTicks() -| late); self.sched.push(.SampleAudio, self.interval() -| late);
// Whether the APU is busy or not is determined by the main loop in emu.zig // Whether the APU is busy or not is determined by the main loop in emu.zig
// This should only ever be true (because this side of the emu is single threaded) // This should only ever be true (because this side of the emu is single threaded)
@ -355,6 +346,7 @@ pub const Apu = struct {
} }
fn replaceSDLResampler(self: *Self) void { fn replaceSDLResampler(self: *Self) void {
@setCold(true);
const sample_rate = Self.sampleRate(self.bias.sampling_cycle.read()); const sample_rate = Self.sampleRate(self.bias.sampling_cycle.read());
log.info("Sample Rate changed from {}Hz to {}Hz", .{ Self.sampleRate(self.sampling_cycle), sample_rate }); log.info("Sample Rate changed from {}Hz to {}Hz", .{ Self.sampleRate(self.sampling_cycle), sample_rate });
@ -367,7 +359,7 @@ pub const Apu = struct {
self.stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, @intCast(c_int, sample_rate), SDL.AUDIO_U16, 2, host_sample_rate).?; self.stream = SDL.SDL_NewAudioStream(SDL.AUDIO_U16, 2, @intCast(c_int, sample_rate), SDL.AUDIO_U16, 2, host_sample_rate).?;
} }
fn sampleTicks(self: *const Self) u64 { fn interval(self: *const Self) u64 {
return (1 << 24) / Self.sampleRate(self.bias.sampling_cycle.read()); return (1 << 24) / Self.sampleRate(self.bias.sampling_cycle.read());
} }
@ -393,19 +385,19 @@ pub const Apu = struct {
} }
fn tick(self: *Self, comptime kind: Tick) void { fn tick(self: *Self, comptime kind: Tick) void {
self.ch1.tick(kind);
switch (kind) { switch (kind) {
.Length => { .Length => {
self.ch1.tick(kind);
self.ch2.tick(kind); self.ch2.tick(kind);
self.ch3.tick(kind); self.ch3.tick(kind);
self.ch4.tick(kind); self.ch4.tick(kind);
}, },
.Envelope => { .Envelope => {
self.ch1.tick(kind);
self.ch2.tick(kind); self.ch2.tick(kind);
self.ch4.tick(kind); self.ch4.tick(kind);
}, },
.Sweep => self.ch1.tick(kind), .Sweep => {}, // Already handled above (only for Ch1)
} }
} }
@ -464,6 +456,7 @@ const DmaSoundKind = enum {
}; };
pub const FrameSequencer = struct { pub const FrameSequencer = struct {
const interval = (1 << 24) / 512;
const Self = @This(); const Self = @This();
step: u3, step: u3,

View File

@ -67,12 +67,12 @@ pub fn tick(self: *Self, comptime kind: Tick) void {
} }
/// NR41, NR42 /// NR41, NR42
pub fn getSoundCntL(self: *const Self) u16 { pub fn sound4CntL(self: *const Self) u16 {
return @as(u16, self.envelope.raw) << 8; return @as(u16, self.envelope.raw) << 8;
} }
/// NR41, NR42 /// NR41, NR42
pub fn setSoundCntL(self: *Self, value: u16) void { pub fn setSound4CntL(self: *Self, value: u16) void {
self.setNr41(@truncate(u8, value)); self.setNr41(@truncate(u8, value));
self.setNr42(@truncate(u8, value >> 8)); self.setNr42(@truncate(u8, value >> 8));
} }
@ -90,12 +90,12 @@ pub fn setNr42(self: *Self, value: u8) void {
} }
/// NR43, NR44 /// NR43, NR44
pub fn getSoundCntH(self: *const Self) u16 { pub fn sound4CntH(self: *const Self) u16 {
return @as(u16, self.poly.raw & 0x40) << 8 | self.cnt.raw; return @as(u16, self.poly.raw & 0x40) << 8 | self.cnt.raw;
} }
/// NR43, NR44 /// NR43, NR44
pub fn setSoundCntH(self: *Self, fs: *const FrameSequencer, value: u16) void { pub fn setSound4CntH(self: *Self, fs: *const FrameSequencer, value: u16) void {
self.poly.raw = @truncate(u8, value); self.poly.raw = @truncate(u8, value);
self.setNr44(fs, @truncate(u8, value >> 8)); self.setNr44(fs, @truncate(u8, value >> 8));
} }

View File

@ -68,12 +68,12 @@ pub fn onToneEvent(self: *Self, late: u64) void {
} }
/// NR21, NR22 /// NR21, NR22
pub fn getSoundCntL(self: *const Self) u16 { pub fn sound2CntL(self: *const Self) u16 {
return @as(u16, self.envelope.raw) << 8 | (self.duty.raw & 0xC0); return @as(u16, self.envelope.raw) << 8 | (self.duty.raw & 0xC0);
} }
/// NR21, NR22 /// NR21, NR22
pub fn setSoundCntL(self: *Self, value: u16) void { pub fn setSound2CntL(self: *Self, value: u16) void {
self.setNr21(@truncate(u8, value)); self.setNr21(@truncate(u8, value));
self.setNr22(@truncate(u8, value >> 8)); self.setNr22(@truncate(u8, value >> 8));
} }
@ -91,12 +91,12 @@ pub fn setNr22(self: *Self, value: u8) void {
} }
/// NR23, NR24 /// NR23, NR24
pub fn getSoundCntH(self: *const Self) u16 { pub fn sound2CntH(self: *const Self) u16 {
return self.freq.raw & 0x4000; return self.freq.raw & 0x4000;
} }
/// NR23, NR24 /// NR23, NR24
pub fn setSoundCntH(self: *Self, fs: *const FrameSequencer, value: u16) void { pub fn setSound2CntH(self: *Self, fs: *const FrameSequencer, value: u16) void {
self.setNr23(@truncate(u8, value)); self.setNr23(@truncate(u8, value));
self.setNr24(fs, @truncate(u8, value >> 8)); self.setNr24(fs, @truncate(u8, value >> 8));
} }

View File

@ -78,18 +78,18 @@ pub fn onToneSweepEvent(self: *Self, late: u64) void {
} }
/// NR10, NR11, NR12 /// NR10, NR11, NR12
pub fn setSoundCnt(self: *Self, value: u32) void { pub fn setSound1Cnt(self: *Self, value: u32) void {
self.setSoundCntL(@truncate(u8, value)); self.setSound1CntL(@truncate(u8, value));
self.setSoundCntH(@truncate(u16, value >> 16)); self.setSound1CntH(@truncate(u16, value >> 16));
} }
/// NR10 /// NR10
pub fn getSoundCntL(self: *const Self) u8 { pub fn sound1CntL(self: *const Self) u8 {
return self.sweep.raw & 0x7F; return self.sweep.raw & 0x7F;
} }
/// NR10 /// NR10
pub fn setSoundCntL(self: *Self, value: u8) void { pub fn setSound1CntL(self: *Self, value: u8) void {
const new = io.Sweep{ .raw = value }; const new = io.Sweep{ .raw = value };
if (self.sweep.direction.read() and !new.direction.read()) { if (self.sweep.direction.read() and !new.direction.read()) {
@ -104,12 +104,12 @@ pub fn setSoundCntL(self: *Self, value: u8) void {
} }
/// NR11, NR12 /// NR11, NR12
pub fn getSoundCntH(self: *const Self) u16 { pub fn sound1CntH(self: *const Self) u16 {
return @as(u16, self.envelope.raw) << 8 | (self.duty.raw & 0xC0); return @as(u16, self.envelope.raw) << 8 | (self.duty.raw & 0xC0);
} }
/// NR11, NR12 /// NR11, NR12
pub fn setSoundCntH(self: *Self, value: u16) void { pub fn setSound1CntH(self: *Self, value: u16) void {
self.setNr11(@truncate(u8, value)); self.setNr11(@truncate(u8, value));
self.setNr12(@truncate(u8, value >> 8)); self.setNr12(@truncate(u8, value >> 8));
} }
@ -127,12 +127,12 @@ pub fn setNr12(self: *Self, value: u8) void {
} }
/// NR13, NR14 /// NR13, NR14
pub fn getSoundCntX(self: *const Self) u16 { pub fn sound1CntX(self: *const Self) u16 {
return self.freq.raw & 0x4000; return self.freq.raw & 0x4000;
} }
/// NR13, NR14 /// NR13, NR14
pub fn setSoundCntX(self: *Self, fs: *const FrameSequencer, value: u16) void { pub fn setSound1CntX(self: *Self, fs: *const FrameSequencer, value: u16) void {
self.setNr13(@truncate(u8, value)); self.setNr13(@truncate(u8, value));
self.setNr14(fs, @truncate(u8, value >> 8)); self.setNr14(fs, @truncate(u8, value >> 8));
} }

View File

@ -60,24 +60,24 @@ pub fn tick(self: *Self, comptime kind: Tick) void {
} }
/// NR30, NR31, NR32 /// NR30, NR31, NR32
pub fn setSoundCnt(self: *Self, value: u32) void { pub fn setSound3Cnt(self: *Self, value: u32) void {
self.setSoundCntL(@truncate(u8, value)); self.setSound3CntL(@truncate(u8, value));
self.setSoundCntH(@truncate(u16, value >> 16)); self.setSound3CntH(@truncate(u16, value >> 16));
} }
/// NR30 /// NR30
pub fn setSoundCntL(self: *Self, value: u8) void { pub fn setSound3CntL(self: *Self, value: u8) void {
self.select.raw = value; self.select.raw = value;
if (!self.select.enabled.read()) self.enabled = false; if (!self.select.enabled.read()) self.enabled = false;
} }
/// NR31, NR32 /// NR31, NR32
pub fn getSoundCntH(self: *const Self) u16 { pub fn sound3CntH(self: *const Self) u16 {
return @as(u16, self.length & 0xE0) << 8; return @as(u16, self.length & 0xE0) << 8;
} }
/// NR31, NR32 /// NR31, NR32
pub fn setSoundCntH(self: *Self, value: u16) void { pub fn setSound3CntH(self: *Self, value: u16) void {
self.setNr31(@truncate(u8, value)); self.setNr31(@truncate(u8, value));
self.vol.raw = (@truncate(u8, value >> 8)); self.vol.raw = (@truncate(u8, value >> 8));
} }
@ -89,7 +89,7 @@ pub fn setNr31(self: *Self, len: u8) void {
} }
/// NR33, NR34 /// NR33, NR34
pub fn setSoundCntX(self: *Self, fs: *const FrameSequencer, value: u16) void { pub fn setSound3CntX(self: *Self, fs: *const FrameSequencer, value: u16) void {
self.setNr33(@truncate(u8, value)); self.setNr33(@truncate(u8, value));
self.setNr34(fs, @truncate(u8, value >> 8)); self.setNr34(fs, @truncate(u8, value >> 8));
} }

View File

@ -8,6 +8,9 @@ const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
pub const DmaTuple = std.meta.Tuple(&[_]type{ DmaController(0), DmaController(1), DmaController(2), DmaController(3) }); 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);
const setHi = util.setHi;
const setLo = util.setLo;
pub fn create() DmaTuple { pub fn create() DmaTuple {
return .{ DmaController(0).init(), DmaController(1).init(), DmaController(2).init(), DmaController(3).init() }; return .{ DmaController(0).init(), DmaController(1).init(), DmaController(2).init(), DmaController(3).init() };
} }
@ -55,31 +58,31 @@ pub fn write(comptime T: type, dma: *DmaTuple, addr: u32, value: T) void {
else => util.io.write.undef(log, "Tried to write 0x{X:0>8}{} to 0x{X:0>8}", .{ value, T, addr }), else => util.io.write.undef(log, "Tried to write 0x{X:0>8}{} to 0x{X:0>8}", .{ value, T, addr }),
}, },
u16 => switch (byte) { u16 => switch (byte) {
0xB0 => dma.*[0].setDmasad(setU32L(dma.*[0].sad, value)), 0xB0 => dma.*[0].setDmasad(setLo(u32, dma.*[0].sad, value)),
0xB2 => dma.*[0].setDmasad(setU32H(dma.*[0].sad, value)), 0xB2 => dma.*[0].setDmasad(setHi(u32, dma.*[0].sad, value)),
0xB4 => dma.*[0].setDmadad(setU32L(dma.*[0].dad, value)), 0xB4 => dma.*[0].setDmadad(setLo(u32, dma.*[0].dad, value)),
0xB6 => dma.*[0].setDmadad(setU32H(dma.*[0].dad, value)), 0xB6 => dma.*[0].setDmadad(setHi(u32, dma.*[0].dad, value)),
0xB8 => dma.*[0].setDmacntL(value), 0xB8 => dma.*[0].setDmacntL(value),
0xBA => dma.*[0].setDmacntH(value), 0xBA => dma.*[0].setDmacntH(value),
0xBC => dma.*[1].setDmasad(setU32L(dma.*[1].sad, value)), 0xBC => dma.*[1].setDmasad(setLo(u32, dma.*[1].sad, value)),
0xBE => dma.*[1].setDmasad(setU32H(dma.*[1].sad, value)), 0xBE => dma.*[1].setDmasad(setHi(u32, dma.*[1].sad, value)),
0xC0 => dma.*[1].setDmadad(setU32L(dma.*[1].dad, value)), 0xC0 => dma.*[1].setDmadad(setLo(u32, dma.*[1].dad, value)),
0xC2 => dma.*[1].setDmadad(setU32H(dma.*[1].dad, value)), 0xC2 => dma.*[1].setDmadad(setHi(u32, dma.*[1].dad, value)),
0xC4 => dma.*[1].setDmacntL(value), 0xC4 => dma.*[1].setDmacntL(value),
0xC6 => dma.*[1].setDmacntH(value), 0xC6 => dma.*[1].setDmacntH(value),
0xC8 => dma.*[2].setDmasad(setU32L(dma.*[2].sad, value)), 0xC8 => dma.*[2].setDmasad(setLo(u32, dma.*[2].sad, value)),
0xCA => dma.*[2].setDmasad(setU32H(dma.*[2].sad, value)), 0xCA => dma.*[2].setDmasad(setHi(u32, dma.*[2].sad, value)),
0xCC => dma.*[2].setDmadad(setU32L(dma.*[2].dad, value)), 0xCC => dma.*[2].setDmadad(setLo(u32, dma.*[2].dad, value)),
0xCE => dma.*[2].setDmadad(setU32H(dma.*[2].dad, value)), 0xCE => dma.*[2].setDmadad(setHi(u32, dma.*[2].dad, value)),
0xD0 => dma.*[2].setDmacntL(value), 0xD0 => dma.*[2].setDmacntL(value),
0xD2 => dma.*[2].setDmacntH(value), 0xD2 => dma.*[2].setDmacntH(value),
0xD4 => dma.*[3].setDmasad(setU32L(dma.*[3].sad, value)), 0xD4 => dma.*[3].setDmasad(setLo(u32, dma.*[3].sad, value)),
0xD6 => dma.*[3].setDmasad(setU32H(dma.*[3].sad, value)), 0xD6 => dma.*[3].setDmasad(setHi(u32, dma.*[3].sad, value)),
0xD8 => dma.*[3].setDmadad(setU32L(dma.*[3].dad, value)), 0xD8 => dma.*[3].setDmadad(setLo(u32, dma.*[3].dad, value)),
0xDA => dma.*[3].setDmadad(setU32H(dma.*[3].dad, value)), 0xDA => dma.*[3].setDmadad(setHi(u32, dma.*[3].dad, value)),
0xDC => dma.*[3].setDmacntL(value), 0xDC => dma.*[3].setDmacntL(value),
0xDE => dma.*[3].setDmacntH(value), 0xDE => dma.*[3].setDmacntH(value),
else => util.io.write.undef(log, "Tried to write 0x{X:0>4}{} to 0x{X:0>8}", .{ value, T, addr }), else => util.io.write.undef(log, "Tried to write 0x{X:0>4}{} to 0x{X:0>8}", .{ value, T, addr }),
@ -283,11 +286,3 @@ const DmaKind = enum(u2) {
VBlank, VBlank,
Special, Special,
}; };
fn setU32L(left: u32, right: u16) u32 {
return (left & 0xFFFF_0000) | right;
}
fn setU32H(left: u32, right: u16) u32 {
return (left & 0x0000_FFFF) | (@as(u32, right) << 16);
}

View File

@ -11,6 +11,9 @@ const Bus = @import("../Bus.zig");
const DmaController = @import("dma.zig").DmaController; const DmaController = @import("dma.zig").DmaController;
const Scheduler = @import("../scheduler.zig").Scheduler; const Scheduler = @import("../scheduler.zig").Scheduler;
const setHi = util.setLo;
const setLo = util.setHi;
const log = std.log.scoped(.@"I/O"); const log = std.log.scoped(.@"I/O");
pub const Io = struct { pub const Io = struct {
@ -233,18 +236,18 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
0x0400_0022 => bus.ppu.aff_bg[0].pb = @bitCast(i16, value), 0x0400_0022 => bus.ppu.aff_bg[0].pb = @bitCast(i16, value),
0x0400_0024 => bus.ppu.aff_bg[0].pc = @bitCast(i16, value), 0x0400_0024 => bus.ppu.aff_bg[0].pc = @bitCast(i16, value),
0x0400_0026 => bus.ppu.aff_bg[0].pd = @bitCast(i16, value), 0x0400_0026 => bus.ppu.aff_bg[0].pd = @bitCast(i16, value),
0x0400_0028 => bus.ppu.aff_bg[0].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[0].x) & 0xFFFF_0000 | value), 0x0400_0028 => bus.ppu.aff_bg[0].x = @bitCast(i32, setLo(u32, @bitCast(u32, bus.ppu.aff_bg[0].x), value)),
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_002A => bus.ppu.aff_bg[0].x = @bitCast(i32, setHi(u32, @bitCast(u32, bus.ppu.aff_bg[0].x), value)),
0x0400_002C => bus.ppu.aff_bg[0].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[0].y) & 0xFFFF_0000 | value), 0x0400_002C => bus.ppu.aff_bg[0].y = @bitCast(i32, setLo(u32, @bitCast(u32, bus.ppu.aff_bg[0].y), value)),
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_002E => bus.ppu.aff_bg[0].y = @bitCast(i32, setHi(u32, @bitCast(u32, bus.ppu.aff_bg[0].y), value)),
0x0400_0030 => bus.ppu.aff_bg[1].pa = @bitCast(i16, value), 0x0400_0030 => bus.ppu.aff_bg[1].pa = @bitCast(i16, value),
0x0400_0032 => bus.ppu.aff_bg[1].pb = @bitCast(i16, value), 0x0400_0032 => bus.ppu.aff_bg[1].pb = @bitCast(i16, value),
0x0400_0034 => bus.ppu.aff_bg[1].pc = @bitCast(i16, value), 0x0400_0034 => bus.ppu.aff_bg[1].pc = @bitCast(i16, value),
0x0400_0036 => bus.ppu.aff_bg[1].pd = @bitCast(i16, value), 0x0400_0036 => bus.ppu.aff_bg[1].pd = @bitCast(i16, value),
0x0400_0038 => bus.ppu.aff_bg[1].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[1].x) & 0xFFFF_0000 | value), 0x0400_0038 => bus.ppu.aff_bg[1].x = @bitCast(i32, setLo(u32, @bitCast(u32, bus.ppu.aff_bg[1].x), value)),
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_003A => bus.ppu.aff_bg[1].x = @bitCast(i32, setHi(u32, @bitCast(u32, bus.ppu.aff_bg[1].x), value)),
0x0400_003C => bus.ppu.aff_bg[1].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[1].y) & 0xFFFF_0000 | value), 0x0400_003C => bus.ppu.aff_bg[1].y = @bitCast(i32, setLo(u32, @bitCast(u32, bus.ppu.aff_bg[1].y), value)),
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_003E => bus.ppu.aff_bg[1].y = @bitCast(i32, setHi(u32, @bitCast(u32, bus.ppu.aff_bg[1].y), value)),
0x0400_0040 => bus.ppu.win.h[0].raw = value, 0x0400_0040 => bus.ppu.win.h[0].raw = value,
0x0400_0042 => bus.ppu.win.h[1].raw = value, 0x0400_0042 => bus.ppu.win.h[1].raw = value,
0x0400_0044 => bus.ppu.win.v[0].raw = value, 0x0400_0044 => bus.ppu.win.v[0].raw = value,
@ -296,16 +299,16 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
}, },
u8 => switch (address) { u8 => switch (address) {
// Display // Display
0x0400_0004 => bus.ppu.dispstat.raw = (bus.ppu.dispstat.raw & 0xFF00) | value, 0x0400_0004 => bus.ppu.dispstat.raw = setLo(u16, bus.ppu.dispstat.raw, value),
0x0400_0005 => bus.ppu.dispstat.raw = (@as(u16, value) << 8) | (bus.ppu.dispstat.raw & 0xFF), 0x0400_0005 => bus.ppu.dispstat.raw = setHi(u16, bus.ppu.dispstat.raw, value),
0x0400_0008 => bus.ppu.bg[0].cnt.raw = (bus.ppu.bg[0].cnt.raw & 0xFF00) | value, 0x0400_0008 => bus.ppu.bg[0].cnt.raw = setLo(u16, bus.ppu.bg[0].cnt.raw, value),
0x0400_0009 => bus.ppu.bg[0].cnt.raw = (@as(u16, value) << 8) | (bus.ppu.bg[0].cnt.raw & 0xFF), 0x0400_0009 => bus.ppu.bg[0].cnt.raw = setHi(u16, bus.ppu.bg[0].cnt.raw, value),
0x0400_000A => bus.ppu.bg[1].cnt.raw = (bus.ppu.bg[1].cnt.raw & 0xFF00) | value, 0x0400_000A => bus.ppu.bg[1].cnt.raw = setLo(u16, bus.ppu.bg[1].cnt.raw, value),
0x0400_000B => bus.ppu.bg[1].cnt.raw = (@as(u16, value) << 8) | (bus.ppu.bg[1].cnt.raw & 0xFF), 0x0400_000B => bus.ppu.bg[1].cnt.raw = setHi(u16, bus.ppu.bg[1].cnt.raw, value),
0x0400_0048 => bus.ppu.win.setInL(value), 0x0400_0048 => bus.ppu.win.in.raw = setLo(u16, bus.ppu.win.in.raw, value),
0x0400_0049 => bus.ppu.win.setInH(value), 0x0400_0049 => bus.ppu.win.in.raw = setHi(u16, bus.ppu.win.in.raw, value),
0x0400_004A => bus.ppu.win.setOutL(value), 0x0400_004A => bus.ppu.win.out.raw = setLo(u16, bus.ppu.win.out.raw, value),
0x0400_0054 => bus.ppu.bldy.raw = (bus.ppu.bldy.raw & 0xFF00) | value, 0x0400_0054 => bus.ppu.bldy.raw = setLo(u16, bus.ppu.bldy.raw, value),
// Sound // Sound
0x0400_0060...0x0400_00A7 => apu.write(T, &bus.apu, address, value), 0x0400_0060...0x0400_00A7 => apu.write(T, &bus.apu, address, value),

View File

@ -808,18 +808,6 @@ const Window = struct {
self.in.raw = @truncate(u16, value); self.in.raw = @truncate(u16, value);
self.out.raw = @truncate(u16, value >> 16); self.out.raw = @truncate(u16, value >> 16);
} }
pub fn setInL(self: *Self, value: u8) void {
self.in.raw = (self.in.raw & 0xFF00) | value;
}
pub fn setInH(self: *Self, value: u8) void {
self.in.raw = (self.in.raw & 0x00FF) | (@as(u16, value) << 8);
}
pub fn setOutL(self: *Self, value: u8) void {
self.out.raw = (self.out.raw & 0xFF00) | value;
}
}; };
const Background = struct { const Background = struct {

View File

@ -268,3 +268,32 @@ pub const audio = struct {
}; };
}; };
}; };
/// Sets the high bits of an integer to a value
pub inline fn setHi(comptime T: type, left: T, right: HalfInt(T)) T {
return switch (T) {
u32 => (left & 0xFFFF_0000) | right,
u16 => (left & 0xFF00) | right,
u8 => (left & 0xF0) | right,
else => @compileError("unsupported type"),
};
}
/// sets the low bits of an integer to a value
pub inline fn setLo(comptime T: type, left: T, right: HalfInt(T)) T {
return switch (T) {
u32 => (left & 0x0000_FFFF) | @as(u32, right) << 16,
u16 => (left & 0x00FF) | @as(u16, right) << 8,
u8 => (left & 0x0F) | @as(u8, right) << 4,
else => @compileError("unsupported type"),
};
}
/// The Integer type which corresponds to T with exactly half the amount of bits
fn HalfInt(comptime T: type) type {
const type_info = @typeInfo(T);
comptime std.debug.assert(type_info == .Int); // Type must be an integer
comptime std.debug.assert(type_info.Int.bits % 2 == 0); // Type must have an even amount of bits
return std.meta.Int(type_info.Int.signedness, type_info.Int.bits >> 1);
}