Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
str-player.hh
Go to the documentation of this file.
1/*
2
3MIT License
4
5Copyright (c) 2026 PCSX-Redux authors
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26
27#pragma once
28
29#include <EASTL/functional.h>
30#include <EASTL/string_view.h>
31#include <stdint.h>
32
33#include "psyqo/cdrom-device.hh"
34#include "psyqo/gpu.hh"
36
37namespace psyqo::paths {
38
39class ArchiveManager;
40
72class StrPlayer {
73 public:
74 enum class Present : uint8_t {
75 // Show a decoded frame at the first vblank after the NEXT frame has
76 // arrived off the disc, the way Sony's libraries do: the disc sets the
77 // rate, and the vblank wait keeps the swap out of the visible picture.
78 // A 320x240 24-bit frame takes about 480 scanlines to decode, so a
79 // 30 fps movie holds 30 fps at 60 Hz but is shown at 25 fps at 50 Hz,
80 // dropping one frame in six.
81 STREAM,
82 // Switch the display to a frame the moment it is decoded, wherever the
83 // beam is. Keeps 30 fps at 50 Hz, but the swap lands anywhere in the
84 // picture and tears visibly on fast motion.
85 ASAP,
86 };
87
88 struct Options {
89 bool rgb24 = true;
90 bool audio = true;
91 // Off for a movie encoded for single speed (psxavenc -x 1).
92 bool doubleSpeed = true;
93 // Setfilter: only play the XA channel matching file/channel. When false,
94 // the drive plays every audio sector it meets.
95 bool xaFilter = false;
96 uint8_t xaFile = 0;
97 uint8_t xaChannel = 0;
99 // Number of frames the reassembly ring holds, and the sector budget of a
100 // single frame. A frame using more chunks than this is dropped.
101 uint8_t frameSlots = 3;
102 uint8_t maxSectorsPerFrame = 12;
103 // Run-level buffer for bsdec, in halfwords; two are allocated. A frame
104 // needing more is dropped. Retail 320x240 movies need up to 26304
105 // (Suikoden II) and 25600 (Castlevania SOTN).
106 uint32_t rlHalfwords = 28672;
107 // Size of the display the frame is centered in, in pixels.
108 uint16_t displayWidth = 320;
109 uint16_t displayHeight = 240;
110 // Where in VRAM to decode, for a frame drawn as a texture: always 15-bit (rgb24 is ignored). -1 for the back
111 // buffer. One rectangle, not double buffered: each frame lands in it during frame(), so a caller that draws
112 // from it waits for its own chain to finish before calling frame().
113 int16_t vramX = -1;
114 int16_t vramY = 0;
115 };
116
117 enum class Status : uint8_t { IDLE, PLAYING, ENDED, FAILED };
118
119 struct Stats {
120 uint32_t framesShown = 0;
121 uint32_t framesDropped = 0; // lost in reassembly: missing chunks, or no free slot
122 uint32_t dropIncomplete = 0; // of which a new frame started before every chunk arrived
123 uint32_t dropRingFull = 0; // of which the decoder was behind and no slot was free
124 uint32_t framesRejected = 0; // complete, but bsdec or the MDEC refused them
125 uint32_t videoSectors = 0;
126 uint32_t otherSectors = 0;
127 uint32_t readErrors = 0;
128 uint32_t badAddresses = 0;
129 uint32_t lastFrameNumber = 0;
130 // Vsyncs between two consecutive presented frames, 1, 2, 3, and 4 or more.
131 uint32_t vsyncHistogram[4] = {};
132 // Scanline the display switch happened on, counted from the start of
133 // vblank, in buckets of 32 lines. Only filled in Present::ASAP.
134 uint32_t switchLineHistogram[10] = {};
135 // Scanlines from the start of a decode to its last column landing in
136 // VRAM, in buckets of 64 lines, the last one 704 and up.
137 uint32_t decodeLineHistogram[12] = {};
138 };
139
140 StrPlayer(CDRomDevice &cdrom, GPU &gpu) : m_cdrom(cdrom), m_gpu(gpu) {}
141 ~StrPlayer();
142
149 bool play(uint32_t lba, uint32_t sectors, const Options &options);
150 bool play(uint32_t lba, uint32_t sectors);
151
159 static uint32_t heapNeeded(const Options &options);
160
168 Status frame();
169
176 void stop();
177
178 const Stats &stats() const { return m_stats; }
179
180 private:
181 struct Slot {
182 uint8_t *data;
183 uint32_t frameNumber;
184 uint32_t size;
185 uint32_t received; // bitmask of chunks
186 uint16_t chunks;
187 uint16_t width;
188 uint16_t height;
189 uint8_t state;
190 };
191 friend class StrStreamAction;
192 uint8_t *sectorDest(const uint8_t *header, uint32_t lba);
193 void sectorLanded();
194 void cdDone(bool success);
195 void present();
196 void checkStall();
197 bool vlcNext();
198 void startDecode();
199 void pump();
200 void mdecOutIRQ();
201 bool finishDecode();
202 void abortDecode();
203 void mdecReset();
204 void finish();
205 uint32_t hsyncs();
206 void waitVBlankEdge();
207
208 CDRomDevice &m_cdrom;
209 GPU &m_gpu;
210 Options m_options;
211 Stats m_stats;
212 struct Layout {
213 uint32_t slotBytes, rlBytes, sliceBytes;
214 uint32_t slotData, rl, slices, total;
215 bool fits; // false when rlHalfwords is past any PS1 RAM
216 static Layout of(const Options &options);
217 };
218 uint8_t *m_heap = nullptr;
219 Slot *m_slots = nullptr;
220 struct Rl {
221 uint32_t command;
222 uint32_t halfwords;
223 uint16_t width;
224 uint16_t height;
225 };
226 uint16_t *m_rlBufs[2] = {nullptr, nullptr};
227 Rl m_rlMeta[2] = {};
228 unsigned m_rlIdx = 0;
229 unsigned m_vlcIdx = 0;
230 unsigned m_dmaSlot = ~0u;
231 uint32_t m_colWords = 0;
232 uint32_t m_decodeStart = 0;
233 uint32_t m_decodeStartLine = 0;
234 uint16_t m_colHeight = 0;
235 int16_t m_colHw = 0;
236 int16_t m_x0 = 0;
237 int16_t m_y0 = 0;
238 uint8_t m_colCount = 0;
239 uint8_t m_colArmed = 0;
240 uint8_t m_colDone = 0;
241 uint8_t m_upStarted = 0;
242 uint8_t m_upDone = 0;
243 bool m_uploading = false;
244 bool m_dma1Busy = false;
245 bool m_decodeDone = false;
246 bool m_decoding = false;
247 bool m_decodeOk = false;
248 uint16_t *m_slices[2] = {nullptr, nullptr};
249 uint32_t m_lba = 0;
250 uint32_t m_end = 0;
251 uint32_t m_lastLba = 0;
252 unsigned m_writeSlot = 0;
253 unsigned m_readSlot = 0;
254 int m_filling = -1;
255 uint32_t m_skipFrame = 0xffffffff;
256 bool m_haveRl = false;
257 bool m_haveDecoded = false;
258 bool m_needReset = false;
259 bool m_failed = false;
260 bool m_cdRunning = false;
261 uint32_t m_lastSectorFrame = 0;
262 uint32_t m_lastPresentVsync = 0;
263 uint32_t m_hsyncHigh = 0;
264 uint16_t m_hsyncLast = 0;
265 uint32_t m_vblankRef = 0;
266 uint32_t m_landing = 0;
267 uint16_t m_savedSpuCtrl = 0;
268 uint16_t m_savedCdLeft = 0;
269 uint16_t m_savedCdRight = 0;
270 uint8_t m_retries = 0;
271 bool m_stopping = false;
272 Status m_status = Status::IDLE;
273};
274
281void resolveMovie(ISO9660Parser &parser, eastl::string_view path,
282 eastl::function<void(bool success, uint32_t lba, uint32_t sectors)> &&callback);
283
290bool resolveMovie(const ArchiveManager &archive, eastl::string_view path, uint32_t *lba, uint32_t *sectors);
291
292} // namespace psyqo::paths
A specialization of the CDRom interface.
Definition cdrom-device.hh:80
The singleton GPU class.
Definition gpu.hh:83
An ISO9660 parser.
Definition iso9660-parser.hh:48
This class manages the reading and decompression of files from an archive.
Definition archive-manager.hh:63
Streams an STR movie off the CD-ROM: MDEC video and interleaved XA audio.
Definition str-player.hh:72
StrPlayer(CDRomDevice &cdrom, GPU &gpu)
Definition str-player.hh:140
Status frame()
Drives the playback, to be called from the scene's frame().
Definition str-player.cpp:638
static uint32_t heapNeeded(const Options &options)
The heap play() takes with these options, in bytes.
Definition str-player.cpp:279
bool play(uint32_t lba, uint32_t sectors, const Options &options)
Starts playing the movie in sectors [lba, lba + sectors).
Definition str-player.cpp:288
~StrPlayer()
Definition str-player.cpp:255
const Stats & stats() const
Definition str-player.hh:178
Status
Definition str-player.hh:117
Present
Definition str-player.hh:74
void stop()
Stops the playback early. The drive is paused and the buffers freed.
Definition str-player.cpp:723
Definition str-player.cpp:109
static int size
Definition string.h:149
Definition archive-manager.hh:43
void resolveMovie(ISO9660Parser &parser, eastl::string_view path, eastl::function< void(bool success, uint32_t lba, uint32_t sectors)> &&callback)
Resolves an ISO9660 path into the sector run of a movie.
Definition gte-timing.c:164
Definition str-player.hh:88
bool xaFilter
Definition str-player.hh:95
uint8_t xaFile
Definition str-player.hh:96
uint8_t frameSlots
Definition str-player.hh:101
uint8_t maxSectorsPerFrame
Definition str-player.hh:102
uint16_t displayHeight
Definition str-player.hh:109
uint8_t xaChannel
Definition str-player.hh:97
bool audio
Definition str-player.hh:90
int16_t vramX
Definition str-player.hh:113
uint32_t rlHalfwords
Definition str-player.hh:106
bool rgb24
Definition str-player.hh:89
int16_t vramY
Definition str-player.hh:114
uint16_t displayWidth
Definition str-player.hh:108
bool doubleSpeed
Definition str-player.hh:92
Present present
Definition str-player.hh:98
Definition str-player.hh:119
uint32_t videoSectors
Definition str-player.hh:125
uint32_t vsyncHistogram[4]
Definition str-player.hh:131
uint32_t dropIncomplete
Definition str-player.hh:122
uint32_t decodeLineHistogram[12]
Definition str-player.hh:137
uint32_t dropRingFull
Definition str-player.hh:123
uint32_t badAddresses
Definition str-player.hh:128
uint32_t lastFrameNumber
Definition str-player.hh:129
uint32_t otherSectors
Definition str-player.hh:126
uint32_t framesDropped
Definition str-player.hh:121
uint32_t framesRejected
Definition str-player.hh:124
uint32_t switchLineHistogram[10]
Definition str-player.hh:134
uint32_t readErrors
Definition str-player.hh:127
uint32_t framesShown
Definition str-player.hh:120
static size_t size_t width
Definition syscalls.h:209