Step 10 · Project orientation · C6

The codebase map & the toolbox

Keep this map open during the loading and graphics lessons that follow: where each subsystem lives, how a run flows through it, and which third-party library does which job.

Before this page: What an emulator is. View the learning route.

Read

Read src/ by responsibility: shared host utilities, loading and linking, guest kernel services, HLE libraries, graphics and the launcher. These are not a strict dependency hierarchy; use the actual includes, callbacks and call sites to trace how two subsystems cooperate.

The map of src/

the main responsibilities, one line each
src/main.cpp, emulator.cpp     the entry: parse args, boot, run
src/common/                   everything independent: abi, logging, threads, file,
                              virtual memory, singleton, debug, host exceptions
src/loader/                   ELF/SELF loading, the runtime linker, NIDs, JIT stubs,
                              guest instruction patching and red-zone protection
src/kernel/                   the guest OS surface: memory, address space, threads,
                              event queues, semaphores, filesystem
src/libs/                     the HLE libraries — topic C5's translation table
src/graphics/                 the GPU half: guest formats, Vulkan host, shader recompiler
src/launcher/                 the Qt launcher that finds games, runs the emulator, checks for updates
tests/                        29 portable test executables, plus x86-64 macOS SSE4a — topic C3

Within graphics, four directories separate guest commands, host rendering, shader compilation and presentation:

DirectoryRoleKey files
graphics/guest_gpu/how the guest sees the GPU — formats, the PM4 command processor, registerscommand_processor/, gpu_defs.h, graphicsRun.cpp (the GPU thread, topic C4)
graphics/host_gpu/the host Vulkan renderer — context, pipeline cache, image/buffer caches, memory trackingrenderer/context.cpp, renderer/cache/, renderer/pipeline/, vulkanCommon.h, pageManager.cpp
graphics/shader/RDNA2 → typed IR → SPIR-Vrecompiler/frontend/{decode,cfg,translate}/, recompiler/ir/, recompiler/backend/spirv/, and ShaderRecompiler.cpp (TranslateProgram + CompileProgram)
graphics/presentation/the window, swapchain and the imgui system overlay — the actual frames on screenpresentation/window/, videoOut.cpp, systemOverlay.cpp

The entry points and boot sequence

The main boot responsibilities follow this sequence, as shown in the Lifetime animation. Follow the source for initialization and error paths between these steps:

