# SharpEmu Gen4 vs Gen5 Handling: Differences Between PS4 and PS5 Emulation

> Explore SharpEmu Gen4 vs Gen5 handling differences. Learn how SharpEmu differentiates PS4 and PS5 emulation via its Generation enum and runtime filtering for improved compatibility.

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

---

**SharpEmu distinguishes PlayStation 4 and PlayStation 5 emulation through a `[Flags]` enum called `Generation`, attaching platform targets to every high-level emulation (HLE) function and filtering exports at runtime based on the guest ELF header.**

The `par274/sharpemu` repository implements a clean architectural separation between console generations using bitwise flags. This design allows the emulator to support both legacy PS4 (Gen4) and modern PS5 (Gen5, also referred to as GenS or PSS) software within a single codebase while maintaining accurate system-call semantics for each platform.

## The Generation Flag Architecture

### Defining Console Generations

At the core of SharpEmu’s platform abstraction lies the `Generation` enum defined in [`SharpEmu.HLE/Generation.cs`](https://github.com/par274/sharpemu/blob/main/SharpEmu.HLE/Generation.cs). This enumeration uses the `[Flags]` attribute to support bitwise combination:

```csharp
[Flags]
public enum Generation
{
    Gen4 = 1 << 0,  // PlayStation 4 family
    Gen5 = 1 << 1,  // PlayStation 5 family (GenS/PSS)
}

```

Only two values exist: `Generation.Gen4` representing the PS4 family, and `Generation.Gen5` representing the PS5 family.

### Multi-Target Support with Bitwise Flags

Because the enum is marked with `[Flags]`, a single export can target one or both generations by combining values with a bitwise OR operation:

```csharp
Generation.Gen4 | Generation.Gen5

```

This flexibility allows developers to mark universal functions that work across both consoles while reserving specific implementations for generation-exclusive features.

## Export Registration and Runtime Filtering

### SysAbiExportAttribute Target Property

Each HLE function in SharpEmu is decorated with `SysAbiExportAttribute`, which contains a `Target` property of type `Generation`. This property determines which console generation(s) can access the function:

```csharp
// Example of a sys-abi export that works on both generations
[SysAbiExport(
    Nid = "Zxa0VhQVTsk",
    ExportName = "sceKernelWaitSema",
    Target = Generation.Gen4 | Generation.Gen5,
    LibraryName = "libKernel")]
public static int KernelWaitSema(int semaId, int timeout) { /* ... */ }

```

### Registry Filtering in SysAbiExportRegistry

During startup, the `SysAbiExportRegistry` (generated from the source analysis) builds a dictionary of exports filtered by the current generation. Only exports whose `Target` flag matches the running generation are made available to the guest OS. This filtering is verified by test suites in [`SysAbiExportGeneratorTests.cs`](https://github.com/par274/sharpemu/blob/main/SysAbiExportGeneratorTests.cs) and [`SysAbiRegistryTests.cs`](https://github.com/par274/sharpemu/blob/main/SysAbiRegistryTests.cs).

```csharp
// Runtime selection (simplified)
var gen = guestImage.DetectGeneration();          // → Generation.Gen4 or Generation.Gen5
var exports = SysAbiExportRegistry.CreateExports(gen);
host.RegisterExports(exports);

```

## Platform-Specific Implementation Differences

### Shared vs. Divergent Code Paths

Inside library source files such as [`VideoOutExports.cs`](https://github.com/par274/sharpemu/blob/main/VideoOutExports.cs), [`UserServiceExports.cs`](https://github.com/par274/sharpemu/blob/main/UserServiceExports.cs), and [`RtcExports.cs`](https://github.com/par274/sharpemu/blob/main/RtcExports.cs), method bodies are often reused for both generations. However, some functions contain conditional logic that checks the `Generation` flag to handle differences in system-call signatures, data structures, or behavior that changed between PS4 and PS5.

### Generation-Exclusive Features

When a function applies only to one generation, its `Target` is set to that single flag. For example, PS5-only features like new audio pipelines use `Generation.Gen5` exclusively:

```csharp
// PS5-only export (GenS / PSS)
[SysAbiExport(
    Nid = "abc123...",
    ExportName = "sceAudioOutOpenExt",
    Target = Generation.Gen5,
    LibraryName = "libAudioOut")]
public static int AudioOutOpenExt(/* ... */) { /* ... */ }

```

Conversely, legacy PS4 behavior remains isolated in classes guarded by `Gen4` checks within the `SharpEmu.HLE.Host.*` namespace.

## Runtime Generation Detection

### ELF Header Analysis

When the emulator launches a guest image, it determines the target generation from the ELF header using [`SharpEmu.Core.Loader.ElfHeader.cs`](https://github.com/par274/sharpemu/blob/main/SharpEmu.Core.Loader.ElfHeader.cs). This detected value is stored in the emulated CPU context and supplied to the HLE layer.

### CPU Context and HLE Layer Integration

The CPU context propagates the generation information to the HLE layer, which then selects the appropriate export set. If a guest requests a function not present for its generation, the emulator returns the standard `SCE_ERROR_NOT_FOUND` error, maintaining correct error semantics for each platform.

## Testing Generation Isolation

The test suite verifies both generations separately to ensure no cross-contamination of exports. For example, [`SysAbiExportGeneratorTests.cs`](https://github.com/par274/sharpemu/blob/main/SysAbiExportGeneratorTests.cs) creates exports with `Target = Generation.Gen4 | Generation.Gen5` and asserts that the registry correctly filters them when called with `Generation.Gen4` versus `Generation.Gen5`. This ensures that PS4 games cannot access PS5-specific syscalls and vice versa.

## Summary

- **SharpEmu** uses the `Generation` flag enum (`Gen4` for PS4, `Gen5` for PS5) to separate platform-specific code paths.
- **SysAbiExportAttribute** attaches a `Target` property to every HLE function, determining which generation(s) can access it.
- **SysAbiExportRegistry** filters exports at runtime based on the detected generation, ensuring only compatible functions are exposed.
- **ElfHeader.cs** analyzes the guest binary to determine the target generation from the ELF header.
- **Generation-exclusive features** (like `sceAudioOutOpenExt`) target only `Gen5`, while shared functions use `Generation.Gen4 | Generation.Gen5`.
- Missing functions for a specific generation return `SCE_ERROR_NOT_FOUND` to maintain accurate emulation semantics.

## Frequently Asked Questions

### How does SharpEmu determine whether to use Gen4 or Gen5 mode?

SharpEmu detects the target generation by analyzing the guest binary's ELF header through [`SharpEmu.Core.Loader.ElfHeader.cs`](https://github.com/par274/sharpemu/blob/main/SharpEmu.Core.Loader.ElfHeader.cs). This value is stored in the emulated CPU context and supplied to the HLE layer, which then filters the available exports accordingly.

### Can a single HLE function target both PS4 and PS5?

Yes. Developers can mark functions with `Target = Generation.Gen4 | Generation.Gen5` using the bitwise OR operator. This is common for stable system calls like `sceKernelWaitSema` that maintain compatible signatures across both console generations.

### What happens when a PS4 game calls a PS5-exclusive function?

If a guest requests a function not present for its detected generation, the emulator returns `SCE_ERROR_NOT_FOUND`. This mirrors the behavior of actual hardware, where incompatible system calls are not implemented for that platform.

### Where is the Generation enum defined in the SharpEmu source?

The `Generation` enum is defined in [`/SharpEmu.HLE/Generation.cs`](https://github.com/par274/sharpemu/blob/main//SharpEmu.HLE/Generation.cs) as a `[Flags]` enumeration with two values: `Gen4` (1 << 0) for PlayStation 4 and `Gen5` (1 << 1) for PlayStation 5 (also referred to as GenS or PSS).