mirror of https://github.com/AxioDL/metaforce.git
Merge branch 'master' of https://github.com/AxioDL/urde
This commit is contained in:
commit
41c66a437a
|
@ -94,6 +94,7 @@ include_directories(${ATHENA_INCLUDE_DIR} ${LOGVISOR_INCLUDE_DIR} ${HECL_INCLUDE
|
|||
add_subdirectory(DataSpec)
|
||||
add_subdirectory(Editor)
|
||||
add_subdirectory(Runtime)
|
||||
add_subdirectory(mpcksum)
|
||||
|
||||
unset(GIT_EXECUTABLE CACHE)
|
||||
find_package(Git)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "CPlayerState.hpp"
|
||||
#include "IOStreams.hpp"
|
||||
#include "zeus/Math.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
@ -9,60 +10,66 @@ namespace urde
|
|||
* 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, 14, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
||||
};
|
||||
|
||||
const char* PowerUpNames[41]=
|
||||
{
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Power Beam",
|
||||
"Ice Beam",
|
||||
"Wave Beam",
|
||||
"Plasma Beam",
|
||||
"Missiles",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Scan Visor",
|
||||
"Morph Ball Bombs",
|
||||
"Power Bombs",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Flamethrower",
|
||||
"Thermal Visor",
|
||||
"Charge Beam",
|
||||
"Super Missile",
|
||||
"GrappleBeam",
|
||||
"X-Ray Visor",
|
||||
"Ice Spreader",
|
||||
"Space Jump Boots",
|
||||
"Morph Ball",
|
||||
"Combat Visor",
|
||||
"Boost Ball",
|
||||
"Spider Ball",
|
||||
"Power Suit",
|
||||
"Gravity Suit",
|
||||
"Varia Suit",
|
||||
"Phazon Suit",
|
||||
"Energy Tanks",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown Item 1",
|
||||
"Health Refill",
|
||||
"Unknown Item 2",
|
||||
"Wavebuster",
|
||||
"Artifact of Truth",
|
||||
"Artifact of Strength",
|
||||
"Artifact of Elder",
|
||||
"Artifact of Wild",
|
||||
"Artifact of Lifegiver",
|
||||
"Artifact of Warrior",
|
||||
"Artifact of Chozo",
|
||||
"Artifact of Nature",
|
||||
"Artifact of Sun",
|
||||
"Artifact of World",
|
||||
"Artifact of Spirit",
|
||||
"Artifact of Newborn",
|
||||
};
|
||||
|
||||
CPlayerState::CPlayerState(CBitStreamReader& in)
|
||||
: x188_staticIntf(5)
|
||||
{
|
||||
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.readBool();
|
||||
in.readBool();
|
||||
|
@ -72,87 +79,351 @@ CPlayerState::CPlayerState(CBitStreamReader& in)
|
|||
in.readBytesToBuf(data, 0xAE);
|
||||
for (u32 k = 0; k < 3; k++)
|
||||
{
|
||||
printf("Game %i\n", k+1);
|
||||
atInt8 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 logFilename = athena::utility::sprintf("Game%i.txt", k + 1);
|
||||
FILE * f = fopen(logFilename.c_str(), "w");
|
||||
CBitStreamWriter w{filename};
|
||||
|
||||
printf("Game State\n");
|
||||
fprintf(f, "Game State\n");
|
||||
for (u32 i = 0; i < 0x80; i++)
|
||||
{
|
||||
u32 tmp = stream.ReadEncoded(8);
|
||||
printf("%i\n", tmp);
|
||||
if (!(i % 16))
|
||||
fprintf(f, "\n");
|
||||
fprintf(f, "%.2i ", tmp);
|
||||
w.WriteEncoded(tmp, 8);
|
||||
}
|
||||
fprintf(f, "\n\n");
|
||||
|
||||
s32 tmp = stream.ReadEncoded(32);
|
||||
w.WriteEncoded(tmp, 0x20);
|
||||
printf("%i\n", tmp);
|
||||
fprintf(f, "%i\n", tmp);
|
||||
tmp = stream.ReadEncoded(1);
|
||||
w.WriteEncoded(tmp, 1);
|
||||
printf("%i\n", tmp);
|
||||
fprintf(f, "%i\n", tmp);
|
||||
tmp = stream.ReadEncoded(1);
|
||||
w.WriteEncoded(tmp, 1);
|
||||
printf("%i\n", tmp);
|
||||
fprintf(f, "%i\n", tmp);
|
||||
tmp = stream.ReadEncoded(32);
|
||||
w.WriteEncoded(tmp, 0x20);
|
||||
printf("%f\n", *reinterpret_cast<float*>(&tmp));
|
||||
fprintf(f, "%f\n", *reinterpret_cast<float*>(&tmp));
|
||||
tmp = stream.ReadEncoded(32);
|
||||
w.WriteEncoded(tmp, 0x20);
|
||||
printf("%f\n", *reinterpret_cast<float*>(&tmp));
|
||||
fprintf(f, "%f\n", *reinterpret_cast<float*>(&tmp));
|
||||
tmp = stream.ReadEncoded(32);
|
||||
printf("%x\n", tmp);
|
||||
fprintf(f, "%x\n", tmp);
|
||||
w.WriteEncoded(tmp, 0x20);
|
||||
|
||||
printf("PlayerState\n");
|
||||
fprintf(f, "PlayerState\n");
|
||||
x4_ = stream.ReadEncoded(0x20);
|
||||
w.WriteEncoded(x4_, 0x20);
|
||||
printf("%x\n", tmp);
|
||||
fprintf(f, "%x\n", x4_);
|
||||
tmp = stream.ReadEncoded(0x20);
|
||||
printf("Base health %f\n", *reinterpret_cast<float*>(&tmp));
|
||||
xc_baseHealth = *reinterpret_cast<float*>(&tmp);
|
||||
fprintf(f, "Base health %f\n", *reinterpret_cast<float*>(&tmp));
|
||||
xc_currentHealth = *reinterpret_cast<float*>(&tmp);
|
||||
w.WriteEncoded(tmp, 0x20);
|
||||
x8_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(5));
|
||||
printf("%i\n", x8_);
|
||||
w.WriteEncoded(x8_, CBitStreamReader::GetBitCount(5));
|
||||
x20_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(4));
|
||||
printf("%i\n", x20_);
|
||||
w.WriteEncoded(x20_, CBitStreamReader::GetBitCount(4));
|
||||
x8_currentBeam = stream.ReadEncoded(CBitStreamReader::GetBitCount(5));
|
||||
fprintf(f, "%i\n", x8_currentBeam);
|
||||
w.WriteEncoded(x8_currentBeam, CBitStreamReader::GetBitCount(5));
|
||||
x20_currentSuit = EPlayerSuit(stream.ReadEncoded(CBitStreamReader::GetBitCount(4)));
|
||||
fprintf(f, "%i\n", x20_currentSuit);
|
||||
w.WriteEncoded(u32(x20_currentSuit), CBitStreamReader::GetBitCount(4));
|
||||
x24_powerups.resize(41);
|
||||
printf("Powerups\n");
|
||||
fprintf(f, "Powerups\n");
|
||||
for (u32 i = 0; i < x24_powerups.size(); ++i)
|
||||
{
|
||||
if (PowerUpMaxes[i] == 0)
|
||||
if (PowerUpMaxValues[i] == 0)
|
||||
continue;
|
||||
|
||||
u32 a = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxes[i]));
|
||||
u32 b = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxes[i]));
|
||||
w.WriteEncoded(a, CBitStreamReader::GetBitCount(PowerUpMaxes[i]));
|
||||
w.WriteEncoded(b, CBitStreamReader::GetBitCount(PowerUpMaxes[i]));
|
||||
u32 a = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i]));
|
||||
u32 b = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i]));
|
||||
w.WriteEncoded(a, CBitStreamReader::GetBitCount(PowerUpMaxValues[i]));
|
||||
w.WriteEncoded(b, CBitStreamReader::GetBitCount(PowerUpMaxValues[i]));
|
||||
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);
|
||||
printf("%i\n", tmp);
|
||||
if (!(i % 32))
|
||||
fprintf(f, "\n");
|
||||
|
||||
fprintf(f, "%i ", tmp);
|
||||
w.WriteEncoded(tmp, 1);
|
||||
}
|
||||
fprintf(f, "\n\n");
|
||||
|
||||
tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100));
|
||||
printf("%i\n", tmp);
|
||||
w.WriteEncoded(tmp, CBitStreamReader::GetBitCount(0x100));
|
||||
fprintf(f, "%i\n", tmp);
|
||||
tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100));
|
||||
printf("%i\n", tmp);
|
||||
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();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float CPlayerState::GetBeamSwitchTime() const
|
||||
{
|
||||
static const float switchTimes[4] {
|
||||
0.2, 0.1, 0.2, 0.2
|
||||
};
|
||||
|
||||
return switchTimes[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,138 @@ namespace urde
|
|||
|
||||
class CPlayerState
|
||||
{
|
||||
static const u32 PowerUpMaxes[41];
|
||||
class CPowerUp
|
||||
{
|
||||
int x0_a = 0;
|
||||
int x4_b = 0;
|
||||
public:
|
||||
enum class EItemType : u32
|
||||
{
|
||||
PowerBeam,
|
||||
IceBeam,
|
||||
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(int a, int b) : x0_a(a), x4_b(b) {}
|
||||
CPowerUp(int amount, int capacity) : x0_amount(amount), x4_capacity(capacity) {}
|
||||
};
|
||||
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 x4_ = 0;
|
||||
u32 x8_ = 0;
|
||||
float xc_baseHealth = 99.f;
|
||||
u32 x8_currentBeam = 0;
|
||||
float xc_currentHealth = 99.f;
|
||||
float x10_ = 50.f;
|
||||
u32 x14_ = 0;
|
||||
u32 x18_ = x14_;
|
||||
float x1c_ = 0.2f;
|
||||
u32 x20_ = 0;
|
||||
EPlayerVisor x14_currentVisor = EPlayerVisor::Combat;
|
||||
EPlayerVisor x18_transitioningVisor = x14_currentVisor;
|
||||
float x1c_visorTransitionFactor = 0.2f;
|
||||
EPlayerSuit x20_currentSuit = EPlayerSuit::Power;
|
||||
rstl::reserved_vector<CPowerUp, 41> x24_powerups;
|
||||
|
||||
CStaticInterference x188_staticIntf;
|
||||
public:
|
||||
|
||||
float GetBeamSwitchTime() const;
|
||||
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(CBitStreamReader& stream);
|
||||
};
|
||||
|
|
|
@ -33,12 +33,7 @@ CRasterFont::CRasterFont(urde::CInputStream& in, urde::IObjectStore& store)
|
|||
u32 txtrId = in.readUint32Big();
|
||||
x30_fontInfo = CFontInfo(tmp1, tmp2, tmp3, tmp4, name.c_str());
|
||||
x80_texture = store.GetObj({'TXTR', txtrId});
|
||||
EColorType 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;
|
||||
x2c_mode = EColorType(in.readUint32Big());
|
||||
|
||||
u32 glyphCount = in.readUint32Big();
|
||||
xc_glyphs.reserve(glyphCount);
|
||||
|
@ -75,13 +70,16 @@ CRasterFont::CRasterFont(urde::CInputStream& in, urde::IObjectStore& store)
|
|||
s32 howMuch = in.readUint32Big();
|
||||
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,
|
||||
CTextRenderBuffer* renderBuf,
|
||||
const wchar_t* str, s32 length) const
|
||||
{
|
||||
if (!x0_)
|
||||
if (!x0_initialized)
|
||||
return;
|
||||
|
||||
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
|
||||
{
|
||||
if (!x0_)
|
||||
if (!x0_initialized)
|
||||
return;
|
||||
|
||||
if (renderBuf)
|
||||
|
|
|
@ -89,16 +89,14 @@ public:
|
|||
|
||||
class CRasterFont
|
||||
{
|
||||
bool x0_ = false;
|
||||
bool x0_initialized = false;
|
||||
s32 x4_monoWidth = 16;
|
||||
s32 x8_monoHeight = 16;
|
||||
std::vector<std::pair<wchar_t, CGlyph>> xc_glyphs;
|
||||
std::vector<CKernPair> x1c_kerning;
|
||||
s32 x28_lineMargin = 0;
|
||||
EColorType x2c_mode = EColorType::Main;
|
||||
CFontInfo x30_fontInfo;
|
||||
TLockedToken<CTexture> x80_texture;
|
||||
bool x88_ = false;
|
||||
s32 x8c_baseline;
|
||||
s32 x90_lineMargin = 0;
|
||||
|
||||
|
|
|
@ -31,7 +31,9 @@ s32 CBitStreamReader::ReadEncoded(u32 bitCount)
|
|||
|
||||
baseVal = (baseVal & (x1c_val >> (32 - x20_bitOffset))) << diff;
|
||||
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 */
|
||||
/* Little Endian sucks */
|
||||
athena::utility::BigUint32(x1c_val);
|
||||
|
@ -41,7 +43,7 @@ s32 CBitStreamReader::ReadEncoded(u32 bitCount)
|
|||
baseVal2 = (1 << diff) - 1;
|
||||
|
||||
ret = baseVal | (baseVal2 & (x1c_val >> (32 - diff))) << x20_bitOffset;
|
||||
x20_bitOffset = (4 << 3) - diff;
|
||||
x20_bitOffset = (count << 3) - diff;
|
||||
x1c_val <<= diff;
|
||||
}
|
||||
|
||||
|
@ -70,7 +72,9 @@ void CBitStreamWriter::WriteEncoded(u32 val, u32 bitCount)
|
|||
x18_bitOffset = 0;
|
||||
u32 tmp = x14_val;
|
||||
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;
|
||||
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