mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-20 17:59:08 +02:00
Implement save state support, with backwards compatibility.
This commit is contained in:
1 parent
89a73be155
commit
6d7625ea6b
5 files changed
+68
-23
No files matched your search
+3
-1
@@ -229,7 +229,7 @@ public:
|
||||
|
||||
virtual int GetSoundSample(int *endSample, int *loopStartSample, int *loopEndSample) const = 0;
|
||||
|
||||
virtual bool IsNewAtracImpl() const { return false; }
|
||||
virtual int GetContextVersion() const = 0;
|
||||
|
||||
protected:
|
||||
u16 outputChannels_ = 2;
|
||||
@@ -325,6 +325,8 @@ public:
|
||||
void UpdateContextFromPSPMem() override;
|
||||
void WriteContextToPSPMem();
|
||||
|
||||
int GetContextVersion() const override { return 1; }
|
||||
|
||||
private:
|
||||
void UpdateBufferState();
|
||||
void ResetData();
|
||||
|
||||
+28
-8
@@ -1,4 +1,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "Common/Serialize/Serializer.h"
|
||||
#include "Common/Serialize/SerializeFuncs.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Core/MemMapHelpers.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
@@ -162,15 +165,32 @@ int Atrac2::RemainingFrames() const {
|
||||
}
|
||||
|
||||
Atrac2::Atrac2(u32 contextAddr, int codecType) {
|
||||
context_ = PSPPointer<SceAtracContext>::Create(contextAddr);
|
||||
SceAtracIdInfo &info = context_->info;
|
||||
info.codec = codecType;
|
||||
info.state = ATRAC_STATUS_NO_DATA;
|
||||
info.curBuffer = 0;
|
||||
if (contextAddr) {
|
||||
context_ = PSPPointer<SceAtracContext>::Create(contextAddr);
|
||||
// First-time initialization.
|
||||
SceAtracIdInfo &info = context_->info;
|
||||
info.codec = codecType;
|
||||
info.state = ATRAC_STATUS_NO_DATA;
|
||||
info.curBuffer = 0;
|
||||
} else {
|
||||
// We're loading state, we'll restore the context in DoState.
|
||||
}
|
||||
}
|
||||
|
||||
void Atrac2::DoState(PointerWrap &p) {
|
||||
_assert_msg_(false, "Savestates not yet support with new Atrac implementation.\n\nTurn it off in Developer settings.\n\n");
|
||||
auto s = p.Section("Atrac2", 1, 1);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
Do(p, outputChannels_);
|
||||
// The only thing we need to save now is the outputChannels_ and the context pointer. And technically, not even that since
|
||||
// it can be computed. Still, for future proofing, let's save it.
|
||||
Do(p, context_);
|
||||
|
||||
const SceAtracIdInfo &info = context_->info;
|
||||
if (p.mode == p.MODE_READ && info.state != ATRAC_STATUS_NO_DATA) {
|
||||
CreateDecoder(info.codec, info.sampleSize, info.numChan);
|
||||
}
|
||||
}
|
||||
|
||||
bool Atrac2::HasSecondBuffer() const {
|
||||
@@ -299,7 +319,7 @@ int Atrac2::GetResetBufferInfo(AtracResetBufferInfo *bufferInfo, int seekPos, bo
|
||||
|
||||
seekPos += info.firstValidSample;
|
||||
|
||||
if ((u32)seekPos > info.endSample) {
|
||||
if ((u32)seekPos > (u32)info.endSample) {
|
||||
return SCE_ERROR_ATRAC_BAD_SAMPLE;
|
||||
}
|
||||
|
||||
@@ -935,7 +955,7 @@ int Atrac2::SetSecondBuffer(u32 secondBuffer, u32 secondBufferSize) {
|
||||
u32 loopEndFileOffset = ComputeLoopEndFileOffset(info, info.loopEnd);
|
||||
if ((info.sampleSize * 3 <= (int)secondBufferSize ||
|
||||
(info.fileDataEnd - loopEndFileOffset) <= (int)secondBufferSize)) {
|
||||
if (info.state == 6) {
|
||||
if (info.state == ATRAC_STATUS_STREAMED_LOOP_WITH_TRAILER) {
|
||||
info.secondBuffer = secondBuffer;
|
||||
info.secondBufferByte = secondBufferSize;
|
||||
info.secondStreamOff = 0;
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
|
||||
class Atrac2 : public AtracBase {
|
||||
public:
|
||||
Atrac2(u32 contextAddr, int codecType);
|
||||
// The default values are only used during save state load, in which case they get restored by DoState.
|
||||
Atrac2(u32 contextAddr = 0, int codecType = 0);
|
||||
~Atrac2() {
|
||||
delete[] decodeTemp_;
|
||||
}
|
||||
@@ -51,7 +52,7 @@ public:
|
||||
void UpdateContextFromPSPMem() override {}
|
||||
void NotifyGetContextAddress() override {}
|
||||
|
||||
bool IsNewAtracImpl() const override { return true; }
|
||||
int GetContextVersion() const override { return 2; }
|
||||
|
||||
u32 GetInternalCodecError() const override;
|
||||
|
||||
|
||||
+32
-10
@@ -152,30 +152,54 @@ static u32 GetAtracContextAddress(int atracID) {
|
||||
}
|
||||
|
||||
void __AtracDoState(PointerWrap &p) {
|
||||
auto s = p.Section("sceAtrac", 1, 2);
|
||||
auto s = p.Section("sceAtrac", 1, 4);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
Do(p, atracInited);
|
||||
if (s >= 4) {
|
||||
Do(p, g_atracBSS);
|
||||
Do(p, g_atracMaxContexts);
|
||||
if (g_atracMaxContexts > PSP_MAX_ATRAC_IDS) // paranoia
|
||||
g_atracMaxContexts = PSP_MAX_ATRAC_IDS;
|
||||
} else {
|
||||
g_atracBSS = 0;
|
||||
g_atracMaxContexts = 6;
|
||||
}
|
||||
for (int i = 0; i < PSP_MAX_ATRAC_IDS; ++i) {
|
||||
bool valid = atracContexts[i] != nullptr;
|
||||
Do(p, valid);
|
||||
if (valid) {
|
||||
DoSubClass<AtracBase, Atrac>(p, atracContexts[i], i);
|
||||
int version = atracContexts[i] ? atracContexts[i]->GetContextVersion() : 0;
|
||||
if (s >= 4) {
|
||||
Do(p, version);
|
||||
_dbg_assert_(version != 0);
|
||||
} else {
|
||||
// Old versions only support old contexts.
|
||||
version = 1;
|
||||
}
|
||||
switch (version) {
|
||||
case 1:
|
||||
DoSubClass<AtracBase, Atrac>(p, atracContexts[i], i);
|
||||
break;
|
||||
case 2:
|
||||
DoSubClass<AtracBase, Atrac2>(p, atracContexts[i]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
delete atracContexts[i];
|
||||
atracContexts[i] = nullptr;
|
||||
}
|
||||
}
|
||||
DoArray(p, atracContextTypes, PSP_MAX_ATRAC_IDS);
|
||||
if (s < 2) {
|
||||
atracLibVersion = 0;
|
||||
atracLibCrc = 0;
|
||||
}
|
||||
else {
|
||||
if (s >= 2) {
|
||||
Do(p, atracLibVersion);
|
||||
Do(p, atracLibCrc);
|
||||
}
|
||||
else {
|
||||
atracLibVersion = 0;
|
||||
atracLibCrc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static AtracBase *getAtrac(int atracID) {
|
||||
@@ -192,9 +216,7 @@ static AtracBase *getAtrac(int atracID) {
|
||||
static int AllocAndRegisterAtrac(int codecType) {
|
||||
for (int i = 0; i < g_atracMaxContexts; ++i) {
|
||||
if (atracContextTypes[i] == codecType && atracContexts[i] == 0) {
|
||||
if (g_Config.bUseExperimentalAtrac) {
|
||||
// Note: This assert isn't really valid until we savestate the new contexts.
|
||||
_dbg_assert_(g_atracBSS != 0);
|
||||
if (g_Config.bUseExperimentalAtrac && g_atracBSS != 0) {
|
||||
atracContexts[i] = new Atrac2(GetAtracContextAddress(i), codecType);
|
||||
} else {
|
||||
atracContexts[i] = new Atrac(i, codecType);
|
||||
|
||||
@@ -1006,7 +1006,7 @@ void DrawAudioDecodersView(ImConfig &cfg, ImControl &control) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", ctx->RemainingFrames());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(ctx->IsNewAtracImpl() ? "NewImpl" : "Legacy");
|
||||
ImGui::TextUnformatted(ctx->GetContextVersion() >= 2 ? "NewImpl" : "Legacy");
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
@@ -1031,7 +1031,7 @@ void DrawAudioDecodersView(ImConfig &cfg, ImControl &control) {
|
||||
ImGui::SameLine();
|
||||
ImClickableValue("ctx", ctx->context_.ptr, control, ImCmd::SHOW_IN_MEMORY_VIEWER);
|
||||
}
|
||||
if (ctx->context_.IsValid() && ctx->IsNewAtracImpl()) {
|
||||
if (ctx->context_.IsValid() && ctx->GetContextVersion() >= 2) {
|
||||
const auto &info = ctx->context_->info;
|
||||
ImGui::Text("Buffer: (size: %d / %08x) Frame: %d", info.bufferByte, info.bufferByte, info.sampleSize);
|
||||
ImGui::SameLine();
|
||||
|
||||
Reference in new issue
Block a user