alttpo / sni

SNES Interface with gRPC API
MIT License
46 stars 11 forks source link

Issue Reconnecting to RetroArch on Linux #35

Open MattEqualsCoder opened 6 months ago

MattEqualsCoder commented 6 months ago

I'm working on a C# connector library that works with SNI, and I'm running into an issue with SNI and RetroArch on Linux. Using the bsnes-mercury (balanced) core.

Basically, when I first launch SNI and RetroArch, it works just fine. However, if I close RetroArch and reopen it, SNI will detect RetroArch in the list of devices, but when a message is sent to retrieve memory, SNI never returns anything.

Here's what I see in the SNI logs on the initial launch where it works when requesting memory:

2024/01/28 04:35:53.206589 retroarch: > READ_CORE_MEMORY 7e0010 1
2024/01/28 04:35:53.219883 retroarch: < READ_CORE_MEMORY 7e0010 01
2024/01/28 04:35:53.220155         /DeviceMemory/SingleRead:   13369745 ns: req=`uri:"ra://127.0.0.1:55355",request:{address:(FxPakPro $f50010 ExHiROM),size:0x1}`, rsp=`uri:"ra://127.0.0.1:55355",response:{address:(SnesABus $7e0010 ExHiROM),size:0x1}`

However, after restarting RetroArch, the only log entry I get is the following for requesting memory:

2024/01/28 04:36:04.584832 retroarch: > READ_CORE_MEMORY 7e0010 1

This becomes an even bigger issue due to the way that when launching a game in RetroArch it restarts RetroArch with a new process, so I've even had this happen if I boot and connect while in the RetroArch menu and just launching the game for the first time. When it gets stuck like this, the only solution is to restart SNI.

To illustrate this, I created a real simple C# app that you can find here: https://github.com/MattEqualsOverflow/SniTestApplication It's a really simple app that connects to SNI, gets the devices, then starts a loop to retrieve the current game state for ALttP(R) and print out the logs. Attached are the logs from Windows (which works fine) and Linux. Also attached is the SNI logs that show it working, then the subsequent failures after restarting the app.

LinuxLog.txt SniLog.log WindowsLog.txt

Some things to note:

Here's the Sni Test Application built for Linux: SniTestApplication.tar.gz](https://github.com/alttpo/sni/files/14075011/SniTestApplication.tar.gz). I think you need .net7 installed, and you'll want to run it via console.

JamesDunne commented 6 months ago

What version of RetroArch are you using? Does it have network_cmd_enable = true in its config?

The network command feature is typically not enabled by default in most releases of RetroArch that I know of. The LinuxLog.txt shows a deadline-exceeded grpc error which means SNI times out when trying to connect to RetroArch, likely due to the network command feature being disabled on RetroArch's side. This is probably why it works on Windows - the network command feature is likely enabled there.

It's good you have a deadline specified for the grpc call. SNI honors that in its back-end communications (with RetroArch in this case) and will cancel the operation if it exceeds the deadline given.

P.S. your WindowsLog.txt file is empty. :)

P.P.S. You should probably simplify your test program a bit: change the line _ = SendMessages(device.Uri); line to await SendMessages(device.Uri);, remove the _ = GetDevice(); from the catch handler, and move the infinite loop up into the GetDevice() Task around the await SendMessages(...); line and have the catch handler do break; there. Then you won't need the await Task.Delay(TimeSpan.FromSeconds(3));.

P.P.P.S. I've pretty much given up on supporting RetroArch at this point. It's got a terrible network protocol (UDP based), most cores don't work properly with the network command feature (bugs left 'n right), and in some more advanced scenarios it's nearly impossible to get past the bus mapping problems, and worst of all there is no standard way that memory chips are exposed to the network command feature so you have no idea what you're reading from / writing to depending on the core. The network command stuff does not appear to be a priority for the RA team to fix either.

MattEqualsCoder commented 6 months ago

It's RetroArch version 1.16.0 which I believe is the latest version (the build date is Jan 22 2024 at least), and yeah, the network_cmd_enable = true is turned on. It's able to connect and send messages just fine the first time just fine, it's only after reclosing and reopening that it fails. I can retest later, but I don't recall the issue happening with qusb2snes, so I don't think it's an issue on the RetroArch side.

Hah. Sorry about the Windows log being empty. Must have not saved the file before restarting my computer into Linux. lol You wouldnt see much of anything interesting other than it working after losing the connection and getting the devices again.

Good call on some of the refactors, though. I had to have this structure for some of the Lua scripts out there due to them not closing sockets all of the time. I sorta adapted it for the Sni connector without putting the thought that it was unnecessary. Hah.

MattEqualsCoder commented 6 months ago

Was just able to confirm that it does work just fine with qusb2snes. RetroArch connects and responds to memory requests, I close and reopen RetroArch, and once it reconnects it's able to request memory just fine. I was also able to replicate the issue with SNI and the Dunka Tracker. Opened everything up, and it tracks just fine, but when I close RetroArch and reopen it and get back into the game, subsequent locations aren't tracked.

Whatever the issue is, it appears to only be isolated to SNI.