### Install zsync on Debian/Ubuntu Source: https://www.ppsspp.org/docs/reference/how-to-update Install the zsync delta-sync tool on Debian-based systems using apt. This tool is used to efficiently update AppImages by downloading only changed parts. ```bash sudo apt install zsync ``` -------------------------------- ### Search for PPSSPP AppImage using AM/appman Source: https://www.ppsspp.org/docs/reference/how-to-update Use 'am -q ppsspp' for system-wide installations or 'appman -q ppsspp' for user-level installations to find PPSSPP AppImages. This command queries the available AppImages matching the term 'ppsspp'. ```bash # For system-wide installation am -q ppsspp # For user-level installation appman -q ppsspp ``` -------------------------------- ### Configure Docker for GitHub CI with Shared Memory Source: https://www.ppsspp.org/docs/development/tips-and-tricks Example GitHub Actions configuration for running PPSSPPHeadless in a Docker container. Ensure sufficient shared memory size (`--shm-size`) for stability. ```yaml build_test_headless_alpine: runs-on: ubuntu-latest container: image: alpine:latest options: --shm-size=8g ``` -------------------------------- ### Clone PPSSPP Repository Source: https://www.ppsspp.org/docs/development/wsl Use this command to clone the PPSSPP repository and its submodules. Ensure you have Git installed in your WSL environment. ```bash git clone git@github.com:hrydgard/ppsspp.git --recursive ``` -------------------------------- ### Open Project in VS Code Source: https://www.ppsspp.org/docs/development/wsl Open the current directory in VS Code from the WSL terminal. This assumes VS Code and the WSL extension are installed on Windows. ```bash code . ``` -------------------------------- ### Build APK for Older Devices Source: https://www.ppsspp.org/docs/development/tips-and-tricks Use this option when Android Studio cannot directly install on ancient phones. The generated APK can then be installed via ADB. ```shell adb install android/build/outputs/apk/normal/optimized/android-normal-optimized.apk ``` -------------------------------- ### Go Directly to Settings Source: https://www.ppsspp.org/docs/reference/command-line Use the --gamesettings flag to launch PPSSPP directly into the settings menu. ```bash --gamesettings ``` -------------------------------- ### Go Directly to Touchscreen Test Source: https://www.ppsspp.org/docs/reference/command-line Use the --touchscreentest flag to launch PPSSPP directly into the touchscreen test screen. ```bash --touchscreentest ``` -------------------------------- ### sceAtracGetSoundSample Source: https://www.ppsspp.org/docs/development/ppsspp-internals/atrac Gets the total length of the audio track and the start/end positions of any loop sections, measured in output audio samples. ```APIDOC ## sceAtracGetSoundSample(id, *outEndSample, *outLoopStartSample, *outLoopEndSample) ### Description Gets the length of the track and the extents of the loop (if any, otherwise -1), counted in output audio sample positions. ``` -------------------------------- ### Typical sceMp3 Calling Sequence Source: https://www.ppsspp.org/docs/development/ppsspp-internals/mp3 This sequence demonstrates the common calls made to the sceMp3 module for MP3 playback, including initialization, data handling, and decoding. Note that sceMp3Init is called after the first read. ```c 0=sceMp3InitResource() startPos 14477 endPos a65e27 mp3buf 08af5580 mp3bufSize 00002000 PCMbuf 08af7580 PCMbufSize 00002400 00000000=sceMp3ReserveMp3Handle(09f94450) 0=sceMp3GetInfoToAddStreamData(00000000, 09f94430[08af5b40], 09f94434[00001a40], 09f94438[00014477]) 0=sceMp3NotifyAddStreamData(00000000, 6720) sceMp3Init(): channels=2, samplerate=32000Hz, bitrate=48kbps, layerBits=1 ,versionBits=3,HEADER: fffb3800 0=sceMp3Init(00000000) -1=sceMp3GetLoopNum(00000000) 4608=sceMp3Decode(00000000, 09f94470[08af7580]) 0=sceMp3SetLoopNum(00000000, 1) << called from main thread for some reason? 1=sceMp3CheckStreamDataNeeded(00000000) 0=sceMp3GetInfoToAddStreamData(00000000, 09f94440[08af5b40], 09f94444[000000d8], 09f94448[00015eb7]) 0=sceMp3NotifyAddStreamData(00000000, 216) 4608=sceMp3Decode(00000000, 09f94470[08af8780]) 1=sceMp3CheckStreamDataNeeded(00000000) 0=sceMp3GetInfoToAddStreamData(00000000, 09f94440[08af5b40], 09f94444[00000360], 09f94448[00015f8f]) 0=sceMp3NotifyAddStreamData(00000000, 864) 1=sceMp3GetLoopNum(00000000) 4608=sceMp3Decode(00000000, 09f94470[08af7580]) 1=sceMp3CheckStreamDataNeeded(00000000) 0=sceMp3GetInfoToAddStreamData(00000000, 09f94440[08af5b40], 09f94444[000003f0], 09f94448[000162ef]) 0=sceMp3NotifyAddStreamData(00000000, 1008) 4608=sceMp3Decode(00000000, 09f94470[08af8780]) 1=sceMp3CheckStreamDataNeeded(00000000) 0=sceMp3GetInfoToAddStreamData(00000000, 09f94440[08af5b40], 09f94444[00000480], 09f94448[000166df]) 0=sceMp3NotifyAddStreamData(00000000, 1152) 1=sceMp3GetLoopNum(00000000) 4608=sceMp3Decode(00000000, 09f94470[08af7580]) 1=sceMp3CheckStreamDataNeeded(00000000) 0=sceMp3GetInfoToAddStreamData(00000000, 09f94440[08af5b40], 09f94444[000003f0], 09f94448[00016b5f]) 0=sceMp3NotifyAddStreamData(00000000, 1008) ``` -------------------------------- ### Set CPU Backend Source: https://www.ppsspp.org/docs/reference/command-line Use flags to set the CPU backend for PPSSPP. Options include JIT (-j), Interpreter (-i), IR Interpreter (-r), and JIT IR (-J). ```bash -j ``` ```bash -i ``` ```bash -r ``` ```bash -J ``` -------------------------------- ### VS Code Launch Configuration for Mac/Linux Debugging Source: https://www.ppsspp.org/docs/development/tips-and-tricks A basic `.vscode/launch.json` configuration for debugging PPSSPP on macOS and Linux using LLDB. This configuration does not include a build step. ```json { "version": "0.2.0", "configurations": [ { "name": "(lldb) Launch", "type": "cppdbg", "request": "launch", "program": "", "osx": { "program": "${workspaceFolder}/build/PPSSPPSDL.app/Contents/MacOS/PPSSPPSDL" }, "linux": { "program": "${workspaceRoot}/build/PPSSPPSDL" }, "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "lldb" } ] } ``` -------------------------------- ### Get PSP Memory Base Address using Lua Source: https://www.ppsspp.org/docs/reference/process-hacks A Lua script to retrieve the PSP Memory Base Address by sending window messages to the PPSSPP process. This function is useful for external memory analysis tools. ```lua -- By "25094" on GitHub function GetEmuBase() local command = 0xB118 local emuHWND = findWindow("PPSSPPWnd") local pointer = {} local result = sendMessage(emuHWND, command, 0, 0) pointer[1] = tonumber(result) result = sendMessage(emuHWND, command, 0, 1) pointer[2] = tonumber(result) local lower = pointer[1] local upper = pointer[2] local combinedPointer = (upper * 0x100000000) + lower return tonumber(combinedPointer) end ``` -------------------------------- ### Compress PNG to KTX2 with Basis/UASTC Source: https://www.ppsspp.org/docs/reference/texture-replacement Use the basisu command-line tool to compress PNG images to KTX2 format with either UASTC or Basis compression. Mipmaps are generated by default. Use -mip_clamp for non-wrapping textures. ```bash basisu -uastc -mipmap -ktx2 my_transparent_or_hq_image.png basisu -mipmap -ktx2 my_solid_lower_quality_image.png ``` -------------------------------- ### Basic Texture Replacement Configuration Source: https://www.ppsspp.org/docs/reference/texture-replacement Configure texture replacement options, including hash algorithm and custom filenames. Use this to map specific memory addresses to custom texture files. ```ini [options] version = 1 hash = xxh64 ignoreAddress="true" [hashes] 099bf1c000000909 = 0993698000000909 = 09a47a0000000909 = 09ad024000000909 = 099c0db096c0500ecd2f3e6e = water/frame1.ktx2 099c2db0d26dc9a7966195cf = water/frame2.ktx2 099c4db0fa2cbcfec0bd3e0f = water/frame3.ktx2 099c6db0d17d9a67c7591d4f = water/frame4.ktx2 094b89907dcca1a5ee284131 = 094b5a707dcca1a5ee284131.png 094b89907dcca1a5ee284131_1 = 094b5a707dcca1a5ee284131_1.png [hashranges] 0x09936980,512,512 = 480,272 0x099bf1c0,512,512 = 480,272 0x09a47a00,512,512 = 480,272 0x09ad0240,512,512 = 480,272 0x090056d0,256,256 = 176,160 0x0900c4d0,256,64 = 208,56 [filtering] # Example: 08d3961000000909ba70b2af = nearest ``` -------------------------------- ### Force Fullscreen Mode Source: https://www.ppsspp.org/docs/reference/command-line Use the --fullscreen flag to force PPSSPP into fullscreen mode, overriding saved configurations. ```bash --fullscreen ``` -------------------------------- ### Launch PPSSPP with Pause Menu Exit Argument Source: https://www.ppsspp.org/docs/reference/front-end-integration Use this command to launch the PPSSPP application and immediately trigger the pause menu exit functionality. Ensure the correct package name for your PPSSPP version is used. ```bash adb shell am start -n org.ppsspp.ppsspp/org.ppsspp.ppsspp.PpssppActivity --es org.ppsspp.ppsspp.Args "--pause-menu-exit" ``` -------------------------------- ### Enforce GPU Backend on Windows Source: https://www.ppsspp.org/docs/reference/command-line Use flags to enforce a specific GPU backend on Windows. Options include Direct3D 11 (-direct3d11), Vulkan (-vulkan), OpenGL ES (-gles), and Software (-software). ```bash -direct3d11 ``` ```bash -vulkan ``` ```bash -gles ``` ```bash -software ``` -------------------------------- ### sceAtracGetBufferInfoForResetting Source: https://www.ppsspp.org/docs/development/ppsspp-internals/atrac Retrieves buffer information required for resetting the playback position and potentially skips frames. ```APIDOC ## sceAtracGetBufferInfoForResetting() ### Description This one is a lot less innocent than it looks! It returns the data range it wants you to read in order to call sceAtracResetPlayPosition, but also, if there are any frames to skip, it'll go ahead and skip it, for no apparent reason. It makes no sense that this happens, given that the next thing that gets called actually resets everything again. ``` -------------------------------- ### Force Windowed Mode Source: https://www.ppsspp.org/docs/reference/command-line Use the --windowed flag to force PPSSPP into windowed mode, overriding saved configurations. ```bash --windowed ``` -------------------------------- ### Initial Savestate Chunk Version Source: https://www.ppsspp.org/docs/development/ppsspp-internals/savestate This C++ code defines the initial version of a savestate chunk for 'SampleSystem', including two integer variables. ```cpp int g_stateVar1; int g_stateVar2; void SampleSystem_DoState(PointerWrap &p) { auto s = p.Section("SampleSystem", 1, 1); if (!s) return; Do(p, g_stateVar1); Do(p, g_stateVar2); } ``` -------------------------------- ### Recursively Convert PNG Directory to KTX2 on Windows Source: https://www.ppsspp.org/docs/reference/texture-replacement A Windows batch script to recursively find all PNG files in a directory and its subdirectories, converting them to KTX2 format using basisu. The output files are placed in the same directory as the original PNGs. ```batch for /r %%v in (*.png) do basisu "%%v" -ktx2 -uastc -mipmap -output_path %%~dpv pause ``` -------------------------------- ### Make PPSSPP AppImage executable Source: https://www.ppsspp.org/docs/reference/how-to-update After updating an AppImage using zsync, if a new file is created, mark it as executable using chmod +x. Then, you can run the updated AppImage directly. ```bash chmod +x PPSSPP-v1.20.3-anylinux-x86_64.AppImage ./PPSSPP-v1.20.3-anylinux-x86_64.AppImage ``` -------------------------------- ### Update PPSSPP AppImage using zsync Source: https://www.ppsspp.org/docs/reference/how-to-update Update an existing PPSSPP AppImage by using the corresponding .zsync file. Place both the current AppImage and the .zsync file in the same directory, then run 'zsync' with the .zsync file as an argument. This reuses most of the old file and only downloads differences. ```bash cd ~/Downloads/PPSSPP zsync PPSSPP-v1.20.3-anylinux-x86_64.AppImage.zsync ``` -------------------------------- ### sceAtracSetDataAndGetID Source: https://www.ppsspp.org/docs/development/ppsspp-internals/atrac Initializes the ATRAC library by filling the entire specified buffer. The resulting internal state depends on the file contents and the provided buffer size. ```APIDOC ## sceAtracSetDataAndGetID(data, size) ### Description Like `sceAtracSetHalfwayBuffer`, but fills the entire specified buffer. Size can be any value (down to certain limitations), even byte-aligned! 0x4301 works and doesn't crash. Games generally uses sizes like 0x18000, 0x10000, etc. ### Depending on the file contents and the buffer size, the internal state can end up as any of: * `ALL_DATA_LOADED` * `STREAMED_WITHOUT_LOOP` * `STREAMED_WITH_LOOP_AT_END` * `STREAMED_WITH_SECOND_BUF` ``` -------------------------------- ### Compress ISO to CHD using chdman Source: https://www.ppsspp.org/docs/getting-started/dumping-games Use this command to compress a PSP ISO file into the CHD format using the 'createdvd' command with a 2048-byte hunk size for optimal performance. ```bash chdman createdvd -hs 2048 -i game.iso -o game.chd ``` -------------------------------- ### PPSSPP Plugin Configuration Source: https://www.ppsspp.org/docs/reference/plugins This INI file configures plugin options, supported games, and language-specific settings. Ensure the 'filename' matches your compiled plugin. ```ini [options] version = 1 type = prx filename = patch.prx ; Always specify games to indicate what games are supported. [games] ; Normal usage: specify game IDs that are supported. ULJM05275 = true ; Advanced usage: specify another ini to use a separate prx for a certain game ID. ; (in most cases, you won't use this.) ULES01048 = spanish.ini ; General plugins for any game: use ALL to indicate all game IDs. ALL = true ; Optional, specify ini for another prx for specific user interface languages. ; (in most cases, you won't use this.) [lang] hr_HR = croatian.ini ``` -------------------------------- ### sceAtracSetHalfwayBufferAndGetID Source: https://www.ppsspp.org/docs/development/ppsspp-internals/atrac Initializes the ATRAC library with a partially filled buffer. This function is useful for looping audio with minimal I/O and can result in various internal states depending on buffer size and loop parameters. ```APIDOC ## sceAtracSetHalfwayBufferAndGetID(bufferPtr, validDataSize, bufferSize) ### Description Tells the library that you'll supply a partially filled buffer (validDataSize out of bufferSize). Use the combination `sceAtracGetRemainFrame/(last output of sceAtracDecodeData)`/`sceAtracGetStreamDataInfo`/`sceAtracAddStreamData` to progressively fill it up while it's being played. This is most useful when you have spare memory, and want to loop the audio without extra I/O later. If the buffer can fit the whole file, the internal state is set to `HALFWAY_BUFFER` (see above). You can also use it to only partially initialize a buffer for streaming, GTA does this. In this case, the state will end up in one of the streaming modes, depending on the loop parameters stored in the WAVE header. ### Possible resulting states: * `ALL_DATA_LOADED` * `HALFWAY_BUFFER` * `STREAMED_WITHOUT_LOOP` * `STREAMED_WITH_LOOP_AT_END` * `STREAMED_WITH_SECOND_BUF` ``` -------------------------------- ### ATRAC Streamed Decoding (Suicide Barbie) Source: https://www.ppsspp.org/docs/development/ppsspp-internals/atrac Demonstrates a streaming ATRAC decoding loop for games like Suicide Barbie. It decodes data in chunks and refills the buffer when remaining frames are low. ```assembly 0=sceAtracSetDataAndGetID(09ef9f00, 00040000) 0=sceAtracGetRemainFrame(0, 09ffee24[0000015f]) 0=sceAtracGetMaxSample(0, 09ffee3c[00000800]) loop: 0=sceAtracDecodeData(0, 09ef1f00, 09ffee28[00000690], 09ffee38[00000000], 09ffee24[350]) Until remainFrame (last param) <= 175. Then: 0=sceAtracGetStreamDataInfo(0, 09ffee2c[09ef9fa0], 09ffee30[00020228], 09ffee34[00040000]) 0=sceAtracAddStreamData(0, 00020000) goto loop ``` -------------------------------- ### Define WM_USER_GET_EMULATION_STATE Source: https://www.ppsspp.org/docs/reference/process-hacks Defines the window message used to query the emulation state of PPSSPP. Returns 1 if a game is running, 0 otherwise. Available since version 1.15.4. ```c++ const UINT WM_USER_GET_EMULATION_STATE = WM_APP + 0x3119; // 0xB119 ``` -------------------------------- ### ATRAC Small Buffer Decoding (Tekken 6) Source: https://www.ppsspp.org/docs/development/ppsspp-internals/atrac Illustrates ATRAC decoding with an unusually small buffer, as used in Tekken 6. This requires careful management of data streaming and buffer refills. ```assembly 0=sceAtracSetDataAndGetID(092bd940, 00010000) 0=sceAtracSetLoopNum(0, -1) 0=sceAtracGetRemainFrame(0, 09fdea78[00000056]) 0=sceAtracIsSecondBufferNeeded(0) 0=sceAtracDecodeData(0, 092cfa00, 09fdea70[000003b4], 09fdea74[00000000], 09fdea78[85]) 0=sceAtracDecodeData(0, 092d08d0, 09fdea70[00000800], 09fdea74[00000000], 09fdea78[84]) 0=sceAtracDecodeData(0, 092d28d0, 09fdea70[00000800], 09fdea74[00000000], 09fdea78[83]) 0=sceAtracGetStreamDataInfo(0, 093241e0[092bdbc4], 093241e4[000080e8], 093241e8[00010000]) 0=sceAtracDecodeData(0, 092d1ad0, 09fdea70[00000800], 09fdea74[00000000], 09fdea78[41]) 0=sceAtracAddStreamData(0, 000080e8) 0=sceAtracDecodeData(0, 092d3ad0, 09fdea70[00000800], 09fdea74[00000000], 09fdea78[85]) ```