mirror of https://github.com/AxioDL/metaforce.git
CPlayerState imps
This commit is contained in:
parent
6301af3133
commit
dc24a864fd
|
@ -94,6 +94,7 @@ include_directories(${ATHENA_INCLUDE_DIR} ${LOGVISOR_INCLUDE_DIR} ${HECL_INCLUDE
|
||||||
add_subdirectory(DataSpec)
|
add_subdirectory(DataSpec)
|
||||||
add_subdirectory(Editor)
|
add_subdirectory(Editor)
|
||||||
add_subdirectory(Runtime)
|
add_subdirectory(Runtime)
|
||||||
|
add_subdirectory(mpcksum)
|
||||||
|
|
||||||
unset(GIT_EXECUTABLE CACHE)
|
unset(GIT_EXECUTABLE CACHE)
|
||||||
find_package(Git)
|
find_package(Git)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "CPlayerState.hpp"
|
#include "CPlayerState.hpp"
|
||||||
#include "IOStreams.hpp"
|
#include "IOStreams.hpp"
|
||||||
|
#include "zeus/Math.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -9,60 +10,66 @@ namespace urde
|
||||||
* a proper RE is still required!
|
* a proper RE is still required!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const u32 CPlayerState::PowerUpMaxes[41] =
|
const u32 CPlayerState::PowerUpMaxValues[41] =
|
||||||
{ 1, 1, 1, 1, 250, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
{ 1, 1, 1, 1, 250, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 14, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
1, 1, 1, 14, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* PowerUpNames[41]=
|
const char* PowerUpNames[41]=
|
||||||
{
|
{
|
||||||
"Unknown",
|
"Power Beam",
|
||||||
"Unknown",
|
"Ice Beam",
|
||||||
"Unknown",
|
"Wave Beam",
|
||||||
"Unknown",
|
"Plasma Beam",
|
||||||
"Missiles",
|
"Missiles",
|
||||||
"Unknown",
|
"Scan Visor",
|
||||||
"Unknown",
|
"Morph Ball Bombs",
|
||||||
"Power Bombs",
|
"Power Bombs",
|
||||||
"Unknown",
|
"Flamethrower",
|
||||||
"Unknown",
|
"Thermal Visor",
|
||||||
"Unknown",
|
"Charge Beam",
|
||||||
"Unknown",
|
"Super Missile",
|
||||||
"Unknown",
|
"GrappleBeam",
|
||||||
"Unknown",
|
"X-Ray Visor",
|
||||||
"Unknown",
|
"Ice Spreader",
|
||||||
"Unknown",
|
"Space Jump Boots",
|
||||||
"Unknown",
|
"Morph Ball",
|
||||||
"Unknown",
|
"Combat Visor",
|
||||||
"Unknown",
|
"Boost Ball",
|
||||||
"Unknown",
|
"Spider Ball",
|
||||||
"Unknown",
|
"Power Suit",
|
||||||
"Unknown",
|
"Gravity Suit",
|
||||||
"Unknown",
|
"Varia Suit",
|
||||||
"Unknown",
|
"Phazon Suit",
|
||||||
"Energy Tanks",
|
"Energy Tanks",
|
||||||
"Unknown",
|
"Unknown Item 1",
|
||||||
"Unknown",
|
"Health Refill",
|
||||||
"Unknown",
|
"Unknown Item 2",
|
||||||
"Unknown",
|
"Wavebuster",
|
||||||
"Unknown",
|
"Artifact of Truth",
|
||||||
"Unknown",
|
"Artifact of Strength",
|
||||||
"Unknown",
|
"Artifact of Elder",
|
||||||
"Unknown",
|
"Artifact of Wild",
|
||||||
"Unknown",
|
"Artifact of Lifegiver",
|
||||||
"Unknown",
|
"Artifact of Warrior",
|
||||||
"Unknown",
|
"Artifact of Chozo",
|
||||||
"Unknown",
|
"Artifact of Nature",
|
||||||
"Unknown",
|
"Artifact of Sun",
|
||||||
"Unknown",
|
"Artifact of World",
|
||||||
"Unknown",
|
"Artifact of Spirit",
|
||||||
"Unknown",
|
"Artifact of Newborn",
|
||||||
};
|
};
|
||||||
|
|
||||||
CPlayerState::CPlayerState(CBitStreamReader& in)
|
CPlayerState::CPlayerState(CBitStreamReader& in)
|
||||||
: x188_staticIntf(5)
|
: x188_staticIntf(5)
|
||||||
{
|
{
|
||||||
x0_24_ = true;
|
x0_24_ = true;
|
||||||
|
u32 bitCount = 0;
|
||||||
|
std::for_each(std::cbegin(CPlayerState::PowerUpMaxValues), std::cend(CPlayerState::PowerUpMaxValues), [&bitCount](const u32& max){
|
||||||
|
bitCount += CBitStreamReader::GetBitCount(max);
|
||||||
|
});
|
||||||
|
|
||||||
|
#if 1
|
||||||
in.readUint32Big();
|
in.readUint32Big();
|
||||||
in.readBool();
|
in.readBool();
|
||||||
in.readBool();
|
in.readBool();
|
||||||
|
@ -72,87 +79,351 @@ CPlayerState::CPlayerState(CBitStreamReader& in)
|
||||||
in.readBytesToBuf(data, 0xAE);
|
in.readBytesToBuf(data, 0xAE);
|
||||||
for (u32 k = 0; k < 3; k++)
|
for (u32 k = 0; k < 3; k++)
|
||||||
{
|
{
|
||||||
printf("Game %i\n", k+1);
|
|
||||||
atInt8 save[0x3AC];
|
atInt8 save[0x3AC];
|
||||||
in.readBytesToBuf(save, 0x3AC);
|
in.readBytesToBuf(save, 0x3AC);
|
||||||
{
|
{
|
||||||
CBitStreamReader stream(save, 0x3AC);
|
CBitStreamReader stream(save, 0x1000);
|
||||||
std::string filename = athena::utility::sprintf("Game%i.dat", k + 1);
|
std::string filename = athena::utility::sprintf("Game%i.dat", k + 1);
|
||||||
|
std::string logFilename = athena::utility::sprintf("Game%i.txt", k + 1);
|
||||||
|
FILE * f = fopen(logFilename.c_str(), "w");
|
||||||
CBitStreamWriter w{filename};
|
CBitStreamWriter w{filename};
|
||||||
|
|
||||||
printf("Game State\n");
|
fprintf(f, "Game State\n");
|
||||||
for (u32 i = 0; i < 0x80; i++)
|
for (u32 i = 0; i < 0x80; i++)
|
||||||
{
|
{
|
||||||
u32 tmp = stream.ReadEncoded(8);
|
u32 tmp = stream.ReadEncoded(8);
|
||||||
printf("%i\n", tmp);
|
if (!(i % 16))
|
||||||
|
fprintf(f, "\n");
|
||||||
|
fprintf(f, "%.2i ", tmp);
|
||||||
w.WriteEncoded(tmp, 8);
|
w.WriteEncoded(tmp, 8);
|
||||||
}
|
}
|
||||||
|
fprintf(f, "\n\n");
|
||||||
|
|
||||||
s32 tmp = stream.ReadEncoded(32);
|
s32 tmp = stream.ReadEncoded(32);
|
||||||
w.WriteEncoded(tmp, 0x20);
|
w.WriteEncoded(tmp, 0x20);
|
||||||
printf("%i\n", tmp);
|
fprintf(f, "%i\n", tmp);
|
||||||
tmp = stream.ReadEncoded(1);
|
tmp = stream.ReadEncoded(1);
|
||||||
w.WriteEncoded(tmp, 1);
|
w.WriteEncoded(tmp, 1);
|
||||||
printf("%i\n", tmp);
|
fprintf(f, "%i\n", tmp);
|
||||||
tmp = stream.ReadEncoded(1);
|
tmp = stream.ReadEncoded(1);
|
||||||
w.WriteEncoded(tmp, 1);
|
w.WriteEncoded(tmp, 1);
|
||||||
printf("%i\n", tmp);
|
fprintf(f, "%i\n", tmp);
|
||||||
tmp = stream.ReadEncoded(32);
|
tmp = stream.ReadEncoded(32);
|
||||||
w.WriteEncoded(tmp, 0x20);
|
w.WriteEncoded(tmp, 0x20);
|
||||||
printf("%f\n", *reinterpret_cast<float*>(&tmp));
|
fprintf(f, "%f\n", *reinterpret_cast<float*>(&tmp));
|
||||||
tmp = stream.ReadEncoded(32);
|
tmp = stream.ReadEncoded(32);
|
||||||
w.WriteEncoded(tmp, 0x20);
|
w.WriteEncoded(tmp, 0x20);
|
||||||
printf("%f\n", *reinterpret_cast<float*>(&tmp));
|
fprintf(f, "%f\n", *reinterpret_cast<float*>(&tmp));
|
||||||
tmp = stream.ReadEncoded(32);
|
tmp = stream.ReadEncoded(32);
|
||||||
printf("%x\n", tmp);
|
fprintf(f, "%x\n", tmp);
|
||||||
w.WriteEncoded(tmp, 0x20);
|
w.WriteEncoded(tmp, 0x20);
|
||||||
|
|
||||||
printf("PlayerState\n");
|
fprintf(f, "PlayerState\n");
|
||||||
x4_ = stream.ReadEncoded(0x20);
|
x4_ = stream.ReadEncoded(0x20);
|
||||||
w.WriteEncoded(x4_, 0x20);
|
w.WriteEncoded(x4_, 0x20);
|
||||||
printf("%x\n", tmp);
|
fprintf(f, "%x\n", x4_);
|
||||||
tmp = stream.ReadEncoded(0x20);
|
tmp = stream.ReadEncoded(0x20);
|
||||||
printf("Base health %f\n", *reinterpret_cast<float*>(&tmp));
|
fprintf(f, "Base health %f\n", *reinterpret_cast<float*>(&tmp));
|
||||||
xc_baseHealth = *reinterpret_cast<float*>(&tmp);
|
xc_currentHealth = *reinterpret_cast<float*>(&tmp);
|
||||||
w.WriteEncoded(tmp, 0x20);
|
w.WriteEncoded(tmp, 0x20);
|
||||||
x8_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(5));
|
x8_currentBeam = stream.ReadEncoded(CBitStreamReader::GetBitCount(5));
|
||||||
printf("%i\n", x8_);
|
fprintf(f, "%i\n", x8_currentBeam);
|
||||||
w.WriteEncoded(x8_, CBitStreamReader::GetBitCount(5));
|
w.WriteEncoded(x8_currentBeam, CBitStreamReader::GetBitCount(5));
|
||||||
x20_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(4));
|
x20_currentSuit = EPlayerSuit(stream.ReadEncoded(CBitStreamReader::GetBitCount(4)));
|
||||||
printf("%i\n", x20_);
|
fprintf(f, "%i\n", x20_currentSuit);
|
||||||
w.WriteEncoded(x20_, CBitStreamReader::GetBitCount(4));
|
w.WriteEncoded(u32(x20_currentSuit), CBitStreamReader::GetBitCount(4));
|
||||||
x24_powerups.resize(41);
|
x24_powerups.resize(41);
|
||||||
printf("Powerups\n");
|
fprintf(f, "Powerups\n");
|
||||||
for (u32 i = 0; i < x24_powerups.size(); ++i)
|
for (u32 i = 0; i < x24_powerups.size(); ++i)
|
||||||
{
|
{
|
||||||
if (PowerUpMaxes[i] == 0)
|
if (PowerUpMaxValues[i] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
u32 a = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxes[i]));
|
u32 a = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i]));
|
||||||
u32 b = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxes[i]));
|
u32 b = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i]));
|
||||||
w.WriteEncoded(a, CBitStreamReader::GetBitCount(PowerUpMaxes[i]));
|
w.WriteEncoded(a, CBitStreamReader::GetBitCount(PowerUpMaxValues[i]));
|
||||||
w.WriteEncoded(b, CBitStreamReader::GetBitCount(PowerUpMaxes[i]));
|
w.WriteEncoded(b, CBitStreamReader::GetBitCount(PowerUpMaxValues[i]));
|
||||||
x24_powerups[i] = CPowerUp(a, b);
|
x24_powerups[i] = CPowerUp(a, b);
|
||||||
printf("%2i(%15s): a=%i b=%i\n", i, PowerUpNames[i], a, b);
|
fprintf(f, "%2i(%21s): cur=%3i max=%3i\n", i, PowerUpNames[i], a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < 0x304 * 8; i++)
|
for (u32 i = 0; i < 832; i++)
|
||||||
{
|
{
|
||||||
u32 tmp = stream.ReadEncoded(1);
|
u32 tmp = stream.ReadEncoded(1);
|
||||||
printf("%i\n", tmp);
|
if (!(i % 32))
|
||||||
|
fprintf(f, "\n");
|
||||||
|
|
||||||
|
fprintf(f, "%i ", tmp);
|
||||||
w.WriteEncoded(tmp, 1);
|
w.WriteEncoded(tmp, 1);
|
||||||
}
|
}
|
||||||
|
fprintf(f, "\n\n");
|
||||||
|
|
||||||
tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100));
|
tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100));
|
||||||
printf("%i\n", tmp);
|
|
||||||
w.WriteEncoded(tmp, CBitStreamReader::GetBitCount(0x100));
|
w.WriteEncoded(tmp, CBitStreamReader::GetBitCount(0x100));
|
||||||
|
fprintf(f, "%i\n", tmp);
|
||||||
tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100));
|
tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100));
|
||||||
printf("%i\n", tmp);
|
|
||||||
w.WriteEncoded(tmp, CBitStreamReader::GetBitCount(0x100));
|
w.WriteEncoded(tmp, CBitStreamReader::GetBitCount(0x100));
|
||||||
|
fprintf(f, "%i\n", tmp);
|
||||||
|
|
||||||
|
fprintf(f, "Final Offset %.8llx\n", stream.position());
|
||||||
|
fprintf(f, "Completion: %.2i%%\n", CalculateItemCollectionRate());
|
||||||
w.save();
|
w.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
float CPlayerState::GetBeamSwitchTime() const
|
||||||
|
{
|
||||||
|
static const float switchTimes[4] {
|
||||||
|
0.2, 0.1, 0.2, 0.2
|
||||||
|
};
|
||||||
|
|
||||||
|
return switchTime[u32(x8_currentBeam)];
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CPlayerState::CalculateItemCollectionRate() const
|
||||||
|
{
|
||||||
|
u32 total = GetItemCapacity(EItemType::PowerBombs);
|
||||||
|
|
||||||
|
if (total >= 4)
|
||||||
|
total -= 3;
|
||||||
|
total += GetItemCapacity(EItemType::WaveBeam);
|
||||||
|
total += GetItemCapacity(EItemType::IceBeam);
|
||||||
|
total += GetItemCapacity(EItemType::PlasmaBeam);
|
||||||
|
total += GetItemCapacity(EItemType::Missiles) / 5;
|
||||||
|
total += GetItemCapacity(EItemType::MorphBallBombs);
|
||||||
|
total += GetItemCapacity(EItemType::Flamethrower);
|
||||||
|
total += GetItemCapacity(EItemType::ThermalVisor);
|
||||||
|
total += GetItemCapacity(EItemType::ChargeBeam);
|
||||||
|
total += GetItemCapacity(EItemType::SuperMissile);
|
||||||
|
total += GetItemCapacity(EItemType::GrappleBeam);
|
||||||
|
total += GetItemCapacity(EItemType::XRayVisor);
|
||||||
|
total += GetItemCapacity(EItemType::IceSpreader);
|
||||||
|
total += GetItemCapacity(EItemType::SpaceJumpBoots);
|
||||||
|
total += GetItemCapacity(EItemType::MorphBall);
|
||||||
|
total += GetItemCapacity(EItemType::BoostBall);
|
||||||
|
total += GetItemCapacity(EItemType::SpiderBall);
|
||||||
|
total += GetItemCapacity(EItemType::GravitySuit);
|
||||||
|
total += GetItemCapacity(EItemType::VariaSuit);
|
||||||
|
total += GetItemCapacity(EItemType::EnergyTanks);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfTruth);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfStrength);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfElder);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfWild);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfLifegiver);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfWarrior);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfChozo);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfNature);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfSun);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfWorld);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfSpirit);
|
||||||
|
total += GetItemCapacity(EItemType::ArtifactOfNewborn);
|
||||||
|
return total + GetItemCapacity(EItemType::Wavebuster);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPlayerState::EPlayerSuit CPlayerState::GetCurrentSuit() const
|
||||||
|
{
|
||||||
|
if (GetFusion())
|
||||||
|
return EPlayerSuit::FusionPower;
|
||||||
|
|
||||||
|
return x20_currentSuit;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPlayerState::CanVisorSeeFog(const CStateManager& stateMgr) const
|
||||||
|
{
|
||||||
|
u32 activeVisor = u32(GetActiveVisor(stateMgr));
|
||||||
|
if (activeVisor == 0 || activeVisor == 2)
|
||||||
|
return true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPlayerState::EPlayerVisor CPlayerState::GetActiveVisor(const CStateManager& stateMgr) const
|
||||||
|
{
|
||||||
|
/* TODO: We need CGameCamera, and gang in order to enable this */
|
||||||
|
#if 0
|
||||||
|
CFirstPersionCamera* cam = dynamic_cast<CFirstPersonCamera*>(stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr));
|
||||||
|
if (!cam)
|
||||||
|
return EVisorType::Zero;
|
||||||
|
#endif
|
||||||
|
return x14_currentVisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlayerState::UpdateStaticInterference(CStateManager& stateMgr, const float& dt)
|
||||||
|
{
|
||||||
|
x188_staticIntf.Update(stateMgr, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlayerState::NewScanTime(u32 time)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPlayerState::GetIsVisorTransitioning() const
|
||||||
|
{
|
||||||
|
if (x14_currentVisor != x18_transitioningVisor || x1c_visorTransitionFactor < 0.2f)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CPlayerState::GetVisorTransitionFactor() const
|
||||||
|
{
|
||||||
|
return x1c_visorTransitionFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlayerState::UpdateVisorTransition(float dt)
|
||||||
|
{
|
||||||
|
if (!GetIsVisorTransitioning())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (x14_currentVisor == x18_transitioningVisor)
|
||||||
|
{
|
||||||
|
x1c_visorTransitionFactor += dt;
|
||||||
|
if (x1c_visorTransitionFactor > 0.2)
|
||||||
|
x1c_visorTransitionFactor = 0.2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x1c_visorTransitionFactor -= dt;
|
||||||
|
if (x1c_visorTransitionFactor < 0.f)
|
||||||
|
{
|
||||||
|
x14_currentVisor = x18_transitioningVisor;
|
||||||
|
x1c_visorTransitionFactor = fabs(x1c_visorTransitionFactor);
|
||||||
|
if (x1c_visorTransitionFactor < 0.19f)
|
||||||
|
x1c_visorTransitionFactor = 0.19f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPlayerState::StartVisorTransition(CPlayerState::EPlayerVisor visor)
|
||||||
|
{
|
||||||
|
x18_transitioningVisor = visor;
|
||||||
|
return x14_currentVisor == x18_transitioningVisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlayerState::ResetVisor()
|
||||||
|
{
|
||||||
|
x18_transitioningVisor = x14_currentVisor = EPlayerVisor::Combat;
|
||||||
|
x1c_visorTransitionFactor = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPlayerState::ItemEnabled(CPlayerState::EItemType type)
|
||||||
|
{
|
||||||
|
if (HasPowerUp(type))
|
||||||
|
return x24_powerups[u32(type)].x4_capacity != 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPlayerState::HasPowerUp(CPlayerState::EItemType type)
|
||||||
|
{
|
||||||
|
if (type < EItemType::Max)
|
||||||
|
return x24_powerups[u32(type)].x4_capacity != 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CPlayerState::GetItemCapacity(CPlayerState::EItemType type) const
|
||||||
|
{
|
||||||
|
if (type < EItemType::Max)
|
||||||
|
return x24_powerups[u32(type)].x4_capacity;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CPlayerState::GetItemAmount(CPlayerState::EItemType type) const
|
||||||
|
{
|
||||||
|
if (type != EItemType::ThermalVisor && type < EItemType::Max)
|
||||||
|
return x24_powerups[u32(type)].x0_amount;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlayerState::DecrPickup(CPlayerState::EItemType type, s32 amount)
|
||||||
|
{
|
||||||
|
if (type >= EItemType::Max)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((type == EItemType::Missiles || type >= EItemType::PowerBombs) && type < EItemType::ThermalVisor)
|
||||||
|
x24_powerups[u32(type)].x0_amount -= amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlayerState::IncrPickup(EItemType type, s32 amount)
|
||||||
|
{
|
||||||
|
if (type >= EItemType::Max)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (amount < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case EItemType::Missiles:
|
||||||
|
case EItemType::PowerBombs:
|
||||||
|
case EItemType::ChargeBeam:
|
||||||
|
case EItemType::SpaceJumpBoots:
|
||||||
|
case EItemType::EnergyTanks:
|
||||||
|
case EItemType::ArtifactOfTruth:
|
||||||
|
case EItemType::ArtifactOfStrength:
|
||||||
|
case EItemType::ArtifactOfElder:
|
||||||
|
case EItemType::ArtifactOfWild:
|
||||||
|
case EItemType::ArtifactOfLifegiver:
|
||||||
|
case EItemType::ArtifactOfWarrior:
|
||||||
|
case EItemType::ArtifactOfChozo:
|
||||||
|
case EItemType::ArtifactOfNature:
|
||||||
|
case EItemType::ArtifactOfSun:
|
||||||
|
case EItemType::ArtifactOfWorld:
|
||||||
|
case EItemType::ArtifactOfSpirit:
|
||||||
|
case EItemType::ArtifactOfNewborn:
|
||||||
|
{
|
||||||
|
CPowerUp& pup = x24_powerups[u32(type)];
|
||||||
|
pup.x0_amount = std::min(pup.x0_amount + amount, pup.x4_capacity);
|
||||||
|
if (type == EItemType::EnergyTanks)
|
||||||
|
IncrPickup(EItemType::HealthRefill, 9999);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EItemType::HealthRefill:
|
||||||
|
{
|
||||||
|
float health = CalculateHealth(amount);
|
||||||
|
xc_currentHealth = std::min(health, xc_currentHealth + amount);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlayerState::ResetAndIncrPickUp(CPlayerState::EItemType type, s32 amount)
|
||||||
|
{
|
||||||
|
x24_powerups[u32(type)].x0_amount = 0;
|
||||||
|
IncrPickup(type, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CPlayerState::CalculateHealth(u32 health)
|
||||||
|
{
|
||||||
|
return (GetBaseHealthCapacity() + (health * GetEnergyTankCapacity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlayerState::InitializePowerUp(CPlayerState::EItemType type, u32 capacity)
|
||||||
|
{
|
||||||
|
if (type >= EItemType::Max)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CPowerUp& pup = x24_powerups[(u32)type];
|
||||||
|
pup.x0_amount = zeus::clamp(u32(0), pup.x4_capacity + capacity, PowerUpMaxValues[u32(type)]);
|
||||||
|
pup.x0_amount = std::min(pup.x0_amount, pup.x4_capacity);
|
||||||
|
if (type >= EItemType::PowerSuit && type <= EItemType::PhazonSuit)
|
||||||
|
{
|
||||||
|
if (HasPowerUp(EItemType::PhazonSuit))
|
||||||
|
x20_currentSuit = EPlayerSuit::Phazon;
|
||||||
|
else if (HasPowerUp(EItemType::GravitySuit))
|
||||||
|
x20_currentSuit = EPlayerSuit::Gravity;
|
||||||
|
else if (HasPowerUp(EItemType::VariaSuit))
|
||||||
|
x20_currentSuit = EPlayerSuit::Varia;
|
||||||
|
else
|
||||||
|
x20_currentSuit = EPlayerSuit::Power;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlayerState::ReInitalizePowerUp(CPlayerState::EItemType type, u32 capacity)
|
||||||
|
{
|
||||||
|
x24_powerups[u32(type)].x4_capacity = 0;
|
||||||
|
InitializePowerUp(type, capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,33 +12,137 @@ namespace urde
|
||||||
|
|
||||||
class CPlayerState
|
class CPlayerState
|
||||||
{
|
{
|
||||||
static const u32 PowerUpMaxes[41];
|
public:
|
||||||
class CPowerUp
|
enum class EItemType : u32
|
||||||
{
|
{
|
||||||
int x0_a = 0;
|
PowerBeam,
|
||||||
int x4_b = 0;
|
IceBeam,
|
||||||
public:
|
WaveBeam,
|
||||||
|
PlasmaBeam,
|
||||||
|
Missiles,
|
||||||
|
ScanVisor,
|
||||||
|
MorphBallBombs,
|
||||||
|
PowerBombs,
|
||||||
|
Flamethrower,
|
||||||
|
ThermalVisor,
|
||||||
|
ChargeBeam,
|
||||||
|
SuperMissile,
|
||||||
|
GrappleBeam,
|
||||||
|
XRayVisor,
|
||||||
|
IceSpreader,
|
||||||
|
SpaceJumpBoots,
|
||||||
|
MorphBall,
|
||||||
|
CombatVisor,
|
||||||
|
BoostBall,
|
||||||
|
SpiderBall,
|
||||||
|
PowerSuit,
|
||||||
|
GravitySuit,
|
||||||
|
VariaSuit,
|
||||||
|
PhazonSuit,
|
||||||
|
EnergyTanks,
|
||||||
|
UnknownItem1,
|
||||||
|
HealthRefill,
|
||||||
|
UnknownItem2,
|
||||||
|
Wavebuster,
|
||||||
|
ArtifactOfTruth,
|
||||||
|
ArtifactOfStrength,
|
||||||
|
ArtifactOfElder,
|
||||||
|
ArtifactOfWild,
|
||||||
|
ArtifactOfLifegiver,
|
||||||
|
ArtifactOfWarrior,
|
||||||
|
ArtifactOfChozo,
|
||||||
|
ArtifactOfNature,
|
||||||
|
ArtifactOfSun,
|
||||||
|
ArtifactOfWorld,
|
||||||
|
ArtifactOfSpirit,
|
||||||
|
ArtifactOfNewborn,
|
||||||
|
|
||||||
|
/* This must remain at the end of the list */
|
||||||
|
Max
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class EPlayerVisor : u32
|
||||||
|
{
|
||||||
|
Combat,
|
||||||
|
XRay,
|
||||||
|
Scan,
|
||||||
|
Thermal,
|
||||||
|
|
||||||
|
/* This must remain at the end of the list */
|
||||||
|
Max
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class EPlayerSuit : u32
|
||||||
|
{
|
||||||
|
Power,
|
||||||
|
Gravity,
|
||||||
|
Varia,
|
||||||
|
Phazon,
|
||||||
|
FusionPower,
|
||||||
|
FusionGravity,
|
||||||
|
FusionVaria,
|
||||||
|
FusionPhazon
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static const u32 PowerUpMaxValues[41];
|
||||||
|
struct CPowerUp
|
||||||
|
{
|
||||||
|
int x0_amount = 0;
|
||||||
|
int x4_capacity = 0;
|
||||||
CPowerUp() {}
|
CPowerUp() {}
|
||||||
CPowerUp(int a, int b) : x0_a(a), x4_b(b) {}
|
CPowerUp(int amount, int capacity) : x0_amount(amount), x4_capacity(capacity) {}
|
||||||
};
|
};
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct { bool x0_24_ : 1; bool x0_25_ : 1; bool x0_26_; };
|
struct { bool x0_24_ : 1; bool x0_25_ : 1; bool x0_26_fusion; };
|
||||||
u32 dummy = 0;
|
u32 dummy = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 x4_ = 0;
|
u32 x4_ = 0;
|
||||||
u32 x8_ = 0;
|
u32 x8_currentBeam = 0;
|
||||||
float xc_baseHealth = 99.f;
|
float xc_currentHealth = 99.f;
|
||||||
float x10_ = 50.f;
|
float x10_ = 50.f;
|
||||||
u32 x14_ = 0;
|
EPlayerVisor x14_currentVisor = EPlayerVisor::Combat;
|
||||||
u32 x18_ = x14_;
|
EPlayerVisor x18_transitioningVisor = x14_currentVisor;
|
||||||
float x1c_ = 0.2f;
|
float x1c_visorTransitionFactor = 0.2f;
|
||||||
u32 x20_ = 0;
|
EPlayerSuit x20_currentSuit = EPlayerSuit::Power;
|
||||||
rstl::reserved_vector<CPowerUp, 41> x24_powerups;
|
rstl::reserved_vector<CPowerUp, 41> x24_powerups;
|
||||||
|
|
||||||
CStaticInterference x188_staticIntf;
|
CStaticInterference x188_staticIntf;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
u32 CalculateItemCollectionRate() const;
|
||||||
|
|
||||||
|
u32 GetBaseHealthCapacityInt32() { return 99; }
|
||||||
|
void SetFusion(bool val) { x0_26_fusion = val; }
|
||||||
|
bool GetFusion() const { return x0_26_fusion; }
|
||||||
|
EPlayerSuit GetCurrentSuit() const;
|
||||||
|
bool CanVisorSeeFog(const CStateManager& stateMgr) const;
|
||||||
|
EPlayerVisor GetActiveVisor(const CStateManager& stateMgr) const;
|
||||||
|
void UpdateStaticInterference(CStateManager& stateMgr, const float& dt);
|
||||||
|
void IncreaseScanTime(u32 time, float val);
|
||||||
|
void NewScanTime(u32 time);
|
||||||
|
bool GetIsVisorTransitioning() const;
|
||||||
|
float GetVisorTransitionFactor() const;
|
||||||
|
void UpdateVisorTransition(float dt);
|
||||||
|
bool StartVisorTransition(EPlayerVisor visor);
|
||||||
|
void ResetVisor();
|
||||||
|
bool ItemEnabled(EItemType type);
|
||||||
|
void DisableItem(EItemType type);
|
||||||
|
void EnableItem(EItemType type);
|
||||||
|
bool HasPowerUp(EItemType type);
|
||||||
|
u32 GetItemCapacity(EItemType type) const;
|
||||||
|
u32 GetItemAmount(EItemType type) const;
|
||||||
|
void DecrPickup(EItemType type, s32 amount);
|
||||||
|
void IncrPickup(EItemType type, s32 amount);
|
||||||
|
void ResetAndIncrPickUp(EItemType type, s32 amount);
|
||||||
|
float GetEnergyTankCapacity() const { return 100.f; }
|
||||||
|
float GetBaseHealthCapacity() const { return 99.f; }
|
||||||
|
float CalculateHealth(u32 health);
|
||||||
|
void ReInitalizePowerUp(EItemType type, u32 capacity);
|
||||||
|
void InitializePowerUp(EItemType type, u32 capacity);
|
||||||
CPlayerState() : x188_staticIntf(5) { x0_24_ = true; }
|
CPlayerState() : x188_staticIntf(5) { x0_24_ = true; }
|
||||||
CPlayerState(CBitStreamReader& stream);
|
CPlayerState(CBitStreamReader& stream);
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,12 +33,7 @@ CRasterFont::CRasterFont(urde::CInputStream& in, urde::IObjectStore& store)
|
||||||
u32 txtrId = in.readUint32Big();
|
u32 txtrId = in.readUint32Big();
|
||||||
x30_fontInfo = CFontInfo(tmp1, tmp2, tmp3, tmp4, name.c_str());
|
x30_fontInfo = CFontInfo(tmp1, tmp2, tmp3, tmp4, name.c_str());
|
||||||
x80_texture = store.GetObj({'TXTR', txtrId});
|
x80_texture = store.GetObj({'TXTR', txtrId});
|
||||||
EColorType mode = EColorType(in.readUint32Big());
|
x2c_mode = EColorType(in.readUint32Big());
|
||||||
/* TODO: Make an enum */
|
|
||||||
if (mode == EColorType::Outline)
|
|
||||||
x2c_mode = EColorType::Outline;
|
|
||||||
else if (mode == EColorType::Main)
|
|
||||||
x2c_mode = EColorType::Main;
|
|
||||||
|
|
||||||
u32 glyphCount = in.readUint32Big();
|
u32 glyphCount = in.readUint32Big();
|
||||||
xc_glyphs.reserve(glyphCount);
|
xc_glyphs.reserve(glyphCount);
|
||||||
|
@ -75,13 +70,16 @@ CRasterFont::CRasterFont(urde::CInputStream& in, urde::IObjectStore& store)
|
||||||
s32 howMuch = in.readUint32Big();
|
s32 howMuch = in.readUint32Big();
|
||||||
x1c_kerning[i] = CKernPair(first, second, howMuch);
|
x1c_kerning[i] = CKernPair(first, second, howMuch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (magic == SBIG('FONT') && version <= 2)
|
||||||
|
x0_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRasterFont::SinglePassDrawString(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout,
|
void CRasterFont::SinglePassDrawString(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout,
|
||||||
CTextRenderBuffer* renderBuf,
|
CTextRenderBuffer* renderBuf,
|
||||||
const wchar_t* str, s32 length) const
|
const wchar_t* str, s32 length) const
|
||||||
{
|
{
|
||||||
if (!x0_)
|
if (!x0_initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const wchar_t* chr = str;
|
const wchar_t* chr = str;
|
||||||
|
@ -133,7 +131,7 @@ void CRasterFont::DrawSpace(const CDrawStringOptions& opts, int x, int y, int& x
|
||||||
|
|
||||||
void CRasterFont::DrawString(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout, CTextRenderBuffer* renderBuf, const wchar_t* str, int len) const
|
void CRasterFont::DrawString(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout, CTextRenderBuffer* renderBuf, const wchar_t* str, int len) const
|
||||||
{
|
{
|
||||||
if (!x0_)
|
if (!x0_initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (renderBuf)
|
if (renderBuf)
|
||||||
|
|
|
@ -89,16 +89,14 @@ public:
|
||||||
|
|
||||||
class CRasterFont
|
class CRasterFont
|
||||||
{
|
{
|
||||||
bool x0_ = false;
|
bool x0_initialized = false;
|
||||||
s32 x4_monoWidth = 16;
|
s32 x4_monoWidth = 16;
|
||||||
s32 x8_monoHeight = 16;
|
s32 x8_monoHeight = 16;
|
||||||
std::vector<std::pair<wchar_t, CGlyph>> xc_glyphs;
|
std::vector<std::pair<wchar_t, CGlyph>> xc_glyphs;
|
||||||
std::vector<CKernPair> x1c_kerning;
|
std::vector<CKernPair> x1c_kerning;
|
||||||
s32 x28_lineMargin = 0;
|
|
||||||
EColorType x2c_mode = EColorType::Main;
|
EColorType x2c_mode = EColorType::Main;
|
||||||
CFontInfo x30_fontInfo;
|
CFontInfo x30_fontInfo;
|
||||||
TLockedToken<CTexture> x80_texture;
|
TLockedToken<CTexture> x80_texture;
|
||||||
bool x88_ = false;
|
|
||||||
s32 x8c_baseline;
|
s32 x8c_baseline;
|
||||||
s32 x90_lineMargin = 0;
|
s32 x90_lineMargin = 0;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,9 @@ s32 CBitStreamReader::ReadEncoded(u32 bitCount)
|
||||||
|
|
||||||
baseVal = (baseVal & (x1c_val >> (32 - x20_bitOffset))) << diff;
|
baseVal = (baseVal & (x1c_val >> (32 - x20_bitOffset))) << diff;
|
||||||
x20_bitOffset = 0;
|
x20_bitOffset = 0;
|
||||||
readUBytesToBuf(&x1c_val, 4);
|
u32 bit = diff & 7;
|
||||||
|
u32 count = (diff >> 3) + ((-bit | bit) >> 31);
|
||||||
|
readUBytesToBuf(&x1c_val, count);
|
||||||
/* The game uses Big Endian, which doesn't work for us */
|
/* The game uses Big Endian, which doesn't work for us */
|
||||||
/* Little Endian sucks */
|
/* Little Endian sucks */
|
||||||
athena::utility::BigUint32(x1c_val);
|
athena::utility::BigUint32(x1c_val);
|
||||||
|
@ -41,7 +43,7 @@ s32 CBitStreamReader::ReadEncoded(u32 bitCount)
|
||||||
baseVal2 = (1 << diff) - 1;
|
baseVal2 = (1 << diff) - 1;
|
||||||
|
|
||||||
ret = baseVal | (baseVal2 & (x1c_val >> (32 - diff))) << x20_bitOffset;
|
ret = baseVal | (baseVal2 & (x1c_val >> (32 - diff))) << x20_bitOffset;
|
||||||
x20_bitOffset = (4 << 3) - diff;
|
x20_bitOffset = (count << 3) - diff;
|
||||||
x1c_val <<= diff;
|
x1c_val <<= diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +72,9 @@ void CBitStreamWriter::WriteEncoded(u32 val, u32 bitCount)
|
||||||
x18_bitOffset = 0;
|
x18_bitOffset = 0;
|
||||||
u32 tmp = x14_val;
|
u32 tmp = x14_val;
|
||||||
athena::utility::BigUint32(tmp);
|
athena::utility::BigUint32(tmp);
|
||||||
writeBytes(&tmp, 4);
|
u32 bit = (32 - x18_bitOffset) & 7;
|
||||||
|
u32 count = ((32 - x18_bitOffset) >> 3) + ((-bit | bit) >> 31);
|
||||||
|
writeBytes(&tmp, count);
|
||||||
|
|
||||||
u32 rem = 32 - diff;
|
u32 rem = 32 - diff;
|
||||||
baseVal = -1;
|
baseVal = -1;
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ./../Runtime)
|
||||||
|
|
||||||
|
add_executable(mpcksum
|
||||||
|
main.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(mpcksum
|
||||||
|
athena-core z lzo2)
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "athena/MemoryReader.hpp"
|
||||||
|
#include "athena/FileWriter.hpp"
|
||||||
|
#include "athena/Checksums.hpp"
|
||||||
|
|
||||||
|
#if __BYTE_ORDER__ == __BIG_ENDIAN
|
||||||
|
#define SBIG(q) q
|
||||||
|
#else
|
||||||
|
#define SBIG(q) ( ( (q) & 0x000000FF ) << 24 | ( (q) & 0x0000FF00 ) << 8 \
|
||||||
|
| ( (q) & 0x00FF0000 ) >> 8 | ( (q) & 0xFF000000 ) >> 24 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
printf("mpcksum <save> [output]\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
athena::io::MemoryCopyReader in(argv[1]);
|
||||||
|
std::unique_ptr<athena::io::FileWriter> out;
|
||||||
|
if (argc > 2)
|
||||||
|
out.reset(new athena::io::FileWriter(argv[2]));
|
||||||
|
else
|
||||||
|
out.reset(new athena::io::FileWriter(argv[1]));
|
||||||
|
|
||||||
|
atUint32 magic;
|
||||||
|
in.readUBytesToBuf(&magic, 4);
|
||||||
|
if (magic != SBIG('GM8E') && magic != SBIG('GM8P') && magic != SBIG('GM8J'))
|
||||||
|
{
|
||||||
|
printf("Unsupported file, MP .gci file expected\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in.length() != 8256)
|
||||||
|
{
|
||||||
|
printf("File too small expected 8,256 bytes got %llu", in.length());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
atUint8* data = in.data();
|
||||||
|
|
||||||
|
atUint32 newCkSum = athena::Checksums::crc32(data + 68, 8188, 0);
|
||||||
|
*(atUint32*)(data + 64) = SBIG(newCkSum);
|
||||||
|
out->writeBytes(data, 8256);
|
||||||
|
|
||||||
|
delete data;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue