flyinghead / flycast

Flycast is a multiplatform Sega Dreamcast, Naomi, Naomi 2 and Atomiswave emulator
GNU General Public License v2.0
1.35k stars 167 forks source link

[Xbox] mslug6 crashing via RetroArch #865

Open blisstik opened 1 year ago

blisstik commented 1 year ago

Please Note: This form is the minimum required information for submitting bugs.
Removing this form may lead to your issue being closed until it is completed.

Platform / OS / Hardware: XBOX Series S

Github hash: 673fb26

Hardware:

Description of the Issue

Launching Metal Slug 6 crashes when launched via RetroArch. I have deleted the nvmem and nvmem2 files, still the same issue.

Debugging Steps Tested

Logs Gathered


Please paste the contents of the log / logs here
You may leave this field blank if you have none.

Screenshots

(Replace this line with any issue screenshots)

blisstik commented 1 year ago

I'm not using any shaders for this core as it's broken anyways. But here is a log

[INFO] === Build =======================================
[INFO] CPU Model Name: Unknown
[INFO] Capabilities: MMX MMXEXT SSE SSE2 SSE3 SSE4 SSE4.2 AES AVX AVX2
[INFO] Built: Dec 13 2022
[INFO] Version: 1.14.0
[INFO] =================================================
[libretro ERROR] core/rend/dx11/dx11_shaders.cpp:606 E[RENDERER]: Pixel shader creation failed
[libretro ERROR] Verify Failed  : shader != nullptr
 in getShader -> /builds/libretro/flycast-upstream/core/rend/dx11/dx11_shaders.cpp : 481
[libretro ERROR] shell/libretro/libretro.cpp:3009 E[COMMON]: DEBUGBREAK!
flyinghead commented 1 year ago

Only this game is crashing? What about other naomi or dreamcast games? What was the last version of the flycast core that was working?

The dx11 shaders haven't changed in the last 8 months. Also it's not the compilation but the creation of the shader that's failing, which is very unexpected.

A more detailed log could help.

blisstik commented 1 year ago

That's the level 3 log I enabled for front-end and core. Let me try a log with just the core. Other SNK games are also crashing.

blisstik commented 1 year ago

Here's a better log

