PS3: Various fixes

- Fix image build when GNU Savannah is down
- Fix SDL2 PSL1GHT bugs
This commit is contained in:
Le Philousophe
2025-12-07 11:37:12 +00:00
parent e4a5dd0d68
commit 2a1dfc56de
2 changed files with 4864 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,345 @@
commit 7b61f592b4d2204fc2f3907602fb3142878f09d7
Author: Le Philousophe <lephilousophe@users.noreply.github.com>
Date: Sun Dec 7 12:19:06 2025 +0100
Update SDL2 PSL1GHT with patch
diff --git a/patches/SDL2_PSL1GHT.patch b/patches/SDL2_PSL1GHT.patch
new file mode 100644
index 0000000..04dd60f
--- /dev/null
+++ b/patches/SDL2_PSL1GHT.patch
@@ -0,0 +1,316 @@
+diff --git a/src/joystick/psl1ght/SDL_sysjoystick.c b/src/joystick/psl1ght/SDL_sysjoystick.c
+index 929e68d8f..b7e966fa1 100644
+--- a/src/joystick/psl1ght/SDL_sysjoystick.c
++++ b/src/joystick/psl1ght/SDL_sysjoystick.c
+@@ -38,6 +38,7 @@
+
+ typedef struct SDL_PSL1GHT_JoyData
+ {
++ u8 status;
+ char name[NAMESIZE];
+ } SDL_PSL1GHT_JoyData;
+
+@@ -50,6 +51,7 @@ static SDL_PSL1GHT_JoyData joy_data[MAX_PADS];
+ static int numberOfJoysticks = 0;
+
+ static void SDL_SYS_JoystickDetect(void);
++static SDL_JoystickID SDL_SYS_JoystickGetDeviceInstanceID(int device_index);
+
+ /* Function to scan the system for joysticks.
+ * This function should set numberOfJoysticks to the number of available
+@@ -99,9 +101,17 @@ SDL_SYS_JoystickDetect(void)
+ unsigned int i;
+ numberOfJoysticks = padinfo.connected;
+
+- for (i = 0; i < padinfo.connected; i++) {
++ for (i = 0; i < padinfo.max; i++) {
++ if (padinfo.status[i] == joy_data[i].status) {
++ continue;
++ }
++ joy_data[i].status = padinfo.status[i];
++ SDL_JoystickID instanceID = SDL_SYS_JoystickGetDeviceInstanceID(i);
+ if (padinfo.status[i]) {
+ sprintf(joy_data[i].name, "PAD%02X", i);
++ SDL_PrivateJoystickAdded(instanceID);
++ } else {
++ SDL_PrivateJoystickRemoved(instanceID);
+ }
+ }
+ }
+diff --git a/src/render/psl1ght/SDL_PSL1GHTrender.c b/src/render/psl1ght/SDL_PSL1GHTrender.c
+index a8b1363cb..cd6f8d3e4 100644
+--- a/src/render/psl1ght/SDL_PSL1GHTrender.c
++++ b/src/render/psl1ght/SDL_PSL1GHTrender.c
+@@ -37,6 +37,8 @@
+ #include <unistd.h>
+ #include <assert.h>
+
++#define GCM_ROP_DONE_INDEX 64
++
+ /* SDL surface based renderer implementation */
+
+ static SDL_Renderer *PSL1GHT_CreateRenderer(SDL_Window *window, Uint32 flags);
+@@ -71,7 +73,7 @@ static int PSL1GHT_RenderFillRects(SDL_Renderer *renderer,
+ static int PSL1GHT_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
+ const SDL_Rect *srcrect, const SDL_FRect *dstrect);
+ static int PSL1GHT_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture,
+- const SDL_Rect *srcrect, const SDL_Rect *dstrect);
++ SDL_Rect *srcrect, SDL_Rect *dstrect);
+ static int PSL1GHT_QueueCopyEx(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
+ const SDL_Rect *srcquad, const SDL_FRect *dstrect,
+ const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip,
+@@ -102,6 +104,7 @@ typedef struct
+ SDL_Surface *screens[3];
+ void *textures[3];
+ gcmContextData *context; // Context to keep track of the RSX buffer.
++ u32 ropValue;
+ } PSL1GHT_RenderData;
+
+ typedef struct
+@@ -117,6 +120,19 @@ static void waitFlip()
+ gcmResetFlipStatus();
+ }
+
++static void waitROP(PSL1GHT_RenderData *data) {
++ vu32 *label = (vu32*)gcmGetLabelAddress(GCM_ROP_DONE_INDEX);
++
++ u32 expectedValue = ++data->ropValue;
++
++ rsxSetWriteBackendLabel(data->context, GCM_ROP_DONE_INDEX, expectedValue);
++ rsxFlushBuffer(data->context);
++
++ while(*label != expectedValue) {
++ usleep(30);
++ }
++}
++
+ static SDL_Surface *
+ PSL1GHT_ActivateRenderer(SDL_Renderer *renderer)
+ {
+@@ -165,6 +181,9 @@ PSL1GHT_CreateRenderer(SDL_Window *window, Uint32 flags)
+ data->current_screen = 0;
+ data->first_fb = true;
+
++ data->ropValue = 0;
++ *(vu32*)gcmGetLabelAddress(GCM_ROP_DONE_INDEX) = 0;
++
+ pitch = displayMode->w * SDL_BYTESPERPIXEL(displayMode->format);
+
+ n = 2;
+@@ -608,12 +627,11 @@ PSL1GHT_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *t
+
+ static int
+ PSL1GHT_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture,
+- const SDL_Rect *srcrect, const SDL_Rect *dstrect)
++ SDL_Rect *srcrect, SDL_Rect *dstrect)
+ {
+ PSL1GHT_RenderData *data = (PSL1GHT_RenderData *)renderer->driverdata;
+ SDL_Surface *dst = PSL1GHT_ActivateRenderer(renderer);
+ SDL_Surface *src = (SDL_Surface *)texture->driverdata;
+- SDL_Rect final_rect = *dstrect;
+ u32 src_offset, dst_offset;
+
+ if (!dst) {
+@@ -621,44 +639,143 @@ PSL1GHT_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture,
+ }
+
+ if (renderer->viewport.x || renderer->viewport.y) {
+- final_rect.x += renderer->viewport.x;
+- final_rect.y += renderer->viewport.y;
++ dstrect->x += renderer->viewport.x;
++ dstrect->y += renderer->viewport.y;
+ }
+
+ rsxAddressToOffset(dst->pixels, &dst_offset);
+ rsxAddressToOffset(src->pixels, &src_offset);
+
+- gcmTransferScale scale;
+- scale.conversion = GCM_TRANSFER_CONVERSION_TRUNCATE;
+- scale.format = GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8;
+- scale.operation = GCM_TRANSFER_OPERATION_SRCCOPY;
+- scale.clipX = final_rect.x;
+- scale.clipY = final_rect.y;
+- scale.clipW = final_rect.w;
+- scale.clipH = final_rect.h;
+- scale.outX = final_rect.x;
+- scale.outY = final_rect.y;
+- scale.outW = final_rect.w;
+- scale.outH = final_rect.h;
+- scale.ratioX = (srcrect->w << 20) / final_rect.w;
+- scale.ratioY = (srcrect->h << 20) / final_rect.h;
+- scale.inX = srcrect->x;
+- scale.inY = srcrect->y;
+- scale.inW = srcrect->w;
+- scale.inH = srcrect->h;
+- scale.offset = src_offset;
+- scale.pitch = src->pitch;
+- scale.origin = GCM_TRANSFER_ORIGIN_CORNER;
+- scale.interp = GCM_TRANSFER_INTERPOLATOR_NEAREST;
+-
+- gcmTransferSurface surface;
+- surface.format = GCM_TRANSFER_SURFACE_FORMAT_A8R8G8B8;
+- surface.pitch = dst->pitch;
+- surface.offset = dst_offset;
+-
+- // Hardware accelerated blit with scaling
+- rsxSetTransferScaleMode(data->context, GCM_TRANSFER_LOCAL_TO_LOCAL, GCM_TRANSFER_SURFACE);
+- rsxSetTransferScaleSurface(data->context, &scale, &surface);
++ if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
++ // Simple blit without scaling
++ if (dstrect->x < 0) {
++ dstrect->w += dstrect->x;
++ srcrect->x -= dstrect->x;
++ dstrect->x = 0;
++ }
++ if (dstrect->y < 0) {
++ dstrect->h += dstrect->y;
++ srcrect->y -= dstrect->y;
++ dstrect->y = 0;
++ }
++ if (dstrect->x + dstrect->w > dst->w) {
++ dstrect->w = dst->w - dstrect->x;
++ }
++ if (dstrect->y + dstrect->h > dst->h) {
++ dstrect->h = dst->h - dstrect->y;
++ }
++
++ // Hardware accelerated blit
++ rsxSetTransferImage(data->context, GCM_TRANSFER_LOCAL_TO_LOCAL, dst_offset, dst->pitch, dstrect->x, dstrect->y,
++ src_offset, src->pitch, srcrect->x, srcrect->y, dstrect->w, dstrect->h, 4);
++ } else {
++ /* Prevent to do scaling + clipping on viewport boundaries as it may lose proportion */
++ if (dstrect->x < 0 || dstrect->y < 0 || dstrect->x + dstrect->w > dst->w || dstrect->y + dstrect->h > dst->h) {
++ int tmp_pitch = (dstrect->w * SDL_BYTESPERPIXEL(dst->format->format) + 63) & ~63; // Round to next multiple of 64
++ void *tmp = rsxMemalign(64, dstrect->h * tmp_pitch);
++ if (!tmp) {
++ return -1;
++ }
++
++ u32 tmp_offset;
++ rsxAddressToOffset(tmp, &tmp_offset);
++ gcmTransferScale scale;
++ gcmTransferSurface surface;
++
++ scale.conversion = GCM_TRANSFER_CONVERSION_TRUNCATE;
++ scale.format = GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8;
++ scale.operation = GCM_TRANSFER_OPERATION_SRCCOPY;
++ scale.clipX = 0;
++ scale.clipY = 0;
++ scale.clipW = dstrect->w;
++ scale.clipH = dstrect->h;
++ scale.outX = 0;
++ scale.outY = 0;
++ scale.outW = dstrect->w;
++ scale.outH = dstrect->h;
++ scale.ratioX = (srcrect->w << 20) / dstrect->w;
++ scale.ratioY = (srcrect->h << 20) / dstrect->h;
++ scale.inX = srcrect->x << 4;
++ scale.inY = srcrect->y << 4;
++ scale.inW = srcrect->w;
++ scale.inH = srcrect->h;
++ scale.offset = src_offset;
++ scale.pitch = src->pitch;
++ scale.origin = GCM_TRANSFER_ORIGIN_CORNER;
++ scale.interp = GCM_TRANSFER_INTERPOLATOR_NEAREST;
++
++ surface.format = GCM_TRANSFER_SURFACE_FORMAT_A8R8G8B8;
++ surface.pitch = tmp_pitch;
++ surface.offset = tmp_offset;
++
++ // Hardware accelerated scaling
++ rsxSetTransferScaleMode(data->context, GCM_TRANSFER_LOCAL_TO_LOCAL, GCM_TRANSFER_SURFACE);
++ rsxSetTransferScaleSurface(data->context, &scale, &surface);
++
++ // Wait for above scale to happen beofre doing the blitting
++ rsxSetWaitForIdle(data->context);
++
++ srcrect->x = srcrect->y = 0;
++
++ if (dstrect->x < 0) {
++ dstrect->w += dstrect->x;
++ srcrect->x -= dstrect->x;
++ dstrect->x = 0;
++ }
++ if (dstrect->y < 0) {
++ dstrect->h += dstrect->y;
++ srcrect->y -= dstrect->y;
++ dstrect->y = 0;
++ }
++ if (dstrect->x + dstrect->w > dst->w) {
++ dstrect->w = dst->w - dstrect->x;
++ }
++ if (dstrect->y + dstrect->h > dst->h) {
++ dstrect->h = dst->h - dstrect->y;
++ }
++
++ // Hardware accelerated blit
++ rsxSetTransferImage(data->context, GCM_TRANSFER_LOCAL_TO_LOCAL, dst_offset, dst->pitch, dstrect->x, dstrect->y,
++ tmp_offset, tmp_pitch, srcrect->x, srcrect->y, dstrect->w, dstrect->h, 4);
++
++ // Wait for end of ROP to free the surface
++ waitROP(data);
++
++ rsxFree(tmp);
++ } else {
++ gcmTransferScale scale;
++ scale.conversion = GCM_TRANSFER_CONVERSION_TRUNCATE;
++ scale.format = GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8;
++ scale.operation = GCM_TRANSFER_OPERATION_SRCCOPY;
++ scale.clipX = dstrect->x;
++ scale.clipY = dstrect->y;
++ scale.clipW = dstrect->w;
++ scale.clipH = dstrect->h;
++ scale.outX = dstrect->x;
++ scale.outY = dstrect->y;
++ scale.outW = dstrect->w;
++ scale.outH = dstrect->h;
++ scale.ratioX = (srcrect->w << 20) / dstrect->w;
++ scale.ratioY = (srcrect->h << 20) / dstrect->h;
++ scale.inX = srcrect->x << 4;
++ scale.inY = srcrect->y << 4;
++ scale.inW = srcrect->w;
++ scale.inH = srcrect->h;
++ scale.offset = src_offset;
++ scale.pitch = src->pitch;
++ scale.origin = GCM_TRANSFER_ORIGIN_CORNER;
++ scale.interp = GCM_TRANSFER_INTERPOLATOR_NEAREST;
++
++ gcmTransferSurface surface;
++ surface.format = GCM_TRANSFER_SURFACE_FORMAT_A8R8G8B8;
++ surface.pitch = dst->pitch;
++ surface.offset = dst_offset;
++
++ // Hardware accelerated blit with scaling
++ rsxSetTransferScaleMode(data->context, GCM_TRANSFER_LOCAL_TO_LOCAL, GCM_TRANSFER_SURFACE);
++ rsxSetTransferScaleSurface(data->context, &scale, &surface);
++ }
++ }
+
+ // TODO: Blending / clipping
+
+@@ -724,7 +841,7 @@ PSL1GHT_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *ve
+
+ case SDL_RENDERCMD_COPY: {
+ const size_t first = cmd->data.draw.first;
+- const PSL1GHT_CopyData *copyData = (PSL1GHT_CopyData *) (((Uint8 *) vertices) + first);
++ PSL1GHT_CopyData *copyData = (PSL1GHT_CopyData *) (((Uint8 *) vertices) + first);
+
+ PSL1GHT_RenderCopy(renderer, cmd->data.draw.texture, &copyData->srcRect, &copyData->dstRect);
+ break;
+@@ -812,6 +929,7 @@ PSL1GHT_RenderPresent(SDL_Renderer * renderer)
+ static void
+ PSL1GHT_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
+ {
++ PSL1GHT_RenderData *data = (PSL1GHT_RenderData *)renderer->driverdata;
+ SDL_Surface *surface = (SDL_Surface *)texture->driverdata;
+
+ if (!surface)
+@@ -819,7 +937,7 @@ PSL1GHT_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
+ return;
+ }
+
+- // TODO: Wait for the DMA transfer to complete
++ waitROP(data);
+ rsxFree(surface->pixels);
+ SDL_FreeSurface(surface);
+ }
diff --git a/scripts/051-sdl2_psl1ght.sh b/scripts/051-sdl2_psl1ght.sh
index 3613df4..2b4ae6e 100755
--- a/scripts/051-sdl2_psl1ght.sh
+++ b/scripts/051-sdl2_psl1ght.sh
@@ -12,6 +12,12 @@ rm -Rf sdl2_psl1ght && mkdir sdl2_psl1ght && tar --strip-components=1 --director
## Create the build directory.
cd sdl2_psl1ght
+## Patch the source code if a patch exists.
+if [ -f ../../patches/SDL2_PSL1GHT.patch ]; then
+ echo "patching SDL2_PSL1GHT..."
+ patch -p1 <../../patches/SDL2_PSL1GHT.patch
+fi
+
./autogen.sh
if [ -f Makefile ]