the boot chain, from argv to the game's main
main.cpp
  └─ ParseArgs()                    --game, the flag table from topic C3
  └─ Run(options)                   emulator.cpp
     └─ Init(...)                   the subsystem sequence from topic C5
     └─ MountSandboxDirs()          /app0, /temp0, ... — topic C5
     └─ LoadElf(eboot.bin)          runtimeLinker: parse SELF/ELF, dynamic tags
     └─ Execute(...)                emulator.cpp — spawns the guest thread
        └─ RuntimeLinker::Execute() load libc if present, resolve relocations, apply patches,
                                    start libc if loaded, call the entry point (topic C2's asm)
     └─ Graphics::WindowRun()       main thread runs the window/event loop

Three files cover most "where does this happen" questions: emulator.cpp (the sequence), loader/runtimeLinker.cpp (the loading/execution), and common/subsystems.h (the lifecycle machinery that runs each step).

The toolbox — third-party libraries

Dependencies in 3rdparty/ come from submodules, configure-time downloads and prebuilt packages; the CMake list in the root CMakeLists.txt is the dependency manifest. The ones you will actually touch:

LibraryWhat it doesWhere it shows up
SDL3window, input, audio host layerWindowRun, controller.cpp, the audio backend
FFmpegaudio & video decodeajm.cpp, avPlayer.cpp, libVideoDec2
Vulkan-Headers + SPIRV-Toolsthe Vulkan API and SPIR-V validation/optimisationthe whole host_gpu layer; spirv-tools-opt in the link list
VulkanMemoryAllocator (VMA)GPU memory allocationimage/buffer allocation in host_gpu; wrapped entirely inside vma.cpp
fmttype-safe printf-style formattingLOGF, EXIT, every string build — topic C3
spdlogthe logging sinks behind common/logging/every log line, routed to console or file by --printf-direction
magic_enumenum → string, string → enum at compile timemagic_enum::enum_name (relocation/crash logs), magic_enum::enum_cast for --shader-optimization-type parsing
xxHashfast, non-cryptographic hashingshader and cache keys
stbimage decoding and PNG encodinglibPngDec / libPngEnc
nlohmann_jsonJSON parsingparam.json, libJson2, ETAHen/GoldHEN-style cheats
Zydis (fetched)x86-64 disassemblerguestInstructionPatcher.cpp decodes guest instructions with it
xbyak (fetched)x86-64 assemblerguestInstructionPatcher.cpp generates patch/trampoline code
Qt 6 (system)the launcher UIsrc/launcher/ — game list, per-game settings, input mapping, trophy viewer, compatibility database, update checker, theme
OpusDualSense Bluetooth audio encodingdualSenseBluetooth.cpp
LibAtrac9the console's ATRAC9 audio codecAJM decode jobs
imguiimmediate-mode UIthe system overlay in presentation/systemOverlay.cpp — the IME keyboard and the error dialogs drawn over the game
tracyframe profiler--profile (topic C3)
winpthreadpthread shim on Windowslinked on clang-cl builds
CTesttest registration and executionkyty_tests builds the test executables; many use their own assertions and main() rather than GoogleTest (topic C3)
cpuinfoCPU feature detectionruntime capability checks

Two of them are the pair you saw in topic C2 and the patcher topics from the course: Zydis reads the guest's x86 instructions, and xbyak writes new ones. The emulator's own JIT in loader/jit.h is hand-assembled bytes; xbyak is the "proper" assembler used where a lot of code has to be generated.

Reading conventions that save time

  • Names map to hardware. pm4.h, gpu_defs.h, RegisterDefaults — if a name looks like a datasheet field, it is one. The codebase keeps console names rather than inventing friendly ones (the path.html appendix covers this in detail).
  • Check linkage and registration separately. Namespace-scope static functions and anonymous namespaces provide internal linkage. An HLE function can still be registered by address through LIB_FUNC; header declarations and namespace membership alone do not tell you whether the guest can call it.
  • EXIT_IF/EXIT = the error channel. Topic C3's macros. A wall of them at the top of a function is a validation contract.
  • Follow a value, not a call graph. Start from a struct (a V#, a Submission, a KernelEvent) and grep for it — the tree is organised around data, and the data names are stable.
Where to start reading

If you want one linear path through the whole tree: main.cpp → emulator.cpp → common/subsystems.h → loader/runtimeLinker.cpp (load one module) → kernel/memory.cpp (allocate one page) → one libs/libPad.cpp function → one draw through commandProcessor. That is roughly the course's own order, and every later page is a deepening of one of those hops.

Learn more · the codebase map
  • Guide
    Reading conventions in this codebaseThe learning path's own appendix — naming, comments, and the habits the maintainers expect.
  • Spec
    KytyPS5 on GitHubThe source this whole site is a reading of. The README's "Important areas" list is the maintainers' own map.
  • Reference
    CMake tutorialIf the CMakeLists.txt is opaque, this is the shortest path to reading the dependency manifest as a manifest.
Watch

The boot sequence the map describes, end to end — three threads, three jobs, and where every subsystem in src/ sits in the flow.

Try

Grep is the map's search box. Prove you can navigate it in ten minutes.

A ten-minute lab

Pick a noun from this page — Submission, KernelEvent, ShaderInfo, PageFaultAccess — and rg it across src/. Read the first struct definition you find, then jump to the two or three places it is consumed. That "follow the value" loop is how every page in this course was researched.

Do

These checkpoints are the map committed to memory.

Checkpoint