diff --git a/Editor/ProjectManager.cpp b/Editor/ProjectManager.cpp index 4427388e8..1c67c8e4b 100644 --- a/Editor/ProjectManager.cpp +++ b/Editor/ProjectManager.cpp @@ -183,7 +183,13 @@ bool ProjectManager::saveProject() void ProjectManager::mainUpdate() { if (m_mainMP1) - m_mainMP1->Proc(); + { + if (m_mainMP1->Proc()) + { + m_mainMP1->Shutdown(); + m_mainMP1 = std::experimental::nullopt; + } + } } void ProjectManager::mainDraw() diff --git a/Runtime/Audio/CAudioSys.cpp b/Runtime/Audio/CAudioSys.cpp index 9cc3413c0..03129ae2b 100644 --- a/Runtime/Audio/CAudioSys.cpp +++ b/Runtime/Audio/CAudioSys.cpp @@ -82,9 +82,23 @@ void CAudioSys::SysRemoveGroupFromAmuse(const std::string& name) RemoveAudioGroup(set->GetAudioGroupData()); } +static float s_MasterVol = 1.f; +static float s_SfxVol = 1.f; +void CAudioSys::_UpdateVolume() +{ + GetAmuseEngine().setVolume(s_MasterVol * s_SfxVol); +} + void CAudioSys::SysSetVolume(u8 volume) { - GetAmuseEngine().setVolume(volume / 127.f); + s_MasterVol = volume / 127.f; + _UpdateVolume(); +} + +void CAudioSys::SysSetSfxVolume(u8 volume, u16 time, bool music, bool fx) +{ + s_SfxVol = volume / 127.f; + _UpdateVolume(); } static s16 s_VolumeScale = 0x7f; diff --git a/Runtime/Audio/CAudioSys.hpp b/Runtime/Audio/CAudioSys.hpp index 5737ed164..6fafff6f0 100644 --- a/Runtime/Audio/CAudioSys.hpp +++ b/Runtime/Audio/CAudioSys.hpp @@ -31,6 +31,7 @@ private: static CAudioSys* g_SharedSys; boo::IAudioVoiceEngine* m_voiceEngine; amuse::Engine m_engine; + static void _UpdateVolume(); public: struct C3DEmitterParmData @@ -86,6 +87,7 @@ public: static void SysAddGroupIntoAmuse(const std::string& name); static void SysRemoveGroupFromAmuse(const std::string& name); static void SysSetVolume(u8 volume); + static void SysSetSfxVolume(u8 volume, u16 time, bool music, bool fx); static s16 GetDefaultVolumeScale(); static void SetDefaultVolumeScale(s16 scale); diff --git a/Runtime/Audio/CStaticAudioPlayer.cpp b/Runtime/Audio/CStaticAudioPlayer.cpp index c766e03ba..239a1b4fc 100644 --- a/Runtime/Audio/CStaticAudioPlayer.cpp +++ b/Runtime/Audio/CStaticAudioPlayer.cpp @@ -66,10 +66,10 @@ void CStaticAudioPlayer::DecodeMonoAndMix(s16* bufOut, u32 numSamples, if (!loopState && cur + i == loopStartCur) loopState.emplace(state); - *bufOut = SampClamp((g721_decoder(*byte & 0xf, &state) * vol) >> 15); + *bufOut = SampClamp(((g721_decoder(*byte & 0xf, &state) * vol) >> 15) * 0.7f); bufOut += 2; - *bufOut = SampClamp((g721_decoder(*byte >> 4 & 0xf, &state) * vol) >> 15); + *bufOut = SampClamp(((g721_decoder(*byte >> 4 & 0xf, &state) * vol) >> 15) * 0.7f); bufOut += 2; } diff --git a/Runtime/Audio/CStreamAudioManager.cpp b/Runtime/Audio/CStreamAudioManager.cpp index 0c3a692b7..78fcc2894 100644 --- a/Runtime/Audio/CStreamAudioManager.cpp +++ b/Runtime/Audio/CStreamAudioManager.cpp @@ -328,8 +328,8 @@ struct SDSPStream : boo::IAudioVoiceCallback if (!x0_active || xe8_silent) return; float coefs[8] = {}; - coefs[int(boo::AudioChannel::FrontLeft)] = m_leftgain * vol; - coefs[int(boo::AudioChannel::FrontRight)] = m_rightgain * vol; + coefs[int(boo::AudioChannel::FrontLeft)] = m_leftgain * vol * 0.7f; + coefs[int(boo::AudioChannel::FrontRight)] = m_rightgain * vol * 0.7f; m_booVoice->setMonoChannelLevels(nullptr, coefs, true); } @@ -1153,12 +1153,44 @@ void CStreamAudioManager::UpdateDSPStreamers(float dt) UpdateDSP(true, dt); } +void CStreamAudioManager::StopAllStreams() +{ + for (int i=0 ; i<2 ; ++i) + { + StopStreaming(i); + SDSPPlayer& p = s_Players[i]; + SDSPPlayer& qp = s_QueuedPlayers[i]; + p = SDSPPlayer(); + qp = SDSPPlayer(); + } +} + void CStreamAudioManager::Update(float dt) { CDSPStreamManager::PollHeaderReadCompletions(); UpdateDSPStreamers(dt); } +void CStreamAudioManager::StopAll() +{ + StopAllStreams(); +} + +void CStreamAudioManager::SetMusicUnmute(bool unmute) +{ + g_MusicUnmute = unmute; +} + +void CStreamAudioManager::SetSfxVolume(u8 volume) +{ + g_SfxVolume = std::min(volume, u8(127)); +} + +void CStreamAudioManager::SetMusicVolume(u8 volume) +{ + g_MusicVolume = std::min(volume, u8(127)); +} + void CStreamAudioManager::Initialize() { CDSPStreamManager::Initialize(); diff --git a/Runtime/Audio/CStreamAudioManager.hpp b/Runtime/Audio/CStreamAudioManager.hpp index 7d502ad9b..af1836b67 100644 --- a/Runtime/Audio/CStreamAudioManager.hpp +++ b/Runtime/Audio/CStreamAudioManager.hpp @@ -17,6 +17,7 @@ class CStreamAudioManager static void StopStreaming(bool oneshot); static void UpdateDSP(bool oneshot, float dt); static void UpdateDSPStreamers(float dt); + static void StopAllStreams(); public: static void Start(bool oneshot, const std::string& fileName, u8 volume, @@ -25,6 +26,11 @@ public: static void FadeBackIn(bool oneshot, float fadeTime); static void TemporaryFadeOut(bool oneshot, float fadeTime); static void Update(float dt); + static void StopAll(); + static void SetMusicUnmute(bool unmute); + static void SetSfxVolume(u8 volume); + static void SetMusicVolume(u8 volume); + static void Initialize(); static void Shutdown(); }; diff --git a/Runtime/CGameOptions.cpp b/Runtime/CGameOptions.cpp index bf3aa97e4..98e3367c6 100644 --- a/Runtime/CGameOptions.cpp +++ b/Runtime/CGameOptions.cpp @@ -8,7 +8,8 @@ #include "CGameState.hpp" #include "Input/CFinalInput.hpp" #include "Audio/CSfxManager.hpp" -//#include "Audio/CStreamedAudioManager.hpp" +#include "Audio/CStreamAudioManager.hpp" +#include "Graphics/CMoviePlayer.hpp" namespace urde { @@ -283,23 +284,19 @@ void CGameOptions::SetSfxVolume(s32 vol, bool apply) { x58_sfxVol = zeus::clamp(0, vol, 0x7f); -#if 0 if (apply) { CAudioSys::SysSetSfxVolume(x58_sfxVol, 1, 1, 1); - CStreamedAudioManager::SetSfxVolume(x58_sfxVol); + CStreamAudioManager::SetSfxVolume(x58_sfxVol); CMoviePlayer::SetSfxVolume(x58_sfxVol); } -#endif } void CGameOptions::SetMusicVolume(s32 vol, bool apply) { x5c_musicVol = zeus::clamp(0, vol, 0x7f); -# if 0 if (apply) - CStreamedAudioManager::SetGlobalVolume(x5c_musicVol); -#endif + CStreamAudioManager::SetMusicVolume(x5c_musicVol); } void CGameOptions::SetHUDAlpha(u32 alpha) @@ -570,4 +567,10 @@ void CHintOptions::SetNextHintTime() g_MemoryCardSys->GetHints()[x10_nextHintIdx].GetTime() + 5.f; } +void CHintOptions::InitializeMemoryState() +{ + const auto& hints = g_MemoryCardSys->GetHints(); + x0_hintStates.resize(hints.size()); +} + } diff --git a/Runtime/CGameOptions.hpp b/Runtime/CGameOptions.hpp index aa3a7de03..e259ae9a0 100644 --- a/Runtime/CGameOptions.hpp +++ b/Runtime/CGameOptions.hpp @@ -205,6 +205,7 @@ public: CHintOptions(CBitStreamReader& stream); void PutTo(CBitStreamWriter& writer) const; void SetNextHintTime(); + void InitializeMemoryState(); }; } diff --git a/Runtime/CGameState.cpp b/Runtime/CGameState.cpp index 07c33dcc7..3a0df08b2 100644 --- a/Runtime/CGameState.cpp +++ b/Runtime/CGameState.cpp @@ -113,7 +113,8 @@ CGameState::GameFileStateInfo CGameState::LoadGameFileState(const u8* data) ret.x20_hardMode = stream.ReadEncoded(1); stream.ReadEncoded(1); - ret.x8_mlvlId = g_ResFactory->TranslateOriginalToNew(stream.ReadEncoded(32)); + ResId origMLVL = stream.ReadEncoded(32); + ret.x8_mlvlId = g_ResFactory->TranslateOriginalToNew(origMLVL); BitsToDouble conv; conv.low = stream.ReadEncoded(32); @@ -124,7 +125,7 @@ CGameState::GameFileStateInfo CGameState::LoadGameFileState(const u8* data) ret.x10_energyTanks = playerState.GetItemCapacity(CPlayerState::EItemType::EnergyTanks); u32 itemPercent; - if (ret.x8_mlvlId == 0x158EFE17) + if (origMLVL == 0x158EFE17) itemPercent = 0; else itemPercent = playerState.CalculateItemCollectionRate() * 100 / playerState.GetPickupTotal(); @@ -142,14 +143,17 @@ CGameState::GameFileStateInfo CGameState::LoadGameFileState(const u8* data) CGameState::CGameState() { - x98_playerState.reset(new CPlayerState()); - x9c_transManager.reset(new CWorldTransManager()); + x98_playerState = std::make_shared(); + x9c_transManager = std::make_shared(); x228_25_deferPowerupInit = true; + if (g_MemoryCardSys) + InitializeMemoryStates(); } CGameState::CGameState(CBitStreamReader& stream, u32 saveIdx) : x20c_saveFileIdx(saveIdx) { + x9c_transManager = std::make_shared(); x228_25_deferPowerupInit = true; for (u32 i = 0; i < 128; i++) @@ -180,6 +184,9 @@ CGameState::CGameState(CBitStreamReader& stream, u32 saveIdx) g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), memWorld.second.GetSaveWorldAssetId()}); x88_worldStates.emplace_back(stream, memWorld.first, *saveWorld); } + + InitializeMemoryWorlds(); + WriteBackupBuf(); } void CGameState::ReadPersistentOptions(CBitStreamReader& r) @@ -292,4 +299,22 @@ float CGameState::GetHardModeWeaponMultiplier() const return g_tweakGame->GetHardModeWeaponMultiplier(); } +void CGameState::InitializeMemoryWorlds() +{ + const auto& memoryWorlds = g_MemoryCardSys->GetMemoryWorlds(); + for (const auto& wld : memoryWorlds) + { + const auto& layerState = StateForWorld(wld.first).GetLayerState(); + layerState->InitializeWorldLayers(wld.second.GetDefaultLayerStates()); + } +} + +void CGameState::InitializeMemoryStates() +{ + x98_playerState->InitializeScanTimes(); + x1f8_hintOptions.InitializeMemoryState(); + InitializeMemoryWorlds(); + WriteBackupBuf(); +} + } diff --git a/Runtime/CGameState.hpp b/Runtime/CGameState.hpp index 98c8d46db..bee866e69 100644 --- a/Runtime/CGameState.hpp +++ b/Runtime/CGameState.hpp @@ -120,6 +120,8 @@ public: void PutTo(CBitStreamWriter& writer) const; float GetHardModeDamageMultiplier() const; float GetHardModeWeaponMultiplier() const; + void InitializeMemoryWorlds(); + void InitializeMemoryStates(); struct GameFileStateInfo { diff --git a/Runtime/CIOWinManager.cpp b/Runtime/CIOWinManager.cpp index 77c0bd5ee..f765257d5 100644 --- a/Runtime/CIOWinManager.cpp +++ b/Runtime/CIOWinManager.cpp @@ -63,8 +63,9 @@ bool CIOWinManager::DistributeOneMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { CArchitectureMessage tmpMsg = msg; - for (IOWinPQNode* node = x4_pumpRoot ; node ; node = node->x8_next) + for (IOWinPQNode* node = x4_pumpRoot ; node ;) { + IOWinPQNode* next = node->x8_next; CIOWin* iow = node->GetIOWin(); CIOWin::EMessageReturn mret = iow->OnMessage(tmpMsg, x8_localGatherQueue); @@ -99,6 +100,8 @@ bool CIOWinManager::DistributeOneMessage(const CArchitectureMessage& msg, return false; default: break; } + + node = next; } return false; diff --git a/Runtime/CIOWinManager.hpp b/Runtime/CIOWinManager.hpp index 54fb141fd..53b2cbe88 100644 --- a/Runtime/CIOWinManager.hpp +++ b/Runtime/CIOWinManager.hpp @@ -37,6 +37,7 @@ public: void RemoveAllIOWins(); void RemoveIOWin(CIOWin* toRemove); void AddIOWin(std::weak_ptr toAdd, int pumpPrio, int drawPrio); + bool IsEmpty() const { return x0_drawRoot == nullptr && x4_pumpRoot == nullptr; } }; } diff --git a/Runtime/CMemoryCardSys.cpp b/Runtime/CMemoryCardSys.cpp index 00e1e360f..1c035a5eb 100644 --- a/Runtime/CMemoryCardSys.cpp +++ b/Runtime/CMemoryCardSys.cpp @@ -138,7 +138,13 @@ bool CMemoryCardSys::InitializePump() x20_scanStates.reserve(x20_scanStates.size() + savw.GetScans().size()); for (const CSaveWorld::SScanState& scan : savw.GetScans()) - x20_scanStates.emplace_back(scan.x0_id, scan.x4_category); + { + auto existingSearch = + std::find_if(x20_scanStates.begin(), x20_scanStates.end(), [&](const auto& test) + { return test.first == scan.x0_id && test.second == scan.x4_category; }); + if (existingSearch == x20_scanStates.end()) + x20_scanStates.emplace_back(scan.x0_id, scan.x4_category); + } wldMemOut.x3c_saveWorld = std::move(world.x34_saveWorld); wldMemOut.x2c_worldName = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), wldMemOut.x0_strgId}); diff --git a/Runtime/CMemoryCardSys.hpp b/Runtime/CMemoryCardSys.hpp index fc625aeeb..90dc48931 100644 --- a/Runtime/CMemoryCardSys.hpp +++ b/Runtime/CMemoryCardSys.hpp @@ -29,7 +29,7 @@ class CSaveWorldMemory public: ResId GetSaveWorldAssetId() const { return x4_savwId; } u32 GetAreaCount() const { return x8_areaCount; } - + const std::vector& GetDefaultLayerStates() const { return x1c_defaultLayerStates; } const TLockedToken& GetWorldName() const { return x2c_worldName; } const TLockedToken& GetSaveWorld() const { return x3c_saveWorld; } const char16_t* GetFrontEndName() const diff --git a/Runtime/CPlayerState.cpp b/Runtime/CPlayerState.cpp index 8278424b8..ad1b7882b 100644 --- a/Runtime/CPlayerState.cpp +++ b/Runtime/CPlayerState.cpp @@ -4,6 +4,8 @@ #include "CStateManager.hpp" #include "Camera/CCameraManager.hpp" #include "Camera/CFirstPersonCamera.hpp" +#include "CMemoryCardSys.hpp" +#include "GameGlobalObjects.hpp" namespace urde { @@ -57,8 +59,15 @@ const char* PowerUpNames[41]= "Artifact of Newborn", }; +CPlayerState::CPlayerState() +: x188_staticIntf(5) +{ + x0_24_ = true; + x24_powerups.resize(41); +} + CPlayerState::CPlayerState(CBitStreamReader& stream) - : CPlayerState() +: x188_staticIntf(5) { x4_ = stream.ReadEncoded(0x20); u32 tmp = stream.ReadEncoded(0x20); @@ -76,14 +85,12 @@ CPlayerState::CPlayerState(CBitStreamReader& stream) x24_powerups[i] = CPowerUp(a, b); } - x170_scanTimes.resize(846); - for (u32 i = 0; i < x170_scanTimes.size(); i++) + const auto& scanStates = g_MemoryCardSys->GetScanStates(); + x170_scanTimes.reserve(scanStates.size()); + for (const auto& state : scanStates) { - x170_scanTimes[i].first = stream.ReadEncoded(1); - if (x170_scanTimes[i].first) - x170_scanTimes[i].second = 1.f; - else - x170_scanTimes[i].second = 0.f; + float time = stream.ReadEncoded(1) ? 1.f : 0.f; + x170_scanTimes.emplace_back(state.first, time); } x180_logScans = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100)); @@ -394,4 +401,15 @@ void CPlayerState::ReInitalizePowerUp(CPlayerState::EItemType type, u32 capacity InitializePowerUp(type, capacity); } +void CPlayerState::InitializeScanTimes() +{ + if (x170_scanTimes.size()) + return; + + const auto& scanStates = g_MemoryCardSys->GetScanStates(); + x170_scanTimes.reserve(scanStates.size()); + for (const auto& state : scanStates) + x170_scanTimes.emplace_back(state.first, 0.f); +} + } diff --git a/Runtime/CPlayerState.hpp b/Runtime/CPlayerState.hpp index d52f053b9..c11836867 100644 --- a/Runtime/CPlayerState.hpp +++ b/Runtime/CPlayerState.hpp @@ -123,7 +123,7 @@ private: float x1c_visorTransitionFactor = 0.2f; EPlayerSuit x20_currentSuit = EPlayerSuit::Power; rstl::reserved_vector x24_powerups; - rstl::reserved_vector, 846> x170_scanTimes; + rstl::reserved_vector, 846> x170_scanTimes; u32 x180_logScans = 0; u32 x184_totalLogScans = 0; CStaticInterference x188_staticIntf; @@ -168,8 +168,9 @@ public: void InitializePowerUp(EItemType type, u32 capacity); u32 GetLogScans() const { return x180_logScans; } u32 GetTotalLogScans() const { return x184_totalLogScans; } - const rstl::reserved_vector, 846>& GetScanTimes() const { return x170_scanTimes; } - CPlayerState() : x188_staticIntf(5) { x0_24_ = true; } + void InitializeScanTimes(); + const rstl::reserved_vector, 846>& GetScanTimes() const { return x170_scanTimes; } + CPlayerState(); CPlayerState(CBitStreamReader& stream); void PutTo(CBitStreamWriter& stream); diff --git a/Runtime/Graphics/CMoviePlayer.cpp b/Runtime/Graphics/CMoviePlayer.cpp index 5c0a7d263..33b61d2bb 100644 --- a/Runtime/Graphics/CMoviePlayer.cpp +++ b/Runtime/Graphics/CMoviePlayer.cpp @@ -191,6 +191,9 @@ static u32 StaticLoopEnd = 0; static g72x_state StaticStateLeft = {}; static g72x_state StaticStateRight = {}; +/* THP SFX audio */ +static float SfxVolume = 1.f; + static const char* BlockNames[] = {"SpecterViewBlock"}; static const char* TexNames[] = {"texY", "texU", "texV"}; @@ -523,6 +526,11 @@ void CMoviePlayer::SetStaticAudio(const void* data, u32 size, u32 loopBegin, u32 g72x_init_state(&StaticStateRight); } +void CMoviePlayer::SetSfxVolume(u8 volume) +{ + SfxVolume = std::min(volume, u8(127)) / 127.f; +} + void CMoviePlayer::MixAudio(s16* out, const s16* in, u32 samples) { /* No audio frames ready */ @@ -557,9 +565,9 @@ void CMoviePlayer::MixAudio(s16* out, const s16* in, u32 samples) for (u32 i=0 ; iaudioBuf[(i+tex->playedSamples)*2]) * 0x50F4 / 0x8000); + s32(tex->audioBuf[(i+tex->playedSamples)*2]) * 0x50F4 / 0x8000 * SfxVolume); out[1] = DSPSampClamp(in[1] + - s32(tex->audioBuf[(i+tex->playedSamples)*2+1]) * 0x50F4 / 0x8000); + s32(tex->audioBuf[(i+tex->playedSamples)*2+1]) * 0x50F4 / 0x8000 * SfxVolume); } } else @@ -567,9 +575,9 @@ void CMoviePlayer::MixAudio(s16* out, const s16* in, u32 samples) for (u32 i=0 ; iaudioBuf[(i+tex->playedSamples)*2]) * 0x50F4 / 0x8000); + s32(tex->audioBuf[(i+tex->playedSamples)*2]) * 0x50F4 / 0x8000 * SfxVolume); out[1] = DSPSampClamp( - s32(tex->audioBuf[(i+tex->playedSamples)*2+1]) * 0x50F4 / 0x8000); + s32(tex->audioBuf[(i+tex->playedSamples)*2+1]) * 0x50F4 / 0x8000 * SfxVolume); } } tex->playedSamples += thisSamples; diff --git a/Runtime/Graphics/CMoviePlayer.hpp b/Runtime/Graphics/CMoviePlayer.hpp index c578abe1c..5030c7b63 100644 --- a/Runtime/Graphics/CMoviePlayer.hpp +++ b/Runtime/Graphics/CMoviePlayer.hpp @@ -146,6 +146,7 @@ public: static void DisableStaticAudio() {SetStaticAudio(nullptr, 0, 0, 0);} static void SetStaticAudioVolume(int vol); static void SetStaticAudio(const void* data, u32 size, u32 loopBegin, u32 loopEnd); + static void SetSfxVolume(u8 volume); static void MixStaticAudio(s16* out, const s16* in, u32 samples); void MixAudio(s16* out, const s16* in, u32 samples); void Rewind(); diff --git a/Runtime/IOStreams.cpp b/Runtime/IOStreams.cpp index 775ce2bb7..19c6d6a1e 100644 --- a/Runtime/IOStreams.cpp +++ b/Runtime/IOStreams.cpp @@ -1,7 +1,21 @@ #include "IOStreams.hpp" +#include "hecl/hecl.hpp" namespace urde { + +#define DUMP_BITS 0 + +#if DUMP_BITS +static void PrintBinary(u32 val, u32 count) +{ + for (int i=0 ; i> (count-i-1)) & 0x1); + } +} +#endif + /*! * \brief CBitStreamReader::ReadBit * Reads and decodes an encoded value from a bitstream. @@ -10,91 +24,95 @@ namespace urde */ s32 CBitStreamReader::ReadEncoded(u32 bitCount) { - s32 ret = 0; - if (bitCount < x20_bitOffset) +#if DUMP_BITS + auto pos = position(); + auto boff = x20_bitOffset; +#endif + + u32 ret = 0; + s32 shiftAmt = x20_bitOffset - s32(bitCount); + if (shiftAmt < 0) { - u32 diff = 0x20 - bitCount; - u32 baseVal = -1; - if (x20_bitOffset != 0x20) - baseVal = (1 << bitCount) - 1; - x20_bitOffset -= bitCount; - ret = baseVal & (x1c_val >> diff); - x1c_val <<= bitCount; + /* OR in remaining bits of cached value */ + u32 mask = (1 << bitCount) - 1; + ret |= (x1c_val << -shiftAmt) & mask; + + /* Load in exact number of bytes remaining */ + auto loadDiv = std::div(-shiftAmt, 8); + if (loadDiv.rem) ++loadDiv.quot; + readUBytesToBuf(reinterpret_cast(&x1c_val) + 4 - loadDiv.quot, loadDiv.quot); + x1c_val = hecl::SBig(x1c_val); + + /* New bit offset */ + x20_bitOffset = loadDiv.quot * 8 + shiftAmt; + + /* OR in next bits */ + mask = (1 << -shiftAmt) - 1; + ret |= (x1c_val >> x20_bitOffset) & mask; } else { - u32 diff = bitCount - x20_bitOffset; - u32 baseVal = -1; - if (x20_bitOffset != 32) - baseVal = (1 << x20_bitOffset) - 1; + /* OR in bits of cached value */ + u32 mask = (1 << bitCount) - 1; + ret |= (x1c_val >> shiftAmt) & mask; - baseVal = (baseVal & (x1c_val >> (32 - x20_bitOffset))) << diff; - x20_bitOffset = 0; - auto pos = std::div(diff, 8); - if (pos.rem) ++pos.quot; - readUBytesToBuf(&x1c_val, pos.quot); - /* The game uses Big Endian, which doesn't work for us */ - /* Little Endian sucks */ - athena::utility::BigUint32(x1c_val); - - u32 baseVal2 = -1; - if (diff != 32) - baseVal2 = (1 << diff) - 1; - - ret = baseVal | (baseVal2 & (x1c_val >> (32 - diff))) << x20_bitOffset; - x20_bitOffset = (pos.quot << 3) - diff; - x1c_val <<= diff; + /* New bit offset */ + x20_bitOffset -= bitCount; } +#if DUMP_BITS + printf("READ "); + PrintBinary(ret, bitCount); + printf(" %d %d\n", int(pos), int(boff)); +#endif + return ret; } void CBitStreamWriter::WriteEncoded(u32 val, u32 bitCount) { - if (x18_bitOffset >= bitCount) +#if DUMP_BITS + printf("WRITE "); + PrintBinary(val, bitCount); + printf(" %d %d\n", int(position()), int(x18_bitOffset)); +#endif + + s32 shiftAmt = x18_bitOffset - s32(bitCount); + if (shiftAmt < 0) { - int baseVal = -1; - if (bitCount != 32) - baseVal = (1 << bitCount) - 1; - x14_val |= (val & baseVal) << (x18_bitOffset - bitCount); - x18_bitOffset -= bitCount; + /* OR remaining bits to cached value */ + u32 mask = (1 << x18_bitOffset) - 1; + x14_val |= (val >> -shiftAmt) & mask; + + /* Write out 32-bits */ + x14_val = hecl::SBig(x14_val); + writeUBytes(reinterpret_cast(&x14_val), 4); + + /* Cache remaining bits */ + x18_bitOffset = 0x20 + shiftAmt; + x14_val = val << x18_bitOffset; } else { - u32 diff = bitCount - x18_bitOffset; - u32 baseVal = -1; - if (x18_bitOffset != 32) - baseVal = (1 << x18_bitOffset) - 1; + /* OR bits to cached value */ + u32 mask = (1 << bitCount) - 1; + x14_val |= (val & mask) << shiftAmt; - x14_val |= (val >> diff) & baseVal; - x18_bitOffset = 0; - u32 tmp = x14_val; - athena::utility::BigUint32(tmp); - auto pos = std::div(32 - x18_bitOffset, 8); - if (pos.rem) ++pos.quot; - writeBytes(&tmp, pos.quot); - - u32 rem = 32 - diff; - baseVal = -1; - if (diff != 32) - baseVal = (1 << diff) - 1; - - x14_val = (val & baseVal) << rem; - x18_bitOffset -= diff; + /* New bit offset */ + x18_bitOffset -= bitCount; } } void CBitStreamWriter::Flush() { - if (x18_bitOffset && x18_bitOffset < 0x20) + if (x18_bitOffset < 0x20) { - u32 tmp = x14_val; - athena::utility::BigUint32(tmp); - auto pos = std::div(32 - x18_bitOffset, 8); + auto pos = std::div(0x20 - x18_bitOffset, 8); if (pos.rem) ++pos.quot; - writeBytes(&tmp, pos.quot); - x18_bitOffset = 32; + x14_val = hecl::SBig(x14_val); + writeUBytes(reinterpret_cast(&x14_val), pos.quot); + x18_bitOffset = 0x20; x14_val = 0; } } diff --git a/Runtime/IOStreams.hpp b/Runtime/IOStreams.hpp index 502a9ecb6..2f7e1f35e 100644 --- a/Runtime/IOStreams.hpp +++ b/Runtime/IOStreams.hpp @@ -31,38 +31,20 @@ public: } CBitStreamReader(const void* data, atUint64 length) - : MemoryReader(data, length) - { - } - - atUint64 readUBytesToBuf(void *buf, atUint64 len) - { - x20_bitOffset = 0; - atUint64 tmp = MemoryReader::readUBytesToBuf(buf, len); - return tmp; - } + : MemoryReader(data, length) {} s32 ReadEncoded(u32 key); }; class CBitStreamWriter : public athena::io::MemoryWriter { -private: u32 x14_val = 0; - u32 x18_bitOffset = 32; + u32 x18_bitOffset = 0x20; public: - static inline u32 GetBitCount(u32 maxVal) { return CBitStreamReader::GetBitCount(maxVal); } + static inline u32 GetBitCount(u32 maxVal) { return CBitStreamReader::GetBitCount(maxVal); } CBitStreamWriter(atUint8* data = nullptr, atUint64 length=0x10) - : MemoryWriter(data, length) - {} - - void writeUBytes(const atUint8 *data, atUint64 len) - { - x14_val = 0; - x18_bitOffset = 0x20; - MemoryWriter::writeUBytes(data, len); - } + : MemoryWriter(data, length) {} void WriteEncoded(u32 val, u32 bitCount); diff --git a/Runtime/MP1/CFrontEndUI.cpp b/Runtime/MP1/CFrontEndUI.cpp index 4f74367c4..c1a41fd16 100644 --- a/Runtime/MP1/CFrontEndUI.cpp +++ b/Runtime/MP1/CFrontEndUI.cpp @@ -1754,7 +1754,9 @@ CFrontEndUI::CFrontEndUI() xdc_saveUI = std::make_unique(ESaveContext::FrontEnd, g_GameState->GetCardSerial()); m->ResetGameState(); - g_GameState->SetCurrentWorldId(g_DefaultWorldTag.id); + g_GameState->SetCurrentWorldId(g_ResFactory->TranslateOriginalToNew(g_DefaultWorldTag.id)); + g_GameState->GameOptions().ResetToDefaults(); + g_GameState->WriteBackupBuf(); for (int i=0 ; CDvdFile::FileExists(GetAttractMovieFileName(i).c_str()) ; ++i) ++xc0_attractCount; diff --git a/Runtime/MP1/CMemoryCardDriver.cpp b/Runtime/MP1/CMemoryCardDriver.cpp index bd733f5f7..edd042f36 100644 --- a/Runtime/MP1/CMemoryCardDriver.cpp +++ b/Runtime/MP1/CMemoryCardDriver.cpp @@ -135,6 +135,7 @@ void CMemoryCardDriver::SGameFileSlot::InitializeFromGameState() { CBitStreamWriter w(x0_saveBuffer, 940); g_GameState->PutTo(w); + w.Flush(); x944_fileInfo = CGameState::LoadGameFileState(x0_saveBuffer); } diff --git a/Runtime/MP1/MP1.cpp b/Runtime/MP1/MP1.cpp index 6d368864f..53d53f700 100644 --- a/Runtime/MP1/MP1.cpp +++ b/Runtime/MP1/MP1.cpp @@ -46,6 +46,7 @@ CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, boo::IAudioVoi CAudioSys::SetDefaultVolumeScale(0x75); CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale()); CStreamAudioManager::Initialize(); + CStreamAudioManager::SetMusicVolume(0x7f); m->ResetGameState(); //std::shared_ptr splash = std::make_shared(CSplashScreen::ESplashScreen::Nintendo); @@ -276,6 +277,16 @@ bool CMain::Proc() x164_archSupport->Update(); CSfxManager::Update(1.f / 60.f); CStreamAudioManager::Update(1.f / 60.f); + if (x164_archSupport->GetIOWinManager().IsEmpty() || CheckReset()) + { + CStreamAudioManager::StopAll(); + /* + x164_archSupport.reset(); + g_archSupport = x164_archSupport.get(); + x164_archSupport->PreloadAudio(); + */ + x160_24_finished = true; + } return x160_24_finished; } diff --git a/Runtime/MP1/MP1.hpp b/Runtime/MP1/MP1.hpp index 6082aaa42..2702bb1dd 100644 --- a/Runtime/MP1/MP1.hpp +++ b/Runtime/MP1/MP1.hpp @@ -172,6 +172,8 @@ public: m_rectIsDirty = false; return m_windowRect; } + + CIOWinManager& GetIOWinManager() { return x58_ioWinManager; } }; #if MP1_USE_BOO @@ -261,7 +263,10 @@ public: if (!memSys) memSys.reset(new CMemoryCardSys()); if (memSys->InitializePump()) + { g_MemoryCardSys = memSys.get(); + g_GameState->InitializeMemoryStates(); + } } } diff --git a/amuse b/amuse index 2e7345f11..aff888059 160000 --- a/amuse +++ b/amuse @@ -1 +1 @@ -Subproject commit 2e7345f11d73219d77d345f3c7a039ab68be0e57 +Subproject commit aff8880595b8a30130695f8a09428347d1f75939 diff --git a/nod b/nod index e86971c9e..dc474ad15 160000 --- a/nod +++ b/nod @@ -1 +1 @@ -Subproject commit e86971c9e082b58bb04ee794a106874b3ceae1c7 +Subproject commit dc474ad1560e93f95d99d7577703387a859d7d26