diff --git a/config/SZBE69_B8/objects.json b/config/SZBE69_B8/objects.json index aa2351368..71b5e2f93 100644 --- a/config/SZBE69_B8/objects.json +++ b/config/SZBE69_B8/objects.json @@ -275,7 +275,7 @@ "band3/meta_band/SongUpgradeMgr.cpp": "NonMatching", "band3/meta_band/StandIn.cpp": "Matching", "band3/meta_band/StandInProvider.cpp": "Matching", - "band3/meta_band/StoreInfoPanel.cpp": "MISSING", + "band3/meta_band/StoreInfoPanel.cpp": "NonMatching", "band3/meta_band/StoreMainPanel.cpp": "NonMatching", "band3/meta_band/StoreMenuPanel.cpp": "MISSING", "band3/meta_band/StoreMenuProvider.cpp": "MISSING", diff --git a/src/band3/meta_band/StoreInfoPanel.cpp b/src/band3/meta_band/StoreInfoPanel.cpp new file mode 100644 index 000000000..826fb6b0b --- /dev/null +++ b/src/band3/meta_band/StoreInfoPanel.cpp @@ -0,0 +1,177 @@ +#include "meta_band/StoreInfoPanel.h" +#include "meta/StoreArtLoaderPanel.h" +#include "meta_band/BandStoreOffer.h" +#include "net/Net.h" +#include "obj/Data.h" +#include "obj/ObjMacros.h" +#include "obj/Object.h" +#include "os/Debug.h" +#include "os/PlatformMgr.h" +#include "os/System.h" +#include "ui/UIPanel.h" +#include "utl/Messages2.h" +#include "utl/Messages3.h" +#include "utl/NetLoader.h" +#include "utl/Std.h" +#include "utl/Symbols.h" + +StoreInfoPanel *TheStoreInfoPanel; + +StoreInfoPanel::StoreInfoPanel() + : mOffer(this), mLoader(0), mCurRecommendationIdx(0), unk5c(0) { + TheStoreInfoPanel = this; +} + +StoreInfoPanel::~StoreInfoPanel() { ClearData(); } + +void StoreInfoPanel::Enter() { + if (mOffer == 0) { + MILO_FAIL("StoreInfoPanel needs an offer set before Enter()!"); + } + UIPanel::Enter(); +} + +void StoreInfoPanel::Poll() { + StoreArtLoaderPanel::Poll(); + if (mLoader != 0) { + mLoader->PollLoading(); + if (mLoader->IsLoaded()) { + if (mLoader->unk_0x4 != 0) { + if (ParseRecommendations(mLoader->unk_0x4)) { + mCurRecommendationIdx = 0; + PushRecommendationsReady(); + } else { + PushRecommendationFailure(); + } + } else { + PushRecommendationFailure(); + } + RELEASE(mLoader); + } else { + if (mLoader->HasFailed()) { + PushRecommendationFailure(); + RELEASE(mLoader); + } + } + } else { + if (mRecommendations.size() && !unk5c && IsAllArtLoadedOrFailed()) { + MILO_ASSERT(mRecommendations.size() == mCoverArtTexs.size(), 0x67); + for (int i = 0; i < mRecommendations.size(); i++) { + RndBitmap *bmp = GetBmp(mRecommendations[i].unkc); + if (bmp) { + MILO_ASSERT(!mCoverArtTexs[i], 0x6F); + RndTex *tex = Hmx::Object::New(); + mCoverArtTexs[i] = tex; + mCoverArtTexs[i]->SetBitmap(*bmp, nullptr, false); + } + } + unk5c = true; + PushRecommendationsReady(); + } + } +} + +void StoreInfoPanel::Unload() { + ClearData(); + StoreArtLoaderPanel::Unload(); +} + +void StoreInfoPanel::ClearData() { + mOffer = nullptr; + unk5c = 0; + DeleteAll(mCoverArtTexs); + mCoverArtTexs.resize(0); + RELEASE(mLoader); + ClearAndShrink(mRecommendations); + ClearArt(); +} + +void StoreInfoPanel::FetchRecommendations() { + if (!mLoader) { + MILO_ASSERT(mOffer, 0x98); + BandStoreOffer *offer = dynamic_cast(mOffer.Ptr()); + MILO_ASSERT(offer, 0x9C); + String str20; + if (!offer->Exists()) { + str20 = offer->mPackedData->GetOfferId(); + String path; + GetRecommendationIndexPath(str20.c_str(), path); + mLoader = new DataNetLoader(path); + } else + PushRecommendationFailure(); + } +} + +void StoreInfoPanel::RotateRecommendation() { + mCurRecommendationIdx = (mCurRecommendationIdx + 1) % mRecommendations.size(); +} + +const StoreInfoPanel::RecommendedEntry *StoreInfoPanel::CurrentRecommendation() const { + MILO_ASSERT(!mRecommendations.empty(), 200); + return &mRecommendations[mCurRecommendationIdx]; +} + +bool StoreInfoPanel::ParseRecommendations(DataArray *data) { + MILO_ASSERT(data, 0xCE); + data->AddRef(); + ClearAndShrink(mRecommendations); + DataArray *cnt = data->FindArray(content, false); + if (cnt) { + int cap = cnt->Size() - 1; + for (int i = 0; i < cap; i++) { + RecommendedEntry entry; + DataArray *result = cnt->Array(i + 1); + if (result->Size() >= 3) { + entry.unk0 = result->Str(0); + entry.unkc = "/dlc_store"; + entry.unkc += result->Str(1); + entry.unk18 = result->Str(2); + EnsureArtLoader(entry.unkc); + mRecommendations.push_back(entry); + mCoverArtTexs.push_back(nullptr); + } else { + TheDebug + << "StoreInfoPanel::ParseRecommendations: invalid recommendation result:\n" + << result << "\n"; + } + } + } + data->Release(); + return !mRecommendations.empty(); +} + +void StoreInfoPanel::GetRecommendationIndexPath(const char *cc, String &str) { + static const char *pathFmt = "dlc_store/%s/%s/related/%s.dta"; + Symbol regionSym = PlatformRegionToSymbol(ThePlatformMgr.GetRegion()); + str = MakeString(pathFmt, regionSym, SystemLanguage(), cc); + Server *server = TheNet.GetServer(); + if (server && server->IsConnected()) { + str += MakeString("?pid=%u", server->GetMasterProfileID()); + } +} + +void StoreInfoPanel::PushRecommendationFailure() { HandleType(no_recommendations_msg); } +void StoreInfoPanel::PushRecommendationsReady() { HandleType(recommendations_ready_msg); } + +RndTex *StoreInfoPanel::GetRecommendationTex(int idx) { + int numRecs = mRecommendations.size(); + int mod = (idx + mCurRecommendationIdx - 1) % numRecs; + if (mod < 0) + mod += numRecs; + return mCoverArtTexs[mod]; +} + +BEGIN_PROPSYNCS(StoreInfoPanel) + SYNC_PROP(cur_offer, mOffer) + SYNC_SUPERCLASS(Hmx::Object) +END_PROPSYNCS + +BEGIN_HANDLERS(StoreInfoPanel) + HANDLE_ACTION(fetch_recommendations, FetchRecommendations()) + HANDLE_EXPR(recommendation_path, CurrentRecommendation()->unk18) + HANDLE_ACTION(rotate_recommendation, RotateRecommendation()) + HANDLE_EXPR(get_recommendation_tex, GetRecommendationTex(_msg->Int(2))) + HANDLE_ACTION(clear_data, ClearData()) + HANDLE_SUPERCLASS(StoreArtLoaderPanel) + HANDLE_CHECK(0x132) +END_HANDLERS \ No newline at end of file diff --git a/src/band3/meta_band/StoreInfoPanel.h b/src/band3/meta_band/StoreInfoPanel.h index 19e91e5b1..484b59bcb 100644 --- a/src/band3/meta_band/StoreInfoPanel.h +++ b/src/band3/meta_band/StoreInfoPanel.h @@ -1,3 +1,42 @@ #pragma once +#include "meta/StoreArtLoaderPanel.h" +#include "meta/StoreOffer.h" +#include "utl/NetLoader.h" -class StoreInfoPanel {}; +class StoreInfoPanel : public StoreArtLoaderPanel { +public: + class RecommendedEntry { + public: + String unk0; + String unkc; + String unk18; + }; + StoreInfoPanel(); + OBJ_CLASSNAME(UIPanel); + OBJ_SET_TYPE(UIPanel); + virtual DataNode Handle(DataArray *, bool); + virtual ~StoreInfoPanel(); + virtual void Enter(); + virtual void Poll(); + virtual void Unload(); + virtual bool SyncProperty(DataNode &_val, DataArray *_prop, int _i, PropOp _op); + + void ClearData(); + void FetchRecommendations(); + void RotateRecommendation(); + void GetRecommendationIndexPath(const char *, String &); + const RecommendedEntry *CurrentRecommendation() const; + bool ParseRecommendations(DataArray *); + RndTex *GetRecommendationTex(int); + void PushRecommendationFailure(); + void PushRecommendationsReady(); + + ObjPtr mOffer; // 0x40, 0x44, 0x48 + std::vector mRecommendations; // 0x4c, 0x50, 0x52 + DataNetLoader *mLoader; // 0x54 + int mCurRecommendationIdx; // 0x58 + bool unk5c; // 0x5c + std::vector mCoverArtTexs; // 0x60 +}; + +extern StoreInfoPanel *TheStoreInfoPanel; \ No newline at end of file diff --git a/src/network/net/Server.h b/src/network/net/Server.h index c6d9a7202..c0075381b 100644 --- a/src/network/net/Server.h +++ b/src/network/net/Server.h @@ -59,7 +59,7 @@ class Server : public MsgSource { MILO_FAIL("not implemented for this platform"); return 0; } - virtual int GetMasterProfileID() { + virtual unsigned int GetMasterProfileID() { MILO_FAIL("not implemented for this platform"); return 0; } diff --git a/src/network/net/Server_Wii.h b/src/network/net/Server_Wii.h index 12c91c2c9..21f0644f9 100644 --- a/src/network/net/Server_Wii.h +++ b/src/network/net/Server_Wii.h @@ -22,7 +22,7 @@ class WiiServer : public Server { virtual int GetCompetitionClient(); virtual Quazal::SecureConnectionClient *GetSecureConnectionClient(); virtual Quazal::AccountManagementClient *GetAccountManagementClient(); - virtual int GetMasterProfileID(); + virtual unsigned int GetMasterProfileID(); virtual int CreateProfile(String); virtual int DeleteProfile(OnlineID &); virtual Quazal::Data *GetCustomAuthData(); diff --git a/src/system/char/CharBones.cpp b/src/system/char/CharBones.cpp index f28b8dd29..9cfcf1c9b 100644 --- a/src/system/char/CharBones.cpp +++ b/src/system/char/CharBones.cpp @@ -107,19 +107,27 @@ void CharBones::ListBones(std::list &bones) const { void CharBones::Zero() { memset(mStart, 0, mTotalSize); } int CharBones::TypeSize(int i) const { - if(i > 1U){ - if(i != 2){ - if(mCompression != kCompressNone) return 2; - else return 4; - } - else { - if(mCompression >= kCompressQuats) return 4; - else if(mCompression != kCompressNone) return 8; - else return 16; - } + switch (i) { + case TYPE_POS: + case TYPE_SCALE: + if (mCompression >= kCompressVects) + return 6; + else + return 12; + case TYPE_QUAT: + if (mCompression >= kCompressQuats) + return 4; + else if (mCompression != kCompressNone) + return 8; + else + return 16; + + default: + if (mCompression != kCompressNone) + return 2; + else + return 4; } - else if(mCompression >= kCompressVects) return 6; - else return 12; } int CharBones::FindOffset(Symbol s) const { @@ -157,7 +165,8 @@ void CharBones::RecomputeSizes() { int diff = mCounts[i + 1] - mCounts[i]; mOffsets[i + 1] = mOffsets[i] + diff * TypeSize(i); } - mTotalSize = mEndOffset + 0xFU & 0xFFFFFFF0; + mTotalSize = mEndOffset + 0xFU & 0xFFFFFFF0; // round up to the nearest 0x10, + // alignment moment } void CharBones::SetCompression(CompressionType ty) { @@ -169,50 +178,46 @@ void CharBones::SetCompression(CompressionType ty) { DECOMP_FORCEACTIVE(CharBones, "!mCompression && !bones.mCompression") -const char* CharBones::StringVal(Symbol s){ - void* ptr = FindPtr(s); +const char *CharBones::StringVal(Symbol s) { + void *ptr = FindPtr(s); CharBones::Type t = TypeOf(s); - if(t < 2){ - if(mCompression >= 2){ - Vector3 vshort((short*)ptr); + if (t < 2) { + if (mCompression >= 2) { + Vector3 vshort((short *)ptr); return MakeString("%g %g %g", vshort.x, vshort.y, vshort.z); - } - else { - Vector3* vptr = (Vector3*)vptr; + } else { + Vector3 *vptr = (Vector3 *)vptr; return MakeString("%g %g %g", vptr->x, vptr->y, vptr->z); } - } - else if(t == 2){ + } else if (t == 2) { Hmx::Quat q; - Hmx::Quat* qPtr = (Hmx::Quat*)ptr; - if(mCompression >= 3){ - ByteQuat* bqPtr = (ByteQuat*)qPtr; + Hmx::Quat *qPtr = (Hmx::Quat *)ptr; + if (mCompression >= 3) { + ByteQuat *bqPtr = (ByteQuat *)qPtr; bqPtr->ToQuat(q); - } - else if(mCompression != kCompressNone){ - ShortQuat* sqPtr = (ShortQuat*)qPtr; + } else if (mCompression != kCompressNone) { + ShortQuat *sqPtr = (ShortQuat *)qPtr; sqPtr->ToQuat(q); - } - else q = *qPtr; + } else + q = *qPtr; Vector3 v40; MakeEuler(q, v40); v40 *= RAD2DEG; - return MakeString("quat(%g %g %g %g) euler(%g %g %g)", q.x, q.y, q.z, q.w, v40.x, v40.y, v40.z); - } - else { + return MakeString( + "quat(%g %g %g %g) euler(%g %g %g)", q.x, q.y, q.z, q.w, v40.x, v40.y, v40.z + ); + } else { float floatVal; - if(mCompression != kCompressNone){ - floatVal = *((short*)ptr) * 0.00061035156f; - } - else { - floatVal = *((float*)ptr); + if (mCompression != kCompressNone) { + floatVal = *((short *)ptr) * 0.00061035156f; + } else { + floatVal = *((float *)ptr); } floatVal *= RAD2DEG; - if(mCompression != kCompressNone){ - return MakeString("deg %g raw %d", floatVal, *((short*)ptr)); - } - else { - return MakeString("deg %g rad %g", floatVal, *((float*)ptr)); + if (mCompression != kCompressNone) { + return MakeString("deg %g raw %d", floatVal, *((short *)ptr)); + } else { + return MakeString("deg %g rad %g", floatVal, *((float *)ptr)); } } } @@ -223,7 +228,9 @@ void CharBones::Print() { } } -DECOMP_FORCEACTIVE(CharBones, "!mCompression", "false", "newSize == 4", "oldSize == 2", "end >= start") +DECOMP_FORCEACTIVE( + CharBones, "!mCompression", "false", "newSize == 4", "oldSize == 2", "end >= start" +) void CharBones::ScaleAdd(CharClip *clip, float f1, float f2, float f3) { clip->ScaleAdd(*this, f1, f2, f3); diff --git a/src/system/utl/NetLoader.h b/src/system/utl/NetLoader.h index a8261b6fc..715e55845 100644 --- a/src/system/utl/NetLoader.h +++ b/src/system/utl/NetLoader.h @@ -1,6 +1,7 @@ #ifndef UTL_NETLOADER_H #define UTL_NETLOADER_H +#include "obj/Data.h" #include "os/Debug.h" #include "utl/Str.h" #include "utl/Loader.h" @@ -55,7 +56,7 @@ class DataNetLoader { bool HasFailed(); NetLoaderStub *mLoader; // 0x0 - int unk_0x4; // 0x4 + DataArray *unk_0x4; // 0x4 }; #endif \ No newline at end of file