Skip to content
vs-sr-devPublic

About

A game-agnostic toolkit for native PC ports of PS3 games: the executable's structure, Cell PPU and SPU decoders, a static recompiler to C++, and a runtime that replaces the PS3's system software. No game data.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

19 Commits

Folders and files

Repository files navigation

ps3kit

A game-agnostic toolkit for native PC ports of PS3 games: the executable's structure, the Cell PPU, a static recompiler from PPU code to C++, and a runtime that replaces the PS3's system software under the recompiled game.

The same idea as wiikit and ps2kit, for the PS3. Each PS3 game has its own engine and formats, but a large part of every port is the same work: the same executable format, CPU, system calls, libraries and GPU. ps3kit collects that shared part. It grows inside the ports: each piece is written because a game needed it, then kept free of that game's knowledge. Game formats and game fixes live in the ports.

It grew inside its first port, PC-ROA, and moved to its own repository, with its history, when the second one started. Each port takes it back as a submodule at ps3kit/.

Ports built on it

Port Game What it asked of ps3kit
pc-ragnarokodysseyace Ragnarok Odyssey ACE (2013) everything so far: the descriptor table, the imports, the PPU recompiler, the process start, threads, files, the command buffer to its first flip, the audio ports and their clock, the window, the RSX's draws: the publishers' logos; save data; cellSail and an MPEG-2 decoder: the first movie; the controller: the title screen, the main menu and character creation; the SPU recompiler and a job manager: CRI's sound, heard; cellFont with an OpenType/CFF reader and a rasterizer of its own: character creation's text; system events and the on-screen keyboard: the hero's name
pc-3ddotgameheroes 3D Dot Game Heroes (2009) the SPUs: SPU ELFs recompiled at their load address, lv2 SPU thread groups (FMOD's mixer), SPURS task sets, tasks and event flags on a kernel of the runtime's own, spu_printf; switch tables the compiler did not optimise; the I/O map, reports and inline image transfers (the fragment programs); audio notifications; /dev_flash and /dev_hdd1: the publishers' and the middleware's logos; trophies, read from the disc's set and kept; SPU modules recompiled where their loader puts them (FMOD's codec): the title screen, its demo play and FMOD's music; SPURS lock-free queues and queues (Edge zlib, Bullet), position-independent SPU code's jumps, vertex arrays kept while unwritten: the first field, played at 30 frames

Using it

ps3kit does not decrypt: the input is the decrypted executable (a 64-bit big-endian ELF), produced from the player's own EBOOT.BIN. The generated C++ is the game's own code translated, so it belongs in a build directory and never in a repository.

python -m ps3kit.elf GAME.elf --imports --opd     # segments, parameters, imports by name
python -m ps3kit.ppu GAME.elf --at 0x10200        # read code
python -m ps3kit.ppu GAME.elf --mix               # the instruction census
python -m ps3kit.spu GAME.elf --at 0xF3D260 --base 0xF3D200   # read SPU code, local-store addresses
python -m ps3kit.spu GAME.elf --mix 0xF3D200:0xFE20           # an SPU program's census
python -m ps3kit.recomp GAME.elf --out build/recomp
cmake -S build/recomp -B build/recomp-build -G Ninja -DCMAKE_CXX_COMPILER=clang++ \
    -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS_RELEASE=-O1
ninja -C build/recomp-build
build/recomp-build/ps3boot GAME.elf --bdvd DISC --hdd0 DIR   # DISC holds PS3_GAME

ps3boot opens a window and runs the game behind it. --hdd1 DIR is the root of the system caches (/dev_hdd1, hdd1 if not given) and --flash DIR is /dev_flash, read-only, for a game whose middleware reads the system's own files there. --no-video runs the game alone, --quit-after SECONDS ends the run, and --dump DIR writes every 60th shown frame as a PNG (--dump-every N for another interval).

