diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index f4fb5a1125..7f0ec47269 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -23,13 +23,14 @@ void Compatibility::Load(const std::string &gameID) { IniFile compat; Clear(); - std::string path = GetSysDirectory(DIRECTORY_SYSTEM) + "compat.ini"; - if (compat.Load(path)) { + // This loads from assets. + if (compat.LoadFromVFS("compat.ini")) { LoadIniSection(compat, gameID); } - // This loads from assets. - if (compat.LoadFromVFS("compat.ini")) { + // This one is user-editable. Need to load it after the system one. + std::string path = GetSysDirectory(DIRECTORY_SYSTEM) + "compat.ini"; + if (compat.Load(path)) { LoadIniSection(compat, gameID); } } @@ -40,4 +41,5 @@ void Compatibility::Clear() { void Compatibility::LoadIniSection(IniFile &iniFile, std::string section) { iniFile.Get(section.c_str(), "NoDepthRounding", &flags_.NoDepthRounding, flags_.NoDepthRounding); + iniFile.Get(section.c_str(), "GTAMusicFix", &flags_.GTAMusicFix, flags_.GTAMusicFix); } diff --git a/Core/Compatibility.h b/Core/Compatibility.h index dc22ee0cf2..5f03cd4bed 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -46,7 +46,7 @@ struct CompatFlags { bool NoDepthRounding; - // GTAMusicFix, ... + bool GTAMusicFix; }; class IniFile; diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index e36827f3c4..3f47ba1010 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -17,13 +17,16 @@ #include +#include "Core/CoreParameter.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/MIPS/MIPS.h" #include "Core/CoreTiming.h" +#include "Core/Compatibility.h" #include "Core/MemMapHelpers.h" #include "Core/Reporting.h" #include "Core/Config.h" +#include "Core/System.h" #include "Core/Debugger/Breakpoints.h" #include "Core/HW/MediaEngine.h" #include "Core/HW/BufferQueue.h" @@ -332,6 +335,12 @@ struct Atrac { } void SeekToSample(int sample) { + if (PSP_CoreParameter().compat.flags().GTAMusicFix) { + s64 seek_pos = (s64)sample; + av_seek_frame(pFormatCtx, audio_stream_index, seek_pos, 0); + return; + } + const u32 atracSamplesPerFrame = (codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); // Discard any pending packet data. @@ -394,11 +403,19 @@ struct Atrac { packet->size = 0; if (FillPacket()) { - int to_copy = packet->size >= needed ? needed : packet->size; - memcpy(tempPacket.data + initialSize, packet->data, to_copy); - packet->size -= to_copy; - packet->data += to_copy; - tempPacket.size = initialSize + to_copy; + if (PSP_CoreParameter().compat.flags().GTAMusicFix) { + if (packet->size >= needed) { + memcpy(tempPacket.data + initialSize, packet->data, needed); + packet->size -= needed; + packet->data += needed; + } + } else { + int to_copy = packet->size >= needed ? needed : packet->size; + memcpy(tempPacket.data + initialSize, packet->data, to_copy); + packet->size -= to_copy; + packet->data += to_copy; + tempPacket.size = initialSize + to_copy; + } } else { tempPacket.size = initialSize; } @@ -876,17 +893,28 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 // It seems like the PSP aligns the sample position to 0x800...? int offsetSamples = atrac->firstSampleoffset + firstOffsetExtra; int skipSamples = 0; + if (PSP_CoreParameter().compat.flags().GTAMusicFix) { + skipSamples = atrac->currentSample == 0 ? offsetSamples : 0; + } u32 maxSamples = atrac->endSample - atrac->currentSample; u32 unalignedSamples = (offsetSamples + atrac->currentSample) % atracSamplesPerFrame; if (unalignedSamples != 0) { // We're off alignment, possibly due to a loop. Force it back on. maxSamples = atracSamplesPerFrame - unalignedSamples; - skipSamples = unalignedSamples; + if (!PSP_CoreParameter().compat.flags().GTAMusicFix) { + skipSamples = unalignedSamples; + } } #ifdef USE_FFMPEG if (!atrac->failedDecode && (atrac->codecType == PSP_MODE_AT_3 || atrac->codecType == PSP_MODE_AT_3_PLUS) && atrac->pCodecCtx) { - atrac->SeekToSample(atrac->currentSample); + if (PSP_CoreParameter().compat.flags().GTAMusicFix) { + int forceseekSample = atrac->currentSample * 2 > atrac->endSample ? 0 : atrac->endSample; + atrac->SeekToSample(forceseekSample); + atrac->SeekToSample(atrac->currentSample == 0 ? 0 : atrac->currentSample + offsetSamples); + } else { + atrac->SeekToSample(atrac->currentSample); + } AtracDecodeResult res = ATDECODE_FEEDME; while (atrac->FillPacket()) { @@ -962,7 +990,11 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 int finishFlag = 0; if (atrac->loopNum != 0 && (atrac->currentSample > atrac->loopEndSample || (numSamples == 0 && atrac->first.size >= atrac->first.filesize))) { - atrac->SeekToSample(atrac->loopStartSample); + if (PSP_CoreParameter().compat.flags().GTAMusicFix) { + atrac->currentSample = 0; + } else { + atrac->SeekToSample(atrac->loopStartSample); + } if (atrac->loopNum > 0) atrac->loopNum --; } else if (atrac->currentSample >= atrac->endSample || @@ -1312,7 +1344,9 @@ static u32 sceAtracGetStreamDataInfo(int atracID, u32 writeAddr, u32 writableByt // Reset temp buf for adding more stream data and set full filled buffer. atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->atracBufSize); } else { - atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->first.writableBytes); + if (!PSP_CoreParameter().compat.flags().GTAMusicFix) { + atrac->first.writableBytes = std::min(atrac->first.filesize - atrac->first.size, atrac->first.writableBytes); + } } atrac->first.offset = 0; @@ -1354,13 +1388,18 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi INFO_LOG(ME, "sceAtracResetPlayPosition(%i, %i, %i, %i)", atracID, sample, bytesWrittenFirstBuf, bytesWrittenSecondBuf); if (bytesWrittenFirstBuf > 0) sceAtracAddStreamData(atracID, bytesWrittenFirstBuf); + if (PSP_CoreParameter().compat.flags().GTAMusicFix) { + atrac->currentSample = sample; + } #ifdef USE_FFMPEG if ((atrac->codecType == PSP_MODE_AT_3 || atrac->codecType == PSP_MODE_AT_3_PLUS) && atrac->pCodecCtx) { atrac->SeekToSample(sample); } else #endif // USE_FFMPEG { - atrac->currentSample = sample; + if (!PSP_CoreParameter().compat.flags().GTAMusicFix) { + atrac->currentSample = sample; + } atrac->decodePos = atrac->getDecodePosBySample(sample); } } @@ -2188,7 +2227,13 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo } int numSamples = 0; - atrac->ForceSeekToSample(atrac->currentSample); + if (PSP_CoreParameter().compat.flags().GTAMusicFix) { + int forceseekSample = 0x200000; + atrac->SeekToSample(forceseekSample); + atrac->SeekToSample(atrac->currentSample); + } else { + atrac->ForceSeekToSample(atrac->currentSample); + } if (!atrac->failedDecode) { AtracDecodeResult res; @@ -2217,11 +2262,18 @@ static int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesCo atrac->currentSample += numSamples; numSamples = (atrac->codecType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); Memory::Write_U32(numSamples * sizeof(s16) * atrac->atracOutputChannels, sampleBytesAddr); + if (PSP_CoreParameter().compat.flags().GTAMusicFix) { + atrac->SeekToSample(atrac->currentSample); + } if (atrac->bufferPos >= atrac->first.size) { atrac->first.writableBytes = atrac->atracBytesPerFrame; atrac->first.size = atrac->firstSampleoffset; - atrac->ForceSeekToSample(0); + if (PSP_CoreParameter().compat.flags().GTAMusicFix) { + atrac->currentSample = 0; + } else { + atrac->ForceSeekToSample(0); + } } else atrac->first.writableBytes = 0; diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index 685bdd09ee..9fb8a6964c 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -393,6 +393,7 @@ + diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index 18972bc407..560e50ad6e 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -329,6 +329,7 @@ Resource Files + diff --git a/assets/compat.ini b/assets/compat.ini index 14e35440ed..a36d4d11f0 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -20,6 +20,10 @@ # * Fun hacks, like enlarged heads or whatever # * Fixing general compatibility issues. First try to find a general solution. Try hard. # +# Game IDs can be looked up at GameFAQs, for example: +# http://www.gamefaqs.com/psp/925776-grand-theft-auto-liberty-city-stories/data +# Sometimes the information may be incomplete though. +# # ======================================================================================== # Issue numbers refer to issues on https://github.com/hrydgard/ppsspp/issues # ======================================================================================== @@ -33,3 +37,42 @@ NoDepthRounding = true [ULUS10066] NoDepthRounding = true + +# GTA audio issues +# These games stream their radio stations from disc as giant audio files. They seek into +# the correct position. Our ATRAC3 module (sceAtrac) implementation is still not very accurate +# and needs some special handling for this to work correctly, for unknown reasons. + +# GTAMusicFix removes the effect of pull #6976, which fixed many games but broke GTA. +# Issue #7863 has some more information. + +# GTA Liberty City Stories +[ULUS10041] +GTAMusicFix = true +[ULES00151] +GTAMusicFix = true +[ULUS10041] +GTAMusicFix = true +[ULJM05255] +GTAMusicFix = true +[ULJM05359] +GTAMusicFix = true +[ULJM05885] +GTAMusicFix = true +[NPJH50825] +GTAMusicFix = true + + +# GTA Vice City Stories +[ULES00502] +GTAMusicFix = true +[ULUS10160] +GTAMusicFix = true +[ULJM05297] +GTAMusicFix = true +[ULJM05395] +GTAMusicFix = true +[ULJM05884] +GTAMusicFix = true +[NPJH50827] +GTAMusicFix = true