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 <map>
19 #include <algorithm>
20 
21 #include "Core/Config.h"
22 #include "Core/Debugger/MemBlockInfo.h"
23 #include "Core/HLE/HLE.h"
24 #include "Core/HLE/FunctionWrappers.h"
25 #include "Core/HLE/sceKernelMemory.h"
26 #include "Core/HLE/sceMp3.h"
27 #include "Core/HW/MediaEngine.h"
28 #include "Core/HW/SimpleAudioDec.h"
29 #include "Core/MemMap.h"
30 #include "Core/Reporting.h"
31 #include "Common/Serialize/SerializeFuncs.h"
32 #include "Common/Serialize/SerializeMap.h"
33 
34 static const u32 ERROR_MP3_INVALID_HANDLE = 0x80671001;
35 static const u32 ERROR_MP3_UNRESERVED_HANDLE = 0x80671102;
36 static const u32 ERROR_MP3_NOT_YET_INIT_HANDLE = 0x80671103;
37 static const u32 ERROR_MP3_NO_RESOURCE_AVAIL = 0x80671201;
38 static const u32 ERROR_MP3_BAD_SAMPLE_RATE = 0x80671302;
39 static const u32 ERROR_MP3_BAD_RESET_FRAME = 0x80671501;
40 static const u32 ERROR_MP3_BAD_ADDR = 0x80671002;
41 static const u32 ERROR_MP3_BAD_SIZE = 0x80671003;
42 static const u32 ERROR_AVCODEC_INVALID_DATA = 0x807f00fd;
43 static const int AU_BUF_MIN_SIZE = 8192;
44 static const int PCM_BUF_MIN_SIZE = 9216;
45 static const size_t MP3_MAX_HANDLES = 2;
46 
47 struct Mp3Context {
48 public:
49 
50 	int mp3StreamStart;
51 	int mp3StreamEnd;
52 	u32 mp3Buf;
53 	int mp3BufSize;
54 	u32 mp3PcmBuf;
55 	int mp3PcmBufSize;
56 
57 	int readPosition;
58 
59 	int bufferRead;
60 	int bufferWrite;
61 	int bufferAvailable;
62 
63 	int mp3DecodedBytes;
64 	int mp3LoopNum;
65 	int mp3MaxSamples;
66 	int mp3SumDecodedSamples;
67 
68 	int mp3Channels;
69 	int mp3Bitrate;
70 	int mp3SamplingRate;
71 	int mp3Version;
72 
DoStateMp3Context73 	void DoState(PointerWrap &p) {
74 		auto s = p.Section("Mp3Context", 1);
75 		if (!s)
76 			return;
77 
78 		Do(p, mp3StreamStart);
79 		Do(p, mp3StreamEnd);
80 		Do(p, mp3Buf);
81 		Do(p, mp3BufSize);
82 		Do(p, mp3PcmBuf);
83 		Do(p, mp3PcmBufSize);
84 		Do(p, readPosition);
85 		Do(p, bufferRead);
86 		Do(p, bufferWrite);
87 		Do(p, bufferAvailable);
88 		Do(p, mp3DecodedBytes);
89 		Do(p, mp3LoopNum);
90 		Do(p, mp3MaxSamples);
91 		Do(p, mp3SumDecodedSamples);
92 		Do(p, mp3Channels);
93 		Do(p, mp3Bitrate);
94 		Do(p, mp3SamplingRate);
95 		Do(p, mp3Version);
96 	};
97 };
98 
99 static std::map<u32, AuCtx *> mp3Map;
100 static const int mp3DecodeDelay = 2400;
101 static bool resourceInited = false;
102 
getMp3Ctx(u32 mp3)103 static AuCtx *getMp3Ctx(u32 mp3) {
104 	if (mp3Map.find(mp3) == mp3Map.end())
105 		return NULL;
106 	return mp3Map[mp3];
107 }
108 
__Mp3Shutdown()109 void __Mp3Shutdown() {
110 	for (auto it = mp3Map.begin(), end = mp3Map.end(); it != end; ++it) {
111 		delete it->second;
112 	}
113 	mp3Map.clear();
114 }
115 
__Mp3DoState(PointerWrap & p)116 void __Mp3DoState(PointerWrap &p) {
117 	auto s = p.Section("sceMp3", 0, 3);
118 	if (!s)
119 		return;
120 
121 	if (s >= 2) {
122 		Do(p, mp3Map);
123 	} else {
124 		std::map<u32, Mp3Context *> mp3Map_old;
125 		Do(p, mp3Map_old); // read old map
126 		for (auto it = mp3Map_old.begin(), end = mp3Map_old.end(); it != end; ++it) {
127 			auto mp3 = new AuCtx;
128 			u32 id = it->first;
129 			auto mp3_old = it->second;
130 			mp3->AuBuf = mp3_old->mp3Buf;
131 			mp3->AuBufSize = mp3_old->mp3BufSize;
132 			mp3->PCMBuf = mp3_old->mp3PcmBuf;
133 			mp3->PCMBufSize = mp3_old->mp3PcmBufSize;
134 			mp3->BitRate = mp3_old->mp3Bitrate;
135 			mp3->Channels = mp3_old->mp3Channels;
136 			mp3->endPos = mp3_old->mp3StreamEnd;
137 			mp3->startPos = mp3_old->mp3StreamStart;
138 			mp3->LoopNum = mp3_old->mp3LoopNum;
139 			mp3->SamplingRate = mp3_old->mp3SamplingRate;
140 			mp3->freq = mp3->SamplingRate;
141 			mp3->SumDecodedSamples = mp3_old->mp3SumDecodedSamples;
142 			mp3->Version = mp3_old->mp3Version;
143 			mp3->MaxOutputSample = mp3_old->mp3MaxSamples;
144 			mp3->readPos = mp3_old->readPosition;
145 			mp3->AuBufAvailable = 0; // reset to read from file
146 			mp3->askedReadSize = 0;
147 
148 			mp3->audioType = PSP_CODEC_MP3;
149 			mp3->decoder = new SimpleAudio(mp3->audioType);
150 			mp3Map[id] = mp3;
151 		}
152 	}
153 
154 	if (s >= 3) {
155 		Do(p, resourceInited);
156 	} else {
157 		// Previous behavior acted as if it was already inited.
158 		resourceInited = true;
159 	}
160 }
161 
sceMp3Decode(u32 mp3,u32 outPcmPtr)162 static int sceMp3Decode(u32 mp3, u32 outPcmPtr) {
163 	AuCtx *ctx = getMp3Ctx(mp3);
164 	if (!ctx) {
165 		if (mp3 >= MP3_MAX_HANDLES)
166 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
167 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "unreserved handle");
168 	} else if (ctx->Version < 0 || ctx->AuBuf == 0) {
169 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "not yet init");
170 	}
171 
172 	int pcmBytes = ctx->AuDecode(outPcmPtr);
173 	if (pcmBytes > 0) {
174 		// decode data successfully, delay thread
175 		return hleDelayResult(hleLogSuccessI(ME, pcmBytes), "mp3 decode", mp3DecodeDelay);
176 	}
177 	// Should already have logged.
178 	return pcmBytes;
179 }
180 
sceMp3ResetPlayPosition(u32 mp3)181 static int sceMp3ResetPlayPosition(u32 mp3) {
182 	AuCtx *ctx = getMp3Ctx(mp3);
183 	if (!ctx) {
184 		if (mp3 >= MP3_MAX_HANDLES)
185 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
186 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "unreserved handle");
187 	} else if (ctx->Version < 0 || ctx->AuBuf == 0) {
188 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "not yet init");
189 	}
190 
191 	return hleLogSuccessI(ME, ctx->AuResetPlayPosition());
192 }
193 
sceMp3CheckStreamDataNeeded(u32 mp3)194 static int sceMp3CheckStreamDataNeeded(u32 mp3) {
195 	AuCtx *ctx = getMp3Ctx(mp3);
196 	if (!ctx) {
197 		if (mp3 >= MP3_MAX_HANDLES)
198 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
199 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "unreserved handle");
200 	} else if (ctx->AuBuf == 0) {
201 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "incorrect handle type");
202 	}
203 
204 	return hleLogSuccessI(ME, ctx->AuCheckStreamDataNeeded());
205 }
206 
sceMp3ReserveMp3Handle(u32 mp3Addr)207 static u32 sceMp3ReserveMp3Handle(u32 mp3Addr) {
208 	if (!resourceInited) {
209 		return hleLogError(ME, ERROR_MP3_NO_RESOURCE_AVAIL, "sceMp3InitResource must be called first");
210 	}
211 	if (mp3Map.size() >= MP3_MAX_HANDLES) {
212 		return hleLogError(ME, ERROR_MP3_NO_RESOURCE_AVAIL, "no free handles");
213 	}
214 	if (mp3Addr != 0 && !Memory::IsValidRange(mp3Addr, 32)) {
215 		// The PSP would crash, but might as well return a proper error.
216 		return hleLogError(ME, SCE_KERNEL_ERROR_INVALID_POINTER, "bad mp3 pointer");
217 	}
218 
219 	AuCtx *Au = new AuCtx;
220 	if (mp3Addr) {
221 		Au->startPos = Memory::Read_U64(mp3Addr); // Audio stream start position.
222 		Au->endPos = Memory::Read_U64(mp3Addr + 8); // Audio stream end position.
223 		Au->AuBuf = Memory::Read_U32(mp3Addr + 16); // Input Au data buffer.
224 		Au->AuBufSize = Memory::Read_U32(mp3Addr + 20); // Input Au data buffer size.
225 		Au->PCMBuf = Memory::Read_U32(mp3Addr + 24); // Output PCM data buffer.
226 		Au->PCMBufSize = Memory::Read_U32(mp3Addr + 28); // Output PCM data buffer size.
227 
228 		if (Au->startPos >= Au->endPos) {
229 			delete Au;
230 			return hleLogError(ME, ERROR_MP3_BAD_SIZE, "start must be before end");
231 		}
232 		if (!Au->AuBuf || !Au->PCMBuf) {
233 			delete Au;
234 			return hleLogError(ME, ERROR_MP3_BAD_ADDR, "invalid buffer addresses");
235 		}
236 		if ((int)Au->AuBufSize < AU_BUF_MIN_SIZE || (int)Au->PCMBufSize < PCM_BUF_MIN_SIZE) {
237 			delete Au;
238 			return hleLogError(ME, ERROR_MP3_BAD_SIZE, "buffers too small");
239 		}
240 
241 		DEBUG_LOG(ME, "startPos %llx endPos %llx mp3buf %08x mp3bufSize %08x PCMbuf %08x PCMbufSize %08x",
242 			Au->startPos, Au->endPos, Au->AuBuf, Au->AuBufSize, Au->PCMBuf, Au->PCMBufSize);
243 	} else {
244 		Au->startPos = 0;
245 		Au->endPos = 0;
246 		Au->AuBuf = 0;
247 		Au->AuBufSize = 0;
248 		Au->PCMBuf = 0;
249 		Au->PCMBufSize = 0;
250 	}
251 
252 	Au->SumDecodedSamples = 0;
253 	Au->LoopNum = -1;
254 	Au->AuBufAvailable = 0;
255 	Au->readPos = Au->startPos;
256 
257 	Au->audioType = PSP_CODEC_MP3;
258 	Au->decoder = new SimpleAudio(Au->audioType);
259 
260 	int handle = (int)mp3Map.size();
261 	mp3Map[handle] = Au;
262 
263 	return hleLogSuccessI(ME, handle);
264 }
265 
sceMp3InitResource()266 static int sceMp3InitResource() {
267 	// TODO: Could validate the utility modules have been loaded?
268 	if (resourceInited) {
269 		return hleLogSuccessI(ME, 0);
270 	}
271 	resourceInited = true;
272 	return hleLogSuccessI(ME, hleDelayResult(0, "mp3 resource init", 200));
273 }
274 
sceMp3TermResource()275 static int sceMp3TermResource() {
276 	if (!resourceInited) {
277 		return hleLogSuccessI(ME, 0);
278 	}
279 
280 	// Free any handles that are still open.
281 	for (auto au : mp3Map) {
282 		delete au.second;
283 	}
284 	mp3Map.clear();
285 
286 	resourceInited = false;
287 	return hleLogSuccessI(ME, hleDelayResult(0, "mp3 resource term", 100));
288 }
289 
__CalculateMp3Channels(int bitval)290 static int __CalculateMp3Channels(int bitval) {
291 	if (bitval == 0 || bitval == 1 || bitval == 2) { // Stereo / Joint Stereo / Dual Channel.
292 		return 2;
293 	}
294 	else if (bitval == 3) { // Mono.
295 		return 1;
296 	}
297 	else {
298 		return -1;
299 	}
300 }
301 
__CalculateMp3SampleRates(int bitval,int mp3version)302 static int __CalculateMp3SampleRates(int bitval, int mp3version) {
303 	if (mp3version == 3) { // MPEG Version 1
304 		int valuemapping[] = { 44100, 48000, 32000, -1 };
305 		return valuemapping[bitval];
306 	}
307 	else if (mp3version == 2) { // MPEG Version 2
308 		int valuemapping[] = { 22050, 24000, 16000, -1 };
309 		return valuemapping[bitval];
310 	}
311 	else if (mp3version == 0) { // MPEG Version 2.5
312 		int valuemapping[] = { 11025, 12000, 8000, -1 };
313 		return valuemapping[bitval];
314 	}
315 	else {
316 		return -1;
317 	}
318 }
319 
__CalculateMp3Bitrates(int bitval,int mp3version,int mp3layer)320 static int __CalculateMp3Bitrates(int bitval, int mp3version, int mp3layer) {
321 	if (mp3version == 3) { // MPEG Version 1
322 		if (mp3layer == 3) { // Layer I
323 			int valuemapping[] = { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1 };
324 			return valuemapping[bitval];
325 		}
326 		else if (mp3layer == 2) { // Layer II
327 			int valuemapping[] = { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1 };
328 			return valuemapping[bitval];
329 		}
330 		else if (mp3layer == 1) { // Layer III
331 			int valuemapping[] = { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 };
332 			return valuemapping[bitval];
333 		}
334 		else {
335 			return -1;
336 		}
337 	}
338 	else if (mp3version == 2 || mp3version == 0) { // MPEG Version 2 or 2.5
339 		if (mp3layer == 3) { // Layer I
340 			int valuemapping[] = { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 };
341 			return valuemapping[bitval];
342 		}
343 		else if (mp3layer == 1 || mp3layer == 2) { // Layer II or III
344 			int valuemapping[] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 };
345 			return valuemapping[bitval];
346 		}
347 		else {
348 			return -1;
349 		}
350 	}
351 	else {
352 		return -1;
353 	}
354 }
355 
CalculateMp3SamplesPerFrame(int versionBits,int layerBits)356 static int CalculateMp3SamplesPerFrame(int versionBits, int layerBits) {
357 	if (versionBits == 1 || layerBits == 0) {
358 		return -1;
359 	} else if (layerBits == 3) {
360 		return 384;
361 	} else if (layerBits == 2 || versionBits == 3) {
362 		return 1152;
363 	} else {
364 		return 576;
365 	}
366 }
367 
FindMp3Header(AuCtx * ctx,int & header,int end)368 static int FindMp3Header(AuCtx *ctx, int &header, int end) {
369 	u32 addr = ctx->AuBuf + ctx->AuStreamWorkareaSize();
370 	if (Memory::IsValidRange(addr, end)) {
371 		u8 *ptr = Memory::GetPointerUnchecked(addr);
372 		for (int offset = 0; offset < end; ++offset) {
373 			// If we hit valid sync bits, then we've found a header.
374 			if (ptr[offset] == 0xFF && (ptr[offset + 1] & 0xC0) == 0xC0) {
375 				header = bswap32(Memory::Read_U32(addr + offset));
376 				return offset;
377 			}
378 		}
379 	}
380 
381 	return -1;
382 }
383 
sceMp3Init(u32 mp3)384 static int sceMp3Init(u32 mp3) {
385 	int sdkver = sceKernelGetCompiledSdkVersion();
386 	AuCtx *ctx = getMp3Ctx(mp3);
387 	if (!ctx) {
388 		if (mp3 >= MP3_MAX_HANDLES)
389 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
390 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "unreserved handle");
391 	} else if (ctx->AuBuf == 0) {
392 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "incorrect handle type");
393 	}
394 
395 	static const int PARSE_DELAY_MS = 500;
396 
397 	// First, let's search for the MP3 header.  It can be offset by at most 1439 bytes.
398 	// If we have an ID3 tag, we'll get past it based on frame sync.  Don't modify startPos.
399 	int header = 0;
400 	if (FindMp3Header(ctx, header, 1440) < 0)
401 		return hleDelayResult(hleLogWarning(ME, ERROR_AVCODEC_INVALID_DATA, "no header found"), "mp3 init", PARSE_DELAY_MS);
402 
403 	// Parse the Mp3 header
404 	int layerBits = (header >> 17) & 0x3;
405 	int versionBits = (header >> 19) & 0x3;
406 	int bitrate = __CalculateMp3Bitrates((header >> 12) & 0xF, versionBits, layerBits);
407 	int samplerate = __CalculateMp3SampleRates((header >> 10) & 0x3, versionBits);;
408 	int channels = __CalculateMp3Channels((header >> 6) & 0x3);
409 
410 	DEBUG_LOG(ME, "sceMp3Init(): channels=%i, samplerate=%iHz, bitrate=%ikbps, layerBits=%d ,versionBits=%d,HEADER: %08x", channels, samplerate, bitrate, layerBits, versionBits, header);
411 
412 	if (layerBits != 1) {
413 		// TODO: Should return ERROR_AVCODEC_INVALID_DATA.
414 		WARN_LOG_REPORT(ME, "sceMp3Init: invalid data: not layer 3");
415 	}
416 	if (bitrate == 0 || bitrate == -1) {
417 		return hleDelayResult(hleReportError(ME, ERROR_AVCODEC_INVALID_DATA, "invalid bitrate v%d l%d rate %04x", versionBits, layerBits, (header >> 12) & 0xF), "mp3 init", PARSE_DELAY_MS);
418 	}
419 	if (samplerate == -1) {
420 		return hleDelayResult(hleReportError(ME, ERROR_AVCODEC_INVALID_DATA, "invalid sample rate v%d l%d rate %02x", versionBits, layerBits, (header >> 10) & 0x3), "mp3 init", PARSE_DELAY_MS);
421 	}
422 
423 	// Before we allow init, newer SDK versions next require at least 156 bytes.
424 	// That happens to be the size of the first frame header for VBR.
425 	if (sdkver >= 0x06000000 && ctx->readPos < 156) {
426 		return hleDelayResult(hleLogError(ME, SCE_KERNEL_ERROR_INVALID_VALUE, "insufficient mp3 data for init"), "mp3 init", PARSE_DELAY_MS);
427 	}
428 
429 	ctx->SamplingRate = samplerate;
430 	ctx->Channels = channels;
431 	ctx->BitRate = bitrate;
432 	ctx->MaxOutputSample = CalculateMp3SamplesPerFrame(versionBits, layerBits);
433 	ctx->freq = ctx->SamplingRate;
434 
435 	if (versionBits != 3) {
436 		// TODO: Should return 0x80671301 (unsupported version?)
437 		WARN_LOG_REPORT(ME, "sceMp3Init: invalid data: not MPEG v1");
438 	}
439 	if (samplerate != 44100 && sdkver < 3090500) {
440 		return hleDelayResult(hleLogError(ME, ERROR_MP3_BAD_SAMPLE_RATE, "invalid data: not 44.1kHz"), "mp3 init", PARSE_DELAY_MS);
441 	}
442 
443 	// Based on bitrate, we can calculate the frame size in bytes.
444 	// Note: this doesn't correctly handle padding or slot size, but the PSP doesn't either.
445 	uint32_t bytesPerSecond = (ctx->MaxOutputSample / 8) * ctx->BitRate * 1000;
446 	// The frame count ignores the upper bits of these sizes, although they are used in cases.
447 	uint64_t totalBytes = (ctx->endPos & 0xFFFFFFFF) - (ctx->startPos & 0xFFFFFFFF);
448 	ctx->FrameNum = (int)((totalBytes * ctx->SamplingRate) / bytesPerSecond);
449 
450 	ctx->Version = versionBits;
451 
452 	// This tells us to resample to the same frequency it decodes to.
453 	ctx->decoder->SetResampleFrequency(ctx->freq);
454 
455 	return hleDelayResult(hleLogSuccessI(ME, 0), "mp3 init", PARSE_DELAY_MS);
456 }
457 
sceMp3GetLoopNum(u32 mp3)458 static int sceMp3GetLoopNum(u32 mp3) {
459 	AuCtx *ctx = getMp3Ctx(mp3);
460 	if (!ctx) {
461 		if (mp3 >= MP3_MAX_HANDLES)
462 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
463 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "unreserved handle");
464 	} else if (ctx->AuBuf == 0) {
465 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "incorrect handle type");
466 	}
467 
468 	return hleLogSuccessI(ME, ctx->AuGetLoopNum());
469 }
470 
sceMp3GetMaxOutputSample(u32 mp3)471 static int sceMp3GetMaxOutputSample(u32 mp3) {
472 	AuCtx *ctx = getMp3Ctx(mp3);
473 	if (!ctx) {
474 		if (mp3 >= MP3_MAX_HANDLES)
475 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
476 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "unreserved handle");
477 	} else if (ctx->Version < 0) {
478 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "not yet init");
479 	} else if (ctx->AuBuf == 0) {
480 		return hleLogWarning(ME, 0, "no channel available for low level");
481 	}
482 
483 	return hleLogSuccessI(ME, ctx->AuGetMaxOutputSample());
484 }
485 
sceMp3GetSumDecodedSample(u32 mp3)486 static int sceMp3GetSumDecodedSample(u32 mp3) {
487 	AuCtx *ctx = getMp3Ctx(mp3);
488 	if (!ctx) {
489 		if (mp3 >= MP3_MAX_HANDLES)
490 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
491 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "unreserved handle");
492 	} else if (ctx->AuBuf == 0) {
493 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "incorrect handle type");
494 	}
495 
496 	return hleLogSuccessI(ME, ctx->AuGetSumDecodedSample());
497 }
498 
sceMp3SetLoopNum(u32 mp3,int loop)499 static int sceMp3SetLoopNum(u32 mp3, int loop) {
500 	AuCtx *ctx = getMp3Ctx(mp3);
501 	if (!ctx) {
502 		if (mp3 >= MP3_MAX_HANDLES)
503 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
504 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "unreserved handle");
505 	} else if (ctx->AuBuf == 0) {
506 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "incorrect handle type");
507 	}
508 
509 	if (loop < 0)
510 		loop = -1;
511 
512 	return hleLogSuccessI(ME, ctx->AuSetLoopNum(loop));
513 }
514 
sceMp3GetMp3ChannelNum(u32 mp3)515 static int sceMp3GetMp3ChannelNum(u32 mp3) {
516 	AuCtx *ctx = getMp3Ctx(mp3);
517 	if (!ctx) {
518 		if (mp3 >= MP3_MAX_HANDLES)
519 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
520 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "unreserved handle");
521 	} else if (ctx->Version < 0) {
522 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "not yet init");
523 	} else if (ctx->AuBuf == 0) {
524 		return hleLogWarning(ME, 0, "no channel available for low level");
525 	}
526 
527 	return hleLogSuccessI(ME, ctx->AuGetChannelNum());
528 }
529 
sceMp3GetBitRate(u32 mp3)530 static int sceMp3GetBitRate(u32 mp3) {
531 	AuCtx *ctx = getMp3Ctx(mp3);
532 	if (!ctx) {
533 		if (mp3 >= MP3_MAX_HANDLES)
534 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
535 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "unreserved handle");
536 	} else if (ctx->Version < 0) {
537 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "not yet init");
538 	} else if (ctx->AuBuf == 0) {
539 		return hleLogWarning(ME, 0, "no bitrate available for low level");
540 	}
541 
542 	return hleLogSuccessI(ME, ctx->AuGetBitRate());
543 }
544 
sceMp3GetSamplingRate(u32 mp3)545 static int sceMp3GetSamplingRate(u32 mp3) {
546 	AuCtx *ctx = getMp3Ctx(mp3);
547 	if (!ctx) {
548 		if (mp3 >= MP3_MAX_HANDLES)
549 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
550 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "unreserved handle");
551 	} else if (ctx->Version < 0) {
552 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "not yet init");
553 	} else if (ctx->AuBuf == 0) {
554 		return hleLogWarning(ME, 0, "no sample rate available for low level");
555 	}
556 
557 	return hleLogSuccessI(ME, ctx->AuGetSamplingRate());
558 }
559 
sceMp3GetInfoToAddStreamData(u32 mp3,u32 dstPtr,u32 towritePtr,u32 srcposPtr)560 static int sceMp3GetInfoToAddStreamData(u32 mp3, u32 dstPtr, u32 towritePtr, u32 srcposPtr) {
561 	AuCtx *ctx = getMp3Ctx(mp3);
562 	if (!ctx) {
563 		if (mp3 >= MP3_MAX_HANDLES)
564 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
565 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "unreserved handle");
566 	} else if (ctx->AuBuf == 0) {
567 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "incorrect handle type");
568 	}
569 
570 	return hleLogSuccessI(ME, ctx->AuGetInfoToAddStreamData(dstPtr, towritePtr, srcposPtr));
571 }
572 
sceMp3NotifyAddStreamData(u32 mp3,int size)573 static int sceMp3NotifyAddStreamData(u32 mp3, int size) {
574 	AuCtx *ctx = getMp3Ctx(mp3);
575 	if (!ctx) {
576 		if (mp3 >= MP3_MAX_HANDLES)
577 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
578 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "unreserved handle");
579 	} else if (ctx->AuBuf == 0) {
580 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "incorrect handle type");
581 	}
582 
583 	return hleLogSuccessI(ME, ctx->AuNotifyAddStreamData(size));
584 }
585 
sceMp3ReleaseMp3Handle(u32 mp3)586 static int sceMp3ReleaseMp3Handle(u32 mp3) {
587 	AuCtx *ctx = getMp3Ctx(mp3);
588 	if (ctx) {
589 		delete ctx;
590 		mp3Map.erase(mp3);
591 		return hleLogSuccessI(ME, 0);
592 	} else if (mp3 >= MP3_MAX_HANDLES) {
593 		return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
594 	}
595 
596 	// Intentionally a zero result.
597 	return hleLogDebug(ME, 0, "double free ignored");
598 }
599 
sceMp3EndEntry()600 static u32 sceMp3EndEntry() {
601 	ERROR_LOG_REPORT(ME, "UNIMPL sceMp3EndEntry(...)");
602 	return 0;
603 }
604 
sceMp3StartEntry()605 static u32 sceMp3StartEntry() {
606 	ERROR_LOG_REPORT(ME, "UNIMPL sceMp3StartEntry(...)");
607 	return 0;
608 }
609 
sceMp3GetFrameNum(u32 mp3)610 static u32 sceMp3GetFrameNum(u32 mp3) {
611 	AuCtx *ctx = getMp3Ctx(mp3);
612 	if (!ctx) {
613 		if (mp3 >= MP3_MAX_HANDLES)
614 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
615 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "unreserved handle");
616 	} else if (ctx->Version < 0 || ctx->AuBuf == 0) {
617 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "not yet init");
618 	}
619 
620 	return hleLogSuccessI(ME, ctx->AuGetFrameNum());
621 }
622 
sceMp3GetMPEGVersion(u32 mp3)623 static u32 sceMp3GetMPEGVersion(u32 mp3) {
624 	AuCtx *ctx = getMp3Ctx(mp3);
625 	if (!ctx) {
626 		if (mp3 >= MP3_MAX_HANDLES)
627 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
628 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "unreserved handle");
629 	} else if (ctx->Version < 0) {
630 		// Seems to be the wrong error code.
631 		return hleLogError(ME, ERROR_MP3_UNRESERVED_HANDLE, "not yet init");
632 	} else if (ctx->AuBuf == 0) {
633 		return hleLogWarning(ME, 0, "no MPEG version available for low level");
634 	}
635 
636 	// Tests have not revealed how to expose more than "3" here as a result.
637 	return hleReportDebug(ME, ctx->AuGetVersion());
638 }
639 
sceMp3ResetPlayPositionByFrame(u32 mp3,u32 frame)640 static u32 sceMp3ResetPlayPositionByFrame(u32 mp3, u32 frame) {
641 	AuCtx *ctx = getMp3Ctx(mp3);
642 	if (!ctx) {
643 		if (mp3 >= MP3_MAX_HANDLES)
644 			return hleLogError(ME, ERROR_MP3_INVALID_HANDLE, "invalid handle");
645 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "unreserved handle");
646 	} else if (ctx->Version < 0 || ctx->AuBuf == 0) {
647 		return hleLogError(ME, ERROR_MP3_NOT_YET_INIT_HANDLE, "not yet init");
648 	}
649 
650 	if ((int)frame >= ctx->AuGetFrameNum()) {
651 		return hleLogError(ME, ERROR_MP3_BAD_RESET_FRAME, "bad frame position");
652 	}
653 
654 	return hleLogSuccessI(ME, ctx->AuResetPlayPositionByFrame(frame));
655 }
656 
sceMp3LowLevelInit(u32 mp3,u32 unk)657 static u32 sceMp3LowLevelInit(u32 mp3, u32 unk) {
658 	INFO_LOG(ME, "sceMp3LowLevelInit(%i, %i)", mp3, unk);
659 	auto ctx = new AuCtx;
660 
661 	ctx->audioType = PSP_CODEC_MP3;
662 	// create mp3 decoder
663 	ctx->decoder = new SimpleAudio(ctx->audioType);
664 
665 	// close the audio if mp3 already exists.
666 	if (mp3Map.find(mp3) != mp3Map.end()) {
667 		delete mp3Map[mp3];
668 		mp3Map.erase(mp3);
669 	}
670 	mp3Map[mp3] = ctx;
671 
672 	// Indicate that we've run low level init by setting version to 1.
673 	ctx->Version = 1;
674 
675 	return 0;
676 }
677 
sceMp3LowLevelDecode(u32 mp3,u32 sourceAddr,u32 sourceBytesConsumedAddr,u32 samplesAddr,u32 sampleBytesAddr)678 static u32 sceMp3LowLevelDecode(u32 mp3, u32 sourceAddr, u32 sourceBytesConsumedAddr, u32 samplesAddr, u32 sampleBytesAddr) {
679 	// sourceAddr: input mp3 stream buffer
680 	// sourceBytesConsumedAddr: consumed bytes decoded in source
681 	// samplesAddr: output pcm buffer
682 	// sampleBytesAddr: output pcm size
683 	DEBUG_LOG(ME, "sceMp3LowLevelDecode(%08x, %08x, %08x, %08x, %08x)", mp3, sourceAddr, sourceBytesConsumedAddr, samplesAddr, sampleBytesAddr);
684 
685 	AuCtx *ctx = getMp3Ctx(mp3);
686 	if (!ctx) {
687 		ERROR_LOG(ME, "%s: bad mp3 handle %08x", __FUNCTION__, mp3);
688 		return -1;
689 	}
690 
691 	if (!Memory::IsValidAddress(sourceAddr) || !Memory::IsValidAddress(sourceBytesConsumedAddr) ||
692 		!Memory::IsValidAddress(samplesAddr) || !Memory::IsValidAddress(sampleBytesAddr)) {
693 		ERROR_LOG(ME, "sceMp3LowLevelDecode(%08x, %08x, %08x, %08x, %08x) : invalid address in args", mp3, sourceAddr, sourceBytesConsumedAddr, samplesAddr, sampleBytesAddr);
694 		return -1;
695 	}
696 
697 	auto inbuff = Memory::GetPointer(sourceAddr);
698 	auto outbuff = Memory::GetPointer(samplesAddr);
699 
700 	int outpcmbytes = 0;
701 	ctx->decoder->Decode((void*)inbuff, 4096, outbuff, &outpcmbytes);
702 	NotifyMemInfo(MemBlockFlags::WRITE, samplesAddr, outpcmbytes, "Mp3LowLevelDecode");
703 
704 	Memory::Write_U32(ctx->decoder->GetSourcePos(), sourceBytesConsumedAddr);
705 	Memory::Write_U32(outpcmbytes, sampleBytesAddr);
706 	return 0;
707 }
708 
709 const HLEFunction sceMp3[] = {
710 	{0X07EC321A, &WrapU_U<sceMp3ReserveMp3Handle>,          "sceMp3ReserveMp3Handle",         'x', "x"    },
711 	{0X0DB149F4, &WrapI_UI<sceMp3NotifyAddStreamData>,      "sceMp3NotifyAddStreamData",      'i', "xi"   },
712 	{0X2A368661, &WrapI_U<sceMp3ResetPlayPosition>,         "sceMp3ResetPlayPosition",        'i', "x"    },
713 	{0X354D27EA, &WrapI_U<sceMp3GetSumDecodedSample>,       "sceMp3GetSumDecodedSample",      'i', "x"    },
714 	{0X35750070, &WrapI_V<sceMp3InitResource>,              "sceMp3InitResource",             'i', ""     },
715 	{0X3C2FA058, &WrapI_V<sceMp3TermResource>,              "sceMp3TermResource",             'i', ""     },
716 	{0X3CEF484F, &WrapI_UI<sceMp3SetLoopNum>,               "sceMp3SetLoopNum",               'i', "xi"   },
717 	{0X44E07129, &WrapI_U<sceMp3Init>,                      "sceMp3Init",                     'i', "x"    },
718 	{0X732B042A, &WrapU_V<sceMp3EndEntry>,                  "sceMp3EndEntry",                 'x', ""     },
719 	{0X7F696782, &WrapI_U<sceMp3GetMp3ChannelNum>,          "sceMp3GetMp3ChannelNum",         'i', "x"    },
720 	{0X87677E40, &WrapI_U<sceMp3GetBitRate>,                "sceMp3GetBitRate",               'i', "x"    },
721 	{0X87C263D1, &WrapI_U<sceMp3GetMaxOutputSample>,        "sceMp3GetMaxOutputSample",       'i', "x"    },
722 	{0X8AB81558, &WrapU_V<sceMp3StartEntry>,                "sceMp3StartEntry",               'x', ""     },
723 	{0X8F450998, &WrapI_U<sceMp3GetSamplingRate>,           "sceMp3GetSamplingRate",          'i', "x"    },
724 	{0XA703FE0F, &WrapI_UUUU<sceMp3GetInfoToAddStreamData>, "sceMp3GetInfoToAddStreamData",   'i', "xppp" },
725 	{0XD021C0FB, &WrapI_UU<sceMp3Decode>,                   "sceMp3Decode",                   'i', "xp"   },
726 	{0XD0A56296, &WrapI_U<sceMp3CheckStreamDataNeeded>,     "sceMp3CheckStreamDataNeeded",    'i', "x"    },
727 	{0XD8F54A51, &WrapI_U<sceMp3GetLoopNum>,                "sceMp3GetLoopNum",               'i', "x"    },
728 	{0XF5478233, &WrapI_U<sceMp3ReleaseMp3Handle>,          "sceMp3ReleaseMp3Handle",         'i', "x"    },
729 	{0XAE6D2027, &WrapU_U<sceMp3GetMPEGVersion>,            "sceMp3GetMPEGVersion",           'x', "x"    },
730 	{0X3548AEC8, &WrapU_U<sceMp3GetFrameNum>,               "sceMp3GetFrameNum",              'i', "x"    },
731 	{0X0840E808, &WrapU_UU<sceMp3ResetPlayPositionByFrame>, "sceMp3ResetPlayPositionByFrame", 'i', "xi"   },
732 	{0X1B839B83, &WrapU_UU<sceMp3LowLevelInit>,             "sceMp3LowLevelInit",             'x', "xx"   },
733 	{0XE3EE2C81, &WrapU_UUUUU<sceMp3LowLevelDecode>,        "sceMp3LowLevelDecode",           'x', "xxxxx"}
734 };
735 
Register_sceMp3()736 void Register_sceMp3() {
737 	RegisterModule("sceMp3", ARRAY_SIZE(sceMp3), sceMp3);
738 }
739