# AGC Initialization Process in SharpEmu: PS5 Graphics Core Startup Sequence

> Explore the AGC initialization process in SharpEmu. Discover how sceAgcInit validates state pointers and populates register groups for shader creation and command buffer generation.

- Repository: [Berk/sharpemu](https://github.com/par274/sharpemu)
- Tags: internals
- Published: 2026-07-13

---

**SharpEmu initializes its Advanced Graphics Core by calling `sceAgcInit`, which validates the state pointer and register defaults version before populating the AGC state with predefined register groups to enable shader creation and command buffer generation.**

The AGC initialization process in SharpEmu faithfully reproduces the PlayStation 5 kernel's graphics startup behavior to support accurate PS5 emulation. This process centers on the `AgcExports` class in `SharpEmu.Libs.Agc`, which exposes the core ABI functions that emulated games call to initialize the graphics pipeline. Understanding this initialization sequence is critical for developers debugging GPU emulation issues or implementing custom graphics tools.

## The AGC Initialization Sequence

The SharpEmu AGC initialization follows a strict sequence that mirrors the real PS5 kernel. The process begins with the `sceAgcInit` export and continues through register defaults loading before the system is ready for shader operations.

### Step 1: Receiving the Init Request via `sceAgcInit`

The initialization starts when the emulator receives a call to **`sceAgcInit`** (NID `23LRUSvYu1M`). Located in [`src/SharpEmu.Libs/Agc/AgcExports.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.Libs/Agc/AgcExports.cs) at lines 404-410, this exported function receives two arguments in CPU registers: `RDI` containing the **state address** and `RSI` containing the **register-defaults version**.

### Step 2: Validating State Address and Version

Before proceeding, the `Init` method performs strict parameter validation at lines 411-415. The function checks that the `stateAddress` is non-zero and that the `version` parameter is supported by calling `IsSupportedRegisterDefaultsVersion(version)`. If either check fails, the function immediately returns `ORBIS_GEN2_ERROR_INVALID_ARGUMENT`, preventing uninitialized memory access or version mismatches.

### Step 3: Diagnostic Logging

When tracing is enabled via the `SHARPEMU_LOG_AGC=1` environment variable, the initialization process logs diagnostic information at line 418. The `TraceAgc` call outputs the state address and version number, printing a line formatted as `agc.init state=0x… version=…` to aid developers in debugging graphics pipeline startup issues.

### Step 4: Loading Register Defaults

After successful validation, the emulator must populate the AGC state with known register values. SharpEmu provides two exported helpers for this purpose: **`sceAgcGetRegisterDefaults2`** and **`sceAgcGetRegisterDefaults2Internal`**.

These functions, defined at lines 424-428 in [`AgcExports.cs`](https://github.com/par274/sharpemu/blob/main/AgcExports.cs), act as thin wrappers around `ReturnRegisterDefaults`. They copy the predefined **`PrimaryRegisterDefaults`** and **`InternalRegisterDefaults`** tables into guest memory, initializing the CX, UC, and SH register groups required for GPU command generation.

### Step 5: Creating Shader Objects

Once the AGC state is initialized and register defaults are loaded, the system proceeds to create graphics objects. The **`sceAgcCreateShader`** function validates shader headers, relocates internal pointers, and stores header-to-code mappings. Subsequent calls to **`sceAgcCreatePrimState`** and **`sceAgcCreateInterpolantMapping`** populate CX/UC/SH registers based on shader metadata, all assuming the AGC state established by the initialization process.

## Key Implementation Details in [`AgcExports.cs`](https://github.com/par274/sharpemu/blob/main/AgcExports.cs)

The AGC initialization logic resides primarily in **[`src/SharpEmu.Libs/Agc/AgcExports.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.Libs/Agc/AgcExports.cs)**, which implements all exported AGC ABI functions including `sceAgcInit`, `sceAgcGetRegisterDefaults2`, and the shader creation methods.

The exported functions use the **`SysAbiExportAttribute`** from `SharpEmu.HLE` to expose C# methods as kernel exports. The runtime registration occurs in `SharpEmu.Core.Runtime.SharpEmuRuntime`, which registers the `libSceAgc` library and makes these functions reachable by the emulated process.

The validation logic uses `IsSupportedRegisterDefaultsVersion` to ensure compatibility with the emulator's supported register default tables, preventing crashes from unrecognized GPU configurations.

## Code Examples: Initializing the AGC in SharpEmu

Below are practical implementations showing how to invoke the AGC initialization sequence from within SharpEmu or test harnesses using `CpuContext`.

### Basic AGC Initialization

```csharp
// Prepare a CpuContext (context creation is handled in SharpEmu.Core)
var ctx = new CpuContext();

// Allocate guest memory for the AGC state
ulong agcStateAddr = guestMemory.Allocate(0x2000);

// Pass state address in RDI and supported version in RSI
ctx[CpuRegister.Rdi] = agcStateAddr;
ctx[CpuRegister.Rsi] = 7;  // Supported version from PrimaryRegisterDefaults

// Call the exported init function
int result = AgcExports.Init(ctx);

// result == ORBIS_GEN2_OK (0) indicates successful initialization

```

### Loading Primary Register Defaults

```csharp
// Use the same state block from initialization
ctx[CpuRegister.Rdi] = agcStateAddr;
int ret = AgcExports.GetRegisterDefaults2(ctx);

// ret == ORBIS_GEN2_OK indicates the state now contains default CX/SH/UC registers

```

### Loading Internal Register Defaults

```csharp
// Populate secondary default group for internal GPU pipelines
int ret2 = AgcExports.GetRegisterDefaults2Internal(ctx);

```

### Creating a Shader After Initialization

```csharp
// Prepare shader creation (requires initialized AGC state)
ctx[CpuRegister.Rdi] = shaderDestPtr;   // Destination for header pointer
ctx[CpuRegister.Rsi] = headerAddr;      // Shader header location
ctx[CpuRegister.Rdx] = codeAddr;        // Shader code location

int shaderRet = AgcExports.CreateShader(ctx);

```

These examples follow the exact sequence the PS5 kernel expects: **init → defaults → shader creation → command-buffer construction**.

## Summary

- The **AGC initialization process** begins with `sceAgcInit` in [`src/SharpEmu.Libs/Agc/AgcExports.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.Libs/Agc/AgcExports.cs), which validates the state pointer and register defaults version.
- SharpEmu checks for non-zero state addresses and supported versions using `IsSupportedRegisterDefaultsVersion`, returning `ORBIS_GEN2_ERROR_INVALID_ARGUMENT` on failure.
- Diagnostic logging via `TraceAgc` aids debugging when `SHARPEMU_LOG_AGC=1` is enabled.
- **Register defaults** are loaded via `sceAgcGetRegisterDefaults2` and `sceAgcGetRegisterDefaults2Internal`, populating `PrimaryRegisterDefaults` and `InternalRegisterDefaults` into guest memory.
- Subsequent graphics operations like `sceAgcCreateShader` depend on the AGC state established during this initialization sequence.

## Frequently Asked Questions

### What is the AGC in SharpEmu?

The **Advanced Graphics Core (AGC)** in SharpEmu is the emulator's implementation of the PS5 graphics pipeline. It provides compatible ABI exports that mimic the real PlayStation 5 kernel, allowing emulated games to initialize graphics hardware, create shaders, and build GPU command buffers. The AGC initialization process sets up the internal state required for these operations.

### Why does `sceAgcInit` validate the register defaults version?

The **register defaults version** validation ensures compatibility between the emulated game and the emulator's predefined register tables (`PrimaryRegisterDefaults` and `InternalRegisterDefaults`). By checking `IsSupportedRegisterDefaultsVersion(version)` at lines 411-415 in [`AgcExports.cs`](https://github.com/par274/sharpemu/blob/main/AgcExports.cs), SharpEmu prevents initialization with unknown GPU configurations that could cause undefined behavior or crashes during shader execution.

### What happens after AGC initialization completes?

After `sceAgcInit` returns `ORBIS_GEN2_OK`, the AGC state is ready for graphics operations. The typical workflow continues with loading register defaults via `sceAgcGetRegisterDefaults2`, then creating shader objects using `sceAgcCreateShader`, followed by setting up primitive states and interpolant mappings. Finally, the system generates GPU command packets using functions like `sceAgcCbDispatch` and `sceAgcDcbSetShRegistersIndirect`.

### Where does the AGC initialization code reside in the repository?

The core AGC initialization logic resides in **[`src/SharpEmu.Libs/Agc/AgcExports.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.Libs/Agc/AgcExports.cs)**, specifically the `Init` method at lines 404-420. Related functionality for runtime registration is found in [`src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs), while the export mechanism uses attributes from [`src/SharpEmu.HLE/SysAbiExportAttribute.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.HLE/SysAbiExportAttribute.cs).