# How SharpEmu Implements Kernel Function Stubs for PlayStation 5 Emulation

> Learn how SharpEmu implements kernel function stubs for PS5 emulation. Discover the SetZeroReturn method for safe execution of unimplemented calls.

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

---

**SharpEmu implements kernel function stubs by returning `0` (success) through a centralized `SetZeroReturn` method in [`KernelExports.cs`](https://github.com/par274/sharpemu/blob/main/KernelExports.cs), allowing unimplemented PlayStation 5 kernel calls to execute safely without crashing the guest code.**

SharpEmu is an open-source PlayStation 5 emulator that uses High-Level Emulation (HLE) to bridge the gap between the guest kernel API and the host system. When encountering unimplemented kernel functions, the emulator relies on **kernel function stubs** to maintain ABI compatibility while preventing crashes. These stubs are defined in [`src/SharpEmu.Libs/Kernel/KernelExports.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.Libs/Kernel/KernelExports.cs) and provide a safe fallback for unknown NIDs (Named Identifiers).

## The Centralized Stub Mechanism

At the core of SharpEmu’s kernel emulation lies a simple but effective pattern for handling unimplemented functions. Rather than leaving undefined behavior or throwing exceptions, the emulator returns success codes to keep the guest process running.

### The SetZeroReturn Method

In [`src/SharpEmu.Libs/Kernel/KernelExports.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.Libs/Kernel/KernelExports.cs), the private method `SetZeroReturn` serves as the universal handler for stubbed kernel functions. This method writes `0` into the `RAX` register (the x86-64 return value register) and returns `0` as the C-style function result:

```csharp
private static int SetZeroReturn(CpuContext ctx)
{
    ctx[CpuRegister.Rax] = 0;   // Return value = success
    return 0;                   // C‑style int return
}

```

By zeroing out `RAX`, the stub mimics a successful kernel call according to the PlayStation 5 ABI contract, allowing the guest binary to continue execution without detecting an error condition.

## Marking Exports with SysAbiExport

Kernel functions in SharpEmu are exposed to the HLE system through the `[SysAbiExport]` attribute, defined in [`src/SharpEmu.HLE/SysAbiExportAttribute.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.HLE/SysAbiExportAttribute.cs). This attribute maps C# methods to specific PlayStation 5 kernel symbols by NID (Named Identifier) and export name.

Each stubbed function follows a consistent pattern:
- It receives a `CpuContext` parameter containing the emulated CPU state
- It invokes `SetZeroReturn` to satisfy the return contract
- It targets specific generations (Gen4 or Gen5) via the `Target` property

For example, the stub for an unknown kernel symbol appears as a simple one-liner forwarding the context:

```csharp
[SysAbiExport(
    Nid = "9T2pDF2Ryqg",
    ExportName = "sceKernelUnknown9T2p",
    Target = Generation.Gen4 | Generation.Gen5,
    LibraryName = "libKernel")]
public static int KernelUnknown9T2p(CpuContext ctx) => SetZeroReturn(ctx);

```

## Handling Unknown NIDs

When the runtime encounters kernel NIDs that lack full implementations, SharpEmu consults [`scripts/ps5_names.txt`](https://github.com/par274/sharpemu/blob/main/scripts/ps5_names.txt). This file collects observed NIDs from the wild, and any unknown entries are routed to stub methods in [`KernelExports.cs`](https://github.com/par274/sharpemu/blob/main/KernelExports.cs) that call `SetZeroReturn`.

This approach provides three key benefits:
- **Safety:** Returning `0` prevents the guest process from crashing when calling unimplemented kernel functions
- **Discoverability:** New NIDs are logged and tracked in [`ps5_names.txt`](https://github.com/par274/sharpemu/blob/main/ps5_names.txt) until developers add proper implementations
- **Performance:** Simple stubs avoid the overhead of full kernel emulation while maintaining ABI compliance

## Functional Implementations vs. Stubs

While many kernel functions are stubbed with zero returns, some require minimal functional logic. The implementation of `sceKernelGetCompiledSdkVersion` demonstrates how functional exports coexist with the stub pattern.

Located in the same [`KernelExports.cs`](https://github.com/par274/sharpemu/blob/main/KernelExports.cs) file, this method uses `CpuContext` helpers to read the version pointer from `RDI`, validate the address, and write the appropriate SDK version for the target generation:

```csharp
[SysAbiExport(
    Nid = "WB66evu8bsU",
    ExportName = "sceKernelGetCompiledSdkVersion",
    Target = Generation.Gen4 | Generation.Gen5,
    LibraryName = "libKernel")]
public static int KernelGetCompiledSdkVersion(CpuContext ctx)
{
    var versionAddress = ctx[CpuRegister.Rdi];
    if (versionAddress == 0)
        return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;

    var sdkVersion = ctx.TargetGeneration == Generation.Gen5
        ? Gen5CompiledSdkVersion
        : Gen4CompiledSdkVersion;

    if (!ctx.TryWriteUInt32(versionAddress, sdkVersion))
        return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;

    ctx[CpuRegister.Rax] = 0;
    return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}

```

Unlike the simple stubs, this method performs actual work: validating arguments, selecting the correct version based on generation, and handling memory writes. However, it still concludes by setting `RAX` to `0` to indicate success, maintaining consistency with the kernel ABI.

## Runtime Registration and Integration

The kernel exports are registered with the emulator through [`src/SharpEmu.HLE/ModuleManager.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.HLE/ModuleManager.cs), which scans for `[SysAbiExport]` attributes and builds the mapping between NIDs and C# methods. During initialization, [`src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs) loads the appropriate kernel exports for the target generation (PlayStation 4 or PlayStation 5 compatibility).

This architecture ensures that:
- Fully implemented kernel functions provide realistic behavior
- Unknown or unimplemented calls fall back to safe stubs
- The emulator can incrementally add proper kernel support without breaking existing functionality

## Summary

- **Kernel function stubs** in SharpEmu are implemented via the `SetZeroReturn` method in [`src/SharpEmu.Libs/Kernel/KernelExports.cs`](https://github.com/par274/sharpemu/blob/main/src/SharpEmu.Libs/Kernel/KernelExports.cs), which writes `0` to the `RAX` register to simulate successful kernel calls.
- The `[SysAbiExport]` attribute registers C# methods as PlayStation 5 kernel exports, mapping them to specific NIDs and library names.

- Unknown NIDs are tracked in [`scripts/ps5_names.txt`](https://github.com/par274/sharpemu/blob/main/scripts/ps5_names.txt) and routed to stub methods that prevent crashes while maintaining ABI compatibility.
- Functional implementations like `sceKernelGetCompiledSdkVersion` demonstrate how real kernel logic integrates with the stub architecture, using `CpuContext` for register access and memory operations.
- The HLE system registers all exports through [`ModuleManager.cs`](https://github.com/par274/sharpemu/blob/main/ModuleManager.cs) and initializes them via [`SharpEmuRuntime.cs`](https://github.com/par274/sharpemu/blob/main/SharpEmuRuntime.cs) based on the target generation.

## Frequently Asked Questions

### What is the purpose of kernel function stubs in SharpEmu?

Kernel function stubs allow the emulator to handle unimplemented PlayStation 5 kernel calls gracefully. By returning `0` (success) through the `SetZeroReturn` method, SharpEmu prevents the guest code from crashing while maintaining the expected ABI contract, giving developers time to implement full kernel functionality later.

### How does SetZeroReturn maintain ABI compatibility?

The `SetZeroReturn` method maintains ABI compatibility by writing `0` into the `RAX` register and returning `0` as the function result. According to the x86-64 System V ABI used by the PlayStation 5, `RAX` holds the return value of functions, so zeroing it signals success to the caller, satisfying the contract without requiring actual kernel logic.

### Where are unknown kernel NIDs documented in SharpEmu?

Unknown kernel NIDs are collected in [`scripts/ps5_names.txt`](https://github.com/par274/sharpemu/blob/main/scripts/ps5_names.txt). When the runtime encounters an NID that lacks a full implementation, it routes the call to a stub method in [`KernelExports.cs`](https://github.com/par274/sharpemu/blob/main/KernelExports.cs). This file serves as a living document of observed kernel symbols that need proper implementation.

### How do functional kernel exports differ from simple stubs?

Functional kernel exports like `sceKernelGetCompiledSdkVersion` perform actual logic using `CpuContext` helpers to read registers, validate pointers, and write memory, while simple stubs immediately return `0` through `SetZeroReturn`. Both types conclude by setting `RAX` to `0`, but functional implementations handle the specific kernel behavior before returning.