From e24288866a455be8eeb67833a99fc60a4d1d975e Mon Sep 17 00:00:00 2001 From: Fancy2209 Date: Tue, 20 May 2025 23:19:54 +0000 Subject: [PATCH] PS3: Initial Work, boots on RPCS3 --- CMakeLists.txt | 29 ++++- include/mgba-util/common.h | 2 +- include/mgba-util/platform/ps3/threading.h | 140 +++++++++++++++++++++ include/mgba-util/threading.h | 5 +- include/mgba-util/vfs.h | 2 +- src/core/config.c | 2 +- src/feature/commandline.c | 6 +- src/gba/sio/dolphin.c | 2 + src/platform/posix/memory.c | 3 + src/platform/ps3/CMakeLists.txt | 14 +++ src/platform/ps3/CMakeToolchain.txt | 63 ++++++++++ src/platform/sdl/CMakeLists.txt | 4 + src/platform/sdl/sdl-events.c | 8 ++ 13 files changed, 270 insertions(+), 10 deletions(-) create mode 100644 include/mgba-util/platform/ps3/threading.h create mode 100644 src/platform/ps3/CMakeLists.txt create mode 100644 src/platform/ps3/CMakeToolchain.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index f7e84cf0d..105ca878d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ set(CMAKE_C_STANDARD 11) if(NOT MSVC) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) - if(SWITCH OR 3DS OR (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.3")) + if(SWITCH OR 3DS OR PS3 OR (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.3")) set(CMAKE_C_EXTENSIONS ON) endif() set(WARNING_FLAGS "-Wall -Wextra -Wno-missing-field-initializers") @@ -176,7 +176,7 @@ source_group("Generated sources" FILES ${CMAKE_CURRENT_BINARY_DIR}/version.c) # Advanced settings if(NOT (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.5")) - set(DEFAULT_LTO ON) + set(DEFAULT_LTO OFF) else() set(DEFAULT_LTO OFF) endif() @@ -291,7 +291,7 @@ if(PSP2) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format") endif() -if(DEFINED 3DS OR DEFINED PSP2 OR DEFINED WII OR DEFINED SWITCH) +if(DEFINED 3DS OR DEFINED PSP2 OR DEFINED WII OR DEFINED SWITCH OR DEFINED PS3) set(IS_EMBEDDED ON) set(ENABLE_DEBUGGERS OFF) set(USE_SQLITE3 OFF) @@ -304,6 +304,16 @@ if(DEFINED SWITCH) set(BUILD_GLES3 ON CACHE BOOL "Build with OpenGL|ES 3" FORCE) endif() +if(DEFINED PS3) + set(BUILD_GLES2 OFF CACHE BOOL "Build with OpenGL|ES 2" FORCE) + set(BUILD_GLES3 OFF CACHE BOOL "Build with OpenGL|ES 3" FORCE) + set(USE_ELF OFF) + set(BUILD_SDL ON) + set(BUILD_GL OFF) + set(BUILD_QT OFF) + set(ENABLE_SCRIPTING OFF) +endif() + if(NOT M_CORE_GBA) set(ENABLE_GDB_STUB OFF) endif() @@ -415,6 +425,10 @@ else() endif() if(BUILD_GL) +if(PS3) +list(APPEND FEATURES EGL) +set(OPENGL_LIBRARY EGL GL stdc++ gcm_sys rsx sysutil io audio rt lv2 io audio) +else() find_package(OpenGL QUIET) if(NOT OPENGL_FOUND OR (APPLE AND MACOSX_SDK VERSION_GREATER 10.14)) set(BUILD_GL OFF CACHE BOOL "OpenGL not found" FORCE) @@ -428,6 +442,7 @@ if(BUILD_GL) list(APPEND FEATURES EGL) list(APPEND OPENGL_LIBRARY ${OPENGL_egl_LIBRARY}) endif() + endif() endif() if(BUILD_GL) list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gl.c) @@ -889,6 +904,10 @@ if(DEFINED SWITCH) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/switch ${CMAKE_CURRENT_BINARY_DIR}/switch) endif() +if(DEFINED PS3) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/ps3 ${CMAKE_CURRENT_BINARY_DIR}/ps3) +endif() + # Binaries list(APPEND CORE_SRC ${UTIL_SRC} @@ -989,7 +1008,7 @@ else() endif() endif() -if(DISABLE_FRONTENDS) +if(DISABLE_FRONTENDS AND NOT PS3) set(BUILD_SDL OFF) set(BUILD_QT OFF) endif() @@ -1062,9 +1081,9 @@ if(NOT USE_CMOCKA) set(BUILD_SUITE OFF) endif() if(BUILD_TEST OR BUILD_SUITE OR BUILD_CINEMA) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/test ${CMAKE_CURRENT_BINARY_DIR}/test) enable_testing() endif() -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/test ${CMAKE_CURRENT_BINARY_DIR}/test) if(BUILD_EXAMPLE) add_executable(${BINARY_NAME}-example-server ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/example/client-server/server.c) diff --git a/include/mgba-util/common.h b/include/mgba-util/common.h index 746e57799..3163b5857 100644 --- a/include/mgba-util/common.h +++ b/include/mgba-util/common.h @@ -78,7 +78,7 @@ typedef intptr_t ssize_t; typedef intptr_t ssize_t; #endif -#ifdef PSP2 +#if defined(PSP2) || defined(__lv2ppu__) // For PATH_MAX on modern toolchains #include #endif diff --git a/include/mgba-util/platform/ps3/threading.h b/include/mgba-util/platform/ps3/threading.h new file mode 100644 index 000000000..3be63f7a9 --- /dev/null +++ b/include/mgba-util/platform/ps3/threading.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef POSIX_THREADING_H +#define POSIX_THREADING_H + +#include + +CXX_GUARD_START + +#include +#include +#include + +#define THREAD_ENTRY void +typedef THREAD_ENTRY (*ThreadEntry)(void*); +#define THREAD_EXIT(RES) return + +typedef sys_ppu_thread_t Thread; +typedef sys_lwmutex_t Mutex; +typedef struct { + Mutex mutex; + sys_sem_t semaphore; + int waiting; +} Condition; + +static inline int MutexInit(Mutex* mutex) { + sys_lwmutex_attr_t attr = { 0 }; + attr.attr_protocol = SYS_MUTEX_PROTOCOL_FIFO; + attr.attr_recursive = SYS_MUTEX_ATTR_NOT_RECURSIVE; + + return sysLwMutexCreate(mutex, &attr); +} + +static inline int MutexDeinit(Mutex* mutex) { + return sysLwMutexDestroy(mutex); +} + +static inline int MutexLock(Mutex* mutex) { + return sysLwMutexLock(mutex, 0); +} + +static inline int MutexTryLock(Mutex* mutex) { + return sysLwMutexTryLock(mutex); +} + +static inline int MutexUnlock(Mutex* mutex) { + return sysLwMutexUnlock(mutex); +} + +static inline int ConditionInit(Condition* cond) { + int res = MutexInit(&cond->mutex); + if (res < 0) { + return res; + } + sys_sem_attr_t attr = { 0 }; + attr.attr_protocol = SYS_SEM_ATTR_PROTOCOL; + attr.attr_pshared = SYS_SEM_ATTR_PSHARED; + attr.key = 0; + attr.flags = 0; + + res = sysSemCreate(&cond->semaphore, &attr, 0, 1); + if (res < 0) { + MutexDeinit(&cond->mutex); + res = cond->semaphore; + } + cond->waiting = 0; + return res; +} + +static inline int ConditionDeinit(Condition* cond) { + MutexDeinit(&cond->mutex); + return sysSemDestroy(cond->semaphore); +} + +static inline int ConditionWait(Condition* cond, Mutex* mutex) { + int ret = MutexLock(&cond->mutex); + if (ret < 0) { + return ret; + } + ++cond->waiting; + MutexUnlock(mutex); + MutexUnlock(&cond->mutex); + ret = sysSemWait(cond->semaphore, 0); + if (ret < 0) { + printf("Premature wakeup: %08X", ret); + } + MutexLock(mutex); + return ret; +} + +static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) { + int ret = MutexLock(&cond->mutex); + if (ret < 0) { + return ret; + } + ++cond->waiting; + MutexUnlock(mutex); + MutexUnlock(&cond->mutex); + u32 timeout = 0; + if (timeoutMs > 0) { + timeout = timeoutMs; + } + ret = sysSemWait(cond->semaphore, timeout); + if (ret < 0) { + printf("Premature wakeup: %08X", ret); + } + MutexLock(mutex); + return ret; +} + +static inline int ConditionWake(Condition* cond) { + MutexLock(&cond->mutex); + if (cond->waiting) { + --cond->waiting; + sysSemPost(cond->semaphore, 1); + } + MutexUnlock(&cond->mutex); + return 0; +} + +static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) { + return sysThreadCreate(thread, entry, context, 0, 0x10000, THREAD_JOINABLE, "sysThread"); +} + +static inline int ThreadJoin(Thread* thread) { + return sysThreadJoin(*thread, 0); +} + +static inline int ThreadSetName(const char* name) { + Thread threadToRename; + sysThreadGetId(&threadToRename); + return sysThreadRename(threadToRename, name); +} + +CXX_GUARD_END + +#endif diff --git a/include/mgba-util/threading.h b/include/mgba-util/threading.h index 445f47f92..1890c5886 100644 --- a/include/mgba-util/threading.h +++ b/include/mgba-util/threading.h @@ -21,6 +21,8 @@ CXX_GUARD_START #include #elif defined(__SWITCH__) #include +#elif defined(__lv2ppu__) +#include #else #define DISABLE_THREADING #endif @@ -75,8 +77,9 @@ static inline int MutexUnlock(Mutex* mutex) { return 0; } -static inline int ConditionInit(Condition* cond) { +static inline int ConditionInit(Condition* cond, Mutex* mutex) { UNUSED(cond); + UNUSED(mutex); return 0; } diff --git a/include/mgba-util/vfs.h b/include/mgba-util/vfs.h index c23515e5d..e6e16a512 100644 --- a/include/mgba-util/vfs.h +++ b/include/mgba-util/vfs.h @@ -99,7 +99,7 @@ struct VDir* VDirOpenZip(const char* path, int flags); struct VDir* VDirOpen7z(const char* path, int flags); #endif -#if defined(__wii__) || defined(__3DS__) || defined(PSP2) +#if defined(__wii__) || defined(__3DS__) || defined(PSP2) || defined(__lv2ppu__) struct VDir* VDeviceList(void); #endif diff --git a/src/core/config.c b/src/core/config.c index 4fa27ba55..4d6e6b0a7 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -297,7 +297,7 @@ void mCoreConfigPortableIniPath(char* out, size_t outLength) { } WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, outLength, 0, 0); StringCchCatA(out, outLength, PATH_SEP "portable.ini"); -#elif defined(PSP2) || defined(GEKKO) || defined(__SWITCH__) || defined(__3DS__) +#elif defined(PSP2) || defined(GEKKO) || defined(__SWITCH__) || defined(__3DS__) || defined(__lv2ppu__) UNUSED(outLength); out[0] = '\0'; #else diff --git a/src/feature/commandline.c b/src/feature/commandline.c index 1e22a4f2c..1a8ed582d 100644 --- a/src/feature/commandline.c +++ b/src/feature/commandline.c @@ -205,7 +205,11 @@ bool mArgumentsParse(struct mArguments* args, int argc, char* const* argv, struc } else if (argc == 1) { args->fname = strdup(argv[0]); } else { +#ifdef __lv2ppu__ + args->fname = "/dev_hdd0/mGBA/rom.gba"; +#else args->fname = NULL; +#endif } return true; } @@ -319,7 +323,7 @@ void mSubParserGraphicsInit(struct mSubParser* parser, struct mGraphicsOpts* opt parser->longOptions = _graphicsLongOpts; parser->handleExtraArg = NULL; opts->multiplier = 0; - opts->fullscreen = false; + opts->fullscreen = true; } bool _parseGraphicsArg(struct mSubParser* parser, int option, const char* arg) { diff --git a/src/gba/sio/dolphin.c b/src/gba/sio/dolphin.c index 0bb783e76..255c5a13f 100644 --- a/src/gba/sio/dolphin.c +++ b/src/gba/sio/dolphin.c @@ -3,6 +3,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef __lv2ppu__ // threads cause issues on PS3, do not include this file #include #include @@ -215,3 +216,4 @@ int32_t _processCommand(struct GBASIODolphin* dol, uint32_t cyclesLate) { bool GBASIODolphinIsConnected(struct GBASIODolphin* dol) { return dol->data != INVALID_SOCKET; } +#endif \ No newline at end of file diff --git a/src/platform/posix/memory.c b/src/platform/posix/memory.c index 67cdd96d7..c0cf08999 100644 --- a/src/platform/posix/memory.c +++ b/src/platform/posix/memory.c @@ -12,6 +12,9 @@ #if __has_feature(address_sanitizer) #define DISABLE_ANON_MMAP #endif +#ifdef __lv2ppu__ +#define DISABLE_ANON_MMAP +#endif #endif #endif diff --git a/src/platform/ps3/CMakeLists.txt b/src/platform/ps3/CMakeLists.txt new file mode 100644 index 000000000..d83bc68b9 --- /dev/null +++ b/src/platform/ps3/CMakeLists.txt @@ -0,0 +1,14 @@ +find_library(GLAPI_LIBRARY GL REQUIRED) +find_library(EGL_LIBRARY EGL REQUIRED) + +set(OS_DEFINES _GNU_SOURCE IOAPI_NO_64 ENABLE_VFS_FD) +list(APPEND VFS_SRC ${PROJECT_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${PROJECT_SOURCE_DIR}/src/util/vfs/vfs-dirent.c) +list(APPEND GUI_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gui-font.c) + +include_directories(AFTER ${OPENGL_EGL_INCLUDE_DIR}) + +set(VFS_SRC ${VFS_SRC} PARENT_SCOPE) +set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE) +set(OS_LIB ${OS_LIB} PARENT_SCOPE) + + diff --git a/src/platform/ps3/CMakeToolchain.txt b/src/platform/ps3/CMakeToolchain.txt new file mode 100644 index 000000000..f5775865c --- /dev/null +++ b/src/platform/ps3/CMakeToolchain.txt @@ -0,0 +1,63 @@ +# +# CMake platform file for PS3 PPU processor +# +# Based on the PS2 EE CMake File by: +# Copyright (C) 2009-2010 Mathias Lafeldt +# Copyright (C) 2023 Francisco Javier Trujillo Mata +# Copyright (C) 2024 André Guilherme +# Copyright (C) 2024-Present PS2DEV Team +# + +INCLUDE(CMakeForceCompiler) + +if(DEFINED ENV{PS3DEV}) + SET(PS3DEV $ENV{PS3DEV}) +else() + message(FATAL_ERROR "The environment variable PS3DEV needs needs to be defined.") +endif() + +if(DEFINED ENV{PSL1GHT}) + SET(PSL1GHT $ENV{PSL1GHT}) +else() + message(FATAL_ERROR "The environment variable PSL1GHT needs to be defined.") +endif() + +SET(CMAKE_SYSTEM_NAME Generic) +SET(CMAKE_SYSTEM_VERSION 1) +SET(CMAKE_SYSTEM_PROCESSOR powerpc) + +SET(CMAKE_C_COMPILER ppu-gcc) +SET(CMAKE_CXX_COMPILER ppu-g++) + +SET(PPU_CFLAGS "-mhard-float -fmodulo-sched -ffunction-sections -fdata-sections -I$ENV{PSL1GHT}/ppu/include -I$ENV{PSL1GHT}/portlibs/ppu/include -I$ENV{PSL1GHT}/ppu/include/simdmath") +SET(PPU_CXXFLAGS "-D_GLIBCXX11_USE_C99_STDIO ${PPU_CFLAGS}") +SET(PPU_LDFLAGS "-mhard-float -fmodulo-sched -Wl,--gc-sections -L$ENV{PSL1GHT}/ppu/lib -L$ENV{PSL1GHT}/portlibs/ppu/lib") + +SET(CMAKE_INSTALL_PREFIX $ENV{PS3DEV}/portlibs/ppu) + +SET(CMAKE_FIND_ROOT_PATH $ENV{PS3DEV} $ENV{PS3DEV}/ppu $ENV{PS3DEV}/portlibs/ppu) +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE) + +SET(CMAKE_C_FLAGS_INIT ${PPU_CFLAGS}) +SET(CMAKE_CXX_FLAGS_INIT ${PPU_CXXFLAGS}) +SET(CMAKE_EXE_LINKER_FLAGS_INIT ${PPU_LDFLAGS}) +SET(CMAKE_EXECUTABLE_SUFFIX "elf") +SET(CMAKE_EXECUTABLE_SUFFIX_ASM .elf) +SET(CMAKE_EXECUTABLE_SUFFIX_C .elf) +SET(CMAKE_EXECUTABLE_SUFFIX_CXX .elf) + + +SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-nostartfiles -Wl,-r -Wl,-d") + +SET($ENV{PKG_CONFIG_DIR} "") +SET($ENV{PKG_CONFIG_PATH} "") +SET($ENV{PKG_CONFIG_SYSROOT_DIR} "") +SET($ENV{PKG_CONFIG_LIBDIR} "$ENV{PS3DEV}/portlibs/ppu/lib/pkgconfig") + +SET(PS3 ON) +SET(PLATFORM_PS3 TRUE) +SET(PPU TRUE) diff --git a/src/platform/sdl/CMakeLists.txt b/src/platform/sdl/CMakeLists.txt index 2399dc599..69396aa1b 100644 --- a/src/platform/sdl/CMakeLists.txt +++ b/src/platform/sdl/CMakeLists.txt @@ -72,7 +72,11 @@ endif() set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libsdl${SDL_VERSION_DEBIAN}" PARENT_SCOPE) file(GLOB PLATFORM_SRC ${CMAKE_CURRENT_SOURCE_DIR}/sdl-*.c) +if(PS3) +set(PLATFORM_LIBRARY EGL GL stdc++ gcm_sys rsx sysutil io audio rt lv2 io audio ${SDL_LIBRARY} EGL GL stdc++ gcm_sys rsx sysutil io audio rt lv2 io audio ${SDLMAIN_LIBRARY} EGL GL stdc++ gcm_sys rsx sysutil io audio rt lv2 io audio ${SDL_LIBRARY} ${PIXMAN-1_LIBRARIES}) +else() set(PLATFORM_LIBRARY ${SDL_LIBRARY} ${SDLMAIN_LIBRARY} ${SDL_LIBRARY} ${PIXMAN-1_LIBRARIES}) +endif() include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${PIXMAN-1_INCLUDE_DIRS} ${SDL_INCLUDE_DIR}) set(SDL_INCLUDE_DIR "${SDL_INCLUDE_DIR}" PARENT_SCOPE) diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index df5218407..54e4bf1ad 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -90,6 +90,14 @@ bool mSDLInitEvents(struct mSDLEvents* context) { #endif SDL_JoystickEventState(SDL_ENABLE); +#if 0 + // Controller won't work unless + // we wait for them to show up + while(SDL_NumJoysticks() == 0) + { + SDL_PumpEvents(); + } +#endif int nJoysticks = SDL_NumJoysticks(); SDL_JoystickListInit(&context->joysticks, nJoysticks); if (nJoysticks > 0) {