Porting SDL3

Started by lifning, Mar 15, 2025, 07:11 PM

Previous topic - Next topic

lifning

After getting Sonic CD working on Wii-ndows, I took another look at SDL, and decided to take another crack at porting it to a game console -- the N64, via libdragon.


There's already PS2, PSP, and N3DS support in SDL3 (which have been a great reference for which driver functions I need to provide vs. which are optional), and so far I've written driver glue for video (software rendering with a perf hack), threads, mutex, semaphore, and timers.

A lot of this has thus far been relatively thin wrappers atop functionality already provided by libdragon! The thread/mutex/semaphore support is still very new and probably not leaving the unstable branch for a good while, but they're load-bearing -- you effectively can't have SDL without them.

I hope to eventually get a 'render' driver going (for the modern SDL_Texture-oriented approach in SDL2+), which may be challenging with the limited amount of texture memory (and bottlenecks around memory in general) on the N64, so that'll be exciting. Though lower-hanging fruit includes wiring up audio and gamepad support and seeing how the Sonic CD decomp fares :mrgreen:
You cannot view this attachment.
Please consider the environment before printing this post.

snow

From there it's probably easy to add Hey You, Pikachu! VRU support to SDL, right? :P

Seriously though, this is really cool to see!

Quote from: lifning on Mar 15, 2025, 07:11 PMA lot of this has thus far been relatively thin wrappers atop functionality already provided by libdragon!

Huh, that's especially neat. I wonder if that was intentional on the libdragon devs' end.

lifning

I imagine it's less that they're intentionally making it a good match and more that SDL and libdragon have both independently arrived at similar "this is a sensible way to expose the functionality needed to make realtime interactive multimedia applications" solutions. Either way, I'll take it!

I've now also hooked up libdragon's condition variable support, real-time clock (where available), logging via ISViewer (which ares supports), and started on audio -- I have some issue to chase down where opening the audio device locks up the main thread, but I'm hopeful I'll figure that out soon.
You cannot view this attachment.
Please consider the environment before printing this post.

lifning


audio!! turns out libdragon's threading system is cooperative and i needed to make the audio thread cooperate better.
You cannot view this attachment.
Please consider the environment before printing this post.

lifning

Quote from: snow on Mar 17, 2025, 12:26 AMFrom there it's probably easy to add Hey You, Pikachu! VRU support to SDL, right? :P

This is actually an interesting question -- SDL does have recording support in its audio systems, but I don't think the VRU provides an audio stream to the console!

In the past few years there's been an amount of reverse-engineering done on the VRU, and it looks like there's some language-specific signal processing and syllable pattern-matching that happens on-peripheral (which makes sense, since the American VRU and Japanese VRS are incompatible with one another). Mupen64Plus's support for it is high-level emulated, with the phoneme detection done by vosk-api.

Now, would it be possible to use the VRU as a very scuffed text IME? ...Patches welcome ;)
You cannot view this attachment.
Please consider the environment before printing this post.

lifning


SDL_GL is here -- though we can't use the opengl "render driver" (the subsystem of modern SDL that accelerates drawing SDL_Textures, et al), because it expects some specific GL functions that aren't supported by libdragon. I'll have to write an rdpq-specific render driver for that instead, which shouldn't be too terribly hard.
You cannot view this attachment.
Please consider the environment before printing this post.

lifning


still very incomplete and broken, but some signs of life from my rdpq-based render driver!
You cannot view this attachment.
Please consider the environment before printing this post.

lifning

here's what that was actually supposed to look like!

i'm still working on multi-part uploads for large textures - TMEM on the N64 is very limited, so if you try to blit a surface where width * height * bytesperpixel > 2048 you're in a bit of trouble. i've started attempting to split up such textures into 64x32-pixel tiles and blit each of those, but i've, er, got some correctness issues to sort out
You cannot view this attachment.
Please consider the environment before printing this post.

lifning

#8
Quote from: lifning on Apr 05, 2025, 07:17 AMi'm still working on multi-part uploads for large textures - TMEM on the N64 is very limited, so if you try to blit a surface where
width * height * bytesperpixel > 2048 you're in a bit of trouble. i've started attempting to split up such textures into 64x32-pixel tiles and blit each of those, but i've, er, got some correctness issues to sort out

turns out that's built-in to the rdpq_tex_blit function i already had used for RenderCopy, and i was just holding it wrong (or to be more precise, i got confused by results i was seeing in SDL_RenderGeometry, which isn't able to use that function). oops!

with a bit more fuss, i got the backend of SDL_RenderTextureRotated implemented, too. the analog-axis indicator arrows in the diagram here use that:

and everything green is rendered using SDL_SetTextureColorMod, which i've implemented with the RDP's color combiner mode.

(previous footage i'd posted elsewhere of this controller test program was done with pure software rendering - this time it's all being drawn with the RDP-accelerated renderer!)
You cannot view this attachment.
Please consider the environment before printing this post.

lifning

the "Woodeneye 008" example from SDL3's codebase running decently on real N64 hardware! dug into SDL's render subsystem and worked out that unless i do a funny SDL_SetHint(SDL_HINT_RENDER_LINE_METHOD, "2"); in my CreateRenderer, SDL will happily automatically render lines as individual pixels - now that it's actually calling my accelerated QueueDrawLines it's totally playable!


also here's an example of RenderReadPixels,


the aforementioned color combiner in action,


and scaling/rotating textures with RenderCopyEx (check out the classic N64 3-point texture filtering on the edges of that smiley face!)


oh and i added a haptic driver for rumble pak support too
You cannot view this attachment.
Please consider the environment before printing this post.