1 // Copyright (c) 2012- PPSSPP Project.
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.
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.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
20 #include "Core/HLE/HLE.h"
21 #include "Core/HLE/FunctionWrappers.h"
22 #include "Core/MIPS/MIPS.h"
23 #include "Core/CoreTiming.h"
24 #include "Core/MemMapHelpers.h"
25 #include "Core/Reporting.h"
26 #include "Core/Config.h"
27 #include "Core/Debugger/Breakpoints.h"
28 #include "Core/HW/MediaEngine.h"
29 #include "Core/HW/BufferQueue.h"
30 #include "Common/ChunkFile.h"
32 #include "Core/HLE/sceKernel.h"
33 #include "Core/HLE/sceUtility.h"
34 #include "Core/HLE/sceKernelMemory.h"
35 #include "Core/HLE/sceAtrac.h"
37 // Notes about sceAtrac buffer management
39 // sceAtrac decodes from a buffer the game fills, where this buffer is one of:
40 // * Not yet initialized (state NO DATA = 1)
41 // * The entire size of the audio data, and filled with audio data (state ALL DATA LOADED = 2)
42 // * The entire size, but only partially filled so far (state HALFWAY BUFFER = 3)
43 // * Smaller than the audio, sliding without any loop (state STREAMED WITHOUT LOOP = 4)
44 // * Smaller than the audio, sliding with a loop at the end (state STREAMED WITH LOOP AT END = 5)
45 // * Smaller with a second buffer to help with a loop in the middle (state STREAMED WITH SECOND BUF = 6)
46 // * Not managed, decoding using "low level" manual looping etc. (LOW LEVEL = 8)
47 // * Not managed, reserved externally - possibly by sceSas - through low level (RESERVED = 16)
49 #define ATRAC_ERROR_API_FAIL 0x80630002
50 #define ATRAC_ERROR_NO_ATRACID 0x80630003
51 #define ATRAC_ERROR_INVALID_CODECTYPE 0x80630004
52 #define ATRAC_ERROR_BAD_ATRACID 0x80630005
53 #define ATRAC_ERROR_UNKNOWN_FORMAT 0x80630006
54 #define ATRAC_ERROR_WRONG_CODECTYPE 0x80630007
55 #define ATRAC_ERROR_ALL_DATA_LOADED 0x80630009
56 #define ATRAC_ERROR_NO_DATA 0x80630010
57 #define ATRAC_ERROR_SIZE_TOO_SMALL 0x80630011
58 #define ATRAC_ERROR_SECOND_BUFFER_NEEDED 0x80630012
59 #define ATRAC_ERROR_INCORRECT_READ_SIZE 0x80630013
60 #define ATRAC_ERROR_BAD_SAMPLE 0x80630015
61 #define ATRAC_ERROR_ADD_DATA_IS_TOO_BIG 0x80630018
62 #define ATRAC_ERROR_NOT_MONO 0x80630019
63 #define ATRAC_ERROR_NO_LOOP_INFORMATION 0x80630021
64 #define ATRAC_ERROR_SECOND_BUFFER_NOT_NEEDED 0x80630022
65 #define ATRAC_ERROR_BUFFER_IS_EMPTY 0x80630023
66 #define ATRAC_ERROR_ALL_DATA_DECODED 0x80630024
67 #define ATRAC_ERROR_AA3_INVALID_DATA 0x80631003
68 #define ATRAC_ERROR_AA3_SIZE_TOO_SMALL 0x80631004
70 #define AT3_MAGIC 0x0270
71 #define AT3_PLUS_MAGIC 0xFFFE
72 #define PSP_MODE_AT_3_PLUS 0x00001000
73 #define PSP_MODE_AT_3 0x00001001
75 const int RIFF_CHUNK_MAGIC
= 0x46464952;
76 const int RIFF_WAVE_MAGIC
= 0x45564157;
77 const int FMT_CHUNK_MAGIC
= 0x20746D66;
78 const int DATA_CHUNK_MAGIC
= 0x61746164;
79 const int SMPL_CHUNK_MAGIC
= 0x6C706D73;
80 const int FACT_CHUNK_MAGIC
= 0x74636166;
82 const int PSP_ATRAC_ALLDATA_IS_ON_MEMORY
= -1;
83 const int PSP_ATRAC_NONLOOP_STREAM_DATA_IS_ON_MEMORY
= -2;
84 const int PSP_ATRAC_LOOP_STREAM_DATA_IS_ON_MEMORY
= -3;
86 const u32 ATRAC3_MAX_SAMPLES
= 0x400;
87 const u32 ATRAC3PLUS_MAX_SAMPLES
= 0x800;
89 static const int atracDecodeDelay
= 2300;
94 #include "libavformat/avformat.h"
95 #include "libswresample/swresample.h"
96 #include "libavutil/samplefmt.h"
101 enum AtracDecodeResult
{
102 ATDECODE_FAILED
= -1,
104 ATDECODE_GOTFRAME
= 1,
118 int __AtracSetContext(Atrac
*atrac
);
119 void _AtracGenarateContext(Atrac
*atrac
, SceAtracId
*context
);
121 struct AtracLoopInfo
{
131 Atrac() : atracID(-1), data_buf(0), decodePos(0), decodeEnd(0), bufferPos(0),
132 atracChannels(0),atracOutputChannels(2),
133 atracBitrate(64), atracBytesPerFrame(0), atracBufSize(0),
134 currentSample(0), endSample(0), firstSampleoffset(0), dataOff(0),
135 loopinfoNum(0), loopStartSample(-1), loopEndSample(-1), loopNum(0),
136 failedDecode(false), resetBuffer(false), codecType(0) {
137 memset(&first
, 0, sizeof(first
));
138 memset(&second
, 0, sizeof(second
));
140 pFormatCtx
= nullptr;
146 audio_stream_index
= 0;
157 ReleaseFFMPEGContext();
164 if (atracContext
.IsValid())
165 kernelMemory
.Free(atracContext
.ptr
);
168 void DoState(PointerWrap
&p
) {
169 auto s
= p
.Section("Atrac", 1, 4);
174 p
.Do(atracOutputChannels
);
183 p
.Do(firstSampleoffset
);
187 dataOff
= firstSampleoffset
;
190 u32 has_data_buf
= data_buf
!= NULL
;
193 if (p
.mode
== p
.MODE_READ
) {
196 data_buf
= new u8
[first
.filesize
];
198 p
.DoArray(data_buf
, first
.filesize
);
200 if (p
.mode
== p
.MODE_READ
&& data_buf
!= NULL
) {
201 __AtracSetContext(this);
210 bufferPos
= decodePos
;
214 p
.Do(atracBytesPerFrame
);
219 p
.Do(loopStartSample
);
232 u32
getDecodePosBySample(int sample
) const {
233 int atracSamplesPerFrame
= (codecType
== PSP_MODE_AT_3_PLUS
? ATRAC3PLUS_MAX_SAMPLES
: ATRAC3_MAX_SAMPLES
);
234 return (u32
)(firstSampleoffset
+ sample
/ atracSamplesPerFrame
* atracBytesPerFrame
);
237 int getRemainFrames() const {
238 // games would like to add atrac data when it wants.
239 // Do not try to guess when it want to add data.
240 // Just return current remainFrames.
243 if (first
.fileoffset
>= first
.filesize
|| currentSample
>= endSample
)
244 remainFrame
= PSP_ATRAC_ALLDATA_IS_ON_MEMORY
;
246 // guess the remain frames.
247 remainFrame
= ((int)first
.size
- (int)decodePos
) / atracBytesPerFrame
;
262 u16 atracOutputChannels
;
264 u16 atracBytesPerFrame
;
269 int firstSampleoffset
;
270 // Offset of the first sample in the input buffer
273 std::vector
<AtracLoopInfo
> loopinfo
;
288 PSPPointer
<SceAtracId
> atracContext
;
291 AVFormatContext
*pFormatCtx
;
292 AVIOContext
*pAVIOCtx
;
293 AVCodecContext
*pCodecCtx
;
297 int audio_stream_index
;
299 void ReleaseFFMPEGContext() {
302 if (pAVIOCtx
&& pAVIOCtx
->buffer
)
303 av_free(pAVIOCtx
->buffer
);
309 avcodec_close(pCodecCtx
);
311 avformat_close_input(&pFormatCtx
);
313 av_free_packet(packet
);
315 pFormatCtx
= nullptr;
323 void ForceSeekToSample(int sample
) {
324 av_seek_frame(pFormatCtx
, audio_stream_index
, sample
+ 0x200000, 0);
325 av_seek_frame(pFormatCtx
, audio_stream_index
, sample
, 0);
326 avcodec_flush_buffers(pCodecCtx
);
328 // Discard any pending packet data.
331 currentSample
= sample
;
334 void SeekToSample(int sample
) {
335 const u32 atracSamplesPerFrame
= (codecType
== PSP_MODE_AT_3_PLUS
? ATRAC3PLUS_MAX_SAMPLES
: ATRAC3_MAX_SAMPLES
);
337 // Discard any pending packet data.
340 // Some kind of header size?
341 const u32 firstOffsetExtra
= codecType
== PSP_CODEC_AT3PLUS
? 368 : 69;
342 // It seems like the PSP aligns the sample position to 0x800...?
343 const u32 offsetSamples
= firstSampleoffset
+ firstOffsetExtra
;
344 const u32 unalignedSamples
= (offsetSamples
+ sample
) % atracSamplesPerFrame
;
345 int seekFrame
= sample
+ offsetSamples
- unalignedSamples
;
347 if (sample
!= currentSample
) {
348 // "Seeking" by reading frames seems to work much better.
349 av_seek_frame(pFormatCtx
, audio_stream_index
, 0, AVSEEK_FLAG_BACKWARD
);
350 avcodec_flush_buffers(pCodecCtx
);
352 for (int i
= 0; i
< seekFrame
; i
+= atracSamplesPerFrame
) {
353 while (FillPacket() && DecodePacket() == ATDECODE_FEEDME
) {
358 // For some reason, if we skip seeking, we get the wrong amount of data.
359 // (even without flushing the packet...)
360 av_seek_frame(pFormatCtx
, audio_stream_index
, seekFrame
, 0);
361 avcodec_flush_buffers(pCodecCtx
);
363 currentSample
= sample
;
367 if (packet
->size
> 0) {
371 // This is double-free safe, so we just call it before each read and at the end.
372 av_free_packet(packet
);
373 if (av_read_frame(pFormatCtx
, packet
) < 0) {
376 // We keep reading until we get the right stream index.
377 } while (packet
->stream_index
!= audio_stream_index
);
382 AtracDecodeResult
DecodePacket() {
384 AVPacket
*decodePacket
= packet
;
385 if (packet
->size
< (int)atracBytesPerFrame
) {
386 // Whoops, we have a packet that is smaller than a frame. Let's meld a new one.
387 u32 initialSize
= packet
->size
;
388 int needed
= atracBytesPerFrame
- initialSize
;
389 av_init_packet(&tempPacket
);
390 av_copy_packet(&tempPacket
, packet
);
391 av_grow_packet(&tempPacket
, needed
);
393 // Okay, we're "out of data", let's get more.
397 int to_copy
= packet
->size
>= needed
? needed
: packet
->size
;
398 memcpy(tempPacket
.data
+ initialSize
, packet
->data
, to_copy
);
399 packet
->size
-= to_copy
;
400 packet
->data
+= to_copy
;
401 tempPacket
.size
= initialSize
+ to_copy
;
403 tempPacket
.size
= initialSize
;
405 decodePacket
= &tempPacket
;
409 int bytes_read
= avcodec_decode_audio4(pCodecCtx
, pFrame
, &got_frame
, decodePacket
);
410 if (packet
!= decodePacket
) {
411 av_free_packet(&tempPacket
);
413 if (bytes_read
== AVERROR_PATCHWELCOME
) {
414 ERROR_LOG(ME
, "Unsupported feature in ATRAC audio.");
415 // Let's try the next packet.
416 if (packet
== decodePacket
) {
419 // TODO: Or actually, should we return a blank frame and pretend it worked?
420 return ATDECODE_FEEDME
;
421 } else if (bytes_read
< 0) {
422 ERROR_LOG_REPORT(ME
, "avcodec_decode_audio4: Error decoding audio %d / %08x", bytes_read
, bytes_read
);
424 return ATDECODE_FAILED
;
427 if (packet
== decodePacket
) {
428 packet
->size
-= bytes_read
;
429 packet
->data
+= bytes_read
;
431 return got_frame
? ATDECODE_GOTFRAME
: ATDECODE_FEEDME
;
439 struct AtracSingleResetBufferInfo
{
446 struct AtracResetBufferInfo
{
447 AtracSingleResetBufferInfo first
;
448 AtracSingleResetBufferInfo second
;
451 const int PSP_NUM_ATRAC_IDS
= 6;
452 static bool atracInited
= true;
453 static Atrac
*atracIDs
[PSP_NUM_ATRAC_IDS
];
454 static u32 atracIDTypes
[PSP_NUM_ATRAC_IDS
];
458 memset(atracIDs
, 0, sizeof(atracIDs
));
460 // Start with 2 of each in this order.
461 atracIDTypes
[0] = PSP_MODE_AT_3_PLUS
;
462 atracIDTypes
[1] = PSP_MODE_AT_3_PLUS
;
463 atracIDTypes
[2] = PSP_MODE_AT_3
;
464 atracIDTypes
[3] = PSP_MODE_AT_3
;
469 avcodec_register_all();
474 void __AtracDoState(PointerWrap
&p
) {
475 auto s
= p
.Section("sceAtrac", 1);
480 for (int i
= 0; i
< PSP_NUM_ATRAC_IDS
; ++i
) {
481 bool valid
= atracIDs
[i
] != NULL
;
490 p
.DoArray(atracIDTypes
, PSP_NUM_ATRAC_IDS
);
493 void __AtracShutdown() {
494 for (size_t i
= 0; i
< ARRAY_SIZE(atracIDs
); ++i
) {
500 static Atrac
*getAtrac(int atracID
) {
501 if (atracID
< 0 || atracID
>= PSP_NUM_ATRAC_IDS
) {
504 return atracIDs
[atracID
];
507 static int createAtrac(Atrac
*atrac
) {
508 for (int i
= 0; i
< (int)ARRAY_SIZE(atracIDs
); ++i
) {
509 if (atracIDTypes
[i
] == atrac
->codecType
&& atracIDs
[i
] == 0) {
516 return ATRAC_ERROR_NO_ATRACID
;
519 static int deleteAtrac(int atracID
) {
520 if (atracID
>= 0 && atracID
< PSP_NUM_ATRAC_IDS
) {
521 if (atracIDs
[atracID
] != NULL
) {
522 delete atracIDs
[atracID
];
523 atracIDs
[atracID
] = NULL
;
529 return ATRAC_ERROR_BAD_ATRACID
;
532 void Atrac::AnalyzeReset() {
533 // Reset some values.
540 loopStartSample
= -1;
547 struct RIFFFmtChunk
{
551 u32_le avgBytesPerSec
;
555 int Atrac::Analyze() {
558 // 72 is about the size of the minimum required data to even be valid.
559 if (first
.size
< 72) {
560 ERROR_LOG_REPORT(ME
, "Atrac buffer very small: %d", first
.size
);
561 return ATRAC_ERROR_SIZE_TOO_SMALL
;
564 if (!Memory::IsValidAddress(first
.addr
)) {
565 WARN_LOG_REPORT(ME
, "Atrac buffer at invalid address: %08x-%08x", first
.addr
, first
.size
);
566 return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS
;
569 // TODO: Validate stuff.
571 if (Memory::Read_U32(first
.addr
) != RIFF_CHUNK_MAGIC
) {
572 ERROR_LOG_REPORT(ME
, "Atrac buffer invalid RIFF header: %08x", first
.addr
);
573 return ATRAC_ERROR_UNKNOWN_FORMAT
;
577 int loopFirstSampleOffset
= 0;
578 firstSampleoffset
= 0;
580 while (Memory::Read_U32(first
.addr
+ offset
) != RIFF_WAVE_MAGIC
) {
581 // Get the size preceding the magic.
582 int chunk
= Memory::Read_U32(first
.addr
+ offset
- 4);
583 // Round the chunk size up to the nearest 2.
584 offset
+= chunk
+ (chunk
& 1);
585 if (offset
+ 12 > first
.size
) {
586 ERROR_LOG_REPORT(ME
, "Atrac buffer too small without WAVE chunk: %d at %d", first
.size
, offset
);
587 return ATRAC_ERROR_SIZE_TOO_SMALL
;
589 if (Memory::Read_U32(first
.addr
+ offset
) != RIFF_CHUNK_MAGIC
) {
590 ERROR_LOG_REPORT(ME
, "RIFF chunk did not contain WAVE");
591 return ATRAC_ERROR_UNKNOWN_FORMAT
;
598 WARN_LOG_REPORT(ME
, "RIFF chunk at offset: %d", offset
);
601 // RIFF size excluding chunk header.
602 first
.filesize
= Memory::Read_U32(first
.addr
+ offset
- 8) + 8;
604 this->decodeEnd
= first
.filesize
;
605 bool bfoundData
= false;
606 while (first
.filesize
>= offset
+ 8 && !bfoundData
) {
607 int chunkMagic
= Memory::Read_U32(first
.addr
+ offset
);
608 u32 chunkSize
= Memory::Read_U32(first
.addr
+ offset
+ 4);
610 if (chunkSize
> first
.filesize
- offset
)
612 switch (chunkMagic
) {
613 case FMT_CHUNK_MAGIC
:
615 if (codecType
!= 0) {
616 ERROR_LOG_REPORT(ME
, "Atrac buffer with multiple fmt definitions");
617 return ATRAC_ERROR_UNKNOWN_FORMAT
;
620 auto at3fmt
= PSPPointer
<const RIFFFmtChunk
>::Create(first
.addr
+ offset
);
621 if (chunkSize
< 32 || (at3fmt
->fmtTag
== AT3_PLUS_MAGIC
&& chunkSize
< 52)) {
622 ERROR_LOG_REPORT(ME
, "Atrac buffer with too small fmt definition %d", chunkSize
);
623 return ATRAC_ERROR_UNKNOWN_FORMAT
;
626 if (at3fmt
->fmtTag
== AT3_MAGIC
)
627 codecType
= PSP_MODE_AT_3
;
628 else if (at3fmt
->fmtTag
== AT3_PLUS_MAGIC
)
629 codecType
= PSP_MODE_AT_3_PLUS
;
631 ERROR_LOG_REPORT(ME
, "Atrac buffer with invalid fmt magic: %04x", at3fmt
->fmtTag
);
632 return ATRAC_ERROR_UNKNOWN_FORMAT
;
634 atracChannels
= at3fmt
->channels
;
635 if (atracChannels
!= 1 && atracChannels
!= 2) {
636 ERROR_LOG_REPORT(ME
, "Atrac buffer with invalid channel count: %d", atracChannels
);
637 return ATRAC_ERROR_UNKNOWN_FORMAT
;
639 if (at3fmt
->samplerate
!= 44100) {
640 ERROR_LOG_REPORT(ME
, "Atrac buffer with unsupported sample rate: %d", at3fmt
->samplerate
);
641 return ATRAC_ERROR_UNKNOWN_FORMAT
;
643 atracBitrate
= at3fmt
->avgBytesPerSec
* 8;
644 atracBytesPerFrame
= at3fmt
->blockAlign
;
645 if (atracBytesPerFrame
== 0) {
646 ERROR_LOG_REPORT(ME
, "Atrac buffer with invalid bytes per frame: %d", atracBytesPerFrame
);
647 return ATRAC_ERROR_UNKNOWN_FORMAT
;
650 // TODO: There are some format specific bytes here which seem to have fixed values?
653 case FACT_CHUNK_MAGIC
:
655 endSample
= Memory::Read_U32(first
.addr
+ offset
);
656 firstSampleoffset
= Memory::Read_U32(first
.addr
+ offset
+ 4);
657 if (chunkSize
>= 12) {
658 // Seems like this indicates it's got a separate offset for loops.
659 loopFirstSampleOffset
= Memory::Read_U32(first
.addr
+ offset
+ 8);
660 } else if (chunkSize
>= 8) {
661 loopFirstSampleOffset
= firstSampleoffset
;
665 case SMPL_CHUNK_MAGIC
:
669 int checkNumLoops
= Memory::Read_U32(first
.addr
+ offset
+ 28);
670 if (chunkSize
>= 36 + (u32
)checkNumLoops
* 24) {
671 loopinfoNum
= checkNumLoops
;
672 loopinfo
.resize(loopinfoNum
);
673 u32 loopinfoAddr
= first
.addr
+ offset
+ 36;
674 for (int i
= 0; i
< loopinfoNum
; i
++, loopinfoAddr
+= 24) {
675 loopinfo
[i
].cuePointID
= Memory::Read_U32(loopinfoAddr
);
676 loopinfo
[i
].type
= Memory::Read_U32(loopinfoAddr
+ 4);
677 loopinfo
[i
].startSample
= Memory::Read_U32(loopinfoAddr
+ 8) - loopFirstSampleOffset
;
678 loopinfo
[i
].endSample
= Memory::Read_U32(loopinfoAddr
+ 12) - loopFirstSampleOffset
;
679 loopinfo
[i
].fraction
= Memory::Read_U32(loopinfoAddr
+ 16);
680 loopinfo
[i
].playCount
= Memory::Read_U32(loopinfoAddr
+ 20);
682 if (loopinfo
[i
].endSample
> endSample
)
683 loopinfo
[i
].endSample
= endSample
;
688 case DATA_CHUNK_MAGIC
:
698 if (codecType
== 0) {
699 WARN_LOG_REPORT(ME
, "Atrac buffer with unexpected or no magic bytes");
700 return ATRAC_ERROR_UNKNOWN_FORMAT
;
703 // set the loopStartSample and loopEndSample by loopinfo
704 if (loopinfoNum
> 0) {
705 loopStartSample
= loopinfo
[0].startSample
;
706 loopEndSample
= loopinfo
[0].endSample
;
708 loopStartSample
= loopEndSample
= -1;
711 // if there is no correct endsample, try to guess it
712 if (endSample
< 0 && atracBytesPerFrame
!= 0) {
713 int atracSamplesPerFrame
= (codecType
== PSP_MODE_AT_3_PLUS
? ATRAC3PLUS_MAX_SAMPLES
: ATRAC3_MAX_SAMPLES
);
714 endSample
= (first
.filesize
/ atracBytesPerFrame
) * atracSamplesPerFrame
;
720 int Atrac::AnalyzeAA3() {
723 if (first
.size
< 10) {
724 return ATRAC_ERROR_AA3_SIZE_TOO_SMALL
;
727 // TODO: Make sure this validation is correct, more testing.
729 const u8
*buffer
= Memory::GetPointer(first
.addr
);
730 if (buffer
[0] != 'e' || buffer
[1] != 'a' || buffer
[2] != '3') {
731 return ATRAC_ERROR_AA3_INVALID_DATA
;
734 // It starts with an id3 header (replaced with ea3.) This is the size.
735 u32 tagSize
= buffer
[9] | (buffer
[8] << 7) | (buffer
[7] << 14) | (buffer
[6] << 21);
736 if (first
.size
< tagSize
+ 36) {
737 return ATRAC_ERROR_AA3_SIZE_TOO_SMALL
;
740 // EA3 header starts at id3 header (10) + tagSize.
741 buffer
= Memory::GetPointer(first
.addr
+ 10 + tagSize
);
742 if (buffer
[0] != 'E' || buffer
[1] != 'A' || buffer
[2] != '3') {
743 return ATRAC_ERROR_AA3_INVALID_DATA
;
746 // Based on FFmpeg's code.
747 u32 codecParams
= buffer
[35] | (buffer
[34] << 8) | (buffer
[35] << 16);
748 const u32 at3SampleRates
[8] = { 32000, 44100, 48000, 88200, 96000, 0 };
750 switch (buffer
[32]) {
752 codecType
= PSP_MODE_AT_3
;
753 atracBytesPerFrame
= (codecParams
& 0x03FF) * 8;
754 atracBitrate
= at3SampleRates
[(codecParams
>> 13) & 7] * atracBytesPerFrame
* 8 / 1024;
758 codecType
= PSP_MODE_AT_3_PLUS
;
759 atracBytesPerFrame
= ((codecParams
& 0x03FF) * 8) + 8;
760 atracBitrate
= at3SampleRates
[(codecParams
>> 13) & 7] * atracBytesPerFrame
* 8 / 2048;
761 atracChannels
= (codecParams
>> 10) & 7;
766 ERROR_LOG_REPORT(ME
, "OMA header contains unsupported codec type: %d", buffer
[32]);
767 return ATRAC_ERROR_AA3_INVALID_DATA
;
769 return ATRAC_ERROR_AA3_INVALID_DATA
;
773 firstSampleoffset
= 0;
774 if (endSample
< 0 && atracBytesPerFrame
!= 0) {
775 int atracSamplesPerFrame
= (codecType
== PSP_MODE_AT_3_PLUS
? ATRAC3PLUS_MAX_SAMPLES
: ATRAC3_MAX_SAMPLES
);
776 endSample
= (first
.filesize
/ atracBytesPerFrame
) * atracSamplesPerFrame
;
781 static u32
sceAtracGetAtracID(int codecType
) {
782 if (codecType
!= PSP_MODE_AT_3
&& codecType
!= PSP_MODE_AT_3_PLUS
) {
783 ERROR_LOG_REPORT(ME
, "sceAtracGetAtracID(%i): invalid codecType", codecType
);
784 return ATRAC_ERROR_INVALID_CODECTYPE
;
787 Atrac
*atrac
= new Atrac();
788 atrac
->codecType
= codecType
;
789 int atracID
= createAtrac(atrac
);
791 ERROR_LOG(ME
, "sceAtracGetAtracID(%i): no free ID", codecType
);
796 INFO_LOG(ME
, "%d=sceAtracGetAtracID(%i)", atracID
, codecType
);
800 u32
_AtracAddStreamData(int atracID
, u32 bufPtr
, u32 bytesToAdd
) {
801 Atrac
*atrac
= getAtrac(atracID
);
804 int addbytes
= std::min(bytesToAdd
, atrac
->first
.filesize
- atrac
->first
.fileoffset
);
805 Memory::Memcpy(atrac
->data_buf
+ atrac
->first
.fileoffset
, bufPtr
, addbytes
);
806 atrac
->first
.size
+= bytesToAdd
;
807 if (atrac
->first
.size
> atrac
->first
.filesize
)
808 atrac
->first
.size
= atrac
->first
.filesize
;
809 atrac
->first
.fileoffset
= atrac
->first
.size
;
810 atrac
->first
.writableBytes
= 0;
811 if (atrac
->atracContext
.IsValid()) {
812 // refresh atracContext
813 _AtracGenarateContext(atrac
, atrac
->atracContext
);
818 // PSP allow games to add stream data to a temp buf, the buf size is given by "atracBufSize "here.
819 // "first.offset" means how many bytes the temp buf has been written,
820 // and "first.writableBytes" means how many bytes the temp buf is allowed to write
821 // (We always have "first.offset + first.writableBytes = atracBufSize").
822 // We only reset the temp buf when games call sceAtracGetStreamDataInfo,
823 // because that function would tell games how to add the left stream data.
824 static u32
sceAtracAddStreamData(int atracID
, u32 bytesToAdd
) {
825 Atrac
*atrac
= getAtrac(atracID
);
827 return hleLogError(ME
, ATRAC_ERROR_BAD_ATRACID
, "bad atrac ID");
828 } else if (!atrac
->data_buf
) {
829 return hleLogError(ME
, ATRAC_ERROR_NO_DATA
, "no data");
831 if (atrac
->first
.size
>= atrac
->first
.filesize
) {
832 // Let's avoid spurious warnings. Some games call this with 0 which is pretty harmless.
834 return hleLogDebug(ME
, ATRAC_ERROR_ALL_DATA_LOADED
, "stream entirely loaded");
835 return hleLogWarning(ME
, ATRAC_ERROR_ALL_DATA_LOADED
, "stream entirely loaded");
837 if (bytesToAdd
> atrac
->first
.writableBytes
)
838 return hleLogWarning(ME
, ATRAC_ERROR_ADD_DATA_IS_TOO_BIG
, "too many bytes");
840 if (bytesToAdd
> 0) {
841 int addbytes
= std::min(bytesToAdd
, atrac
->first
.filesize
- atrac
->first
.fileoffset
);
842 Memory::Memcpy(atrac
->data_buf
+ atrac
->first
.fileoffset
, atrac
->first
.addr
+ atrac
->first
.offset
, addbytes
);
844 atrac
->first
.size
+= bytesToAdd
;
845 if (atrac
->first
.size
> atrac
->first
.filesize
)
846 atrac
->first
.size
= atrac
->first
.filesize
;
847 atrac
->first
.fileoffset
= atrac
->first
.size
;
848 atrac
->first
.writableBytes
-= bytesToAdd
;
849 atrac
->first
.offset
+= bytesToAdd
;
851 return hleLogSuccessI(ME
, 0);
854 u32
_AtracDecodeData(int atracID
, u8
*outbuf
, u32 outbufPtr
, u32
*SamplesNum
, u32
*finish
, int *remains
) {
855 Atrac
*atrac
= getAtrac(atracID
);
859 ret
= ATRAC_ERROR_BAD_ATRACID
;
860 } else if (!atrac
->data_buf
) {
861 ret
= ATRAC_ERROR_NO_DATA
;
863 // We already passed the end - return an error (many games check for this.)
864 if (atrac
->currentSample
>= atrac
->endSample
&& atrac
->loopNum
== 0) {
868 ret
= ATRAC_ERROR_ALL_DATA_DECODED
;
870 // TODO: This isn't at all right, but at least it makes the music "last" some time.
872 u32 atracSamplesPerFrame
= (atrac
->codecType
== PSP_MODE_AT_3_PLUS
? ATRAC3PLUS_MAX_SAMPLES
: ATRAC3_MAX_SAMPLES
);
874 // Some kind of header size?
875 u32 firstOffsetExtra
= atrac
->codecType
== PSP_CODEC_AT3PLUS
? 368 : 69;
876 // It seems like the PSP aligns the sample position to 0x800...?
877 int offsetSamples
= atrac
->firstSampleoffset
+ firstOffsetExtra
;
879 u32 maxSamples
= atrac
->endSample
- atrac
->currentSample
;
880 u32 unalignedSamples
= (offsetSamples
+ atrac
->currentSample
) % atracSamplesPerFrame
;
881 if (unalignedSamples
!= 0) {
882 // We're off alignment, possibly due to a loop. Force it back on.
883 maxSamples
= atracSamplesPerFrame
- unalignedSamples
;
884 skipSamples
= unalignedSamples
;
888 if (!atrac
->failedDecode
&& (atrac
->codecType
== PSP_MODE_AT_3
|| atrac
->codecType
== PSP_MODE_AT_3_PLUS
) && atrac
->pCodecCtx
) {
889 atrac
->SeekToSample(atrac
->currentSample
);
891 AtracDecodeResult res
= ATDECODE_FEEDME
;
892 while (atrac
->FillPacket()) {
893 res
= atrac
->DecodePacket();
894 if (res
== ATDECODE_FAILED
) {
898 return ATRAC_ERROR_ALL_DATA_DECODED
;
901 if (res
== ATDECODE_GOTFRAME
) {
903 // Use a small buffer and keep overwriting it with file data constantly
904 atrac
->first
.writableBytes
+= atrac
->atracBytesPerFrame
;
905 int skipped
= std::min(skipSamples
, atrac
->pFrame
->nb_samples
);
906 skipSamples
-= skipped
;
907 numSamples
= atrac
->pFrame
->nb_samples
- skipped
;
909 // If we're at the end, clamp to samples we want. It always returns a full chunk.
910 numSamples
= std::min(maxSamples
, numSamples
);
912 if (skipped
> 0 && numSamples
== 0) {
913 // Wait for the next one.
914 res
= ATDECODE_FEEDME
;
917 if (outbuf
!= NULL
&& numSamples
!= 0) {
920 AVSampleFormat fmt
= (AVSampleFormat
)atrac
->pFrame
->format
;
921 // We want the offset per channel.
922 inbufOffset
= av_samples_get_buffer_size(NULL
, 1, skipped
, fmt
, 1);
926 const u8
*inbuf
[2] = {
927 atrac
->pFrame
->extended_data
[0] + inbufOffset
,
928 atrac
->pFrame
->extended_data
[1] + inbufOffset
,
930 int avret
= swr_convert(atrac
->pSwrCtx
, &out
, numSamples
, inbuf
, numSamples
);
931 if (outbufPtr
!= 0) {
932 u32 outBytes
= numSamples
* atrac
->atracOutputChannels
* sizeof(s16
);
933 CBreakPoints::ExecMemCheck(outbufPtr
, true, outBytes
, currentMIPS
->pc
);
936 ERROR_LOG(ME
, "swr_convert: Error while converting %d", avret
);
940 if (res
== ATDECODE_GOTFRAME
) {
941 // We only want one frame per call, let's continue the next time.
946 if (res
!= ATDECODE_GOTFRAME
&& atrac
->currentSample
< atrac
->endSample
) {
947 // Never got a frame. We may have dropped a GHA frame or otherwise have a bug.
948 // For now, let's try to provide an extra "frame" if possible so games don't infinite loop.
949 numSamples
= std::min(maxSamples
, atracSamplesPerFrame
);
950 u32 outBytes
= numSamples
* atrac
->atracOutputChannels
* sizeof(s16
);
951 memset(outbuf
, 0, outBytes
);
952 CBreakPoints::ExecMemCheck(outbufPtr
, true, outBytes
, currentMIPS
->pc
);
957 *SamplesNum
= numSamples
;
958 // update current sample and decodePos
959 atrac
->currentSample
+= numSamples
;
960 atrac
->decodePos
= atrac
->getDecodePosBySample(atrac
->currentSample
);
963 if (atrac
->loopNum
!= 0 && (atrac
->currentSample
> atrac
->loopEndSample
||
964 (numSamples
== 0 && atrac
->first
.size
>= atrac
->first
.filesize
))) {
965 atrac
->SeekToSample(atrac
->loopStartSample
);
966 if (atrac
->loopNum
> 0)
968 } else if (atrac
->currentSample
>= atrac
->endSample
||
969 (numSamples
== 0 && atrac
->first
.size
>= atrac
->first
.filesize
)) {
973 *finish
= finishFlag
;
974 *remains
= atrac
->getRemainFrames();
976 if (atrac
->atracContext
.IsValid()) {
977 // refresh atracContext
978 _AtracGenarateContext(atrac
, atrac
->atracContext
);
985 static u32
sceAtracDecodeData(int atracID
, u32 outAddr
, u32 numSamplesAddr
, u32 finishFlagAddr
, u32 remainAddr
) {
988 // Note that outAddr being null is completely valid here, used to skip data.
993 ret
= _AtracDecodeData(atracID
, Memory::GetPointer(outAddr
), outAddr
, &numSamples
, &finish
, &remains
);
994 if (ret
!= (int)ATRAC_ERROR_BAD_ATRACID
&& ret
!= (int)ATRAC_ERROR_NO_DATA
) {
995 if (Memory::IsValidAddress(numSamplesAddr
))
996 Memory::Write_U32(numSamples
, numSamplesAddr
);
997 if (Memory::IsValidAddress(finishFlagAddr
))
998 Memory::Write_U32(finish
, finishFlagAddr
);
999 if (Memory::IsValidAddress(remainAddr
))
1000 Memory::Write_U32(remains
, remainAddr
);
1002 DEBUG_LOG(ME
, "%08x=sceAtracDecodeData(%i, %08x, %08x[%08x], %08x[%08x], %08x[%d])", ret
, atracID
, outAddr
,
1003 numSamplesAddr
, numSamples
,
1004 finishFlagAddr
, finish
,
1005 remainAddr
, remains
);
1007 // decode data successfully, delay thread
1008 return hleDelayResult(ret
, "atrac decode data", atracDecodeDelay
);
1013 static u32
sceAtracEndEntry() {
1014 ERROR_LOG_REPORT(ME
, "UNIMPL sceAtracEndEntry()");
1018 static u32
sceAtracGetBufferInfoForResetting(int atracID
, int sample
, u32 bufferInfoAddr
) {
1019 auto bufferInfo
= PSPPointer
<AtracResetBufferInfo
>::Create(bufferInfoAddr
);
1021 Atrac
*atrac
= getAtrac(atracID
);
1023 WARN_LOG(ME
, "sceAtracGetBufferInfoForResetting(%i, %i, %08x): invalid id", atracID
, sample
, bufferInfoAddr
);
1024 return ATRAC_ERROR_BAD_ATRACID
;
1025 } else if (!atrac
->data_buf
) {
1026 ERROR_LOG(ME
, "sceAtracGetBufferInfoForResetting(%i, %i, %08x): no data", atracID
, sample
, bufferInfoAddr
);
1027 return ATRAC_ERROR_NO_DATA
;
1028 } else if (!bufferInfo
.IsValid()) {
1029 ERROR_LOG_REPORT(ME
, "sceAtracGetBufferInfoForResetting(%i, %i, %08x): invalid buffer, should crash", atracID
, sample
, bufferInfoAddr
);
1030 return SCE_KERNEL_ERROR_ILLEGAL_ADDR
;
1032 u32 atracSamplesPerFrame
= (atrac
->codecType
== PSP_MODE_AT_3_PLUS
? ATRAC3PLUS_MAX_SAMPLES
: ATRAC3_MAX_SAMPLES
);
1033 if ((u32
)sample
+ atracSamplesPerFrame
> (u32
)atrac
->endSample
) {
1034 WARN_LOG(ME
, "sceAtracGetBufferInfoForResetting(%i, %i, %08x): invalid sample position", atracID
, sample
, bufferInfoAddr
);
1035 return ATRAC_ERROR_BAD_SAMPLE
;
1038 int Sampleoffset
= atrac
->getDecodePosBySample(sample
);
1039 int minWritebytes
= std::max(Sampleoffset
- (int)atrac
->first
.size
, 0);
1040 // Reset temp buf for adding more stream data and set full filled buffer
1041 atrac
->first
.writableBytes
= std::min(atrac
->first
.filesize
- atrac
->first
.size
, atrac
->atracBufSize
);
1042 atrac
->first
.offset
= 0;
1043 // minWritebytes should not be bigger than writeablebytes
1044 minWritebytes
= std::min(minWritebytes
, (int)atrac
->first
.writableBytes
);
1046 if (atrac
->first
.fileoffset
<= 2*atrac
->atracBufSize
){
1047 Sampleoffset
= atrac
->first
.fileoffset
;
1050 // If we've already loaded everything, the answer is 0.
1051 if (atrac
->first
.size
>= atrac
->first
.filesize
) {
1055 bufferInfo
->first
.writePosPtr
= atrac
->first
.addr
;
1056 bufferInfo
->first
.writableBytes
= atrac
->first
.writableBytes
;
1057 bufferInfo
->first
.minWriteBytes
= minWritebytes
;
1058 bufferInfo
->first
.filePos
= Sampleoffset
;
1060 // TODO: It seems like this is always the same as the first buffer's pos?
1061 bufferInfo
->second
.writePosPtr
= atrac
->first
.addr
;
1062 bufferInfo
->second
.writableBytes
= atrac
->second
.writableBytes
;
1063 bufferInfo
->second
.minWriteBytes
= atrac
->second
.neededBytes
;
1064 bufferInfo
->second
.filePos
= atrac
->second
.fileoffset
;
1066 INFO_LOG(ME
, "0=sceAtracGetBufferInfoForResetting(%i, %i, %08x)",atracID
, sample
, bufferInfoAddr
);
1071 static u32
sceAtracGetBitrate(int atracID
, u32 outBitrateAddr
) {
1072 Atrac
*atrac
= getAtrac(atracID
);
1074 ERROR_LOG(ME
, "sceAtracGetBitrate(%i, %08x): bad atrac ID", atracID
, outBitrateAddr
);
1075 return ATRAC_ERROR_BAD_ATRACID
;
1076 } else if (!atrac
->data_buf
) {
1077 ERROR_LOG(ME
, "sceAtracGetBitrate(%i, %08x): no data", atracID
, outBitrateAddr
);
1078 return ATRAC_ERROR_NO_DATA
;
1080 atrac
->atracBitrate
= ( atrac
->atracBytesPerFrame
* 352800 ) / 1000;
1081 if (atrac
->codecType
== PSP_MODE_AT_3_PLUS
)
1082 atrac
->atracBitrate
= ((atrac
->atracBitrate
>> 11) + 8) & 0xFFFFFFF0;
1084 atrac
->atracBitrate
= (atrac
->atracBitrate
+ 511) >> 10;
1085 if (Memory::IsValidAddress(outBitrateAddr
)) {
1086 Memory::Write_U32(atrac
->atracBitrate
, outBitrateAddr
);
1087 DEBUG_LOG(ME
, "sceAtracGetBitrate(%i, %08x[%d])", atracID
, outBitrateAddr
, atrac
->atracBitrate
);
1090 DEBUG_LOG_REPORT(ME
, "sceAtracGetBitrate(%i, %08x[%d]) invalid address", atracID
, outBitrateAddr
, atrac
->atracBitrate
);
1095 static u32
sceAtracGetChannel(int atracID
, u32 channelAddr
) {
1096 Atrac
*atrac
= getAtrac(atracID
);
1098 ERROR_LOG(ME
, "sceAtracGetChannel(%i, %08x): bad atrac ID", atracID
, channelAddr
);
1099 return ATRAC_ERROR_BAD_ATRACID
;
1100 } else if (!atrac
->data_buf
) {
1101 ERROR_LOG(ME
, "sceAtracGetChannel(%i, %08x): no data", atracID
, channelAddr
);
1102 return ATRAC_ERROR_NO_DATA
;
1104 if (Memory::IsValidAddress(channelAddr
)){
1105 Memory::Write_U32(atrac
->atracChannels
, channelAddr
);
1106 DEBUG_LOG(ME
, "sceAtracGetChannel(%i, %08x[%d])", atracID
, channelAddr
, atrac
->atracChannels
);
1109 DEBUG_LOG_REPORT(ME
, "sceAtracGetChannel(%i, %08x[%d]) invalid address", atracID
, channelAddr
, atrac
->atracChannels
);
1114 static u32
sceAtracGetLoopStatus(int atracID
, u32 loopNumAddr
, u32 statusAddr
) {
1115 Atrac
*atrac
= getAtrac(atracID
);
1117 ERROR_LOG(ME
, "sceAtracGetLoopStatus(%i, %08x, %08x): bad atrac ID", atracID
, loopNumAddr
, statusAddr
);
1118 return ATRAC_ERROR_BAD_ATRACID
;
1119 } else if (!atrac
->data_buf
) {
1120 ERROR_LOG(ME
, "sceAtracGetLoopStatus(%i, %08x, %08x): no data", atracID
, loopNumAddr
, statusAddr
);
1121 return ATRAC_ERROR_NO_DATA
;
1123 DEBUG_LOG(ME
, "sceAtracGetLoopStatus(%i, %08x, %08x)", atracID
, loopNumAddr
, statusAddr
);
1124 if (Memory::IsValidAddress(loopNumAddr
))
1125 Memory::Write_U32(atrac
->loopNum
, loopNumAddr
);
1126 // return audio's loopinfo in at3 file
1127 if (Memory::IsValidAddress(statusAddr
)) {
1128 if (atrac
->loopinfoNum
> 0)
1129 Memory::Write_U32(1, statusAddr
);
1131 Memory::Write_U32(0, statusAddr
);
1137 static u32
sceAtracGetInternalErrorInfo(int atracID
, u32 errorAddr
) {
1138 Atrac
*atrac
= getAtrac(atracID
);
1140 ERROR_LOG(ME
, "sceAtracGetInternalErrorInfo(%i, %08x): bad atrac ID", atracID
, errorAddr
);
1141 return ATRAC_ERROR_BAD_ATRACID
;
1142 } else if (!atrac
->data_buf
) {
1143 WARN_LOG(ME
, "sceAtracGetInternalErrorInfo(%i, %08x): no data", atracID
, errorAddr
);
1144 return ATRAC_ERROR_NO_DATA
;
1146 ERROR_LOG(ME
, "UNIMPL sceAtracGetInternalErrorInfo(%i, %08x)", atracID
, errorAddr
);
1147 if (Memory::IsValidAddress(errorAddr
))
1148 Memory::Write_U32(0, errorAddr
);
1153 static u32
sceAtracGetMaxSample(int atracID
, u32 maxSamplesAddr
) {
1154 Atrac
*atrac
= getAtrac(atracID
);
1156 ERROR_LOG(ME
, "sceAtracGetMaxSample(%i, %08x): bad atrac ID", atracID
, maxSamplesAddr
);
1157 return ATRAC_ERROR_BAD_ATRACID
;
1158 } else if (!atrac
->data_buf
) {
1159 ERROR_LOG(ME
, "sceAtracGetMaxSample(%i, %08x): no data", atracID
, maxSamplesAddr
);
1160 return ATRAC_ERROR_NO_DATA
;
1162 DEBUG_LOG(ME
, "sceAtracGetMaxSample(%i, %08x)", atracID
, maxSamplesAddr
);
1163 if (Memory::IsValidAddress(maxSamplesAddr
)) {
1164 int atracSamplesPerFrame
= (atrac
->codecType
== PSP_MODE_AT_3_PLUS
? ATRAC3PLUS_MAX_SAMPLES
: ATRAC3_MAX_SAMPLES
);
1165 Memory::Write_U32(atracSamplesPerFrame
, maxSamplesAddr
);
1171 static u32
sceAtracGetNextDecodePosition(int atracID
, u32 outposAddr
) {
1172 Atrac
*atrac
= getAtrac(atracID
);
1174 ERROR_LOG(ME
, "sceAtracGetNextDecodePosition(%i, %08x): bad atrac ID", atracID
, outposAddr
);
1175 return ATRAC_ERROR_BAD_ATRACID
;
1176 } else if (!atrac
->data_buf
) {
1177 ERROR_LOG(ME
, "sceAtracGetNextDecodePosition(%i, %08x): no data", atracID
, outposAddr
);
1178 return ATRAC_ERROR_NO_DATA
;
1180 DEBUG_LOG(ME
, "sceAtracGetNextDecodePosition(%i, %08x)", atracID
, outposAddr
);
1181 if (atrac
->currentSample
>= atrac
->endSample
) {
1182 if (Memory::IsValidAddress(outposAddr
))
1183 Memory::Write_U32(0, outposAddr
);
1184 return ATRAC_ERROR_ALL_DATA_DECODED
;
1186 if (Memory::IsValidAddress(outposAddr
))
1187 Memory::Write_U32(atrac
->currentSample
, outposAddr
);
1193 static u32
sceAtracGetNextSample(int atracID
, u32 outNAddr
) {
1194 Atrac
*atrac
= getAtrac(atracID
);
1196 ERROR_LOG(ME
, "sceAtracGetNextSample(%i, %08x): bad atrac ID", atracID
, outNAddr
);
1197 return ATRAC_ERROR_BAD_ATRACID
;
1198 } else if (!atrac
->data_buf
) {
1199 ERROR_LOG(ME
, "sceAtracGetNextSample(%i, %08x): no data", atracID
, outNAddr
);
1200 return ATRAC_ERROR_NO_DATA
;
1202 if (atrac
->currentSample
>= atrac
->endSample
) {
1203 if (Memory::IsValidAddress(outNAddr
))
1204 Memory::Write_U32(0, outNAddr
);
1205 DEBUG_LOG(ME
, "sceAtracGetNextSample(%i, %08x): 0 samples left", atracID
, outNAddr
);
1208 u32 atracSamplesPerFrame
= (atrac
->codecType
== PSP_MODE_AT_3_PLUS
? ATRAC3PLUS_MAX_SAMPLES
: ATRAC3_MAX_SAMPLES
);
1209 // Some kind of header size?
1210 u32 firstOffsetExtra
= atrac
->codecType
== PSP_CODEC_AT3PLUS
? 368 : 69;
1211 // It seems like the PSP aligns the sample position to 0x800...?
1212 u32 skipSamples
= atrac
->firstSampleoffset
+ firstOffsetExtra
;
1213 u32 firstSamples
= (atracSamplesPerFrame
- skipSamples
) % atracSamplesPerFrame
;
1214 u32 numSamples
= atrac
->endSample
- atrac
->currentSample
;
1215 if (atrac
->currentSample
== 0 && firstSamples
!= 0) {
1216 numSamples
= firstSamples
;
1218 u32 unalignedSamples
= (skipSamples
+ atrac
->currentSample
) % atracSamplesPerFrame
;
1219 if (unalignedSamples
!= 0) {
1220 // We're off alignment, possibly due to a loop. Force it back on.
1221 numSamples
= atracSamplesPerFrame
- unalignedSamples
;
1223 if (numSamples
> atracSamplesPerFrame
)
1224 numSamples
= atracSamplesPerFrame
;
1225 if (Memory::IsValidAddress(outNAddr
))
1226 Memory::Write_U32(numSamples
, outNAddr
);
1227 DEBUG_LOG(ME
, "sceAtracGetNextSample(%i, %08x): %d samples left", atracID
, outNAddr
, numSamples
);
1233 static u32
sceAtracGetRemainFrame(int atracID
, u32 remainAddr
) {
1234 Atrac
*atrac
= getAtrac(atracID
);
1236 ERROR_LOG(ME
, "sceAtracGetRemainFrame(%i, %08x): bad atrac ID", atracID
, remainAddr
);
1237 return ATRAC_ERROR_BAD_ATRACID
;
1238 } else if (!atrac
->data_buf
) {
1239 ERROR_LOG(ME
, "sceAtracGetRemainFrame(%i, %08x): no data", atracID
, remainAddr
);
1240 return ATRAC_ERROR_NO_DATA
;
1242 if (Memory::IsValidAddress(remainAddr
)) {
1243 Memory::Write_U32(atrac
->getRemainFrames(), remainAddr
);
1244 DEBUG_LOG(ME
, "sceAtracGetRemainFrame(%i, %08x[%d])", atracID
, remainAddr
, atrac
->getRemainFrames());
1247 DEBUG_LOG_REPORT(ME
, "sceAtracGetRemainFrame(%i, %08x[%d]) invalid address", atracID
, remainAddr
, atrac
->getRemainFrames());
1248 // Let sceAtracGetStreamDataInfo() know to set the full filled buffer .
1249 atrac
->resetBuffer
= true;
1255 static u32
sceAtracGetSecondBufferInfo(int atracID
, u32 outposAddr
, u32 outBytesAddr
) {
1256 Atrac
*atrac
= getAtrac(atracID
);
1258 ERROR_LOG(ME
, "sceAtracGetSecondBufferInfo(%i, %08x, %08x): bad atrac ID", atracID
, outposAddr
, outBytesAddr
);
1259 return ATRAC_ERROR_BAD_ATRACID
;
1260 } else if (!atrac
->data_buf
) {
1261 ERROR_LOG(ME
, "sceAtracGetSecondBufferInfo(%i, %08x, %08x): no data", atracID
, outposAddr
, outBytesAddr
);
1262 return ATRAC_ERROR_NO_DATA
;
1264 ERROR_LOG(ME
, "sceAtracGetSecondBufferInfo(%i, %08x, %08x)", atracID
, outposAddr
, outBytesAddr
);
1265 if (Memory::IsValidAddress(outposAddr
) && atrac
)
1266 Memory::Write_U32(atrac
->second
.fileoffset
, outposAddr
);
1267 if (Memory::IsValidAddress(outBytesAddr
) && atrac
)
1268 Memory::Write_U32(atrac
->second
.writableBytes
, outBytesAddr
);
1270 // TODO: Maybe don't write the above?
1271 return ATRAC_ERROR_SECOND_BUFFER_NOT_NEEDED
;
1274 static u32
sceAtracGetSoundSample(int atracID
, u32 outEndSampleAddr
, u32 outLoopStartSampleAddr
, u32 outLoopEndSampleAddr
) {
1275 Atrac
*atrac
= getAtrac(atracID
);
1277 ERROR_LOG(ME
, "sceAtracGetSoundSample(%i, %08x, %08x, %08x): bad atrac ID", atracID
, outEndSampleAddr
, outLoopStartSampleAddr
, outLoopEndSampleAddr
);
1278 return ATRAC_ERROR_BAD_ATRACID
;
1279 } else if (!atrac
->data_buf
) {
1280 ERROR_LOG(ME
, "sceAtracGetSoundSample(%i, %08x, %08x, %08x): no data", atracID
, outEndSampleAddr
, outLoopStartSampleAddr
, outLoopEndSampleAddr
);
1281 return ATRAC_ERROR_NO_DATA
;
1283 if (Memory::IsValidAddress(outEndSampleAddr
))
1284 Memory::Write_U32(atrac
->endSample
- 1, outEndSampleAddr
);
1285 if (Memory::IsValidAddress(outLoopStartSampleAddr
))
1286 Memory::Write_U32(atrac
->loopStartSample
, outLoopStartSampleAddr
);
1287 if (Memory::IsValidAddress(outLoopEndSampleAddr
))
1288 Memory::Write_U32(atrac
->loopEndSample
, outLoopEndSampleAddr
);
1289 if (Memory::IsValidAddress(outEndSampleAddr
) && (Memory::IsValidAddress(outLoopStartSampleAddr
)) && (Memory::IsValidAddress(outLoopEndSampleAddr
)))
1290 DEBUG_LOG(ME
, "sceAtracGetSoundSample(%i, %08x[%08x], %08x[%d], %08x[%d])", atracID
, outEndSampleAddr
, atrac
->endSample
- 1, outLoopStartSampleAddr
, atrac
->loopStartSample
, outLoopEndSampleAddr
, atrac
->loopEndSample
);
1292 DEBUG_LOG_REPORT(ME
, "sceAtracGetSoundSample(%i, %08x[%08x], %08x[%d], %08x[%d]) invalid address", atracID
, outEndSampleAddr
, atrac
->endSample
- 1, outLoopStartSampleAddr
, atrac
->loopStartSample
, outLoopEndSampleAddr
, atrac
->loopEndSample
);
1298 // Games call this function to get some info for add more stream data,
1299 // such as where the data read from, where the data add to,
1300 // and how many bytes are allowed to add.
1301 static u32
sceAtracGetStreamDataInfo(int atracID
, u32 writeAddr
, u32 writableBytesAddr
, u32 readOffsetAddr
) {
1302 Atrac
*atrac
= getAtrac(atracID
);
1304 ERROR_LOG(ME
, "sceAtracGetStreamDataInfo(%i, %08x, %08x, %08x): bad atrac ID", atracID
, writeAddr
, writableBytesAddr
, readOffsetAddr
);
1305 return ATRAC_ERROR_BAD_ATRACID
;
1306 } else if (!atrac
->data_buf
) {
1307 ERROR_LOG(ME
, "sceAtracGetStreamDataInfo(%i, %08x, %08x, %08x): no data", atracID
, writeAddr
, writableBytesAddr
, readOffsetAddr
);
1308 return ATRAC_ERROR_NO_DATA
;
1310 // TODO: Is this check even needed? More testing is needed on writableBytes.
1311 if (atrac
->resetBuffer
) {
1312 // Reset temp buf for adding more stream data and set full filled buffer.
1313 atrac
->first
.writableBytes
= std::min(atrac
->first
.filesize
- atrac
->first
.size
, atrac
->atracBufSize
);
1315 atrac
->first
.writableBytes
= std::min(atrac
->first
.filesize
- atrac
->first
.size
, atrac
->first
.writableBytes
);
1318 atrac
->first
.offset
= 0;
1319 if (Memory::IsValidAddress(writeAddr
))
1320 Memory::Write_U32(atrac
->first
.addr
, writeAddr
);
1321 if (Memory::IsValidAddress(writableBytesAddr
))
1322 Memory::Write_U32(atrac
->first
.writableBytes
, writableBytesAddr
);
1323 if (Memory::IsValidAddress(readOffsetAddr
))
1324 Memory::Write_U32(atrac
->first
.fileoffset
, readOffsetAddr
);
1325 if ((Memory::IsValidAddress(writeAddr
)) && (Memory::IsValidAddress(writableBytesAddr
)) && (Memory::IsValidAddress(readOffsetAddr
)))
1326 DEBUG_LOG(ME
, "sceAtracGetStreamDataInfo(%i, %08x[%08x], %08x[%08x], %08x[%08x])", atracID
,
1327 writeAddr
, atrac
->first
.addr
,
1328 writableBytesAddr
, atrac
->first
.writableBytes
,
1329 readOffsetAddr
, atrac
->first
.fileoffset
);
1331 //TODO:Use JPCSPtrace to correct
1332 DEBUG_LOG_REPORT(ME
, "sceAtracGetStreamDataInfo(%i, %08x[%08x], %08x[%08x], %08x[%08x]) invalid address", atracID
,
1333 writeAddr
, atrac
->first
.addr
,
1334 writableBytesAddr
, atrac
->first
.writableBytes
,
1335 readOffsetAddr
, atrac
->first
.fileoffset
);
1340 static u32
sceAtracReleaseAtracID(int atracID
) {
1341 INFO_LOG(ME
, "sceAtracReleaseAtracID(%i)", atracID
);
1342 return deleteAtrac(atracID
);
1345 static u32
sceAtracResetPlayPosition(int atracID
, int sample
, int bytesWrittenFirstBuf
, int bytesWrittenSecondBuf
) {
1346 Atrac
*atrac
= getAtrac(atracID
);
1348 ERROR_LOG(ME
, "sceAtracResetPlayPosition(%i, %i, %i, %i): bad atrac ID", atracID
, sample
, bytesWrittenFirstBuf
, bytesWrittenSecondBuf
);
1349 return ATRAC_ERROR_BAD_ATRACID
;
1350 } else if (!atrac
->data_buf
) {
1351 ERROR_LOG(ME
, "sceAtracResetPlayPosition(%i, %i, %i, %i): no data", atracID
, sample
, bytesWrittenFirstBuf
, bytesWrittenSecondBuf
);
1352 return ATRAC_ERROR_NO_DATA
;
1354 INFO_LOG(ME
, "sceAtracResetPlayPosition(%i, %i, %i, %i)", atracID
, sample
, bytesWrittenFirstBuf
, bytesWrittenSecondBuf
);
1355 if (bytesWrittenFirstBuf
> 0)
1356 sceAtracAddStreamData(atracID
, bytesWrittenFirstBuf
);
1358 if ((atrac
->codecType
== PSP_MODE_AT_3
|| atrac
->codecType
== PSP_MODE_AT_3_PLUS
) && atrac
->pCodecCtx
) {
1359 atrac
->SeekToSample(sample
);
1361 #endif // USE_FFMPEG
1363 atrac
->currentSample
= sample
;
1364 atrac
->decodePos
= atrac
->getDecodePosBySample(sample
);
1371 static int _AtracReadbuffer(void *opaque
, uint8_t *buf
, int buf_size
) {
1372 Atrac
*atrac
= (Atrac
*)opaque
;
1373 if (atrac
->bufferPos
> atrac
->first
.filesize
)
1375 int size
= std::min((int)atrac
->atracBufSize
, buf_size
);
1376 size
= std::max(std::min(((int)atrac
->first
.size
- (int)atrac
->bufferPos
), size
), 0);
1378 memcpy(buf
, atrac
->data_buf
+ atrac
->bufferPos
, size
);
1379 atrac
->bufferPos
+= size
;
1383 static int64_t _AtracSeekbuffer(void *opaque
, int64_t offset
, int whence
) {
1384 Atrac
*atrac
= (Atrac
*)opaque
;
1385 if (offset
> atrac
->first
.filesize
)
1390 atrac
->bufferPos
= (u32
)offset
;
1393 atrac
->bufferPos
+= (u32
)offset
;
1396 atrac
->bufferPos
= atrac
->first
.filesize
- (u32
)offset
;
1400 return atrac
->first
.filesize
;
1403 return atrac
->bufferPos
;
1406 #endif // USE_FFMPEG
1409 static int __AtracUpdateOutputMode(Atrac
*atrac
, int wanted_channels
) {
1410 if (atrac
->pSwrCtx
&& atrac
->atracOutputChannels
== wanted_channels
)
1412 atrac
->atracOutputChannels
= wanted_channels
;
1413 int64_t wanted_channel_layout
= av_get_default_channel_layout(wanted_channels
);
1414 int64_t dec_channel_layout
= av_get_default_channel_layout(atrac
->atracChannels
);
1420 wanted_channel_layout
,
1422 atrac
->pCodecCtx
->sample_rate
,
1424 atrac
->pCodecCtx
->sample_fmt
,
1425 atrac
->pCodecCtx
->sample_rate
,
1429 if (!atrac
->pSwrCtx
) {
1430 ERROR_LOG(ME
, "swr_alloc_set_opts: Could not allocate resampler context");
1433 if (swr_init(atrac
->pSwrCtx
) < 0) {
1434 ERROR_LOG(ME
, "swr_init: Failed to initialize the resampling context");
1439 #endif // USE_FFMPEG
1441 int __AtracSetContext(Atrac
*atrac
) {
1445 u8
* tempbuf
= (u8
*)av_malloc(atrac
->atracBufSize
);
1447 atrac
->pFormatCtx
= avformat_alloc_context();
1448 atrac
->pAVIOCtx
= avio_alloc_context(tempbuf
, atrac
->atracBufSize
, 0, (void*)atrac
, _AtracReadbuffer
, NULL
, _AtracSeekbuffer
);
1449 atrac
->pFormatCtx
->pb
= atrac
->pAVIOCtx
;
1452 // Load audio buffer
1453 if((ret
= avformat_open_input((AVFormatContext
**)&atrac
->pFormatCtx
, NULL
, NULL
, NULL
)) != 0) {
1454 ERROR_LOG(ME
, "avformat_open_input: Cannot open input %d", ret
);
1455 // TODO: This is not exactly correct, but if the header is right and there's not enough data
1456 // (which is likely the case here), this is the correct error.
1457 return ATRAC_ERROR_ALL_DATA_DECODED
;
1460 if((ret
= avformat_find_stream_info(atrac
->pFormatCtx
, NULL
)) < 0) {
1461 ERROR_LOG(ME
, "avformat_find_stream_info: Cannot find stream information %d", ret
);
1466 // select the audio stream
1467 ret
= av_find_best_stream(atrac
->pFormatCtx
, AVMEDIA_TYPE_AUDIO
, -1, -1, &pCodec
, 0);
1469 if (ret
== AVERROR_DECODER_NOT_FOUND
) {
1470 ERROR_LOG(HLE
, "av_find_best_stream: No appropriate decoder found");
1472 ERROR_LOG(HLE
, "av_find_best_stream: Cannot find an audio stream in the input file %d", ret
);
1476 atrac
->audio_stream_index
= ret
;
1477 atrac
->pCodecCtx
= atrac
->pFormatCtx
->streams
[atrac
->audio_stream_index
]->codec
;
1479 // Appears we need to force mono in some cases. (See CPkmn's comments in issue #4248)
1480 if (atrac
->atracChannels
== 1)
1481 atrac
->pCodecCtx
->channel_layout
= AV_CH_LAYOUT_MONO
;
1483 // Explicitly set the block_align value (needed by newer FFmpeg versions, see #5772.)
1484 if (atrac
->pCodecCtx
->block_align
== 0) {
1485 atrac
->pCodecCtx
->block_align
= atrac
->atracBytesPerFrame
;
1488 atrac
->pCodecCtx
->request_sample_fmt
= AV_SAMPLE_FMT_S16
;
1489 if ((ret
= avcodec_open2(atrac
->pCodecCtx
, pCodec
, NULL
)) < 0) {
1490 ERROR_LOG(ME
, "avcodec_open2: Cannot open audio decoder %d", ret
);
1494 if ((ret
= __AtracUpdateOutputMode(atrac
, atrac
->atracOutputChannels
)) < 0)
1497 // alloc audio frame
1498 atrac
->pFrame
= av_frame_alloc();
1499 atrac
->packet
= new AVPacket
;
1500 av_init_packet(atrac
->packet
);
1501 atrac
->packet
->data
= nullptr;
1502 atrac
->packet
->size
= 0;
1503 // reinit decodePos, because ffmpeg had changed it.
1504 atrac
->decodePos
= 0;
1510 static int _AtracSetData(Atrac
*atrac
, u32 buffer
, u32 bufferSize
) {
1511 if (atrac
->first
.size
> atrac
->first
.filesize
)
1512 atrac
->first
.size
= atrac
->first
.filesize
;
1513 atrac
->first
.fileoffset
= atrac
->first
.size
;
1515 // got the size of temp buf, and calculate writableBytes and offset
1516 atrac
->atracBufSize
= bufferSize
;
1517 atrac
->first
.writableBytes
= (u32
)std::max((int)bufferSize
- (int)atrac
->first
.size
, 0);
1518 atrac
->first
.offset
= atrac
->first
.size
;
1520 // some games may reuse an atracID for playing sound
1521 atrac
->CleanStuff();
1524 if (atrac
->codecType
== PSP_MODE_AT_3
) {
1525 if (atrac
->atracChannels
== 1) {
1526 WARN_LOG(ME
, "This is an atrac3 mono audio");
1528 WARN_LOG(ME
, "This is an atrac3 stereo audio");
1532 atrac
->data_buf
= new u8
[atrac
->first
.filesize
];
1533 u32 copybytes
= std::min(bufferSize
, atrac
->first
.filesize
);
1534 Memory::Memcpy(atrac
->data_buf
, buffer
, copybytes
);
1535 return __AtracSetContext(atrac
);
1536 #endif // USE_FFMPEG
1538 } else if (atrac
->codecType
== PSP_MODE_AT_3_PLUS
) {
1539 if (atrac
->atracChannels
== 1) {
1540 WARN_LOG(ME
, "This is an atrac3+ mono audio");
1542 WARN_LOG(ME
, "This is an atrac3+ stereo audio");
1544 atrac
->data_buf
= new u8
[atrac
->first
.filesize
];
1545 u32 copybytes
= std::min(bufferSize
, atrac
->first
.filesize
);
1546 Memory::Memcpy(atrac
->data_buf
, buffer
, copybytes
);
1547 return __AtracSetContext(atrac
);
1554 static int _AtracSetData(int atracID
, u32 buffer
, u32 bufferSize
, bool needReturnAtracID
= false) {
1555 Atrac
*atrac
= getAtrac(atracID
);
1558 int ret
= _AtracSetData(atrac
, buffer
, bufferSize
);
1559 if (needReturnAtracID
&& ret
>= 0)
1561 // not sure the real delay time
1562 return hleDelayResult(ret
, "atrac set data", 100);
1565 static u32
sceAtracSetHalfwayBuffer(int atracID
, u32 halfBuffer
, u32 readSize
, u32 halfBufferSize
) {
1566 Atrac
*atrac
= getAtrac(atracID
);
1568 ERROR_LOG(ME
, "sceAtracSetHalfwayBuffer(%i, %08x, %8x, %8x): bad atrac ID", atracID
, halfBuffer
, readSize
, halfBufferSize
);
1569 return ATRAC_ERROR_BAD_ATRACID
;
1572 INFO_LOG(ME
, "sceAtracSetHalfwayBuffer(%i, %08x, %8x, %8x)", atracID
, halfBuffer
, readSize
, halfBufferSize
);
1573 if (readSize
> halfBufferSize
)
1574 return ATRAC_ERROR_INCORRECT_READ_SIZE
;
1577 if (atrac
!= NULL
) {
1578 atrac
->first
.addr
= halfBuffer
;
1579 atrac
->first
.size
= readSize
;
1580 ret
= atrac
->Analyze();
1582 ERROR_LOG_REPORT(ME
, "sceAtracSetHalfwayBuffer(%i, %08x, %8x, %8x): bad data", atracID
, halfBuffer
, readSize
, halfBufferSize
);
1585 atrac
->atracOutputChannels
= 2;
1586 ret
= _AtracSetData(atracID
, halfBuffer
, halfBufferSize
);
1591 static u32
sceAtracSetSecondBuffer(int atracID
, u32 secondBuffer
, u32 secondBufferSize
) {
1592 Atrac
*atrac
= getAtrac(atracID
);
1594 ERROR_LOG(ME
, "sceAtracSetSecondBuffer(%i, %08x, %8x): bad atrac ID", atracID
, secondBuffer
, secondBufferSize
);
1595 return ATRAC_ERROR_BAD_ATRACID
;
1596 } else if (!atrac
->data_buf
) {
1597 ERROR_LOG(ME
, "sceAtracSetSecondBuffer(%i, %08x, %8x): no data", atracID
, secondBuffer
, secondBufferSize
);
1598 return ATRAC_ERROR_NO_DATA
;
1601 ERROR_LOG_REPORT(ME
, "UNIMPL sceAtracSetSecondBuffer(%i, %08x, %8x)", atracID
, secondBuffer
, secondBufferSize
);
1605 static u32
sceAtracSetData(int atracID
, u32 buffer
, u32 bufferSize
) {
1606 Atrac
*atrac
= getAtrac(atracID
);
1607 if (atrac
!= NULL
) {
1608 INFO_LOG(ME
, "sceAtracSetData(%i, %08x, %08x)", atracID
, buffer
, bufferSize
);
1609 atrac
->first
.addr
= buffer
;
1610 atrac
->first
.size
= bufferSize
;
1611 int ret
= atrac
->Analyze();
1613 ERROR_LOG_REPORT(ME
, "sceAtracSetData(%i, %08x, %08x): bad data", atracID
, buffer
, bufferSize
);
1614 } else if (atrac
->codecType
!= atracIDTypes
[atracID
]) {
1615 ERROR_LOG_REPORT(ME
, "sceAtracSetData(%i, %08x, %08x): atracID uses different codec type than data", atracID
, buffer
, bufferSize
);
1616 ret
= ATRAC_ERROR_WRONG_CODECTYPE
;
1618 atrac
->atracOutputChannels
= 2;
1619 ret
= _AtracSetData(atracID
, buffer
, bufferSize
);
1623 ERROR_LOG(ME
, "sceAtracSetData(%i, %08x, %08x): bad atrac ID", atracID
, buffer
, bufferSize
);
1624 return ATRAC_ERROR_BAD_ATRACID
;
1628 static int sceAtracSetDataAndGetID(u32 buffer
, int bufferSize
) {
1629 // A large value happens in Tales of VS, and isn't handled somewhere properly as a u32.
1630 // It's impossible for it to be that big anyway, so cap it.
1631 if (bufferSize
< 0) {
1632 WARN_LOG(ME
, "sceAtracSetDataAndGetID(%08x, %08x): negative bufferSize", buffer
, bufferSize
);
1633 bufferSize
= 0x10000000;
1635 Atrac
*atrac
= new Atrac();
1636 atrac
->first
.addr
= buffer
;
1637 atrac
->first
.size
= bufferSize
;
1638 int ret
= atrac
->Analyze();
1640 ERROR_LOG_REPORT(ME
, "sceAtracSetDataAndGetID(%08x, %08x): bad data", buffer
, bufferSize
);
1644 atrac
->atracOutputChannels
= 2;
1645 int atracID
= createAtrac(atrac
);
1647 ERROR_LOG(ME
, "sceAtracSetDataAndGetID(%08x, %08x): no free ID", buffer
, bufferSize
);
1651 INFO_LOG(ME
, "%d=sceAtracSetDataAndGetID(%08x, %08x)", atracID
, buffer
, bufferSize
);
1652 return _AtracSetData(atracID
, buffer
, bufferSize
, true);
1655 static int sceAtracSetHalfwayBufferAndGetID(u32 halfBuffer
, u32 readSize
, u32 halfBufferSize
) {
1656 if (readSize
> halfBufferSize
) {
1657 ERROR_LOG(ME
, "sceAtracSetHalfwayBufferAndGetID(%08x, %08x, %08x): incorrect read size", halfBuffer
, readSize
, halfBufferSize
);
1658 return ATRAC_ERROR_INCORRECT_READ_SIZE
;
1660 Atrac
*atrac
= new Atrac();
1661 atrac
->first
.addr
= halfBuffer
;
1662 atrac
->first
.size
= readSize
;
1663 int ret
= atrac
->Analyze();
1665 ERROR_LOG_REPORT(ME
, "sceAtracSetHalfwayBufferAndGetID(%08x, %08x, %08x): bad data", halfBuffer
, readSize
, halfBufferSize
);
1669 atrac
->atracOutputChannels
= 2;
1670 int atracID
= createAtrac(atrac
);
1672 ERROR_LOG(ME
, "sceAtracSetHalfwayBufferAndGetID(%08x, %08x, %08x): no free ID", halfBuffer
, readSize
, halfBufferSize
);
1676 INFO_LOG(ME
, "%d=sceAtracSetHalfwayBufferAndGetID(%08x, %08x, %08x)", atracID
, halfBuffer
, readSize
, halfBufferSize
);
1677 return _AtracSetData(atracID
, halfBuffer
, halfBufferSize
, true);
1680 static u32
sceAtracStartEntry() {
1681 ERROR_LOG_REPORT(ME
, "UNIMPL sceAtracStartEntry()");
1685 static u32
sceAtracSetLoopNum(int atracID
, int loopNum
) {
1686 Atrac
*atrac
= getAtrac(atracID
);
1688 ERROR_LOG(ME
, "sceAtracSetLoopNum(%i, %i): bad atrac ID", atracID
, loopNum
);
1689 return ATRAC_ERROR_BAD_ATRACID
;
1690 } else if (!atrac
->data_buf
) {
1691 ERROR_LOG(ME
, "sceAtracSetLoopNum(%i, %i): no data", atracID
, loopNum
);
1692 return ATRAC_ERROR_NO_DATA
;
1694 if (atrac
->loopinfoNum
== 0) {
1695 DEBUG_LOG(ME
, "sceAtracSetLoopNum(%i, %i): error: no loop information", atracID
, loopNum
);
1696 return ATRAC_ERROR_NO_LOOP_INFORMATION
;
1699 DEBUG_LOG(ME
, "sceAtracSetLoopNum(%i, %i)", atracID
, loopNum
);
1700 atrac
->loopNum
= loopNum
;
1701 if (loopNum
!= 0 && atrac
->loopinfoNum
== 0) {
1702 // Just loop the whole audio
1703 atrac
->loopStartSample
= 0;
1704 atrac
->loopEndSample
= atrac
->endSample
;
1710 static int sceAtracReinit(int at3Count
, int at3plusCount
) {
1711 for (int i
= 0; i
< PSP_NUM_ATRAC_IDS
; ++i
) {
1712 if (atracIDs
[i
] != NULL
) {
1713 ERROR_LOG_REPORT(ME
, "sceAtracReinit(%d, %d): cannot reinit while IDs in use", at3Count
, at3plusCount
);
1714 return SCE_KERNEL_ERROR_BUSY
;
1718 memset(atracIDTypes
, 0, sizeof(atracIDTypes
));
1720 int space
= PSP_NUM_ATRAC_IDS
;
1722 // This seems to deinit things. Mostly, it cause a reschedule on next deinit (but -1, -1 does not.)
1723 if (at3Count
== 0 && at3plusCount
== 0) {
1724 INFO_LOG(ME
, "sceAtracReinit(%d, %d): deinit", at3Count
, at3plusCount
);
1725 atracInited
= false;
1726 return hleDelayResult(0, "atrac reinit", 200);
1729 // First, ATRAC3+. These IDs seem to cost double (probably memory.)
1730 // Intentionally signed. 9999 tries to allocate, -1 does not.
1731 for (int i
= 0; i
< at3plusCount
; ++i
) {
1734 atracIDTypes
[next
++] = PSP_MODE_AT_3_PLUS
;
1737 for (int i
= 0; i
< at3Count
; ++i
) {
1740 atracIDTypes
[next
++] = PSP_MODE_AT_3
;
1744 // If we ran out of space, we still initialize some, but return an error.
1745 int result
= space
>= 0 ? 0 : (int)SCE_KERNEL_ERROR_OUT_OF_MEMORY
;
1746 if (atracInited
|| next
== 0) {
1747 INFO_LOG(ME
, "sceAtracReinit(%d, %d)", at3Count
, at3plusCount
);
1751 INFO_LOG(ME
, "sceAtracReinit(%d, %d): init", at3Count
, at3plusCount
);
1753 return hleDelayResult(result
, "atrac reinit", 400);
1757 static int sceAtracGetOutputChannel(int atracID
, u32 outputChanPtr
) {
1758 Atrac
*atrac
= getAtrac(atracID
);
1760 ERROR_LOG(ME
, "sceAtracGetOutputChannel(%i, %08x): bad atrac ID", atracID
, outputChanPtr
);
1761 return ATRAC_ERROR_BAD_ATRACID
;
1762 } else if (!atrac
->data_buf
) {
1763 ERROR_LOG(ME
, "sceAtracGetOutputChannel(%i, %08x): no data", atracID
, outputChanPtr
);
1764 return ATRAC_ERROR_NO_DATA
;
1766 DEBUG_LOG(ME
, "sceAtracGetOutputChannel(%i, %08x)", atracID
, outputChanPtr
);
1767 if (Memory::IsValidAddress(outputChanPtr
))
1768 Memory::Write_U32(atrac
->atracOutputChannels
, outputChanPtr
);
1773 static int sceAtracIsSecondBufferNeeded(int atracID
) {
1774 Atrac
*atrac
= getAtrac(atracID
);
1776 ERROR_LOG(ME
, "sceAtracIsSecondBufferNeeded(%i): bad atrac ID", atracID
);
1777 return ATRAC_ERROR_BAD_ATRACID
;
1778 } else if (!atrac
->data_buf
) {
1779 ERROR_LOG(ME
, "sceAtracIsSecondBufferNeeded(%i): no data", atracID
);
1780 return ATRAC_ERROR_NO_DATA
;
1782 WARN_LOG(ME
, "UNIMPL sceAtracIsSecondBufferNeeded(%i)", atracID
);
1786 static int sceAtracSetMOutHalfwayBuffer(int atracID
, u32 buffer
, u32 readSize
, u32 bufferSize
) {
1787 Atrac
*atrac
= getAtrac(atracID
);
1789 ERROR_LOG(ME
, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x): bad atrac ID", atracID
, buffer
, readSize
, bufferSize
);
1790 return ATRAC_ERROR_BAD_ATRACID
;
1793 INFO_LOG(ME
, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x)", atracID
, buffer
, readSize
, bufferSize
);
1794 if (readSize
> bufferSize
)
1795 return ATRAC_ERROR_INCORRECT_READ_SIZE
;
1798 if (atrac
!= NULL
) {
1799 atrac
->first
.addr
= buffer
;
1800 atrac
->first
.size
= readSize
;
1801 ret
= atrac
->Analyze();
1803 ERROR_LOG_REPORT(ME
, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x): bad data", atracID
, buffer
, readSize
, bufferSize
);
1806 if (atrac
->atracChannels
!= 1) {
1807 ERROR_LOG_REPORT(ME
, "sceAtracSetMOutHalfwayBuffer(%i, %08x, %08x, %08x): not mono data", atracID
, buffer
, readSize
, bufferSize
);
1808 ret
= ATRAC_ERROR_NOT_MONO
;
1809 // It seems it still sets the data.
1810 atrac
->atracOutputChannels
= 2;
1811 _AtracSetData(atrac
, buffer
, bufferSize
);
1814 atrac
->atracOutputChannels
= 1;
1815 ret
= _AtracSetData(atracID
, buffer
, bufferSize
);
1821 static u32
sceAtracSetMOutData(int atracID
, u32 buffer
, u32 bufferSize
) {
1822 Atrac
*atrac
= getAtrac(atracID
);
1824 ERROR_LOG(ME
, "sceAtracSetMOutData(%i, %08x, %08x): bad atrac ID", atracID
, buffer
, bufferSize
);
1825 return ATRAC_ERROR_BAD_ATRACID
;
1828 // This doesn't seem to be part of any available libatrac3plus library.
1829 WARN_LOG_REPORT(ME
, "sceAtracSetMOutData(%i, %08x, %08x)", atracID
, buffer
, bufferSize
);
1831 // TODO: What is the proper error code here?
1833 if (atrac
!= NULL
) {
1834 atrac
->first
.addr
= buffer
;
1835 atrac
->first
.size
= bufferSize
;
1836 ret
= atrac
->Analyze();
1838 ERROR_LOG_REPORT(ME
, "sceAtracSetMOutData(%i, %08x, %08x): bad data", atracID
, buffer
, bufferSize
);
1841 if (atrac
->atracChannels
!= 1) {
1842 ERROR_LOG_REPORT(ME
, "sceAtracSetMOutData(%i, %08x, %08x): not mono data", atracID
, buffer
, bufferSize
);
1843 ret
= ATRAC_ERROR_NOT_MONO
;
1844 // It seems it still sets the data.
1845 atrac
->atracOutputChannels
= 2;
1846 _AtracSetData(atrac
, buffer
, bufferSize
);
1847 // Not sure of the real delay time.
1850 atrac
->atracOutputChannels
= 1;
1851 ret
= _AtracSetData(atracID
, buffer
, bufferSize
);
1857 static int sceAtracSetMOutDataAndGetID(u32 buffer
, u32 bufferSize
) {
1858 Atrac
*atrac
= new Atrac();
1859 atrac
->first
.addr
= buffer
;
1860 atrac
->first
.size
= bufferSize
;
1861 int ret
= atrac
->Analyze();
1863 ERROR_LOG_REPORT(ME
, "sceAtracSetMOutDataAndGetID(%08x, %08x): bad data", buffer
, bufferSize
);
1867 if (atrac
->atracChannels
!= 1) {
1868 ERROR_LOG_REPORT(ME
, "sceAtracSetMOutDataAndGetID(%08x, %08x): not mono data", buffer
, bufferSize
);
1870 return ATRAC_ERROR_NOT_MONO
;
1872 atrac
->atracOutputChannels
= 1;
1873 int atracID
= createAtrac(atrac
);
1875 ERROR_LOG(ME
, "sceAtracSetMOutDataAndGetID(%08x, %08x): no free ID", buffer
, bufferSize
);
1879 // This doesn't seem to be part of any available libatrac3plus library.
1880 WARN_LOG_REPORT(ME
, "%d=sceAtracSetMOutDataAndGetID(%08x, %08x)", atracID
, buffer
, bufferSize
);
1881 return _AtracSetData(atracID
, buffer
, bufferSize
, true);
1884 static int sceAtracSetMOutHalfwayBufferAndGetID(u32 halfBuffer
, u32 readSize
, u32 halfBufferSize
) {
1885 if (readSize
> halfBufferSize
) {
1886 ERROR_LOG(ME
, "sceAtracSetMOutHalfwayBufferAndGetID(%08x, %08x, %08x): incorrect read size", halfBuffer
, readSize
, halfBufferSize
);
1887 return ATRAC_ERROR_INCORRECT_READ_SIZE
;
1889 Atrac
*atrac
= new Atrac();
1890 atrac
->first
.addr
= halfBuffer
;
1891 atrac
->first
.size
= readSize
;
1892 int ret
= atrac
->Analyze();
1894 ERROR_LOG_REPORT(ME
, "sceAtracSetMOutHalfwayBufferAndGetID(%08x, %08x, %08x): bad data", halfBuffer
, readSize
, halfBufferSize
);
1898 if (atrac
->atracChannels
!= 1) {
1899 ERROR_LOG_REPORT(ME
, "sceAtracSetMOutHalfwayBufferAndGetID(%08x, %08x, %08x): not mono data", halfBuffer
, readSize
, halfBufferSize
);
1901 return ATRAC_ERROR_NOT_MONO
;
1903 atrac
->atracOutputChannels
= 1;
1904 int atracID
= createAtrac(atrac
);
1906 ERROR_LOG(ME
, "sceAtracSetMOutHalfwayBufferAndGetID(%08x, %08x, %08x): no free ID", halfBuffer
, readSize
, halfBufferSize
);
1910 INFO_LOG(ME
, "%d=sceAtracSetMOutHalfwayBufferAndGetID(%08x, %08x, %08x)", atracID
, halfBuffer
, readSize
, halfBufferSize
);
1911 return _AtracSetData(atracID
, halfBuffer
, halfBufferSize
, true);
1914 static int sceAtracSetAA3DataAndGetID(u32 buffer
, u32 bufferSize
, u32 fileSize
, u32 metadataSizeAddr
) {
1915 Atrac
*atrac
= new Atrac();
1916 atrac
->first
.addr
= buffer
;
1917 atrac
->first
.size
= bufferSize
;
1918 atrac
->first
.filesize
= fileSize
;
1919 int ret
= atrac
->AnalyzeAA3();
1921 ERROR_LOG(ME
, "sceAtracSetAA3DataAndGetID(%08x, %i, %i, %08x): bad data", buffer
, bufferSize
, fileSize
, metadataSizeAddr
);
1925 int atracID
= createAtrac(atrac
);
1927 ERROR_LOG(ME
, "sceAtracSetAA3DataAndGetID(%08x, %i, %i, %08x): no free ID", buffer
, bufferSize
, fileSize
, metadataSizeAddr
);
1931 WARN_LOG(ME
, "%d=sceAtracSetAA3DataAndGetID(%08x, %i, %i, %08x)", atracID
, buffer
, bufferSize
, fileSize
, metadataSizeAddr
);
1932 return _AtracSetData(atracID
, buffer
, bufferSize
, true);
1935 int _AtracGetIDByContext(u32 contextAddr
) {
1936 int atracID
= (int)Memory::Read_U32(contextAddr
+ 0xfc);
1938 Atrac
*atrac
= getAtrac(atracID
);
1940 __AtracUpdateOutputMode(atrac
, 1);
1941 #endif // USE_FFMPEG
1945 void _AtracGenarateContext(Atrac
*atrac
, SceAtracId
*context
) {
1946 context
->info
.buffer
= atrac
->first
.addr
;
1947 context
->info
.bufferByte
= atrac
->atracBufSize
;
1948 context
->info
.secondBuffer
= atrac
->second
.addr
;
1949 context
->info
.secondBufferByte
= atrac
->second
.size
;
1950 context
->info
.codec
= atrac
->codecType
;
1951 context
->info
.loopNum
= atrac
->loopNum
;
1952 context
->info
.loopStart
= atrac
->loopStartSample
> 0 ? atrac
->loopStartSample
: 0;
1953 context
->info
.loopEnd
= atrac
->loopEndSample
> 0 ? atrac
->loopEndSample
: 0;
1954 if (context
->info
.endSample
> 0) {
1955 // do not change info.state if this was not called at first time
1956 // In Sol Trigger, it would set info.state = 0x10 outside
1957 // TODO: Should we just keep this in PSP ram then, or something?
1958 } else if (!atrac
->data_buf
) {
1959 // State 1, no buffer yet.
1960 context
->info
.state
= 1;
1961 } else if (atrac
->first
.size
>= atrac
->first
.filesize
) {
1962 // state 2, all data loaded
1963 context
->info
.state
= 2;
1964 } else if (atrac
->loopinfoNum
== 0) {
1965 // state 3, lack some data, no loop info
1966 context
->info
.state
= 3;
1968 // state 6, lack some data, has loop info
1969 context
->info
.state
= 6;
1971 context
->info
.samplesPerChan
= (atrac
->codecType
== PSP_MODE_AT_3_PLUS
? ATRAC3PLUS_MAX_SAMPLES
: ATRAC3_MAX_SAMPLES
);
1972 context
->info
.sampleSize
= atrac
->atracBytesPerFrame
;
1973 context
->info
.numChan
= atrac
->atracChannels
;
1974 context
->info
.dataOff
= atrac
->dataOff
;
1975 context
->info
.endSample
= atrac
->endSample
;
1976 context
->info
.dataEnd
= atrac
->first
.filesize
;
1977 context
->info
.curOff
= atrac
->first
.size
;
1978 context
->info
.decodePos
= atrac
->getDecodePosBySample(atrac
->currentSample
);
1979 context
->info
.streamDataByte
= atrac
->first
.size
- atrac
->firstSampleoffset
;
1981 u8
* buf
= (u8
*)context
;
1982 *(u32
*)(buf
+ 0xfc) = atrac
->atracID
;
1985 static int _sceAtracGetContextAddress(int atracID
) {
1986 Atrac
*atrac
= getAtrac(atracID
);
1988 ERROR_LOG(ME
, "_sceAtracGetContextAddress(%i): bad atrac id", atracID
);
1991 if (!atrac
->atracContext
.IsValid()) {
1992 // allocate a new atracContext
1993 u32 contextsize
= 256;
1994 atrac
->atracContext
= kernelMemory
.Alloc(contextsize
, false, "Atrac Context");
1995 if (atrac
->atracContext
.IsValid())
1996 Memory::Memset(atrac
->atracContext
.ptr
, 0, 256);
1998 WARN_LOG(ME
, "%08x=_sceAtracGetContextAddress(%i): allocated new context", atrac
->atracContext
.ptr
, atracID
);
2001 WARN_LOG(ME
, "%08x=_sceAtracGetContextAddress(%i)", atrac
->atracContext
.ptr
, atracID
);
2002 if (atrac
->atracContext
.IsValid())
2003 _AtracGenarateContext(atrac
, atrac
->atracContext
);
2004 return atrac
->atracContext
.ptr
;
2007 struct At3HeaderMap
{
2013 bool Matches(const Atrac
*at
) const {
2014 return bytes
== at
->atracBytesPerFrame
&& channels
== at
->atracChannels
;
2018 static const u8 at3HeaderTemplate
[] ={0x52,0x49,0x46,0x46,0x3b,0xbe,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x20,0x00,0x00,0x00,0x70,0x02,0x02,0x00,0x44,0xac,0x00,0x00,0x4d,0x20,0x00,0x00,0xc0,0x00,0x00,0x00,0x0e,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x64,0x61,0x74,0x61,0xc0,0xbd,0x00,0x00};
2019 static const At3HeaderMap at3HeaderMap
[] = {
2020 { 0x00C0, 0x1, 0x8, 0x00 },
2021 { 0x0098, 0x1, 0x8, 0x00 },
2022 { 0x0180, 0x2, 0x10, 0x00 },
2023 { 0x0130, 0x2, 0x10, 0x00 },
2024 { 0x00C0, 0x2, 0x10, 0x01 }
2027 struct At3plusHeaderMap
{
2032 bool Matches(const Atrac
*at
) const {
2033 return bytes
== at
->atracBytesPerFrame
&& channels
== at
->atracChannels
;
2037 static const u8 at3plusHeaderTemplate
[] = { 0x52, 0x49, 0x46, 0x46, 0x00, 0xb5, 0xff, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x34, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0xa0, 0x1f, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x00, 0x22, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0xbf, 0xaa, 0x23, 0xe9, 0x58, 0xcb, 0x71, 0x44, 0xa1, 0x19, 0xff, 0xfa, 0x01, 0xe4, 0xce, 0x62, 0x01, 0x00, 0x28, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x61, 0x63, 0x74, 0x08, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x08, 0x00, 0x00, 0x64, 0x61, 0x74, 0x61, 0xa8, 0xb4, 0xff, 0x00 };
2038 static const At3plusHeaderMap at3plusHeaderMap
[] = {
2039 { 0x00C0, 0x1, 0x1724 },
2040 { 0x0180, 0x1, 0x2224 },
2041 { 0x0178, 0x1, 0x2E24 },
2043 { 0x0230, 0x1, 0x4524 },
2044 { 0x02E8, 0x1, 0x5C24 },
2045 { 0x0118, 0x1, 0x2224 },
2047 { 0x0118, 0x2, 0x2228 },
2048 { 0x0178, 0x2, 0x2E28 },
2050 { 0x0230, 0x2, 0x4528 },
2051 { 0x02E8, 0x2, 0x5C28 },
2053 { 0x03A8, 0x2, 0x7428 },
2054 { 0x0460, 0x2, 0x8B28 },
2056 { 0x05D0, 0x2, 0xB928 },
2057 { 0x0748, 0x2, 0xE828 },
2059 { 0x0800, 0x2, 0xFF28 },
2062 static bool initAT3Decoder(Atrac
*atrac
, u8
*at3Header
, u32 dataSize
= 0xffb4a8) {
2063 for (size_t i
= 0; i
< ARRAY_SIZE(at3HeaderMap
); ++i
) {
2064 if (at3HeaderMap
[i
].Matches(atrac
)) {
2065 *(u32
*)(at3Header
+ 0x04) = dataSize
+ sizeof(at3HeaderTemplate
) - 8;
2066 *(u16
*)(at3Header
+ 0x16) = atrac
->atracChannels
;
2067 *(u16
*)(at3Header
+ 0x20) = atrac
->atracBytesPerFrame
;
2068 atrac
->atracBitrate
= ( atrac
->atracBytesPerFrame
* 352800 ) / 1000;
2069 atrac
->atracBitrate
= (atrac
->atracBitrate
+ 511) >> 10;
2070 *(u32
*)(at3Header
+ 0x1c) = atrac
->atracBitrate
* 1000 / 8;
2071 at3Header
[0x29] = at3HeaderMap
[i
].headerVal1
;
2072 at3Header
[0x2c] = at3HeaderMap
[i
].headerVal2
;
2073 at3Header
[0x2e] = at3HeaderMap
[i
].headerVal2
;
2074 *(u32
*)(at3Header
+ sizeof(at3HeaderTemplate
) - 4) = dataSize
;
2081 static bool initAT3plusDecoder(Atrac
*atrac
, u8
*at3plusHeader
, u32 dataSize
= 0xffb4a8) {
2082 for (size_t i
= 0; i
< ARRAY_SIZE(at3plusHeaderMap
); ++i
) {
2083 if (at3plusHeaderMap
[i
].Matches(atrac
)) {
2084 *(u32
*)(at3plusHeader
+ 0x04) = dataSize
+ sizeof(at3plusHeaderTemplate
) - 8;
2085 *(u16
*)(at3plusHeader
+ 0x16) = atrac
->atracChannels
;
2086 *(u16
*)(at3plusHeader
+ 0x20) = atrac
->atracBytesPerFrame
;
2087 atrac
->atracBitrate
= ( atrac
->atracBytesPerFrame
* 352800 ) / 1000;
2088 atrac
->atracBitrate
= ((atrac
->atracBitrate
>> 11) + 8) & 0xFFFFFFF0;
2089 *(u32
*)(at3plusHeader
+ 0x1c) = atrac
->atracBitrate
* 1000 / 8;
2090 *(u16
*)(at3plusHeader
+ 0x3e) = at3plusHeaderMap
[i
].headerVal
;
2091 *(u32
*)(at3plusHeader
+ sizeof(at3plusHeaderTemplate
) - 4) = dataSize
;
2098 static int sceAtracLowLevelInitDecoder(int atracID
, u32 paramsAddr
) {
2099 Atrac
*atrac
= getAtrac(atracID
);
2101 ERROR_LOG(ME
, "sceAtracLowLevelInitDecoder(%i, %08x): bad atrac ID", atracID
, paramsAddr
);
2102 return ATRAC_ERROR_BAD_ATRACID
;
2105 INFO_LOG(ME
, "sceAtracLowLevelInitDecoder(%i, %08x)", atracID
, paramsAddr
);
2106 if (Memory::IsValidAddress(paramsAddr
)) {
2107 atrac
->atracChannels
= Memory::Read_U32(paramsAddr
);
2108 atrac
->atracOutputChannels
= Memory::Read_U32(paramsAddr
+ 4);
2109 atrac
->atracBufSize
= Memory::Read_U32(paramsAddr
+ 8);
2110 atrac
->atracBytesPerFrame
= atrac
->atracBufSize
;
2111 atrac
->first
.writableBytes
= atrac
->atracBytesPerFrame
;
2112 atrac
->CleanStuff();
2113 INFO_LOG(ME
, "Channels: %i outputChannels: %i bytesperFrame: %x",
2114 atrac
->atracChannels
, atrac
->atracOutputChannels
, atrac
->atracBytesPerFrame
);
2116 if (atrac
->codecType
== PSP_MODE_AT_3
) {
2117 if (atrac
->atracChannels
== 1) {
2118 WARN_LOG(ME
, "This is an atrac3 mono audio (low level)");
2120 WARN_LOG(ME
, "This is an atrac3 stereo audio (low level)");
2122 const int headersize
= sizeof(at3HeaderTemplate
);
2123 u8 at3Header
[headersize
];
2124 memcpy(at3Header
, at3HeaderTemplate
, headersize
);
2125 if (!initAT3Decoder(atrac
, at3Header
)) {
2126 ERROR_LOG_REPORT(ME
, "AT3 header map lacks entry for bpf: %i channels: %i", atrac
->atracBytesPerFrame
, atrac
->atracChannels
);
2127 // TODO: What to do, if anything?
2130 atrac
->firstSampleoffset
= headersize
;
2131 atrac
->dataOff
= headersize
;
2132 atrac
->first
.size
= headersize
;
2133 atrac
->first
.filesize
= headersize
+ atrac
->atracBytesPerFrame
;
2134 atrac
->data_buf
= new u8
[atrac
->first
.filesize
];
2135 memcpy(atrac
->data_buf
, at3Header
, headersize
);
2136 atrac
->currentSample
= 0;
2137 __AtracSetContext(atrac
);
2141 if (atrac
->codecType
== PSP_MODE_AT_3_PLUS
){
2142 if (atrac
->atracChannels
== 1) {
2143 WARN_LOG(ME
, "This is an atrac3+ mono audio (low level)");
2145 WARN_LOG(ME
, "This is an atrac3+ stereo audio (low level)");
2147 const int headersize
= sizeof(at3plusHeaderTemplate
);
2148 u8 at3plusHeader
[headersize
];
2149 memcpy(at3plusHeader
, at3plusHeaderTemplate
, headersize
);
2150 if (!initAT3plusDecoder(atrac
, at3plusHeader
)) {
2151 ERROR_LOG_REPORT(ME
, "AT3plus header map lacks entry for bpf: %i channels: %i", atrac
->atracBytesPerFrame
, atrac
->atracChannels
);
2152 // TODO: What to do, if anything?
2155 atrac
->firstSampleoffset
= headersize
;
2156 atrac
->dataOff
= headersize
;
2157 atrac
->first
.size
= headersize
;
2158 atrac
->first
.filesize
= headersize
+ atrac
->atracBytesPerFrame
;
2159 atrac
->data_buf
= new u8
[atrac
->first
.filesize
];
2160 memcpy(atrac
->data_buf
, at3plusHeader
, headersize
);
2161 atrac
->currentSample
= 0;
2162 __AtracSetContext(atrac
);
2165 #endif // USE_FFMPEG
2170 static int sceAtracLowLevelDecode(int atracID
, u32 sourceAddr
, u32 sourceBytesConsumedAddr
, u32 samplesAddr
, u32 sampleBytesAddr
) {
2171 Atrac
*atrac
= getAtrac(atracID
);
2173 ERROR_LOG(ME
, "sceAtracLowLevelDecode(%i, %08x, %08x, %08x, %08x): bad atrac ID", atracID
, sourceAddr
, sourceBytesConsumedAddr
, samplesAddr
, sampleBytesAddr
);
2174 return ATRAC_ERROR_BAD_ATRACID
;
2177 DEBUG_LOG(ME
, "UNIMPL sceAtracLowLevelDecode(%i, %08x, %08x, %08x, %08x)", atracID
, sourceAddr
, sourceBytesConsumedAddr
, samplesAddr
, sampleBytesAddr
);
2179 if (atrac
&& atrac
->pCodecCtx
&& Memory::IsValidAddress(sourceAddr
) && Memory::IsValidAddress(sourceBytesConsumedAddr
) &&
2180 Memory::IsValidAddress(samplesAddr
) && Memory::IsValidAddress(sampleBytesAddr
)) {
2181 u32 sourcebytes
= atrac
->first
.writableBytes
;
2182 if (sourcebytes
> 0) {
2183 Memory::Memcpy(atrac
->data_buf
+ atrac
->first
.size
, sourceAddr
, sourcebytes
);
2184 if (atrac
->bufferPos
>= atrac
->first
.size
) {
2185 atrac
->bufferPos
= atrac
->first
.size
;
2187 atrac
->first
.size
+= sourcebytes
;
2191 atrac
->ForceSeekToSample(atrac
->currentSample
);
2193 if (!atrac
->failedDecode
) {
2194 AtracDecodeResult res
;
2195 while (atrac
->FillPacket()) {
2196 res
= atrac
->DecodePacket();
2197 if (res
== ATDECODE_FAILED
) {
2201 if (res
== ATDECODE_GOTFRAME
) {
2203 u8
*out
= Memory::GetPointer(samplesAddr
);
2204 numSamples
= atrac
->pFrame
->nb_samples
;
2205 int avret
= swr_convert(atrac
->pSwrCtx
, &out
, numSamples
,
2206 (const u8
**)atrac
->pFrame
->extended_data
, numSamples
);
2207 u32 outBytes
= numSamples
* atrac
->atracOutputChannels
* sizeof(s16
);
2208 CBreakPoints::ExecMemCheck(samplesAddr
, true, outBytes
, currentMIPS
->pc
);
2210 ERROR_LOG(ME
, "swr_convert: Error while converting %d", avret
);
2217 atrac
->currentSample
+= numSamples
;
2218 numSamples
= (atrac
->codecType
== PSP_MODE_AT_3_PLUS
? ATRAC3PLUS_MAX_SAMPLES
: ATRAC3_MAX_SAMPLES
);
2219 Memory::Write_U32(numSamples
* sizeof(s16
) * atrac
->atracOutputChannels
, sampleBytesAddr
);
2221 if (atrac
->bufferPos
>= atrac
->first
.size
) {
2222 atrac
->first
.writableBytes
= atrac
->atracBytesPerFrame
;
2223 atrac
->first
.size
= atrac
->firstSampleoffset
;
2224 atrac
->ForceSeekToSample(0);
2227 atrac
->first
.writableBytes
= 0;
2228 Memory::Write_U32(atrac
->first
.writableBytes
, sourceBytesConsumedAddr
);
2229 return hleDelayResult(0, "low level atrac decode data", atracDecodeDelay
);
2231 #endif // USE_FFMPEG
2236 static int sceAtracSetAA3HalfwayBufferAndGetID(u32 halfBuffer
, u32 readSize
, u32 halfBufferSize
, u32 fileSize
) {
2237 if (readSize
> halfBufferSize
) {
2238 ERROR_LOG(ME
, "sceAtracSetAA3HalfwayBufferAndGetID(%08x, %08x, %08x, %08x): invalid read size", halfBuffer
, readSize
, halfBufferSize
, fileSize
);
2239 return ATRAC_ERROR_INCORRECT_READ_SIZE
;
2242 Atrac
*atrac
= new Atrac();
2243 atrac
->first
.addr
= halfBuffer
;
2244 atrac
->first
.size
= halfBufferSize
;
2245 atrac
->first
.filesize
= fileSize
;
2246 int ret
= atrac
->AnalyzeAA3();
2248 ERROR_LOG(ME
, "sceAtracSetAA3HalfwayBufferAndGetID(%08x, %08x, %08x, %08x): bad data", halfBuffer
, readSize
, halfBufferSize
, fileSize
);
2252 int atracID
= createAtrac(atrac
);
2254 ERROR_LOG(ME
, "sceAtracSetAA3HalfwayBufferAndGetID(%08x, %08x, %08x, %08x): no free ID", halfBuffer
, readSize
, halfBufferSize
, fileSize
);
2258 ERROR_LOG(ME
, "UNIMPL %d=sceAtracSetAA3HalfwayBufferAndGetID(%08x, %08x, %08x)", atracID
, halfBuffer
, readSize
, halfBufferSize
);
2259 return _AtracSetData(atracID
, halfBuffer
, halfBufferSize
, true);
2262 const HLEFunction sceAtrac3plus
[] = {
2263 {0X7DB31251, &WrapU_IU
<sceAtracAddStreamData
>, "sceAtracAddStreamData", 'x', "ix" },
2264 {0X6A8C3CD5, &WrapU_IUUUU
<sceAtracDecodeData
>, "sceAtracDecodeData", 'x', "ixxxx"},
2265 {0XD5C28CC0, &WrapU_V
<sceAtracEndEntry
>, "sceAtracEndEntry", 'x', "" },
2266 {0X780F88D1, &WrapU_I
<sceAtracGetAtracID
>, "sceAtracGetAtracID", 'x', "i" },
2267 {0XCA3CA3D2, &WrapU_IIU
<sceAtracGetBufferInfoForResetting
>, "sceAtracGetBufferInfoForReseting", 'x', "iix" },
2268 {0XA554A158, &WrapU_IU
<sceAtracGetBitrate
>, "sceAtracGetBitrate", 'x', "ix" },
2269 {0X31668BAA, &WrapU_IU
<sceAtracGetChannel
>, "sceAtracGetChannel", 'x', "ix" },
2270 {0XFAA4F89B, &WrapU_IUU
<sceAtracGetLoopStatus
>, "sceAtracGetLoopStatus", 'x', "ixx" },
2271 {0XE88F759B, &WrapU_IU
<sceAtracGetInternalErrorInfo
>, "sceAtracGetInternalErrorInfo", 'x', "ix" },
2272 {0XD6A5F2F7, &WrapU_IU
<sceAtracGetMaxSample
>, "sceAtracGetMaxSample", 'x', "ix" },
2273 {0XE23E3A35, &WrapU_IU
<sceAtracGetNextDecodePosition
>, "sceAtracGetNextDecodePosition", 'x', "ix" },
2274 {0X36FAABFB, &WrapU_IU
<sceAtracGetNextSample
>, "sceAtracGetNextSample", 'x', "ix" },
2275 {0X9AE849A7, &WrapU_IU
<sceAtracGetRemainFrame
>, "sceAtracGetRemainFrame", 'x', "ix" },
2276 {0X83E85EA0, &WrapU_IUU
<sceAtracGetSecondBufferInfo
>, "sceAtracGetSecondBufferInfo", 'x', "ixx" },
2277 {0XA2BBA8BE, &WrapU_IUUU
<sceAtracGetSoundSample
>, "sceAtracGetSoundSample", 'x', "ixxx" },
2278 {0X5D268707, &WrapU_IUUU
<sceAtracGetStreamDataInfo
>, "sceAtracGetStreamDataInfo", 'x', "ixxx" },
2279 {0X61EB33F5, &WrapU_I
<sceAtracReleaseAtracID
>, "sceAtracReleaseAtracID", 'x', "i" },
2280 {0X644E5607, &WrapU_IIII
<sceAtracResetPlayPosition
>, "sceAtracResetPlayPosition", 'x', "iiii" },
2281 {0X3F6E26B5, &WrapU_IUUU
<sceAtracSetHalfwayBuffer
>, "sceAtracSetHalfwayBuffer", 'x', "ixxx" },
2282 {0X83BF7AFD, &WrapU_IUU
<sceAtracSetSecondBuffer
>, "sceAtracSetSecondBuffer", 'x', "ixx" },
2283 {0X0E2A73AB, &WrapU_IUU
<sceAtracSetData
>, "sceAtracSetData", 'x', "ixx" },
2284 {0X7A20E7AF, &WrapI_UI
<sceAtracSetDataAndGetID
>, "sceAtracSetDataAndGetID", 'i', "xi" },
2285 {0XD1F59FDB, &WrapU_V
<sceAtracStartEntry
>, "sceAtracStartEntry", 'x', "" },
2286 {0X868120B5, &WrapU_II
<sceAtracSetLoopNum
>, "sceAtracSetLoopNum", 'x', "ii" },
2287 {0X132F1ECA, &WrapI_II
<sceAtracReinit
>, "sceAtracReinit", 'i', "ii" },
2288 {0XECA32A99, &WrapI_I
<sceAtracIsSecondBufferNeeded
>, "sceAtracIsSecondBufferNeeded", 'i', "i" },
2289 {0X0FAE370E, &WrapI_UUU
<sceAtracSetHalfwayBufferAndGetID
>, "sceAtracSetHalfwayBufferAndGetID", 'i', "xxx" },
2290 {0X2DD3E298, &WrapU_IIU
<sceAtracGetBufferInfoForResetting
>, "sceAtracGetBufferInfoForResetting", 'x', "iix" },
2291 {0X5CF9D852, &WrapI_IUUU
<sceAtracSetMOutHalfwayBuffer
>, "sceAtracSetMOutHalfwayBuffer", 'i', "ixxx" },
2292 {0XF6837A1A, &WrapU_IUU
<sceAtracSetMOutData
>, "sceAtracSetMOutData", 'x', "ixx" },
2293 {0X472E3825, &WrapI_UU
<sceAtracSetMOutDataAndGetID
>, "sceAtracSetMOutDataAndGetID", 'i', "xx" },
2294 {0X9CD7DE03, &WrapI_UUU
<sceAtracSetMOutHalfwayBufferAndGetID
>, "sceAtracSetMOutHalfwayBufferAndGetID", 'i', "xxx" },
2295 {0XB3B5D042, &WrapI_IU
<sceAtracGetOutputChannel
>, "sceAtracGetOutputChannel", 'i', "ix" },
2296 {0X5622B7C1, &WrapI_UUUU
<sceAtracSetAA3DataAndGetID
>, "sceAtracSetAA3DataAndGetID", 'i', "xxxx" },
2297 {0X5DD66588, &WrapI_UUUU
<sceAtracSetAA3HalfwayBufferAndGetID
>, "sceAtracSetAA3HalfwayBufferAndGetID", 'i', "xxxx" },
2298 {0X231FC6B7, &WrapI_I
<_sceAtracGetContextAddress
>, "_sceAtracGetContextAddress", 'i', "i" },
2299 {0X1575D64B, &WrapI_IU
<sceAtracLowLevelInitDecoder
>, "sceAtracLowLevelInitDecoder", 'i', "ix" },
2300 {0X0C116E1B, &WrapI_IUUUU
<sceAtracLowLevelDecode
>, "sceAtracLowLevelDecode", 'i', "ixxxx"},
2303 void Register_sceAtrac3plus() {
2305 RegisterModule("sceATRAC3plus_Library", ARRAY_SIZE(sceAtrac3plus
), sceAtrac3plus
);
2306 RegisterModule("sceAtrac3plus", ARRAY_SIZE(sceAtrac3plus
), sceAtrac3plus
);