[INFO] [Core]: Using content: "E:\games\atomiswave\mslug6.zip".
[INFO] [Core]: Content ran for a total of: 00 hours, 00 minutes, 00 seconds.
[INFO] [Core]: Unloading core..
[INFO] [Core]: Unloading core symbols..
[INFO] [Video]: Does not have enough samples for monitor refresh rate estimation. Requires to run for at least 4096 frames.
[INFO] === Build =======================================
[INFO] CPU Model Name: Unknown
[INFO] Capabilities: MMX MMXEXT SSE SSE2 SSE3 SSE4 SSE4.2 AES AVX AVX2
[INFO] Built: Dec 13 2022
[INFO] Version: 1.14.0
[INFO] =================================================
[INFO] [Input]: Found input driver: "uwp".
[INFO] [Core]: Loading dynamic libretro core from: "S:\Program Files\WindowsApps\1e4cf179-f3c2-404f-b9f3-cb2070a5aad8_1.14.0.0_x64__8ngdn9a6dx1ma\cores\flycast_libretro.dll"
[INFO] [Environ]: GET_CORE_OPTIONS_VERSION.
[INFO] [Environ]: GET_LANGUAGE: "0".
[INFO] [Environ]: RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL.
[INFO] [Core]: Folder-specific core options found at "E:\RetroArch\config\Flycast\\atomiswave.opt".
[INFO] [Environ]: SET_CONTROLLER_INFO.
[INFO] [Remaps]: Game-specific remap found at "E:\RetroArch\config\remaps\Flycast\mslug6.rmp".
[INFO] [Overrides]: Redirecting save file to "E:\RetroArch\saves\mslug6.srm".
[INFO] [Overrides]: Redirecting save state to "E:\RetroArch\states\mslug6.state".
[INFO] [Environ]: GET_LOG_INTERFACE.
[INFO] [Environ]: GET_PERF_INTERFACE.
[INFO] [Environ]: SET_PIXEL_FORMAT: XRGB8888.
[INFO] [Environ]: SET_KEYBOARD_CALLBACK.
[INFO] [Environ]: GET_DISK_CONTROL_INTERFACE_VERSION.
[INFO] [Environ]: SET_DISK_CONTROL_EXT_INTERFACE.
[INFO] [Content]: Content loading skipped. Implementation will load it on its own.
[INFO] [Environ]: GET_RUMBLE_INTERFACE.
[INFO] [Environ]: SYSTEM_DIRECTORY: "E:\RetroArch\system".
[INFO] [Environ]: GET_SAVE_DIRECTORY.
[INFO] [Environ]: SET_SAVE_STATE_IN_BACKGROUND: yes.
[INFO] [Environ]: GET_PREFERRED_HW_RENDER, video driver name: d3d11.
[INFO] [Environ]: GET_PREFERRED_HW_RENDER - Context callback set to RETRO_HW_CONTEXT_DIRECT3D.
[INFO] [Environ]: SET_HW_RENDER, context type: d3d11.
[INFO] Requesting D3D11 context.
[INFO] Reached end of SET_HW_RENDER.
[INFO] [Environ]: GET_SAVE_DIRECTORY.
[INFO] [Environ]: SET_ROTATION: 0
[INFO] [Environ]: SET_INPUT_DESCRIPTORS:
[INFO] [SRAM]: Skipping SRAM load.
[INFO] [Core]: Version of libretro API: 1, Compiled against API: 1
[INFO] [Audio]: Set audio input rate to: 44100.00 Hz.
[INFO] [Video]: Set video size to: 1920x1080.
[INFO] [Video]: Using HW render, d3d11 driver forced.
[WARN] [XInput]: No guide button support.
[INFO] [Joypad]: Found joypad driver: "xinput".
[INFO] [D3D11]: Device created (Feature Level: 11.0)
[INFO] [D3D11]: Found GPU at index 0: "SraKmd_arden".
[INFO] [D3D11]: Found GPU at index 1: "Microsoft Basic Render Driver".
[INFO] [D3D11]: Using GPU index 0.
[INFO] [Video]: Found display server: "null".
[INFO] [XAudio2]: Requesting 64 ms latency, using 64 ms latency.
[INFO] [Display]: Found display driver: "d3d11".
[INFO] [Playlist]: Loading history file: "Q:\Users\UserMgr18\AppData\Local\Packages\1e4cf179-f3c2-404f-b9f3-cb2070a5aad8_8ngdn9a6dx1ma\LocalState\content_history.lpl".
[INFO] [Playlist]: Loading history file: "Q:\Users\UserMgr18\AppData\Local\Packages\1e4cf179-f3c2-404f-b9f3-cb2070a5aad8_8ngdn9a6dx1ma\LocalState\content_music_history.lpl".
[INFO] [Playlist]: Loading history file: "Q:\Users\UserMgr18\AppData\Local\Packages\1e4cf179-f3c2-404f-b9f3-cb2070a5aad8_8ngdn9a6dx1ma\LocalState\content_image_history.lpl".
[INFO] [Playlist]: Loading favorites file: "Q:\Users\UserMgr18\AppData\Local\Packages\1e4cf179-f3c2-404f-b9f3-cb2070a5aad8_8ngdn9a6dx1ma\LocalState\content_favorites.lpl".
[INFO] [Environ]: SET_INPUT_DESCRIPTORS:
[INFO] [Environ]: SET_GEOMETRY: 640x480, Aspect: 1.333.
[INFO] [Environ]: SET_GEOMETRY.
[libretro ERROR] core/rend/dx11/dx11_texture.cpp:99 E[RENDERER]: Texture creation failed type 1 dim 128x128 mipmap 0 (included 0)
[libretro ERROR] Verify Failed  : texture != nullptr
 in UploadToGPU -> /builds/libretro/flycast-upstream/core/rend/dx11/dx11_texture.cpp : 101
[libretro ERROR] shell/libretro/libretro.cpp:3009 E[COMMON]: DEBUGBREAK!
blisstik commented 1 year ago

Samurai Spirits and KOF NeoWave also crash. These have the same error logs.

flyinghead commented 1 year ago

There's definitely something wrong with this build, either RA or Flycast.

The first error was:

[libretro ERROR] core/rend/dx11/dx11_shaders.cpp:606 E[RENDERER]: Pixel shader creation failed

Now we have:

