@@ -175,26 +175,37 @@ Atrac2::Atrac2(u32 contextAddr, int codecType) {
175175 info.state = ATRAC_STATUS_NO_DATA;
176176 info.curBuffer = 0 ;
177177
178- sasReadOffset_ = 0 ;
179- sasBasePtr_ = 0 ;
178+ sas_.streamOffset = 0 ;
179+ sas_.bufPtr [0 ] = 0 ;
180+ sas_.bufPtr [1 ] = 0 ;
180181 } else {
181182 // We're loading state, we'll restore the context in DoState.
182183 }
183184}
184185
185186void Atrac2::DoState (PointerWrap &p) {
186- auto s = p.Section (" Atrac2" , 1 , 2 );
187+ auto s = p.Section (" Atrac2" , 1 , 3 );
187188 if (!s)
188189 return ;
189190
190191 Do (p, outputChannels_);
191192 // The only thing we need to save now is the outputChannels_ and the context pointer. And technically, not even that since
192193 // it can be computed. Still, for future proofing, let's save it.
193194 Do (p, context_);
195+
194196 // Actually, now we also need to save sas state. I guess this could also be saved on the Sas side, but this is easier.
195197 if (s >= 2 ) {
196- Do (p, sasReadOffset_);
197- Do (p, sasBasePtr_);
198+ Do (p, sas_.streamOffset );
199+ Do (p, sas_.bufPtr [0 ]);
200+ }
201+ // Added support for streaming sas audio, need some more context state.
202+ if (s >= 3 ) {
203+ Do (p, sas_.bufPtr [1 ]);
204+ Do (p, sas_.bufSize [0 ]);
205+ Do (p, sas_.bufSize [1 ]);
206+ Do (p, sas_.isStreaming );
207+ Do (p, sas_.curBuffer );
208+ Do (p, sas_.fileOffset );
198209 }
199210
200211 const SceAtracIdInfo &info = context_->info ;
@@ -497,20 +508,6 @@ int Atrac2::AddStreamData(u32 bytesToAdd) {
497508 return 0 ;
498509}
499510
500- u32 Atrac2::AddStreamDataSas (u32 bufPtr, u32 bytesToAdd) {
501- SceAtracIdInfo &info = context_->info ;
502- // Internal API, seems like a combination of GetStreamDataInfo and AddStreamData, for use when
503- // an Atrac context is bound to an sceSas channel.
504- // Sol Trigger is the only game I know that uses this.
505- _dbg_assert_ (false );
506-
507- u8 *dest = Memory::GetPointerWrite (sasBasePtr_ + sasReadOffset_);
508- memcpy (dest, Memory::GetPointer (bufPtr), bytesToAdd);
509- info.buffer += bytesToAdd;
510- info.streamDataByte += bytesToAdd;
511- return 0 ;
512- }
513-
514511static int ComputeLoopedStreamWritableBytes (const SceAtracIdInfo &info, const int loopStartFileOffset, const u32 loopEndFileOffset) {
515512 const u32 writeOffset = info.curFileOff + info.streamDataByte ;
516513 if (writeOffset >= loopEndFileOffset) {
@@ -681,6 +678,10 @@ u32 Atrac2::DecodeInternal(u32 outbufAddr, int *SamplesNum, int *finish) {
681678 return SCE_ERROR_ATRAC_BUFFER_IS_EMPTY;
682679 }
683680
681+ if (info.state == ATRAC_STATUS_FOR_SCESAS) {
682+ _dbg_assert_ (false );
683+ }
684+
684685 u32 streamOff;
685686 u32 bufferPtr;
686687 if (!AtracStatusIsStreaming (info.state )) {
@@ -1039,27 +1040,132 @@ int Atrac2::DecodeLowLevel(const u8 *srcData, int *bytesConsumed, s16 *dstData,
10391040 return 0 ;
10401041}
10411042
1043+ void Atrac2::CheckForSas () {
1044+ SceAtracIdInfo &info = context_->info ;
1045+ if (info.numChan != 1 ) {
1046+ WARN_LOG (Log::ME, " Caller forgot to set channels to 1" );
1047+ }
1048+ if (info.state != 0x10 ) {
1049+ WARN_LOG (Log::ME, " Caller forgot to set state to 0x10" );
1050+ }
1051+ sas_.isStreaming = info.fileDataEnd > info.bufferByte ;
1052+ if (sas_.isStreaming ) {
1053+ INFO_LOG (Log::ME, " SasAtrac stream mode" );
1054+ } else {
1055+ INFO_LOG (Log::ME, " SasAtrac non-streaming mode" );
1056+ }
1057+ }
1058+
1059+ int Atrac2::EnqueueForSas (u32 address, u32 ptr) {
1060+ SceAtracIdInfo &info = context_->info ;
1061+ // Set the new buffer up to be adopted by the next call to Decode that needs more data.
1062+ // Note: Can't call this if the decoder isn't asking for another buffer to be queued.
1063+ if (info.secondBuffer != 0xFFFFFFFF ) {
1064+ return SCE_SAS_ERROR_ATRAC3_ALREADY_QUEUED;
1065+ }
1066+
1067+ if (address == 0 && ptr == 0 ) {
1068+ WARN_LOG (Log::ME, " Caller tries to send us a zero buffer. Something went wrong." );
1069+ }
1070+
1071+ DEBUG_LOG (Log::ME, " EnqueueForSas: Second buffer updated to %08x, sz: %08x" , address, ptr);
1072+ info.secondBuffer = address;
1073+ info.secondBufferByte = ptr;
1074+ return 0 ;
1075+ }
1076+
1077+ // Completely different streaming setup!
10421078void Atrac2::DecodeForSas (s16 *dstData, int *bytesWritten, int *finish) {
10431079 SceAtracIdInfo &info = context_->info ;
1080+ *bytesWritten = 0 ;
10441081
1082+ // First frame handling. Not sure if accurate. Set up the initial buffer as the current streaming buffer.
1083+ // Also works for the non-streaming case.
10451084 if (info.buffer ) {
1046- // Adopt it then zero it.
1047- sasBasePtr_ = info.buffer ;
1048- sasReadOffset_ = 0 ;
1049- info.buffer = 0 ;
1050- }
1085+ sas_.curBuffer = 0 ;
1086+ sas_.bufPtr [0 ] = info.buffer ;
1087+ sas_.bufSize [0 ] = info.bufferByte - info.streamOff ; // also equals info.streamDataByte
1088+ sas_.streamOffset = 0 ;
1089+ sas_.fileOffset = info.bufferByte ; // Possibly should just set it to info.curFileOff
1090+ info.buffer = 0 ; // yes, this happens.
1091+ }
1092+
1093+ u8 assembly[1000 ];
1094+ // Keep decoding from the current buffer until it runs out.
1095+ if (sas_.streamOffset + info.sampleSize <= sas_.bufSize [sas_.curBuffer ]) {
1096+ // Just decode.
1097+ const u8 *srcData = Memory::GetPointer (sas_.bufPtr [sas_.curBuffer ] + sas_.streamOffset );
1098+ int bytesConsumed = 0 ;
1099+ bool decodeResult = decoder_->Decode (srcData, info.sampleSize , &bytesConsumed, 1 , dstData, bytesWritten);
1100+ if (!decodeResult) {
1101+ ERROR_LOG (Log::ME, " SAS failed to decode regular packet" );
1102+ }
1103+ sas_.streamOffset += bytesConsumed;
1104+ } else if (sas_.isStreaming ) {
1105+ // TODO: Do we need special handling for the first buffer, since SetData will wrap around that packet? I think yes!
1106+ DEBUG_LOG (Log::ME, " Streaming atrac through sas, and hit the end of buffer %d" , sas_.curBuffer );
1107+
1108+ // Compute the part sizes using the current size.
1109+ int part1Size = sas_.bufSize [sas_.curBuffer ] - sas_.streamOffset ;
1110+ int part2Size = info.sampleSize - part1Size;
1111+ _dbg_assert_ (part1Size >= 0 );
1112+ if (part1Size >= 0 ) {
1113+ // Grab the partial packet, before we switch over to the other buffer.
1114+ Memory::Memcpy (assembly, sas_.bufPtr [sas_.curBuffer ] + sas_.streamOffset , part1Size);
1115+ }
10511116
1052- const u8 *srcData = Memory::GetPointer (sasBasePtr_ + sasReadOffset_);
1117+ // Check if we hit the end.
1118+ if (sas_.fileOffset >= info.fileDataEnd ) {
1119+ DEBUG_LOG (Log::ME, " Streaming and hit the file end." );
1120+ *bytesWritten = 0 ;
1121+ *finish = 1 ;
1122+ return ;
1123+ }
10531124
1054- int outSamples = 0 ;
1055- int bytesConsumed = 0 ;
1056- decoder_->Decode (srcData, info.sampleSize , &bytesConsumed, 1 , dstData, bytesWritten);
1125+ // Check that a new buffer actually exists
1126+ if (info.secondBuffer == sas_.bufPtr [sas_.curBuffer ]) {
1127+ ERROR_LOG (Log::ME, " Can't enqueue the same buffer twice in a row!" );
1128+ *bytesWritten = 0 ;
1129+ *finish = 1 ;
1130+ return ;
1131+ }
10571132
1058- sasReadOffset_ += bytesConsumed;
1133+ if ((int )info.secondBuffer < 0 ) {
1134+ ERROR_LOG (Log::ME, " AtracSas streaming ran out of data, no secondbuffer pending" );
1135+ *bytesWritten = 0 ;
1136+ *finish = 1 ;
1137+ return ;
1138+ }
10591139
1060- if (sasReadOffset_ + info.dataOff >= info.fileDataEnd ) {
1061- *finish = 1 ;
1062- } else {
1063- *finish = 0 ;
1140+ // Switch to the other buffer.
1141+ sas_.curBuffer ^= 1 ;
1142+
1143+ sas_.bufPtr [sas_.curBuffer ] = info.secondBuffer ;
1144+ sas_.bufSize [sas_.curBuffer ] = info.secondBufferByte ;
1145+ sas_.fileOffset += info.secondBufferByte ;
1146+
1147+ sas_.streamOffset = part2Size;
1148+
1149+ // If we'll reach the end during this buffer, set second buffer to 0, signaling that we don't need more data.
1150+ if (sas_.fileOffset >= info.fileDataEnd ) {
1151+ // We've reached the end.
1152+ info.secondBuffer = 0 ;
1153+ DEBUG_LOG (Log::ME, " %08x >= %08x: Reached the end." , sas_.fileOffset , info.fileDataEnd );
1154+ } else {
1155+ // Signal to the caller that we accept a new next buffer.
1156+ info.secondBuffer = 0xFFFFFFFF ;
1157+ }
1158+
1159+ DEBUG_LOG (Log::ME, " Switching over to buffer %d, updating buffer to %08x, sz: %08x. %s" , sas_.curBuffer , info.secondBuffer , info.secondBufferByte , info.secondBuffer == 0xFFFFFFFF ? " Signalling for more data." : " " );
1160+
1161+ // Copy the second half (or if part1Size == 0, the whole packet) to the assembly buffer.
1162+ Memory::Memcpy (assembly + part1Size, sas_.bufPtr [sas_.curBuffer ], part2Size);
1163+ // Decode the packet from the assembly, whether it's was assembled from two or one.
1164+ const u8 *srcData = assembly;
1165+ int bytesConsumed = 0 ;
1166+ bool decodeResult = decoder_->Decode (srcData, info.sampleSize , &bytesConsumed, 1 , dstData, bytesWritten);
1167+ if (!decodeResult) {
1168+ ERROR_LOG (Log::ME, " SAS failed to decode assembled packet" );
1169+ }
10641170 }
10651171}
0 commit comments