Debugging a run: ps3boot reports a host fault with the guest address it touched (in a library, such as the C runtime's memcpy, with the library's name and the executable's addresses found on the stack above it, which nm names), and gdb_trace.py traces any recompiled function under gdb (arguments, result, the guest call chain) with no debug build:

PS3KIT_TRACE_FUNCS=81BEE8 PS3KIT_TRACE_CHAIN=1 gdb -q -batch -x ps3kit/gdb_trace.py \
    --args build/recomp-build/ps3boot GAME.elf --bdvd DISC

PS3KIT_TRACE=1 reports every import call (by default each one's first three), PS3KIT_FS=1 every file opened, PS3KIT_RSX_TRACE=N every RSX method of frame N with its argument, PS3KIT_DRAWDUMP=N draw N's vertices, constants and state, PS3KIT_SHADERDUMP=1 every program pair as GLSL, PS3KIT_TEXDUMP=DIR every texture as first decoded (PNG), and PS3KIT_GLDEBUG=1 the OpenGL driver's complaints, PS3KIT_GLSYNC=N each draw from draw N on, waited for (so that a draw which brings the driver down is the last one reported), PS3KIT_SAVEDATA=1 each save data step and callback result, PS3KIT_TROPHY=1 each trophy context and status reported to the game, PS3KIT_SAIL=1 each movie player call and event and every 30th frame shown.

PS3KIT_SPU=1 reports each SPU program's first job and how long its jobs take, PS3KIT_SPU_DMA=1 every DMA transfer an SPU program makes (=2 with its words), PS3KIT_SPU_TRACE=1 every indirect branch in SPU code, and PS3KIT_SPU_TRACE=2 every instruction, once the code has been generated with python -m ps3kit.recomp ... --spu-step. PS3KIT_AUDIODUMP=FILE.wav writes what the audio output plays, and PS3KIT_AUDIO=1 how many notifications the audio clock sent and dropped each second.

PS3KIT_LV2=1 reports every lv2 call that has an implementation, with its arguments and result (the stubs are always reported). PS3KIT_SPURS=1 reports each SPURS task's start, system calls, events and exit, and the raw block behind each spu_printf it makes.

PS3KIT_PROF=1 reports, every 30 flips, where the wall-clock time went: the RSX thread idle, on semaphores, capturing draws, waiting for the vblank or for the renderer; the renderer executing, presenting, idle, compiling new programs and making new textures; SPURS jobs; with the draws, the bytes hashed and sent, and the new programs and textures. A frame-rate drop then names its own cause.

PS3KIT_OSK=1 reports each on-screen keyboard call, and PS3KIT_OSK_TYPE="Name" answers every keyboard at once with that text, confirmed.

PS3KIT_PAD_PRESS="30:cross,46:start,52:cross+up" presses the controller's buttons for a fifth of a second at those times (seconds from the window's first poll), so that a run nobody plays can still get past a screen.

PS3KIT_FONT=1 reports each font call and every glyph drawn, with where it lands on the surface.

fonttest FONT SIZE TEXT OUT.pgm (ninja fonttest) lays a string out with the font reader and the rasterizer alone, so that it can be set beside another renderer's image of the same string.

mpeg2test MOVIE OUT.yuv [--offset BYTES] (ninja mpeg2test) runs the MPEG-2 decoder alone, on a program stream or an elementary stream, so that its frames can be compared with another decoder's.

Building needs SDL3, CMake, Ninja and clang (the generated code's tail jumps are [[clang::musttail]]; clang 22 from MSYS2 is what is used here). The Python side has no dependencies.

How it works

Functions. A PS3 executable is stripped, but every function whose address is ever taken has an 8-byte descriptor, {entry, toc}, in one table that e_entry points into. Those entries, plus every bl target, are the units; the code ends where the last unit reachable that way ends (the import stubs). A branch out of a unit's body to a place that is not a unit start makes an extra entry, as wiikit does.

Code. Each entry becomes void f_XXXXXXXX(PPUContext&). Registers live in the context; memory is a 4 GiB host reservation indexed by guest address, big-endian. A branch to another function is a guaranteed tail call, so a guest loop that crosses a function boundary does not grow the host stack. Switch tables (lwz of the table from the TOC, lwzx, extsw, add, bctr) become C++ switches; every other indirect branch goes through a sorted address table.

Imports. The loader's job, done the loader's way: each slot of the stub table gets a descriptor whose entry is an address in the runtime's range. A call through it is dispatched to the C++ function registered under the import's name (PS3_HLE(name)), or to a stub that reports it. Names come from nids.txt; a NID is computed from its name, never stored.

System calls. sc dispatches on r11 to LV2_SYSCALL(number, name).

SPU programs. Each one is translated whole into a single function, compiled for the local-store address it will be loaded at: every instruction is a label, a direct branch is a goto, and an indirect one (a return, a computed jump) goes through a switch over every instruction. SPU code has no call distinct from a branch and returns through registers, so this needs no discovery of functions at all. A register keeps its bytes in host order reversed as a whole, which makes the 128-bit value the same number as on the SPU: element-wise operations run on host vector lanes and quadword shifts are shifts of an unsigned __int128. SPURS job binaries are found by the header their job runtime (JOBCRT) carries; they are position-independent and relocate themselves.

Layers

Layer Question it answers Now Next
1. Recognise What is in this executable? elf: segments, process parameters, TLS, the descriptor table, imports by name; SPURS job binaries by their job-runtime header; SPU ELFs by their header and .note.spu_name (recomp.spu.find_elfs) task sets, the middleware it links
2. Read code What does this function do? ppu: the PPU decoder, disassembly, census; spu: the same for the SPU cross-references through the TOC
3. Recompile The code as C++ recomp: discovery, switch tables, the whole user-mode PPU set and the VMX operations games use; each SPU program whole, every SPU instruction but bisled and the double compares by magnitude: SPURS jobs, and SPU ELFs at their load address, dispatching only where an indirect branch can land; SPU modules another SPU program loads (FMOD's codecs and effects), at the bias a run shows (--spu-module-bias)
4. Run The PS3 under the game runtime: memory map, dispatch, loader, imports, lv2 calls, the process start; PPU threads, lightweight and lv2 synchronisation, event queues; the file system (cellFs and sys_fs); cellGame; cellGcmSys and cellResc with a FIFO consumer, labels, reports, the I/O map, flips and a 59.94 Hz vblank; the renderer (SDL3, OpenGL 4.5): a window, render targets on the host GPU, clears, draws with vertex and fragment programs translated to GLSL, textures, blending, flips; video out; cellAudio and the audio output, with the 48 kHz clock that consumes the ports and plays them through SDL3; SPURS job queues with a job manager running recompiled SPU programs: the SPU's channels, its DMA and atomic unit, the lock-line reservation event; lv2 SPU images and thread groups, the threads' mailboxes, event ports and local stores; SPURS instances, task sets, tasks, exit codes, event flags and the PPU's side of lock-free queues, on a kernel of the runtime's own; save data (Auto, ListAuto, Fixed) with PARAM.SFO; trophies (sceNpTrophy) from the disc's TROPHY.TRP, the unlocks kept on /dev_hdd0; SPU modules run as overlays when their loader branches into them; cellSail playing PAMF through the runtime's own MPEG-2 decoder; cellPad from the host's gamepad and keyboard; system events raised through cellSysutilCheckCallback; cellOskDialog typed on the host's keyboard; cellFont over the runtime's own OpenType reader (CFF outlines, name- or CID-keyed) and coverage rasterizer the rest of the 3D engine's state (fog, clip planes, two-sided colour, point sprites), TrueType outlines and the system's font sets, the list save dialogs, SPURS queues and barriers, the SPU's side of lock-free queues

Known approximations

Declared here as they are made, so that the list is the cost:

  • fres, frsqrte and the VMX estimates return exact values, not the hardware's estimates; FPSCR exception bits are not kept, and the saturating VMX operations never set VSCR[SAT].
  • The word divides write zero into the undefined high word.
  • lwarx/stwcx. is a compare-and-swap against the value the reservation saw: a store of the same value in between goes unnoticed.
  • Guest threads are host threads and the host schedules them. Guest priorities order nothing among themselves; a thread more urgent than the primary thread runs at the host's above-normal priority. Every synchronisation object shares one lock and one condition variable; waiters race rather than queue.
  • sys_timer_usleep and the system's clocks sleep on a high-resolution waitable timer on Windows, and the process opts out of the power throttling that coarsens a background window's timers. With the ordinary sleep, CRI's 60 Hz server woke up to 12 ms late a few times a second and the audio it feeds fell a whole port behind.
  • The RSX's 3D engine is the registers a draw reads so far: surfaces, clears, viewport, scissor, blending, colour masks, depth, stencil, culling, logic op, alpha test, vertex arrays, both programs, textures. Fog, user clip planes, two-sided colour, flat shading, point sprites, polygon offset and depth bounds are written and not acted on.
  • Fragment programs keep their 16-bit H registers apart from the 32-bit R registers instead of aliasing two H onto one R, and compute everything at full precision; only the fixed-point and saturating clamps are applied.
  • Not translated yet, and reported when met: a vertex program's branch through the address register (BRA) and its texture fetches, CAL in a fragment program, indexed fragment inputs, texture expansion (_bx2), unnormalised texture coordinates and packed (CMP) vertex attributes.
  • A texture's key is the hash of its layout and bytes, kept by address and layout while its memory goes unwritten: the pages are made read-only when it is hashed, and a write into one faults once, is recorded and goes through (Windows only; elsewhere every bind hashes again). The host's own file reads into guest memory unprotect their range first, since a kernel write into a read-only page fails rather than faults. Hashing every bind had cost the RSX thread up to 3 GB a second in the first town. The renderer keeps each distinct texture until 512 MB have been sent; then it forgets them all. A texture over a surface the renderer has made (by a draw or a clear) is sampled on the GPU and guest memory is not read: what the GPU drew is not there. Hashing the 1280x1280 shadow map's depth buffer from memory on every draw that sampled it had held character creation to 9 frames a second.
  • A draw's vertex arrays are watched the same way, by address, length and format. One found unwritten by a later draw gets a key, and the renderer draws it from a buffer of its own, until 256 MB of them have been sent; until then, and as soon as it is written again, it is sent with every draw and its buffer let go, so that arrays the game rewrites make no buffers (thousands of short-lived ones had slowed the driver down, by up to half a frame rate). An array found written three times running is taken to be rewritten every frame and is copied every time without being watched (each write would fault), tried again every 256th time. Copying every array of every draw had held 3D Dot Game Heroes' first field to 8 frames a second (110 MB a frame of voxel triangle lists).
  • A D24S8 depth surface sampled as A8R8G8B8 is converted on the GPU to the bytes the RSX would read (depth from the top in A, R and G, the stencil in B), again only when the surface has been written since. Any other format over a depth surface is read from memory and reported.
  • A render target found again at the same address with another size or format is made anew, and what it held is lost.
  • A display buffer no render target was drawn to is read from guest memory when the renderer shows it, which may be up to two flips after the game flipped it.
  • Resc's conversion shows the source buffer itself, which is only right while the source and the display are the same size (1280x720 here).
  • cellRescGetBufferSize's colour-buffer size is a reading: the largest supported, registered destination times its buffer count. Its vertex-array and fragment-shader sizes are the runtime's own.
  • The video output is fixed: one HDMI display, 1280x720, 59.94 Hz.
  • System events are raised only for what the runtime posts (so far the on-screen keyboard's): to every registered callback, on the thread that next calls cellSysutilCheckCallback; an event posted while they run waits for the next check. The XMB, quitting and the other system events never happen.
  • The on-screen keyboard is the runtime's own: a panel over the display with the game's message and the text typed so far, in the first font the game opened from memory, typed on the host's keyboard (Enter, Escape, Backspace); the display behind it is dimmed to half unless the game disabled the dimmer. Its protocol is the system's (LOADED, FINISHED with 0 for confirm and 1 for cancel, the result written by UnloadAsync, then UNLOADED); the FINISHED parameter and the error for a dialog that is not open (the message dialog's) are readings, not confirmed. While it is open the controller reports a neutral state with the intercepted bit set, and after it closes the keyboard counts again only once every key is up. A confirm-word filter callback is accepted and never run.
  • The audio system's clock consumes every started port's block each 256/48000 s, clears it and moves the read index on, from the host's steady clock, and plays what it took: mixed down to stereo (centre and surrounds at -3 dB, the LFE dropped) and sent to an SDL3 stream, which drops a block when more than a fifth of a second is queued. The port buffers and read indices live in the runtime's heap, so their addresses are the runtime's own.
  • The audio output is fixed like the video output: HDMI, two-channel linear PCM at 48 kHz. Configuring any other channel count is refused.
  • A SPURS job queue's jobs run when they are pushed, on the pushing thread, in a local store of that thread's, so every job has completed when the push returns and a sync never waits. The manager is the runtime's own: the binary sits at local store 0x1000, its context and descriptor below it, its buffers above and the stack at the top. Of the context it fills the input buffer, the output buffer, scratch, the DMA tag (16, a choice; the job uses the next one too) and the descriptor's address; the word at +0x14, which the job runtime insists is a non-null local-store pointer and then clears, points at the descriptor's copy. Cache lists and in-out buffers are refused and reported. A job whose program was not recompiled completes having done nothing.
  • The MFC completes each command as it is issued, so every tag group is always complete; list stall-and-notify is not honoured. GETLLAR and PUTLLC compare the whole 128-byte line under a lock shared by the SPUs only. The mailboxes are reported and never answered; the decrementer runs at 79.8 MHz from the host clock.
  • SPU single precision is the host's IEEE arithmetic: no saturation in place of infinities, denormals kept. frest/frsqest are exact and fi passes its estimate through.
  • cellSysutilGetBgmPlaybackStatus reports the system's music player stopped. Its PLAY state is 0, so a status left unwritten told the game the user's music was playing, and CRI held the game's own music at -100 dB.
  • Save data: no dialog is drawn. A Fixed operation's confirmation is answered yes; a callback's error ends the call with CELL_SAVEDATA_ERROR_CBRESULT and no message. The List operations, whose list dialog is the user's, are not implemented. Files are stored as written: secure files are not encrypted and no PARAM.PFD is made; the runtime's PS3KIT.LST keeps the files' order and which are secure. ACCOUNT_ID, PARAMS and PARAMS2 in a save's PARAM.SFO are zeros. The system's own files are reported as 35 KB, and the free space as cellGameBootCheck reports it.
  • cellSail plays the first video stream of a PAMF file; audio streams, MP4 and AVI are not supported. The order of its events is a reading of what the one caller so far polls for (see sail.cpp); the state the player passes through at the end of a stream (straight to OPENED) is the runtime's. It allocates nothing through the game's allocator; it asks the graphics adapter for four frame buffers. Frames are shown on the host's clock from the first one decoded, never dropped.
  • cellSailGraphicsAdapterGetFrame2 returns the frame's size in bytes: its caller takes any result above 255 as a frame. PtsToTimePosition answers in microseconds from the first picture; the caller only tests it against zero, so the unit is unconfirmed.
  • Movie frames are converted to ARGB with the stream's matrix (BT.709 here) from limited range, chroma interpolated linearly; how the system's converter filters is not known.
  • The MPEG-2 decoder uses the floating-point reference IDCT. On the disc's movies it is within 3 levels of ffmpeg's (63 dB and above), which is the difference between two IDCTs. Field pictures and dual-prime prediction are reported and not decoded; nothing on this disc uses them.
  • A texture whose format the renderer does not know, or whose linear rows are longer than their pitch, is reported with its registers and drawn with no image.
  • One standard controller is connected to port 0, and no keyboard. Its state is the host's first SDL gamepad, by position (south is cross), and the keyboard mapped onto the same buttons (see pad.cpp); the keyboard map is the runtime's own, standing where a gamepad goes. Pressure values are 255 for a pressed button, the triggers' travel for L2 and R2; the motion sensors report a controller at rest; the motors do not turn.
  • Vertex programs that branch are translated as the basic blocks their start reaches, in a loop over a program counter, at most 65,535 passes a vertex (a switch with a case per instruction brought the NVIDIA driver down). A branch tests its condition whether or not the instruction's test-enable bit is set; read the other way, every branch was taken and a skinning loop never ended.
  • Fonts are drawn unhinted, each pixel's coverage the exact area of the flattened outline in it (nonzero rule, 256 levels clamped to 255, as FreeType's smooth renderer counts them). The system library is FreeType, but which version, and whether it hints, is not known; the shapes match FreeType 2.14's on the disc's font. Glyph metrics are the outline's control box and its hmtx advance at the scale set, unrounded; vertical metrics come from vmtx and VORG, with the vertical bearing X centred. The library's record of a font set's type is all zeros.
  • cellFontRenderCharGlyphImage places the baseline one em (the render scale's height) below y: a reading of the one game's arithmetic, which its font cannot tell from the font's ascent-to-descent height (see font.cpp). The pen's x is taken to whole pixels. The glyph image lives in a buffer of the runtime's heap, not one allocated through the game's memory interface; a surface of one byte per pixel is drawn into, a wider one is left to the caller, who copies the image the transfer record points at. GetHorizontalLayout reports hhea's ascender as the baseline and ascender to descender plus line gap as the line's height, unconfirmed (the game reads neither).
  • The system's font sets are not installed. cellFontOpenFontset succeeds, and every glyph asked of such a font is refused with NO_SUPPORT_GLYPH and reported once per character.
  • SPU ELFs are translated for the address their program header loads them at, and their dispatch has a case only where an indirect branch can land: the entry, every return address, and every code address the program holds as a constant, in an immediate load or as a word of its loaded segments. An indirect branch anywhere else inside the program is reported (spu_missed) and ends it. (A case for every instruction had clang compiling Bullet's 43,448-instruction task for more than ten minutes; the targets are 588.) Jobs keep a case per instruction.
  • lv2 SPU threads run on host threads, from the moment their group starts. A terminated group's threads end at their next channel access or stop; sys_spu_thread_group_suspend is reported and not done. Only the user event ports (SYS_SPU_THREAD_EVENT_USER) connect.
  • A relocatable SPU module (FMOD's codecs and effects) is recompiled at one or more biases given to the recompiler, read off a run of the game (--spu-module-bias): every module at every bias, every instruction a possible target. A branch out of a program runs the overlay whose image local store holds at that address, compared whole on every entry; a module copied anywhere else is reported once and ends the program, as before, and the report names the module local store holds there and the base it was copied to (its bytes at the target, looked for in every module's image), so that its bias can go on the recompiler's command line. The .fixup words a loader patches are data, and are not compared.
  • SPURS has a kernel of the runtime's own that does not schedule: every task runs on a host thread of its own from its creation, whatever the number of SPUs the instance was given. The taskset policy module's context and the kernel's are written where a task's library reads them, with the layouts RPCS3 documents. A task waiting for a signal polls its taskset's signalled bit every 50 microseconds, and a task that waits or yields in a taskset that has been shut down ends there, without an exit code, as the system would never resume it; a task's context is never saved, so the save areas and LS patterns are only checked by the task itself. The workload flag syscall is reported and answers 0. An event a task sends goes to the queue attached to that SPU port of its instance; spu_printf (port 1, when no queue is attached) is printed by the runtime. _cellSpursTaskAttributeInitialize's signature, (attr, revision, sdk, elf, saveConfig*, argument*), is read off a call site.
  • SPURS lock-free queues are pushed by the PPU only (PPU2SPU and ANY2ANY), in the CellSyncLFQueue layout that a task's own pop code reads; where an ANY2ANY queue keeps its waiters' counters (in the pop and push wait flags) was read off Edge zlib's inflate task, which RPCS3 does not implement. A PPU that finds a queue full polls it every 50 microseconds rather than waiting on the attached event queue. SPURS queues and barriers answer CELL_OK and do nothing: their layouts are what the tasks' own code reads, and are not read yet.
  • The SPU's events: only the lock-line reservation lost (0x400) is raised, by polling the reserved line every 20 microseconds while the SPU waits.
  • Inline image transfers (NV308A into the NV3062 surface) are taken to be on libgcm's subchannels, 3 and 5; the objects bound to them are not read.
  • Reports: the local ones are in a part of local memory the game is not given (0x0FE00000), the main-memory ones at I/O offset 0x0E000000. A ZPASS_PIXEL_CNT report is always 0x100000 (everything passes); the other kinds write 0.
  • Trophies: the set is the disc's PS3_GAME/TROPDIR/<id>/TROPHY.TRP, its TROP_01.SFM (English, the language cellSysutil reports) or TROP.SFM. Registering reports installed or not installed, then setup, progress (one step per trophy), finalize and complete, on the calling thread. The unlocks are kept as id tick lines in PS3KIT.TROPUSR under /dev_hdd0/home/00000001/trophy/<id>, the runtime's own record; the system's TROPUSR.DAT and TROPTROP.DAT are not made, no icon is installed and no notification is drawn (the runtime logs each unlock). A disc without the package gets an empty set: registration succeeds, and any trophy number unlocks.
  • cellFsGetFreeSize reports the free space cellGameBootCheck does, 40,000,000 KB, whatever the host has.
  • The system cache relays a cache whose directory exists from an earlier run, and clears any other.
  • cellAudioOutGetSoundAvailability answers 2 channels for linear PCM at 48 kHz and 0 for everything else. Audio notifications are an event to each registered queue every 256 samples; their source is the queue's key.
  • cellSysutilGetSystemParamInt answers as a console set to English with cross to confirm, in the SCEE area, with no parental limit.
  • An import with no implementation returns CELL_OK; an lv2 call with none returns CELL_ENOSYS. Both are reported.

About

A game-agnostic toolkit for native PC ports of PS3 games: the executable's structure, Cell PPU and SPU decoders, a static recompiler to C++, and a runtime that replaces the PS3's system software. No game data.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages