Skip to content

psyqo: groundwork for a host PC port#2047

Open
nicolasnoble wants to merge 3 commits into
grumpycoders:mainfrom
nicolasnoble:psyqo-pc-port
Open

psyqo: groundwork for a host PC port#2047
nicolasnoble wants to merge 3 commits into
grumpycoders:mainfrom
nicolasnoble:psyqo-pc-port

Conversation

@nicolasnoble

Copy link
Copy Markdown
Member

Groundwork so psyqo can be compiled on a non-MIPS host as part of a PC port,
originating from Elias Daler's fork.

Two pieces:

  • Gate the non-portable inline assembly (GTE kernels/registers, BIOS syscall
    wrappers, the cop0 helpers, the AdvancedPad busy loop) behind PS1_PC_PORT.
    When the macro is defined those paths compile out; on a normal PS1 build the
    macro is undefined and the generated code is unchanged.

  • Abstract the DMA chain link word behind a ChainEntry type. The packed
    24-bit-address + 8-bit-count "head" is PS1-specific and does not survive a
    64-bit host, where the next-pointer needs its own word; ChainEntry resolves
    to the packed head on PS1 and to a {next, size} pair on the host. The head
    type descends through chain()/scheduleOTC() as uintptr_t.

The macro is not defined by any in-tree build; the swappable pieces (the GPU
class and friends) remain the porter's responsibility. Native builds are
unaffected - the psyqo examples (cube, gte, torus, tetris) build unchanged.

nicolasnoble and others added 2 commits July 8, 2026 13:31
The GTE kernels/registers, the BIOS syscall wrappers, the cop0 helpers in
kernel.hh, and the AdvancedPad busy loop are thin wrappers around MIPS
instructions that only assemble for the target. Guard them behind
PS1_PC_PORT so psyqo can be built on the host as part of a PC port: with the
macro defined those paths compile out (the GTE register readers return 0),
and on a normal PS1 build the macro is undefined and codegen is unchanged.

Co-authored-by: Elias Daler <eliasdaler@protonmail.com>
Signed-off-by: Nicolas 'Pixel' Noble <nicolas@nobis-crew.org>
Fragments and ordering tables encode their DMA linked-list pointer as a
packed 24-bit-address + 8-bit-count word ("head"). That packing is
PS1-specific: on a 64-bit host the next-pointer alone fills the word, so a
PC port needs the pointer and size stored separately. Introduce a ChainEntry
type that resolves to the packed head on PS1 (ChainEntryPS1) and to a
{next, size} pair on the host (ChainEntryPC), and have every fragment type
inherit it. Because the DMA node begins at the link word, the fixed
fragments' count field moves after the payload so it is never transferred.

Descend the head type through the GPU chaining API: chain(), scheduleOTC()
and the internal chain-walk pointers become uintptr_t so the link word is
pointer-width on the host. sendFragment() keeps uint32_t*, since it carries
primitive words rather than a link pointer.

Co-authored-by: Elias Daler <eliasdaler@protonmail.com>
Signed-off-by: Nicolas 'Pixel' Noble <nicolas@nobis-crew.org>
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a PS1_PC_PORT compilation path that disables MIPS, COP0, and COP2 assembly, and refactors fragment, ordering-table, and GPU DMA chain storage around platform-specific ChainEntry types.

Changes

PS1_PC_PORT Inline Assembly Guards

Layer / File(s) Summary
Syscall header conditional region
src/mips/common/syscalls/syscalls.h
Wraps syscall definitions in a PS1_PC_PORT guard.
AdvancedPad busy-wait guard
src/mips/psyqo/advancedpad.hh
Guards the busyLoop delay loop and assembly.
Kernel COP0 and critical-section guards
src/mips/psyqo/kernel.hh
Returns default status values and removes COP0 assembly for PS1_PC_PORT.
GTE register access guards
src/mips/psyqo/gte-registers.hh
Provides zero, empty-value, or no-op behavior instead of GTE assembly.
GTE kernel COP2 emission guards
src/mips/psyqo/gte-kernels.hh
Guards COP2 assembly across the GTE kernel helpers.

Fragment ChainEntry Abstraction and GPU Chaining

