Commit Graph

186 Commits

Author SHA1 Message Date
Ran-j 39251a05f4 feat: remove LLE IOPs 2026-09-19 21:17:58 -03:00
Ran-j 78ecbae377 fix: fix texture caching
feat: wip multi version on dbcman
2026-09-14 02:11:06 -03:00
Ran-j 590b884ba4 Merge origin/main into feature/iop-emulator
Preserve the branch's GS CLUT and texture cache implementation while integrating upstream thread initialization and syscall resume coverage. Build passes; 448/456 tests pass with the same eight failures reproduced on pre-merge HEAD (447/455).
2026-09-07 18:21:48 -03:00
Ran-j 2a61ba0df3 feat: added a lot of tests 2026-09-02 18:06:13 -03:00
Ran-j c8c86661fa refactor: Refactor PS2 IOP Host Adapter and Memory Management
feat: Added PS2Vfs for virtual file system operations, including file opening, reading, writing, and path resolution.
feat: Improve VIF1 data processing to handle GIF image packets more efficiently.
2026-09-02 18:05:55 -03:00
Ran-j 08dc217818 feat: add SET_GPR_ZE32 macro for zero-extending loads with unsigned semantics 2026-09-02 17:41:14 -03:00
Ran-j 6560a37b8b feat: update memory hint handling and enhance entry point discovery logic 2026-09-02 17:40:43 -03:00
Ran-j 5ebc2475e0 eat: enhance ELF parser with improved callable entry detection and control flow analysis 2026-09-02 17:38:18 -03:00
Ran-j b9dba607d8 feat: remove recompiled version of GetRomName
refactor: split IOP emulator logic
feat: added more HLE IOP modules
feat: added ps2_path
2026-09-02 17:19:00 -03:00
Ran-j cc9e075573 feat: analyzer resolve the complete constant-producing sequence with five-instruction backward scan stopped at LUI and therefore 2026-09-02 16:45:57 -03:00
Ran-j a293fa433a feat: IOP emulator
refactor: codegen to catch callbacks on mips code
feat: added a lot of entries or IOP emulator
2026-08-19 16:53:00 -03:00
Sinan 14b1e5cb39 Start the main thread with COP0 Status.IE set (#214)
Guest code reads COP0 Status to decide whether interrupts are enabled,
and two different bits are involved:

  IE  (bit 0)   the architectural MIPS interrupt enable, set once by the
                kernel during boot and normally left set.
  EIE (bit 16)  the EE-specific enable that `ei` and `di` toggle.

We never execute the boot ROM, so nothing was setting either one, and
R5900Context started with Status at zero.

That is not cosmetic. libkernel's StartThread opens with
`mfc0 Status; xori 1; andi 1` and bails out with -1 when IE is clear --
its "you must call iStartThread from an interrupt handler" guard. With
Status at zero that guard fired every time, so every StartThread failed.
Dragon Quest VIII hits this during boot: it creates its CD streaming
thread, gets -1, prints "Can't start thread for streaming." and then
deadlocks with every thread blocked and none runnable. Nothing in the
runtime logs anything, because from its point of view the guest simply
asked a question and got an answer.

EIE matters for the matching reason: DIntr reports whether it was set so
the caller knows whether to pair it with an EIntr. Starting at zero makes
DIntr always answer "already disabled", so the re-enable never happens.

Two changes, both needed:

- R5900Context's constructor now sets Status to EIE | IE rather than 0.
  BEV is deliberately left clear -- that selects the boot exception
  vectors, which is the pre-handoff state, not this one.

- PS2Runtime's constructor no longer memsets m_cpuContext. R5900Context
  already zeroes itself before applying its reset values, so the memset
  only threw those values away. Threads created later were unaffected
  because EeScheduler::startThread assigns `R5900Context{}`, which is
  why this presented as "the main thread cannot start threads" rather
  than something more obviously global.

(cherry picked from commit 2ac2ce6320)
2026-08-18 19:50:13 -03:00
Sinan d9ea4fb63d Let a thread resume at the instruction after a syscall (#210)
A syscall can hand control back to the scheduler before the instruction
after it runs. SetSyscall lets the guest install its own handler for a
syscall number; dispatchSyscallOverride then suspends the calling
thread and queues that handler as a GuestInvocation. When the
invocation finishes, EeScheduler resumes the parent thread at the
address the generated code stored just before calling handleSyscall --
the instruction right after the syscall.

The analyzer never marked that address as an entry point. It queues
resume entries for JAL and JALR only, so no generated function could be
re-entered there, EeScheduler's hasFunction() check failed, and the
thread was made dormant instead of resumed. The thread simply stops;
because the scheduler then drains normally and run() returns, it looks
like a clean shutdown rather than a fault, which makes it awkward to
recognise.

This is reachable during early boot on a real title. Dragon Quest VIII
hits it in crt0: the Metrowerks startup code installs a handler for
syscall 0x83 and immediately issues it, and execution ends there,
roughly ten functions into the binary.

Note the offset is +4, not the +8 used for JAL and JALR -- syscall has
no delay slot.

(cherry picked from commit becb2be5bd)
2026-08-18 19:49:38 -03:00
Ranieri d74a3ce139 Feature/gs refactor (#204)
* refactor: from guest  threads to EE scheduler

* feat: bad wip mpeg fix for code veronica

* feat: cheap copy from host
feat: small perf o vsync tick

* feat: added EE clock Hz
fix: fix MPEG out of sync with new EE refactor

* fix: fix lotr tests

* fix: fix cri dtx loading
fix: fix wrong mmi instruction translation
fix: fix thread info params
feat: added EE  timers decoder and consumer
feat: split SFI and IOP memory to prevent collision and overrides

* feat: revert wrong changes

* refactor: change GS architecture
2026-08-13 22:49:04 -03:00
Ran-j a6739395b3 Merge branch 'main' of https://github.com/ran-j/PS2Recomp into feature/gs-refactor 2026-08-13 10:11:02 -03:00
Ran-j 3b9b14c618 refactor: change GS architecture 2026-08-13 09:33:49 -03:00
Ranieri 8d7e8a5a46 Feature/ee timers and fixes (#203)
* refactor: from guest  threads to EE scheduler

* feat: bad wip mpeg fix for code veronica

* feat: cheap copy from host
feat: small perf o vsync tick

* feat: added EE clock Hz
fix: fix MPEG out of sync with new EE refactor

* fix: fix lotr tests

* fix: fix cri dtx loading
fix: fix wrong mmi instruction translation
fix: fix thread info params
feat: added EE  timers decoder and consumer
feat: split SFI and IOP memory to prevent collision and overrides

* feat: revert wrong changes
2026-08-12 12:11:06 -03:00
Ran-j 8b57926df6 feat: revert wrong changes 2026-08-12 11:57:50 -03:00
Ran-j 715933073b Merge branch 'main' of https://github.com/ran-j/PS2Recomp into feature/ee-timers-and-fixes 2026-08-12 11:55:09 -03:00
Ran-j 4fff58373c fix: fix cri dtx loading
fix: fix wrong mmi instruction translation
fix: fix thread info params
feat: added EE  timers decoder and consumer
feat: split SFI and IOP memory to prevent collision and overrides
2026-08-12 11:49:30 -03:00
Ranieri f4309cd18c refactor: from guest threads to EE scheduler (#184)
* refactor: from guest  threads to EE scheduler

* feat: bad wip mpeg fix for code veronica

* feat: cheap copy from host
feat: small perf o vsync tick

* feat: added EE clock Hz
fix: fix MPEG out of sync with new EE refactor

* fix: fix lotr tests
2026-08-11 11:35:50 -03:00
Ran-j f9332d6df1 fix: fix lotr tests 2026-08-11 11:21:56 -03:00
Ran-j d91d2c1b75 feat: added EE clock Hz
fix: fix MPEG out of sync with new EE refactor
2026-08-07 21:54:33 -03:00
Ran-j 3e5fb2b3b4 feat: cheap copy from host
feat: small perf o vsync tick
2026-08-05 19:03:03 -03:00
Ran-j c09e90aa93 Merge branch 'main' of https://github.com/ran-j/PS2Recomp into feature/remove-runtime-guest-threads 2026-08-05 16:32:36 -03:00
Ranieri f49ca4edbc refactor: refactor VU1 (#191)
* feat: implement fix and changes based on dark cloud report
fix: fix GS AFAIL for RGB/alpha/Z, ZMSK
fix: fix VU1 flags mask and pipeline
fix: small VU1 cache fix
feat: __ct__, __sinit_ are not sillent stubs anymore

* feat: fix song JP pulling

* feat: sound update for lotR

* feat: prevent guest execution to be very slow

* fix: small gs size bug

* feat: refactor VU
fix: fix cliping and other issues on gs
fix: fix wrong vu0 register on recompiler

* fix fix ACC scheduler stall
feat: remove unused test
fix: .fix overflow e underflow on FMAC

* feat: small setting  for windows test
2026-08-05 14:50:24 -03:00
Shane Michael Mathews (Personal Account) 61300792a0 fix(recomp): include <cstdint> before elfio in elf_parser.h (#199)
ELFIO, pinned at Release_3.12 via FetchContent, uses uint16_t, uint32_t
and uint64_t in elf_types.hpp without including <cstdint> itself. Newer
libstdc++ releases trimmed the transitive includes that used to supply
those typedefs, so building elf_parser.cpp fails:

  elf_types.hpp:30:20: error: 'uint16_t' does not name a type
     30 | using Elf_Half   = uint16_t;

Include <cstdint> ahead of elfio.hpp so the typedefs are visible when
that header is processed. Header-only change; no behaviour is affected.
2026-08-01 12:48:48 -03:00
gustavoauneth d87bff4256 fix(recomp): incorrect opcode mapping for MMI2 in PMADDH, PHMADH, PMSUBH and PHMSBH instructions (#194) 2026-08-01 00:58:03 -03:00
Shane Michael Mathews (Personal Account) 6970f3a2c4 feat(hle): implement sceVu0 macro-mode matrix/vector math library (#183)
Fill the remaining TODO_NAMED bodies in Kernel/Stubs/VU.cpp so the
out-of-line libvu0 macro-mode routines write their documented results to
the caller's output operand instead of leaving guest memory untouched (the
TODO_NAMED stub throws, or returns -1 once its per-name warning budget is
spent, and never writes the destination).

Implements the matrix/geometry/clip/lighting entry points:
CameraMatrix, InversMatrix, MulMatrix, TransMatrix, RotMatrix,
NormalLightMatrix, LightColorMatrix, DropShadowMatrix, ViewScreenMatrix,
RotTransPers/RotTransPersN, ClipScreen/ClipScreen3/ClipAll, MulVector,
ScaleVectorXYZ, DivVector/DivVectorXYZ, InterVector/InterVectorXYZ,
ClampVector, ecossin. Pure input->output arithmetic over guest memory
through the existing getMemPtr/getConstMemPtr and getRegU32/ctx->f[]
accessors already used by the implemented sceVu0 functions in the same
file. No new runtime state, no signature changes, no VU.h changes.

The clip and view/shadow routines provide the functional contract callers
rely on (nonzero => offscreen; projection by formula shape) rather than a
bit-exact reproduction of the COP2 sticky clip-flag register.

Adds ps2xTest/src/ps2_vu_tests.cpp covering each routine against its
documented formula.
2026-07-28 15:21:01 -03:00
Ran-j 9f99d615c5 feat: bad wip mpeg fix for code veronica 2026-07-25 21:26:31 -03:00
Ran-j cc941d2f4f refactor: from guest threads to EE scheduler 2026-07-25 21:23:24 -03:00
Ranieri f3687c5ae6 Feature/random fixes platform support (#179)
* feat: implement memory card IOP

* feat: IOP trace

* feat: move IOP logic to ps2xIOP
refactor: small refactor on audio api on runtime

* feat: android support
feat: prevent race on GS
feat: a bit cleanup and reimplement on memory card

* feat: finish guest thread
feat: android build support
feat: vita build support with suspicious setup scripts

* feat: remove idea from track
2026-07-22 02:37:53 -03:00
Shane Michael Mathews (Personal Account) 1176609890 test(sema): make contended semaphore poll/signal test deterministic (#176)
The "Semaphore poll/signal remains stable under host-thread contention"
test created the semaphore full (init == max == 1), so SignalSema could
only succeed after PollSema had already freed a slot. With no start
barrier, under host-thread contention the signaler thread could run all
64 of its iterations before the poller's first timeslice, making every
SignalSema legitimately return KE_SEMA_OVF and leaving signalOkCount at
0 — a false failure of "contended SignalSema should observe successful
releases". An earlier investigation of the unfixed test observed this
twice in 24 contended (8-way-parallel) full-suite runs and never in 20
serial runs; CI has independently hit the same assertion on the
unrelated draft PR #174, confirming the trigger is host scheduling, not
the code under review.

Seed the semaphore with headroom (init=1, max=2) so the first PollSema
and the first SignalSema each succeed regardless of scheduling order,
and add a start barrier so both workers start together, maximizing the
opportunity to interleave. Widen the final-count range check to the new
max. The semaphore implementation is unchanged; both threads still
contend concurrently on the same per-semaphore mutex.
2026-07-21 11:09:38 -03:00
Ranieri ee149581aa Refactor IOP system (#170)
* feat: implement memory card IOP

* feat: IOP trace

* feat: move IOP logic to ps2xIOP
refactor: small refactor on audio api on runtime
2026-07-15 01:44:06 -03:00
TH3BACKLOG 905b4edfa8 fix(recomp): advance ctx->pc on fallthrough functions with no terminating branch (#168)
* fix(recomp): advance ctx->pc on fallthrough functions with no terminating branch

FunctionEmitter::emit only ever advances ctx->pc via the per-instruction
`ctx->pc = 0x<addr>u;` assignment (overwritten by the next instruction in
the same function) or via handleBranchDelaySlots when the last instruction
is a branch/jump. A function whose last instruction is neither (e.g. a
lone padduw/NOP-style instruction with no terminator) leaves ctx->pc
pointing at its own last instruction forever after returning, since
nothing ever advances it to the next function.

dispatchLoop then reads ctx->pc, looks up the same function, and calls it
again -- forever. No exception, no crash, just an infinite loop that
silently never makes forward progress.

Reproduced on SDBZ's SLUS_214.42 ELF entry point: 0x100008 is emitted as a
standalone 1-instruction function (padduw $at, $zero, $zero) with no
branch, causing dispatchLoop to spin on pc=0x100008 indefinitely.

Fix: track whether the last processed instruction had a delay slot (i.e.
was a branch/jump); if the function ends without one, emit an
unconditional ctx->pc = function.end before closing the function so
dispatchLoop resumes at the next function instead of spinning.

* review: trim overly verbose comment per ran-j feedback
2026-07-13 09:50:36 -03:00
Shane Michael Mathews (Personal Account) 81f2a7f5e1 fix(runtime): stop double-counting nloop in sceGifPkRefLoadImage A+D header GIFtag (#149)
sceGifPkRefLoadImage seeded its A+D header GIFtag with nloop=4 via
makeGiftagAplusD(4u), then closePacketGifTag computed the appended
register-qword count (4) from the write-cursor delta and ADDED it to the
seed, finalizing nloop=8 for a tag with only 4 A+D register qwords
(BITBLTBUF/TRXPOS/TRXREG/TRXDIR). A GIF parser consuming that tag eats the
following IMAGE GIFtag and its first payload qwords as bogus A+D data,
starving the CLUT/texture upload that the setup packet precedes (e.g. DQ8
font-glyph CLUTs staying all-zero).

Seed an open A+D tag (nloop=0, nreg=1, EOP clear) instead and let
closePacketGifTag add the true count, finalizing 0x1000000000000004 -- the
value the regression test pins. The seed is written via a named
makeGiftagAplusDOpen(nloop) helper in Support.h (mirrors makeGiftagAplusD but
leaves EOP/bit 15 clear for a chained tag whose nloop is finalized at close),
rather than a bare (1ULL << 60) literal, to keep the file's
GIFtag-construction convention consistent. makeGiftagAplusD(0u) can't be used
because it always sets EOP.

Adds a byte-level regression test that drives sceGifPkRefLoadImage (setup
only, qwcRemaining=0) against a scratch packet-builder state and asserts the
finalized header tag lo/hi, the four A+D register descriptors (0x50..0x53),
and their four register payloads (BITBLTBUF dbp/dbw/psm, TRXPOS, TRXREG
width/height, TRXDIR) -- pinning the full setup packet.

Full build clean; ps2x_tests 297/297.
2026-07-10 14:20:59 -03:00
Shane Michael Mathews (Personal Account) c4355c8cda Pads open in DIGITAL mode, not analog (spec 06) (#153)
Real PS2 pads power up in DIGITAL mode (CURID 4, mode byte 0x41) and only
switch to analog (CURID 7, 0x73) when the game calls scePadSetMainMode. The
three open-time sites in Pad.cpp incorrectly set analogMode=true, so
scePadInfoMode(PAD_MODECURID) reported analog from frame 0. Games that gate
logic on the analog transition (e.g. DQ8 fn_165b20) saw an impossible state.

- PadPortState default, initializePadPortLocked, scePadPortOpen: analogMode=false
- scePadSetMainMode remains the only path into analog mode (unchanged)
- Updated the existing pad-info test's at-open CURID expectation (7 -> 4)
- Added a regression test: open reports digital (CURID 4, 0x41), then
  scePadSetMainMode(mode=1) switches to analog (CURID 7, 0x73)
2026-07-10 14:10:23 -03:00
Shane Michael Mathews (Personal Account) d50ed4e300 test(gs): H-format shared-plane texture regression coverage (T8H/T4HL/T4HH) (#155)
Add byte-level regression tests for the GS "high" indexed texture formats,
which store their index in the alpha byte of a shared PSMCT32 word -- T4HL in
bits 24-27, T4HH in bits 28-31, T8H in the full byte 24-31. The format-aware
VRAM path (the #140 refactor) already implements these at main; these tests
pin the plane-separation and over-transfer behavior so it can't silently
regress.

- Plane separation: uploading distinct T4HL then T4HH patterns to the same dbp
  leaves both planes intact (RMW into the shared CT32 word), cross-checked
  against GSMem::ReadP4HL/ReadP4HH.
- T8H coverage: uploads the full byte into bits 24-31 via a real BITBLTBUF+GIF
  IMAGE transfer (one byte per texel through WriteP8H) and round-trips it via
  GSMem::ReadP8H. T8H takes the plain byte-store branch of
  PixelStorageTraits::Write and its own upload loop, distinct from the
  T4HL/T4HH nibble RMW path, so it needs independent coverage.
- Clobber interaction: a T4HL nibble upload over a prior T8H byte overwrites
  bits 24-27 with the nibble and preserves bits 28-31 (the T8H byte's high
  nibble) -- the hardware-modeled RMW outcome.
- Sampled channels: each plane resolves through its own 16-entry CT32 CLUT to
  the expected RGBA, with distractor CLUT entries so a cross-plane nibble read
  produces a non-matching color.
- Over-transfer hard-stop: an ~8x oversized T4HL IMAGE payload writes only
  rrw*rrh texels and deactivates the transfer (trxdir=3), and a subsequent
  transfer to a different dbp is byte-correct.

Test-only; no product code change. ps2x_tests: 299/299.
2026-07-10 12:06:20 -03:00
Ranieri cf4a90c4ab feat: default capture history gs to false (#167)
fix: remove wrong logic on frameupload
fix: fix option to enable and disable logs
2026-07-08 22:09:23 -03:00
Ranieri ecc86f4b5d Feature vu1 cache (#158)
* feat: explode vu1 in files
feat: added way  more tests for vu1

* feat: added VU1 cache
2026-07-07 21:48:26 -03:00
Ranieri 52edf07657 Feature/agressive recompiler (#146)
* feat: added guestBranchKind enum to categorize branch types
feat: added missingFunctionPolicy enum to define behaviors for missing function scenarios
refactor: added handle guest branches and report missing functions
feat lookupFunction to utilize new dispatch logic and improve error handling for unregistered functions

* fix: fix test conflict

* feat: added debug sound driver logs

* feat: emmiter for return

* feat: added recompiler reporter
feat: added strict diagnostics flag for heavy debug calls

* feat: staticc table insted of hashmap for runtime

* feat: back file to ignore

* feat: explode code across helpers and classes

* feat: update codegen test
feat: better guest nop check

* feat: fix link problem on linux

* feat: fix Segmentation fault

* feat: added recompile replace for DMA and MMIO
feat: added a clean memory helpers
feat: use memory helpers across the project
feat: fix ucrt on msvc

* feat: undo messup merge
2026-07-07 10:14:25 -03:00
Shane Michael Mathews (Personal Account) 61621b8313 fix(runtime): make GS CSR atomic to fix vsync-worker/guest data race (#145)
updateGsCsrFieldForVSync runs on the detached vsync worker and updated the
FIELD bit with a non-atomic read-modify-write of GSRegisters::csr while
guest threads concurrently read/write the same word (MMIO read32/read64 and
the W1C handling in write32/write64) and the GIF path sets SIGNAL/FINISH.
Even though the writers touch disjoint bits, a whole-word RMW loses the
other side's update: a clobbered SIGNAL/FINISH set hangs a game
synchronizing on GS completion, a clobbered W1C clear re-asserts a handled
interrupt, and a clobbered FIELD toggle stalls interlace field polling.
ThreadSanitizer flags the race on main (updateGsCsrFieldForVSync vs
PS2Memory::write64 and GS::writeRegister).

Make the field std::atomic<uint64_t> and perform every update as a single
atomic RMW:

- vsync FIELD toggle -> fetch_or / fetch_and
- MMIO W1C writes -> compare_exchange loop in shared helpers (a
  load-then-store pair would still race); a 32-bit store to the CSR's upper
  dword previously bypassed the W1C special case entirely and went through
  the plain merge branch - both halves now share the same atomic helper
  with unchanged guest-visible semantics
- GIF SIGNAL/FINISH -> fetch_or
- reads -> load()

std::atomic<uint64_t> is lock-free on all supported targets (static_assert
added), the struct's size/alignment asserts are unchanged, GSRegisters is
never copied by value, and default (seq_cst) ordering is used throughout -
these operations are rare (vblank ticks, GIF signals, CSR MMIO), so
reviewability wins over micro-optimization.

New regression test: two racer threads each own one status bit (SIGNAL /
FINISH) and loop 80k GIF-set + W1C-clear cycles verifying their own bit
after each half-op while the vsync worker toggles FIELD. Fails 20/20 runs
against the previous code, passes 50/50 with the fix, ~350ms runtime, no
sanitizer needed.
2026-07-06 12:35:44 -03:00
Ranieri 5196a6672a Refactor runtime for move speed and better code style (#140)
* feat: added guestBranchKind enum to categorize branch types
feat: added missingFunctionPolicy enum to define behaviors for missing function scenarios
refactor: added handle guest branches and report missing functions
feat lookupFunction to utilize new dispatch logic and improve error handling for unregistered functions

* fix: fix test conflict

* feat: added debug sound driver logs

* feat: emmiter for return

* feat: added recompiler reporter
feat: added strict diagnostics flag for heavy debug calls

* feat: staticc table insted of hashmap for runtime

* feat: back file to ignore

* feat: explode code across helpers and classes

* feat: update codegen test
feat: better guest nop check

* feat: fix link problem on linux

* feat: fix Segmentation fault
2026-07-04 00:43:22 -03:00
Jeffrey Shulkin 3a2e0d69fd feat: add SSE2 support and fix SSE4.1 paths for PADDSW and PSUBSW instructions (#141)
* feat: add sses2 support for PADDSW and PSUBSW instructions

* Fixed SSE4.1 PADDSW/PSUBSW implementations
2026-07-04 00:02:00 -03:00
Jeffrey Shulkin db3d44fbde Added explicit FPU ACC register (#143) 2026-07-03 10:03:59 -03:00
Ranieri 8c8a97af65 Feature/mpeg decoder (#120)
* feat: added ffmepg as dependency

* feat: wip decoder video

* feat: some perf and cleanup

* feat:  added generic MPEG stream notification

* feat: CMakeLists.txt in ps2xStudio to configure SDL2 build options for static linking.
fix: fix ffmpeg setup for linux
fix: now MPEG decoder now identify that movie has ended and can play again anytime
feat: better audio stub to not block games

* feat: fix expansion test

* feat: foo

* a

* feat: finally added a helper to to prevent thread starvation

* feat: added basic  vu0 code execution

* feat: added yield Guest Execution After Wake to prevent deadlock

* feat: added  options  on  cmake for logs
feat: better input for keyboard pad

* feat: small corrections like top and itop vu branches etc

* feat: changes

* feat: working feature

* feat: fatal frame iop

* feat: test fix
feat: z buffer fix

* fix: gix GsPutIMR IMR

* feat: added rl imgui

* feat: added helper to get snapshot

* feat: added debug panel consuming snapshots

* feat: added pad snapshot
feat: added RCP debug events

* feat: final cleanup from old code

* feat: added EE timer counter
feat: applyed sound driver for Lotr
feat: better check for sound driver compat layout
feat: enquee and cosumed DMa cause
feat: added Pad execCMd
feat: update GS vsync signal flag
feat: custom IOPs for LotR

* feat: small cleanups

* fix: fix wrong import
2026-06-26 21:04:39 -03:00
tealalchemist a111059a70 [runtime] fixup rasterizer (#139)
- missing RGBA5551 to RGBA8888 conversion in lookupClut
- round depth up for triangles (Code Veronica text bug)
2026-06-24 14:07:47 -03:00
tealalchemist 9bf9c08d9d [runtime] various fixup (#138) 2026-06-22 11:16:54 -03:00
Shane Michael Mathews (Personal Account) a8828f5c77 fix: semaphore syscalls return sid on success instead of KE_OK (#136)
* fix: semaphore syscalls return sid on success instead of KE_OK

The PS2 EE BIOS returns the semaphore ID on success for all semaphore
syscalls, not zero. PollSema, WaitSema, SignalSema, and DeleteSema were
all returning KE_OK (0) on success, which breaks games that compare the
return value against the semaphore ID.

DQ8's init code polls a mutex semaphore at 0x12A670 and checks the result
against the semaphore ID using bne. With KE_OK returned, the comparison
always fails and the game spins forever at PC 0x164978 and never starts.
Other games that follow the same EE BIOS convention would hit the same
problem. CreateSema already returned the ID correctly; this brings the
other four operations in line with the same convention.

The fix is five changes in Sync.cpp: the four return sites are updated to
return sid, and the count-decrement guard in WaitSema is changed from
ret == 0 to ret >= 0. The guard change is necessary because ret is now
seeded to sid (a positive value) on the success path, and the old equality
check would have silently stopped decrementing the semaphore count. Error
paths (KE_WAIT_DELETE, KE_RELEASE_WAIT) are negative and still correctly
bypass the decrement.

Tests are updated to expect sid instead of KE_OK on success paths, and new
test cases cover the blocked-wait-then-signal path (the actual DQ8 scenario),
force-release via ReleaseWaitThread, and the count-decrement guard directly.

* fix: update stale KE_OK assertions in expansion and SIF RPC tests

Two test files were not updated alongside the semaphore return-value change.
PollSema and SignalSema now return sid on success; update the four assertions
that expected KE_OK on those success paths.

* fix: tighten WaitSema count-decrement guard to ret == sid

ret is seeded to sid on success and only ever overwritten with negative
error codes, so ret == sid precisely expresses "this wait acquired this
semaphore" — more explicit than the looser ret >= 0.

Suggested by ran-j in PR review.
2026-06-21 00:07:58 -03:00
tealalchemist 91592e3faa GS rasterizer rework (#132)
* [runtime] Memory swizzling rework

Reimplementation of memory swizzling supporting all valid GS texture
storage types.

An additional optimization was done to improve the speed of lookups.
Since page access is linear, we can precompute the non-linear bit
(blocks and columns) for an entire page for each format. This reduces
the runtime calculation to just calculating the correct page in 2d
memory space and then performing a lookup in the table to get the
location in memory inside a page. Since all page accesses are the same,
this works across all pages. Speed improvements should be compounded by
the number of accesses but there might be some reductions as a result of
actually implementing formats that were not implemented before.

I took care to do this with simple math. GS swizzling is complicated and
optimizing it for debug builds is outside the scope of my current work.

This is just the standalone code. It will be worked into the current
rasterizer in a follow up commit.

* [runtime] Reimplement GS host -> local transfers

Reimplement the host -> local transfers using new swizzling code

* [runtime] Reimplement sampling with new swizzling

Reimplements the rasterizer sampling code to use the new swizzling code

* [runtime] Replace fb writes with new swizzling

Replace the framebuffer write code with the new swizzling code

* [runtime] Reduce vram read/write to func lookup

Reduces the vram read write switches to a function lookup

* [tests] fix GS tests not handling depth test

* [runtime] z interpolation and write support

Add support for interpolating z from primitives and writing to the z
buffer after z testing and masking

* [runtime] local to local transfer rework

* [runtime] host readout uses new sizzling code

plus cleanup some dead code

* [runtime] rework local->host transfer

update to the new swizzling code

* [runtime] update clear function with new swizzling
2026-06-21 00:07:26 -03:00