This commit is contained in:
Jack Andersen 2016-03-23 14:06:16 -10:00
commit 41c66a437a
8 changed files with 532 additions and 97 deletions

View File

@ -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)

View File

@ -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);
}
}

View File

@ -12,33 +12,138 @@ namespace urde
class CPlayerState
{
static const u32 PowerUpMaxes[41];
class CPowerUp
public:
enum class EItemType : u32
{
int x0_a = 0;
int x4_b = 0;
public:
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);
};

View File

@ -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)

View File

@ -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;

View File

@ -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;

7
mpcksum/CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ./../Runtime)
add_executable(mpcksum
main.cpp)
target_link_libraries(mpcksum
athena-core z lzo2)

51
mpcksum/main.cpp Normal file
View File

@ -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;
}