[libretro ERROR] core/rend/dx11/dx11_texture.cpp:99 E[RENDERER]: Texture creation failed type 1 dim 128x128 mipmap 0 (included 0)

So it looks like the DX11 device passed by RA is invalid because these operations should not fail.

Have you tried standalone?

flyinghead commented 1 year ago

From @GABO1423:

When using the libretro core on an Xbox Series X after you last Merged the Dev branch changes to the master branch, Metal Slug 6 (Atomiswave) fails to boot. Crashing RetroArch every time regardless of the settings used. Dolphin Blue in contrast boots up just fine.

Also, enabling full framebuffer emulation makes any game fail to boot, crashing the app once again. This issue in particular isn't present in the standalone UWP version.

Logging both issues wasn't particularly useful, as the logs just stop at a certain point without reporting any errors. Both of these issues are present on the latest master branch build.

flyinghead commented 1 year ago

Can I get an even better log? That is with debug level logging for the core as well?

It seems I only see ERROR messages from the core, and not NOTICE or WARN. In particular I don't know if the DX11 context is initialized.

Thanks

flyinghead commented 1 year ago

Also I did a number of changes on master recently. This one in particular may help: 8f3b6a23710c3ae2df620dfb4b1625ee89516db4. It would be interesting to test a more recent build.

flyinghead commented 1 year ago

I just pushed a change that might help the issue.

blisstik commented 1 year ago

I tested it, same result unfortunately.

flyinghead commented 1 year ago

For reference, some retroarch log files from @GABO1423: retroarch__dolphinblue_OK.log retroarch__mslug6.log retroarch__dolphinblue_fail.log

blisstik commented 1 year ago

Here's my mslug log at Debug. I thought level 3 (Error) was the best log

https://pastebin.com/raw/KYWvcdUw

LibretroAdmin commented 1 year ago

@blisstik Could you do a bisect so we can figure out at what point it broke down? Thanks.

you can compile the core from your Windows machine and then deploy to your Xbox for testing.

blisstik commented 1 year ago

Hello @flyinghead - I did not do a bisect but the issue started happening here

https://github.com/flyinghead/flycast/commit/ae47ac19b861695653586220f19b2adb1ac1daff

Maybe it's forcing 32bit textures?

flyinghead commented 1 year ago

Thank you for helping. Based on the log files above it looks like the xbox gpu supports all texture types so no conversion to 32-bit is needed. Also RGBA8888 is by far the most common format so it wouldn't be an issue even if it was the case.

