This commit is contained in:
2026-03-23 12:11:07 +01:00
commit e64eb40b38
4573 changed files with 3117439 additions and 0 deletions
+119
View File
@@ -0,0 +1,119 @@
#include <Core.hpp>
#include <log.hpp>
namespace n64 {
AI::AI() { Reset(); }
void AI::Reset() {
dmaEnable = false;
dacRate = 0;
bitrate = 0;
dmaCount = 0;
dmaAddrCarry = false;
cycles = 0;
dmaLen = {};
dmaAddr = {};
dac = {44100, N64_CPU_FREQ / dac.freq, 16};
device.Reset();
}
// https://github.com/ares-emulator/ares/blob/master/ares/n64/ai/io.cpp
// https://github.com/ares-emulator/ares/blob/master/LICENSE
auto AI::Read(const u32 addr) const -> u32 {
if (addr == 0x0450000C) {
u32 val = 0;
val |= (dmaCount > 1);
val |= 1 << 20;
val |= 1 << 24;
val |= (dmaEnable << 25);
val |= (dmaCount > 0) << 30;
val |= (dmaCount > 1) << 31;
return val;
}
return dmaLen[0];
}
void AI::Write(const u32 addr, const u32 val) {
n64::Mem& mem = n64::Core::GetMem();
switch (addr) {
case 0x04500000:
if (dmaCount < 2) {
dmaAddr[dmaCount] = val & 0xFFFFFF & ~7;
}
break;
case 0x04500004:
{
const u32 len = (val & 0x3FFFF) & ~7;
if (dmaCount < 2) {
if (dmaCount == 0)
mem.mmio.mi.InterruptRaise(MI::Interrupt::AI);
dmaLen[dmaCount] = len;
dmaCount++;
}
}
break;
case 0x04500008:
dmaEnable = val & 1;
break;
case 0x0450000C:
mem.mmio.mi.InterruptLower(MI::Interrupt::AI);
break;
case 0x04500010:
{
const u32 oldDacFreq = dac.freq;
dacRate = val & 0x3FFF;
dac.freq = std::max(1.f, (float)GetVideoFrequency(mem.IsROMPAL()) / (dacRate + 1)) * 1.037;
dac.period = GetVideoFrequency(mem.IsROMPAL()) / dac.freq;
if (oldDacFreq != dac.freq) {
device.AdjustSampleRate(dac.freq);
}
}
break;
case 0x04500014:
bitrate = val & 0xF;
dac.precision = bitrate + 1;
break;
default:
panic("Unhandled AI write at addr {:08X} with val {:08X}", addr, val);
}
}
void AI::Step(const u32 cpuCycles, const float volumeL, const float volumeR) {
n64::Mem& mem = n64::Core::GetMem();
cycles += cpuCycles;
while (cycles > dac.period) {
if (dmaCount == 0) {
return;
}
if (dmaLen[0] && dmaEnable) {
const u32 addrHi = (dmaAddr[0] >> 13) + dmaAddrCarry & 0x7FF;
dmaAddr[0] = addrHi << 13 | dmaAddr[0] & 0x1FFF;
const u32 data = mem.mmio.rdp.ReadRDRAM<u32>(dmaAddr[0]);
const s16 l = s16(data >> 16);
const s16 r = s16(data);
if (volumeR > 0 && volumeL > 0) {
device.PushSample((float)l / std::numeric_limits<s16>::max(), volumeL, (float)r / std::numeric_limits<s16>::max(), volumeR);
}
const u32 addrLo = dmaAddr[0] + 4 & 0x1FFF;
dmaAddr[0] = dmaAddr[0] & ~0x1FFF | addrLo;
dmaAddrCarry = addrLo == 0;
dmaLen[0] -= 4;
}
if (!dmaLen[0]) {
if (--dmaCount > 0) {
mem.mmio.mi.InterruptRaise(MI::Interrupt::AI);
dmaAddr[0] = dmaAddr[1];
dmaLen[0] = dmaLen[1];
}
}
cycles -= dac.period;
}
}
} // namespace n64