style: improve code quality
This commit is contained in:
parent
3c5b30dece
commit
207a99edbe
|
@ -15,6 +15,9 @@ const Noise = @import("apu/Noise.zig");
|
|||
const SoundFifo = std.fifo.LinearFifo(u8, .{ .Static = 0x20 });
|
||||
|
||||
const intToBytes = @import("../util.zig").intToBytes;
|
||||
const setHi = @import("../util.zig").setHi;
|
||||
const setLo = @import("../util.zig").setLo;
|
||||
|
||||
const log = std.log.scoped(.APU);
|
||||
|
||||
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) {
|
||||
u16 => switch (byte) {
|
||||
0x60 => apu.ch1.getSoundCntL(),
|
||||
0x62 => apu.ch1.getSoundCntH(),
|
||||
0x64 => apu.ch1.getSoundCntX(),
|
||||
0x68 => apu.ch2.getSoundCntL(),
|
||||
0x6C => apu.ch2.getSoundCntH(),
|
||||
0x60 => apu.ch1.sound1CntL(),
|
||||
0x62 => apu.ch1.sound1CntH(),
|
||||
0x64 => apu.ch1.sound1CntX(),
|
||||
0x68 => apu.ch2.sound2CntL(),
|
||||
0x6C => apu.ch2.sound2CntH(),
|
||||
|
||||
0x70 => apu.ch3.select.raw & 0xE0, // SOUND3CNT_L
|
||||
0x72 => apu.ch3.getSoundCntH(),
|
||||
0x72 => apu.ch3.sound3CntH(),
|
||||
0x74 => apu.ch3.freq.raw & 0x4000, // SOUND3CNT_X
|
||||
|
||||
0x78 => apu.ch4.getSoundCntL(),
|
||||
0x7C => apu.ch4.getSoundCntH(),
|
||||
0x78 => apu.ch4.sound4CntL(),
|
||||
0x7C => apu.ch4.sound4CntH(),
|
||||
|
||||
0x80 => apu.psg_cnt.raw & 0xFF77, // SOUNDCNT_L
|
||||
0x82 => apu.dma_cnt.raw & 0x770F, // SOUNDCNT_H
|
||||
0x84 => apu.getSoundCntX(),
|
||||
0x84 => apu.soundCntX(),
|
||||
0x88 => apu.bias.raw, // SOUNDBIAS
|
||||
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 }),
|
||||
},
|
||||
u8 => switch (byte) {
|
||||
0x60 => apu.ch1.getSoundCntL(), // NR10
|
||||
0x60 => apu.ch1.sound1CntL(), // NR10
|
||||
0x62 => apu.ch1.duty.raw, // NR11
|
||||
0x63 => apu.ch1.envelope.raw, // NR12
|
||||
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
|
||||
0x7C => apu.ch4.poly.raw, // NR43
|
||||
0x81 => @truncate(u8, apu.psg_cnt.raw >> 8), // NR51
|
||||
0x84 => apu.getSoundCntX(),
|
||||
0x84 => apu.soundCntX(),
|
||||
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 }),
|
||||
},
|
||||
|
@ -68,14 +71,14 @@ pub fn write(comptime T: type, apu: *Apu, addr: u32, value: T) void {
|
|||
|
||||
switch (T) {
|
||||
u32 => switch (byte) {
|
||||
0x60 => apu.ch1.setSoundCnt(value),
|
||||
0x64 => apu.ch1.setSoundCntX(&apu.fs, @truncate(u16, value)),
|
||||
0x68 => apu.ch2.setSoundCntL(@truncate(u16, value)),
|
||||
0x6C => apu.ch2.setSoundCntH(&apu.fs, @truncate(u16, value)),
|
||||
0x70 => apu.ch3.setSoundCnt(value),
|
||||
0x74 => apu.ch3.setSoundCntX(&apu.fs, @truncate(u16, value)),
|
||||
0x78 => apu.ch4.setSoundCntL(@truncate(u16, value)),
|
||||
0x7C => apu.ch4.setSoundCntH(&apu.fs, @truncate(u16, value)),
|
||||
0x60 => apu.ch1.setSound1Cnt(value),
|
||||
0x64 => apu.ch1.setSound1CntX(&apu.fs, @truncate(u16, value)),
|
||||
0x68 => apu.ch2.setSound2CntL(@truncate(u16, value)),
|
||||
0x6C => apu.ch2.setSound2CntH(&apu.fs, @truncate(u16, value)),
|
||||
0x70 => apu.ch3.setSound3Cnt(value),
|
||||
0x74 => apu.ch3.setSound3CntX(&apu.fs, @truncate(u16, value)),
|
||||
0x78 => apu.ch4.setSound4CntL(@truncate(u16, value)),
|
||||
0x7C => apu.ch4.setSound4CntH(&apu.fs, @truncate(u16, value)),
|
||||
|
||||
0x80 => apu.setSoundCnt(value),
|
||||
// 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 }),
|
||||
},
|
||||
u16 => switch (byte) {
|
||||
0x60 => apu.ch1.setSoundCntL(@truncate(u8, value)), // SOUND1CNT_L
|
||||
0x62 => apu.ch1.setSoundCntH(value),
|
||||
0x64 => apu.ch1.setSoundCntX(&apu.fs, value),
|
||||
0x60 => apu.ch1.setSound1CntL(@truncate(u8, value)), // SOUND1CNT_L
|
||||
0x62 => apu.ch1.setSound1CntH(value),
|
||||
0x64 => apu.ch1.setSound1CntX(&apu.fs, value),
|
||||
|
||||
0x68 => apu.ch2.setSoundCntL(value),
|
||||
0x6C => apu.ch2.setSoundCntH(&apu.fs, value),
|
||||
0x68 => apu.ch2.setSound2CntL(value),
|
||||
0x6C => apu.ch2.setSound2CntH(&apu.fs, value),
|
||||
|
||||
0x70 => apu.ch3.setSoundCntL(@truncate(u8, value)),
|
||||
0x72 => apu.ch3.setSoundCntH(value),
|
||||
0x74 => apu.ch3.setSoundCntX(&apu.fs, value),
|
||||
0x70 => apu.ch3.setSound3CntL(@truncate(u8, value)),
|
||||
0x72 => apu.ch3.setSound3CntH(value),
|
||||
0x74 => apu.ch3.setSound3CntX(&apu.fs, value),
|
||||
|
||||
0x78 => apu.ch4.setSoundCntL(value),
|
||||
0x7C => apu.ch4.setSoundCntH(&apu.fs, value),
|
||||
0x78 => apu.ch4.setSound4CntL(value),
|
||||
0x7C => apu.ch4.setSound4CntH(&apu.fs, value),
|
||||
|
||||
0x80 => apu.psg_cnt.raw = value, // SOUNDCNT_L
|
||||
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 }),
|
||||
},
|
||||
u8 => switch (byte) {
|
||||
0x60 => apu.ch1.setSoundCntL(value),
|
||||
0x60 => apu.ch1.setSound1CntL(value),
|
||||
0x62 => apu.ch1.setNr11(value),
|
||||
0x63 => apu.ch1.setNr12(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),
|
||||
0x6D => apu.ch2.setNr24(&apu.fs, value),
|
||||
|
||||
0x70 => apu.ch3.setSoundCntL(value), // NR30
|
||||
0x70 => apu.ch3.setSound3CntL(value), // NR30
|
||||
0x72 => apu.ch3.setNr31(value),
|
||||
0x73 => apu.ch3.vol.raw = value, // NR32
|
||||
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),
|
||||
0x81 => apu.setNr51(value),
|
||||
0x82 => apu.setSoundCntHL(value),
|
||||
0x83 => apu.setSoundCntHH(value),
|
||||
0x82 => apu.setSoundCntH(setLo(u16, apu.dma_cnt.raw, value)),
|
||||
0x83 => apu.setSoundCntH(setHi(u16, apu.dma_cnt.raw, value)),
|
||||
0x84 => apu.setSoundCntX(value >> 7 & 1 == 1), // NR52
|
||||
0x89 => apu.setSoundBiasH(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,
|
||||
};
|
||||
|
||||
sched.push(.SampleAudio, apu.sampleTicks());
|
||||
sched.push(.SampleAudio, apu.interval());
|
||||
sched.push(.{ .ApuChannel = 0 }, @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 = 3 }, @import("apu/signal/Lfsr.zig").interval);
|
||||
sched.push(.FrameSequencer, ((1 << 24) / 512));
|
||||
sched.push(.FrameSequencer, FrameSequencer.interval);
|
||||
|
||||
return apu;
|
||||
}
|
||||
|
@ -217,18 +220,6 @@ pub const Apu = struct {
|
|||
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
|
||||
pub fn setSoundCntH(self: *Self, value: u16) void {
|
||||
const new: io.DmaSoundControl = .{ .raw = value };
|
||||
|
@ -260,7 +251,7 @@ pub const Apu = struct {
|
|||
}
|
||||
|
||||
/// 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 ch1_enable: u8 = @boolToInt(self.ch1.enabled);
|
||||
|
@ -286,7 +277,7 @@ pub const Apu = struct {
|
|||
}
|
||||
|
||||
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
|
||||
// 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 {
|
||||
@setCold(true);
|
||||
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 });
|
||||
|
||||
|
@ -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).?;
|
||||
}
|
||||
|
||||
fn sampleTicks(self: *const Self) u64 {
|
||||
fn interval(self: *const Self) u64 {
|
||||
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 {
|
||||
self.ch1.tick(kind);
|
||||
|
||||
switch (kind) {
|
||||
.Length => {
|
||||
self.ch1.tick(kind);
|
||||
self.ch2.tick(kind);
|
||||
self.ch3.tick(kind);
|
||||
self.ch4.tick(kind);
|
||||
},
|
||||
.Envelope => {
|
||||
self.ch1.tick(kind);
|
||||
self.ch2.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 {
|
||||
const interval = (1 << 24) / 512;
|
||||
const Self = @This();
|
||||
|
||||
step: u3,
|
||||
|
|
|
@ -67,12 +67,12 @@ pub fn tick(self: *Self, comptime kind: Tick) void {
|
|||
}
|
||||
|
||||
/// NR41, NR42
|
||||
pub fn getSoundCntL(self: *const Self) u16 {
|
||||
pub fn sound4CntL(self: *const Self) u16 {
|
||||
return @as(u16, self.envelope.raw) << 8;
|
||||
}
|
||||
|
||||
/// NR41, NR42
|
||||
pub fn setSoundCntL(self: *Self, value: u16) void {
|
||||
pub fn setSound4CntL(self: *Self, value: u16) void {
|
||||
self.setNr41(@truncate(u8, value));
|
||||
self.setNr42(@truncate(u8, value >> 8));
|
||||
}
|
||||
|
@ -90,12 +90,12 @@ pub fn setNr42(self: *Self, value: u8) void {
|
|||
}
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// 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.setNr44(fs, @truncate(u8, value >> 8));
|
||||
}
|
||||
|
|
|
@ -68,12 +68,12 @@ pub fn onToneEvent(self: *Self, late: u64) void {
|
|||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// NR21, NR22
|
||||
pub fn setSoundCntL(self: *Self, value: u16) void {
|
||||
pub fn setSound2CntL(self: *Self, value: u16) void {
|
||||
self.setNr21(@truncate(u8, value));
|
||||
self.setNr22(@truncate(u8, value >> 8));
|
||||
}
|
||||
|
@ -91,12 +91,12 @@ pub fn setNr22(self: *Self, value: u8) void {
|
|||
}
|
||||
|
||||
/// NR23, NR24
|
||||
pub fn getSoundCntH(self: *const Self) u16 {
|
||||
pub fn sound2CntH(self: *const Self) u16 {
|
||||
return self.freq.raw & 0x4000;
|
||||
}
|
||||
|
||||
/// 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.setNr24(fs, @truncate(u8, value >> 8));
|
||||
}
|
||||
|
|
|
@ -78,18 +78,18 @@ pub fn onToneSweepEvent(self: *Self, late: u64) void {
|
|||
}
|
||||
|
||||
/// NR10, NR11, NR12
|
||||
pub fn setSoundCnt(self: *Self, value: u32) void {
|
||||
self.setSoundCntL(@truncate(u8, value));
|
||||
self.setSoundCntH(@truncate(u16, value >> 16));
|
||||
pub fn setSound1Cnt(self: *Self, value: u32) void {
|
||||
self.setSound1CntL(@truncate(u8, value));
|
||||
self.setSound1CntH(@truncate(u16, value >> 16));
|
||||
}
|
||||
|
||||
/// NR10
|
||||
pub fn getSoundCntL(self: *const Self) u8 {
|
||||
pub fn sound1CntL(self: *const Self) u8 {
|
||||
return self.sweep.raw & 0x7F;
|
||||
}
|
||||
|
||||
/// NR10
|
||||
pub fn setSoundCntL(self: *Self, value: u8) void {
|
||||
pub fn setSound1CntL(self: *Self, value: u8) void {
|
||||
const new = io.Sweep{ .raw = value };
|
||||
|
||||
if (self.sweep.direction.read() and !new.direction.read()) {
|
||||
|
@ -104,12 +104,12 @@ pub fn setSoundCntL(self: *Self, value: u8) void {
|
|||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// NR11, NR12
|
||||
pub fn setSoundCntH(self: *Self, value: u16) void {
|
||||
pub fn setSound1CntH(self: *Self, value: u16) void {
|
||||
self.setNr11(@truncate(u8, value));
|
||||
self.setNr12(@truncate(u8, value >> 8));
|
||||
}
|
||||
|
@ -127,12 +127,12 @@ pub fn setNr12(self: *Self, value: u8) void {
|
|||
}
|
||||
|
||||
/// NR13, NR14
|
||||
pub fn getSoundCntX(self: *const Self) u16 {
|
||||
pub fn sound1CntX(self: *const Self) u16 {
|
||||
return self.freq.raw & 0x4000;
|
||||
}
|
||||
|
||||
/// 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.setNr14(fs, @truncate(u8, value >> 8));
|
||||
}
|
||||
|
|
|
@ -60,24 +60,24 @@ pub fn tick(self: *Self, comptime kind: Tick) void {
|
|||
}
|
||||
|
||||
/// NR30, NR31, NR32
|
||||
pub fn setSoundCnt(self: *Self, value: u32) void {
|
||||
self.setSoundCntL(@truncate(u8, value));
|
||||
self.setSoundCntH(@truncate(u16, value >> 16));
|
||||
pub fn setSound3Cnt(self: *Self, value: u32) void {
|
||||
self.setSound3CntL(@truncate(u8, value));
|
||||
self.setSound3CntH(@truncate(u16, value >> 16));
|
||||
}
|
||||
|
||||
/// NR30
|
||||
pub fn setSoundCntL(self: *Self, value: u8) void {
|
||||
pub fn setSound3CntL(self: *Self, value: u8) void {
|
||||
self.select.raw = value;
|
||||
if (!self.select.enabled.read()) self.enabled = false;
|
||||
}
|
||||
|
||||
/// NR31, NR32
|
||||
pub fn getSoundCntH(self: *const Self) u16 {
|
||||
pub fn sound3CntH(self: *const Self) u16 {
|
||||
return @as(u16, self.length & 0xE0) << 8;
|
||||
}
|
||||
|
||||
/// NR31, NR32
|
||||
pub fn setSoundCntH(self: *Self, value: u16) void {
|
||||
pub fn setSound3CntH(self: *Self, value: u16) void {
|
||||
self.setNr31(@truncate(u8, value));
|
||||
self.vol.raw = (@truncate(u8, value >> 8));
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ pub fn setNr31(self: *Self, len: u8) void {
|
|||
}
|
||||
|
||||
/// 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.setNr34(fs, @truncate(u8, value >> 8));
|
||||
}
|
||||
|
|
|
@ -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) });
|
||||
const log = std.log.scoped(.DmaTransfer);
|
||||
|
||||
const setHi = util.setHi;
|
||||
const setLo = util.setLo;
|
||||
|
||||
pub fn create() DmaTuple {
|
||||
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 }),
|
||||
},
|
||||
u16 => switch (byte) {
|
||||
0xB0 => dma.*[0].setDmasad(setU32L(dma.*[0].sad, value)),
|
||||
0xB2 => dma.*[0].setDmasad(setU32H(dma.*[0].sad, value)),
|
||||
0xB4 => dma.*[0].setDmadad(setU32L(dma.*[0].dad, value)),
|
||||
0xB6 => dma.*[0].setDmadad(setU32H(dma.*[0].dad, value)),
|
||||
0xB0 => dma.*[0].setDmasad(setLo(u32, dma.*[0].sad, value)),
|
||||
0xB2 => dma.*[0].setDmasad(setHi(u32, dma.*[0].sad, value)),
|
||||
0xB4 => dma.*[0].setDmadad(setLo(u32, dma.*[0].dad, value)),
|
||||
0xB6 => dma.*[0].setDmadad(setHi(u32, dma.*[0].dad, value)),
|
||||
0xB8 => dma.*[0].setDmacntL(value),
|
||||
0xBA => dma.*[0].setDmacntH(value),
|
||||
|
||||
0xBC => dma.*[1].setDmasad(setU32L(dma.*[1].sad, value)),
|
||||
0xBE => dma.*[1].setDmasad(setU32H(dma.*[1].sad, value)),
|
||||
0xC0 => dma.*[1].setDmadad(setU32L(dma.*[1].dad, value)),
|
||||
0xC2 => dma.*[1].setDmadad(setU32H(dma.*[1].dad, value)),
|
||||
0xBC => dma.*[1].setDmasad(setLo(u32, dma.*[1].sad, value)),
|
||||
0xBE => dma.*[1].setDmasad(setHi(u32, dma.*[1].sad, value)),
|
||||
0xC0 => dma.*[1].setDmadad(setLo(u32, dma.*[1].dad, value)),
|
||||
0xC2 => dma.*[1].setDmadad(setHi(u32, dma.*[1].dad, value)),
|
||||
0xC4 => dma.*[1].setDmacntL(value),
|
||||
0xC6 => dma.*[1].setDmacntH(value),
|
||||
|
||||
0xC8 => dma.*[2].setDmasad(setU32L(dma.*[2].sad, value)),
|
||||
0xCA => dma.*[2].setDmasad(setU32H(dma.*[2].sad, value)),
|
||||
0xCC => dma.*[2].setDmadad(setU32L(dma.*[2].dad, value)),
|
||||
0xCE => dma.*[2].setDmadad(setU32H(dma.*[2].dad, value)),
|
||||
0xC8 => dma.*[2].setDmasad(setLo(u32, dma.*[2].sad, value)),
|
||||
0xCA => dma.*[2].setDmasad(setHi(u32, dma.*[2].sad, value)),
|
||||
0xCC => dma.*[2].setDmadad(setLo(u32, dma.*[2].dad, value)),
|
||||
0xCE => dma.*[2].setDmadad(setHi(u32, dma.*[2].dad, value)),
|
||||
0xD0 => dma.*[2].setDmacntL(value),
|
||||
0xD2 => dma.*[2].setDmacntH(value),
|
||||
|
||||
0xD4 => dma.*[3].setDmasad(setU32L(dma.*[3].sad, value)),
|
||||
0xD6 => dma.*[3].setDmasad(setU32H(dma.*[3].sad, value)),
|
||||
0xD8 => dma.*[3].setDmadad(setU32L(dma.*[3].dad, value)),
|
||||
0xDA => dma.*[3].setDmadad(setU32H(dma.*[3].dad, value)),
|
||||
0xD4 => dma.*[3].setDmasad(setLo(u32, dma.*[3].sad, value)),
|
||||
0xD6 => dma.*[3].setDmasad(setHi(u32, dma.*[3].sad, value)),
|
||||
0xD8 => dma.*[3].setDmadad(setLo(u32, dma.*[3].dad, value)),
|
||||
0xDA => dma.*[3].setDmadad(setHi(u32, dma.*[3].dad, value)),
|
||||
0xDC => dma.*[3].setDmacntL(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 }),
|
||||
|
@ -283,11 +286,3 @@ const DmaKind = enum(u2) {
|
|||
VBlank,
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@ const Bus = @import("../Bus.zig");
|
|||
const DmaController = @import("dma.zig").DmaController;
|
||||
const Scheduler = @import("../scheduler.zig").Scheduler;
|
||||
|
||||
const setHi = util.setLo;
|
||||
const setLo = util.setHi;
|
||||
|
||||
const log = std.log.scoped(.@"I/O");
|
||||
|
||||
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_0024 => bus.ppu.aff_bg[0].pc = @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_002A => bus.ppu.aff_bg[0].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[0].x) & 0x0000_FFFF | (@as(u32, value) << 16)),
|
||||
0x0400_002C => bus.ppu.aff_bg[0].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[0].y) & 0xFFFF_0000 | 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_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, setHi(u32, @bitCast(u32, bus.ppu.aff_bg[0].x), 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, setHi(u32, @bitCast(u32, bus.ppu.aff_bg[0].y), value)),
|
||||
0x0400_0030 => bus.ppu.aff_bg[1].pa = @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_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_003A => bus.ppu.aff_bg[1].x = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[1].x) & 0x0000_FFFF | (@as(u32, value) << 16)),
|
||||
0x0400_003C => bus.ppu.aff_bg[1].y = @bitCast(i32, @bitCast(u32, bus.ppu.aff_bg[1].y) & 0xFFFF_0000 | 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_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, setHi(u32, @bitCast(u32, bus.ppu.aff_bg[1].x), 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, setHi(u32, @bitCast(u32, bus.ppu.aff_bg[1].y), value)),
|
||||
0x0400_0040 => bus.ppu.win.h[0].raw = value,
|
||||
0x0400_0042 => bus.ppu.win.h[1].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) {
|
||||
// Display
|
||||
0x0400_0004 => bus.ppu.dispstat.raw = (bus.ppu.dispstat.raw & 0xFF00) | value,
|
||||
0x0400_0005 => bus.ppu.dispstat.raw = (@as(u16, value) << 8) | (bus.ppu.dispstat.raw & 0xFF),
|
||||
0x0400_0008 => bus.ppu.bg[0].cnt.raw = (bus.ppu.bg[0].cnt.raw & 0xFF00) | value,
|
||||
0x0400_0009 => bus.ppu.bg[0].cnt.raw = (@as(u16, value) << 8) | (bus.ppu.bg[0].cnt.raw & 0xFF),
|
||||
0x0400_000A => bus.ppu.bg[1].cnt.raw = (bus.ppu.bg[1].cnt.raw & 0xFF00) | value,
|
||||
0x0400_000B => bus.ppu.bg[1].cnt.raw = (@as(u16, value) << 8) | (bus.ppu.bg[1].cnt.raw & 0xFF),
|
||||
0x0400_0048 => bus.ppu.win.setInL(value),
|
||||
0x0400_0049 => bus.ppu.win.setInH(value),
|
||||
0x0400_004A => bus.ppu.win.setOutL(value),
|
||||
0x0400_0054 => bus.ppu.bldy.raw = (bus.ppu.bldy.raw & 0xFF00) | value,
|
||||
0x0400_0004 => bus.ppu.dispstat.raw = setLo(u16, bus.ppu.dispstat.raw, value),
|
||||
0x0400_0005 => bus.ppu.dispstat.raw = setHi(u16, bus.ppu.dispstat.raw, 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 = setHi(u16, bus.ppu.bg[0].cnt.raw, 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 = setHi(u16, bus.ppu.bg[1].cnt.raw, value),
|
||||
0x0400_0048 => bus.ppu.win.in.raw = setLo(u16, bus.ppu.win.in.raw, value),
|
||||
0x0400_0049 => bus.ppu.win.in.raw = setHi(u16, bus.ppu.win.in.raw, value),
|
||||
0x0400_004A => bus.ppu.win.out.raw = setLo(u16, bus.ppu.win.out.raw, value),
|
||||
0x0400_0054 => bus.ppu.bldy.raw = setLo(u16, bus.ppu.bldy.raw, value),
|
||||
|
||||
// Sound
|
||||
0x0400_0060...0x0400_00A7 => apu.write(T, &bus.apu, address, value),
|
||||
|
|
|
@ -808,18 +808,6 @@ const Window = struct {
|
|||
self.in.raw = @truncate(u16, value);
|
||||
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 {
|
||||
|
|
29
src/util.zig
29
src/util.zig
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue