v1.70.4 is out now - crash recovery added - fixed a memory allocator bug that crashed GTA: Liberty City Stories - config self-heal - CWCheat + PSPAR in one plugin - works on CFW only, not OFW - full changelog inside
The Big Picture

TempAR is a single PSP kernel-mode PRX module. There is no multi-process architecture, no IPC, no separate "backend" — it's one .prx file loaded into the address space of whatever game/homebrew is running, via the PSP's plugin system (seplugins). Everything described on this page happens inside that one module.

module_start()                       [src/objects/main.c]
   |  records the plugin's own boot path, snapshots the current thread list
   +- spawns "TempAR_thread" -> main_thread()
                                         |
                                         |  one-time init (in order):
                                         |   config_load()      - settings from config.bin
                                         |   gameid_get()       - identify the running game
                                         |   cheat_init()       - allocate cheat/block pools
                                         |   cheat_load()       - load cheats for this game id
                                         |   language_init/load - UI strings
                                         |   psid_init()        - (optional) PSID corruption
                                         |   screenshot_init()  - (optional)
                                         |   search_init()      - resume any in-progress search
                                         |   menu_init()        - zero UI state
                                         |   sceCtrlRegisterButtonCallback(button_callback)
                                         |
                                         +- while(running):
                                               if menu.visible      -> menu_show()   (blocking UI)
                                               else if cheat_hz set -> cheat_apply(0) (apply cheats)
                                               screenshot handling
                                               sceKernelDelayThread(cheat_hz or 15ms)

module_stop() tears this down: flips running = 0, waits (with a timeout + forced terminate) for the thread to exit, then frees cheat/language/text-viewer memory and disconnects USB.

This is the entire lifecycle. There's no event loop framework, no scheduler beyond the PSP's own kernel threads, and no persistent background service beyond this one thread.

Module Map
ModuleFilesResponsibility
Entry pointmain.c / main.hmodule_start/module_stop, the main thread loop, global hotkey dispatch (button_callback), game-thread pause/resume
Cheat enginecheat.c / cheat.hCheat/Block data model, loading cheats from .db/.bin/.txt/NitePR files, saving, and executing CWCheat/PSPAR code types against memory every loop tick
Menu / UImenu.c / menu.hAll on-screen menus: cheat list, searcher, options, browser/decoder, credits. Owns the tab state machine
Inputctrl.c / ctrl.hController polling, CROSS/CIRCLE swap, analog→dpad synthesis, key-repeat, blocking wait helpers
Configconfig.c / config.hLoads/saves config.bin (raw packed struct + checksum) and colors/colorN.txt skin files
Searchsearch.c / search.hMemory search ("cheat finder") — exact/unknown search across 8/16/32-bit values, backed by files so searches persist across sessions
Disassemblerdisasm.c / disasm.hMIPS instruction decoder, vendored from PSPLINK — feeds the in-menu "Decoder" screen
File browserfilebrowser.cLists/navigates memory stick directories for loading text/patch/cheat files
File bufferingfilebuffer.cBuffered file I/O helpers used everywhere instead of raw sceIo* calls
On-screen keyboardpspdebugkb.cVendored PSPSDK utility for text entry without the system OSK
Text/guide viewertext.cPages through an arbitrary text file for the in-menu game guide viewer
Languagelanguage.cLoads a binary string table so the UI can be shown in multiple languages
PSIDpsid.cDeliberately corrupts the PSP's PSID for network anti-cheat evasion
Screenshotscreenshot.cCaptures the framebuffer to a file on a hotkey
USBusb.cToggles USB mass-storage mode so a PC can read the memory stick without rebooting
kmallockmalloc.cKernel partition-memory allocator wrapper
syslibcsyslibc.cMinimal libc-shaped shims the kernel-mode libc doesn't provide
floatfloat.cFloat/fixed-point helpers used by a couple of PSPAR-extended code types
utilsutils.cGame ID resolution, misc string/memory helpers
loglog.cDebug logging to a file, compiled out unless _DEBUG_ is set
SDK shimsdk.cSmall exported API surface for third-party PRX plugins

common.h is the "include everything" header — nearly every .c file includes only common.h plus whatever PSPSDK headers it needs directly.

Two Binaries, One Source Tree

The build produces two PRX files from the same source files, differentiated entirely by preprocessor defines set in the makefile:

  • tempar.prx — full build: CWCheat + PSPAR + USB + PSID + screenshots + guide viewer + UMD dump + module list + thread list + disassembler + auto-off + multi-language.
  • tempar_lite.prx — drops USB, PSID, UMD dump, module list, thread list (smaller memory footprint); used for POPS (PS1-on-PSP) and other memory-constrained game modes.

Because both binaries share every .c file, most feature code is wrapped in #ifdef _FEATURE_ guards rather than living in separate files. See the Build System page for the full flag reference.

Data Flow: Cheat File to Game Memory
  1. Load. cheat_load() is called once at boot with the resolved game ID. It tries, in order: the plugin's own cheat.db (indexed multi-game database), then per-game .txt CWCheat/PSPAR files, then a PSPAR .bin file, then a NitePR .txt file (converted to PSPAR format on load).
  2. Toggle. The user opens the menu, navigates the Cheater tab, and presses CROSS/SQUARE to flip CHEAT_SELECTED/CHEAT_CONSTANT bits on a cheat's flags. This does not touch memory yet.
  3. Apply. Every iteration of the main loop, cheat_apply(0) walks the whole cheat list and, for every enabled cheat, dispatches to cheat_apply_cwcheat(), cheat_apply_pspar(), or cheat_apply_psx_gs() depending on the cheat's engine flag.
  4. Persist. cheat_save() writes the current in-memory cheat list back out to cheats/{game-id}.db so new cheats, edits, and favorite/order changes survive a reboot.
Why So Much Global State

This is homebrew for a single-core, no-MMU-protection, cooperative-ish embedded target with 32-64MB of RAM. There is exactly one "session" (one game running, one plugin instance), so there was never a reason to avoid module-level globals (cheats, blocks, cfg, menu, search, game_id, etc.) — they are the application state, shared via extern across files. If you're coming from application/server development, expect this pattern everywhere rather than passed-around context objects. See the Gotchas page for the specific ways this bites contributors.