Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Graphics/Video.cpp
1163 views
1
#include "RSDK/Core/RetroEngine.hpp"
2
3
using namespace RSDK;
4
5
FileInfo VideoManager::file;
6
7
ogg_sync_state VideoManager::oy;
8
ogg_page VideoManager::og;
9
ogg_packet VideoManager::op;
10
ogg_stream_state VideoManager::vo;
11
ogg_stream_state VideoManager::to;
12
th_info VideoManager::ti;
13
th_comment VideoManager::tc;
14
th_dec_ctx *VideoManager::td = NULL;
15
th_setup_info *VideoManager::ts = NULL;
16
17
th_pixel_fmt VideoManager::pixelFormat;
18
ogg_int64_t VideoManager::granulePos = 0;
19
bool32 VideoManager::initializing = false;
20
21
bool32 RSDK::LoadVideo(const char *filename, double startDelay, bool32 (*skipCallback)())
22
{
23
if (ENGINE_VERSION == 5 && sceneInfo.state == ENGINESTATE_VIDEOPLAYBACK)
24
return false;
25
#if RETRO_REV0U
26
if (ENGINE_VERSION == 3 && RSDK::Legacy::gameMode == RSDK::Legacy::v3::ENGINE_VIDEOWAIT)
27
return false;
28
#endif
29
30
char fullFilePath[0x80];
31
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Video/%s", filename);
32
33
InitFileInfo(&VideoManager::file);
34
if (LoadFile(&VideoManager::file, fullFilePath, FMODE_RB)) {
35
// Init
36
ogg_sync_init(&VideoManager::oy);
37
38
th_comment_init(&VideoManager::tc);
39
th_info_init(&VideoManager::ti);
40
41
int32 theora_p = 0;
42
char *buffer = NULL;
43
44
// Parse header stuff
45
bool32 finishedHeader = false;
46
while (!finishedHeader) {
47
buffer = ogg_sync_buffer(&VideoManager::oy, 0x1000);
48
int32 ret = (int32)ReadBytes(&VideoManager::file, buffer, 0x1000);
49
ogg_sync_wrote(&VideoManager::oy, 0x1000);
50
51
if (ret == 0)
52
break;
53
54
while (ogg_sync_pageout(&VideoManager::oy, &VideoManager::og) > 0) {
55
ogg_stream_state test;
56
57
/* is this a mandated initial header? If not, stop parsing */
58
if (!ogg_page_bos(&VideoManager::og)) {
59
/* don't leak the page; get it into the appropriate stream */
60
ogg_stream_pagein(&VideoManager::to, &VideoManager::og);
61
finishedHeader = true;
62
break;
63
}
64
65
ogg_stream_init(&test, ogg_page_serialno(&VideoManager::og));
66
ogg_stream_pagein(&test, &VideoManager::og);
67
ogg_stream_packetout(&test, &VideoManager::op);
68
69
// identify codec
70
if (!theora_p && th_decode_headerin(&VideoManager::ti, &VideoManager::tc, &VideoManager::ts, &VideoManager::op) >= 0) {
71
// theora
72
memcpy(&VideoManager::to, &test, sizeof(test));
73
theora_p = 1;
74
}
75
else {
76
// we dont care (possibly vorbis)
77
ogg_stream_clear(&test);
78
}
79
}
80
}
81
82
if (theora_p) {
83
VideoManager::ts = NULL;
84
theora_p = 1;
85
while (theora_p && theora_p < 3) {
86
int32 ret;
87
88
while (theora_p && (theora_p < 3) && (ret = ogg_stream_packetout(&VideoManager::to, &VideoManager::op))) {
89
if (ret < 0) {
90
#if !RETRO_USE_ORIGINAL_CODE
91
PrintLog(PRINT_NORMAL, "ERROR: failed to parse theora stream headers. corrupted stream?");
92
#endif
93
94
theora_p = 0;
95
break;
96
}
97
98
if (!th_decode_headerin(&VideoManager::ti, &VideoManager::tc, &VideoManager::ts, &VideoManager::op)) {
99
#if !RETRO_USE_ORIGINAL_CODE
100
PrintLog(PRINT_NORMAL, "ERROR: failed to parse theora stream headers. corrupted stream?");
101
#endif
102
103
theora_p = 0;
104
break;
105
}
106
107
theora_p++;
108
}
109
110
if (!theora_p)
111
break;
112
113
/* The header pages/packets will arrive before anything else we
114
care about, or the stream is not obeying spec */
115
116
if (ogg_sync_pageout(&VideoManager::oy, &VideoManager::og) > 0) {
117
ogg_stream_pagein(&VideoManager::to, &VideoManager::og);
118
}
119
else {
120
buffer = ogg_sync_buffer(&VideoManager::oy, 0x1000);
121
int32 ret = (int32)ReadBytes(&VideoManager::file, buffer, 0x1000);
122
ogg_sync_wrote(&VideoManager::oy, 0x1000);
123
if (ret == 0) {
124
#if !RETRO_USE_ORIGINAL_CODE
125
PrintLog(PRINT_NORMAL, "ERROR: Reached end of file while searching for codec headers.");
126
#endif
127
128
theora_p = 0;
129
}
130
}
131
}
132
133
if (!theora_p) {
134
th_info_clear(&VideoManager::ti);
135
th_comment_clear(&VideoManager::tc);
136
th_setup_free(VideoManager::ts);
137
}
138
else {
139
VideoManager::td = th_decode_alloc(&VideoManager::ti, VideoManager::ts);
140
VideoManager::pixelFormat = VideoManager::ti.pixel_fmt;
141
142
int32 ppLevelMax = 0;
143
th_decode_ctl(VideoManager::td, TH_DECCTL_GET_PPLEVEL_MAX, &ppLevelMax, sizeof(int32));
144
int32 ppLevel = 0;
145
th_decode_ctl(VideoManager::td, TH_DECCTL_SET_PPLEVEL, &ppLevel, sizeof(int32));
146
147
th_setup_free(VideoManager::ts);
148
149
engine.storedShaderID = videoSettings.shaderID;
150
videoSettings.screenCount = 0;
151
152
if (ENGINE_VERSION == 5)
153
engine.storedState = sceneInfo.state;
154
#if RETRO_REV0U
155
else if (ENGINE_VERSION == 3)
156
engine.storedState = RSDK::Legacy::gameMode;
157
#endif
158
engine.displayTime = 0.0;
159
VideoManager::initializing = true;
160
VideoManager::granulePos = 0;
161
162
engine.displayTime = 0.0;
163
engine.videoStartDelay = 0.0;
164
if (AudioDevice::audioState == 1)
165
engine.videoStartDelay = startDelay;
166
167
switch (VideoManager::pixelFormat) {
168
default: break;
169
case TH_PF_420: videoSettings.shaderID = SHADER_YUV_420; break;
170
case TH_PF_422: videoSettings.shaderID = SHADER_YUV_422; break;
171
case TH_PF_444: videoSettings.shaderID = SHADER_YUV_444; break;
172
}
173
174
engine.skipCallback = NULL;
175
ProcessVideo();
176
engine.skipCallback = skipCallback;
177
178
changedVideoSettings = false;
179
if (ENGINE_VERSION == 5)
180
sceneInfo.state = ENGINESTATE_VIDEOPLAYBACK;
181
#if RETRO_REV0U
182
else if (ENGINE_VERSION == 3)
183
RSDK::Legacy::gameMode = RSDK::Legacy::v3::ENGINE_VIDEOWAIT;
184
#endif
185
186
return true;
187
}
188
}
189
190
CloseFile(&VideoManager::file);
191
}
192
193
return false;
194
}
195
196
void RSDK::ProcessVideo()
197
{
198
bool32 finished = false;
199
double curTime = 0;
200
if (!VideoManager::initializing) {
201
double streamPos = GetVideoStreamPos();
202
203
if (streamPos <= -1.0)
204
engine.displayTime += (1.0 / 60.0); // deltaTime frame-step
205
else
206
engine.displayTime = streamPos;
207
208
curTime = th_granule_time(VideoManager::td, VideoManager::granulePos);
209
210
#if RETRO_USE_MOD_LOADER
211
RunModCallbacks(MODCB_ONVIDEOSKIPCB, (void *)engine.skipCallback);
212
#endif
213
if (engine.skipCallback && engine.skipCallback()) {
214
finished = true;
215
}
216
}
217
218
if (!finished && (VideoManager::initializing || engine.displayTime >= engine.videoStartDelay + curTime)) {
219
while (ogg_stream_packetout(&VideoManager::to, &VideoManager::op) <= 0) {
220
char *buffer = ogg_sync_buffer(&VideoManager::oy, 0x1000);
221
// if we're playing and reached the end of file
222
if (!ReadBytes(&VideoManager::file, buffer, 0x1000) && !VideoManager::initializing) {
223
finished = true;
224
break;
225
}
226
227
ogg_sync_wrote(&VideoManager::oy, 0x1000);
228
229
while (ogg_sync_pageout(&VideoManager::oy, &VideoManager::og) > 0) ogg_stream_pagein(&VideoManager::to, &VideoManager::og);
230
}
231
232
if (!finished && !th_decode_packetin(VideoManager::td, &VideoManager::op, &VideoManager::granulePos)) {
233
th_ycbcr_buffer yuv;
234
th_decode_ycbcr_out(VideoManager::td, yuv);
235
236
int32 dataPos = (VideoManager::ti.pic_x & 0xFFFFFFFE) + (VideoManager::ti.pic_y & 0xFFFFFFFE) * yuv[0].stride;
237
switch (VideoManager::pixelFormat) {
238
default: break;
239
240
case TH_PF_444:
241
RenderDevice::SetupVideoTexture_YUV444(yuv[0].width, yuv[0].height, &yuv[0].data[dataPos], &yuv[1].data[dataPos],
242
&yuv[2].data[dataPos], yuv[0].stride, yuv[1].stride, yuv[2].stride);
243
break;
244
245
case TH_PF_422:
246
RenderDevice::SetupVideoTexture_YUV422(yuv[0].width, yuv[0].height, &yuv[0].data[dataPos],
247
&yuv[1].data[yuv[1].stride * VideoManager::ti.pic_y + (VideoManager::ti.pic_x >> 1)],
248
&yuv[2].data[yuv[1].stride * VideoManager::ti.pic_y + (VideoManager::ti.pic_x >> 1)],
249
yuv[0].stride, yuv[1].stride, yuv[2].stride);
250
break;
251
252
case TH_PF_420:
253
RenderDevice::SetupVideoTexture_YUV420(
254
yuv[0].width, yuv[0].height, &yuv[0].data[dataPos],
255
&yuv[1].data[yuv[1].stride * (VideoManager::ti.pic_y >> 1) + (VideoManager::ti.pic_x >> 1)],
256
&yuv[2].data[yuv[1].stride * (VideoManager::ti.pic_y >> 1) + (VideoManager::ti.pic_x >> 1)], yuv[0].stride, yuv[1].stride,
257
yuv[2].stride);
258
break;
259
}
260
}
261
262
VideoManager::initializing = false;
263
}
264
265
if (finished) {
266
CloseFile(&VideoManager::file);
267
268
// Flush everything out
269
while (ogg_sync_pageout(&VideoManager::oy, &VideoManager::og) > 0) ogg_stream_pagein(&VideoManager::to, &VideoManager::og);
270
271
ogg_stream_clear(&VideoManager::to);
272
th_decode_free(VideoManager::td);
273
th_comment_clear(&VideoManager::tc);
274
th_info_clear(&VideoManager::ti);
275
ogg_sync_clear(&VideoManager::oy);
276
277
videoSettings.shaderID = engine.storedShaderID;
278
videoSettings.screenCount = 1;
279
if (ENGINE_VERSION == 5)
280
sceneInfo.state = engine.storedState;
281
#if RETRO_REV0U
282
else if (ENGINE_VERSION == 3)
283
RSDK::Legacy::gameMode = engine.storedState;
284
#endif
285
}
286
}
287
288