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

[psyqo] basic "hello" sample doesn't work on Mednafen #1769

Open
eliasdaler opened this issue Oct 8, 2024 · 3 comments
Open

[psyqo] basic "hello" sample doesn't work on Mednafen #1769

eliasdaler opened this issue Oct 8, 2024 · 3 comments

Comments

@eliasdaler
Copy link
Contributor

The psyqo applications (even basic ones) don't seem to work on Mednafen - here's a "hello" sample - it hangs somewhere after the first frame (but seems to boot and do a clear):

image

~/work/ps1dev$ mednafen --version
Starting Mednafen 1.32.1
 Build information:
   Compiled with gcc 13.2.0
   Compiled against zlib 1.3, running with zlib 1.3.1(flags=0x000000a9)
   Compiled against SDL 2.30.1(SDL-release-2.30.1-0-g5adbf3765 (Debian 2.30.1+dfsg-4)), running with SDL 2.30.7(SDL-release-2.30.7-0-g9519b9916 (Debian 2.30.7+dfsg-1))
   Running with libFLAC 1.4.3
 Base directory: /home/eliasdaler/.mednafen
 Emulation modules: apple2 nes snes gb gba pce lynx md pcfx ngp psx ss ssfplay vb wswan sms gg sasplay snes_faust pce_fast demo cdplay

Here's a .cue/.iso of the demo I built:

game.zip

And here's the output of "warnings" psx.dbg_mask of Mednafen - not sure if it's relevant, because most of the warnings happen during boot logo:
dbg_out.txt

@nicolasnoble
Copy link
Member

I mean, supporting all emulators out there is going to be difficult. The main loop is definitely different from the typical one from psyq, and there's absolutely a few tricks used here and there that are unusual, even though I tried to avoid really nasty stuff which I know would've been hell to work out on emulators.

My point being, this feels more like this belongs to the mednafen repository than anything else. I'm more than happy to help locate what the emulator is doing that's not proper, but it's also likely documented in the psx-spx, so emulators following it would have no issues.

My hunch is how psyqo is handling DMA transfers, which uses documented behavior of the DMA hardware registers but which is rarely used by games. Note that I said "rarely" , not "never".

This code, basically:

Kernel::registerDmaEvent(Kernel::DMA::GPU, [this]() {
eastl::atomic_signal_fence(eastl::memory_order_acquire);
uint32_t mode = (DMA_CTRL[DMA_GPU].CHCR & 0x00000600) >> 9;
switch (mode) {
case 1: { // was a normal DMA
auto chainNext = m_chainNext;
if (!chainNext) break;
// We just processed a block which was too big, so now we need to send the next one
// Loading the next header
uint32_t head = *chainNext;
uint32_t count = head >> 24;
if (count > (c_chainThreshold / 4)) {
// next one still too big
m_chainNext = head == 0xff0000 ? nullptr : reinterpret_cast<uint32_t *>(head & 0x7fffff);
scheduleNormalDMA(reinterpret_cast<uintptr_t>(chainNext) + 4, count);
} else {
// next one is small enough
m_chainNext = nullptr;
scheduleChainedDMA(reinterpret_cast<uintptr_t>(chainNext));
}
return;
}
case 2: { // was a linked DMA
uint32_t madr = DMA_CTRL[DMA_GPU].MADR;
if (madr != 0xff0000) {
madr &= 0x7fffff;
// Did we get interrupted in the middle of a chain?
// It means we linked a node too big for the DMA engine to handle,
// so we need to send it manually
uint32_t *next = reinterpret_cast<uint32_t *>(madr | 0x80000000);
uint32_t head = *next;
uint32_t count = head >> 24;
head &= 0xffffff;
if (head != 0xff0000) {
m_chainNext = reinterpret_cast<uint32_t *>(head & 0x7fffff);
}
scheduleNormalDMA(madr + 4, count);
return;
}
} break;
}
// GPU back in Fifo polling mode, in case we were uploading to VRAM
Hardware::GPU::Ctrl = 0x04000001;
if (m_flushCacheAfterDMA) {
Prim::FlushCache fc;
sendPrimitive(fc);
m_flushCacheAfterDMA = false;
}
checkOTCAndTriggerCallback();
});

I know I surprised @stenzek with it, who had to tweak some details of his own implementation in Duckstation.

Note this works fine in older but proper emulators like Xebra.

@eliasdaler
Copy link
Contributor Author

My point being, this feels more like this belongs to the mednafen repository than anything else. I'm more than happy to help locate what the emulator is doing that's not proper, but it's also likely documented in the psx-spx, so emulators following it would have no issues.

Yes, I understand that it might be mednafen doing wrong things, so it would be good if you could take a look so that I don't come to them with the code and it turns out that it's the psyqo issue. If it's mednafen doing things wrong, I'll report it to them. :)

It would be great to support mednafen as well as it's yet another data point for some bugs which show up on HW, but don't show up in Redux/Duckstation.

@nicolasnoble
Copy link
Member

Right, we can try and narrow it down a bit, but FYI, there's also emulators like older PCSX, ePSXe, or even no$psx, which also struggle with this code, afaik. Basically, they don't properly update the DMA hardware registers upon completion, and psyqo heavily relies on that to avoid a way more costly back-and-forth to the main loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants