mirror of
https://github.com/rafaelvcaetano/melonDS-android-lib.git
synced 2024-11-23 05:40:09 +00:00
more DSP unfucking: make Teakra directly use melonDS's NWRAM banks instead of trying to translate to a flat buffer, fixes bugs with the way the memory banks are ordered etc
This commit is contained in:
parent
a8fba8cc34
commit
cdd05c10b4
64
src/DSi.cpp
64
src/DSi.cpp
@ -991,23 +991,22 @@ void MapNWRAM_A(u32 num, u8 val)
|
||||
MBK[1][mbkn] = MBK[0][mbkn];
|
||||
|
||||
// When we only update the mapping on the written MBK, we will
|
||||
// have priority of the last witten MBK over the others
|
||||
// However the hardware has a fixed order. Therefor
|
||||
// have priority of the last written MBK over the others
|
||||
// However the hardware has a fixed order. Therefore
|
||||
// we need to iterate through them all in a fixed order and update
|
||||
// the mapping, so the result is independend on the MBK write order
|
||||
for (unsigned int part = 0; part < 4; part++)
|
||||
// the mapping, so the result is independent on the MBK write order
|
||||
for (int part = 0; part < 4; part++)
|
||||
{
|
||||
NWRAMMap_A[0][part] = NULL;
|
||||
NWRAMMap_A[1][part] = NULL;
|
||||
NWRAMMap_A[0][part] = nullptr;
|
||||
NWRAMMap_A[1][part] = nullptr;
|
||||
}
|
||||
for (int part = 3; part >= 0; part--)
|
||||
{
|
||||
u8* ptr = &NWRAM_A[part << 16];
|
||||
|
||||
if ((MBK[0][0 + (part / 4)] >> ((part % 4) * 8)) & 0x80)
|
||||
u8 mVal = (MBK[0][0 + (part >> 2)] >> ((part & 3) * 8)) & 0xFD;
|
||||
if (mVal & 0x80)
|
||||
{
|
||||
u8 mVal = (MBK[0][0 + (part / 4)] >> ((part % 4) * 8)) & 0xfd;
|
||||
|
||||
NWRAMMap_A[mVal & 0x03][(mVal >> 2) & 0x3] = ptr;
|
||||
}
|
||||
}
|
||||
@ -1039,30 +1038,24 @@ void MapNWRAM_B(u32 num, u8 val)
|
||||
MBK[1][mbkn] = MBK[0][mbkn];
|
||||
|
||||
// When we only update the mapping on the written MBK, we will
|
||||
// have priority of the last witten MBK over the others
|
||||
// However the hardware has a fixed order. Therefor
|
||||
// have priority of the last written MBK over the others
|
||||
// However the hardware has a fixed order. Therefore
|
||||
// we need to iterate through them all in a fixed order and update
|
||||
// the mapping, so the result is independend on the MBK write order
|
||||
for (unsigned int part = 0; part < 8; part++)
|
||||
// the mapping, so the result is independent on the MBK write order
|
||||
for (int part = 0; part < 8; part++)
|
||||
{
|
||||
NWRAMMap_B[0][part] = NULL;
|
||||
NWRAMMap_B[1][part] = NULL;
|
||||
NWRAMMap_B[2][part] = NULL;
|
||||
NWRAMMap_B[0][part] = nullptr;
|
||||
NWRAMMap_B[1][part] = nullptr;
|
||||
NWRAMMap_B[2][part] = nullptr;
|
||||
}
|
||||
for (int part = 7; part >= 0; part--)
|
||||
{
|
||||
u8* ptr = &NWRAM_B[part << 15];
|
||||
|
||||
if (part == num)
|
||||
u8 mVal = (MBK[0][1 + (part >> 2)] >> ((part & 3) * 8)) & 0xFF;
|
||||
if (mVal & 0x80)
|
||||
{
|
||||
DSi_DSP::OnMBKCfg('B', num, oldval, val, ptr);
|
||||
}
|
||||
|
||||
if ((MBK[0][1 + (part / 4)] >> ((part % 4) * 8)) & 0x80)
|
||||
{
|
||||
u8 mVal = (MBK[0][1 + (part / 4)] >> ((part % 4) * 8)) & 0xff;
|
||||
if (mVal & 0x02) mVal &= 0xFE;
|
||||
|
||||
NWRAMMap_B[mVal & 0x03][(mVal >> 2) & 0x7] = ptr;
|
||||
}
|
||||
}
|
||||
@ -1094,28 +1087,23 @@ void MapNWRAM_C(u32 num, u8 val)
|
||||
MBK[1][mbkn] = MBK[0][mbkn];
|
||||
|
||||
// When we only update the mapping on the written MBK, we will
|
||||
// have priority of the last witten MBK over the others
|
||||
// However the hardware has a fixed order. Therefor
|
||||
// have priority of the last written MBK over the others
|
||||
// However the hardware has a fixed order. Therefore
|
||||
// we need to iterate through them all in a fixed order and update
|
||||
// the mapping, so the result is independend on the MBK write order
|
||||
for (unsigned int part = 0; part < 8; part++)
|
||||
// the mapping, so the result is independent on the MBK write order
|
||||
for (int part = 0; part < 8; part++)
|
||||
{
|
||||
NWRAMMap_C[0][part] = NULL;
|
||||
NWRAMMap_C[1][part] = NULL;
|
||||
NWRAMMap_C[2][part] = NULL;
|
||||
NWRAMMap_C[0][part] = nullptr;
|
||||
NWRAMMap_C[1][part] = nullptr;
|
||||
NWRAMMap_C[2][part] = nullptr;
|
||||
}
|
||||
for (int part = 7; part >= 0; part--)
|
||||
{
|
||||
u8* ptr = &NWRAM_C[part << 15];
|
||||
|
||||
if (part == num)
|
||||
u8 mVal = MBK[0][3 + (part >> 2)] >> ((part & 3) * 8) & 0xFF;
|
||||
if (mVal & 0x80)
|
||||
{
|
||||
DSi_DSP::OnMBKCfg('C', num, oldval, val, ptr);
|
||||
}
|
||||
|
||||
if ((MBK[0][3 + (part / 4)] >> ((part % 4) * 8)) & 0x80)
|
||||
{
|
||||
u8 mVal = MBK[0][3 + (part / 4)] >> ((part % 4) *8) & 0xff;
|
||||
if (mVal & 0x02) mVal &= 0xFE;
|
||||
NWRAMMap_C[mVal & 0x03][(mVal >> 2) & 0x7] = ptr;
|
||||
}
|
||||
|
@ -89,6 +89,36 @@ void IrqSem()
|
||||
NDS::SetIRQ(0, NDS::IRQ_DSi_DSP);
|
||||
}
|
||||
|
||||
u16 DSPRead16(u32 addr)
|
||||
{
|
||||
if (!(addr & 0x40000))
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_B[2][(addr >> 15) & DSi::NWRAMMask[0][1]];
|
||||
return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_C[2][(addr >> 15) & DSi::NWRAMMask[0][2]];
|
||||
return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DSPWrite16(u32 addr, u16 val)
|
||||
{
|
||||
// TODO: does the rule for overlapping NWRAM slots also apply to the DSP side?
|
||||
|
||||
if (!(addr & 0x40000))
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_B[2][(addr >> 15) & DSi::NWRAMMask[0][1]];
|
||||
if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_C[2][(addr >> 15) & DSi::NWRAMMask[0][2]];
|
||||
if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioCb(std::array<s16, 2> frame)
|
||||
{
|
||||
// TODO
|
||||
@ -107,6 +137,11 @@ bool Init()
|
||||
|
||||
TeakraCore->SetSemaphoreHandler(IrqSem);
|
||||
|
||||
Teakra::SharedMemoryCallback smcb;
|
||||
smcb.read16 = DSPRead16;
|
||||
smcb.write16 = DSPWrite16;
|
||||
TeakraCore->SetSharedMemoryCallback(smcb);
|
||||
|
||||
// these happen instantaneously and without too much regard for bus aribtration
|
||||
// rules, so, this might have to be changed later on
|
||||
Teakra::AHBMCallback cb;
|
||||
@ -169,46 +204,6 @@ void SetRstLine(bool release)
|
||||
DSPTimestamp = NDS::ARM9Timestamp; // only start now!
|
||||
}
|
||||
|
||||
void OnMBKCfg(char bank, u32 slot, u8 oldcfg, u8 newcfg, u8* nwrambacking)
|
||||
{
|
||||
if (bank != 'B' && bank != 'C')
|
||||
{
|
||||
printf("WTF?? (DSP MBK recfg, nonsense bank '%c')\n", bank);
|
||||
return;
|
||||
}
|
||||
|
||||
bool olddsp = (oldcfg & 3) >= 2, // was mapped to the DSP
|
||||
newdsp = (newcfg & 3) >= 2; // will be mapped to the DSP
|
||||
|
||||
// nothing changes
|
||||
if (olddsp == newdsp)
|
||||
return;
|
||||
|
||||
const u8* src;
|
||||
u8* dst;
|
||||
|
||||
if (newdsp)
|
||||
{
|
||||
// need to map stuff to DSP memory (== Teakra-owned memory) from NWRAM
|
||||
src = nwrambacking;
|
||||
dst = &TeakraCore->GetDspMemory()[((newcfg >> 2) & 7) << 15];
|
||||
|
||||
if (bank == 'C') // C: DSP data (B: DSP code)
|
||||
dst += DataMemoryOffset*2;
|
||||
}
|
||||
else //if (olddsp)
|
||||
{
|
||||
// it was mapped to the DSP, but now we have to copy it out, back to NWRAM
|
||||
src = &TeakraCore->GetDspMemory()[((oldcfg >> 2) & 7) << 15];
|
||||
dst = nwrambacking;
|
||||
|
||||
if (bank == 'C') // C: DSP data (B: DSP code)
|
||||
src += DataMemoryOffset*2;
|
||||
}
|
||||
|
||||
memcpy(dst, src, 1<<15); // 1 full slot
|
||||
}
|
||||
|
||||
inline bool IsDSPCoreEnabled()
|
||||
{
|
||||
return (DSi::SCFG_Clock9 & (1<<1)) && SCFG_RST && (!(DSP_PCFG & (1<<0)));
|
||||
@ -395,7 +390,7 @@ u16 PDataDMAReadMMIO()
|
||||
|
||||
u8 Read8(u32 addr)
|
||||
{
|
||||
if (!IsDSPIOEnabled()) return 0;
|
||||
//if (!IsDSPIOEnabled()) return 0;
|
||||
DSPCatchUp();
|
||||
|
||||
addr &= 0x3F; // mirroring wheee
|
||||
@ -423,7 +418,7 @@ u8 Read8(u32 addr)
|
||||
u16 Read16(u32 addr)
|
||||
{
|
||||
//printf("DSP READ16 %d %08X %08X\n", IsDSPCoreEnabled(), addr, NDS::GetPC(0));
|
||||
if (!IsDSPIOEnabled()) return 0;
|
||||
//if (!IsDSPIOEnabled()) return 0;
|
||||
DSPCatchUp();
|
||||
|
||||
addr &= 0x3E; // mirroring wheee
|
||||
@ -472,7 +467,7 @@ u32 Read32(u32 addr)
|
||||
|
||||
void Write8(u32 addr, u8 val)
|
||||
{
|
||||
if (!IsDSPIOEnabled()) return;
|
||||
//if (!IsDSPIOEnabled()) return;
|
||||
DSPCatchUp();
|
||||
|
||||
addr &= 0x3F;
|
||||
@ -493,8 +488,8 @@ void Write8(u32 addr, u8 val)
|
||||
}
|
||||
void Write16(u32 addr, u16 val)
|
||||
{
|
||||
//printf("DSP WRITE16 %d %08X %08X %08X\n", IsDSPCoreEnabled(), addr, val, NDS::GetPC(0));
|
||||
if (!IsDSPIOEnabled()) return;
|
||||
printf("DSP WRITE16 %d %08X %08X %08X\n", IsDSPCoreEnabled(), addr, val, NDS::GetPC(0));
|
||||
//if (!IsDSPIOEnabled()) return;
|
||||
DSPCatchUp();
|
||||
|
||||
addr &= 0x3E;
|
||||
|
@ -53,9 +53,6 @@ void DSPCatchUpU32(u32 _);
|
||||
bool IsRstReleased();
|
||||
void SetRstLine(bool release);
|
||||
|
||||
// apply NWRAM settings
|
||||
void OnMBKCfg(char bank, u32 slot, u8 oldcfg, u8 newcfg, u8* nwrambacking);
|
||||
|
||||
// DSP_* regs (0x040043xx) (NOTE: checks SCFG_EXT)
|
||||
u8 Read8(u32 addr);
|
||||
void Write8(u32 addr, u8 val);
|
||||
|
@ -7,6 +7,11 @@
|
||||
|
||||
namespace Teakra {
|
||||
|
||||
struct SharedMemoryCallback {
|
||||
std::function<std::uint16_t(std::uint32_t address)> read16;
|
||||
std::function<void(std::uint32_t address, std::uint16_t value)> write16;
|
||||
};
|
||||
|
||||
struct AHBMCallback {
|
||||
std::function<std::uint8_t(std::uint32_t address)> read8;
|
||||
std::function<void(std::uint32_t address, std::uint8_t value)> write8;
|
||||
@ -25,9 +30,6 @@ public:
|
||||
|
||||
void Reset();
|
||||
|
||||
std::array<std::uint8_t, 0x80000>& GetDspMemory();
|
||||
const std::array<std::uint8_t, 0x80000>& GetDspMemory() const;
|
||||
|
||||
// APBP Data
|
||||
bool SendDataIsEmpty(std::uint8_t index) const;
|
||||
void SendData(std::uint8_t index, std::uint16_t value);
|
||||
@ -70,6 +72,7 @@ public:
|
||||
// core
|
||||
void Run(unsigned cycle);
|
||||
|
||||
void SetSharedMemoryCallback(const SharedMemoryCallback& callback);
|
||||
void SetAHBMCallback(const AHBMCallback& callback);
|
||||
|
||||
void SetAudioCallback(std::function<void(std::array<std::int16_t, 2>)> callback);
|
||||
|
@ -5,19 +5,21 @@
|
||||
|
||||
namespace Teakra {
|
||||
struct SharedMemory {
|
||||
std::array<u8, 0x80000> raw{};
|
||||
u16 ReadWord(u32 word_address) const {
|
||||
u32 byte_address = word_address * 2;
|
||||
u8 low = raw[byte_address];
|
||||
u8 high = raw[byte_address + 1];
|
||||
return low | ((u16)high << 8);
|
||||
return read_external16(word_address << 1);
|
||||
}
|
||||
void WriteWord(u32 word_address, u16 value) {
|
||||
u8 low = value & 0xFF;
|
||||
u8 high = value >> 8;
|
||||
u32 byte_address = word_address * 2;
|
||||
raw[byte_address] = low;
|
||||
raw[byte_address + 1] = high;
|
||||
write_external16(word_address << 1, value);
|
||||
}
|
||||
|
||||
void SetExternalMemoryCallback(
|
||||
std::function<u16(u32)> read16, std::function<void(u32, u16)> write16) {
|
||||
|
||||
read_external16 = std::move(read16);
|
||||
write_external16 = std::move(write16);
|
||||
}
|
||||
|
||||
std::function<u16(u32)> read_external16;
|
||||
std::function<void(u32, u16)> write_external16;
|
||||
};
|
||||
} // namespace Teakra
|
||||
|
@ -50,7 +50,6 @@ struct Teakra::Impl {
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
//shared_memory.raw.fill(0); // BAD!!!!
|
||||
miu.Reset();
|
||||
apbp_from_cpu.Reset();
|
||||
apbp_from_dsp.Reset();
|
||||
@ -71,14 +70,6 @@ void Teakra::Reset() {
|
||||
impl->Reset();
|
||||
}
|
||||
|
||||
std::array<std::uint8_t, 0x80000>& Teakra::GetDspMemory() {
|
||||
return impl->shared_memory.raw;
|
||||
}
|
||||
|
||||
const std::array<std::uint8_t, 0x80000>& Teakra::GetDspMemory() const {
|
||||
return impl->shared_memory.raw;
|
||||
}
|
||||
|
||||
void Teakra::Run(unsigned cycle) {
|
||||
impl->processor.Run(cycle);
|
||||
}
|
||||
@ -117,6 +108,9 @@ void Teakra::ClearSemaphore(std::uint16_t value) {
|
||||
void Teakra::MaskSemaphore(std::uint16_t value) {
|
||||
impl->apbp_from_dsp.MaskSemaphore(value);
|
||||
}
|
||||
void Teakra::SetSharedMemoryCallback(const SharedMemoryCallback& callback) {
|
||||
impl->shared_memory.SetExternalMemoryCallback(callback.read16, callback.write16);
|
||||
}
|
||||
void Teakra::SetAHBMCallback(const AHBMCallback& callback) {
|
||||
impl->ahbm.SetExternalMemoryCallback(callback.read8, callback.write8,
|
||||
callback.read16, callback.write16,
|
||||
|
Loading…
Reference in New Issue
Block a user