Skip to content

Feat: GS, VIF1, VU1 pathways + font rendering stubs + mpeg stubs#80

Merged
ran-j merged 3 commits intoran-j:mainfrom
aslanhudajev:feat/gs-v1f-vu1-impl
Feb 24, 2026
Merged

Feat: GS, VIF1, VU1 pathways + font rendering stubs + mpeg stubs#80
ran-j merged 3 commits intoran-j:mainfrom
aslanhudajev:feat/gs-v1f-vu1-impl

Conversation

@aslanhudajev
Copy link
Contributor

PS2 Recomp Playground — Pull Request Description

Overview

Adds three GS pathways.
Adds font loading and rendering stubs.
Adds mpeg stubs.


Architecture Diagram

flowchart TB
    subgraph EE["Emotion Engine (EE)"]
        direction TB
        RDRAM["RDRAM (32MB)"]
        EE_CPU["EE CPU (R5900)"]
        Runner["Recompiled Functions"]
        Stubs["ps2_stubs"]
        Syscalls["ps2_syscalls"]
        EE_CPU --> Runner
        EE_CPU --> Stubs
        EE_CPU --> Syscalls
        Runner --> RDRAM
        Stubs --> RDRAM
    end

    subgraph DMA["DMA Controller"]
        DMA_CH0["DMA Ch0"]
        DMA_CH1["DMA Ch1 (VIF1)"]
        DMA_CH2["DMA Ch2 (GIF)"]
    end

    subgraph VIF1["VIF1 (Vector Interface)"]
        VIF1_Regs["VIF1 Registers"]
        VIF1_Interp["VIF1 Interpreter"]
        VIF1_Interp --> |"MPG: load VU1 microcode"| VU1_Code
        VIF1_Interp --> |"UNPACK: load VU1 data"| VU1_Data
        VIF1_Interp --> |"DIRECT: Path 2"| GIF_Arbiter
        VIF1_Interp --> |"MSCAL: trigger VU1"| VU1_Exec
    end

    subgraph VU1["VU1 (Vector Unit 1)"]
        VU1_Code["VU1 Micro Memory (16KB)"]
        VU1_Data["VU1 Data Memory (16KB)"]
        VU1_Exec["VU1 Interpreter"]
        VU1_Exec --> |"XGKICK: Path 1"| GIF_Arbiter
    end

    subgraph GS["Graphics Synthesizer (GS)"]
        GIF_Arbiter["GIF Arbiter"]
        GS_GPU["GS GPU"]
        GS_VRAM["GS VRAM (4MB)"]
        GS_Raster["GS Rasterizer"]
        GIF_Arbiter --> GS_GPU
        GS_GPU --> GS_Raster
        GS_Raster --> GS_VRAM
    end

    subgraph Host["Host"]
        Raylib["Raylib Window"]
        GS_VRAM --> |"Display snapshot"| Raylib
    end

    RDRAM --> |"sceDmaSend / sceDmaSendN"| DMA_CH2
    RDRAM --> |"sceDmaSend (VIF1)"| DMA_CH1
    DMA_CH2 --> |"Path 3"| GIF_Arbiter
    DMA_CH1 --> VIF1_Interp
    VIF1_Regs --> VIF1_Interp
Loading

EE–GS–VIF1–VU1 Pathways

The GIF (Graphics Interface) sends textures and geometry to the GS. It receives data from three different PATHs. Only one PATH may run at a time; when one PATH stops, the highest-priority queued PATH begins transfer.

PATH Source Priority
PATH1 VU1 via XGKICK instruction Highest
PATH2 VIF1 via DIRECT/DIRECTHL Medium
PATH3 GIF DMAC channel (channel 2) Lowest

Path 1: VU1 Memory → GIF (VU1-Assisted Rendering)

Source: VU1 internal VU Memory (XGKICK)

Path: EE → DMA channel 0x10009000 (VIF1) → VIF1 Interpreter → VU1 Data / VU1 Code → VU1 Interpreter → XGKICK → GIF Path 1 → GS

  • Trigger: sceDmaSend to VIF1 channel (0x10009000)

  • Flow:

    1. Game DMAs data to VIF1; processPendingTransfers() enqueues to m_pendingVif1Transfers
    2. processVIF1Data() interprets VIF commands:
      • MPG: Load microcode into VU1 micro memory
      • UNPACK: Load vectors into VU1 data memory
      • DIRECT / DIRECTHL: Pass data through to GIF as Path 2
      • MSCAL / MSCALF: Trigger VU1 execution at given PC
    3. VU1 runs microcode; when it hits XGKICK, it sends a GIF packet from VU1 data memory to Path 1
    4. GIF Arbiter drains; Path 1 has highest priority
  • Use case: 3D geometry, transforms, and complex rendering pipelines

Path 2: VIF1 Interface → GIF

Source: VIF1 interface (pass-through)