Layer / File(s) Summary
ChainEntry types and fragment struct layout
src/mips/psyqo/fragment-concept.hh, src/mips/psyqo/fragments.hh
Adds platform-specific ChainEntry types and updates fragment inheritance, layout checks, and member ordering.
GPU header chaining API updates
src/mips/psyqo/gpu.hh
Uses explicit payload casts, .head chain pointers, and uintptr_t* chain state.
OrderingTable header refactor
src/mips/psyqo/ordering-table.hh
Stores buckets as ChainEntry objects and updates insertion, clearing, and inheritance interfaces.
GPU.cpp chaining implementation updates
src/mips/psyqo/src/gpu.cpp
Uses uintptr_t* for DMA continuation, recovery, chain submission, and OTC scheduling.
OrderingTable.cpp clear implementation
src/mips/psyqo/src/ordering-table.cpp
Initializes chain entries with setEndMarker() and set().

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GPU
  participant OrderingTable
  participant ChainEntry
  GPU->>OrderingTable: request ordering-table chain
  OrderingTable->>ChainEntry: set bucket links and end marker
  GPU->>ChainEntry: read chain head pointers
  GPU->>GPU: schedule DMA chain and OTC
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 43.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: preparing psyqo for a host PC port.
Description check ✅ Passed The description accurately describes the assembly gating and ChainEntry DMA abstraction in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/mips/psyqo/fragments.hh (1)

66-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider guarding ChainEntryPC/ChainEntryPS1 definitions with #ifdef.

Both structs are always compiled regardless of PS1_PC_PORT. When PS1_PC_PORT is not defined, ChainEntry is ChainEntryPS1, so ChainEntryPC::next (typed as ChainEntry*) resolves to ChainEntryPS1* — a semantically incorrect member type that could confuse future developers. Guarding each definition behind its respective #ifdef/#ifndef would eliminate this latent type mismatch and make the intent clearer.

♻️ Proposed refactor
-struct ChainEntryPS1;
-struct ChainEntryPC;
-
-#ifdef PS1_PC_PORT
-using ChainEntry = ChainEntryPC;
-#else
-using ChainEntry = ChainEntryPS1;
-#endif
-
-struct ChainEntryPC {
-    ChainEntry* next;
-    unsigned size;
-    void setEndMarker() {
-        next = nullptr;
-        size = 0;
-    }
-    void set(ChainEntry* next_, unsigned size_) {
-        next = next_;
-        size = size_;
-    }
-};
-
-struct ChainEntryPS1 {
-    uintptr_t head;
-    void setEndMarker() {
-        head = 0xffffff;
-    }
-    void set(ChainEntryPS1* next, unsigned size) {
-        head = (size << 24) | (next->head & 0xffffff);
-    }
-};

+#ifdef PS1_PC_PORT
+struct ChainEntryPC {
+    ChainEntryPC* next;
+    unsigned size;
+    void setEndMarker() {
+        next = nullptr;
+        size = 0;
+    }
+    void set(ChainEntryPC* next_, unsigned size_) {
+        next = next_;
+        size = size_;
+    }
+};
+using ChainEntry = ChainEntryPC;
+#else
+struct ChainEntryPS1 {
+    uintptr_t head;
+    void setEndMarker() {
+        head = 0xffffff;
+    }
+    void set(ChainEntryPS1* next, unsigned size) {
+        head = (size << 24) | (next->head & 0xffffff);
+    }
+};
+using ChainEntry = ChainEntryPS1;
+#endif
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mips/psyqo/fragments.hh` around lines 66 - 96, Guard the ChainEntryPC
definition with `#ifdef` PS1_PC_PORT and the ChainEntryPS1 definition with the
corresponding `#ifndef` PS1_PC_PORT. Keep the existing ChainEntry alias and each
platform’s methods unchanged, ensuring only the selected platform’s struct is
compiled.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/mips/psyqo/gpu.hh`:
- Line 231: Guard the GPU fragment and chain templates, including sendFragment,
chain(Frag&), chain(Frag1*, Frag2*), and chain(OrderingTable&), so PS1_PC_PORT
builds never access .head on Fragments::ChainEntryPC. Mirror the conditional
path used by ordering-table.hh::insert(), or use the ChainEntry abstraction for
PC-port fragments while preserving the existing non-PC behavior.

---

Nitpick comments:
In `@src/mips/psyqo/fragments.hh`:
- Around line 66-96: Guard the ChainEntryPC definition with `#ifdef` PS1_PC_PORT
and the ChainEntryPS1 definition with the corresponding `#ifndef` PS1_PC_PORT.
Keep the existing ChainEntry alias and each platform’s methods unchanged,
ensuring only the selected platform’s struct is compiled.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 18b22e80-7479-4b63-897e-0eb774ea49d5

