Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/HLE/sceAac.cpp
3186 views
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 "Core/HLE/sceAac.h"
19
20
#include <algorithm>
21
22
#include "Common/Serialize/SerializeFuncs.h"
23
#include "Common/Serialize/SerializeMap.h"
24
#include "Core/HLE/HLE.h"
25
#include "Core/HLE/FunctionWrappers.h"
26
#include "Core/Reporting.h"
27
#include "Core/HW/SimpleAudioDec.h"
28
29
std::map<u32, AuCtx*> g_aacMap;
30
31
static AuCtx *getAacCtx(u32 id) {
32
if (g_aacMap.find(id) == g_aacMap.end())
33
return NULL;
34
return g_aacMap[id];
35
}
36
37
void __AACShutdown() {
38
for (auto it = g_aacMap.begin(), end = g_aacMap.end(); it != end; it++) {
39
delete it->second;
40
}
41
g_aacMap.clear();
42
}
43
44
void __AACDoState(PointerWrap &p) {
45
auto s = p.Section("sceAAC", 0, 1);
46
if (!s)
47
return;
48
49
Do(p, g_aacMap);
50
}
51
52
static u32 sceAacExit(u32 id) {
53
if (g_aacMap.find(id) != g_aacMap.end()) {
54
delete g_aacMap[id];
55
g_aacMap.erase(id);
56
} else {
57
return hleLogError(Log::ME, -1, "bad aac ID");
58
}
59
return hleLogInfo(Log::ME, 0);
60
}
61
62
static u32 sceAacInit(u32 id)
63
{
64
if (!Memory::IsValidAddress(id)) {
65
return hleLogError(Log::ME, ERROR_AAC_INVALID_ADDRESS, "AAC Invalid id address %08x", id);
66
}
67
68
AuCtx *aac = new AuCtx();
69
aac->startPos = Memory::Read_U64(id); // AUDIO stream start position.
70
aac->endPos = Memory::Read_U32(id + 8); // AUDIO stream end position.
71
aac->AuBuf = Memory::Read_U32(id + 16); // Input AAC data buffer.
72
aac->AuBufSize = Memory::Read_U32(id + 20); // Input AAC data buffer size.
73
aac->PCMBuf = Memory::Read_U32(id + 24); // Output PCM data buffer.
74
aac->PCMBufSize = Memory::Read_U32(id + 28); // Output PCM data buffer size.
75
aac->freq = Memory::Read_U32(id + 32); // Frequency.
76
if (aac->AuBuf == 0 || aac->PCMBuf == 0) {
77
ERROR_LOG(Log::ME, "sceAacInit() AAC INVALID ADDRESS AuBuf %08x PCMBuf %08x", aac->AuBuf, aac->PCMBuf);
78
delete aac;
79
return hleNoLog(ERROR_AAC_INVALID_ADDRESS);
80
}
81
if (aac->startPos > aac->endPos) {
82
ERROR_LOG(Log::ME, "sceAacInit() AAC INVALID startPos %lli endPos %lli", aac->startPos, aac->endPos);
83
delete aac;
84
return hleNoLog(ERROR_AAC_INVALID_PARAMETER);
85
}
86
if (aac->AuBufSize < 8192 || aac->PCMBufSize < 8192) {
87
ERROR_LOG(Log::ME, "sceAacInit() AAC INVALID PARAMETER, bufferSize %i outputSize %i", aac->AuBufSize, aac->PCMBufSize);
88
delete aac;
89
return hleNoLog(ERROR_AAC_INVALID_PARAMETER);
90
}
91
if (aac->freq != 24000 && aac->freq != 32000 && aac->freq != 44100 && aac->freq != 48000) {
92
ERROR_LOG(Log::ME, "sceAacInit() AAC INVALID freq %i", aac->freq);
93
delete aac;
94
return hleNoLog(ERROR_AAC_INVALID_PARAMETER);
95
}
96
97
DEBUG_LOG(Log::ME, "startPos %llx endPos %llx AuBuf %08x AuBufSize %08x PCMbuf %08x PCMbufSize %08x freq %d",
98
aac->startPos, aac->endPos, aac->AuBuf, aac->AuBufSize, aac->PCMBuf, aac->PCMBufSize, aac->freq);
99
100
aac->Channels = 2;
101
aac->MaxOutputSample = aac->PCMBufSize / 4;
102
aac->SetReadPos((int)aac->startPos);
103
104
// create aac decoder
105
aac->decoder = CreateAudioDecoder(PSP_CODEC_AAC);
106
107
// close the audio if id already exist.
108
if (g_aacMap.find(id) != g_aacMap.end()) {
109
delete g_aacMap[id];
110
g_aacMap.erase(id);
111
}
112
g_aacMap[id] = aac;
113
114
return hleNoLog(id);
115
}
116
117
static u32 sceAacInitResource(u32 numberIds) {
118
// Do nothing here
119
WARN_LOG_REPORT(Log::ME, "sceAacInitResource(%i)", numberIds);
120
return hleNoLog(0);
121
}
122
123
static u32 sceAacTermResource() {
124
return hleLogError(Log::ME, 0, "UNIMPL");
125
}
126
127
static u32 sceAacDecode(u32 id, u32 pcmAddr) {
128
// return the size of output pcm, <0 error
129
auto ctx = getAacCtx(id);
130
if (!ctx) {
131
return hleLogError(Log::ME, -1, "bad aac id");
132
}
133
return hleLogDebug(Log::ME, ctx->AuDecode(pcmAddr));
134
}
135
136
static u32 sceAacGetLoopNum(u32 id) {
137
auto ctx = getAacCtx(id);
138
if (!ctx) {
139
return hleLogError(Log::ME, -1, "bad aac id");
140
}
141
return hleLogInfo(Log::ME, ctx->LoopNum);
142
}
143
144
static u32 sceAacSetLoopNum(u32 id, int loop) {
145
auto ctx = getAacCtx(id);
146
if (!ctx) {
147
return hleLogError(Log::ME, -1, "bad aac id");
148
}
149
ctx->LoopNum = loop;
150
return hleLogInfo(Log::ME, 0);
151
}
152
153
static int sceAacCheckStreamDataNeeded(u32 id) {
154
// return 1 to read more data stream, 0 don't read, <0 error
155
auto ctx = getAacCtx(id);
156
if (!ctx) {
157
return hleLogError(Log::ME, -1, "bad aac id");
158
}
159
return hleLogDebug(Log::ME, ctx->AuCheckStreamDataNeeded());
160
}
161
162
static u32 sceAacNotifyAddStreamData(u32 id, int size) {
163
// check how many bytes we have read from source file
164
auto ctx = getAacCtx(id);
165
if (!ctx) {
166
return hleLogError(Log::ME, -1, "bad aac id");
167
}
168
return hleLogDebug(Log::ME, ctx->AuNotifyAddStreamData(size));
169
}
170
171
static u32 sceAacGetInfoToAddStreamData(u32 id, u32 buff, u32 size, u32 srcPos) {
172
// read from stream position srcPos of size bytes into buff
173
auto ctx = getAacCtx(id);
174
if (!ctx) {
175
return hleLogError(Log::ME, -1, "bad aac id");
176
}
177
return hleLogDebug(Log::ME, ctx->AuGetInfoToAddStreamData(buff, size, srcPos));
178
}
179
180
static u32 sceAacGetMaxOutputSample(u32 id) {
181
auto ctx = getAacCtx(id);
182
if (!ctx) {
183
return hleLogError(Log::ME, -1, "bad aac id");
184
}
185
return hleLogDebug(Log::ME, ctx->MaxOutputSample);
186
}
187
188
static u32 sceAacGetSumDecodedSample(u32 id) {
189
auto ctx = getAacCtx(id);
190
if (!ctx) {
191
return hleLogError(Log::ME, -1, "bad aac id");
192
}
193
return hleLogDebug(Log::ME, ctx->SumDecodedSamples);
194
}
195
196
static u32 sceAacResetPlayPosition(u32 id) {
197
INFO_LOG(Log::ME, "sceAacResetPlayPosition(id %i)", id);
198
auto ctx = getAacCtx(id);
199
if (!ctx) {
200
return hleLogError(Log::ME, -1, "bad aac id");
201
}
202
return hleLogInfo(Log::ME, ctx->AuResetPlayPosition());
203
}
204
205
const HLEFunction sceAac[] = {
206
{0XE0C89ACA, &WrapU_U<sceAacInit>, "sceAacInit", 'x', "x" },
207
{0X33B8C009, &WrapU_U<sceAacExit>, "sceAacExit", 'x', "x" },
208
{0X5CFFC57C, &WrapU_U<sceAacInitResource>, "sceAacInitResource", 'x', "x" },
209
{0X23D35CAE, &WrapU_V<sceAacTermResource>, "sceAacTermResource", 'x', "" },
210
{0X7E4CFEE4, &WrapU_UU<sceAacDecode>, "sceAacDecode", 'x', "xx" },
211
{0X523347D9, &WrapU_U<sceAacGetLoopNum>, "sceAacGetLoopNum", 'x', "x" },
212
{0XBBDD6403, &WrapU_UI<sceAacSetLoopNum>, "sceAacSetLoopNum", 'x', "xi" },
213
{0XD7C51541, &WrapI_U<sceAacCheckStreamDataNeeded>, "sceAacCheckStreamDataNeeded", 'i', "x" },
214
{0XAC6DCBE3, &WrapU_UI<sceAacNotifyAddStreamData>, "sceAacNotifyAddStreamData", 'x', "xi" },
215
{0X02098C69, &WrapU_UUUU<sceAacGetInfoToAddStreamData>, "sceAacGetInfoToAddStreamData", 'x', "xxxx" },
216
{0X6DC7758A, &WrapU_U<sceAacGetMaxOutputSample>, "sceAacGetMaxOutputSample", 'x', "x" },
217
{0X506BF66C, &WrapU_U<sceAacGetSumDecodedSample>, "sceAacGetSumDecodedSample", 'x', "x" },
218
{0XD2DA2BBA, &WrapU_U<sceAacResetPlayPosition>, "sceAacResetPlayPosition", 'x', "x" },
219
};
220
221
void Register_sceAac() {
222
RegisterHLEModule("sceAac", ARRAY_SIZE(sceAac), sceAac);
223
}
224
225