Path: EE → VIF1 → VIF_DIRECT / VIF_DIRECTHL → GIF Path 2 → GS

  • Flow: VIF1 receives data; VIF_DIRECT / VIF_DIRECTHL submit the following QWs to the GIF Arbiter as Path 2
  • Use case: EE-generated data that goes through VIF1 but bypasses VU1 processing

Path 3: GIF DMAC Channel → GIF

Source: GIF DMAC channel (channel 2, 0x1000A000)

Path: EE → DMA channel 2 (0x1000A000) → GIF Arbiter → GS

  • Trigger: sceDmaSend, sceDmaSendN, sceDmaSendI, sceDmaSendM (stubs)

  • Flow:

    1. Game writes to DMA CHCR register: MADR (source address), QWC (quadword count)
    2. Stub writes to I/O registers and calls processPendingTransfers()
    3. PS2Memory::processPendingTransfers() reads from RDRAM at MADR, submits to GifArbiter as Path 3
    4. GifArbiter sorts by path priority (Path1 < Path2 < Path3) and drains
    5. GS::processGIFPacket() parses GIF tags (PACKED, REGLIST, IMAGE) and updates GS state / rasterizes
  • Use case: EE builds GIF packets in RDRAM and sends them directly to the GS (e.g. 2D UI, fonts, simple draws)

GIF Path Arbitration

Only one PATH may run at a time. Under normal conditions, when one PATH stops, the highest-priority queued PATH begins transfer. The arbiter drains in priority order: PATH1 (VU1 XGKICK) → PATH2 (VIF1 DIRECT) → PATH3 (GIF DMAC channel 2).


File-by-File Description

File Role
ps2_gif_arbiter.cpp GIF arbiter: queues packets by path ID, sorts by path priority, drains to GS::processGIFPacket.
ps2_gs_gpu.cpp GS GPU: parses GIF packets (PACKED, REGLIST, IMAGE), updates GS state, rasterizes primitives. Writes to GS VRAM.
ps2_gs_rasterizer.cpp Rasterizer: draws triangles, sprites, lines, etc. into VRAM.
ps2_vif1_interpreter.cpp VIF1 interpreter: parses VIF commands (NOP, STCYCL, MPG, UNPACK, DIRECT, MSCAL, etc.). Loads VU1 code/data; triggers VU1 MSCAL; forwards DIRECT data to GIF.
ps2_vu1.cpp VU1 interpreter: executes VU1 microcode. Handles XGKICK to send GIF packets from VU1 data memory to Path 1.

New Stubs in ps2_stubs_misc.inl

sceeFont (10 stubs)

  • sceeFontInit
  • sceeFontLoadFont
  • sceeFontPrintfAt
  • sceeFontPrintfAt2
  • sceeFontGenerateString
  • sceeFontClose
  • sceeFontSetColour
  • sceeFontSetMode
  • sceeFontSetFont
  • sceeFontSetScale

sceMpeg (6 stubs)

  • sceMpegAddStrCallback
  • sceMpegClearRefBuff
  • sceMpegCreate
  • sceMpegGetPicture
  • sceMpegIsEnd
  • sceMpegReset

- Replace direct VRAM writes with GIF packet path
- sceGsExecLoadImage: build GIF packet, set MADR/QWC/CHCR
- sceGsExecStoreImage: GIF packet, processPendingTransfers, consumeLocalToHostBytes
- sceGsPutDispEnv/sceGsPutDrawEnv: program GIF DMA Path3 (5/9 QWs)
- sceGsResetGraph: GIF packet + writeIORegister for pmode/smode2/dispfb/display/bgcolor
- sceGsSetDefDrawEnv: GIF packet layout, sceGszbufaddr for zbuf
- sceGsSyncPath: processPendingTransfers, poll DMA channels
- sceGsSyncV/sceGsSyncVCallback: return 0
- sceGszbufaddr: zbuf calculation (width/height blocks, gparam)

Helpers (ps2_stubs_helpers.inl):
- GsDispEnvMem: 5 fields (pmode, smode2, dispfb, display, bgcolor) for GIF layout
- writeGsDispEnv: read-modify-write pattern
- toDmaPhys: SPR (scratchpad) handling for DMA MADR bit 31
- submitDmaSend: chain mode (chcr=0x185) for sceDmaSend/sceDmaSendI/sceDmaSendM

Misc stubs (ps2_stubs_misc.inl):
- Add sceeFontInit, sceeFontLoadFont, sceeFontPrintfAt, sceeFontPrintfAt2
- Add sceeFontClose, sceeFontSetColour, sceeFontSetMode, sceeFontSetFont, sceeFontSetScale
- Font stubs use GIF packets for CLUT and texture upload

Call list (ps2_call_list.h):
- Add sceeFont* entries between sceGszbufaddr and sceIoctl
fix: fixed flickering error when rendering in memory.cpp
@ran-j
Copy link
Owner

ran-j commented Feb 24, 2026

Since it's tested on a recompiled game I will merge but I see some Edge cases on this code but we can work on it

@ran-j ran-j merged commit 1551d59 into ran-j:main Feb 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants