1 // Copyright (c) 2012- PPSSPP Project.
2 
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6 
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License 2.0 for more details.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17 
18 #include <algorithm>
19 
20 #include "Common/Serialize/SerializeFuncs.h"
21 #include "Common/Serialize/SerializeMap.h"
22 #include "Core/HLE/HLE.h"
23 #include "Core/HLE/FunctionWrappers.h"
24 #include "Core/Reporting.h"
25 #include "Core/HLE/sceMp4.h"
26 #include "Core/HW/SimpleAudioDec.h"
27 
28 static std::map<u32, AuCtx*> aacMap;
29 
getAacCtx(u32 id)30 static AuCtx *getAacCtx(u32 id) {
31 	if (aacMap.find(id) == aacMap.end())
32 		return NULL;
33 	return aacMap[id];
34 }
35 
__AACShutdown()36 void __AACShutdown() {
37 	for (auto it = aacMap.begin(), end = aacMap.end(); it != end; it++) {
38 		delete it->second;
39 	}
40 	aacMap.clear();
41 }
42 
__AACDoState(PointerWrap & p)43 void __AACDoState(PointerWrap &p) {
44 	auto s = p.Section("sceAAC", 0, 1);
45 	if (!s)
46 		return;
47 
48 	Do(p, aacMap);
49 }
50 
sceMp4Init()51 static u32 sceMp4Init()
52 {
53 	INFO_LOG(ME, "sceMp4Init()");
54 	return 0;
55 }
56 
sceMp4Finish()57 static u32 sceMp4Finish()
58 {
59 	ERROR_LOG(ME, "UNIMPL sceMp4Finish()");
60 	return 0;
61 }
62 
sceMp4Create(u32 mp4,u32 unknown2,u32 readBufferAddr,u32 readBufferSize)63 static u32 sceMp4Create(u32 mp4, u32 unknown2, u32 readBufferAddr, u32 readBufferSize)
64 {
65 	ERROR_LOG_REPORT(ME, "UNIMPL sceMp4Create(mp4 %i,unknown2 %08x,readBufferAddr %08x,readBufferSize %i)", mp4, unknown2, readBufferAddr, readBufferSize);
66 	return 0;
67 }
68 
sceMp4GetNumberOfSpecificTrack()69 static u32 sceMp4GetNumberOfSpecificTrack()
70 {
71 	ERROR_LOG(ME, "UNIMPL sceMp4GetNumberOfSpecificTrack()");
72 	return 1;
73 }
74 
sceMp4GetMovieInfo(u32 mp4,u32 unknown2)75 static u32 sceMp4GetMovieInfo(u32 mp4, u32 unknown2)
76 {
77 	ERROR_LOG(ME, "UNIMPL sceMp4GetMovieInfo(mp4 %i, unknown2 %08x)",mp4, unknown2);
78 	return 0;
79 }
80 
sceMp4TrackSampleBufAvailableSize(u32 mp4,u32 trackAddr,u32 writableSamplesAddr,u32 writableBytesAddr)81 static u32 sceMp4TrackSampleBufAvailableSize(u32 mp4, u32 trackAddr, u32 writableSamplesAddr, u32 writableBytesAddr) {
82 	return hleLogError(ME, 0, "unimplemented");
83 }
84 
sceMp4Delete(u32 mp4)85 static u32 sceMp4Delete(u32 mp4) {
86 	return hleLogError(ME, 0, "unimplemented");
87 }
88 
sceMp4AacDecodeInitResource(int unknown)89 static u32 sceMp4AacDecodeInitResource(int unknown)
90 {
91 	ERROR_LOG(ME, "UNIMPL sceMp4AacDecodeInitResource(%i)",unknown);
92 	return 0;
93 }
94 
sceMp4InitAu(u32 mp4,u32 unknown2,u32 auAddr)95 static u32 sceMp4InitAu(u32 mp4, u32 unknown2, u32 auAddr)
96 {
97 	// unknown2 = return value of sceMpegAvcResourceGetAvcEsBuf()
98 	ERROR_LOG(ME, "UNIMPL sceMp4InitAu(mp4 %i,unknown2 %08x,auAddr %08x)", mp4, unknown2, auAddr);
99 	return 0;
100 }
101 
sceMp4GetAvcAu(u32 mp4,u32 unknown2,u32 auAddr,u32 unknown4)102 static u32 sceMp4GetAvcAu(u32 mp4, u32 unknown2, u32 auAddr, u32 unknown4)
103 {
104 	// unknown2 = return value of sceMpegAvcResourceGetAvcEsBuf()
105 	ERROR_LOG(ME, "UNIMPL sceMp4InitAu(mp4 %i,unknown2 %08x,auAddr %08x,unknown4 %08x)", mp4, unknown2, auAddr, unknown4);
106 	return 0;
107 }
108 
109 
sceMp4GetAvcTrackInfoData()110 static u32 sceMp4GetAvcTrackInfoData()
111 {
112 	ERROR_LOG(ME, "UNIMPL sceMp4GetAvcTrackInfoData()");
113 	return 0;
114 }
115 
sceMp4TrackSampleBufConstruct(u32 mp4,u32 unknown2,u32 unknown3,u32 unknown4,u32 unknown5,u32 unknown6,u32 unknown7)116 static u32 sceMp4TrackSampleBufConstruct(u32 mp4, u32 unknown2, u32 unknown3, u32 unknown4, u32 unknown5, u32 unknown6, u32 unknown7)
117 {
118 	// unknown4 == value returned by sceMp4_BCA9389C
119 	ERROR_LOG(ME, "UNIMPL sceMp4TrackSampleBufConstruct(mp4 %i,unknown2 %08x,unknown3 %08x, unknown4 %08x, unknown5 %08x, unknown6 %08x, unknown7 %08x)", mp4, unknown2, unknown3, unknown4, unknown5, unknown6, unknown7);
120 	return 0;
121 }
122 
sceMp4TrackSampleBufQueryMemSize(u32 unknown1,u32 unknown2,u32 unknown3,u32 unknown4,u32 unknown5)123 static u32 sceMp4TrackSampleBufQueryMemSize(u32 unknown1, u32 unknown2, u32 unknown3, u32 unknown4, u32 unknown5)
124 {
125 	u32 value = std::max(unknown2 * unknown3, unknown4 << 1) + (unknown2 << 6) + unknown5 + 256;
126 	ERROR_LOG(ME, "sceMp4TrackSampleBufQueryMemSize return %i",value);
127 	return value;
128 }
129 
sceMp4AacDecode(u32 mp4,u32 auAddr,u32 bufferAddr,u32 init,u32 frequency)130 static u32 sceMp4AacDecode(u32 mp4, u32 auAddr, u32 bufferAddr, u32 init, u32 frequency)
131 {
132 	// Decode audio:
133 	// - init: 1 at first call, 0 afterwards
134 	// - frequency: 44100
135 	ERROR_LOG(ME, "sceMp4AacDecode(mp4 %i,auAddr %08x,bufferAddr %08x,init %i,frequency %i ", mp4, auAddr, bufferAddr, init, frequency);
136 	return 0;
137 	//This is hack
138 	//return -1;
139 }
140 
sceMp4GetAacAu(u32 mp4,u32 unknown2,u32 auAddr,u32 unknown4)141 static u32 sceMp4GetAacAu(u32 mp4, u32 unknown2, u32 auAddr, u32 unknown4)
142 {
143 	// unknown4: pointer to a 40-bytes structure
144 	ERROR_LOG(ME, "sceMp4GetAacAu(mp4 %i,unknown2 %08x,auAddr %08x,unknown4 %i ", mp4, unknown2, auAddr, unknown4);
145 	return 0;
146 }
147 
sceMp4GetSampleInfo()148 static u32 sceMp4GetSampleInfo()
149 {
150 	ERROR_LOG(ME, "UNIMPL sceMp4GetSampleInfo()");
151 	return 0;
152 }
153 
sceMp4GetSampleNumWithTimeStamp()154 static u32 sceMp4GetSampleNumWithTimeStamp()
155 {
156 	ERROR_LOG(ME, "UNIMPL sceMp4GetSampleNumWithTimeStamp()");
157 	return 0;
158 }
159 
sceMp4TrackSampleBufFlush()160 static u32 sceMp4TrackSampleBufFlush()
161 {
162 	ERROR_LOG(ME, "UNIMPL sceMp4TrackSampleBufFlush()");
163 	return 0;
164 }
165 
sceMp4AacDecodeInit(int unknown)166 static u32 sceMp4AacDecodeInit(int unknown)
167 {
168 	ERROR_LOG(ME, "UNIMPL sceMp4AacDecodeInit(%i)",unknown);
169 	return 0;
170 }
171 
sceMp4GetAacTrackInfoData()172 static u32 sceMp4GetAacTrackInfoData()
173 {
174 	ERROR_LOG(ME, "UNIMPL sceMp4GetAacTrackInfoData()");
175 	return 0;
176 }
177 
sceMp4GetNumberOfMetaData()178 static u32 sceMp4GetNumberOfMetaData()
179 {
180 	ERROR_LOG(ME, "UNIMPL sceMp4GetNumberOfMetaData()");
181 	return 0;
182 }
183 
sceMp4RegistTrack(u32 mp4,u32 unknown2,u32 unknown3,u32 callbacks,u32 unknown5)184 static u32 sceMp4RegistTrack(u32 mp4, u32 unknown2, u32 unknown3, u32 callbacks, u32 unknown5)
185 {
186 	ERROR_LOG(ME, "UNIMPL sceMp4RegistTrack(mp4 %i,unknown2 %i,unknown3 %i,callbacks %i unknown5 %i)",mp4,unknown2,unknown3,callbacks,unknown5);
187 	return 0;
188 }
189 
sceMp4SearchSyncSampleNum()190 static u32 sceMp4SearchSyncSampleNum()
191 {
192 	ERROR_LOG(ME, "UNIMPL sceMp4SearchSyncSampleNum()");
193 	return 0;
194 }
195 
196 
197 // sceAac module starts from here
198 
sceAacExit(u32 id)199 static u32 sceAacExit(u32 id)
200 {
201 	INFO_LOG(ME, "sceAacExit(id %i)", id);
202 	if (aacMap.find(id) != aacMap.end()) {
203 		delete aacMap[id];
204 		aacMap.erase(id);
205 	}
206 	else{
207 		ERROR_LOG(ME, "%s: bad aac id %08x", __FUNCTION__, id);
208 		return -1;
209 	}
210 	return 0;
211 }
212 
sceAacInit(u32 id)213 static u32 sceAacInit(u32 id)
214 {
215 	INFO_LOG(ME, "UNIMPL sceAacInit(%08x)", id);
216 	if (!Memory::IsValidAddress(id)){
217 		ERROR_LOG(ME, "sceAacInit() AAC Invalid id address %08x", id);
218 		return ERROR_AAC_INVALID_ADDRESS;
219 	}
220 
221 	AuCtx *aac = new AuCtx();
222 	aac->startPos = Memory::Read_U64(id);				// Audio stream start position.
223 	aac->endPos = Memory::Read_U32(id + 8);				// Audio stream end position.
224 	aac->AuBuf = Memory::Read_U32(id + 16);             // Input AAC data buffer.
225 	aac->AuBufSize = Memory::Read_U32(id + 20);         // Input AAC data buffer size.
226 	aac->PCMBuf = Memory::Read_U32(id + 24);            // Output PCM data buffer.
227 	aac->PCMBufSize = Memory::Read_U32(id + 28);        // Output PCM data buffer size.
228 	aac->freq = Memory::Read_U32(id + 32);              // Frequency.
229 	if (aac->AuBuf == 0 || aac->PCMBuf == 0) {
230 		ERROR_LOG(ME, "sceAacInit() AAC INVALID ADDRESS AuBuf %08x PCMBuf %08x", aac->AuBuf, aac->PCMBuf);
231 		delete aac;
232 		return ERROR_AAC_INVALID_ADDRESS;
233 	}
234 	if (aac->startPos > aac->endPos) {
235 		ERROR_LOG(ME, "sceAacInit() AAC INVALID startPos %lli endPos %lli", aac->startPos, aac->endPos);
236 		delete aac;
237 		return ERROR_AAC_INVALID_PARAMETER;
238 	}
239 	if (aac->AuBufSize < 8192 || aac->PCMBufSize < 8192) {
240 		ERROR_LOG(ME, "sceAacInit() AAC INVALID PARAMETER, bufferSize %i outputSize %i", aac->AuBufSize, aac->PCMBufSize);
241 		delete aac;
242 		return ERROR_AAC_INVALID_PARAMETER;
243 	}
244 	if (aac->freq != 24000 && aac->freq != 32000 && aac->freq != 44100 && aac->freq != 48000) {
245 		ERROR_LOG(ME, "sceAacInit() AAC INVALID freq %i", aac->freq);
246 		delete aac;
247 		return ERROR_AAC_INVALID_PARAMETER;
248 	}
249 
250 	DEBUG_LOG(ME, "startPos %llx endPos %llx AuBuf %08x AuBufSize %08x PCMbuf %08x PCMbufSize %08x freq %d",
251 		aac->startPos, aac->endPos, aac->AuBuf, aac->AuBufSize, aac->PCMBuf, aac->PCMBufSize, aac->freq);
252 
253 	aac->Channels = 2;
254 	aac->MaxOutputSample = aac->PCMBufSize / 4;
255 	aac->readPos = aac->startPos;
256 	aac->audioType = PSP_CODEC_AAC;
257 
258 	// create aac decoder
259 	aac->decoder = new SimpleAudio(aac->audioType);
260 
261 	// close the audio if id already exist.
262 	if (aacMap.find(id) != aacMap.end()) {
263 		delete aacMap[id];
264 		aacMap.erase(id);
265 	}
266 	aacMap[id] = aac;
267 
268 	return id;
269 }
270 
sceAacInitResource(u32 numberIds)271 static u32 sceAacInitResource(u32 numberIds)
272 {
273 	// Do nothing here
274 	INFO_LOG_REPORT(ME, "sceAacInitResource(%i)", numberIds);
275 	return 0;
276 }
277 
sceAacTermResource()278 static u32 sceAacTermResource()
279 {
280 	ERROR_LOG(ME, "UNIMPL sceAacTermResource()");
281 	return 0;
282 }
283 
sceAacDecode(u32 id,u32 pcmAddr)284 static u32 sceAacDecode(u32 id, u32 pcmAddr)
285 {
286 	// return the size of output pcm, <0 error
287 	DEBUG_LOG(ME, "sceAacDecode(id %i, bufferAddress %08x)", id, pcmAddr);
288 	auto ctx = getAacCtx(id);
289 	if (!ctx) {
290 		ERROR_LOG(ME, "%s: bad aac id %08x", __FUNCTION__, id);
291 		return -1;
292 	}
293 
294 	return ctx->AuDecode(pcmAddr);
295 }
296 
sceAacGetLoopNum(u32 id)297 static u32 sceAacGetLoopNum(u32 id)
298 {
299 	INFO_LOG(ME, "sceAacGetLoopNum(id %i)", id);
300 	auto ctx = getAacCtx(id);
301 	if (!ctx) {
302 		ERROR_LOG(ME, "%s: bad aac id %08x", __FUNCTION__, id);
303 		return -1;
304 	}
305 	return ctx->AuGetLoopNum();
306 }
307 
sceAacSetLoopNum(u32 id,int loop)308 static u32 sceAacSetLoopNum(u32 id, int loop)
309 {
310 	INFO_LOG(ME, "sceAacSetLoopNum(id %i,loop %d)", id, loop);
311 	auto ctx = getAacCtx(id);
312 	if (!ctx) {
313 		ERROR_LOG(ME, "%s: bad aac id %08x", __FUNCTION__, id);
314 		return -1;
315 	}
316 
317 	return ctx->AuSetLoopNum(loop);
318 }
319 
sceAacCheckStreamDataNeeded(u32 id)320 static int sceAacCheckStreamDataNeeded(u32 id)
321 {
322 	// return 1 to read more data stream, 0 don't read, <0 error
323 	DEBUG_LOG(ME, "sceAacCheckStreamDataNeeded(%i)", id);
324 
325 	auto ctx = getAacCtx(id);
326 	if (!ctx) {
327 		ERROR_LOG(ME, "%s: bad aac id %08x", __FUNCTION__, id);
328 		return -1;
329 	}
330 
331 	return ctx->AuCheckStreamDataNeeded();
332 }
333 
sceAacNotifyAddStreamData(u32 id,int size)334 static u32 sceAacNotifyAddStreamData(u32 id, int size)
335 {
336 	// check how many bytes we have read from source file
337 	DEBUG_LOG(ME, "sceAacNotifyAddStreamData(%i, %08x)", id, size);
338 
339 	auto ctx = getAacCtx(id);
340 	if (!ctx) {
341 		ERROR_LOG(ME, "%s: bad aac id %08x", __FUNCTION__, id);
342 		return -1;
343 	}
344 
345 	return ctx->AuNotifyAddStreamData(size);
346 }
347 
sceAacGetInfoToAddStreamData(u32 id,u32 buff,u32 size,u32 srcPos)348 static u32 sceAacGetInfoToAddStreamData(u32 id, u32 buff, u32 size, u32 srcPos)
349 {
350 	// read from stream position srcPos of size bytes into buff
351 	DEBUG_LOG(ME, "sceAacGetInfoToAddStreamData(%08X, %08X, %08X, %08X)", id, buff, size, srcPos);
352 
353 	auto ctx = getAacCtx(id);
354 	if (!ctx) {
355 		ERROR_LOG(ME, "%s: bad aac handle %08x", __FUNCTION__, id);
356 		return -1;
357 	}
358 
359 	return ctx->AuGetInfoToAddStreamData(buff, size, srcPos);
360 }
361 
sceAacGetMaxOutputSample(u32 id)362 static u32 sceAacGetMaxOutputSample(u32 id)
363 {
364 	DEBUG_LOG(ME, "sceAacGetMaxOutputSample(id %i)", id);
365 	auto ctx = getAacCtx(id);
366 	if (!ctx) {
367 		ERROR_LOG(ME, "%s: bad aac id %08x", __FUNCTION__, id);
368 		return -1;
369 	}
370 
371 	return ctx->AuGetMaxOutputSample();
372 }
373 
sceAacGetSumDecodedSample(u32 id)374 static u32 sceAacGetSumDecodedSample(u32 id)
375 {
376 	DEBUG_LOG(ME, "sceAacGetSumDecodedSample(id %i)", id);
377 	auto ctx = getAacCtx(id);
378 	if (!ctx) {
379 		ERROR_LOG(ME, "%s: bad aac id %08x", __FUNCTION__, id);
380 		return -1;
381 	}
382 
383 	return ctx->AuGetSumDecodedSample();
384 }
385 
sceAacResetPlayPosition(u32 id)386 static u32 sceAacResetPlayPosition(u32 id)
387 {
388 	INFO_LOG(ME, "sceAacResetPlayPosition(id %i)", id);
389 	auto ctx = getAacCtx(id);
390 	if (!ctx) {
391 		ERROR_LOG(ME, "%s: bad aac id %08x", __FUNCTION__, id);
392 		return -1;
393 	}
394 
395 	return ctx->AuResetPlayPosition();
396 }
397 
398 const HLEFunction sceMp4[] =
399 {
400 	{0X68651CBC, &WrapU_V<sceMp4Init>,                           "sceMp4Init",                        'x', ""       },
401 	{0X9042B257, &WrapU_V<sceMp4Finish>,                         "sceMp4Finish",                      'x', ""       },
402 	{0XB1221EE7, &WrapU_UUUU<sceMp4Create>,                      "sceMp4Create",                      'x', "xxxx"   },
403 	{0X538C2057, &WrapU_U<sceMp4Delete>,                         "sceMp4Delete",                      'x', "x"      },
404 	{0X113E9E7B, &WrapU_V<sceMp4GetNumberOfMetaData>,            "sceMp4GetNumberOfMetaData",         'x', ""       },
405 	{0X7443AF1D, &WrapU_UU<sceMp4GetMovieInfo>,                  "sceMp4GetMovieInfo",                'x', "xx"     },
406 	{0X5EB65F26, &WrapU_V<sceMp4GetNumberOfSpecificTrack>,       "sceMp4GetNumberOfSpecificTrack",    'x', ""       },
407 	{0X7ADFD01C, &WrapU_UUUUU<sceMp4RegistTrack>,                "sceMp4RegistTrack",                 'x', "xxxxx"  },
408 	{0XBCA9389C, &WrapU_UUUUU<sceMp4TrackSampleBufQueryMemSize>, "sceMp4TrackSampleBufQueryMemSize",  'x', "xxxxx"  },
409 	{0X9C8F4FC1, &WrapU_UUUUUUU<sceMp4TrackSampleBufConstruct>,  "sceMp4TrackSampleBufConstruct",     'x', "xxxxxxx"},
410 	{0X0F0187D2, &WrapU_V<sceMp4GetAvcTrackInfoData>,            "sceMp4GetAvcTrackInfoData",         'x', ""       },
411 	{0X9CE6F5CF, &WrapU_V<sceMp4GetAacTrackInfoData>,            "sceMp4GetAacTrackInfoData",         'x', ""       },
412 	{0X4ED4AB1E, &WrapU_I<sceMp4AacDecodeInitResource>,          "sceMp4AacDecodeInitResource",       'x', "i"      },
413 	{0X10EE0D2C, &WrapU_I<sceMp4AacDecodeInit>,                  "sceMp4AacDecodeInit",               'x', "i"      },
414 	{0X496E8A65, &WrapU_V<sceMp4TrackSampleBufFlush>,            "sceMp4TrackSampleBufFlush",         'x', ""       },
415 	{0XB4B400D1, &WrapU_V<sceMp4GetSampleNumWithTimeStamp>,      "sceMp4GetSampleNumWithTimeStamp",   'x', ""       },
416 	{0XF7C51EC1, &WrapU_V<sceMp4GetSampleInfo>,                  "sceMp4GetSampleInfo",               'x', ""       },
417 	{0X74A1CA3E, &WrapU_V<sceMp4SearchSyncSampleNum>,            "sceMp4SearchSyncSampleNum",         'x', ""       },
418 	{0XD8250B75, nullptr,                                        "sceMp4PutSampleNum",                '?', ""       },
419 	{0X8754ECB8, &WrapU_UUUU<sceMp4TrackSampleBufAvailableSize>, "sceMp4TrackSampleBufAvailableSize", 'x', "xppp"   },
420 	{0X31BCD7E0, nullptr,                                        "sceMp4TrackSampleBufPut",           '?', ""       },
421 	{0X5601A6F0, &WrapU_UUUU<sceMp4GetAacAu>,                    "sceMp4GetAacAu",                    'x', "xxxx"   },
422 	{0X7663CB5C, &WrapU_UUUUU<sceMp4AacDecode>,                  "sceMp4AacDecode",                   'x', "xxxxx"  },
423 	{0X503A3CBA, &WrapU_UUUU<sceMp4GetAvcAu>,                    "sceMp4GetAvcAu",                    'x', "xxxx"   },
424 	{0X01C76489, nullptr,                                        "sceMp4TrackSampleBufDestruct",      '?', ""       },
425 	{0X6710FE77, nullptr,                                        "sceMp4UnregistTrack",               '?', ""       },
426 	{0X5D72B333, nullptr,                                        "sceMp4AacDecodeExit",               '?', ""       },
427 	{0X7D332394, nullptr,                                        "sceMp4AacDecodeTermResource",       '?', ""       },
428 	{0X131BDE57, &WrapU_UUU<sceMp4InitAu>,                       "sceMp4InitAu",                      'x', "xxx"    },
429 	{0X17EAA97D, nullptr,                                        "sceMp4GetAvcAuWithoutSampleBuf",    '?', ""       },
430 	{0X28CCB940, nullptr,                                        "sceMp4GetTrackEditList",            '?', ""       },
431 	{0X3069C2B5, nullptr,                                        "sceMp4GetAvcParamSet",              '?', ""       },
432 	{0XD2AC9A7E, nullptr,                                        "sceMp4GetMetaData",                 '?', ""       },
433 	{0X4FB5B756, nullptr,                                        "sceMp4GetMetaDataInfo",             '?', ""       },
434 	{0X427BEF7F, nullptr,                                        "sceMp4GetTrackNumOfEditList",       '?', ""       },
435 	{0X532029B8, nullptr,                                        "sceMp4GetAacAuWithoutSampleBuf",    '?', ""       },
436 	{0XA6C724DC, nullptr,                                        "sceMp4GetSampleNum",                '?', ""       },
437 	{0X3C2183C7, nullptr,                                        "mp4msv_3C2183C7",                   '?', ""       },
438 	{0X9CA13D1A, nullptr,                                        "mp4msv_9CA13D1A",                   '?', ""       },
439 };
440 
441 // 395
442 const HLEFunction sceAac[] = {
443 	{0XE0C89ACA, &WrapU_U<sceAacInit>,                           "sceAacInit",                        'x', "x"      },
444 	{0X33B8C009, &WrapU_U<sceAacExit>,                           "sceAacExit",                        'x', "x"      },
445 	{0X5CFFC57C, &WrapU_U<sceAacInitResource>,                   "sceAacInitResource",                'x', "x"      },
446 	{0X23D35CAE, &WrapU_V<sceAacTermResource>,                   "sceAacTermResource",                'x', ""       },
447 	{0X7E4CFEE4, &WrapU_UU<sceAacDecode>,                        "sceAacDecode",                      'x', "xx"     },
448 	{0X523347D9, &WrapU_U<sceAacGetLoopNum>,                     "sceAacGetLoopNum",                  'x', "x"      },
449 	{0XBBDD6403, &WrapU_UI<sceAacSetLoopNum>,                    "sceAacSetLoopNum",                  'x', "xi"     },
450 	{0XD7C51541, &WrapI_U<sceAacCheckStreamDataNeeded>,          "sceAacCheckStreamDataNeeded",       'i', "x"      },
451 	{0XAC6DCBE3, &WrapU_UI<sceAacNotifyAddStreamData>,           "sceAacNotifyAddStreamData",         'x', "xi"     },
452 	{0X02098C69, &WrapU_UUUU<sceAacGetInfoToAddStreamData>,      "sceAacGetInfoToAddStreamData",      'x', "xxxx"   },
453 	{0X6DC7758A, &WrapU_U<sceAacGetMaxOutputSample>,             "sceAacGetMaxOutputSample",          'x', "x"      },
454 	{0X506BF66C, &WrapU_U<sceAacGetSumDecodedSample>,            "sceAacGetSumDecodedSample",         'x', "x"      },
455 	{0XD2DA2BBA, &WrapU_U<sceAacResetPlayPosition>,              "sceAacResetPlayPosition",           'x', "x"      },
456 };
457 
Register_sceMp4()458 void Register_sceMp4()
459 {
460 	RegisterModule("sceMp4", ARRAY_SIZE(sceMp4), sceMp4);
461 	RegisterModule("sceAac", ARRAY_SIZE(sceAac), sceAac);
462 }
463