The first change (resize()) was later moved to a non-RA section (https://github.com/flyinghead/flycast/commit/9954768636b7c67813b33293d9f6d7a360cc6962)

The rest is just logging or error checking so perhaps the call to DX11Context::checkTextureSupport() is having side effect? I don't see why but I could try to remove it on xbox since it's not needed.

blisstik commented 1 year ago

Still crashing but log looks different.

Full log here -> https://pastebin.com/raw/0P7MKBcH

I do see a couple errors:

[ERROR] [Environ]: GET_VARIABLE: pvr.rend - Invalid value.
[ERROR] [Environ]: GET_VARIABLE: rend.PerStripSorting - Invalid value.

And this is the end of the log, where it just crashes.

[INFO] [Replay]: Found last replay slot: #0
[INFO] [SRAM]: Skipping SRAM load.
[INFO] [Core]: Version of libretro API: 1, Compiled against API: 1
[libretro INFO] shell/libretro/libretro.cpp:2130 N[RENDERER]: retro_get_system_av_info: Res=960
[INFO] [Audio]: Set audio input rate to: 44100.00 Hz.
[INFO] [Video]: Set video size to: 1920x1080.
[INFO] [Video]: Using HW render, d3d11 driver forced.
[WARN] [XInput]: No guide button support.
[INFO] [Joypad]: Found joypad driver: "xinput".
[INFO] [D3D11]: Device created (Feature Level: 11.0)
[INFO] [D3D11]: Found GPU at index 0: "SraKmd_arden".
[INFO] [D3D11]: Found GPU at index 1: "Microsoft Basic Render Driver".
[INFO] [D3D11]: Using GPU index 0.
[INFO] [Video]: Found display server: "null".
[libretro INFO] shell/libretro/libretro.cpp:1744 N[RENDERER]: DX11 context reset
[libretro INFO] core/rend/dx11/dx11context_lr.cpp:64 N[RENDERER]: DX11 Context terminating
[libretro INFO] core/rend/dx11/dx11_shaders.cpp:681 N[RENDERER]: Saved 0 shaders to E:\RetroArch\system\dc\dx11_shader_cache.bin
[libretro INFO] core/rend/dx11/dx11context_lr.cpp:76 N[RENDERER]: DX11 Context terminated
[libretro INFO] core/rend/dx11/dx11context_lr.cpp:28 N[RENDERER]: DX11 Context initializing
[libretro INFO] core/rend/dx11/dx11_renderer.cpp:42 N[RENDERER]: DX11 renderer initializing
[INFO] [XAudio2]: Requesting 64 ms latency, using 64 ms latency.
[INFO] [Display]: Found display driver: "d3d11".
blisstik commented 1 year ago

Here's a log from Dolphin Blue loading, no issue

[INFO] [Replay]: Found last replay slot: #0
[INFO] [SRAM]: Skipping SRAM load.
[INFO] [Core]: Version of libretro API: 1, Compiled against API: 1
[libretro INFO] shell/libretro/libretro.cpp:2130 N[RENDERER]: retro_get_system_av_info: Res=960
[INFO] [Audio]: Set audio input rate to: 44100.00 Hz.
[INFO] [Video]: Set video size to: 1920x1080.
[INFO] [Video]: Using HW render, d3d11 driver forced.
[WARN] [XInput]: No guide button support.
[INFO] [Joypad]: Found joypad driver: "xinput".
[INFO] [D3D11]: Device created (Feature Level: 11.0)
[INFO] [D3D11]: Found GPU at index 0: "SraKmd_arden".
[INFO] [D3D11]: Found GPU at index 1: "Microsoft Basic Render Driver".
[INFO] [D3D11]: Using GPU index 0.
[INFO] [Video]: Found display server: "null".
[libretro INFO] shell/libretro/libretro.cpp:1744 N[RENDERER]: DX11 context reset
[libretro INFO] core/rend/dx11/dx11context_lr.cpp:64 N[RENDERER]: DX11 Context terminating
[libretro INFO] core/rend/dx11/dx11_shaders.cpp:681 N[RENDERER]: Saved 0 shaders to E:\RetroArch\system\dc\dx11_shader_cache.bin
[libretro INFO] core/rend/dx11/dx11context_lr.cpp:76 N[RENDERER]: DX11 Context terminated
[libretro INFO] core/rend/dx11/dx11context_lr.cpp:28 N[RENDERER]: DX11 Context initializing
[libretro INFO] core/rend/dx11/dx11_renderer.cpp:42 N[RENDERER]: DX11 renderer initializing
[INFO] [XAudio2]: Requesting 64 ms latency, using 64 ms latency.
[INFO] [Display]: Found display driver: "d3d11".
[INFO] [Playlist]: Loading history file: "Q:\Users\UserMgr18\AppData\Local\Packages\1e4cf179-f3c2-404f-b9f3-cb2070a5aad8_8ngdn9a6dx1ma\LocalState\content_history.lpl".
[INFO] [Playlist]: Loading history file: "Q:\Users\UserMgr18\AppData\Local\Packages\1e4cf179-f3c2-404f-b9f3-cb2070a5aad8_8ngdn9a6dx1ma\LocalState\content_music_history.lpl".
[INFO] [Playlist]: Loading history file: "Q:\Users\UserMgr18\AppData\Local\Packages\1e4cf179-f3c2-404f-b9f3-cb2070a5aad8_8ngdn9a6dx1ma\LocalState\content_image_history.lpl".
[INFO] [Playlist]: Loading favorites file: "Q:\Users\UserMgr18\AppData\Local\Packages\1e4cf179-f3c2-404f-b9f3-cb2070a5aad8_8ngdn9a6dx1ma\LocalState\content_favorites.lpl".
[INFO] [Playlist]: Written to playlist file: "Q:\Users\UserMgr18\AppData\Local\Packages\1e4cf179-f3c2-404f-b9f3-cb2070a5aad8_8ngdn9a6dx1ma\LocalState\content_history.lpl".
[INFO] [Environ]: SET_INPUT_DESCRIPTORS:
[DEBUG]    RetroPad, Port 1, Button "B (bottom)" => "SHOOT"
[DEBUG]    RetroPad, Port 1, Button "Y (left)" => "SPECIAL"
[DEBUG]    RetroPad, Port 1, Button "Select" => "Coin"
[DEBUG]    RetroPad, Port 1, Button "Start" => "Start"
[DEBUG]    RetroPad, Port 1, Button "D-Pad Up" => "D-Pad Up"
[DEBUG]    RetroPad, Port 1, Button "D-Pad Down" => "D-Pad Down"
[DEBUG]    RetroPad, Port 1, Button "D-Pad Left" => "D-Pad Left"
[DEBUG]    RetroPad, Port 1, Button "D-Pad Right" => "D-Pad Right"
[DEBUG]    RetroPad, Port 1, Button "A (right)" => "JUMP"
[DEBUG]    RetroPad, Port 1, Button "L3" => "Test"
[DEBUG]    RetroPad, Port 1, Button "R3" => "Service"
[DEBUG]    RetroPad, Port 2, Button "B (bottom)" => "SHOOT"
[DEBUG]    RetroPad, Port 2, Button "Y (left)" => "SPECIAL"
[DEBUG]    RetroPad, Port 2, Button "Select" => "Coin"
[DEBUG]    RetroPad, Port 2, Button "Start" => "Start"
[DEBUG]    RetroPad, Port 2, Button "D-Pad Up" => "D-Pad Up"
[DEBUG]    RetroPad, Port 2, Button "D-Pad Down" => "D-Pad Down"
[DEBUG]    RetroPad, Port 2, Button "D-Pad Left" => "D-Pad Left"
[DEBUG]    RetroPad, Port 2, Button "D-Pad Right" => "D-Pad Right"
[DEBUG]    RetroPad, Port 2, Button "A (right)" => "JUMP"
[DEBUG]    RetroPad, Port 2, Button "L3" => "Test"
[DEBUG]    RetroPad, Port 2, Button "R3" => "Service"
[DEBUG]    RetroPad, Port 3, Button "B (bottom)" => "SHOOT"
[DEBUG]    RetroPad, Port 3, Button "Y (left)" => "SPECIAL"
[DEBUG]    RetroPad, Port 3, Button "Select" => "Coin"
[DEBUG]    RetroPad, Port 3, Button "Start" => "Start"
[DEBUG]    RetroPad, Port 3, Button "D-Pad Up" => "D-Pad Up"
[DEBUG]    RetroPad, Port 3, Button "D-Pad Down" => "D-Pad Down"
[DEBUG]    RetroPad, Port 3, Button "D-Pad Left" => "D-Pad Left"
[DEBUG]    RetroPad, Port 3, Button "D-Pad Right" => "D-Pad Right"
[DEBUG]    RetroPad, Port 3, Button "A (right)" => "JUMP"
[DEBUG]    RetroPad, Port 3, Button "L3" => "Test"
[DEBUG]    RetroPad, Port 3, Button "R3" => "Service"
[DEBUG]    RetroPad, Port 4, Button "B (bottom)" => "SHOOT"
[DEBUG]    RetroPad, Port 4, Button "Y (left)" => "SPECIAL"
[DEBUG]    RetroPad, Port 4, Button "Select" => "Coin"
[DEBUG]    RetroPad, Port 4, Button "Start" => "Start"
[DEBUG]    RetroPad, Port 4, Button "D-Pad Up" => "D-Pad Up"
[DEBUG]    RetroPad, Port 4, Button "D-Pad Down" => "D-Pad Down"
[DEBUG]    RetroPad, Port 4, Button "D-Pad Left" => "D-Pad Left"
[DEBUG]    RetroPad, Port 4, Button "D-Pad Right" => "D-Pad Right"
[DEBUG]    RetroPad, Port 4, Button "A (right)" => "JUMP"
[DEBUG]    RetroPad, Port 4, Button "L3" => "Test"
[DEBUG]    RetroPad, Port 4, Button "R3" => "Service"
[INFO] [Environ]: SET_GEOMETRY: 640x480, Aspect: 1.333.
GABO1423 commented 1 year ago

I don't think that commit would help due to the conditional used. LIBRETRO and TARGET_UWP can't be both true at once due to the how the CMake build files work. If you are building for Libretro you aren't building for UWP, and vice versa.

EDIT: And just for the record since I haven't seen it mentioned here, this issue is UWP Libretro exclusive. Standalone doesn't suffer from these crashes.

flyinghead commented 1 year ago

TARGET_UWP is defined in core/build.h:

#ifdef _WIN32
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
#define TARGET_UWP
#endif
#endif

so it should be defined unless the flycast UWP core is the regular windows core.

GABO1423 commented 1 year ago

so it should be defined unless the flycast UWP core is the regular windows core.

That's exactly what it has been from the start, that's also what all cores are for Xbox.

EDIT: Well, all of them are the regular Windows cores except for the three ANGLE cores (Mupen64Plus-Next, ParaLLEl-N64, and YabaSanshiro). But all of those are based on forks anyway.

flyinghead commented 1 year ago

I didn't know that so thanks for clarifying. I need a closer look at the implications because I was assuming that TARGET_UWP was always defined/true on xbox.

GABO1423 commented 1 year ago

I didn't know that so thanks for clarifying. I need a closer look at the implications because I was assuming that TARGET_UWP was always defined/true on xbox.

It is when making a standalone build, but since it's not currently possible to build a core with both of those flags being true, the added code is essentially bloat. There never was a way for a core to detect during run time that's it's running on the Xbox.

Although like I mentioned above, on standalone the issue was never a thing even before that commit was pushed. So what exactly is it about libretro and UWP at once that's causing this is beyond me.

flyinghead commented 1 year ago

The mystery is actually deepening: how can the regular windows core possibly work on uwp/xbox?

On standalone, virtual memory is disabled on UWP. This is because CreateFileMapping and some other functions aren't available. Yet, the windows core does use virtual mem and it apparently works on UWP:

[libretro INFO] core/hw/mem/_vmem.cpp:473 N[VMEM]: Info: nvmem is enabled
[libretro INFO] core/hw/mem/_vmem.cpp:508 N[VMEM]: BASE 00007ff43cfb0000 RAM(16 MB) 00007ff448fb0000 VRAM64(8 MB) 00007ff440fb0000 ARAM(2 MB) 00007ff45cfb0000

Even weirder: rwx pages aren't possible on UWP so the dynarec must switch its code buffer to rw- when generating code, and back to r-x when executing. Yet the windows core does nothing of this and it still works.

More: AddVectoredExceptionHandler used by the exception handler on windows isn't available on UWP but the windows core uses it.

However I didn't spot any issue with the directx11 code. All uwp-only code is for standalone only with the exception of one function that calls IsWindows8OrGreater (not available on UWP but still works fine in the core...)

GABO1423 commented 1 year ago

The mystery is actually deepening: how can the regular windows core possibly work on uwp/xbox?

On standalone, virtual memory is disabled on UWP. This is because CreateFileMapping and some other functions aren't available. Yet, the windows core does use virtual mem and it apparently works on UWP:

[libretro INFO] core/hw/mem/_vmem.cpp:473 N[VMEM]: Info: nvmem is enabled
[libretro INFO] core/hw/mem/_vmem.cpp:508 N[VMEM]: BASE 00007ff43cfb0000 RAM(16 MB) 00007ff448fb0000 VRAM64(8 MB) 00007ff440fb0000 ARAM(2 MB) 00007ff45cfb0000

Even weirder: rwx pages aren't possible on UWP so the dynarec must switch its code buffer to rw- when generating code, and back to r-x when executing. Yet the windows core does nothing of this and it still works.

More: AddVectoredExceptionHandler used by the exception handler on windows isn't available on UWP but the windows core uses it.

However I didn't spot any issue with the directx11 code. All uwp-only code is for standalone only with the exception of one function that calls IsWindows8OrGreater (not available on UWP but still works fine in the core...)

Maybe the fact that it's running under a RetroArch frontend that is made for UWP is helping matters? But those differences could explain why this issue is happening in these very specific circumstances.

I can't think of a pretty solution tbh, all that comes to mind is to make it possible to build a core with both the Libretro and UWP flags be true. Which would mean potentially it's own workflow, and I don't know how distribution outside of the workflow would work since the libretro buildbot doesn't seem to be an option. Since UWP uses the regular Windows buildbot, it would mean two Flycast cores being offered at once.