Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding DMA test to Redux. #1538

Merged
merged 14 commits into from
Jan 16, 2024
Merged
22 changes: 21 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/pcsx-redux",
"args": [],
"args": ["-stdout", "-lua_stdout"],
"stopAtEntry": false,
"preLaunchTask": "make",
"cwd": "${workspaceFolder}",
Expand All @@ -211,6 +211,26 @@
"ignoreFailures": true
}
]
},

{
"name": "(gdb) Launch PCSX-Redux DMA test",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/pcsx-redux-tests",
"args": ["--gtest_filter=DMA.Interpreter*"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
6 changes: 3 additions & 3 deletions src/core/gpu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ uint32_t PCSX::GPU::gpuDmaChainSize(uint32_t addr) {
size = 1;

do {
addr &= 0x1ffffc;
addr &= 0x7ffffc;

if (DMACommandCounter++ > 2000000) break;
if (CheckForEndlessLoop(addr)) break;
Expand All @@ -446,7 +446,7 @@ uint32_t PCSX::GPU::gpuDmaChainSize(uint32_t addr) {
size += head >> 24;

// next 32-bit pointer
addr = head & 0xffffff;
addr = head & 0xfffffc;
size += 1;
} while (!(addr & 0x800000)); // contrary to some documentation, the end-of-linked-list marker is not actually
// 0xFF'FFFF any pointer with bit 23 set will do.
Expand Down Expand Up @@ -663,7 +663,7 @@ void PCSX::GPU::chainedDMAWrite(const uint32_t *memory, uint32_t hwAddr) {
}

// next 32-bit pointer
addr = header & 0xffffff;
addr = header & 0xfffffc;
} while (!(addr & 0x800000)); // contrary to some documentation, the end-of-linked-list marker is not actually
// 0xFF'FFFF any pointer with bit 23 set will do.
}
Expand Down
4 changes: 4 additions & 0 deletions src/core/psxcounters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ uint32_t PCSX::Counters::readCounter(uint32_t index) {
update();
uint32_t count = readCounterInternal(index);

#if 0
// Parasite Eve 2 fix - artificial clock jitter based on PCSX::Emulator::BIAS
// TODO: any other games depend on getting excepted value from RCNT?
if (PCSX::g_emulator->config().HackFix && index == 2 && m_rcnts[index].counterState == CountToTarget &&
Expand Down Expand Up @@ -305,6 +306,7 @@ uint32_t PCSX::Counters::readCounter(uint32_t index) {
cylast = PCSX::g_emulator->m_cpu->m_regs.cycle;
clast = count;
}
#endif

verboseLog(2, "[RCNT %i] rcount: %x\n", index, count);
return count;
Expand All @@ -331,9 +333,11 @@ void PCSX::Counters::calculateHsync() {
if (PCSX::g_emulator->config().VSyncWA) {
m_HSyncTotal[PCSX::g_emulator->settings.get<PCSX::Emulator::SettingVideo>()] =
m_HSyncTotal[PCSX::g_emulator->settings.get<PCSX::Emulator::SettingVideo>()] / PCSX::Emulator::BIAS;
#if 0
} else if (PCSX::g_emulator->config().HackFix) {
m_HSyncTotal[PCSX::g_emulator->settings.get<PCSX::Emulator::SettingVideo>()] =
m_HSyncTotal[PCSX::g_emulator->settings.get<PCSX::Emulator::SettingVideo>()] + 1;
#endif
}
}

Expand Down
1 change: 0 additions & 1 deletion src/core/psxemulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@ class Emulator {
uint32_t RewindInterval = 0;
uint32_t AltSpeed1 = 0; // Percent relative to natural speed.
uint32_t AltSpeed2 = 0;
uint8_t HackFix = 0;
bool OverClock = false; // enable overclocking
float PsxClock = 0.0f;
// PGXP variables
Expand Down
141 changes: 38 additions & 103 deletions src/core/psxhw.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/***************************************************************************

Check notice on line 1 in src/core/psxhw.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Overall Code Complexity

The mean cyclomatic complexity decreases from 15.15 to 13.62, threshold = 4. This file has many conditional statements (e.g. if, for, while) across its implementation, leading to lower code health. Avoid adding more conditionals.
* Copyright (C) 2023 PCSX-Redux authors *
* *
* This program is free software; you can redistribute it and/or modify *
Expand Down Expand Up @@ -310,39 +310,7 @@
break;
case 0x1f801824:
hard = g_emulator->m_mdec->read1();
break;

Check notice on line 313 in src/core/psxhw.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Complex Method

PCSX::HW::read32 decreases in cyclomatic complexity from 32 to 24, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
case 0x1f8010a0:
hard = g_emulator->m_mem->readHardwareRegister<0x10a0>();
PSXHW_LOG("DMA2 MADR 32bit read %x\n", hard);
return hard;
case 0x1f8010a4:
hard = g_emulator->m_mem->readHardwareRegister<0x10a4>();
PSXHW_LOG("DMA2 BCR 32bit read %x\n", hard);
return hard;
case 0x1f8010a8:
hard = g_emulator->m_mem->readHardwareRegister<0x10a8>();
PSXHW_LOG("DMA2 CHCR 32bit read %x\n", hard);
return hard;
case 0x1f8010b0:
hard = g_emulator->m_mem->readHardwareRegister<0x10b0>();
PSXHW_LOG("DMA3 MADR 32bit read %x\n", hard);
return hard;
case 0x1f8010b4:
hard = g_emulator->m_mem->readHardwareRegister<0x10b4>();
PSXHW_LOG("DMA3 BCR 32bit read %x\n", hard);
return hard;
case 0x1f8010b8:
hard = g_emulator->m_mem->readHardwareRegister<0x10b8>();
PSXHW_LOG("DMA3 CHCR 32bit read %x\n", hard);
return hard;
case 0x1f8010f0:
hard = g_emulator->m_mem->readHardwareRegister<0x10f0>();
PSXHW_LOG("DMA PCR 32bit read %x\n", hard);
return hard;
case 0x1f8010f4:
hard = g_emulator->m_mem->readHardwareRegister<0x10f4>();
PSXHW_LOG("DMA ICR 32bit read %x\n", hard);
return hard;
// time for rootcounters :)
case 0x1f801100:
hard = g_emulator->m_counters->readCounter(0);
Expand Down Expand Up @@ -652,112 +620,81 @@
break;
case 0x1f801080:
PSXHW_LOG("DMA0 MADR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x1080>(value);
break; // DMA0 madr
case 0x1f801084:
PSXHW_LOG("DMA0 BCR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x1084>(value);
break; // DMA0 bcr
g_emulator->m_mem->setMADR<0>(value & 0xffffff);
return;

Check warning on line 624 in src/core/psxhw.cc

View check run for this annotation

Codecov / codecov/patch

src/core/psxhw.cc#L623-L624

Added lines #L623 - L624 were not covered by tests
case 0x1f801088:
PSXHW_LOG("DMA0 CHCR 32bit write %x\n", value);
dmaExec<0>(value); // DMA0 chcr (MDEC in DMA)
break;
return;
case 0x1f801090:
PSXHW_LOG("DMA1 MADR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x1090>(value);
break; // DMA1 madr
case 0x1f801094:
PSXHW_LOG("DMA1 BCR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x1094>(value);
break; // DMA1 bcr
g_emulator->m_mem->setMADR<1>(value & 0xffffff);
return;
case 0x1f801098:
PSXHW_LOG("DMA1 CHCR 32bit write %x\n", value);
dmaExec<1>(value); // DMA1 chcr (MDEC out DMA)
break;
return;
case 0x1f8010a0:
PSXHW_LOG("DMA2 MADR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x10a0>(value);
break; // DMA2 madr
case 0x1f8010a4:
PSXHW_LOG("DMA2 BCR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x10a4>(value);
break; // DMA2 bcr
case 0x1f8010a8: {
g_emulator->m_mem->setMADR<2>(value & 0xffffff);
return;
case 0x1f8010a8:
PSXHW_LOG("DMA2 CHCR 32bit write %x\n", value);

Check notice on line 642 in src/core/psxhw.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ No longer an issue: Complex Conditional

PCSX::HW::write32 no longer has a complex conditional
/* A hack that makes Vampire Hunter D title screen visible,
* but makes Tomb Raider II water effect to stay opaque
* Root cause for this problem is that when DMA2 is issued
* the whole chain is incomplete and still being built by
* the game. In order for this to work properly, without hacks,
* we need the GPU rendering to delay more accurately, instead of
* rendering virtually immediately.
*/
auto &mem = g_emulator->m_mem;
uint32_t bcr = mem->readHardwareRegister<0x1084 + 2 * 0x10>();
uint32_t chcr = value;
mem->setCHCR<2>(value);

if (m_dmaGpuListHackEn && (chcr == 0x00000401) && (bcr == 0x0)) {
uint32_t madr = mem->readHardwareRegister<0x1080 + 2 * 0x10>();
dma2(madr, bcr, chcr);
break;
}
dmaExec<2>(value); // DMA2 chcr (GPU DMA)
chcr = mem->getCHCR<2>();
if (g_emulator->config().HackFix && chcr == 0x1000401) m_dmaGpuListHackEn = true;
} break;
return;
case 0x1f8010b0:
PSXHW_LOG("DMA3 MADR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x10b0>(value);
break; // DMA3 madr
case 0x1f8010b4:
PSXHW_LOG("DMA3 BCR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x10b4>(value);
break; // DMA3 bcr
g_emulator->m_mem->setMADR<3>(value & 0xffffff);
return;
case 0x1f8010b8:
PSXHW_LOG("DMA3 CHCR 32bit write %x\n", value);
dmaExec<3>(value); // DMA3 chcr (CDROM DMA)
break;
return;
case 0x1f8010c0:
PSXHW_LOG("DMA4 MADR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x10c0>(value);
break; // DMA4 madr
case 0x1f8010c4:
PSXHW_LOG("DMA4 BCR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x10c4>(value);
break; // DMA4 bcr
g_emulator->m_mem->setMADR<4>(value & 0xffffff);
return;
case 0x1f8010c8:
PSXHW_LOG("DMA4 CHCR 32bit write %x\n", value);
dmaExec<4>(value); // DMA4 chcr (SPU DMA)
break;

return;
case 0x1f8010d0:
PSXHW_LOG("DMA5 MADR 32bit write %x\n", value);
g_emulator->m_mem->setMADR<5>(value & 0xffffff);
return;
#if 0
case 0x1f8010d0: break; //DMA5write_madr();
case 0x1f8010d4: break; //DMA5write_bcr();
case 0x1f8010d8: break; //DMA5write_chcr(); // Not needed
case 0x1f8010d8:
PSXHW_LOG("DMA5 CHCR 32bit write %x\n", value);
dmaExec<5>(value); // DMA5 chcr (PIO DMA)
return;
#endif
case 0x1f8010e0:
PSXHW_LOG("DMA6 MADR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x10e0>(value);
break; // DMA6 bcr
case 0x1f8010e4:
PSXHW_LOG("DMA6 BCR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x10e4>(value);
break; // DMA6 bcr
g_emulator->m_mem->setMADR<6>(value & 0xffffff);
return;
case 0x1f8010e8:
PSXHW_LOG("DMA6 CHCR 32bit write %x\n", value);
dmaExec<6>(value); // DMA6 chcr (OT clear)
break;
return;
case 0x1f8010f0:
// TODO: check if toggling PCR triggers pending DMAs.
PSXHW_LOG("DMA PCR 32bit write %x\n", value);
g_emulator->m_mem->writeHardwareRegister<0x10f0>(value);
break;
case 0x1f8010f4:
PSXHW_LOG("DMA ICR 32bit write %x\n", value);
{
auto &mem = g_emulator->m_mem;
uint32_t icr = (~value) & mem->readHardwareRegister<Memory::DMA_ICR>();
mem->writeHardwareRegister<Memory::DMA_ICR>(((icr ^ value) & 0xffffff) ^ icr);
uint32_t icr = mem->readHardwareRegister<Memory::DMA_ICR>();
uint32_t ack = value & 0b0'1111111'000000000'000000000'000000;
ack ^= 0b0'1111111'000000000'000000000'000000;
value &= 0b0'0000000'111111111'000000000'111111;
icr &= ack;
icr |= value;
if ((icr & 0x7f008000) != 0) {
icr |= 0x80000000;
}
mem->writeHardwareRegister<Memory::DMA_ICR>(icr);

Check warning on line 697 in src/core/psxhw.cc

View check run for this annotation

Codecov / codecov/patch

src/core/psxhw.cc#L691-L697

Added lines #L691 - L697 were not covered by tests
return;
}
case 0x1f801014:
Expand All @@ -770,10 +707,8 @@
break;
case 0x1f801814:
PSXHW_LOG("GPU STATUS 32bit write %x\n", value);
if (value & 0x8000000) m_dmaGpuListHackEn = false;
g_emulator->m_gpu->writeStatus(value);
break;

Check notice on line 711 in src/core/psxhw.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Complex Method

PCSX::HW::write32 decreases in cyclomatic complexity from 56 to 44, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

case 0x1f801820:
g_emulator->m_mdec->write0(value);
break;
Expand Down
46 changes: 40 additions & 6 deletions src/core/psxhw.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@
void write32(uint32_t add, uint32_t value);

private:
bool m_dmaGpuListHackEn = false;

void dma0(uint32_t madr, uint32_t bcr, uint32_t chcr);
void dma1(uint32_t madr, uint32_t bcr, uint32_t chcr);
void dma2(uint32_t madr, uint32_t bcr, uint32_t chcr);
Expand All @@ -49,10 +47,11 @@
void dmaExec(uint32_t chcr) {
auto &mem = g_emulator->m_mem;
mem->setCHCR<n>(chcr);
uint32_t pcr = mem->readHardwareRegister<0x10f0>();
if ((chcr & 0x01000000) && (pcr & (8 << (n * 4)))) {
uint32_t madr = mem->readHardwareRegister<0x1080 + n * 0x10>();
uint32_t bcr = mem->readHardwareRegister<0x1084 + n * 0x10>();
if ((chcr & 0x01000000) && mem->template isDMAEnabled<n>()) {
uint32_t madr = mem->template getMADR<n>();
madr &= 0x7ffffc;
uint32_t bcr = mem->template getBCR<n>();
uint32_t mode = (chcr & 0x00000600) >> 9;
if constexpr (n == 0) {
dma0(madr, bcr, chcr);
} else if constexpr (n == 1) {
Expand All @@ -66,6 +65,41 @@
} else if constexpr (n == 6) {
dma6(madr, bcr, chcr);
}
if (mode == 2) {
uint32_t usedAddr[3] = {0xffffff, 0xffffff, 0xffffff};
uint32_t DMACommandCounter = 0;

do {
madr &= 0x7ffffc;

if (DMACommandCounter++ > 2000000) break;
if (madr == usedAddr[1]) break;
if (madr == usedAddr[2]) break;

if (madr < usedAddr[0]) {
usedAddr[1] = madr;
} else {
usedAddr[2] = madr;
}

usedAddr[0] = madr;
madr = SWAP_LEu32(*mem->getPointer<uint32_t>(madr)) & 0xffffff;
} while (!(madr & 0x800000));
if ((madr & 0xffffff) != 0xffffff) {
mem->dmaInterruptError();
}
} else {
uint32_t blocSize = bcr >> 16;
if (blocSize == 0) blocSize = 0x10000;
uint32_t size = blocSize * (bcr & 0xffff);
madr = madr + size * 4;
}
mem->template setMADR<n>(madr);
if (mode == 0) {
mem->template setBCR<n>(bcr & 0xffff0000);

Check warning on line 99 in src/core/psxhw.h

View check run for this annotation

Codecov / codecov/patch

src/core/psxhw.h#L99

Added line #L99 was not covered by tests
} else if (mode == 1) {
mem->template setBCR<n>(bcr & 0x0000ffff);
}
}
}
};
Expand Down
7 changes: 0 additions & 7 deletions src/core/psxmem.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/***************************************************************************

Check notice on line 1 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Code Duplication

reduced similar code in: PCSX::Memory::pointerRead,PCSX::Memory::pointerWrite. Avoid duplicated, aka copy-pasted, code inside the module. More duplication lowers the code health.

Check notice on line 1 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Overall Code Complexity

The mean cyclomatic complexity decreases from 9.00 to 8.68, threshold = 4. This file has many conditional statements (e.g. if, for, while) across its implementation, leading to lower code health. Avoid adding more conditionals.
* Copyright (C) 2023 PCSX-Redux authors *
* *
* This program is free software; you can redistribute it and/or modify *
Expand Down Expand Up @@ -617,20 +617,13 @@
switch (address) {
// IO regs that are safe to write to directly. For some of these,
// Writing a 8-bit/16-bit value actually writes the entire 32-bit reg, so they're not safe to write
// directly
case 0x1f801080:
case 0x1f801084:
case 0x1f801090:
case 0x1f801094:
case 0x1f8010a0:
case 0x1f8010a4:
case 0x1f8010b0:
case 0x1f8010b4:
case 0x1f8010c0:
case 0x1f8010c4:
case 0x1f8010d0:
case 0x1f8010d4:

Check notice on line 626 in src/core/psxmem.cc

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Complex Method

PCSX::Memory::pointerWrite decreases in cyclomatic complexity from 24 to 17, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
case 0x1f8010e0:
case 0x1f8010e4:
case 0x1f801074:
case 0x1f8010f0:
Expand Down
Loading
Loading