diff --git a/CMakeLists.txt b/CMakeLists.txt index f758bd95..978395a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(isle LANGUAGES CXX C VERSION 0.1) if (EMSCRIPTEN) add_compile_options(-pthread) - add_link_options(-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=2gb -sUSE_PTHREADS=1 -sPROXY_TO_PTHREAD=1 -sPTHREAD_POOL_SIZE_STRICT=0 -sFORCE_FILESYSTEM=1 -sWASMFS=1 -sEXIT_RUNTIME=1) + add_link_options(-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=2gb -sUSE_PTHREADS=1 -sPROXY_TO_PTHREAD=1 -sOFFSCREENCANVAS_SUPPORT=1 -sPTHREAD_POOL_SIZE_STRICT=0 -sFORCE_FILESYSTEM=1 -sWASMFS=1 -sEXIT_RUNTIME=1) set(SDL_PTHREADS ON CACHE BOOL "Enable SDL pthreads" FORCE) endif() @@ -38,14 +38,14 @@ option(ISLE_WERROR "Treat warnings as errors" OFF) option(ISLE_DEBUG "Enable imgui debug" ON) cmake_dependent_option(ISLE_USE_DX5 "Build with internal DirectX 5 SDK" "${NOT_MINGW}" "WIN32;CMAKE_SIZEOF_VOID_P EQUAL 4" OFF) cmake_dependent_option(ISLE_MINIWIN "Use miniwin" ON "NOT ISLE_USE_DX5" OFF) -cmake_dependent_option(ISLE_BUILD_CONFIG "Build CONFIG.EXE application" ON "MSVC OR ISLE_MINIWIN;NOT NINTENDO_3DS" OFF) +cmake_dependent_option(ISLE_BUILD_CONFIG "Build CONFIG.EXE application" ON "(MSVC OR ISLE_MINIWIN) AND (NOT PSP) AND (NOT NINTENDO_3DS)" OFF) cmake_dependent_option(ISLE_COMPILE_SHADERS "Compile shaders" ON "SDL_SHADERCROSS_BIN;TARGET Python3::Interpreter" OFF) -option(CMAKE_POSITION_INDEPENDENT_CODE "Build with -fPIC" ON) +cmake_dependent_option(CMAKE_POSITION_INDEPENDENT_CODE "Build with -fPIC" ON "NOT PSP" OFF) option(ENABLE_CLANG_TIDY "Enable clang-tidy") option(DOWNLOAD_DEPENDENCIES "Download dependencies" ON) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" CACHE PATH "Directory where to put executables and dll") set(ISLE_EMSCRIPTEN_HOST "" CACHE STRING "Host URL for Emscripten streaming (e.g., https://test.com)") -cmake_dependent_option(BUILD_SHARED_LIBS "Build lego1 as a shared library" ON "NOT EMSCRIPTEN" OFF) +cmake_dependent_option(BUILD_SHARED_LIBS "Build lego1 as a shared library" ON "NOT EMSCRIPTEN AND NOT PSP" OFF) message(STATUS "Isle app: ${ISLE_BUILD_APP}") message(STATUS "Config app: ${ISLE_BUILD_CONFIG}") @@ -58,15 +58,19 @@ add_library(Isle::iniparser INTERFACE IMPORTED) if (DOWNLOAD_DEPENDENCIES) # FetchContent downloads and configures dependencies - message(STATUS "Fetching SDL3 and iniparser. This might take a while...") include(FetchContent) - FetchContent_Declare( - SDL3 - GIT_REPOSITORY "https://github.com/libsdl-org/SDL.git" - GIT_TAG "main" - EXCLUDE_FROM_ALL - ) - FetchContent_MakeAvailable(SDL3) + if (NOT PSP) + message(STATUS "Fetching SDL3 and iniparser. This might take a while...") + FetchContent_Declare( + SDL3 + GIT_REPOSITORY "https://github.com/libsdl-org/SDL.git" + GIT_TAG "main" + EXCLUDE_FROM_ALL + ) + FetchContent_MakeAvailable(SDL3) + else() + find_package(SDL3 CONFIG REQUIRED) + endif() FetchContent_Declare( iniparser @@ -348,6 +352,11 @@ if (WIN32) target_link_libraries(lego1 INTERFACE winmm) endif() target_link_libraries(lego1 PRIVATE libsmacker miniaudio) + +if (PSP) + target_link_libraries(lego1 PRIVATE atomic) +endif() + target_include_directories(lego1 PUBLIC $>) # lego1_impl sources @@ -505,6 +514,9 @@ if (ISLE_BUILD_APP) ) target_compile_definitions(isle PRIVATE ISLE_DEBUG) target_link_libraries(isle PRIVATE imgui) + if(PSP) + target_compile_definitions(imgui PRIVATE IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS) + endif() find_path(valgrind_INCLUDE_PATH NAMES valgrind/callgrind.h) if(valgrind_INCLUDE_PATH) # Run isle under valgrind to create a profile. Use e.g. kcachegrind to view the profile. @@ -673,6 +685,18 @@ if(NINTENDO_3DS) endif() if(MSVC) set(CPACK_GENERATOR ZIP) +elseif(PSP) + # Create an EBOOT.PBP file + create_pbp_file( + TARGET ${PROJECT_NAME} + ICON_PATH "${CMAKE_SOURCE_DIR}/XMB/Game/ICON0.png" + ANIM_PATH "${CMAKE_SOURCE_DIR}/XMB/Game/ICON1.pmf" + BACKGROUND_PATH "${CMAKE_SOURCE_DIR}/XMB/Game/PIC1.png" + PREVIEW_PATH NULL + MUSIC_PATH "${CMAKE_SOURCE_DIR}/XMB/Game/SND0.at3" + TITLE ${PROJECT_NAME} + VERSION 01.00 + ) else() set(CPACK_GENERATOR TGZ) endif() diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index e12f9183..8f69bf4e 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -665,7 +665,9 @@ MxResult IsleApp::SetupWindow() #if defined(MINIWIN) && !defined(__3DS__) SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); +#ifndef __PSP__ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); +#endif #endif window = SDL_CreateWindowWithProperties(props); diff --git a/LEGO1/omni/include/mxthread.h b/LEGO1/omni/include/mxthread.h index 8afa4454..ba0d89fa 100644 --- a/LEGO1/omni/include/mxthread.h +++ b/LEGO1/omni/include/mxthread.h @@ -5,7 +5,11 @@ #include "mxsemaphore.h" #include "mxtypes.h" +#ifdef PSP +#include +#else #include +#endif class MxCore; @@ -33,9 +37,15 @@ class MxThread { virtual ~MxThread(); private: +#ifdef PSP + static int ThreadProc(SceSize args, void* argp); + + int m_thread; +#else static int SDLCALL ThreadProc(void* p_thread); SDL_Thread* m_thread; +#endif MxBool m_running; // 0x0c MxSemaphore m_semaphore; // 0x10 diff --git a/LEGO1/omni/src/system/mxthread.cpp b/LEGO1/omni/src/system/mxthread.cpp index 96e64992..6c118d4d 100644 --- a/LEGO1/omni/src/system/mxthread.cpp +++ b/LEGO1/omni/src/system/mxthread.cpp @@ -3,13 +3,20 @@ #include "decomp.h" #include +#ifdef PSP +#include +#endif DECOMP_SIZE_ASSERT(MxThread, 0x1c) // FUNCTION: LEGO1 0x100bf510 MxThread::MxThread() { +#ifdef PSP + m_thread = 0; +#else m_thread = NULL; +#endif m_running = TRUE; } @@ -17,7 +24,13 @@ MxThread::MxThread() MxThread::~MxThread() { if (m_thread) { +#ifdef PSP + sceKernelWaitThreadEnd(m_thread, NULL); + sceKernelDeleteThread(m_thread); + m_thread = 0; +#else SDL_WaitThread(m_thread, NULL); +#endif } } @@ -27,6 +40,25 @@ MxResult MxThread::Start(MxS32 p_stackSize, MxS32 p_flag) MxResult result = FAILURE; if (m_semaphore.Init(0, 1) == SUCCESS) { +#ifdef PSP + int thid = sceKernelCreateThread( + "MxThread", + ThreadProc, + 0x18, // priority (0x18 is typical) + p_stackSize * 4, + 0, + NULL + ); + + if (thid >= 0) { + MxThread* self = this; + int start = sceKernelStartThread(thid, sizeof(MxThread*), &self); + if (start >= 0) { + result = SUCCESS; + m_thread = thid; // store thread ID if needed + } + } +#else const SDL_PropertiesID props = SDL_CreateProperties(); SDL_SetPointerProperty(props, SDL_PROP_THREAD_CREATE_ENTRY_FUNCTION_POINTER, (void*) MxThread::ThreadProc); SDL_SetPointerProperty(props, SDL_PROP_THREAD_CREATE_USERDATA_POINTER, this); @@ -37,6 +69,7 @@ MxResult MxThread::Start(MxS32 p_stackSize, MxS32 p_flag) } SDL_DestroyProperties(props); +#endif } return result; @@ -55,11 +88,19 @@ void MxThread::Terminate() m_semaphore.Wait(); } +#ifdef PSP +int MxThread::ThreadProc(SceSize args, void* argp) +{ + MxThread* self = *(MxThread**) argp; + return self->Run(); +} +#else // FUNCTION: LEGO1 0x100bf680 int MxThread::ThreadProc(void* p_thread) { return static_cast(p_thread)->Run(); } +#endif // FUNCTION: LEGO1 0x100bf690 MxResult MxThread::Run() diff --git a/XMB/Game/ICON0.png b/XMB/Game/ICON0.png new file mode 100644 index 00000000..d16c278b Binary files /dev/null and b/XMB/Game/ICON0.png differ diff --git a/XMB/Game/ICON1.pmf b/XMB/Game/ICON1.pmf new file mode 100644 index 00000000..bac01979 Binary files /dev/null and b/XMB/Game/ICON1.pmf differ diff --git a/XMB/Game/PIC1.png b/XMB/Game/PIC1.png new file mode 100644 index 00000000..b0916359 Binary files /dev/null and b/XMB/Game/PIC1.png differ diff --git a/XMB/Game/SND0.at3 b/XMB/Game/SND0.at3 new file mode 100644 index 00000000..47afc159 Binary files /dev/null and b/XMB/Game/SND0.at3 differ diff --git a/XMB/Save/EMPTY.png b/XMB/Save/EMPTY.png new file mode 100644 index 00000000..284649e6 Binary files /dev/null and b/XMB/Save/EMPTY.png differ diff --git a/XMB/Save/ICON0.png b/XMB/Save/ICON0.png new file mode 100644 index 00000000..d16c278b Binary files /dev/null and b/XMB/Save/ICON0.png differ diff --git a/XMB/Save/ICON1.pmf b/XMB/Save/ICON1.pmf new file mode 100644 index 00000000..faf5a77d Binary files /dev/null and b/XMB/Save/ICON1.pmf differ diff --git a/XMB/Save/Memory Stick Model Source.txt b/XMB/Save/Memory Stick Model Source.txt new file mode 100644 index 00000000..2a465251 --- /dev/null +++ b/XMB/Save/Memory Stick Model Source.txt @@ -0,0 +1 @@ +The model was sourced from https://3dwarehouse.sketchup.com/model/c300a598e63cb2f593dcf5e22ecc3f5e/Memory-Stick-Pro-Duo. It was further modified by Sonen10 to get the results seen in the animation. \ No newline at end of file diff --git a/XMB/Save/PIC1.png b/XMB/Save/PIC1.png new file mode 100644 index 00000000..7a0a7c4d Binary files /dev/null and b/XMB/Save/PIC1.png differ diff --git a/XMB/Save/SND0.AT3 b/XMB/Save/SND0.AT3 new file mode 100644 index 00000000..6f19ec8e Binary files /dev/null and b/XMB/Save/SND0.AT3 differ diff --git a/XMB/explanation.txt b/XMB/explanation.txt new file mode 100644 index 00000000..458d206c --- /dev/null +++ b/XMB/explanation.txt @@ -0,0 +1,10 @@ +Explanation of where the assets in these folders are used +ICON0.PNG - Icon used in various scenarios depending on if it's used for a save or a game. This includes when: +> The game/save isn't selected in the XMB +> There is no ICON1.PMF present (XMB only) +> The "Group Content" mode is enabled in the XMB game selection menu +> The game is on a save management screen with UI elements shared with the XMB (note the font) +ICON1.PMF - Seen when the game/save is selected in the XMB (NOT IN-GAME) +PIC1.PNG - Seen as a background when the game/save is selected in the XMB +SND0.AT3 - Plays when the game/save is selected in the XMB (NOT IN-GAME) +EMPTY.PNG - Used as an icon for empty saves when selecting a save to write to. diff --git a/miniwin/CMakeLists.txt b/miniwin/CMakeLists.txt index 851403cc..c2aa0bd6 100644 --- a/miniwin/CMakeLists.txt +++ b/miniwin/CMakeLists.txt @@ -45,11 +45,13 @@ else() endif() find_library(OPENGL_ES2_LIBRARY NAMES GLESv2) -if(OPENGL_ES2_LIBRARY) +if(EMSCRIPTEN OR OPENGL_ES2_LIBRARY) message(STATUS "Found OpenGL: enabling OpenGL ES 2.x renderer") target_sources(miniwin PRIVATE src/d3drm/backends/opengles2/renderer.cpp) target_compile_definitions(miniwin PRIVATE USE_OPENGLES2) - target_link_libraries(miniwin PRIVATE OpenGL::GL) + if(OPENGL_ES2_LIBRARY) + target_link_libraries(miniwin PRIVATE OpenGL::GL) + endif() else() message(STATUS "🧩 OpenGL ES 2.x support not enabled") endif() diff --git a/miniwin/src/d3drm/backends/opengl1/actual.cpp b/miniwin/src/d3drm/backends/opengl1/actual.cpp index b9234c8e..bf9c7504 100644 --- a/miniwin/src/d3drm/backends/opengl1/actual.cpp +++ b/miniwin/src/d3drm/backends/opengl1/actual.cpp @@ -211,8 +211,18 @@ void GL11_SubmitDraw( glLoadMatrixf(&modelViewMatrix[0][0]); glEnable(GL_NORMALIZE); +#ifndef __PSP__ glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a); +#else + GLfloat color[4] = { + appearance.color.r / 255.0f, + appearance.color.g / 255.0f, + appearance.color.b / 255.0f, + appearance.color.a / 255.0f + }; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); +#endif if (appearance.shininess != 0.0f) { GLfloat whiteSpec[] = {1.f, 1.f, 1.f, 1.f}; diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp index 4c6aacf9..65ebb20d 100644 --- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp @@ -23,7 +23,9 @@ Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height) // call below when on an EGL-based backend, and crashes with EGL_BAD_MATCH. SDL_GL_ResetAttributes(); // But ResetAttributes resets it to 16. +#ifndef __PSP__ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); +#endif SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); diff --git a/miniwin/src/internal/d3drmrenderer_opengl1.h b/miniwin/src/internal/d3drmrenderer_opengl1.h index 656a964b..6b19b219 100644 --- a/miniwin/src/internal/d3drmrenderer_opengl1.h +++ b/miniwin/src/internal/d3drmrenderer_opengl1.h @@ -56,11 +56,13 @@ class OpenGL1Renderer : public Direct3DRMRenderer { inline static void OpenGL1Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { +#ifndef __PSP__ Direct3DRMRenderer* device = OpenGL1Renderer::Create(640, 480); if (!device) { return; } delete device; +#endif D3DDEVICEDESC halDesc = {}; halDesc.dcmColorModel = D3DCOLORMODEL::RGB;