📥 Commits

Reviewing files that changed from the base of the PR and between 0a7f74f and a10e59f.

📒 Files selected for processing (11)
  • src/mips/common/syscalls/syscalls.h
  • src/mips/psyqo/advancedpad.hh
  • src/mips/psyqo/fragment-concept.hh
  • src/mips/psyqo/fragments.hh
  • src/mips/psyqo/gpu.hh
  • src/mips/psyqo/gte-kernels.hh
  • src/mips/psyqo/gte-registers.hh
  • src/mips/psyqo/kernel.hh
  • src/mips/psyqo/ordering-table.hh
  • src/mips/psyqo/src/gpu.cpp
  • src/mips/psyqo/src/ordering-table.cpp

Comment thread src/mips/psyqo/gpu.hh
template <Fragment Frag>
void sendFragment(const Frag &fragment) {
sendFragment(&fragment.head + 1, fragment.getActualFragmentSize());
sendFragment(reinterpret_cast<const uint32_t *>(&fragment.head + 1), fragment.getActualFragmentSize());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Find all .head references in gpu.hh templates that lack PS1_PC_PORT guards.

rg -n '\.head' src/mips/psyqo/gpu.hh | grep -v 'm_chainHead\|m_chainTail\|chainHead\|chainTail\|head ='

Repository: grumpycoders/pcsx-redux

Length of output: 603


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## gpu.hh outline\n'
ast-grep outline src/mips/psyqo/gpu.hh --view expanded || true

printf '\n## fragment-concept.hh outline\n'
ast-grep outline src/mips/psyqo/fragment-concept.hh --view expanded || true

printf '\n## ordering-table.hh outline\n'
ast-grep outline src/mips/psyqo/ordering-table.hh --view expanded || true

printf '\n## gpu.hh relevant ranges\n'
sed -n '200,380p' src/mips/psyqo/gpu.hh | cat -n

printf '\n## fragment-concept.hh relevant ranges\n'
sed -n '1,140p' src/mips/psyqo/fragment-concept.hh | cat -n

printf '\n## ordering-table.hh relevant ranges\n'
sed -n '1,220p' src/mips/psyqo/ordering-table.hh | cat -n

Repository: grumpycoders/pcsx-redux

Length of output: 20849


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## fragments.hh outline\n'
ast-grep outline src/mips/psyqo/fragments.hh --view expanded || true

printf '\n## fragments.hh relevant ranges\n'
sed -n '1,260p' src/mips/psyqo/fragments.hh | cat -n

printf '\n## search for ChainEntryPC / ChainEntryPS1\n'
rg -n 'ChainEntryPC|ChainEntryPS1|struct ChainEntry|class ChainEntry|using ChainEntry' src/mips/psyqo

Repository: grumpycoders/pcsx-redux

Length of output: 8340


Guard GPU fragment/chain templates for PS1_PC_PORT
sendFragment, chain(Frag&), chain(Frag1*, Frag2*), and chain(OrderingTable&) still dereference .head unconditionally. Fragments::ChainEntryPC has no head, so these templates won’t instantiate for PC-port fragments even though the Fragment concept already drops that requirement. Mirror the #ifdef PS1_PC_PORT split used in ordering-table.hh::insert(), or route the PC path through the ChainEntry abstraction.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mips/psyqo/gpu.hh` at line 231, Guard the GPU fragment and chain
templates, including sendFragment, chain(Frag&), chain(Frag1*, Frag2*), and
chain(OrderingTable&), so PS1_PC_PORT builds never access .head on
Fragments::ChainEntryPC. Mirror the conditional path used by
ordering-table.hh::insert(), or use the ChainEntry abstraction for PC-port
fragments while preserving the existing non-PC behavior.

@codecov

codecov Bot commented Jul 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 12.63%. Comparing base (cbf70bd) to head (a10e59f).
⚠️ Report is 18 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2047      +/-   ##
==========================================
- Coverage   12.63%   12.63%   -0.01%     
==========================================
  Files         538      541       +3     
  Lines      150069   150140      +71     
==========================================
- Hits        18967    18964       -3     
- Misses     131102   131176      +74     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant