Skip to content

End sceMpegIsEnd at the PSS program end when no sceCdSt stream fed the movie - #414

Open
0xLeathery wants to merge 2 commits into
ran-j:mainfrom
0xLeathery:feat/mpeg-isend-program-end
Open

0xLeathery wants to merge 2 commits into
ran-j:mainfrom
0xLeathery:feat/mpeg-isend-program-end

Conversation

@0xLeathery

Copy link
Copy Markdown

Problem

The MPEG HLE's sceMpegIsEnd only returns 1 once the producer reports end of file: currentCdStreamEofSeen plus a matching cdStreamGeneration. Only the HLE's sceCdSt streaming path advances those.

Many games don't use sceCdSt. Sly 2 (SCUS-97316) reads its movies with plain sceCdRead into its own ring and demuxes them with sceMpegDemuxPssRing. For those games the EOF flag is never set, so sceMpegIsEnd never returns 1 and a loop like do { …GetPicture… } while (!sceMpegIsEnd(mp)) never exits.

This happens even though the demux has already seen the PSS program-end code (0x000001B9) and set playback.streamEnded. Unlike a sequence-end code, the program end marks the end of the whole PSS file.

Change

  • Playback not fed by sceCdSt (playback.cdStreamGeneration == 0, meaning no sceCdStStart this session): the producer counts as ended once streamEnded is set by the program-end path.
  • Unchanged checks: IsEnd still requires an empty decoded-frame queue and complete presentation, so it returns 1 only after every frame has been shown.
  • sceCdSt-fed playback keeps exactly the previous rule.
  • Trace: the [MPEG:IsEnd] trace gains a cdStreamFed= field.

Testing

New tests in ps2_runtime_expansion_tests.cpp:

  • Program end without sceCdSt: IsEnd stays 0 while frames are queued and returns 1 once they've been shown and two real VBlanks have passed. This test failed before the change.
  • No program end: IsEnd stays 0 after the queue drains.
  • sceCdSt path: a program end alone doesn't end an active sceCdSt stream; its EOF still does.

Results:

  • ps2x_tests: 449/449.
  • Extra probes, not committed:
    • A program end that arrives with frames still queued doesn't end the movie early.
    • A stream that has only a sequence end (B7) never ends.

With a recompiled Sly 2 (USA), whose sceMpegIsEnd at 0x24B610 is bound to the HLE, the intro movie now ends and boot continues past it. The movie's data on disc does end with 00 00 01 B9.

Known limits, not changed here

  • A non-sceCdSt movie that plays while an sceCdSt stream has started but hasn't reached EOF still waits for that EOF. Once that stream reaches EOF or is stopped, the old rule ends the movie.
  • This predates this PR. After sceMpegReset (rather than sceMpegCreate), the handle carries streamEnded forward, and appendPssBytes drops the next movie's bytes. With this change, a second movie played on the same handle reports IsEnd immediately; before, it hung. Worth a separate issue.

Built and tested on macOS arm64 (Apple clang).

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.

1 participant