From f2ad835dde48348448646d5a52e600524d0bc7b9 Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Mon, 21 Apr 2025 20:08:29 -0400 Subject: [PATCH 1/7] First 100% match for testing --- src/SB/Core/x/xBehaviour.h | 6 +++--- src/SB/Game/zWadNME.cpp | 9 ++++++--- src/SB/Game/zWadNME.h | 1 - 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/SB/Core/x/xBehaviour.h b/src/SB/Core/x/xBehaviour.h index cfa111b..9ea9513 100644 --- a/src/SB/Core/x/xBehaviour.h +++ b/src/SB/Core/x/xBehaviour.h @@ -226,9 +226,9 @@ struct xListItem_1 struct xGoal : xListItem_1, xFactoryInst { - xPsyche* psyche; + xPsyche* psyche; //0x18 en_GOALSTATE stat; - S32 flg_able; + S32 flg_able; //0x20 S32 (*fun_process)(xGoal*, void*, en_trantype*, F32, void*); void* cbdata; @@ -250,7 +250,7 @@ struct zNMEGoalCommon : xGoal S32 bul_entered : 1; S32 bul_resumed : 1; S32 bul_unused : 6; - }; + } flags; struct { S32 flg_info : 16; diff --git a/src/SB/Game/zWadNME.cpp b/src/SB/Game/zWadNME.cpp index e4c1c48..7d8fcdf 100644 --- a/src/SB/Game/zWadNME.cpp +++ b/src/SB/Game/zWadNME.cpp @@ -7,9 +7,12 @@ S32 zNMEGoalDentDamage::Exit(float, void*) S32 zNMEGoalDenDamage::Exit(float dt, void* ctxt) //POSSIBLY RIGHT, NEEDS DOUBLE CHECKED { - //something = -1.0f - dt = -1.0f; // NOT CORRECT, FOR TESTING + zNMEDennis* npc; + npc->spd_throttle = -1.0f; return 0; } -//TEST +S32 zNMEDennis::DfltVulnFlags() +{ + return 0xc07b0007; // HACKED TOGETHER FOR TESTING PURPOSES +} diff --git a/src/SB/Game/zWadNME.h b/src/SB/Game/zWadNME.h index 9c7e10a..1901ae0 100644 --- a/src/SB/Game/zWadNME.h +++ b/src/SB/Game/zWadNME.h @@ -302,7 +302,6 @@ struct zNMEDenToo : zNMEBoss S32 WannaPoolShadow(); }; -//zNMEGoalDenDamage : zNMEGoalCommon struct zNMEGoalDenDamage : zNMEGoalCommon { S32 GoalHandleMail(NMEMsg* mail); From 6f37d8c69dc25041d526bf7995105971b3b9d3fb Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Mon, 21 Apr 2025 22:46:06 -0400 Subject: [PATCH 2/7] zParticleSystemWaterfall --- src/SB/Game/zParticleSystemWaterfall.cpp | 109 +++++++++ src/SB/Game/zParticleSystemWaterfall.h | 274 +++++++++++++++++++++++ 2 files changed, 383 insertions(+) create mode 100644 src/SB/Game/zParticleSystemWaterfall.h diff --git a/src/SB/Game/zParticleSystemWaterfall.cpp b/src/SB/Game/zParticleSystemWaterfall.cpp index e69de29..abcf743 100644 --- a/src/SB/Game/zParticleSystemWaterfall.cpp +++ b/src/SB/Game/zParticleSystemWaterfall.cpp @@ -0,0 +1,109 @@ +#include "zParticleSystemWaterfall.h" + +void zParticleGeneratorWaterfallSplash::deactivate() +{ + zParticleGenerator* pGen; + pGen->deactivate(); + locator.deactivate(); +} + +void zParticleGeneratorWaterfallSplash::activate() +{ + zParticleGenerator* pGen; + pGen->activate(); + locator.activate(*asset, attach_to); // Make const +} + +void zParticleGeneratorWaterfallSplash::reset() +{ + zParticleGenerator::reset(); + emitted = 0; + locator.restart(); + locator.deactivate(); + if (&flags != 0) // This arg needs fixed + { + locator.activate(*asset, attach_to); + } +} + +S32 zParticleSystemWaterfallSplash::get_asset_size() const +{ + return 56; // Calls for 0x38 +} + +void zParticleSystemWaterfallSplash::scene_enter() +{ + batch_group.create(); +} + +void zParticleGeneratorWaterfallMist::deactivate() +{ + zParticleGenerator* pGen; + pGen->deactivate(); + locator.deactivate(); +} + +void zParticleGeneratorWaterfallMist::activate() +{ + zParticleGenerator* pGen; + pGen->activate(); + locator.activate(*asset, attach_to); // Make const +} + +void zParticleGeneratorWaterfallMist::reset() +{ + zParticleGenerator::reset(); + emitted = 0; + locator.restart(); + locator.deactivate(); + if (&flags != 0) // This arg needs fixed + { + locator.activate(*asset, attach_to); + } +} + +S32 zParticleSystemWaterfallMist::get_asset_size() const +{ + return 52; // Calls for 0x34 +} + +void zParticleSystemWaterfallMist::scene_enter() +{ + batch_group.create(); +} + +void zParticleGeneratorWaterfall::deactivate() +{ + zParticleGenerator* pGen; + pGen->deactivate(); + locator.deactivate(); +} + +void zParticleGeneratorWaterfall::activate() +{ + zParticleGenerator* pGen; + pGen->activate(); + locator.activate(*asset, attach_to); // Make const +} + +void zParticleGeneratorWaterfall::reset() // 87% +{ + zParticleGenerator::reset(); + emitted = 0; + locator.restart(); + locator.deactivate(); + if (&flags != 0) // This arg needs fixed + { + locator.activate(*asset, attach_to); + } +} + +S32 zParticleSystemWaterfall::get_asset_size() const +{ + return 76; // Calls for 0x4c +} + +void zParticleSystemWaterfall::scene_enter() +{ + batch_group.create(); +} diff --git a/src/SB/Game/zParticleSystemWaterfall.h b/src/SB/Game/zParticleSystemWaterfall.h new file mode 100644 index 0000000..dbb704d --- /dev/null +++ b/src/SB/Game/zParticleSystemWaterfall.h @@ -0,0 +1,274 @@ +#ifndef ZPARTICLESYSTEMWATERFALL_H +#define ZPARTICLESYSTEMWATERFALL_H + +#include "xNME.h" + +struct _class_0 +{ + F32 yaw; + F32 pitch; + F32 roll; +}; + +struct attach_fixed_data +{ +}; + +struct attach_entity_data +{ + U32 entity; + U8 bone; + U8 pad1; + U8 pad2; + U8 pad3; +}; + +struct attach_entity_tag_data +{ + U32 entity; + xVec3 tag; +}; + +struct attach_data +{ + union + { + attach_fixed_data fixed; + attach_entity_data entity; + attach_entity_tag_data entity_tag; + }; +}; + +struct motion_none_data +{ +}; + +struct motion_spiral_data +{ + U8 flags; + U8 points; + U8 pad1; + U8 pad2; + F32 radius_inner; + F32 radius_outer; + F32 duration; + F32 frequency; +}; + +struct motion_data +{ + union + { + motion_none_data none; + motion_spiral_data spiral; + }; +}; + +struct volume_point_data +{ +}; + +struct volume_sphere_data +{ + F32 radius; +}; + +struct volume_circle_data +{ + F32 radius; + F32 arc_length; +}; + +struct volume_line_data +{ + U8 flags; + U8 pad1; + U8 pad2; + U8 pad3; + F32 radius; + F32 length; +}; + +struct volume_model_data +{ + U8 flags; + U8 exclude; + U8 pad1; + U8 pad2; + F32 expand; +}; + +struct volume_data +{ + union + { + volume_point_data point; + volume_sphere_data sphere; + volume_circle_data circle; + volume_line_data line; + volume_model_data model; + }; +}; + +struct zParticleAsset : xDynAsset +{ + U8 flags; + U8 attach_flags; + U8 motion_flags; + U8 volume_flags; + F32 rate; + U32 texture; + U8 attach_type; + U8 motion_type; + U8 volume_type; + U8 system_type; + xVec3 location; + _class_0 axis; + attach_data attach; + motion_data motion; + volume_data volume; +}; + +struct zParticleGenerator : xBase +{ + zParticleAsset* asset; + S32 flags; + + void activate(); + void deactivate(); + void reset(); + void perturb_dir(xVec3& dir, F32 angle); + xEnt* get_attach_entity(zParticleAsset& asset); + void event_handler(xBase* to, U32 event); +}; + +struct relative_ordering +{ + S32 other; + U8 before_other; +}; + +struct zParticleSystem +{ + S32 type; + S32 need; + zParticleGenerator** generators; + S32 generators_size; + S32 generators_active; + + void destroy_generator(); + void scene_exit(); + void setup(); + void reset(); + void pre_render(); + void render(); + relative_ordering* get_ordering(S32& size); + void scene_enter(); + void update(); +}; + +struct xParticleBatchGroup +{ + U8* elements; + S32 elements_size; + + void create(); +}; + +struct zParticleSystemWaterfall : zParticleSystem +{ + S32 unk; + xParticleBatchGroup batch_group; + + S32 get_asset_size() const; + void update(F32 dt); + void scene_enter(); + zParticleGenerator* create_generator(zParticleAsset& asset); +}; + +struct activity_data +{ +}; + +struct zParticleLocator +{ + activity_data* activity; + + void restart(); + void scene_enter(); + U8 activate(zParticleAsset& asset, xEnt* attach_to); + void deactivate(); +}; + +struct zParticleGeneratorWaterfall : zParticleGenerator +{ + S32 unk; + zParticleSystemWaterfall* system; + xEnt* attach_to; + F32 emitted; //0x24 + zParticleLocator locator; + S32 batch_id; + xVec3 vel_dir; + + void deactivate(); + void activate(); + void reset(); + void create(zParticleSystemWaterfall& system, zParticleAsset& asset); + void update(F32 dt); +}; + +struct zParticleSystemWaterfallMist : zParticleSystem +{ + S32 unk; + xParticleBatchGroup batch_group; + + S32 get_asset_size() const; + void update(F32 dt); + void scene_enter(); + zParticleGenerator* create_generator(zParticleAsset& asset); +}; + +struct zParticleGeneratorWaterfallMist : zParticleGenerator +{ + S32 unk; + zParticleSystemWaterfallMist* system; + xEnt* attach_to; + F32 emitted; + zParticleLocator locator; + S32 batch_id; + + void deactivate(); + void activate(); + void reset(); + void create(zParticleSystemWaterfallMist& system, zParticleAsset& asset); + void update(F32 dt); +}; + +struct zParticleSystemWaterfallSplash : zParticleSystem +{ + S32 unk; + xParticleBatchGroup batch_group; + + S32 get_asset_size() const; + void update(F32 dt); + void scene_enter(); + zParticleGenerator* create_generator(zParticleAsset& asset); +}; + +struct zParticleGeneratorWaterfallSplash : zParticleGenerator +{ + S32 unk; + zParticleSystemWaterfallSplash* system; + xEnt* attach_to; + F32 emitted; + zParticleLocator locator; + S32 batch_id; + + void deactivate(); + void activate(); + void reset(); + void create(zParticleSystemWaterfallSplash& system, zParticleAsset& asset); + void update(F32 dt); +}; + +#endif From bc16f9e7befcf71f492d22ae395cd7a633cbdbbc Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Wed, 23 Apr 2025 23:46:55 -0400 Subject: [PATCH 3/7] Added all of the bfbb core files into the movie repo --- src/SB/Core/gc/iAnim.cpp | 234 ++ src/SB/Core/gc/iAnim.h | 16 + src/SB/Core/gc/iAnimSKB.cpp | 132 + src/SB/Core/gc/iAnimSKB.h | 26 + src/SB/Core/gc/iCollide.cpp | 7 + src/SB/Core/gc/iCollide.h | 17 + src/SB/Core/gc/iCollideFast.cpp | 6 + src/SB/Core/gc/iCollideFast.h | 8 + src/SB/Core/gc/iColor.h | 23 + src/SB/Core/gc/iCutscene.cpp | 358 +++ src/SB/Core/gc/iCutscene.h | 15 + src/SB/Core/gc/iDraw.cpp | 41 + src/SB/Core/gc/iDraw.h | 10 + src/SB/Core/gc/iEnv.cpp | 216 ++ src/SB/Core/gc/iEnv.h | 30 + src/SB/Core/gc/iException.h | 0 src/SB/Core/gc/iFMV.cpp | 422 +++ src/SB/Core/gc/iFMV.h | 29 + src/SB/Core/gc/iFX.cpp | 3 + src/SB/Core/gc/iFX.h | 4 + src/SB/Core/gc/iFile.cpp | 351 ++ src/SB/Core/gc/iFile.h | 71 + src/SB/Core/gc/iLight.cpp | 156 + src/SB/Core/gc/iLight.h | 49 + src/SB/Core/gc/iMath.cpp | 39 + src/SB/Core/gc/iMath.h | 17 + src/SB/Core/gc/iMath3.cpp | 751 +++++ src/SB/Core/gc/iMath3.h | 30 + src/SB/Core/gc/iMemMgr.cpp | 55 + src/SB/Core/gc/iMemMgr.h | 9 + src/SB/Core/gc/iMix.c | 0 src/SB/Core/gc/iMix.cpp | 3 + src/SB/Core/gc/iMix.h | 11 + src/SB/Core/gc/iModel.cpp | 7 + src/SB/Core/gc/iModel.h | 28 + src/SB/Core/gc/iMorph.cpp | 3 + src/SB/Core/gc/iMorph.h | 12 + src/SB/Core/gc/iPad.cpp | 168 + src/SB/Core/gc/iPad.h | 25 + src/SB/Core/gc/iParMgr.cpp | 11 + src/SB/Core/gc/iParMgr.h | 27 + src/SB/Core/gc/iSnd.cpp | 165 + src/SB/Core/gc/iSnd.h | 78 + src/SB/Core/gc/iSystem.cpp | 235 ++ src/SB/Core/gc/iSystem.h | 26 + src/SB/Core/gc/iTime.cpp | 57 + src/SB/Core/gc/iTime.h | 38 + src/SB/Core/gc/isavegame.cpp | 2048 ++++++++++++ src/SB/Core/gc/isavegame.h | 184 ++ src/SB/Core/gc/ngcrad3d.c | 1 + src/SB/Core/gc/ngcrad3d.cpp | 3 + src/SB/Core/gc/ngcrad3d.h | 4 + src/SB/Core/x/containers.h | 57 + src/SB/Core/x/iCamera.cpp | 341 ++ src/SB/Core/x/iCamera.h | 39 + src/SB/Core/x/xAnim.cpp | 2185 +++++++++++++ src/SB/Core/x/xAnim.h | 229 ++ src/SB/Core/x/xBase.cpp | 71 + src/SB/Core/x/xBase.h | 42 + src/SB/Core/x/xBehaveGoalSimple.cpp | 85 + src/SB/Core/x/xBehaveGoalSimple.h | 58 + src/SB/Core/x/xBehaveMgr.cpp | 210 ++ src/SB/Core/x/xBehaveMgr.h | 40 + src/SB/Core/x/xBehaviour.cpp | 120 + src/SB/Core/x/xBehaviour.h | 361 +-- src/SB/Core/x/xBound.cpp | 495 +++ src/SB/Core/x/xBound.h | 52 + src/SB/Core/x/xCM.cpp | 115 + src/SB/Core/x/xCM.h | 97 + src/SB/Core/x/xCamera.cpp | 1344 ++++++++ src/SB/Core/x/xCamera.h | 236 ++ src/SB/Core/x/xClimate.cpp | 199 ++ src/SB/Core/x/xClimate.h | 41 + src/SB/Core/x/xClumpColl.cpp | 92 + src/SB/Core/x/xClumpColl.h | 40 +- src/SB/Core/x/xCollide.cpp | 242 ++ src/SB/Core/x/xCollide.h | 138 + src/SB/Core/x/xCollideFast.cpp | 36 + src/SB/Core/x/xCollideFast.h | 12 + src/SB/Core/x/xCollis.h | 42 - src/SB/Core/x/xColor.cpp | 16 + src/SB/Core/x/xColor.h | 23 + src/SB/Core/x/xCounter.cpp | 160 + src/SB/Core/x/xCounter.h | 29 + src/SB/Core/x/xCurveAsset.cpp | 38 + src/SB/Core/x/xCurveAsset.h | 29 + src/SB/Core/x/xCutscene.cpp | 185 ++ src/SB/Core/x/xCutscene.h | 108 + src/SB/Core/x/xCutsceneMgr.h | 40 + src/SB/Core/x/xDebug.cpp | 56 + src/SB/Core/x/xDebug.h | 105 + src/SB/Core/x/xDecal.cpp | 11 + src/SB/Core/x/xDecal.h | 84 + src/SB/Core/x/xDraw.h | 12 + src/SB/Core/x/xDynAsset.h | 13 + src/SB/Core/x/xEnt.cpp | 1979 ++++++++++++ src/SB/Core/x/xEnt.h | 296 +- src/SB/Core/x/xEntBoulder.cpp | 63 + src/SB/Core/x/xEntBoulder.h | 87 + src/SB/Core/x/xEntDrive.cpp | 422 +++ src/SB/Core/x/xEntDrive.h | 41 + src/SB/Core/x/xEntMotion.cpp | 224 ++ src/SB/Core/x/xEntMotion.h | 183 ++ src/SB/Core/x/xEnv.cpp | 38 + src/SB/Core/x/xEnv.h | 58 +- src/SB/Core/x/xEvent.cpp | 138 + src/SB/Core/x/{xMail.h => xEvent.h} | 468 +-- src/SB/Core/x/xFColor.h | 14 + src/SB/Core/x/xFFX.cpp | 166 + src/SB/Core/x/xFFX.h | 60 + src/SB/Core/x/xFX.cpp | 549 ++++ src/SB/Core/x/xFX.h | 127 +- src/SB/Core/x/xFactory.cpp | 247 ++ src/SB/Core/x/xFactory.h | 55 + src/SB/Core/x/xFile.h | 26 + src/SB/Core/x/xFog.cpp | 82 + src/SB/Core/x/xFog.h | 35 + src/SB/Core/x/xFont.cpp | 3705 ++++++++++++++++++++++ src/SB/Core/x/xFont.h | 219 ++ src/SB/Core/x/xFrag.h | 370 --- src/SB/Core/x/xGlobals.h | 60 + src/SB/Core/x/xGrid.cpp | 214 ++ src/SB/Core/x/xGrid.h | 171 +- src/SB/Core/x/xGroup.cpp | 215 ++ src/SB/Core/x/xGroup.h | 35 + src/SB/Core/x/xHud.cpp | 469 +++ src/SB/Core/x/xHud.h | 206 ++ src/SB/Core/x/xHudFontMeter.cpp | 3 + src/SB/Core/x/xHudFontMeter.h | 36 + src/SB/Core/x/xHudMeter.cpp | 3 + src/SB/Core/x/xHudMeter.h | 40 + src/SB/Core/x/xHudModel.cpp | 77 + src/SB/Core/x/xHudModel.h | 40 + src/SB/Core/x/xHudText.cpp | 143 + src/SB/Core/x/xHudText.h | 42 + src/SB/Core/x/xHudUnitMeter.cpp | 3 + src/SB/Core/x/xHudUnitMeter.h | 33 + src/SB/Core/x/xIni.cpp | 202 ++ src/SB/Core/x/xIni.h | 37 + src/SB/Core/x/xIsect.h | 17 + src/SB/Core/x/xJSP.cpp | 62 + src/SB/Core/x/xJSP.h | 65 +- src/SB/Core/x/xJaw.cpp | 88 + src/SB/Core/x/xJaw.h | 9 + src/SB/Core/x/xLaserBolt.cpp | 69 + src/SB/Core/x/xLaserBolt.h | 133 + src/SB/Core/x/xLightKit.cpp | 149 + src/SB/Core/x/xLightKit.h | 30 + src/SB/Core/x/xLinkAsset.h | 16 + src/SB/Core/x/xListItem.h | 26 + src/SB/Core/x/xMarkerAsset.h | 11 + src/SB/Core/x/xMath.cpp | 159 + src/SB/Core/x/xMath.h | 148 +- src/SB/Core/x/xMath2.cpp | 4 + src/SB/Core/x/xMath2.h | 59 + src/SB/Core/x/xMath3.cpp | 766 +++++ src/SB/Core/x/xMath3.h | 163 + src/SB/Core/x/xMathInlines.h | 18 + src/SB/Core/x/xMem.h | 48 - src/SB/Core/x/xMemMgr.cpp | 395 +++ src/SB/Core/x/xMemMgr.h | 114 + src/SB/Core/x/xMgr.h | 8 + src/SB/Core/x/xModel.cpp | 229 ++ src/SB/Core/x/xModel.h | 407 +-- src/SB/Core/x/xModelBucket.cpp | 109 + src/SB/Core/x/xModelBucket.h | 43 + src/SB/Core/x/xMorph.cpp | 122 + src/SB/Core/x/xMorph.h | 47 + src/SB/Core/x/xMovePoint.cpp | 180 ++ src/SB/Core/x/xMovePoint.h | 56 + src/SB/Core/x/xNME.h | 613 ---- src/SB/Core/x/xNPCBasic.cpp | 366 +++ src/SB/Core/x/xNPCBasic.h | 131 + src/SB/Core/x/xPad.cpp | 122 + src/SB/Core/x/xPad.h | 113 + src/SB/Core/x/xPar.cpp | 97 + src/SB/Core/x/xPar.h | 200 +- src/SB/Core/x/xParCmd.cpp | 800 +++++ src/SB/Core/x/xParCmd.h | 366 +++ src/SB/Core/x/xParEmitter.cpp | 3 + src/SB/Core/x/xParEmitter.h | 113 + src/SB/Core/x/xParEmitterType.cpp | 3 + src/SB/Core/x/xParEmitterType.h | 69 + src/SB/Core/x/xParGroup.cpp | 303 ++ src/SB/Core/x/xParGroup.h | 48 + src/SB/Core/x/xParMgr.cpp | 49 + src/SB/Core/x/xParMgr.h | 11 + src/SB/Core/x/xParSys.cpp | 3 + src/SB/Core/x/xParSys.h | 44 + src/SB/Core/x/xPartition.cpp | 42 + src/SB/Core/x/xPartition.h | 46 + src/SB/Core/x/xPlayer.h | 30 - src/SB/Core/x/xPtankPool.cpp | 3 + src/SB/Core/x/xPtankPool.h | 65 + src/SB/Core/x/xQuickCull.cpp | 41 + src/SB/Core/x/xQuickCull.h | 67 +- src/SB/Core/x/xRMemData.cpp | 72 + src/SB/Core/x/xRMemData.h | 33 + src/SB/Core/x/xRay3.h | 15 + src/SB/Core/x/xRenderState.cpp | 31 + src/SB/Core/x/xRenderState.h | 11 + src/SB/Core/x/xRumble.h | 33 + src/SB/Core/x/xSFX.cpp | 103 + src/SB/Core/x/xSFX.h | 41 + src/SB/Core/x/xScene.cpp | 433 +++ src/SB/Core/x/xScene.h | 66 + src/SB/Core/x/xScrFx.cpp | 11 + src/SB/Core/x/xScrFx.h | 23 + src/SB/Core/x/xShadow.cpp | 272 ++ src/SB/Core/x/xShadow.h | 53 +- src/SB/Core/x/xShadowSimple.cpp | 3 + src/SB/Core/x/xShadowSimple.h | 45 + src/SB/Core/x/xSkyDome.cpp | 101 + src/SB/Core/x/xSkyDome.h | 10 + src/SB/Core/x/xSnd.cpp | 444 +++ src/SB/Core/x/xSnd.h | 148 + src/SB/Core/x/xSound.h | 31 - src/SB/Core/x/xSpline.cpp | 3 + src/SB/Core/x/xSpline.h | 37 + src/SB/Core/x/xString.cpp | 102 + src/SB/Core/x/xString.h | 47 + src/SB/Core/x/xSurface.cpp | 70 + src/SB/Core/x/xSurface.h | 35 + src/SB/Core/x/xSystem.h | 6 + src/SB/Core/x/xTRC.cpp | 67 + src/SB/Core/x/xTRC.h | 40 + src/SB/Core/x/xTextAsset.h | 13 + src/SB/Core/x/xTimer.cpp | 98 + src/SB/Core/x/xTimer.h | 31 + src/SB/Core/x/xUpdateCull.cpp | 98 + src/SB/Core/x/xUpdateCull.h | 59 + src/SB/Core/x/xVec3.cpp | 96 + src/SB/Core/x/xVec3.h | 70 + src/SB/Core/x/xVec3Inlines.h | 37 + src/SB/Core/x/xVolume.cpp | 40 + src/SB/Core/x/xVolume.h | 27 + src/SB/Core/x/xbinio.cpp | 734 +++++ src/SB/Core/x/xbinio.h | 77 + src/SB/Core/x/xhipio.cpp | 511 +++ src/SB/Core/x/xhipio.h | 90 + src/SB/Core/x/xordarray.cpp | 183 ++ src/SB/Core/x/xordarray.h | 26 + src/SB/Core/x/xpkrsvc.cpp | 1768 +++++++++++ src/SB/Core/x/xpkrsvc.h | 224 ++ src/SB/Core/x/xsavegame.cpp | 1480 +++++++++ src/SB/Core/x/xsavegame.h | 217 ++ src/SB/Core/x/xserializer.cpp | 3 + src/SB/Core/x/xserializer.h | 51 + src/SB/Core/x/xstransvc.cpp | 587 ++++ src/SB/Core/x/xstransvc.h | 41 + src/SB/Core/x/xutil.cpp | 181 ++ src/SB/Core/x/xutil.h | 17 + src/SB/Game/zBase.h | 81 + src/SB/Game/zNMECommon.h | 0 src/SB/Game/zParticleSystemWaterfall.cpp | 188 +- src/SB/Game/zParticleSystemWaterfall.h | 548 ++-- src/SB/Game/zTalkBox.cpp | 19 + src/SB/Game/zTalkBox.h | 96 + src/SB/Game/zTaskBox.cpp | 232 ++ src/SB/Game/zTaskBox.h | 88 + src/SB/Game/zTextBox.cpp | 467 +++ src/SB/Game/zTextBox.h | 103 + src/SB/Game/zWadNME.cpp | 30 +- src/SB/Game/zWadNME.h | 323 -- 264 files changed, 41437 insertions(+), 3249 deletions(-) create mode 100644 src/SB/Core/gc/iAnim.cpp create mode 100644 src/SB/Core/gc/iAnim.h create mode 100644 src/SB/Core/gc/iAnimSKB.cpp create mode 100644 src/SB/Core/gc/iAnimSKB.h create mode 100644 src/SB/Core/gc/iCollide.cpp create mode 100644 src/SB/Core/gc/iCollide.h create mode 100644 src/SB/Core/gc/iCollideFast.cpp create mode 100644 src/SB/Core/gc/iCollideFast.h create mode 100644 src/SB/Core/gc/iColor.h create mode 100644 src/SB/Core/gc/iCutscene.cpp create mode 100644 src/SB/Core/gc/iCutscene.h create mode 100644 src/SB/Core/gc/iDraw.cpp create mode 100644 src/SB/Core/gc/iDraw.h create mode 100644 src/SB/Core/gc/iEnv.cpp create mode 100644 src/SB/Core/gc/iEnv.h create mode 100644 src/SB/Core/gc/iException.h create mode 100644 src/SB/Core/gc/iFMV.cpp create mode 100644 src/SB/Core/gc/iFMV.h create mode 100644 src/SB/Core/gc/iFX.cpp create mode 100644 src/SB/Core/gc/iFX.h create mode 100644 src/SB/Core/gc/iFile.cpp create mode 100644 src/SB/Core/gc/iFile.h create mode 100644 src/SB/Core/gc/iLight.cpp create mode 100644 src/SB/Core/gc/iLight.h create mode 100644 src/SB/Core/gc/iMath.cpp create mode 100644 src/SB/Core/gc/iMath.h create mode 100644 src/SB/Core/gc/iMath3.cpp create mode 100644 src/SB/Core/gc/iMath3.h create mode 100644 src/SB/Core/gc/iMemMgr.cpp create mode 100644 src/SB/Core/gc/iMemMgr.h create mode 100644 src/SB/Core/gc/iMix.c create mode 100644 src/SB/Core/gc/iMix.cpp create mode 100644 src/SB/Core/gc/iMix.h create mode 100644 src/SB/Core/gc/iModel.cpp create mode 100644 src/SB/Core/gc/iModel.h create mode 100644 src/SB/Core/gc/iMorph.cpp create mode 100644 src/SB/Core/gc/iMorph.h create mode 100644 src/SB/Core/gc/iPad.cpp create mode 100644 src/SB/Core/gc/iPad.h create mode 100644 src/SB/Core/gc/iParMgr.cpp create mode 100644 src/SB/Core/gc/iParMgr.h create mode 100644 src/SB/Core/gc/iSnd.cpp create mode 100644 src/SB/Core/gc/iSnd.h create mode 100644 src/SB/Core/gc/iSystem.cpp create mode 100644 src/SB/Core/gc/iSystem.h create mode 100644 src/SB/Core/gc/iTime.cpp create mode 100644 src/SB/Core/gc/iTime.h create mode 100644 src/SB/Core/gc/isavegame.cpp create mode 100644 src/SB/Core/gc/isavegame.h create mode 100644 src/SB/Core/gc/ngcrad3d.c create mode 100644 src/SB/Core/gc/ngcrad3d.cpp create mode 100644 src/SB/Core/gc/ngcrad3d.h create mode 100644 src/SB/Core/x/containers.h create mode 100644 src/SB/Core/x/iCamera.cpp create mode 100644 src/SB/Core/x/iCamera.h create mode 100644 src/SB/Core/x/xAnim.cpp create mode 100644 src/SB/Core/x/xAnim.h create mode 100644 src/SB/Core/x/xBase.cpp create mode 100644 src/SB/Core/x/xBase.h create mode 100644 src/SB/Core/x/xBehaveGoalSimple.cpp create mode 100644 src/SB/Core/x/xBehaveGoalSimple.h create mode 100644 src/SB/Core/x/xBehaveMgr.cpp create mode 100644 src/SB/Core/x/xBehaveMgr.h create mode 100644 src/SB/Core/x/xBehaviour.cpp create mode 100644 src/SB/Core/x/xBound.cpp create mode 100644 src/SB/Core/x/xBound.h create mode 100644 src/SB/Core/x/xCM.cpp create mode 100644 src/SB/Core/x/xCM.h create mode 100644 src/SB/Core/x/xCamera.h create mode 100644 src/SB/Core/x/xClimate.cpp create mode 100644 src/SB/Core/x/xClimate.h create mode 100644 src/SB/Core/x/xClumpColl.cpp create mode 100644 src/SB/Core/x/xCollide.cpp create mode 100644 src/SB/Core/x/xCollide.h create mode 100644 src/SB/Core/x/xCollideFast.cpp create mode 100644 src/SB/Core/x/xCollideFast.h delete mode 100644 src/SB/Core/x/xCollis.h create mode 100644 src/SB/Core/x/xColor.cpp create mode 100644 src/SB/Core/x/xColor.h create mode 100644 src/SB/Core/x/xCounter.cpp create mode 100644 src/SB/Core/x/xCounter.h create mode 100644 src/SB/Core/x/xCurveAsset.cpp create mode 100644 src/SB/Core/x/xCurveAsset.h create mode 100644 src/SB/Core/x/xCutscene.cpp create mode 100644 src/SB/Core/x/xCutscene.h create mode 100644 src/SB/Core/x/xCutsceneMgr.h create mode 100644 src/SB/Core/x/xDebug.cpp create mode 100644 src/SB/Core/x/xDebug.h create mode 100644 src/SB/Core/x/xDecal.cpp create mode 100644 src/SB/Core/x/xDecal.h create mode 100644 src/SB/Core/x/xDraw.h create mode 100644 src/SB/Core/x/xDynAsset.h create mode 100644 src/SB/Core/x/xEnt.cpp create mode 100644 src/SB/Core/x/xEntBoulder.cpp create mode 100644 src/SB/Core/x/xEntBoulder.h create mode 100644 src/SB/Core/x/xEntDrive.cpp create mode 100644 src/SB/Core/x/xEntDrive.h create mode 100644 src/SB/Core/x/xEntMotion.cpp create mode 100644 src/SB/Core/x/xEntMotion.h create mode 100644 src/SB/Core/x/xEnv.cpp create mode 100644 src/SB/Core/x/xEvent.cpp rename src/SB/Core/x/{xMail.h => xEvent.h} (56%) create mode 100644 src/SB/Core/x/xFColor.h create mode 100644 src/SB/Core/x/xFFX.cpp create mode 100644 src/SB/Core/x/xFFX.h create mode 100644 src/SB/Core/x/xFX.cpp create mode 100644 src/SB/Core/x/xFactory.cpp create mode 100644 src/SB/Core/x/xFactory.h create mode 100644 src/SB/Core/x/xFile.h create mode 100644 src/SB/Core/x/xFog.cpp create mode 100644 src/SB/Core/x/xFog.h create mode 100644 src/SB/Core/x/xFont.cpp create mode 100644 src/SB/Core/x/xFont.h delete mode 100644 src/SB/Core/x/xFrag.h create mode 100644 src/SB/Core/x/xGlobals.h create mode 100644 src/SB/Core/x/xGrid.cpp create mode 100644 src/SB/Core/x/xGroup.cpp create mode 100644 src/SB/Core/x/xGroup.h create mode 100644 src/SB/Core/x/xHud.cpp create mode 100644 src/SB/Core/x/xHud.h create mode 100644 src/SB/Core/x/xHudFontMeter.cpp create mode 100644 src/SB/Core/x/xHudFontMeter.h create mode 100644 src/SB/Core/x/xHudMeter.cpp create mode 100644 src/SB/Core/x/xHudMeter.h create mode 100644 src/SB/Core/x/xHudModel.cpp create mode 100644 src/SB/Core/x/xHudModel.h create mode 100644 src/SB/Core/x/xHudText.cpp create mode 100644 src/SB/Core/x/xHudText.h create mode 100644 src/SB/Core/x/xHudUnitMeter.cpp create mode 100644 src/SB/Core/x/xHudUnitMeter.h create mode 100644 src/SB/Core/x/xIni.cpp create mode 100644 src/SB/Core/x/xIni.h create mode 100644 src/SB/Core/x/xIsect.h create mode 100644 src/SB/Core/x/xJSP.cpp create mode 100644 src/SB/Core/x/xJaw.cpp create mode 100644 src/SB/Core/x/xJaw.h create mode 100644 src/SB/Core/x/xLaserBolt.cpp create mode 100644 src/SB/Core/x/xLaserBolt.h create mode 100644 src/SB/Core/x/xLightKit.cpp create mode 100644 src/SB/Core/x/xLightKit.h create mode 100644 src/SB/Core/x/xLinkAsset.h create mode 100644 src/SB/Core/x/xListItem.h create mode 100644 src/SB/Core/x/xMarkerAsset.h create mode 100644 src/SB/Core/x/xMath.cpp create mode 100644 src/SB/Core/x/xMath2.cpp create mode 100644 src/SB/Core/x/xMath2.h create mode 100644 src/SB/Core/x/xMath3.cpp create mode 100644 src/SB/Core/x/xMath3.h create mode 100644 src/SB/Core/x/xMathInlines.h delete mode 100644 src/SB/Core/x/xMem.h create mode 100644 src/SB/Core/x/xMemMgr.cpp create mode 100644 src/SB/Core/x/xMemMgr.h create mode 100644 src/SB/Core/x/xMgr.h create mode 100644 src/SB/Core/x/xModel.cpp create mode 100644 src/SB/Core/x/xModelBucket.cpp create mode 100644 src/SB/Core/x/xModelBucket.h create mode 100644 src/SB/Core/x/xMorph.cpp create mode 100644 src/SB/Core/x/xMorph.h create mode 100644 src/SB/Core/x/xMovePoint.cpp create mode 100644 src/SB/Core/x/xMovePoint.h delete mode 100644 src/SB/Core/x/xNME.h create mode 100644 src/SB/Core/x/xNPCBasic.cpp create mode 100644 src/SB/Core/x/xNPCBasic.h create mode 100644 src/SB/Core/x/xPad.cpp create mode 100644 src/SB/Core/x/xPad.h create mode 100644 src/SB/Core/x/xPar.cpp create mode 100644 src/SB/Core/x/xParCmd.cpp create mode 100644 src/SB/Core/x/xParCmd.h create mode 100644 src/SB/Core/x/xParEmitter.cpp create mode 100644 src/SB/Core/x/xParEmitter.h create mode 100644 src/SB/Core/x/xParEmitterType.cpp create mode 100644 src/SB/Core/x/xParEmitterType.h create mode 100644 src/SB/Core/x/xParGroup.cpp create mode 100644 src/SB/Core/x/xParGroup.h create mode 100644 src/SB/Core/x/xParMgr.cpp create mode 100644 src/SB/Core/x/xParMgr.h create mode 100644 src/SB/Core/x/xParSys.cpp create mode 100644 src/SB/Core/x/xParSys.h create mode 100644 src/SB/Core/x/xPartition.cpp create mode 100644 src/SB/Core/x/xPartition.h delete mode 100644 src/SB/Core/x/xPlayer.h create mode 100644 src/SB/Core/x/xPtankPool.cpp create mode 100644 src/SB/Core/x/xPtankPool.h create mode 100644 src/SB/Core/x/xQuickCull.cpp create mode 100644 src/SB/Core/x/xRMemData.cpp create mode 100644 src/SB/Core/x/xRMemData.h create mode 100644 src/SB/Core/x/xRay3.h create mode 100644 src/SB/Core/x/xRenderState.cpp create mode 100644 src/SB/Core/x/xRenderState.h create mode 100644 src/SB/Core/x/xRumble.h create mode 100644 src/SB/Core/x/xSFX.cpp create mode 100644 src/SB/Core/x/xSFX.h create mode 100644 src/SB/Core/x/xScene.cpp create mode 100644 src/SB/Core/x/xScene.h create mode 100644 src/SB/Core/x/xScrFx.cpp create mode 100644 src/SB/Core/x/xScrFx.h create mode 100644 src/SB/Core/x/xShadow.cpp create mode 100644 src/SB/Core/x/xShadowSimple.cpp create mode 100644 src/SB/Core/x/xShadowSimple.h create mode 100644 src/SB/Core/x/xSkyDome.cpp create mode 100644 src/SB/Core/x/xSkyDome.h create mode 100644 src/SB/Core/x/xSnd.cpp create mode 100644 src/SB/Core/x/xSnd.h delete mode 100644 src/SB/Core/x/xSound.h create mode 100644 src/SB/Core/x/xSpline.cpp create mode 100644 src/SB/Core/x/xSpline.h create mode 100644 src/SB/Core/x/xString.cpp create mode 100644 src/SB/Core/x/xString.h create mode 100644 src/SB/Core/x/xSurface.cpp create mode 100644 src/SB/Core/x/xSurface.h create mode 100644 src/SB/Core/x/xSystem.h create mode 100644 src/SB/Core/x/xTRC.cpp create mode 100644 src/SB/Core/x/xTRC.h create mode 100644 src/SB/Core/x/xTextAsset.h create mode 100644 src/SB/Core/x/xTimer.cpp create mode 100644 src/SB/Core/x/xTimer.h create mode 100644 src/SB/Core/x/xUpdateCull.cpp create mode 100644 src/SB/Core/x/xUpdateCull.h create mode 100644 src/SB/Core/x/xVec3.cpp create mode 100644 src/SB/Core/x/xVec3.h create mode 100644 src/SB/Core/x/xVec3Inlines.h create mode 100644 src/SB/Core/x/xVolume.cpp create mode 100644 src/SB/Core/x/xVolume.h create mode 100644 src/SB/Core/x/xbinio.cpp create mode 100644 src/SB/Core/x/xbinio.h create mode 100644 src/SB/Core/x/xhipio.cpp create mode 100644 src/SB/Core/x/xhipio.h create mode 100644 src/SB/Core/x/xordarray.cpp create mode 100644 src/SB/Core/x/xordarray.h create mode 100644 src/SB/Core/x/xpkrsvc.cpp create mode 100644 src/SB/Core/x/xpkrsvc.h create mode 100644 src/SB/Core/x/xsavegame.cpp create mode 100644 src/SB/Core/x/xsavegame.h create mode 100644 src/SB/Core/x/xserializer.cpp create mode 100644 src/SB/Core/x/xserializer.h create mode 100644 src/SB/Core/x/xstransvc.cpp create mode 100644 src/SB/Core/x/xstransvc.h create mode 100644 src/SB/Core/x/xutil.cpp create mode 100644 src/SB/Core/x/xutil.h create mode 100644 src/SB/Game/zBase.h create mode 100644 src/SB/Game/zNMECommon.h create mode 100644 src/SB/Game/zTalkBox.h create mode 100644 src/SB/Game/zTaskBox.h create mode 100644 src/SB/Game/zTextBox.h diff --git a/src/SB/Core/gc/iAnim.cpp b/src/SB/Core/gc/iAnim.cpp new file mode 100644 index 0000000..87e56de --- /dev/null +++ b/src/SB/Core/gc/iAnim.cpp @@ -0,0 +1,234 @@ +#include "iAnim.h" + +#include "iAnimSKB.h" +#include "xMath.h" + +#include +#include + +static U8 scratchBuffer[9120]; + +U8* giAnimScratch = scratchBuffer; + +void iAnimInit() +{ + return; +} + +void iAnimEval(void* RawData, F32 time, U32 flags, xVec3* tran, xQuat* quat) +{ + iAnimEvalSKB((iAnimSKBHeader*)RawData, time, flags, tran, quat); +} + +F32 iAnimDuration(void* RawData) +{ + return iAnimDurationSKB((iAnimSKBHeader*)RawData); +} + +U32 iAnimBoneCount(void* RawData) +{ + if (*(U32*)RawData == '1BKS') + { + return ((iAnimSKBHeader*)RawData)->BoneCount; + } + + return 0; +} + +// non-matching: incorrect instruction order and regalloc +void iAnimBlend(F32 BlendFactor, F32 BlendRecip, U16* BlendTimeOffset, + F32* BoneTable, U32 BoneCount, xVec3* Tran1, xQuat* Quat1, xVec3* Tran2, + xQuat* Quat2, xVec3* TranDest, xQuat* QuatDest) +{ + U32 i; + U32 invert = 0; + RtQuat* q2; + RtQuat ident = { 0.0f, 0.0f, 0.0f, 1.0f }; + xVec3* t2; + + if (!Quat2) + { + q2 = &ident; + invert = 1; + t2 = (xVec3*)&ident.imag; + } + else + { + q2 = (RtQuat*)Quat2; + t2 = Tran2; + } + + if (BlendFactor < 0.0f) + { + BlendFactor = -BlendFactor; + invert ^= 1; + } + + if (!BoneTable && !BlendTimeOffset) + { + F32 lerp = BlendFactor * BlendRecip; + + if (lerp < 0.0f) + { + lerp = 0.0f; + } + else if (lerp > 1.0f) + { + lerp = 1.0f; + } + + if (invert) + { + lerp = 1.0f - lerp; + } + + if (Quat1) + { + // non-matching: 0.0f constant is loaded outside of loop + + for (i = 0; i < BoneCount; i++) + { + RtQuatSlerpCache qcache; + + RtQuatSetupSlerpCache((RtQuat*)Quat1, q2, &qcache); + RtQuatSlerp((RtQuat*)QuatDest, (RtQuat*)Quat1, q2, lerp, &qcache); + + Quat1++; + + if (Quat2) + { + q2++; + } + + QuatDest++; + } + } + + if (Tran1) + { + if (Quat2) + { + for (i = 0; i < BoneCount; i++, TranDest++, t2++, Tran1++) + { + TranDest->x = lerp * (t2->x - Tran1->x) + Tran1->x; + TranDest->y = lerp * (t2->y - Tran1->y) + Tran1->y; + TranDest->z = lerp * (t2->z - Tran1->z) + Tran1->z; + } + } + else + { + for (i = 0; i < BoneCount; i++, TranDest++, Tran1++) + { + TranDest->x = lerp * (t2->x - Tran1->x) + Tran1->x; + TranDest->y = lerp * (t2->y - Tran1->y) + Tran1->y; + TranDest->z = lerp * (t2->z - Tran1->z) + Tran1->z; + } + } + } + } + else + { + F32 baselerp; + + if (!BlendTimeOffset) + { + baselerp = BlendFactor * BlendRecip; + + if (baselerp < 0.0f) + { + baselerp = 0.0f; + } + else if (baselerp > 1.0f) + { + baselerp = 1.0f; + } + + if (invert) + { + baselerp = 1.0f - baselerp; + } + } + + for (i = 0; i < BoneCount; i++) + { + F32 lerp; + + if (BlendTimeOffset) + { + baselerp = -(1 / 1024.0f * BlendTimeOffset[i * 2] - BlendFactor); + + if (BlendTimeOffset[i * 2 + 1] != 0) + { + baselerp *= 1 / 1024.0f * BlendTimeOffset[i * 2 + 1]; + + if (baselerp < 0.0f) + { + baselerp = 0.0f; + } + else if (baselerp > 1.0f) + { + baselerp = 1.0f; + } + } + else + { + if (baselerp < 0.0f) + { + baselerp = 0.0f; + } + else + { + baselerp = 1.0f; + } + } + + if (invert) + { + baselerp = 1.0f - baselerp; + } + } + + if (BoneTable) + { + lerp = baselerp * BoneTable[i]; + } + else + { + lerp = baselerp; + } + + if (Quat1) + { + RtQuatSlerpCache qcache; + + RtQuatSetupSlerpCache((RtQuat*)Quat1, q2, &qcache); + RtQuatSlerp((RtQuat*)QuatDest, (RtQuat*)Quat1, q2, lerp, &qcache); + + Quat1++; + + if (Quat2) + { + q2++; + } + + QuatDest++; + } + + if (Tran1) + { + TranDest->x = lerp * (t2->x - Tran1->x) + Tran1->x; + TranDest->y = lerp * (t2->y - Tran1->y) + Tran1->y; + TranDest->z = lerp * (t2->z - Tran1->z) + Tran1->z; + + Tran1++; + + if (Quat2) + { + t2++; + } + + TranDest++; + } + } + } +} diff --git a/src/SB/Core/gc/iAnim.h b/src/SB/Core/gc/iAnim.h new file mode 100644 index 0000000..594f67a --- /dev/null +++ b/src/SB/Core/gc/iAnim.h @@ -0,0 +1,16 @@ +#ifndef IANIM_H +#define IANIM_H + +#include "xMath3.h" + +extern U8* giAnimScratch; + +void iAnimInit(); +F32 iAnimDuration(void* RawData); +U32 iAnimBoneCount(void* RawData); +void iAnimBlend(F32 BlendFactor, F32 BlendRecip, U16* BlendTimeOffset, F32* BoneTable, + U32 BoneCount, xVec3* Tran1, xQuat* Quat1, xVec3* Tran2, xQuat* Quat2, + xVec3* TranDest, xQuat* QuatDest); +void iAnimEval(void* RawData, float time, unsigned int flags, class xVec3* tran, class xQuat* quat); + +#endif diff --git a/src/SB/Core/gc/iAnimSKB.cpp b/src/SB/Core/gc/iAnimSKB.cpp new file mode 100644 index 0000000..8dace6e --- /dev/null +++ b/src/SB/Core/gc/iAnimSKB.cpp @@ -0,0 +1,132 @@ +#include "iAnimSKB.h" + +#include +#include + +#include + +void iAnimEvalSKB(iAnimSKBHeader* data, F32 time, U32 flags, xVec3* tran, xQuat* quat) +{ + U32 i, tidx, bcount, tcount; + iAnimSKBKey* keys; + F32* times; + U16* offsets; + S32 asdf; // unused + F32 scalex, scaley, scalez; + + tcount = data->TimeCount; + bcount = data->BoneCount; + + keys = (iAnimSKBKey*)(data + 1); + times = (F32*)(keys + data->KeyCount); + offsets = (U16*)(times + tcount); + + if (time < 0.0f) + { + time = 0.0f; + } + + if (time > times[tcount - 1]) + { + time = times[tcount - 1]; + } + + tidx = (tcount - 1) % 4; + + while (times[tidx] < time) + { + tidx += 4; + } + + while (tidx && time <= times[tidx]) + { + tidx--; + } + + offsets += tidx * bcount; + + if (flags & 0x1) + { + bcount = 1; + } + + if (flags & 0x2) + { + bcount--; + offsets++; + } + + if (tcount == 1) + { + // non-matching: float constants are loaded outside of loop + + scalex = data->Scale[0]; + scaley = data->Scale[1]; + scalez = data->Scale[2]; + + for (i = 0; i < bcount; i++, quat++, tran++) + { + iAnimSKBKey* k = &keys[i]; + + quat->v.x = k->Quat[0] * (1.0f / SHRT_MAX); + quat->v.y = k->Quat[1] * (1.0f / SHRT_MAX); + quat->v.z = k->Quat[2] * (1.0f / SHRT_MAX); + quat->s = k->Quat[3] * (1.0f / SHRT_MAX); + + tran->x = k->Tran[0] * scalex; + tran->y = k->Tran[1] * scaley; + tran->z = k->Tran[2] * scalez; + } + } + else + { + // non-matching: float constants are loaded outside of loop + + scalex = data->Scale[0]; + scaley = data->Scale[1]; + scalez = data->Scale[2]; + + for (i = 0; i < bcount; i++, quat++, tran++) + { + // no idea if this part even functionally matches. + // come back to this when not lazy + + RtQuatSlerpCache qcache; + RtQuat q1, q2; + RwReal time1, time2, lerp; + iAnimSKBKey* k = &keys[*offsets]; + U32 costheta, theta; // unused + + offsets++; + + time1 = time - times[k->TimeIndex]; + time2 = times[k[1].TimeIndex] - times[k[0].TimeIndex]; + lerp = time1 / time2; + + q1.imag.x = k[0].Quat[0] * (1.0f / SHRT_MAX); + q1.imag.y = k[0].Quat[1] * (1.0f / SHRT_MAX); + q1.imag.z = k[0].Quat[2] * (1.0f / SHRT_MAX); + q1.real = k[0].Quat[3] * (1.0f / SHRT_MAX); + + q2.imag.x = k[1].Quat[0] * (1.0f / SHRT_MAX); + q2.imag.y = k[1].Quat[1] * (1.0f / SHRT_MAX); + q2.imag.z = k[1].Quat[2] * (1.0f / SHRT_MAX); + q2.real = k[1].Quat[3] * (1.0f / SHRT_MAX); + + RtQuatSetupSlerpCache(&q1, &q2, &qcache); + RtQuatSlerp((RtQuat*)quat, &q1, &q2, lerp, &qcache); + + tran->x = + lerp * (scalex * k[1].Tran[0] - scalex * k[0].Tran[0]) + scalex * k[0].Tran[0]; + tran->y = + lerp * (scaley * k[1].Tran[1] - scaley * k[0].Tran[1]) + scaley * k[1].Tran[1]; + tran->z = + lerp * (scalez * k[1].Tran[2] - scalez * k[0].Tran[2]) + scalez * k[1].Tran[2]; + } + } +} + +F32 iAnimDurationSKB(iAnimSKBHeader* data) +{ + return ((F32*)((iAnimSKBKey*)(data + 1) + data->KeyCount))[data->TimeCount - 1]; +} diff --git a/src/SB/Core/gc/iAnimSKB.h b/src/SB/Core/gc/iAnimSKB.h new file mode 100644 index 0000000..d67fc03 --- /dev/null +++ b/src/SB/Core/gc/iAnimSKB.h @@ -0,0 +1,26 @@ +#ifndef IANIMSKB_H +#define IANIMSKB_H + +#include "xMath3.h" + +struct iAnimSKBHeader +{ + U32 Magic; + U32 Flags; + U16 BoneCount; + U16 TimeCount; + U32 KeyCount; + F32 Scale[3]; +}; + +struct iAnimSKBKey +{ + U16 TimeIndex; + S16 Quat[4]; + S16 Tran[3]; +}; + +void iAnimEvalSKB(iAnimSKBHeader* data, F32 time, U32 flags, xVec3* tran, xQuat* quat); +F32 iAnimDurationSKB(iAnimSKBHeader* data); + +#endif diff --git a/src/SB/Core/gc/iCollide.cpp b/src/SB/Core/gc/iCollide.cpp new file mode 100644 index 0000000..2272a46 --- /dev/null +++ b/src/SB/Core/gc/iCollide.cpp @@ -0,0 +1,7 @@ +#include "iCollide.h" + +#include + +void iCollideInit(xScene*) +{ +} diff --git a/src/SB/Core/gc/iCollide.h b/src/SB/Core/gc/iCollide.h new file mode 100644 index 0000000..41f9af9 --- /dev/null +++ b/src/SB/Core/gc/iCollide.h @@ -0,0 +1,17 @@ +#ifndef ICOLLIDE_H +#define ICOLLIDE_H + +#include "xMath3.h" +#include "xModel.h" +#include "xEnv.h" +#include "xCollide.h" + +void iBoxForModelLocal(xBox* o, const xModelInstance* m); +void iBoxForModel(xBox* o, const xModelInstance* m); +S32 iSphereHitsEnv3(const xSphere* b, const xEnv* env, xCollis* colls, U8 ncolls, F32 sth); +S32 iSphereHitsModel3(const xSphere* b, const xModelInstance* m, xCollis* colls, U8 ncolls, + F32 sth); +U32 iRayHitsModel(const xRay3* r, const xModelInstance* m, xCollis* coll); +void iCollideInit(xScene* sc); + +#endif diff --git a/src/SB/Core/gc/iCollideFast.cpp b/src/SB/Core/gc/iCollideFast.cpp new file mode 100644 index 0000000..945d8ca --- /dev/null +++ b/src/SB/Core/gc/iCollideFast.cpp @@ -0,0 +1,6 @@ +#include "iCollideFast.h" + +void iCollideFastInit(xScene* sc) +{ + return; +} \ No newline at end of file diff --git a/src/SB/Core/gc/iCollideFast.h b/src/SB/Core/gc/iCollideFast.h new file mode 100644 index 0000000..2e3dcb8 --- /dev/null +++ b/src/SB/Core/gc/iCollideFast.h @@ -0,0 +1,8 @@ +#ifndef ICOLLIDEFAST_H +#define ICOLLIDEFAST_H + +#include "xScene.h" + +void iCollideFastInit(xScene* sc); + +#endif diff --git a/src/SB/Core/gc/iColor.h b/src/SB/Core/gc/iColor.h new file mode 100644 index 0000000..c01e8ba --- /dev/null +++ b/src/SB/Core/gc/iColor.h @@ -0,0 +1,23 @@ +#ifndef ICOLOR_H +#define ICOLOR_H + +#include + +struct iColor_tag +{ + U8 r; + U8 g; + U8 b; + U8 a; + + iColor_tag& operator=(const iColor_tag& rhs) + { + this->r = rhs.r; + this->g = rhs.g; + this->b = rhs.b; + this->a = rhs.a; + return *this; + }; +}; + +#endif diff --git a/src/SB/Core/gc/iCutscene.cpp b/src/SB/Core/gc/iCutscene.cpp new file mode 100644 index 0000000..973bf9f --- /dev/null +++ b/src/SB/Core/gc/iCutscene.cpp @@ -0,0 +1,358 @@ +#include "iCutscene.h" + +#include "xpkrsvc.h" +#include "xstransvc.h" +#include "xMath.h" + +#include "iModel.h" + +#include +#include + +U32 read_sizzze = 0; + +void iCSSoundSetup(xCutscene* csn) +{ + xCutsceneData* data; + U32 dataIndex; + U32 numData; + + data = (xCutsceneData*)(csn->Play + 1); + numData = csn->Play->NumData; + + for (dataIndex = 0; dataIndex < numData; dataIndex++) + { + if (data->DataType == XCUTSCENEDATA_TYPE_SOUND) + { + if (csn->SndNumChannel >= 2) + { + break; + } + + csn->SndAssetID[csn->SndNumChannel] = data->AssetID; + csn->SndNumChannel++; + } + + data = (xCutsceneData*)((U8*)data + ALIGN(data->ChunkSize, 16) + sizeof(xCutsceneData)); + } +} + +void* iCSSoundGetData(xSndVoiceInfo* vp, U32* size) +{ + U32 channelIndex; + U32 dataIndex; + xCutscene* csn; + void* retdata; + xCutsceneData* data; + U32 numChannel; + U32 numData; + S32 sndChannelIndex; + U32 r4; + U32 sndChannelReq; + + csn = xCutscene_CurrentCutscene(); + + numChannel = csn->SndNumChannel; + retdata = NULL; + sndChannelIndex = -1; + + for (channelIndex = 0; channelIndex < numChannel; channelIndex++) + { + if (csn->SndAssetID[channelIndex] == vp->assetID) + { + sndChannelIndex = channelIndex; + sndChannelReq = csn->SndChannelReq[channelIndex]; + } + } + + if (sndChannelIndex == -1) + { + return NULL; + } + + if (!csn->Waiting && csn->Stream->ChunkIndex == sndChannelReq) + { + numData = csn->Stream->NumData; + data = (xCutsceneData*)(csn->Stream + 1); + } + else + { + numData = csn->Play->NumData; + data = (xCutsceneData*)(csn->Play + 1); + + if (csn->SndChannelReq[sndChannelIndex] != csn->Play->ChunkIndex) + { + csn->SndChannelReq[sndChannelIndex] = csn->Play->ChunkIndex; + } + } + + r4 = 0; + + for (dataIndex = 0; dataIndex < numData; dataIndex++) + { + if (data->DataType == XCUTSCENEDATA_TYPE_SOUND) + { + if (!retdata) + { + retdata = (void*)(data + 1); + *size = data->ChunkSize; + } + + if (sndChannelIndex == r4) + { + retdata = (void*)(data + 1); + *size = data->ChunkSize; + + break; + } + else + { + r4++; + } + } + + data = (xCutsceneData*)((U8*)data + ALIGN(data->ChunkSize, 16) + sizeof(xCutsceneData)); + } + + if (!retdata) + { + return NULL; + } + + while ((U32)retdata & 0x1F) + { + retdata = (void*)((U8*)retdata + 16); + *size -= 16; + } + + csn->SndChannelReq[sndChannelIndex]++; + + return retdata; +} + +static void iCSAsyncReadCB(tag_xFile* file) +{ + S32 bytes; + xCutscene* csn; + + if (file) + { + if (iFileReadAsyncStatus(file->ps.asynckey, &bytes) == IFILE_RDSTAT_DONE) + { + iFileSeek(file, bytes, IFILE_SEEK_CUR); + } + + csn = xCutscene_CurrentCutscene(); + csn->Waiting = 0; + } +} + +U32 iCSFileOpen(xCutscene* csn) +{ + U32 headerskip; + st_PKR_ASSET_TOCINFO ainfo; + const char* filename; + + headerskip = ALIGN(csn->Info->HeaderSize, 2048); + + if (!xSTGetAssetInfo(csn->Info->AssetID, &ainfo)) + { + return 0; + } + + filename = xST_xAssetID_HIPFullPath(csn->Info->AssetID); + + if (iFileOpen(filename, 0x1, &csn->File) == 0) + { + iFileSeek(&csn->File, headerskip + (ainfo.sector - csn->File.ps.fileInfo.startAddr << 5), + IFILE_SEEK_SET); + + csn->File.ps.asynckey = -1; + } + else + { + return 0; + } + + return 1; +} + +void iCSFileAsyncRead(xCutscene* csn, void* dest, U32 size) +{ + U32* buf = (U32*)dest; + U32 i; + + read_sizzze = size; + csn->Waiting = 1; + + for (i = 0; i < size / 4; i++) + { + buf[i] = 0xDEADBEEF; + } + + iFileReadAsync(&csn->File, dest, size, iCSAsyncReadCB, 0); +} + +void iCSFileAsyncSkip(xCutscene* csn, U32 amount) +{ + csn->Waiting = 1; + + iFileSeek(&csn->File, amount, IFILE_SEEK_CUR); +} + +void iCSFileClose(xCutscene* csn) +{ + iFileReadStop(); + + csn->Opened = 0; +} + +S32 iCSLoadStep(xCutscene* csn) +{ + S32 bytes; + XFILE_READSECTOR_STATUS cdstat; + U32 skipAccum; + U32 tmpSize; + void* foundModel; + U32 i; + + if (csn->Waiting) + { + cdstat = xFileReadAsyncStatus(csn->File.ps.asynckey, &bytes); + + if (cdstat == XFILE_RDSTAT_INPROG || cdstat == XFILE_RDSTAT_QUEUED) + { + return 0; + } + } + + if (csn->DataLoading >= 0) + { + skipAccum = 0; + + while (csn->DataLoading < (S32)csn->Info->NumData) + { + if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_6) + { + foundModel = NULL; + } + else + { + foundModel = xSTFindAsset(csn->Data[csn->DataLoading].AssetID, &tmpSize); + } + + if (foundModel || csn->Data[csn->DataLoading].ChunkSize == 0) + { + csn->Data[csn->DataLoading].DataPtr = foundModel; + + skipAccum += ALIGN(csn->Data[csn->DataLoading].ChunkSize, 2048); + + csn->DataLoading++; + } + else + { + if (skipAccum) + { + iCSFileAsyncSkip(csn, skipAccum); + + skipAccum = 0; + } + + if (csn->GotData) + { + if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_6) + { + csn->Data[csn->DataLoading].DataPtr = + RwMalloc(csn->Data[csn->DataLoading].ChunkSize); + + memcpy(csn->Data[csn->DataLoading].DataPtr, csn->AlignBuf, + csn->Data[csn->DataLoading].ChunkSize); + } + else + { + csn->Data[csn->DataLoading].DataPtr = + iModelFileNew(csn->AlignBuf, csn->Data[csn->DataLoading].ChunkSize); + } + + csn->Data[csn->DataLoading].DataType |= 0x80000000; + csn->DataLoading++; + csn->GotData = 0; + } + else + { + iCSFileAsyncRead(csn, csn->AlignBuf, + ALIGN(csn->Data[csn->DataLoading].ChunkSize, 2048)); + + csn->GotData = 1; + return 0; + } + } + } + + if (skipAccum) + { + iCSFileAsyncSkip(csn, skipAccum); + } + + csn->DataLoading = -1; + } + + if (csn->DataLoading == -1) + { + if (csn->GotData) + { + iCSSoundSetup(csn); + + if (csn->SndNumChannel != 0) + { + xSndPauseAll(1, 1); + xSndUpdate(); + + if (csn->SndNumChannel == 2) + { + // Stereo + + csn->SndHandle[0] = xSndPlay(csn->SndAssetID[0], 0.9f, -99999.0f, 255, 0x200, 0, + SND_CAT_CUTSCENE, 0.0f); + csn->SndHandle[1] = xSndPlay(csn->SndAssetID[1], 0.9f, -99999.0f, 255, 0x200, 0, + SND_CAT_CUTSCENE, 0.0f); + } + else + { + // Mono + + csn->SndHandle[0] = xSndPlay(csn->SndAssetID[0], 0.9f, -99999.0f, 255, 0x200, 0, + SND_CAT_CUTSCENE, 0.0f); + csn->SndHandle[1] = 0; + } + } + + csn->GotData = 0; + csn->DataLoading = -2; + } + else + { + iCSFileAsyncRead(csn, csn->Play, csn->TimeChunkOffs[1] - csn->TimeChunkOffs[0]); + + csn->GotData = 1; + return 0; + } + } + + if (csn->DataLoading == -2) + { + if (csn->Info->NumTime > 1) + { + iCSFileAsyncRead(csn, csn->Stream, csn->TimeChunkOffs[2] - csn->TimeChunkOffs[1]); + } + + csn->DataLoading = -3; + } + + for (i = 0; i < csn->SndNumChannel; i++) + { + } + + csn->Ready = 1; + return 1; +} diff --git a/src/SB/Core/gc/iCutscene.h b/src/SB/Core/gc/iCutscene.h new file mode 100644 index 0000000..8872dc6 --- /dev/null +++ b/src/SB/Core/gc/iCutscene.h @@ -0,0 +1,15 @@ +#ifndef ICUTSCENE_H +#define ICUTSCENE_H + +#include "xCutscene.h" +#include "xSnd.h" + +void iCSSoundSetup(xCutscene* csn); +void* iCSSoundGetData(xSndVoiceInfo* vp, U32* size); +U32 iCSFileOpen(xCutscene* csn); +void iCSFileAsyncRead(xCutscene* csn, void* dest, U32 size); +void iCSFileAsyncSkip(xCutscene* csn, U32 amount); +void iCSFileClose(xCutscene* csn); +S32 iCSLoadStep(xCutscene* csn); + +#endif diff --git a/src/SB/Core/gc/iDraw.cpp b/src/SB/Core/gc/iDraw.cpp new file mode 100644 index 0000000..cffc6a8 --- /dev/null +++ b/src/SB/Core/gc/iDraw.cpp @@ -0,0 +1,41 @@ +#include "iDraw.h" + +#include +#include + +void iDrawSetFBMSK(U32 abgr) +{ + size_t tmp, hi; + + hi = abgr >> 24; + + if (hi == 0) + { + GXSetAlphaUpdate(GX_TRUE); + } + else if (hi == 255) + { + GXSetAlphaUpdate(GX_FALSE); + } + + tmp = abgr & 0x00FFFFFF; + + if (tmp == 0) + { + GXSetColorUpdate(GX_TRUE); + } + else + { + GXSetColorUpdate(GX_FALSE); + } +} + +void iDrawBegin() +{ + return; +} + +void iDrawEnd() +{ + return; +} diff --git a/src/SB/Core/gc/iDraw.h b/src/SB/Core/gc/iDraw.h new file mode 100644 index 0000000..c772b4f --- /dev/null +++ b/src/SB/Core/gc/iDraw.h @@ -0,0 +1,10 @@ +#ifndef IDRAW_H +#define IDRAW_H + +#include + +void iDrawSetFBMSK(U32 abgr); +void iDrawBegin(); +void iDrawEnd(); + +#endif diff --git a/src/SB/Core/gc/iEnv.cpp b/src/SB/Core/gc/iEnv.cpp new file mode 100644 index 0000000..f377f2e --- /dev/null +++ b/src/SB/Core/gc/iEnv.cpp @@ -0,0 +1,216 @@ +#include "iEnv.h" + +#include "iModel.h" + +#include "iCamera.h" +#include "xMemMgr.h" + +static S32 sBeginDrawFX; +static RpWorld* sPipeWorld; +static RwCamera* sPipeCamera; +static iEnv* lastEnv; + +static RpAtomic* SetPipelineCB(RpAtomic* atomic, void* data) +{ + if (RwCameraBeginUpdate(sPipeCamera)) + { + RpAtomicInstance(atomic); + RwCameraEndUpdate(sPipeCamera); + } + + if (data) + { + RpAtomicSetPipeline(atomic, (RxPipeline*)data); + } + + return atomic; +} + +static void iEnvSetBSP(iEnv* env, S32 envDataType, RpWorld* bsp) +{ + if (envDataType == 0) + { + env->world = bsp; + } + else if (envDataType == 1) + { + env->collision = bsp; + } + else if (envDataType == 2) + { + env->fx = bsp; + } + else if (envDataType == 3) + { + env->camera = bsp; + } +} + +void iEnvLoad(iEnv* env, const void* data, U32, S32 dataType) +{ + RpWorld* bsp = (RpWorld*)data; + xJSPHeader* jsp = (xJSPHeader*)data; + + if (jsp->idtag[0] == 'J' && jsp->idtag[1] == 'S' && jsp->idtag[2] == 'P' && + jsp->idtag[3] == '\0') + { + if (dataType == 0) + { + RwBBox tmpbbox = { 1000.0f, 1000.0f, 1000.0f, -1000.0f, -1000.0f, -1000.0f }; + + env->world = RpWorldCreate(&tmpbbox); + + sPipeCamera = iCameraCreate(640, 480, 0); + sPipeWorld = env->world; + + // non-matching: sPipeCamera and sPipeWorld loads are skipped + + RpWorldAddCamera(sPipeWorld, sPipeCamera); + + env->jsp = jsp; + + RpClumpForAllAtomics(env->jsp->clump, SetPipelineCB, NULL); + xClumpColl_InstancePointers(env->jsp->colltree, env->jsp->clump); + + RpWorldRemoveCamera(sPipeWorld, sPipeCamera); + + iCameraDestroy(sPipeCamera); + + sPipeWorld = NULL; + sPipeCamera = NULL; + } + } + else + { + if (dataType == 0) + { + env->jsp = NULL; + } + + iEnvSetBSP(env, dataType, bsp); + } + + if (dataType == 0) + { + env->memlvl = xMemGetBase(); + } +} + +void iEnvFree(iEnv* env) +{ + _rwFrameSyncDirty(); + + RpWorldDestroy(env->world); + env->world = NULL; + + if (env->fx) + { + RpWorldDestroy(env->fx); + env->fx = NULL; + } + + if (env->collision) + { + RpWorldDestroy(env->collision); + env->collision = NULL; + } +} + +void iEnvDefaultLighting(iEnv*) +{ +} + +void iEnvLightingBasics(iEnv*, xEnvAsset*) +{ +} + +// This is named JspPS2_ClumpRender on PS2 +static void Jsp_ClumpRender(RpClump* clump, xJSPNodeInfo* nodeInfo) +{ + S32 backcullon = 1; + S32 zbufferon = 1; + RwLLLink* cur = rwLinkListGetFirstLLLink(&clump->atomicList); + RwLLLink* end = rwLinkListGetTerminator(&clump->atomicList); + + while (cur != end) + { + RpAtomic* apAtom = rwLLLinkGetData(cur, RpAtomic, inClumpLink); + + if (RpAtomicGetFlags(apAtom) & rpATOMICRENDER) + { + RwFrame* frame = RpAtomicGetFrame(apAtom); + + if (!iModelCull(apAtom, &frame->ltm)) + { + if (backcullon) + { + if (nodeInfo->nodeFlags & 0x4) + { + backcullon = 0; + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); + } + } + else + { + if (!(nodeInfo->nodeFlags & 0x4)) + { + backcullon = 1; + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLBACK); + } + } + + if (zbufferon) + { + if (nodeInfo->nodeFlags & 0x2) + { + zbufferon = 0; + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + } + } + else + { + if (!(nodeInfo->nodeFlags & 0x2)) + { + zbufferon = 1; + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + } + } + + RpAtomicRender(apAtom); + } + } + + cur = rwLLLinkGetNext(cur); + nodeInfo++; + } +} + +void iEnvRender(iEnv* env) +{ + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + + if (env->jsp) + { + Jsp_ClumpRender(env->jsp->clump, env->jsp->jspNodeList); + } + else + { + RpWorldRender(env->world); + } + + lastEnv = env; +} + +void iEnvEndRenderFX(iEnv*) +{ + iEnv* env = lastEnv; + + if (env->fx && globalCamera && sBeginDrawFX) + { + RpWorldRemoveCamera(env->fx, globalCamera); + RpWorldAddCamera(env->world, globalCamera); + + sBeginDrawFX = 0; + } +} diff --git a/src/SB/Core/gc/iEnv.h b/src/SB/Core/gc/iEnv.h new file mode 100644 index 0000000..acceb7a --- /dev/null +++ b/src/SB/Core/gc/iEnv.h @@ -0,0 +1,30 @@ +#ifndef IENV_H +#define IENV_H + +#include "xJSP.h" + +#include +#include + +struct iEnv +{ + RpWorld* world; + RpWorld* collision; + RpWorld* fx; + RpWorld* camera; + xJSPHeader* jsp; + RpLight* light[2]; + RwFrame* light_frame[2]; + S32 memlvl; +}; + +struct xEnvAsset; + +void iEnvLoad(iEnv* env, const void* data, U32 datasize, S32 dataType); +void iEnvFree(iEnv* env); +void iEnvDefaultLighting(iEnv*); +void iEnvLightingBasics(iEnv*, xEnvAsset*); +void iEnvRender(iEnv* env); +void iEnvEndRenderFX(iEnv*); + +#endif diff --git a/src/SB/Core/gc/iException.h b/src/SB/Core/gc/iException.h new file mode 100644 index 0000000..e69de29 diff --git a/src/SB/Core/gc/iFMV.cpp b/src/SB/Core/gc/iFMV.cpp new file mode 100644 index 0000000..2d34852 --- /dev/null +++ b/src/SB/Core/gc/iFMV.cpp @@ -0,0 +1,422 @@ +#include "iFMV.h" + +#include "iCamera.h" +#include "iFile.h" +#include "iPad.h" +#include "iSystem.h" +#include "iTRC.h" + +#include "xFile.h" +#include "xPar.h" + +#include "zGlobals.h" + +#include +#include + +// FIXME: These should be in a RW header somewhere +extern GXRenderModeObj* _RwDlRenderMode; +extern "C" { +void RwGameCubeGetXFBs(void*, void*); +} + +// .bss +static U32 Bink_surface_type[5]; + +// .sbss +static S32 frame_num; +U32 fuckingSurfaceType; +static HBINK Bink; +static HRAD3DIMAGE Image; +static S32 Paused; +static void* pixels; +static volatile F32 vol; +S32 ip; +s32 oof; +void* iFMV::mXFBs[2]; +void* iFMV::mCurrentFrameBuffer; +GXRenderModeObj* iFMV::mRenderMode; + +// .sdata +static float Width_scale = 1.0f; +static float Height_scale = 1.0f; +U8 iFMV::mFirstFrame = 1; + +void* iFMVmalloc(size_t size) +{ + return RwMalloc(size); +} + +void iFMVfree(void* mem) +{ + RwFree(mem); +} + +static void PlayFMV(char* filename, size_t buttons, F32 time); +U32 iFMVPlay(char* filename, U32 buttons, F32 time, bool skippable, bool lockController) +{ + if (filename == NULL) + { + return 1; + } + + frame_num = 0; + while (frame_num >= 0) + { + PlayFMV(filename, buttons, time); + } + return 0; +} + +static void Setup_surface_array() +{ + Bink_surface_type[0] = BINKSURFACE32; + Bink_surface_type[1] = BINKSURFACE32A; + Bink_surface_type[2] = BINKSURFACE565; + Bink_surface_type[3] = BINKSURFACE4444; + Bink_surface_type[4] = BINKSURFACEYUY2; +} + +// WIP. +void Decompress_frame(HBINK bnk, HRAD3DIMAGE rad_image, long flags) +{ + struct Result + { + S32 unk_0; + S32 unk_4; + U32 unk_8; + U32 unk_c; + }; + Result result; + result.unk_4 = BinkDoFrame(bnk); + if (Lock_RAD_3D_image(rad_image, &pixels, &result.unk_c, &result.unk_8) != 0) + { + S32 mask = flags * -1; + mask = mask | flags; + mask = mask >> 0x1f; + mask = mask & 0x80000000; + mask |= Bink_surface_type[result.unk_8]; + result.unk_0 = BinkCopyToBuffer(bnk, pixels, result.unk_c, bnk->unk_4, NULL, NULL, mask); + Unlock_RAD_3D_image(rad_image); + } +} + +static void DrawFrame(float arg0, float arg1, float arg2, float arg3) +{ + GXRenderModeObj* rm = _RwDlRenderMode; + Mtx idt; + Mtx44 mtx; + + GXSetViewport(0.0f, 0.0f, rm->fbWidth, rm->efbHeight, 0.0f, 1.0f); + GXSetScissor(0, 0, rm->fbWidth, rm->efbHeight); + GXSetDispCopySrc(0, 0, rm->fbWidth, rm->efbHeight); + GXSetDispCopyDst(rm->fbWidth, rm->xfbHeight); + GXSetDispCopyYScale((float)rm->xfbHeight / rm->efbHeight); + GXSetCopyFilter(rm->aa, rm->sample_pattern, GX_TRUE, rm->vfilter); + + if (rm->aa) + { + GXSetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); + } + else + { + GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + } + + GXSetDispCopyGamma(GX_GM_1_0); + C_MTXOrtho(mtx, 0.0f, 480.0f, 0.0f, 640.0f, 0.0f, 10000.0f); + GXSetProjection(mtx, GX_ORTHOGRAPHIC); + PSMTXIdentity(idt); + GXLoadPosMtxImm(idt, 0); + + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_NRM_NBT, GX_S16, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_NRM_NBT, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_NRM_NBT, GX_RGBA6, 0); + + GXSetNumTexGens(1); + GXSetNumChans(1); + GXSetNumTevStages(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); + GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + + if (rm->field_rendering) + { + u32 field = VIGetNextField(); + GXSetViewportJitter(0.0f, 0.0f, rm->fbWidth, rm->efbHeight, 0.0f, 1.0f, field); + } + else + { + GXSetViewport(0.0f, 0.0f, rm->fbWidth, rm->efbHeight, 0.0f, 1.0f); + } + + GXInvalidateVtxCache(); + GXInvalidateTexAll(); + Blit_RAD_3D_image(Image, arg0, arg1, arg2, arg3, 1.0f); +} + +static void xDrawLine2D_LocaliFMVVersion(float, float, float, float); +static void Show_frame() +{ + RwRGBA color = { 0 }; + RwCamera* cam = iCameraCreate(640, 480, FALSE); + RwCameraClear(cam, &color, rwCAMERACLEARIMAGE); + + RwCameraBeginUpdate(cam); + Width_scale = 640 / Bink->unk_0; + Height_scale = 480 / Bink->unk_4; + xDrawLine2D_LocaliFMVVersion(0.0f, 0.0f, 0.0f, 0.0f); + DrawFrame(0.0f, 0.0f, Width_scale, Height_scale); + RwCameraEndUpdate(cam); + RwCameraShowRaster(cam, NULL, 0); + + iCameraDestroy(cam); +} + +static void* arammalloc(size_t size) +{ + return (void*)ARAlloc(size); +} + +// Something weird is going on here... +static void aramfree(void* mem) +{ + u32 vol; + ARFree(&vol); +} + +static void PlayFMV(char* fname, u32 buttons, F32 time) +{ + GXCullMode cull_mode; + GXGetCullMode(&cull_mode); + iFMV::InitDisplay(_RwDlRenderMode); + iPadStopRumble(globals.pad0); + RADSetAudioMemory(arammalloc, aramfree); + RADSetMemory(iFMVmalloc, iFMVfree); + Setup_surface_array(); + + for (char* c = fname; *c != NULL; c++) + { + if (*c == '\\') + { + *c = '/'; + } + } + + tag_xFile file; + DVDFileInfo* pfinfo = &file.ps.fileInfo; + do + { + if (iTRCDisk::IsDiskIDed()) + { + Bink = BinkOpen(fname, NULL); + if (Bink == NULL) + { + BinkGetError(); + } + } + if (iTRCDisk::CheckDVDAndResetState() != 0) + { + break; + } + if (Bink == NULL) + { + iFileOpen(fname, 0, &file); + DVDSeekAsyncPrio(pfinfo, 0, NULL, 2); + if (iTRCDisk::CheckDVDAndResetState()) + { + DVDCancel(&pfinfo->cb); + break; + } + else + { + DVDCancel(&pfinfo->cb); + } + } + } while (Bink == NULL); + + if (Bink != NULL) + { + if (Bink->unk_f0 != 0) + { + for (ip = 0; ip <= Bink->unk_f0; ++ip) + { + vol = gSnd.categoryVolFader[SND_CAT_CUTSCENE]; + vol = vol * vol; + vol = vol * 32768.0f; + BinkSetVolume(Bink, ip, vol); + } + } + + Image = Open_RAD_3D_image(NULL, Bink->unk_0, Bink->unk_4, fuckingSurfaceType); + if (Image != NULL) + { + if (frame_num != 0) + { + BinkGoto(Bink, frame_num, 0); + } + oof = 0; + + do + { + if (iTRCDisk::CheckDVDAndResetState()) + { + goto superbreak; + } + if (BinkWait(Bink) == 0) + { + Decompress_frame(Bink, Image, 1); + Show_frame(); + BinkNextFrame(Bink); + } + else if (Paused) + { + Show_frame(); + } + xPadUpdate(globals.currentActivePad, 0.0f); + + F32 t = (float)Bink->unk_c / (Bink->unk_14 / Bink->unk_18); + if (buttons && t >= time && globals.pad0->pressed & buttons) + { + frame_num = -1; + goto superbreak; + } + } while (Bink->unk_c < Bink->unk_8 - 1); + frame_num = -1; + } + superbreak: + if (frame_num != -1) + { + frame_num = Bink->unk_c; + } + Close_RAD_3D_image(Image); + Image = NULL; + BinkClose(Bink); + Bink = NULL; + } + + GXSetCullMode(cull_mode); + iVSync(); + xPadUpdate(globals.currentActivePad, 0.0f); +} + +void iFMV::InitDisplay(GXRenderModeObj* InRenderMode) +{ + GXColor clr = { 0 }; + Mtx44 mtx; + Mtx idt; + mRenderMode = InRenderMode; + void** xfb = &mXFBs[1]; + RwGameCubeGetXFBs(&mXFBs[0], &mXFBs[1]); + mCurrentFrameBuffer = *xfb; + + InitGX(); + InitVI(); + + GXSetCopyClear(clr, GX_MAX_Z24); + C_MTXOrtho(mtx, 0.0f, mRenderMode->efbHeight, 0.0f, mRenderMode->fbWidth, 0.0f, -100.0f); + GXSetProjection(mtx, GX_ORTHOGRAPHIC); + PSMTXIdentity(idt); + GXLoadPosMtxImm(idt, 0); + GXSetCurrentMtx(0); + + GXSetZMode(GX_TRUE, GX_ALWAYS, GX_TRUE); + GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR); + + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_NRM_NBT, GX_S16, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_NRM_NBT, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_NRM_NBT, GX_RGBA6, 0); + + GXSetNumTexGens(1); + GXSetNumChans(1); + GXSetNumTevStages(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); + GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + mFirstFrame = 1; +} + +void iFMV::InitGX() +{ + GXSetViewport(0, 0, mRenderMode->fbWidth, mRenderMode->efbHeight, 0.0f, 1.0f); + GXSetScissor(0, 0, mRenderMode->fbWidth, mRenderMode->efbHeight); + f32 yScaleFactor = GXGetYScaleFactor(mRenderMode->efbHeight, mRenderMode->xfbHeight); + u16 r = GXSetDispCopyYScale(yScaleFactor); + + GXSetDispCopySrc(0, 0, mRenderMode->fbWidth, mRenderMode->efbHeight); + GXSetDispCopyDst(mRenderMode->fbWidth, r); + GXSetCopyFilter(mRenderMode->aa, mRenderMode->sample_pattern, GX_TRUE, mRenderMode->vfilter); + + if (mRenderMode->aa) + { + GXSetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); + } + else + { + GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + } + + GXCopyDisp(mCurrentFrameBuffer, GX_TRUE); + GXSetDispCopyGamma(GX_GM_1_0); + GXSetCullMode(GX_CULL_NONE); +} + +void iFMV::InitVI() +{ + VISetNextFrameBuffer(iFMV::mXFBs[0]); + mCurrentFrameBuffer = mXFBs[1]; + VIFlush(); + VIWaitForRetrace(); + if (mRenderMode->viTVmode & 1) + { + VIWaitForRetrace(); + } +} + +void iFMV::Suspend() +{ +} + +void iFMV::Resume() +{ +} + +static void xDrawLine2D_LocaliFMVVersion(F32 arg0, F32 arg1, F32 arg2, F32 arg3) +{ + RwRGBA color = { -1, -1, -1, -1 }; + + F32 nearz = RwIm2DGetNearScreenZ(); + void* texraster_state; + RwRenderStateGet(rwRENDERSTATETEXTURERASTER, &texraster_state); + void* vtx_alpha_state; + RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vtx_alpha_state); + RwIm2DVertex verts[2]; + + // RwIm2DVertexSetRealRGBA + + RwIm2DVertexSetScreenX(&verts[0], arg0); + RwIm2DVertexSetScreenY(&verts[0], arg1); + RwIm2DVertexSetScreenZ(&verts[0], nearz); + RwIm2DVertexSetIntRGBA(&verts[0], color.red, color.green, color.blue, color.alpha); + + RwIm2DVertexSetScreenX(&verts[1], arg2); + RwIm2DVertexSetScreenY(&verts[1], arg3); + RwIm2DVertexSetScreenZ(&verts[1], nearz); + RwIm2DVertexSetIntRGBA(&verts[1], color.red, color.green, color.blue, color.alpha); + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, NULL); + + // { arg2, arg3, nearz, -1 }; + RwIm2DRenderLine(verts, 2, 0, 1); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, texraster_state); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, vtx_alpha_state); +} diff --git a/src/SB/Core/gc/iFMV.h b/src/SB/Core/gc/iFMV.h new file mode 100644 index 0000000..5d0a57c --- /dev/null +++ b/src/SB/Core/gc/iFMV.h @@ -0,0 +1,29 @@ +#ifndef IFMV_H +#define IFMV_H + +#include +#include +#include + +struct _GXRenderModeObj; + +struct iFMV +{ + static void* mXFBs[2]; + static void* mCurrentFrameBuffer; + static _GXRenderModeObj* mRenderMode; + static U8 mFirstFrame; + + static void InitDisplay(_GXRenderModeObj*); + static void InitGX(); + static void InitVI(); + static void Suspend(); + static void Resume(); +}; + +void* iFMVmalloc(size_t size); +void iFMVfree(void* mem); +U32 iFMVPlay(char* filename, U32 buttons, F32 time, bool skippable, bool lockController); +static void Setup_surface_array(); +void Decompress_frame(HBINK bnk, HRAD3DIMAGE rad_image, long flags); +#endif diff --git a/src/SB/Core/gc/iFX.cpp b/src/SB/Core/gc/iFX.cpp new file mode 100644 index 0000000..64e1f70 --- /dev/null +++ b/src/SB/Core/gc/iFX.cpp @@ -0,0 +1,3 @@ +#include "iFX.h" + +#include diff --git a/src/SB/Core/gc/iFX.h b/src/SB/Core/gc/iFX.h new file mode 100644 index 0000000..3e81ed1 --- /dev/null +++ b/src/SB/Core/gc/iFX.h @@ -0,0 +1,4 @@ +#ifndef IFX_H +#define IFX_H + +#endif \ No newline at end of file diff --git a/src/SB/Core/gc/iFile.cpp b/src/SB/Core/gc/iFile.cpp new file mode 100644 index 0000000..c774766 --- /dev/null +++ b/src/SB/Core/gc/iFile.cpp @@ -0,0 +1,351 @@ +#include "iFile.h" + +#include "iTRC.h" + +#include "xFile.h" +#include "xMath.h" +#include "xTRC.h" + +#include + +struct file_queue_entry +{ + tag_xFile* file; + void* buf; + U32 size; + U32 offset; + IFILE_READSECTOR_STATUS stat; + void (*callback)(tag_xFile* file); + U32 asynckey; +}; + +extern file_queue_entry file_queue[4]; + +static U32 tbuffer[1024 + 8]; +static U32* buffer32; +volatile U32 iFileSyncAsyncReadActive; + +void iFileInit() +{ + buffer32 = (U32*)OSRoundUp32B(tbuffer); +} + +void iFileExit() +{ +} + +U32* iFileLoad(char* name, U32* buffer, U32* size) +{ + char path[128]; + tag_xFile file; + S32 fileSize, alignedSize; + + iFileFullPath(name, path); + iFileOpen(name, IFILE_OPEN_ABSPATH, &file); + + fileSize = iFileGetSize(&file); + + if (!buffer) + { + buffer = (U32*)OSAlloc(OSRoundUp32B(fileSize)); + } + + alignedSize = OSRoundUp32B(fileSize); + + iFileRead(&file, buffer, alignedSize); + + if (size) + { + *size = alignedSize; + } + + iFileClose(&file); + + return buffer; +} + +U32 iFileOpen(const char* name, S32 flags, tag_xFile* file) +{ + tag_iFile* ps = &file->ps; + + if (flags & IFILE_OPEN_ABSPATH) + { + strcpy(ps->path, name); + } + else + { + iFileFullPath(name, ps->path); + } + + ps->entrynum = DVDConvertPathToEntrynum(ps->path); + + if (ps->entrynum == -1) + { + return 1; + } + + if (!DVDFastOpen(ps->entrynum, &ps->fileInfo)) + { + ps->entrynum = -1; + return 1; + } + + ps->unkC4 = 0; + ps->flags = 0x1; + + iFileSeek(file, 0, IFILE_SEEK_SET); + + return 0; +} + +S32 iFileSeek(tag_xFile* file, S32 offset, S32 whence) +{ + tag_iFile* ps = &file->ps; + S32 position, new_pos; + + switch (whence) + { + case IFILE_SEEK_SET: + { + new_pos = offset; + break; + } + case IFILE_SEEK_CUR: + { + if (DVDGetCommandBlockStatus(&ps->fileInfo.cb) == DVD_STATE_BUSY) + { + return -1; + } + + new_pos = offset + ps->offset; + break; + } + case IFILE_SEEK_END: + { + new_pos = ps->fileInfo.length - offset; + + if (new_pos < 0) + { + new_pos = 0; + } + + break; + } + default: + { + new_pos = offset; + break; + } + } + + ps->offset = new_pos; + + return ps->offset; +} + +static void ifilereadCB(tag_xFile* file) +{ + iFileSyncAsyncReadActive = 0; +} + +U32 iFileRead(tag_xFile* file, void* buf, U32 size) +{ + tag_iFile* ps = &file->ps; + + iFileSeek(file, ps->offset, IFILE_SEEK_SET); + + iFileSyncAsyncReadActive = 1; + + iFileReadAsync(file, buf, size, ifilereadCB, 0); + + while (iFileSyncAsyncReadActive) + { + iTRCDisk::CheckDVDAndResetState(); + } + + return size; +} + +static void async_cb(s32 result, DVDFileInfo* fileInfo) +{ + file_queue_entry* entry = &file_queue[(S32)fileInfo->cb.userData]; + s32 r7 = DVD_RESULT_FATAL_ERROR; + + switch (result) + { + case DVD_RESULT_FATAL_ERROR: + { + xTRCDisk(TRC_DiskFatal); + return; + } + case DVD_RESULT_GOOD: + case DVD_RESULT_IGNORED: + { + if (result >= DVD_RESULT_GOOD) + { + r7 = result; + } + + break; + } + } + + if (r7 < DVD_RESULT_GOOD) + { + entry->stat = IFILE_RDSTAT_FAIL; + + if (entry->callback) + { + entry->callback(entry->file); + } + } + else if (r7 + entry->offset >= entry->size || + r7 + entry->offset + entry->file->ps.offset >= entry->file->ps.fileInfo.length) + { + entry->stat = IFILE_RDSTAT_DONE; + entry->offset = entry->size; + + if (entry->callback) + { + entry->callback(entry->file); + } + + entry->file->ps.asynckey = -1; + } + else + { + entry->offset += r7; + entry->stat = IFILE_RDSTAT_INPROG; + + s32 length; + if ((entry->size - entry->offset < 0x8000)) + { + length = ALIGN(entry->size - entry->offset, 4); + } + else + { + length = 0x10000 - 0x8000; + } + + if (length + entry->offset + entry->file->ps.offset > entry->file->ps.fileInfo.length) + { + // length = OSRoundUp32B(entry->file->ps.fileInfo.length - entry->file->ps.offset - + // entry->offset); + length = entry->file->ps.fileInfo.length; + length -= entry->file->ps.offset; + length -= entry->offset; + length = length + 32 - 1; + length = length & ~(32 - 1); + } + + void* addr = (void*)((U32)entry->buf + entry->offset); + DVDReadAsync(&entry->file->ps.fileInfo, addr, length, + entry->file->ps.offset + entry->offset, async_cb); + } +} + +S32 iFileReadAsync(tag_xFile* file, void* buf, U32 aSize, void (*callback)(tag_xFile*), + S32 priority) +{ + static S32 fopcount = 1; + tag_iFile* ps = &file->ps; + S32 i; + + for (i = 0; i < 4; i++) + { + if (file_queue[i].stat != IFILE_RDSTAT_QUEUED && file_queue[i].stat != IFILE_RDSTAT_INPROG) + { + S32 id = fopcount++ << 2; + S32 asynckey = id + i; + + file_queue[i].file = file; + file_queue[i].buf = buf; + file_queue[i].size = aSize; + file_queue[i].offset = 0; + file_queue[i].stat = IFILE_RDSTAT_QUEUED; + file_queue[i].callback = callback; + file_queue[i].asynckey = asynckey; + + aSize = (aSize < 32) ? ALIGN(aSize, 4) : 32; + + ps->fileInfo.cb.userData = (void*)i; + + DVDReadAsync(&ps->fileInfo, buf, aSize, ps->offset, async_cb); + + ps->asynckey = asynckey; + + return id + i; + } + } + + return -1; +} + +IFILE_READSECTOR_STATUS iFileReadAsyncStatus(S32 key, S32* amtToFar) +{ + if (key != file_queue[key & 0x3].asynckey) + { + return IFILE_RDSTAT_EXPIRED; + } + + if (amtToFar) + { + *amtToFar = file_queue[key & 0x3].offset; + } + + return file_queue[key & 0x3].stat; +} + +U32 iFileClose(tag_xFile* file) +{ + tag_iFile* ps = &file->ps; + S32 ret; + + ret = DVDClose(&file->ps.fileInfo); + ret = DVDClose(&file->ps.fileInfo); + + if (!ret) + { + return 1; + } + + ps->flags = 0; + return 0; +} + +U32 iFileGetSize(tag_xFile* file) +{ + return file->ps.fileInfo.length; +} + +void iFileReadStop() +{ + DVDCancelAllAsync(NULL); +} + +void iFileFullPath(const char* relname, char* fullname) +{ + strcpy(fullname, relname); +} + +void iFileSetPath(char* path) +{ +} + +U32 iFileFind(const char* name, tag_xFile* file) +{ + return iFileOpen(name, 0, file); +} + +void iFileGetInfo(tag_xFile* file, U32* addr, U32* length) +{ + if (addr) + { + *addr = file->ps.fileInfo.startAddr; + } + + if (length) + { + *length = file->ps.fileInfo.length; + } +} diff --git a/src/SB/Core/gc/iFile.h b/src/SB/Core/gc/iFile.h new file mode 100644 index 0000000..3958f7f --- /dev/null +++ b/src/SB/Core/gc/iFile.h @@ -0,0 +1,71 @@ +#ifndef IFILE_H +#define IFILE_H + +#include +#include + +enum IFILE_READSECTOR_STATUS +{ + IFILE_RDSTAT_NOOP, + IFILE_RDSTAT_INPROG, + IFILE_RDSTAT_DONE, + IFILE_RDSTAT_FAIL, + IFILE_RDSTAT_QUEUED, + IFILE_RDSTAT_EXPIRED +}; + +#ifdef GAMECUBE +struct tag_iFile +{ + U32 flags; + char path[128]; + S32 entrynum; + DVDFileInfo fileInfo; + S32 unkC4; + S32 asynckey; + S32 unknown[7]; + S32 unkE8; + S32 offset; +}; +#else +#ifdef PS2 +struct tag_iFile +{ + U32 flags; + char path[128]; + S32 fd; + S32 offset; + S32 length; +}; +#endif +#endif + +#define IFILE_OPEN_READ 0x1 +#define IFILE_OPEN_WRITE 0x2 +#define IFILE_OPEN_ABSPATH 0x4 + +#define IFILE_SEEK_SET 0 +#define IFILE_SEEK_CUR 1 +#define IFILE_SEEK_END 2 + +struct tag_xFile; + +void iFileInit(); +void iFileExit(); +U32* iFileLoad(char* name, U32* buffer, U32* size); +U32 iFileOpen(const char* name, S32 flags, tag_xFile* file); +S32 iFileSeek(tag_xFile* file, S32 offset, S32 whence); +U32 iFileRead(tag_xFile* file, void* buf, U32 size); +S32 iFileReadAsync(tag_xFile* file, void* buf, U32 aSize, void (*callback)(tag_xFile*), + S32 priority); +IFILE_READSECTOR_STATUS iFileReadAsyncStatus(S32 key, S32* amtToFar); +U32 iFileClose(tag_xFile* file); +U32 iFileGetSize(tag_xFile* file); +void iFileReadStop(); +void iFileFullPath(const char* relname, char* fullname); +void iFileSetPath(char* path); +U32 iFileFind(const char* name, tag_xFile* file); +void iFileGetInfo(tag_xFile* file, U32* addr, U32* length); +void iFileAsyncService(); + +#endif diff --git a/src/SB/Core/gc/iLight.cpp b/src/SB/Core/gc/iLight.cpp new file mode 100644 index 0000000..92a8c18 --- /dev/null +++ b/src/SB/Core/gc/iLight.cpp @@ -0,0 +1,156 @@ +#include "iLight.h" + +RpWorld* gLightWorld; + +void iLightInit(RpWorld* world) +{ + gLightWorld = world; +} + +iLight* iLightCreate(iLight* light, U32 type) +{ + RwFrame* frame; + + switch (type) + { + case ILIGHT_TYPE_POINT: + light->hw = RpLightCreate(rpLIGHTPOINT); + break; + case ILIGHT_TYPE_SPOT: + light->hw = RpLightCreate(rpLIGHTSPOT); + break; + case ILIGHT_TYPE_SPOTSOFT: + light->hw = RpLightCreate(rpLIGHTSPOTSOFT); + break; + default: + return NULL; + } + + if (!light->hw) + { + return NULL; + } + + frame = RwFrameCreate(); + + if (!frame) + { + RpLightDestroy(light->hw); + return NULL; + } + + RpLightSetFlags(light->hw, rpLIGHTLIGHTATOMICS); + RpLightSetFrame(light->hw, frame); + + RwFrameUpdateObjects(frame); + + light->type = type; + light->sph.center.x = 0.0f; + light->sph.center.y = 0.0f; + light->sph.center.z = 0.0f; + light->sph.r = 0.0f; + light->color.r = 1.0f; + light->color.g = 1.0f; + light->color.b = 1.0f; + light->color.a = 1.0f; + light->dir.x = 0.0f; + light->dir.y = 0.0f; + light->dir.z = 1.0f; + light->coneangle = 0.0f; + + return light; +} + +void iLightModify(iLight* light, U32 flags) +{ + if (flags & 0x5) + { + RwFrame* frame = RpLightGetFrame(light->hw); + RwMatrix temp; + + *(xVec3*)RwMatrixGetRight(&temp) = g_O3; + *(xVec3*)RwMatrixGetUp(&temp) = g_O3; + *(xVec3*)RwMatrixGetAt(&temp) = light->dir; + *(xVec3*)RwMatrixGetPos(&temp) = light->sph.center; + + RwFrameTransform(frame, &temp, rwCOMBINEREPLACE); + } + + if (flags & 0x2) + { + RpLightSetRadius(light->hw, light->sph.r); + } + + if (flags & 0x8) + { + RpLightSetColor(light->hw, (RwRGBAReal*)&light->color); + } + + if (flags & 0x10) + { + if (light->type == ILIGHT_TYPE_SPOT || light->type == ILIGHT_TYPE_SPOTSOFT) + { + RpLightSetConeAngle(light->hw, light->coneangle); + } + } +} + +void iLightSetColor(iLight* light, _xFColor* col) +{ + RpLightSetColor(light->hw, (RwRGBAReal*)col); +} + +void iLightSetPos(iLight* light, xVec3* pos) +{ + RwFrame* f = RpLightGetFrame(light->hw); + RwMatrix* m = RwFrameGetMatrix(f); + + RwMatrixGetPos(m)->x = pos->x; + RwMatrixGetPos(m)->y = pos->y; + RwMatrixGetPos(m)->z = pos->z; + + RwMatrixUpdate(m); + + RwFrameUpdateObjects(f); +} + +void iLightDestroy(iLight* light) +{ + RwFrame* frame; + + light->type = ILIGHT_TYPE_NONE; + + _rwFrameSyncDirty(); + + frame = RpLightGetFrame(light->hw); + + if (frame) + { + RwFrameDestroy(frame); + } + + RpLightDestroy(light->hw); +} + +void iLightEnv(iLight* light, S32 env) +{ + RwUInt32 flags = 0; + + switch (env) + { + case ILIGHT_ENV_NONE: + flags = 0; + break; + case ILIGHT_ENV_ATOMIC: + flags = rpLIGHTLIGHTWORLD; + break; + case ILIGHT_ENV_WORLD: + flags = rpLIGHTLIGHTATOMICS; + break; + case ILIGHT_ENV_ATOMICWORLD: + flags = rpLIGHTLIGHTATOMICS | rpLIGHTLIGHTWORLD; + break; + } + + RpLightSetFlags(light->hw, flags); +} diff --git a/src/SB/Core/gc/iLight.h b/src/SB/Core/gc/iLight.h new file mode 100644 index 0000000..d19b54d --- /dev/null +++ b/src/SB/Core/gc/iLight.h @@ -0,0 +1,49 @@ +#ifndef ILIGHT_H +#define ILIGHT_H + +#include "xFColor.h" +#include "xMath3.h" + +#include +#include + +#define ILIGHT_TYPE_NONE 0 +#define ILIGHT_TYPE_POINT 1 +#define ILIGHT_TYPE_SPOT 2 +#define ILIGHT_TYPE_SPOTSOFT 3 + +#define ILIGHT_ENV_NONE 0 +#define ILIGHT_ENV_ATOMIC 1 +#define ILIGHT_ENV_WORLD 2 +#define ILIGHT_ENV_ATOMICWORLD 3 + +// Size: 0x3C +struct iLight +{ + // 0x0 + U32 type; + RpLight* hw; + + //0x8 + xSphere sph; + F32 radius_sq; + + //0x1C + _xFColor color; + + //0x2C + xVec3 dir; + F32 coneangle; +}; + +extern RpWorld* gLightWorld; + +void iLightInit(RpWorld* world); +iLight* iLightCreate(iLight* light, U32 type); +void iLightModify(iLight* light, U32 flags); +void iLightSetColor(iLight* light, _xFColor* col); +void iLightSetPos(iLight* light, xVec3* pos); +void iLightDestroy(iLight* light); +void iLightEnv(iLight* light, S32 env); + +#endif diff --git a/src/SB/Core/gc/iMath.cpp b/src/SB/Core/gc/iMath.cpp new file mode 100644 index 0000000..35f6ff6 --- /dev/null +++ b/src/SB/Core/gc/iMath.cpp @@ -0,0 +1,39 @@ +#include "iMath.h" + +#include + +F32 isin(F32 x) +{ + return std::sinf(x); +} + +#ifndef INLINE +float std::sinf(float x) +{ + return (float)sin((double)x); +} +#endif + +F32 icos(F32 x) +{ + return std::cosf(x); +} + +#ifndef INLINE +float std::cosf(float x) +{ + return (float)cos((double)x); +} +#endif + +F32 itan(F32 x) +{ + return std::tanf(x); +} + +#ifndef INLINE +float std::tanf(float x) +{ + return (float)tan((double)x); +} +#endif diff --git a/src/SB/Core/gc/iMath.h b/src/SB/Core/gc/iMath.h new file mode 100644 index 0000000..d90af35 --- /dev/null +++ b/src/SB/Core/gc/iMath.h @@ -0,0 +1,17 @@ +#ifndef IMATH_H +#define IMATH_H + +#include +#include + +#ifdef __MWERKS__ +#define iabs(x) (float)(__fabs((float)x)) +#else +#define iabs(x) fabsf(x) +#endif + +F32 isin(F32 x); +F32 icos(F32 x); +F32 itan(F32 x); + +#endif diff --git a/src/SB/Core/gc/iMath3.cpp b/src/SB/Core/gc/iMath3.cpp new file mode 100644 index 0000000..0539117 --- /dev/null +++ b/src/SB/Core/gc/iMath3.cpp @@ -0,0 +1,751 @@ +#include "iMath3.h" + +#include "xMath.h" +#include "xMath2.h" +#include "xMathInlines.h" + +#include + +extern F32 _555_1; // 0.5f +extern F32 _557_1; // 0.0f +extern F32 _558_3; // 1.0f +extern F32 _560_2; // 0.00001f +extern F32 _607; // 2.0f +extern F32 _608_0; // -1.0f +extern F32 _1060; // -9.9999997e37f +extern F32 _1061; // 9.9999997e37f +extern F32 _1062; // -0.5f + +void iMath3Init() +{ +} + +void iSphereIsectVec(const xSphere* s, const xVec3* v, xIsect* isx) +{ + xVec3Sub(&isx->norm, v, &s->center); + + isx->dist = xVec3Length(&isx->norm); + isx->penned = isx->dist - s->r; +} + +void iSphereIsectRay(const xSphere* s, const xRay3* r, xIsect* isx) +{ + F32 t_in, t_out; + U32 num; + + if (!(r->flags & 0x400)) + { + ((xRay3*)r)->min_t = _557_1; // wait, that's illegal + } + + if (!(r->flags & 0x800)) + { + ((xRay3*)r)->max_t = _558_3; + } + + xVec3Sub(&isx->norm, &r->origin, &s->center); + + num = xMathSolveQuadratic(xVec3Dot(&r->dir, &r->dir), _607 * xVec3Dot(&isx->norm, &r->dir), + xVec3Dot(&isx->norm, &isx->norm) - s->r * s->r, &t_in, &t_out); + + if (num == 0) + { + isx->penned = _558_3; + isx->contained = _558_3; + } + else if (num == 1) + { + if (t_in < r->min_t || t_in > r->max_t) + { + isx->dist = t_in; + isx->penned = _558_3; + isx->contained = _558_3; + } + else + { + isx->dist = t_in; + isx->penned = _608_0; + isx->contained = _558_3; + } + } + else if (t_in < r->min_t) + { + if (t_out < r->min_t) + { + isx->dist = t_out; + isx->penned = _558_3; + isx->contained = _558_3; + } + else + { + isx->dist = t_out; + isx->penned = _608_0; + isx->contained = _608_0; + } + } + else + { + if (t_in <= r->max_t) + { + isx->dist = t_in; + isx->penned = _608_0; + isx->contained = _558_3; + } + else + { + isx->dist = t_in; + isx->penned = _558_3; + isx->contained = _558_3; + } + } +} + +void iSphereIsectSphere(const xSphere* s, const xSphere* p, xIsect* isx) +{ + xVec3Sub(&isx->norm, &p->center, &s->center); + + isx->dist = xVec3Length(&isx->norm); + isx->penned = isx->dist - p->r - s->r; + isx->contained = isx->dist - s->r; +} + +void iSphereInitBoundVec(xSphere* s, const xVec3* v) +{ + xVec3Copy(&s->center, v); + + s->r = _560_2; +} + +void iSphereBoundVec(xSphere* o, const xSphere* s, const xVec3* v) +{ + F32 scale; + xSphere temp; + xSphere* tp; + U32 usetemp; + xIsect isx; + + usetemp = (o == s); + + iSphereIsectVec(s, v, &isx); + + if (isx.penned <= _557_1) + { + if (!usetemp) + { + memcpy(o, s, sizeof(xSphere)); + } + } + else + { + if (usetemp) + { + tp = &temp; + } + else + { + tp = o; + } + + xVec3Copy(&tp->center, &isx.norm); + + scale = (isx.dist - s->r) / (_607 * isx.dist); + + xVec3SMul(&tp->center, &tp->center, scale); + xVec3Add(&tp->center, &tp->center, &s->center); + + tp->r = _555_1 * (isx.dist + s->r); + + if (usetemp) + { + memcpy(o, tp, sizeof(xSphere)); + } + } +} + +void iCylinderIsectVec(const xCylinder* c, const xVec3* v, xIsect* isx) +{ + F32 b = c->center.y + c->h; + + if (v->y >= c->center.y - c->h && v->y <= b && + xVec2Dist(c->center.x, c->center.z, v->x, v->z) <= c->r) + { + isx->penned = _608_0; + } + else + { + isx->penned = _558_3; + } +} + +void iBoxVecDist(const xBox* box, const xVec3* v, xIsect* isx) +{ + if (v->x < box->lower.x) + { + if (v->y < box->lower.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x00000000; + isx->flags |= 0x80000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = _557_1; + isx->flags = isx->flags & ~0x1F000000 | 0x01000000; + isx->flags |= 0x40000000; + } + else + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x02000000; + isx->flags |= 0x80000000; + } + } + else if (v->y <= box->upper.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = _557_1; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x03000000; + isx->flags |= 0x40000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = _557_1; + isx->norm.z = _557_1; + isx->flags = isx->flags & ~0x1F000000 | 0x04000000; + isx->flags |= 0x20000000; + } + else + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = _557_1; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x05000000; + isx->flags |= 0x40000000; + } + } + else + { + if (v->z < box->lower.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x06000000; + isx->flags |= 0x80000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = _557_1; + isx->flags = isx->flags & ~0x1F000000 | 0x07000000; + isx->flags |= 0x40000000; + } + else + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x08000000; + isx->flags |= 0x80000000; + } + } + } + else if (v->x <= box->upper.x) + { + if (v->y < box->lower.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = _557_1; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x09000000; + isx->flags |= 0x40000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = _557_1; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = _557_1; + isx->flags = isx->flags & ~0x1F000000 | 0x0A000000; + isx->flags |= 0x20000000; + } + else + { + isx->norm.x = _557_1; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x0B000000; + isx->flags |= 0x40000000; + } + } + else if (v->y <= box->upper.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = _557_1; + isx->norm.y = _557_1; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x0C000000; + isx->flags |= 0x20000000; + } + else if (v->z <= box->upper.z) + { + } + else + { + isx->norm.x = _557_1; + isx->norm.y = _557_1; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x0E000000; + isx->flags |= 0x20000000; + } + } + else + { + if (v->z < box->lower.z) + { + isx->norm.x = _557_1; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x0F000000; + isx->flags |= 0x40000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = _557_1; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = _557_1; + isx->flags = isx->flags & ~0x1F000000 | 0x10000000; + isx->flags |= 0x20000000; + } + else + { + isx->norm.x = _557_1; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x11000000; + isx->flags |= 0x40000000; + } + } + } + else + { + if (v->y < box->lower.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x12000000; + isx->flags |= 0x80000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = _557_1; + isx->flags = isx->flags & ~0x1F000000 | 0x13000000; + isx->flags |= 0x40000000; + } + else + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x14000000; + isx->flags |= 0x80000000; + } + } + else if (v->y <= box->upper.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = _557_1; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x15000000; + isx->flags |= 0x40000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = _557_1; + isx->norm.z = _557_1; + isx->flags = isx->flags & ~0x1F000000 | 0x16000000; + isx->flags |= 0x20000000; + } + else + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = _557_1; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x17000000; + isx->flags |= 0x40000000; + } + } + else + { + if (v->z < box->lower.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x18000000; + isx->flags |= 0x80000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = _557_1; + isx->flags = isx->flags & ~0x1F000000 | 0x19000000; + isx->flags |= 0x40000000; + } + else + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x1A000000; + isx->flags |= 0x80000000; + } + } + } + + isx->dist = xVec3Length(&isx->norm); +} + +void iBoxIsectVec(const xBox* b, const xVec3* v, xIsect* isx) +{ + if (v->x >= b->lower.x && v->x <= b->upper.x && v->y >= b->lower.y && v->y <= b->upper.y && + v->z >= b->lower.z && v->z <= b->upper.z) + { + isx->penned = _608_0; + } + else + { + isx->penned = _558_3; + } +} + +static U32 ClipPlane(F32 denom, F32 numer, F32* t_in, F32* t_out) +{ + if (denom > _557_1) + { + if (numer > denom * (*t_out)) + { + return 0; + } + + if (numer > denom * (*t_in)) + { + *t_in = numer / denom; + } + + return 1; + } + else if (denom < _557_1) + { + if (numer > denom * (*t_in)) + { + return 0; + } + + if (numer > denom * (*t_out)) + { + *t_out = numer / denom; + } + + return 1; + } + + return (numer <= _557_1); +} + +static U32 ClipBox(const xVec3* r3, const xVec3* r4, const xVec3* r5, F32* t_in, F32* t_out) +{ + return (ClipPlane(r5->x, -r4->x - r3->x, t_in, t_out) && + ClipPlane(-r5->x, r4->x - r3->x, t_in, t_out) && + ClipPlane(r5->y, -r4->y - r3->y, t_in, t_out) && + ClipPlane(-r5->y, r4->y - r3->y, t_in, t_out) && + ClipPlane(r5->z, -r4->z - r3->z, t_in, t_out) && + ClipPlane(-r5->z, r4->z - r3->z, t_in, t_out)); +} + +void iBoxIsectRay(const xBox* b, const xRay3* r, xIsect* isx) +{ + xVec3 var_14, var_20; + F32 t_in, t_out; + + if (!(r->flags & 0x400)) + { + ((xRay3*)r)->min_t = _557_1; // wait, that's illegal + } + + if (!(r->flags & 0x800)) + { + ((xRay3*)r)->max_t = _558_3; + } + + // non-matching: incorrect instruction order + + t_in = _1060; + t_out = _1061; + + var_14.x = b->upper.x - b->lower.x; + var_14.y = b->upper.y - b->lower.y; + var_14.z = b->upper.z - b->lower.z; + + var_20.x = b->lower.x + b->upper.x; + var_20.y = b->lower.y + b->upper.y; + + var_14.x *= _555_1; + var_14.y *= _555_1; + var_14.z *= _555_1; + + var_20.z = b->lower.z + b->upper.z; + + var_20.x *= _1062; + var_20.y *= _1062; + var_20.z *= _1062; + + var_20.x += r->origin.x; + var_20.y += r->origin.y; + var_20.z += r->origin.z; + + if (ClipBox(&var_14, &var_20, &r->dir, &t_in, &t_out)) + { + if (t_in < r->min_t) + { + if (t_out < r->min_t) + { + isx->dist = t_out; + isx->penned = _558_3; + isx->contained = _558_3; + } + else + { + isx->dist = t_out; + isx->penned = _608_0; + isx->contained = _608_0; + } + } + else + { + if (t_in <= r->max_t) + { + isx->dist = t_in; + isx->penned = _608_0; + isx->contained = _558_3; + } + else + { + isx->dist = t_in; + isx->penned = _558_3; + isx->contained = _558_3; + } + } + } + else + { + isx->penned = _558_3; + isx->contained = _558_3; + } +} + +void iBoxIsectSphere(const xBox* box, const xSphere* p, xIsect* isx) +{ + U32 xcode, ycode, zcode; + + // non-matching: (p->center.x + p->r) computed inside if statement + + if (p->center.x - p->r < box->lower.x) + { + if (p->center.x + p->r < box->lower.x) + { + xcode = 2; + } + else if (p->center.x + p->r > box->upper.x) + { + xcode = 0; + } + else + { + xcode = 1; + } + } + else + { + if (p->center.x - p->r > box->upper.x) + { + xcode = 5; + } + else if (p->center.x + p->r > box->upper.x) + { + xcode = 4; + } + else + { + xcode = 3; + } + } + + // non-matching: missing division instructions + + if (xcode / 3 == 2) + { + isx->penned = _558_3; + return; + } + + // non-matching: (p->center.y + p->r) computed inside if statement + + if (p->center.y - p->r < box->lower.y) + { + if (p->center.y + p->r < box->lower.y) + { + ycode = 2; + } + else if (p->center.y + p->r > box->upper.y) + { + ycode = 0; + } + else + { + ycode = 1; + } + } + else + { + if (p->center.y - p->r > box->upper.y) + { + ycode = 5; + } + else if (p->center.y + p->r > box->upper.y) + { + ycode = 4; + } + else + { + ycode = 3; + } + } + + // non-matching: missing division instructions + + if (ycode / 3 == 2) + { + isx->penned = _558_3; + return; + } + + // non-matching: (p->center.z + p->r) computed inside if statement + + if (p->center.z - p->r < box->lower.z) + { + if (p->center.z + p->r < box->lower.z) + { + zcode = 2; + } + else if (p->center.z + p->r > box->upper.z) + { + zcode = 0; + } + else + { + zcode = 1; + } + } + else + { + if (p->center.z - p->r > box->upper.z) + { + zcode = 5; + } + else if (p->center.z + p->r > box->upper.z) + { + zcode = 4; + } + else + { + zcode = 3; + } + } + + // non-matching: missing division instructions + + if (zcode / 3 == 2) + { + isx->penned = _558_3; + return; + } + + iBoxIsectVec(box, &p->center, isx); + + if (isx->penned < _557_1) + { + xVec3 var_28; + + xVec3Add(&var_28, &box->lower, &box->upper); + xVec3SMulBy(&var_28, _555_1); + xVec3Sub(&isx->norm, &p->center, &var_28); + + isx->dist = xVec3Length(&isx->norm); + isx->contained = _608_0; + } + else + { + isx->flags = xcode | (ycode << 4) | (zcode << 8); + + iBoxVecDist(box, &p->center, isx); + + isx->penned = isx->dist - p->r; + isx->contained = _558_3; + } +} + +void iBoxInitBoundVec(xBox* b, const xVec3* v) +{ + xVec3Copy(&b->lower, v); + xVec3Copy(&b->upper, v); +} + +void iBoxBoundVec(xBox* o, const xBox* b, const xVec3* v) +{ + xVec3Init(&o->lower, MIN(v->x, b->lower.x), MIN(v->y, b->lower.y), MIN(v->z, b->lower.z)); + xVec3Init(&o->upper, MAX(v->x, b->upper.x), MAX(v->y, b->upper.y), MAX(v->z, b->upper.z)); +} + +F32 xVec2Dist(F32 x1, F32 y1, F32 x2, F32 y2) +{ + F32 x = x1 - x2; + F32 y = y1 - y2; + + return xsqrt(SQR(x) + SQR(y)); +} + +F32 xVec2Dot(const xVec2* a, const xVec2* b) +{ + return a->x * b->x + a->y * b->y; +} + +void xVec2Init(xVec2* v, F32 _x, F32 _y) +{ + v->x = _x; + v->y = _y; +} diff --git a/src/SB/Core/gc/iMath3.h b/src/SB/Core/gc/iMath3.h new file mode 100644 index 0000000..e69caf2 --- /dev/null +++ b/src/SB/Core/gc/iMath3.h @@ -0,0 +1,30 @@ +#ifndef IMATH3_H +#define IMATH3_H + +#include "xMath3.h" +#include "xIsect.h" +#include "xRay3.h" + +#include + +union xiMat4x3Union +{ + xMat4x3 xm; + RwMatrix im; +}; + +void iMath3Init(); +void iSphereIsectVec(const xSphere* s, const xVec3* v, xIsect* isx); +void iSphereIsectRay(const xSphere* s, const xRay3* r, xIsect* isx); +void iSphereIsectSphere(const xSphere* s, const xSphere* p, xIsect* isx); +void iSphereInitBoundVec(xSphere* s, const xVec3* v); +void iSphereBoundVec(xSphere* o, const xSphere* s, const xVec3* v); +void iCylinderIsectVec(const xCylinder* c, const xVec3* v, xIsect* isx); +void iBoxVecDist(const xBox* box, const xVec3* v, xIsect* isx); +void iBoxIsectVec(const xBox* b, const xVec3* v, xIsect* isx); +void iBoxIsectRay(const xBox* b, const xRay3* r, xIsect* isx); +void iBoxIsectSphere(const xBox* box, const xSphere* p, xIsect* isx); +void iBoxInitBoundVec(xBox* b, const xVec3* v); +void iBoxBoundVec(xBox* o, const xBox* b, const xVec3* v); + +#endif diff --git a/src/SB/Core/gc/iMemMgr.cpp b/src/SB/Core/gc/iMemMgr.cpp new file mode 100644 index 0000000..91665e9 --- /dev/null +++ b/src/SB/Core/gc/iMemMgr.cpp @@ -0,0 +1,55 @@ +#include "iMemMgr.h" +#include "iSystem.h" +#include "xMemMgr.h" + +#include +#include +#include + +extern xMemInfo_tag gMemInfo; +extern OSHeapHandle he; +extern OSHeapHandle hs; +extern volatile OSHeapHandle the_heap; +extern unsigned char _stack_addr[]; +extern U32 HeapSize; +extern U32 mem_top_alloc; +extern U32 mem_base_alloc; + +// Starts going wrong after the if and else statement, everything else before looks fine. +void iMemInit() +{ + OSHeapHandle hi = (OSHeapHandle)OSGetArenaHi(); + he = hi & 0xffffffe0; + hs = (OSHeapHandle)OSGetArenaLo() + 0x1f & 0xffffffe0; + the_heap = OSCreateHeap(OSInitAlloc((void*)hs, (void*)(hi & 0xffffffe0), 1), (void*)he); + OSHeapHandle currHeap = the_heap; + if (currHeap >= 0) + { + OSSetCurrentHeap(currHeap); + } + else + { + exit(-5); + } + gMemInfo.system.addr = 0; + gMemInfo.system.size = 0x100000; + gMemInfo.system.flags = 0x20; + gMemInfo.stack.addr = (U32)&_stack_addr; + gMemInfo.stack.size = 0xffff8000; + gMemInfo.stack.flags = gMemInfo.DRAM.flags = 0x820; + HeapSize = 0x384000; + gMemInfo.DRAM.addr = (U32)OSAllocFromHeap(__OSCurrHeap, 0x384000); + gMemInfo.DRAM.size = HeapSize; + gMemInfo.DRAM.flags = 0x820; + gMemInfo.SRAM.addr = 0; + gMemInfo.SRAM.size = 0x200000; + gMemInfo.SRAM.flags = 0x660; + mem_top_alloc = gMemInfo.DRAM.addr + HeapSize; + mem_base_alloc = gMemInfo.DRAM.addr; +} + +void iMemExit() +{ + free((void*)gMemInfo.DRAM.addr); + gMemInfo.DRAM.addr = 0; +} diff --git a/src/SB/Core/gc/iMemMgr.h b/src/SB/Core/gc/iMemMgr.h new file mode 100644 index 0000000..67096c6 --- /dev/null +++ b/src/SB/Core/gc/iMemMgr.h @@ -0,0 +1,9 @@ +#ifndef IMEMMGR_H +#define IMEMMGR_H + +#include + +void iMemInit(); +void iMemExit(); + +#endif \ No newline at end of file diff --git a/src/SB/Core/gc/iMix.c b/src/SB/Core/gc/iMix.c new file mode 100644 index 0000000..e69de29 diff --git a/src/SB/Core/gc/iMix.cpp b/src/SB/Core/gc/iMix.cpp new file mode 100644 index 0000000..28a8da4 --- /dev/null +++ b/src/SB/Core/gc/iMix.cpp @@ -0,0 +1,3 @@ +#include "iMix.h" + +#include diff --git a/src/SB/Core/gc/iMix.h b/src/SB/Core/gc/iMix.h new file mode 100644 index 0000000..93eaa61 --- /dev/null +++ b/src/SB/Core/gc/iMix.h @@ -0,0 +1,11 @@ +#ifndef IMIX_H +#define IMIX_H + +#include "iSnd.h" +struct _AXVPB; + +extern "C" { +void MIXUnMute(_AXVPB* p); +} + +#endif diff --git a/src/SB/Core/gc/iModel.cpp b/src/SB/Core/gc/iModel.cpp new file mode 100644 index 0000000..dd3e9b6 --- /dev/null +++ b/src/SB/Core/gc/iModel.cpp @@ -0,0 +1,7 @@ +#include "iModel.h" + +#include + +void iModelCacheAtomic(RpAtomic*) +{ +} diff --git a/src/SB/Core/gc/iModel.h b/src/SB/Core/gc/iModel.h new file mode 100644 index 0000000..b9ddb99 --- /dev/null +++ b/src/SB/Core/gc/iModel.h @@ -0,0 +1,28 @@ +#ifndef IMODEL_H +#define IMODEL_H + +#include "xMath3.h" +#include "xModel.h" + +#include +#include + +void iModelInit(); +U32 iModelNumBones(RpAtomic* model); +S32 iModelCull(RpAtomic* model, RwMatrixTag* mat); +S32 iModelSphereCull(xSphere* sphere); +RpAtomic* iModelFile_RWMultiAtomic(RpAtomic* model); +void iModelSetMaterialTexture(RpAtomic* model, void* texture); +void iModelResetMaterial(RpAtomic* model); +S32 iModelCullPlusShadow(RpAtomic* model, RwMatrix* mat, xVec3* shadowVec, S32* shadowOutside); +void iModelTagEval(RpAtomic* model, const xModelTag* tag, RwMatrixTag* mat, xVec3* dest); +U32 iModelTagSetup(xModelTag* tag, RpAtomic* model, F32 x, F32 y, F32 z); +void iModelSetMaterialAlpha(RpAtomic* model, U8 alpha); +U32 iModelVertCount(RpAtomic* model); +void iModelMaterialMul(RpAtomic* model, F32 rm, F32 gm, F32 bm); +RpAtomic* iModelFileNew(void* buffer, U32 size); +void iModelRender(RpAtomic* model, RwMatrix* mat); +void iModelUnload(RpAtomic* userdata); +void iModelAnimMatrices(RpAtomic* model, xQuat* quat, xVec3* tran, RwMatrixTag* mat); + +#endif diff --git a/src/SB/Core/gc/iMorph.cpp b/src/SB/Core/gc/iMorph.cpp new file mode 100644 index 0000000..5af9baf --- /dev/null +++ b/src/SB/Core/gc/iMorph.cpp @@ -0,0 +1,3 @@ +#include "iMorph.h" + +#include diff --git a/src/SB/Core/gc/iMorph.h b/src/SB/Core/gc/iMorph.h new file mode 100644 index 0000000..a3b0333 --- /dev/null +++ b/src/SB/Core/gc/iMorph.h @@ -0,0 +1,12 @@ +#ifndef IMORPH_H +#define IMORPH_H + +#include "types.h" + +#include +#include + +void iMorphOptimize(RpAtomic* model, S32 normals); +void iMorphRender(RpAtomic* model, RwMatrix* mat, S16** v_array, S16* weight, U32 normals, F32 scale); + +#endif \ No newline at end of file diff --git a/src/SB/Core/gc/iPad.cpp b/src/SB/Core/gc/iPad.cpp new file mode 100644 index 0000000..6a04b9c --- /dev/null +++ b/src/SB/Core/gc/iPad.cpp @@ -0,0 +1,168 @@ +#include +#include + +#include "xTRC.h" +#include "zGlobals.h" + +extern xGlobals* xglobals; +extern zGlobals globals; + +PADStatus sPadData[PAD_MAX_CONTROLLERS]; + +S32 iPadInit() +{ + PADInit(); + return 1; +} + +_tagxPad* iPadEnable(_tagxPad* pad, S16 port) +{ + pad->port = port; + pad->slot = 0; + pad->state = ePad_Enabled; + gTrcPad[pad->port].state = TRC_PadInserted; + pad->flags |= 3; + pad->flags |= 4; + return pad; +} + +S32 iPadConvStick(F32 value) +{ + F32 clampedValue; + if (value > 40.0f) + { + clampedValue = 40.0f; + } + else if (value < -40.0f) + { + clampedValue = -40.0f; + } + else + { + clampedValue = value; + } + + F32 convertedValue = 3.2f * clampedValue; + + if (convertedValue > 127.0f) + { + convertedValue = 127.0f; + } + else if (convertedValue < -127.0f) + { + convertedValue = -127.0f; + } + + return convertedValue; +} + +S32 iPadUpdate(_tagxPad* pad, U32* on) +{ + U16 buttons; + U32 temp_on; + + if (pad->port == 0) + { + PADRead(sPadData); + PADClamp(sPadData); + } + + PADStatus* padData = (PADStatus*)&sPadData; + switch (padData[pad->port].err) + { + case PAD_ERR_NO_CONTROLLER: + xTRCPad(pad->port, TRC_PadMissing); + PADReset(0x80000000 >> pad->port); + goto defaultError; + + case PAD_ERR_NOT_READY: + case PAD_ERR_TRANSFER: + return 0; + + default: + defaultError: + return 0; + + case PAD_ERR_NONE: + temp_on = iPadConvFromGCN(padData[pad->port].button, 1, 0x80); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 2, 0x20); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 4, 0x40); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 8, 0x10); + buttons = sPadData[pad->port].button; + + if (buttons & 0x10) + { + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x20, 0x2000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x40, 0x200); + if (sPadData[pad->port].triggerLeft >= 0x18) + { + temp_on |= 0x200; + } + if (sPadData[pad->port].triggerRight >= 0x18) + { + temp_on |= 0x2000; + } + temp_on |= 0x100000; + } + else + { + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x20, 0x1000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x40, 0x100); + if (sPadData[pad->port].triggerLeft >= 0x18) + { + temp_on |= 0x100; + } + if (sPadData[pad->port].triggerRight >= 0x18) + { + temp_on |= 0x1000; + } + } + + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x100, 0x10000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x200, 0x80000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x800, 0x40000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x400, 0x20000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x1000, 0x1); + (*on) = temp_on; + + pad->analog1.x = iPadConvStick(sPadData[pad->port].stickX); + pad->analog1.y = -iPadConvStick(sPadData[pad->port].stickY); // Scheduling memes. + pad->analog2.x = iPadConvStick(sPadData[pad->port].substickX); + pad->analog2.y = -iPadConvStick(sPadData[pad->port].substickY); // Same as above. + if (gTrcPad[pad->port].state != TRC_PadInserted) + { + xTRCPad(pad->port, TRC_PadInserted); + } + } + return 1; +} + +S32 iPadConvFromGCN(U32 a, U32 b, U32 c) +{ + // TODO: this can probably be simplified, + // basically a copy of ghidra's output + return c & (S32)(-(a & b) | a & b) >> 0x1f; +} + +void iPadRumbleFx(_tagxPad* p, _tagxRumble* r, F32 time_passed) +{ +} + +void iPadStopRumble() +{ + PADControlMotor(mPad[globals.currentActivePad].port, 0); // Scheduling memes. +} + +void iPadStopRumble(_tagxPad* pad) +{ + PADControlMotor(pad->port, 0); +} + +void iPadStartRumble(_tagxPad* pad, _tagxRumble* rumble) +{ + PADControlMotor(pad->port, 1); +} + +void iPadKill() +{ +} diff --git a/src/SB/Core/gc/iPad.h b/src/SB/Core/gc/iPad.h new file mode 100644 index 0000000..a35fdb2 --- /dev/null +++ b/src/SB/Core/gc/iPad.h @@ -0,0 +1,25 @@ +#ifndef IPAD_H +#define IPAD_H + +#include + +struct _tagiPad +{ + S32 port; +}; + +struct _tagxPad; +struct _tagxRumble; + +S32 iPadInit(); +_tagxPad* iPadEnable(_tagxPad* pad, S16 port); +S32 iPadConvStick(float value); +S32 iPadUpdate(_tagxPad* pad, U32* on); +S32 iPadConvFromGCN(U32 a, U32 b, U32 c); +void iPadRumbleFx(_tagxPad* p, _tagxRumble* r, F32 time_passed); +void iPadStopRumble(_tagxPad* pad); +void iPadStopRumble(); +void iPadStartRumble(_tagxPad* pad, _tagxRumble* rumble); +void iPadKill(); + +#endif diff --git a/src/SB/Core/gc/iParMgr.cpp b/src/SB/Core/gc/iParMgr.cpp new file mode 100644 index 0000000..b8e280c --- /dev/null +++ b/src/SB/Core/gc/iParMgr.cpp @@ -0,0 +1,11 @@ +#include "iParMgr.h" + +#include + +void iParMgrUpdate(F32) +{ +} + +void iParMgrRender() +{ +} diff --git a/src/SB/Core/gc/iParMgr.h b/src/SB/Core/gc/iParMgr.h new file mode 100644 index 0000000..d64f594 --- /dev/null +++ b/src/SB/Core/gc/iParMgr.h @@ -0,0 +1,27 @@ +#ifndef IPARMGR_H +#define IPARMGR_H + +#include "xMath3.h" + +#include + +struct tagiRenderInput +{ + U16* m_index; + RwIm3DVertex* m_vertex; + F32* m_vertexTZ; + U32 m_mode; + S32 m_vertexType; + S32 m_vertexTypeSize; + S32 m_indexCount; + S32 m_vertexCount; + xMat4x3 m_camViewMatrix; + xVec4 m_camViewR; + xVec4 m_camViewU; +}; + +void iParMgrInit(); +void iParMgrUpdate(F32 elapsedTime); +void iParMgrRender(); + +#endif diff --git a/src/SB/Core/gc/iSnd.cpp b/src/SB/Core/gc/iSnd.cpp new file mode 100644 index 0000000..7ac9e89 --- /dev/null +++ b/src/SB/Core/gc/iSnd.cpp @@ -0,0 +1,165 @@ +#include "iSnd.h" + +#include +#include + +#include "intrin.h" + +#include "iMix.h" +#include "xCutscene.h" +#include "xSnd.h" +#include "xMath.h" + +extern vinfo voices[58]; +extern char soundInited; +extern S32 SoundFlags; +extern F32 _1262; +extern F32 _1263; +extern volatile S32 fc; + +void arq_callback(long) +{ + if (!soundInited) + { + return; + } + SoundFlags = 0; +} + +void iSndExit() +{ + soundInited = 0; + AXQuit(); +} + +//not sure where this type is from. +void iSndSetEnvironmentalEffect(isound_effect) +{ + return; +} + +void iSndInitSceneLoaded() +{ +} + +U32 iVolFromX(F32 param1) +{ + float f = MAX(param1, 1e-20f); + + S32 i = 43.43f * xlog(f); + S32 comp = MIN(i, 0); + + if (comp < -0x388) + { + return -0x388; + } + else + { + return MIN(i, 0); + } +} + +void iSndVolUpdate(xSndVoiceInfo* info, vinfo* vinfo) +{ + MIXUnMute(vinfo->voice); + xSndInternalUpdateVoicePos(info); + if ((info->flags & 8) != 0) + { + iSndCalcVol3d(info, vinfo); + } + else + { + iSndCalcVol(info, vinfo); + } +} + +void iSndUpdateSounds() +{ + if (!soundInited) + { + return; + } + + for (int i = 0; i < 58; i++) + { + if (voices[i].voice != NULL) + { + iSndVolUpdate(&gSnd.voice[i + 6], &voices[i]); + } + } +} + +void iSndStartStereo(U32 id1, U32 id2, F32 pitch) +{ +} + +void iSndStereo(U32 i) +{ + if (i == 0) + { + OSSetSoundMode(0); + gSnd.stereo = 0; + } + else + { + OSSetSoundMode(1); + gSnd.stereo = 1; + } +} + +void iSndWaitForDeadSounds() +{ + fc = 0; + int i = 0; + // Can't get 0x8c to get stored in r31 + while ((i = fc) < 0x8c) //for (int i = 0; (i = fc) < 0x8c; ) + { + i = fc; + while (fc < i + 0xe) + ; + iSndUpdate(); + } +} + +void iSndSuspendCD(U32) +{ +} + +void iSndMessWithEA(sDSPADPCM* param1) +{ + if (param1 != NULL) + { + param1->buffer[5] = SampleToNybbleAddress(param1->buffer[0] - 1); + } +} + +U32 SampleToNybbleAddress(U32 sample) +{ + U32 a = __mulhwu(0x24924925, sample); + U32 b = (sample - a) >> 1; + + a = b + a; + b = (a >> 3); + a = (a << 1) & 0xfffffff0; + a = a + (sample - (b * 0xe)) + 2; + + return a; +} + +void sndloadcb(tag_xFile* tag) +{ + SoundFlags = 0; +} + +void iSndSetExternalCallback(void (*func_ptr)(U32)) +{ +} + +void iSndMyAXFree(_AXVPB** param1) +{ + if (param1 != NULL && *param1 != NULL) + { + AXFreeVoice(*param1); + *param1 = NULL; + } +} diff --git a/src/SB/Core/gc/iSnd.h b/src/SB/Core/gc/iSnd.h new file mode 100644 index 0000000..0455a3e --- /dev/null +++ b/src/SB/Core/gc/iSnd.h @@ -0,0 +1,78 @@ +#ifndef ISND_H +#define ISND_H + +#include + +struct xSndVoiceInfo; +struct tag_xFile; +struct _AXVPB; + +struct iSndVol +{ + S16 volL; + S16 volR; +}; + +struct iSndInfo +{ + U32 flags; + iSndVol vol; + U32 pitch; + S32 lastStreamBuffer; +}; + +// Size: 0x20 +// This was not in dwarf data +struct vinfo +{ + _AXVPB* voice; + S32 buffer[4]; + U32 _0x14; + S32 buffer2[2]; +}; + +// Size: ??? +// Not in dwarf data +struct sDSPADPCM +{ + S32 buffer[6]; +}; + +// not in dwarf data, +enum isound_effect +{ + iSND_EFFECT_NONE, + iSND_EFFECT_CAVE +}; + +void arq_callback(long); +void iSndExit(); + +void iSndPause(U32 snd, U32 pause); +void iSndSetEnvironmentalEffect(isound_effect); +void iSndInit(); +void iSndCalcVol(xSndVoiceInfo* xSndVoiceInfo, vinfo* vinfo); +void iSndCalcVol3d(xSndVoiceInfo* xSndVoiceInfo, vinfo* vinfo); +void iSndVolUpdate(xSndVoiceInfo* info, vinfo* vinfo); +void iSndUpdateSounds(); +void iSndUpdate(); +void iSndSuspendCD(U32); +void iSndMessWithEA(sDSPADPCM* param1); +U32 SampleToNybbleAddress(U32 sample); +void iSndInitSceneLoaded(); +S32 iSndIsPlaying(U32 assetID); +S32 iSndIsPlaying(U32 assetID, U32 parid); +void iSndWaitForDeadSounds(); +void iSndSceneExit(); +void sndloadcb(tag_xFile* tag); +S32 iSndLoadSounds(void*); +void iSndSetExternalCallback(void (*func_ptr)(U32)); +void iSndAXFree(_AXVPB** param1); +void iSndStartStereo(U32 id1, U32 id2, F32 pitch); +void iSndStop(U32 snd); +void iSndSetVol(U32 snd, F32 vol); +void iSndSetPitch(U32 snd, F32 pitch); +F32 iSndGetVol(U32 snd); +void iSndStereo(U32 stereo); + +#endif diff --git a/src/SB/Core/gc/iSystem.cpp b/src/SB/Core/gc/iSystem.cpp new file mode 100644 index 0000000..d226793 --- /dev/null +++ b/src/SB/Core/gc/iSystem.cpp @@ -0,0 +1,235 @@ +#include "iSystem.h" + +#include + +#include + +#include "xDebug.h" +#include "xMath.h" +#include "xSnd.h" +#include "xPad.h" +#include "xMemMgr.h" + +#include "iSystem.h" +#include "iFile.h" +#include "iTime.h" +#include "iTRC.h" + +extern U32 mem_base_alloc; +extern U32 add; +extern U32 size; +extern S32 gEmergencyMemLevel; +extern OSHeapHandle the_heap; +extern void* bad_val; +extern void* MemoryFunctions[4]; +extern U16 last_error; +extern OSContext* last_context; + +// Taken from iSystem.s +// Defining these here makes the stringBase0 offsets match in the later functions. +char* str1 = "Level %d, Warning $03d: %s\n"; +char* str2 = "FPE: Invalid operation: "; +char* str3 = "SNaN\n"; +char* str4 = "Infinity - Infinity\n"; +char* str5 = "Infinity / Infinity\n"; +char* str6 = "0 / 0\n"; +char* str7 = "Infinity * 0\n"; +char* str8 = "Invalid compare\n"; +char* str9 = "Software request\n"; +char* str10 = "Invalid square root\n"; +char* str11 = "Invalid integer convert\n"; +char* str12 = "FPE: Overflow\n"; +char* str13 = "FPE: Underflow\n"; +char* str14 = "FPE: Zero division\n"; +char* str15 = "FPE: Inexact result\n"; +char* str16 = "iSystem.cpp"; +char* str17 = "Unable to initialize memory system.\n"; +char* str18 = "(With apologies to Jim Morrison) This the end, my only friend, The End."; +char* str19 = "%s.rw3"; + +void** psGetMemoryFunctions() +{ + return MemoryFunctions; +} + +void iVSync() +{ + VIWaitForRetrace(); +} + +U16 my_dsc(U16 dsc) +{ + return dsc; +} + +void MemoryProtectionErrorHandler(U16 last, OSContext* ctx, U64 unk1, U64 unk2) +{ + last_error = last; + last_context = ctx; + if (ctx->fpscr) + { + null_func(); + } +} + +// FIXME: Define a bunch of functions :) +void TRCInit() +{ + iTRCDisk::Init(); + // iTRCDisk::SetPadStopRumblingFunction(iPadStopRumble); + // iTRCDisk::SetSndSuspendFunction(iSndSuspend); + // iTRCDisk::SetSndResumeFunction(iSndResume); + // iTRCDisk::SetSndKillFunction(iSndDIEDIEDIE); + // iTRCDisk::SetMovieSuspendFunction(iFMV::Suspend); + // iTRCDisk::SetMovieResumeFunction(iFMV::Resume); + // ResetButton::SetSndKillFunction(iSndDIEDIEDIE); +} + +S32 RenderWareExit() +{ + RwEngineStop(); + RwEngineClose(); + return RwEngineTerm(); +} + +void iSystemExit() +{ + xDebugExit(); + xMathExit(); + RenderWareExit(); + xSndExit(); + xPadKill(); + iFileExit(); + iTimeExit(); + xMemExit(); + OSPanic("iSystem.cpp", 0x21d, + "(With apologies to Jim Morrison) This the end, my only friend, The End."); +} + +void null_func() +{ + mem_base_alloc += 4; +} + +extern "C" { +void mem_null(U32 param_1, U32 param_2) +{ + add = param_1; + size = param_2; +} + +void* malloc(U32 __size) +{ + if ((S32)__size <= 0) + { + return NULL; + } + + void* result = OSAllocFromHeap(the_heap, __size); + + if (result == NULL) + { + null_func(); + } + + return result; +} + +void free(void* __ptr) +{ + if (__ptr != NULL) + { + OSFreeToHeap(the_heap, __ptr); + } +} +} + +void _rwDolphinHeapFree(void* __ptr) +{ + if (__ptr == bad_val) + { + mem_null(0, 0); + } + if (__ptr != NULL) + { + if (*(S32*)((S32)__ptr - 4) == 0xDEADBEEF) + { + free((void*)((S32)__ptr - 32)); + } + else + { + null_func(); + if (gEmergencyMemLevel != 0) + { + xMemPopBase(gEmergencyMemLevel); + gEmergencyMemLevel = 0; + } + } + } +} + +S32 iGetMinute() +{ + OSTime ticks = OSGetTime(); + OSCalendarTime td; + OSTicksToCalendarTime(ticks, &td); + return td.min; +} + +S32 iGetHour() +{ + OSTime ticks = OSGetTime(); + OSCalendarTime td; + OSTicksToCalendarTime(ticks, &td); + return td.hour; +} + +S32 iGetDay() +{ + OSTime ticks = OSGetTime(); + OSCalendarTime td; + OSTicksToCalendarTime(ticks, &td); + return td.mday; +} + +S32 iGetMonth() +{ + OSTime ticks = OSGetTime(); + OSCalendarTime td; + OSTicksToCalendarTime(ticks, &td); + return td.mon + 1; +} + +// Template for future use. TODO +char* iGetCurrFormattedDate(char* input) +{ + return NULL; +} + +// WIP. +char* iGetCurrFormattedTime(char* input) +{ + OSTime ticks = OSGetTime(); + OSCalendarTime td; + OSTicksToCalendarTime(ticks, &td); + bool pm = false; + // STUFF. + char* ret = input; + // STUFF. + if (pm) + { + ret[8] = 'P'; + ret[9] = '.'; + ret[10] = 'M'; + ret[11] = '.'; + } + else + { + ret[8] = 'A'; + ret[9] = '.'; + ret[10] = 'M'; + ret[11] = '.'; + } + ret[12] = '\0'; + return ret + (0xd - (S32)input); +} diff --git a/src/SB/Core/gc/iSystem.h b/src/SB/Core/gc/iSystem.h new file mode 100644 index 0000000..81c15e8 --- /dev/null +++ b/src/SB/Core/gc/iSystem.h @@ -0,0 +1,26 @@ +#ifndef ISYSTEM_H +#define ISYSTEM_H + +#include +#include + +extern "C" { +void* malloc(U32 __size); +void free(void* __ptr); +} + +void iVSync(); + +#define GET_MAKER_CODE() (*((U32*)0x80000004)) +#define GET_BUS_FREQUENCY() (*((U32*)0x800000F8)) + +void** psGetMemoryFunctions(); +void iVSync(); +U16 my_dsc(U16 dsc); + +void MemoryProtectionErrorHandler(U16 last, OSContext* ctx, U64 unk1, U64 unk2); +void TRCInit(); + +void null_func(); + +#endif diff --git a/src/SB/Core/gc/iTime.cpp b/src/SB/Core/gc/iTime.cpp new file mode 100644 index 0000000..0035caf --- /dev/null +++ b/src/SB/Core/gc/iTime.cpp @@ -0,0 +1,57 @@ +#include "iTime.h" +#include "iSystem.h" + +#include +#include + +static iTime sStartupTime; +static F32 sGameTime; + +void iTimeInit() +{ + sStartupTime = OSGetTime(); +} + +void iTimeExit() +{ +} + +iTime iTimeGet() +{ + return OSGetTime() - sStartupTime; +} + +F32 iTimeDiffSec(iTime time) +{ + return (F32)time / (GET_BUS_FREQUENCY() / 4); +} + +F32 iTimeDiffSec(iTime t0, iTime t1) +{ + return iTimeDiffSec(t1 - t0); +} + +void iTimeGameAdvance(F32 elapsed) +{ + sGameTime += elapsed; +} + +void iTimeSetGame(F32 time) +{ + sGameTime = time; +} + +void iProfileClear(U32 sceneID) +{ + // Redacted. :} +} + +void iFuncProfileDump() +{ + // Redacted. :} +} + +void iFuncProfileParse(char* elfPath, S32 profile) +{ + // Redacted. :} +} diff --git a/src/SB/Core/gc/iTime.h b/src/SB/Core/gc/iTime.h new file mode 100644 index 0000000..e73b748 --- /dev/null +++ b/src/SB/Core/gc/iTime.h @@ -0,0 +1,38 @@ +#ifndef ITIME_H +#define ITIME_H + +#include + +#define JANUARY 1 +#define FEBRUARY 2 +#define MARCH 3 +#define APRIL 4 +#define MAY 5 +#define JUNE 6 +#define JULY 7 +#define AUGUST 8 +#define SEPTEMBER 9 +#define OCTOBER 10 +#define NOVEMBER 11 +#define DECEMBER 12 + +typedef S64 iTime; + +S32 iGetMinute(); +S32 iGetHour(); +S32 iGetDay(); +S32 iGetMonth(); +char* iGetCurrFormattedDate(char* input); +char* iGetCurrFormattedTime(char* input); +void iTimeInit(); +void iTimeExit(); +iTime iTimeGet(); +F32 iTimeDiffSec(iTime t0, iTime t1); +F32 iTimeDiffSec(iTime time); +void iTimeGameAdvance(F32 elapsed); +void iTimeSetGame(F32 time); +void iProfileClear(U32 sceneID); +void iFuncProfileDump(); +void iFuncProfileParse(char* elfPath, S32 profile); + +#endif diff --git a/src/SB/Core/gc/isavegame.cpp b/src/SB/Core/gc/isavegame.cpp new file mode 100644 index 0000000..cfdab72 --- /dev/null +++ b/src/SB/Core/gc/isavegame.cpp @@ -0,0 +1,2048 @@ +#include "isavegame.h" + +#include "zGlobals.h" + +#include "xMemMgr.h" +#include "xSnd.h" + +#include "iFile.h" +#include "iSystem.h" +#include "iTRC.h" + +#include +#include +#include +#include + +// Not 100% on what this does or if it's correctly defined for all cases. Seems to be used for allocation alignment +#define ALIGN_THING(x, n) (n + x - 1 & -x) + +// name is a total guess for now +struct st_ISG_TPL_TEX +{ + struct UnkIn + { + U32 unk_0; + U32 unk_4; + void* unk_8; + U32 unk_c; + U32 unk_10[4]; + U8 unk_20; + U8 unk_21; + U8 unk_22; + U8 unk_23; + }; + struct UnkOut + { + U8 unk_0; + U8 unk_1; + U8 unk_2; + U8 unk_3; + U32 unk_4; + void* unk_8; + }; + + UnkIn* unk_0; + UnkOut* unk_4; +}; +// WIP. Looks like some sort of header for a file with embedded texture information. +struct st_ISG_TPL_TEXPALETTE +{ + U32 magic; + U32 count; + st_ISG_TPL_TEX* unk_8; +}; + +// .bss +static char cardwork[2][0xa000]; + +// .sbss +static volatile S32 g_isginit; +static st_ISG_TPL_TEXPALETTE* g_rawicon; +static st_ISG_TPL_TEXPALETTE* g_rawbanr; +static U32 g_iconsize; +static U32 g_banrsize; +static U8 isMounted; + +// .data +static st_ISGSESSION g_isgdata_MAIN = { 0 }; +static S32 g_legalSectSize[] = { 0x2000, 0, -1 }; + +static S32 iSG_start_your_engines(); +static S32 iSG_chk_icondata(); +static S32 iSG_load_icondata(); +static void iSG_discard_icondata(); +static S32 iSG_mc_unmount(S32 slot); + +S32 iSGStartup() +{ + if (g_isginit++ != 0) + { + return g_isginit; + } + + iSG_start_your_engines(); + iSG_load_icondata(); + return g_isginit; +} + +S32 iSGShutdown() +{ + iSG_discard_icondata(); + return 1; +} + +char* iSGMakeName(en_NAMEGEN_TYPE type, const char* base, S32 idx) +{ + static volatile S32 rotate = 0; // fakematch?? + static char rotatebuf[8][32] = { 0 }; + + const char* fmt_sd = "%s%02d"; + char* use_buf = rotatebuf[rotate++]; + if (rotate == 8) + { + rotate = 0; + } + + *use_buf = NULL; + switch (type) + { + case ISG_NGTYP_GAMEFILE: + + if (base != NULL) + { + sprintf(use_buf, fmt_sd, base, idx); + } + else + { + sprintf(use_buf, fmt_sd, "SpongeBob", idx); + } + break; + case ISG_NGTYP_GAMEDIR: + case ISG_NGTYP_CONFIG: + case ISG_NGTYP_ICONTHUM: + break; + } + + return use_buf; +} + +static const char* __deadstripped() +{ + return "Slot %c\0" + "Memory Card Slot %c\0" + "Nintendo GameCube Memory Card in Slot %c\0" + "Nintendo GameCube%s Memory Card in Slot %c\0" + "^\0" + "Nintendo GameCube%s Memory Card\0" + "is damaged and cannot be used\0" + "unsupprted sector size\0" + "is formatted for another market\0" + "encountered unexpected error (%d)"; +} + +st_ISGSESSION* iSGSessionBegin(void* cltdata, void (*chgfunc)(void*, en_CHGCODE), S32 monitor) +{ + iTRCDisk::CheckDVDAndResetState(); + memset(&g_isgdata_MAIN, 0, sizeof(st_ISGSESSION)); + + g_isgdata_MAIN.slot = -1; + g_isgdata_MAIN.chgfunc = chgfunc; + g_isgdata_MAIN.cltdata = cltdata; + + iSG_chk_icondata(); + return &g_isgdata_MAIN; +} + +void iSGSessionEnd(st_ISGSESSION* isgdata) +{ + iTRCDisk::CheckDVDAndResetState(); + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + if (isgdata->mcdata[i].unk_0) + { + iSG_mc_unmount(i); + isgdata->mcdata[i].unk_0 = 0; + } + } + + memset(isgdata, 0, sizeof(st_ISGSESSION)); +} + +S32 iSGTgtCount(st_ISGSESSION* isgdata, S32* max) +{ + s32 memSize = 0; + s32 sectorSize = 0; + S32 ret = 0; + + if (max != NULL) + { + *max = 2; + } + + for (S32 i = 0; i < ISG_NUM_SLOTS; ++i) + { + iTRCDisk::CheckDVDAndResetState(); + s32 result; + do + { + result = CARDProbeEx(i, &memSize, §orSize); + } while (result == CARD_RESULT_BUSY); + if (result == CARD_RESULT_READY) + { + ret++; + } + } + + return ret; +} + +S32 iSGTgtPhysSlotIdx(st_ISGSESSION* isgdata, S32 tidx) +{ + S32 idx = -1; + if (iSG_mcidx2slot(tidx, &idx, NULL)) + { + return idx; + } + return -1; +} + +static S32 iSG_mc_exists(S32 slot); +static S32 iSG_mc_isGCcard(st_ISG_MEMCARD_DATA* mcdata, int* param2, int* param3); +static S32 iSG_mc_format(st_ISG_MEMCARD_DATA*, S32, S32* canRecover); +S32 iSGTgtFormat(st_ISGSESSION* isgdata, S32 tgtidx, S32 async, S32* canRecover) +{ + S32 slot = 0; + S32 rc = 0; + iTRCDisk::CheckDVDAndResetState(); + if (iSG_mc_exists(isgdata->slot) == 0) + { + return 0; + } + + iSG_mcidx2slot(tgtidx, &slot, NULL); + // FIXME: r3 and r0 are swapped here for some reason ... + if (slot != isgdata->slot) + { + return 0; + } + + st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; + if (data->unk_0 == NULL) + { + return 0; + } + + if (iSG_mc_isGCcard(data, NULL, NULL) == 0) + { + return 0; + } + + rc = iSG_mc_format(data, 0, canRecover); + if (rc == -1) + { + return -1; + } + return rc == 0 ? 0 : 1; +} + +static S32 iSG_mc_isformatted(st_ISG_MEMCARD_DATA* mcdata); +U32 iSGTgtState(st_ISGSESSION* isgdata, S32 tgtidx, const char* dpath) +{ + S32 isSectSizeValid = 0; + S32 state = 0; + + S32 rc = 0; + + S32 slot = 0; + S32 x = 0; + S32 y = 0; + iTRCDisk::CheckDVDAndResetState(); + + iSG_mcidx2slot(tgtidx, &slot, NULL); + if (slot != isgdata->slot) + { + iSGTgtSetActive(isgdata, tgtidx); + } + + if (isgdata->slot < 0) + { + return 0x1000000; + } + + st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; + if (data->unk_0 == NULL) + { + return 0; + } + + if (iSG_mc_exists(isgdata->slot)) + { + state |= 1; + } + else + { + return 0; + } + + if (data->unk_12c != 0) + { + return state | 0x1000000; + } + + rc = iSG_mc_isGCcard(data, &x, &y); + if (x != 0) + { + state |= 0x4000000; + } + + if (y != 0) + { + state |= 0x2000000; + } + + if (rc == 0) + { + return state; + } + + if (g_legalSectSize[0] > 0) + { + for (S32 i = 0; g_legalSectSize[i] > 0; i++) + { + if (data->sectorSize == g_legalSectSize[i]) + { + isSectSizeValid = 1; + break; + } + } + if (isSectSizeValid == 0) + { + state |= 0x8000004; + return state & ~4; + } + } + + if (iSG_mc_isformatted(data) == 0) + { + return state | 4; + } + else + { + return state | 0xe; + } + + return state; +} + +static S32 iSG_mc_settgt(st_ISG_MEMCARD_DATA* mcdata, S32 slot); +S32 iSGTgtSetActive(st_ISGSESSION* isgdata, S32 tgtidx) +{ + S32 ret = 0; + S32 slot = 0; + iSG_mcidx2slot(tgtidx, &slot, NULL); + st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[slot]; + iTRCDisk::CheckDVDAndResetState(); + if (data->unk_0) + { + ret = 1; + } + else + { + if (iSG_mc_settgt(data, slot) != 0) + { + ret = 1; + isgdata->slot = slot; + } + } + return ret; +} + +static S32 iSG_get_finfo(st_ISG_MEMCARD_DATA* mcdata, const char* dpath); +static S32 iSG_isSpaceForFile(st_ISG_MEMCARD_DATA* mcdata, S32 param2, const char* param3, + S32* param4, S32* param5, S32* param6); +S32 iSGTgtHaveRoom(st_ISGSESSION* isgdata, S32 tidx, S32 fsize, const char* dpath, + const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile) +{ + st_ISG_MEMCARD_DATA* data; + S32 i; + S32 count; + S32 opened; + S32 is_space; + if (isgdata->slot < 0) + { + return 0; + } + data = &isgdata->mcdata[isgdata->slot]; + if (data->unk_0 == NULL) + { + return 0; + } + count = 0; + if (fname == NULL) + { + for (i = 0; i < ISG_NUM_FILES; ++i) + { + iTRCDisk::CheckDVDAndResetState(); + fname = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, i); + if (iSG_get_finfo(data, fname) != 0) + { + count++; + } + } + } + + is_space = iSG_isSpaceForFile(data, fsize, fname, bytesNeeded, availOnDisk, needFile); + if (count > 0 && *bytesNeeded > *availOnDisk) + { + if (needFile != NULL && *bytesNeeded > *availOnDisk) + { + *needFile = 0; + return 0; + } + return 1; + } + + CARDFileInfo fileInfo; + opened = 0; + for (i = 0; i < CARD_MAX_FILE && isgdata->slot >= 0 && isgdata->slot < ISG_NUM_SLOTS; ++i) + { + if (CARDFastOpen(isgdata->slot, i, &fileInfo) == 0) + { + opened++; + CARDClose(&fileInfo); + } + } + + if (opened >= CARD_MAX_FILE) + { + if (count > 0) + { + if (needFile != NULL) + { + *needFile = 0; + } + return 1; + } + return 0; + } + + return (*bytesNeeded > *availOnDisk) ? 0 : is_space; +} + +S32 iSGTgtHaveRoomStartup(st_ISGSESSION* isgdata, S32 tidx, S32 fsize, const char* dpath, + const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile) +{ + st_ISG_MEMCARD_DATA* data; + S32 i; + S32 count; + S32 opened; + S32 is_space; + if (isgdata->slot < 0) + { + return 0; + } + data = &isgdata->mcdata[isgdata->slot]; + if (data->unk_0 == NULL) + { + return 0; + } + count = 0; + if (fname == NULL) + { + for (i = 0; i < ISG_NUM_FILES; ++i) + { + iTRCDisk::CheckDVDAndResetState(); + fname = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, i); + if (iSG_get_finfo(data, fname) != 0) + { + count++; + } + } + } + + is_space = iSG_isSpaceForFile(data, fsize, fname, bytesNeeded, availOnDisk, needFile); + if (count > 0 && *bytesNeeded > *availOnDisk) + { + if (needFile != NULL && *bytesNeeded > *availOnDisk) + { + *needFile = 0; + return 0; + } + return 1; + } + + CARDFileInfo fileInfo; + opened = 0; + for (i = 0; i < CARD_MAX_FILE && isgdata->slot >= 0 && isgdata->slot < ISG_NUM_SLOTS; ++i) + { + if (CARDFastOpen(isgdata->slot, i, &fileInfo) == 0) + { + opened++; + CARDClose(&fileInfo); + } + } + + if (opened >= CARD_MAX_FILE) + { + if (count > 0) + { + if (needFile != NULL) + { + *needFile = 0; + } + return 0; + } + *needFile = -1; + return 0; + } + + if (*bytesNeeded > *availOnDisk) + { + return 0; + } + return (count >= 3) ? 0 : is_space; +} + +static S32 iSG_get_fsize(st_ISG_MEMCARD_DATA* mcdata, const char* param2); +static S32 iSG_cubeicon_size(S32 slot, S32 param2); +S32 iSGFileSize(st_ISGSESSION* isgdata, const char* fname) +{ + S32 ret = 0; + if (isgdata->slot < 0) + { + return -1; + } + st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; + iTRCDisk::CheckDVDAndResetState(); + ret = iSG_get_fsize(data, fname); + if (ret >= 0) + { + ret -= iSG_cubeicon_size(data->chan, data->sectorSize); + if (ret < 0) + { + ret = -1; + } + } + return ret; +} + +char* iSGFileModDate(st_ISGSESSION* isgdata, const char* fname) +{ + return iSGFileModDate(isgdata, fname, NULL, NULL, NULL, NULL, NULL, NULL); +} + +static S32 iSG_get_fmoddate(st_ISG_MEMCARD_DATA* mcdata, const char* fname, int* sec, int* min, + int* hr, int* mon, int* day, int* yr); +char* iSGFileModDate(st_ISGSESSION* isgdata, const char* fname, S32* sec, S32* min, S32* hr, + S32* mon, S32* day, S32* yr) +{ + static char datestr[0x40] = { 0 }; + int sec_str = 0; + int min_str = 0; + int hr_str = 0; + int mon_str = 0; + int day_str = 0; + int yr_str = 0; + if (iSG_get_fmoddate(&isgdata->mcdata[isgdata->slot], fname, &sec_str, &min_str, &hr_str, + &mon_str, &day_str, &yr_str) != 0) + { + sprintf(datestr, "%02d/%02d/%04d %02d:%02d:%02d", mon_str, day_str, yr_str, hr_str, min_str, + sec_str); + + if (sec != NULL) + { + *sec = sec_str; + } + if (min != NULL) + { + *min = min_str; + } + if (hr != NULL) + { + *hr = hr_str; + } + if (mon != NULL) + { + *mon = mon_str; + } + if (day != NULL) + { + *day = day_str; + } + if (yr != NULL) + { + *yr = yr_str; + } + } + else + { + sprintf(datestr, ""); + } + return datestr; +} + +void iSGMakeTimeStamp(char* str) +{ + OSCalendarTime calendar_time = { 0 }; + OSTime time = OSGetTime(); + OSTicksToCalendarTime(time, &calendar_time); + sprintf(str, "%02d/%02d/%04d %02d:%02d:%02d", calendar_time.mon + 1, calendar_time.mday, + calendar_time.year, calendar_time.hour, calendar_time.min, calendar_time.sec); +} + +S32 iSGSelectGameDir(st_ISGSESSION* isgdata, const char* dname) +{ + if (isgdata->slot < 0) + { + return 0; + } + st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; + + if (data->unk_0 == 0) + { + return 0; + } + + if (iSG_mc_isGCcard(data, NULL, NULL) == 0) + { + return 0; + } + + if (iSG_mc_isformatted(data) == 0) + { + return 0; + } + + S32 count = 0; + for (S32 idx = 0; idx < ISG_NUM_FILES; ++idx) + { + const char* n = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, idx); + if (iSG_get_finfo(data, n) != 0) + { + count++; + } + } + + return count != 0; +} + +S32 iSGSetupGameDir(st_ISGSESSION* isgdata, const char* dname, S32 force_iconfix) +{ + return 1; +} + +static char* iSG_bfr_icondata(char* param1, CARDStat* stat, char* param3, int param4); +static S32 iSG_mc_fopen(st_ISG_MEMCARD_DATA*, const char*, S32, en_ISG_IOMODE, en_ASYNC_OPERR*); +static S32 iSG_mc_fclose(st_ISG_MEMCARD_DATA*); +static S32 iSG_mc_fclose(st_ISG_MEMCARD_DATA*, CARDStat*); +static S32 iSG_mc_fdel(st_ISG_MEMCARD_DATA* mcdata, const char* fname); +static S32 iSG_mc_fwrite(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 bufsize); +static void iSG_upd_icostat(CARDStat*, CARDStat*); +static void iSG_timestamp(CARDStat*); +S32 iSGSaveFile(st_ISGSESSION* isgdata, const char* fname, char* data, S32 n, S32 async, char* arg5) +{ + void* alloc; + S32 allocsize; + char* icondata; + S32 iconsize; + + S32 writeret = 0; + en_ASYNC_OPERR operr = ISG_OPERR_NONE; + CARDStat statA = { 0 }; + CARDStat statB = { 0 }; + + ResetButton::DisableReset(); + if (isgdata->slot < 0) + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + isgdata->unk_268 = ISG_OPERR_NOCARD; + return 0; + } + + st_ISG_MEMCARD_DATA* mcdata = &isgdata->mcdata[isgdata->slot]; + if (mcdata->unk_12c != 0) + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + isgdata->unk_268 = ISG_OPERR_DAMAGE; + return 0; + } + + iTRCDisk::CheckDVDAndResetState(); + iconsize = iSG_cubeicon_size(isgdata->slot, mcdata->sectorSize); + S32 sectorsize200 = ALIGN_THING(mcdata->sectorSize, 0x200); + iconsize += ALIGN_THING(sectorsize200, n); + + allocsize = iconsize + 0x1f; + alloc = xMemPushTemp(allocsize); + memset(alloc, 0, allocsize); + icondata = (char*)((U32)alloc + 0x1f & 0xFFFFFFE0); + + memcpy(iSG_bfr_icondata(icondata, &statA, arg5, mcdata->sectorSize), data, n); + iTRCDisk::CheckDVDAndResetState(); + + if (iSG_mc_fopen(mcdata, fname, iconsize, ISG_IOMODE_WRITE, &operr) != 0) + { + if (iSG_mc_fwrite(mcdata, icondata, iconsize) != 0) + { + writeret = 1; + } + else + { + writeret = 0; + operr = ISG_OPERR_SVWRITE; + } + + if (writeret != 0) + { + iSG_upd_icostat(&statA, &mcdata->fstat); + iSG_timestamp(&mcdata->fstat); + s32 result; + do + { + result = CARDSetStatus(mcdata->chan, mcdata->finfo.fileNo, &mcdata->fstat); + } while (result == CARD_RESULT_BUSY); + + if (result != CARD_RESULT_READY) + { + writeret = 0; + } + } + + if (writeret != 0) + { + s32 result; + do + { + result = CARDSetAttributes(mcdata->chan, mcdata->finfo.fileNo, CARD_ATTR_PUBLIC); + } while (result == CARD_RESULT_BUSY); + } + + iSG_mc_fclose(mcdata, &statB); + } + xMemPopTemp(alloc); + + if (writeret == 0 && mcdata->unk_12c == 0) + { + iSG_mc_fdel(mcdata, fname); + } + + ResetButton::EnableReset(); + iTRCDisk::CheckDVDAndResetState(); + + isgdata->unk_268 = ISG_OPERR_NONE; + if (writeret != 0) + { + isgdata->unk_26c = ISG_OPSTAT_SUCCESS; + } + else + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + if (operr != ISG_OPERR_NONE) + { + isgdata->unk_268 = operr; + } + else + { + isgdata->unk_268 = ISG_OPERR_UNKNOWN; + } + } + return writeret; +} + +S32 iSGLoadFile(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 async) +{ + S32 numBytes = iSGFileSize(isgdata, fname); + return iSGReadLeader(isgdata, fname, databuf, numBytes, async); +} + +static S32 iSG_mc_fread(st_ISG_MEMCARD_DATA* mcdata, char*, S32, S32); +S32 iSGReadLeader(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 numbytes, S32 async) +{ + S32 bufsize; + S32 iconsize; + S32 allocsize; + char* readbuf; + + S32 readret = 0; + st_ISG_MEMCARD_DATA* data; + void* alloc = NULL; + + en_ASYNC_OPERR operr = ISG_OPERR_NONE; + if (isgdata->slot < 0) + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + isgdata->unk_268 = ISG_OPERR_NOCARD; + return 0; + } + data = &isgdata->mcdata[isgdata->slot]; + + if (data->unk_12c != 0) + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + isgdata->unk_268 = ISG_OPERR_DAMAGE; + return 0; + } + + iTRCDisk::CheckDVDAndResetState(); + iconsize = iSG_cubeicon_size(data->chan, data->sectorSize); + S32 sectorsize200 = ALIGN_THING(data->sectorSize, 0x200); + if ((S32)databuf % 32 != 0 || numbytes - (numbytes / sectorsize200) * sectorsize200 != 0) + { + S32 tmpsize = (numbytes + 0x1ff & ~0x1ff); + allocsize = tmpsize + 0x1f; + alloc = xMemPushTemp(allocsize); + memset(alloc, 0, allocsize); + bufsize = tmpsize; + readbuf = (char*)((U32)alloc + 0x1f & ~0x1f); + } + else + { + readbuf = databuf; + bufsize = numbytes; + } + + iTRCDisk::CheckDVDAndResetState(); + + if (iSG_mc_fopen(data, fname, -1, ISG_IOMODE_READ, &operr) != 0) + { + readret = (bool)iSG_mc_fread(data, (char*)readbuf, bufsize, iconsize); + iSG_mc_fclose(data); + } + + if (readret != 0 && alloc != NULL) + { + memcpy(databuf, readbuf, numbytes); + } + if (alloc != NULL) + { + xMemPopTemp(alloc); + } + + isgdata->unk_268 = ISG_OPERR_NONE; + if (readret != 0) + { + isgdata->unk_26c = ISG_OPSTAT_SUCCESS; + } + else + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + if (data->unk_12c != 0) + { + isgdata->unk_268 = ISG_OPERR_DAMAGE; + } + else + { + isgdata->unk_268 = ISG_OPERR_OTHER; + } + } + return readret; +} + +en_ASYNC_OPSTAT iSGPollStatus(st_ISGSESSION* isgdata, en_ASYNC_OPCODE* curop, S32 block) +{ + return isgdata->unk_26c; +} + +en_ASYNC_OPERR iSGOpError(st_ISGSESSION* isgdata, char* errmsg) +{ + static char* errmsgs[0x16] = { + "No current error", + "No operation in async queue", + "Too many async ops queued simultaneously", + "Init Failed", + "Unable to access Save Game Directory", + "Access Error - no card ?!? (eg yanked out)", + "Access Error - no room on card (file handles free bytes, etc)", + "Access Error - card is damaged or something bad", + "Access Error - file being loaded appears to be corrupt (I-Level)", + "Access Error - general problem", + "Save Error - Not enough free space to save file", + "Save Error - during initalization (async queue)", + "Save Error - during write", + "Save Error - opening file", + "Load Error - during initalization (async queue)", + "Load Error - during read", + "Load Error - opening file", + "Target problem (general error)", + "Target Error - media removed or changed", + "Target Error - Not ready for I/O (unformatted?)", + "Operation encountered unknown error", + NULL + }; + + en_ASYNC_OPERR err; + if (errmsg == NULL) + { + return isgdata->unk_268; + } + + if (isgdata->unk_268 < ISG_OPERR_NOMORE) + { + strncpy(errmsg, errmsgs[isgdata->unk_268], 0x80); + } + else + { + strncpy(errmsg, errmsgs[ISG_OPERR_UNKNOWN], 0x80); + } + errmsg[0x7f] = NULL; + return isgdata->unk_268; +} + +static S32 iSG_start_your_engines() +{ + CARDInit(); + return 1; +} + +// Looks equivalent. Can't get variable initializtions to match. +S32 iSG_mcidx2slot(S32 param1, S32* out_slot, S32* param3) +{ + s32 cardReady[ISG_NUM_SLOTS] = {}; + S32 ret = 0; + S32 idk = 0; + s32 memSize = 0; + s32 sectorSize = 0; + *out_slot = -1; + + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + s32 result; + do + { + result = CARDProbeEx(i, &memSize, §orSize); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + cardReady[i] = TRUE; + } + } + + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + if (cardReady[i]) + { + if (idk == param1) + { + *out_slot = i; + ret = 1; + break; + } + idk++; + } + } + + if (param3) + { + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + param3[i] = cardReady[i]; + } + } + + return ret; +} + +static S32 iSG_mc_exists(S32 slot) +{ + S32 ret = 0; + s32 memSize = 0; + s32 sectorSize = 0; + + if (slot < -1) + { + return 0; + } + + S32 result; + do + { + result = CARDProbeEx(slot, &memSize, §orSize); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + + return ret; +} + +static S32 iSG_mc_tryRepair(st_ISG_MEMCARD_DATA* mcdata) +{ + S32 result = 0; + S32 rc = 0; + s32 xferBytes = 0; + + if (mcdata->unk_0 == 0) + { + rc = 0; + } + + else if (mcdata->unk_12c) + { + rc = 0; + } + else + { + do + { + result = CARDCheckEx(mcdata->chan, &xferBytes); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + rc = 1; + } + else if (result == CARD_RESULT_ENCODING) + { + rc = 1; + } + else + { + if (result != CARD_RESULT_BROKEN) + { + mcdata->unk_12c = 1; + } + rc = 0; + } + } + return rc; +} + +static S32 iSG_mc_isformatted(st_ISG_MEMCARD_DATA* mcdata) +{ + S32 result = 0; + S32 rc = 0; + s32 xferBytes = 0; + + if (mcdata->unk_0 == 0) + { + rc = 0; + } + else if (mcdata->unk_12c) + { + rc = 0; + } + else + { + do + { + result = CARDCheckEx(mcdata->chan, &xferBytes); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + rc = 1; + } + else if (result == CARD_RESULT_BROKEN) + { + rc = 0; + } + else + { + rc = 0; + } + } + + return rc; +} + +static S32 iSG_mc_isGCcard(st_ISG_MEMCARD_DATA* mcdata, int* param2, int* param3) +{ + S32 result = 0; + S32 rc = 0; + + s32 xferBytes = 0; + u16 encoding = 0; + s32 memSize = 0; + s32 sectorSize = 0; + + if (param2) + { + *param2 = 0; + } + + if (param3) + { + *param3 = 0; + } + + if (mcdata->unk_0 == 0) + { + return 0; + } + if (mcdata->unk_12c) + { + return 0; + } + + do + { + result = CARDProbeEx(mcdata->chan, &memSize, §orSize); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + rc = 1; + } + + if (rc != 0) + { + do + { + result = CARDCheckEx(mcdata->chan, &xferBytes); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + rc = 1; + } + else if (result == CARD_RESULT_BROKEN) + { + rc = 2; + } + else + { + if (result == CARD_RESULT_ENCODING) + { + rc = 3; + if (param2) + { + *param2 = 1; + } + } + else + { + rc = 0; + if (result == CARD_RESULT_ENCODING && param2) + { + *param2 = 1; + } + if (result == CARD_RESULT_IOERROR && param3) + { + *param3 = 1; + } + } + } + } + + if (rc == 1) + { + do + { + result = CARDGetEncoding(mcdata->chan, &encoding); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY && encoding && param2) + { + *param2 = 1; + } + } + + return rc; +} + +static S32 iSG_cubeicon_size(S32 param1, S32 param2); +static S32 iSG_get_finfo(st_ISG_MEMCARD_DATA*, const char*); +// PS2 signature: +// static signed int iSG_isSpaceForFile(class st_ISG_MEMCARD_DATA* mcdata, S32 mcidx, S32 fsize, +// char* dpath, char* fname, S32* bytesNeeded, S32* availOnDisk) +static S32 iSG_isSpaceForFile(st_ISG_MEMCARD_DATA* mcdata, S32 param2, const char* param3, + S32* param4, S32* param5, S32* param6) +{ + S32 rc = 0; + S32 result = 0; + s32 byteNotUsed = 0; + s32 filesNotUsed = 0; + S32 len; + + if (mcdata->unk_0 == 0) + { + return 0; + } + len = iSG_cubeicon_size(mcdata->chan, mcdata->sectorSize); + len = len + param2; + len = ALIGN_THING(mcdata->sectorSize, len); + + do + { + result = CARDFreeBlocks(mcdata->chan, &byteNotUsed, &filesNotUsed); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + if (param5) + { + *param5 = byteNotUsed / mcdata->sectorSize; + } + if (param4) + { + *param4 = len / mcdata->sectorSize; + } + } + else + { + return 0; + } + + if (param6) + { + *param6 = 1; + } + + if (iSG_get_finfo(mcdata, param3)) + { + if (param6) + { + *param6 = *param6 - 1 & ~(*param6 - 1 >> 0x1f); // FIXME: Fakematch + } + if (len <= mcdata->unk_b0.length + byteNotUsed) + { + rc = 1; + } + } + else + { + if (len <= byteNotUsed && filesNotUsed > 0) + { + rc = 1; + } + } + + return rc; +} + +static S32 iSG_mc_mount(S32 slot); +static S32 iSG_mc_settgt(st_ISG_MEMCARD_DATA* mcdata, S32 slot) +{ + if (iSG_mc_mount(slot)) + { + mcdata->unk_0 = 1; + mcdata->chan = slot; + + iSG_mc_tryRepair(mcdata); + CARDGetSectorSize(slot, (u32*)&mcdata->sectorSize); + } + else + { + mcdata->unk_0 = 0; + } + + return mcdata->unk_0 != 0 ? 1 : 0; +} + +static S32 iSG_get_finfo(st_ISG_MEMCARD_DATA* mcdata, const char* dpath) +{ + S32 rc = 0; + en_ASYNC_OPERR operr = ISG_OPERR_NONE; + + if (iSG_mc_fopen(mcdata, dpath, -1, ISG_IOMODE_READ, &operr)) + { + rc = 1; + memcpy(&mcdata->unk_b0, &mcdata->fstat, sizeof(CARDStat)); + memcpy(&mcdata->unk_9c, &mcdata->finfo, sizeof(CARDFileInfo)); + iSG_mc_fclose(mcdata); + } + + return rc; +} + +static S32 iSG_curKosher(CARDStat* stat, CARDFileInfo* info) +{ + S32 rc = 1; + + if ((stat->iconAddr < 1 || stat->iconAddr > 0x7fffffff) && + (stat->commentAddr < 1 || stat->commentAddr > 0x7fffffff)) + { + rc = 0; + } + else + { + char stuff[0x200] = { 0 }; + sprintf(stuff, "SPONGEBOB:WHENROBOTSATTACK::RyanNeilDan"); + void* alloc = xMemPushTemp(0x5e00 + 0x1f); + // align buf address to 32 bytes + char* buf = (char*)((U32)alloc + 0x1f & ~0x1f); + + S32 result; + do + { + result = CARDRead(info, buf, 0x5e00, 0); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + if (memcmp(buf + 0x5a40, stuff, strlen(stuff) - 1)) + { + rc = 0; + } + + if (memcmp(buf, "Battle for Bikini Bottom", strlen("Battle for Bikini Bottom") - 1)) + { + rc = 0; + } + } + + xMemPopTemp(alloc); + } + + return rc; +} +static S32 iSG_fileKosher(st_ISG_MEMCARD_DATA* mcdata, const char* param2, int param3, int* param4) +{ + S32 rc = 0; + en_ASYNC_OPERR operr = ISG_OPERR_NONE; + + if (param4) + { + *param4 = 0; + } + + if (iSG_mc_fopen(mcdata, param2, -1, ISG_IOMODE_READ, &operr) == 0) + { + return -1; + } + + S32 ret = iSG_curKosher(&mcdata->fstat, &mcdata->finfo); + iSG_mc_fclose(mcdata); + + if (ret == 0) + { + rc = 0; + if (param3 && iSG_mc_fdel(mcdata, param2) && param4) + { + *param4 = 1; + } + } + else + { + rc = 1; + } + return rc; +} + +static S32 iSG_get_fsize(st_ISG_MEMCARD_DATA* mcdata, const char* param2) +{ + S32 rc = -1; + + if (iSG_get_finfo(mcdata, param2)) + { + rc = mcdata->unk_b0.length; + } + + if (rc < 0) + { + rc = -1; + } + + return rc; +} + +static S32 iSG_get_fmoddate(st_ISG_MEMCARD_DATA* mcdata, const char* fname, int* sec, int* min, + int* hr, int* mon, int* day, int* yr) +{ + S32 rc = 1; + OSCalendarTime time = { 0 }; + + if (iSG_get_finfo(mcdata, fname) == 0) + { + rc = 0; + } + else + { + OSTime t = mcdata->unk_b0.time; + t = OSSecondsToTicks(t); + OSTicksToCalendarTime(t, &time); + + if (sec) + { + *sec = time.sec; + } + if (min) + { + *min = time.min; + } + if (hr) + { + *hr = time.hour; + } + if (mon) + { + *mon = time.mon + 1; + } + if (day) + { + *day = time.mday; + } + if (mon) + { + *mon = time.mon + 1; + } + if (day) + { + *day = time.mday; + } + if (yr) + { + *yr = time.year; + } + } + + return rc; +} + +static void iSG_timestamp(CARDStat*) +{ +} + +struct IconData +{ + char game_name[0x20]; + char buf0[0x20]; + char buf1[0x1800]; + char buf2[8][0x800]; + char pad[0x200]; + char footer[0x200]; +}; +static S32 iSG_cubeicon_size(S32 slot, S32 param2) +{ + if ((U32)slot > 1) + { + return -1; + } + + S32 t = ALIGN_THING(param2, 0x200); + + // FIXME: Macro not quite right + // return ALIGN_THING(t, sizeof(IconData)); + return -t & sizeof(IconData) + t - 1; +} + +static S32 iSG_chk_icondata() +{ + return 1; +} + +static S32 iSG_tpl_unpack(st_ISG_TPL_TEXPALETTE*); +static S32 iSG_bnr_unpack(st_ISG_TPL_TEXPALETTE*); +static S32 iSG_load_icondata() +{ + g_rawicon = (st_ISG_TPL_TEXPALETTE*)iFileLoad("/SBGCIcon.tpl", NULL, &g_iconsize); + g_rawbanr = (st_ISG_TPL_TEXPALETTE*)iFileLoad("/SBGCBanner.tpl", NULL, &g_banrsize); + iSG_tpl_unpack(g_rawicon); + iSG_bnr_unpack(g_rawbanr); + + return g_rawicon && (S32)g_iconsize && g_rawbanr && (S32)g_banrsize ? 1 : 0; +} + +static void iSG_discard_icondata() +{ + OSFreeToHeap(__OSCurrHeap, g_rawicon); + OSFreeToHeap(__OSCurrHeap, g_rawbanr); + g_rawicon = NULL; + g_iconsize = 0; + g_rawbanr = NULL; + g_banrsize = 0; +} + +static st_ISG_TPL_TEX* iSG_tpl_TEXGet(st_ISG_TPL_TEXPALETTE*, unsigned int); +static char* iSG_bfr_icondata(char* param1, CARDStat* stat, char* param3, int param4) +{ + IconData data = { 0 }; + static st_ISG_TPL_TEXPALETTE* ico_pal; + static st_ISG_TPL_TEX* ico_desc; + static U32 i = 0; + + sprintf(data.footer, "SPONGEBOB:WHENROBOTSATTACK::RyanNeilDan"); + strncpy(data.game_name, "Battle for Bikini Bottom", sizeof(data.game_name)); + data.game_name[0x1f] = NULL; + + if (param3) + { + strncpy(data.buf0, param3, sizeof(data.buf0)); + } + data.buf0[0x1f] = NULL; + + ico_pal = g_rawbanr; + ico_desc = iSG_tpl_TEXGet(ico_pal, 0); + memcpy(data.buf1, ico_desc->unk_0->unk_8, sizeof(data.buf1)); + + ico_pal = g_rawicon; + for (i = 0; i < 8; i++) + { + ico_desc = iSG_tpl_TEXGet(ico_pal, i); + memcpy(data.buf2[i], ico_desc->unk_0->unk_8, sizeof(data.buf2[i])); + } + + memcpy(param1, &data, sizeof(data)); + + S32 t = ALIGN_THING(param4, 0x200); + return param1 + (t + (sizeof(IconData) - 1) & -t); +} + +static void iSG_upd_icostat(CARDStat*, CARDStat* stat) +{ + CARDSetCommentAddress(stat, 0); + CARDSetBannerFormat(stat, CARD_STAT_BANNER_RGB5A3); + CARDSetIconAddress(stat, 0x40); + CARDSetIconAnim(stat, CARD_STAT_ANIM_LOOP); + + for (S32 i = 0; i < CARD_ICON_MAX; ++i) + { + CARDSetIconFormat(stat, i, CARD_STAT_BANNER_RGB5A3); + CARDSetIconSpeed(stat, i, CARD_STAT_SPEED_MIDDLE); + } +} + +static S32 iSG_tpl_unpack(st_ISG_TPL_TEXPALETTE* tpl) +{ + if (tpl->magic != 0x20af30) + { + return 0; + } + + tpl->unk_8 = (st_ISG_TPL_TEX*)((U32)tpl + (U32)tpl->unk_8); + for (S32 i = 0; i < tpl->count; ++i) + { + st_ISG_TPL_TEX* x = &tpl->unk_8[i]; + if (x->unk_0 != NULL) + { + x->unk_0 = (st_ISG_TPL_TEX::UnkIn*)((U32)tpl + (U32)x->unk_0); + if (x->unk_0->unk_23 == 0) + { + x->unk_0->unk_8 = (void*)((U32)tpl + (U32)x->unk_0->unk_8); + x->unk_0->unk_23 = 1; + } + } + if (x->unk_4 != NULL) + { + x->unk_4 = (st_ISG_TPL_TEX::UnkOut*)((U32)tpl + (U32)x->unk_4); + if (x->unk_4->unk_2 == 0) + { + x->unk_4->unk_8 = tpl; + x->unk_4->unk_2 = 1; + } + } + } + return 1; +} + +static S32 iSG_bnr_unpack(st_ISG_TPL_TEXPALETTE* tpl) +{ + return iSG_tpl_unpack(tpl); +} + +static st_ISG_TPL_TEX* iSG_tpl_TEXGet(st_ISG_TPL_TEXPALETTE* tpl, U32 n) +{ + return &tpl->unk_8[n]; +} + +static void iSG_cb_unmount(s32 chan, s32 result); +static S32 iSG_mc_mount(S32 slot) +{ + s32 ret = 0; + // ?? for some reason this variable is in the stack frame + volatile s32 result = 0; + do + { + result = CARDMount(slot, cardwork[slot], iSG_cb_unmount); + isMounted = 1; + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + else if (result == CARD_RESULT_BROKEN || result == CARD_RESULT_ENCODING) + { + ret = 1; + } + return ret; +} + +static S32 iSG_mc_unmount(S32 slot) +{ + S32 rc = 0; + S32 result; + + do + { + result = CARDUnmount(slot); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + rc = 1; + } + else if (result == CARD_RESULT_NOCARD) + { + rc = 1; + } + + return rc; +} + +static void iSG_cb_unmount(s32 chan, s32 result) +{ + st_ISGSESSION* session = &g_isgdata_MAIN; + if (chan != session->slot) + { + return; + } + session->slot = -1; + if (session->chgfunc != NULL) + { + session->chgfunc(session->cltdata, ISG_CHG_TARGET); + } + memset(&session->mcdata[chan], 0, sizeof(st_ISG_MEMCARD_DATA)); +} + +static S32 iSG_mc_format(st_ISG_MEMCARD_DATA* mcdata, S32, S32* canRecover) +{ + if (mcdata->unk_12c != 0) + { + if (canRecover != NULL) + { + *canRecover = 0; + } + return 0; + } + + if (canRecover != NULL) + { + *canRecover = 1; + } + + s32 result; + do + { + result = CARDFormat(mcdata->chan); + } while (result == CARD_RESULT_BUSY); + + S32 ret; + if (result == CARD_RESULT_READY) + { + ret = 1; + } + else + { + ret = 0; + + switch (result) + { + case CARD_RESULT_IOERROR: + mcdata->unk_12c = 1; + if (canRecover != NULL) + { + *canRecover = 0; + } + break; + case CARD_RESULT_NOCARD: + if (canRecover != NULL) + { + *canRecover = -1; + } + ret = -1; + break; + case CARD_RESULT_FATAL_ERROR: + case CARD_RESULT_WRONGDEVICE: + case CARD_RESULT_NOFILE: + break; + } + } + return ret; +} + +static S32 iSG_mc_fopen(st_ISG_MEMCARD_DATA* mcdata, const char* fname, S32 fsize, + en_ISG_IOMODE mode, en_ASYNC_OPERR* operr) +{ + S32 ret = 0; + CARDFileInfo* finfo = &mcdata->finfo; + CARDStat* stat = &mcdata->fstat; + if (operr != NULL) + { + *operr = ISG_OPERR_NONE; + } + + if (mode == ISG_IOMODE_READ) + { + s32 result; + do + { + result = CARDOpen(mcdata->chan, (char*)fname, finfo); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + } + else + { + S32 res = iSG_mc_fdel(mcdata, fname); + if (mcdata->unk_12c == 0 && res > 0) + { + s32 result; + do + { + result = CARDCreate(mcdata->chan, (char*)fname, fsize, finfo); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + mcdata->unk_98 = 0; + } + else if (operr != NULL) + { + switch (result) + { + case CARD_RESULT_WRONGDEVICE: + case CARD_RESULT_NOCARD: + *operr = ISG_OPERR_NOCARD; + break; + case CARD_RESULT_IOERROR: + case CARD_RESULT_BROKEN: + mcdata->unk_12c = 1; + *operr = ISG_OPERR_DAMAGE; + break; + case CARD_RESULT_NOENT: + case CARD_RESULT_INSSPACE: + *operr = ISG_OPERR_NOROOM; + break; + default: + *operr = ISG_OPERR_OTHER; + break; + case CARD_RESULT_READY: + case CARD_RESULT_BUSY: + case CARD_RESULT_EXIST: + case CARD_RESULT_NOPERM: + break; + } + } + } + } + + if (ret != 0) + { + s32 result; + do + { + result = CARDGetStatus(mcdata->chan, finfo->fileNo, stat); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + } + + if (ret != 0) + { + if (memcmp(stat->gameName, "GQPE", 4) != 0 || memcmp(stat->company, "78", 2) != 0) + { + iSG_mc_fclose(mcdata); + ret = 0; + } + } + + return ret; +} + +static S32 iSG_mc_fclose(st_ISG_MEMCARD_DATA* mcdata) +{ + return iSG_mc_fclose(mcdata, NULL); +} + +static S32 iSG_mc_fclose(st_ISG_MEMCARD_DATA* mcdata, CARDStat* stat) +{ + S32 ret = 0; + s32 result; + do + { + result = CARDClose(&mcdata->finfo); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + + if (stat != NULL) + { + memcpy(stat, &mcdata->fstat, sizeof(CARDStat)); + } + + memset(&mcdata->finfo, 0, sizeof(CARDFileInfo)); + memset(&mcdata->fstat, 0, sizeof(CARDStat)); + + return ret; +} + +static S32 iSG_mc_fdel(st_ISG_MEMCARD_DATA* mcdata, const char* fname) +{ + if (mcdata->chan < 0 || mcdata->chan > 1) + { + return 0; + } + + if (isMounted == 0) + { + return 0; + } + + s32 result; + do + { + result = CARDDelete(mcdata->chan, fname); + } while (result == CARD_RESULT_BUSY); + + S32 ret; + if (result == CARD_RESULT_NOFILE) + { + ret = 1; + } + else if (result == CARD_RESULT_READY) + { + ret = 1; + } + else + { + ret = 0; + switch (result) + { + case CARD_RESULT_IOERROR: + mcdata->unk_12c = 1; + break; + case CARD_RESULT_NOPERM: + case CARD_RESULT_FATAL_ERROR: + case CARD_RESULT_WRONGDEVICE: + break; + } + } + return ret; +} + +static void iSG_cb_asyndone(s32, s32) +{ +} + +static S32 iSG_mcqa_fread(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len, S32 offset); +static S32 iSG_mc_fread(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len, S32 offset) +{ + return iSG_mcqa_fread(mcdata, buf, len, offset); +} + +static void iSG_cb_asyndone(s32, s32); +static S32 iSG_mcqa_fread(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len, S32 offset) +{ + S32 x = 1000; + s32 result = CARDGetResultCode(mcdata->chan); + do + { + result = CARDGetResultCode(mcdata->chan); + } while (result == CARD_RESULT_BUSY); + + if (result != CARD_RESULT_READY) + { + return 0; + } + + CARDGetXferredBytes(mcdata->chan); + do + { + result = CARDReadAsync(&mcdata->finfo, buf, len, offset, iSG_cb_asyndone); + } while (result == CARD_RESULT_BUSY); + + if (result != CARD_RESULT_READY) + { + return 0; + } + + result = CARD_RESULT_BUSY; + do + { + if (x++ > 500) + { + xSndUpdate(); + CARDGetXferredBytes(mcdata->chan); + result = CARDGetResultCode(mcdata->chan); + x = 0; + } + iTRCDisk::CheckDVDAndResetState(); + } while (result == CARD_RESULT_BUSY); + return result != 0 ? 0 : 1; +} + +static S32 iSG_mcqa_fwrite(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len); +static S32 iSG_mc_fwrite(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len) +{ + return iSG_mcqa_fwrite(mcdata, buf, len); +} + +static S32 iSG_mcqa_fwrite(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len) +{ + S32 ret = 0; + S32 x = 1000; + CARDStat* fstat = &mcdata->fstat; + s32 result; + do + { + result = CARDGetResultCode(mcdata->chan); + } while (result == CARD_RESULT_BUSY); + + if (result != CARD_RESULT_READY) + { + return 0; + } + + CARDGetXferredBytes(mcdata->chan); + s32 asynresult; + do + { + asynresult = CARDWriteAsync(&mcdata->finfo, buf, len, mcdata->unk_98, iSG_cb_asyndone); + } while (asynresult == CARD_RESULT_BUSY); + + if (asynresult != CARD_RESULT_READY) + { + return 0; + } + + result = CARD_RESULT_BUSY; + do + { + if (x++ > 500) + { + result = CARDGetResultCode(mcdata->chan); + xSndUpdate(); + CARDGetXferredBytes(mcdata->chan); + x = 0; + } + iTRCDisk::CheckDVDAndResetState(); + } while (result == CARD_RESULT_BUSY); + + if (asynresult == CARD_RESULT_READY) + { + mcdata->unk_98 += len; + + do + { + result = CARDGetStatus(mcdata->chan, mcdata->finfo.fileNo, fstat); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + } + return ret; +} + +S32 iSGCheckForWrongDevice() +{ + char* workarea = (char*)RwMalloc(0x10000 - 0x6000); + + S32 ret = -1; + for (S32 i = 0; i < ISG_NUM_SLOTS; ++i) + { + s32 result = CARDMount(i, workarea, NULL); + + switch (result) + { + case CARD_RESULT_READY: + case CARD_RESULT_BROKEN: + case CARD_RESULT_ENCODING: + CARDUnmount(i); + break; + case CARD_RESULT_WRONGDEVICE: + ret = i; + i = ISG_NUM_SLOTS; + break; + } + } + + RwFree(workarea); + + return ret; +} + +S32 iSGCheckForCorruptFiles(st_ISGSESSION* isgdata, char files[][64]) +{ + if (isgdata->slot < 0) + { + return 0; + } + + S32 i; + char* name; + st_ISG_MEMCARD_DATA* mcdata = &isgdata->mcdata[isgdata->slot]; + S32 ret = 0; + memset(files, NULL, 0xc0); + + for (i = 0; i < ISG_NUM_FILES; ++i) + { + name = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, i); + if (iSG_fileKosher(mcdata, name, 0, NULL) == 0) + { + strcpy(files[ret], name); + ret++; + } + } + return ret; +} + +U8 iSGCheckMemoryCard(st_ISGSESSION* isgdata, S32 index) +{ + s32 memSize; + s32 sectorSize; + + switch (CARDProbeEx(index, &memSize, §orSize)) + { + case CARD_RESULT_READY: + return 1; + } + return 0; +} + +void iSGAutoSave_Startup() +{ +} + +st_ISGSESSION* iSGAutoSave_Connect(S32 idx_target, void* cltdata, void (*chg)(void*, en_CHGCODE)) +{ + st_ISGSESSION* isgdata = iSGSessionBegin(cltdata, chg, 1); + if (isgdata == NULL) + { + return isgdata; + } + + if (iSGTgtSetActive(isgdata, idx_target) == 0) + { + iSGSessionEnd(isgdata); + isgdata = NULL; + } + return isgdata; +} + +void iSGAutoSave_Disconnect(st_ISGSESSION* isg) +{ + iSGSessionEnd(isg); +} + +S32 iSGAutoSave_Monitor(st_ISGSESSION* isg, S32 idx_target) +{ + if (isg == NULL) + { + return 0; + } + + U32 ret = iSGTgtState(isg, idx_target, NULL); + if (ret == 0 || (ret & 1) == 0) + { + globals.autoSaveFeature = 0; + return 0; + } + return 1; +} diff --git a/src/SB/Core/gc/isavegame.h b/src/SB/Core/gc/isavegame.h new file mode 100644 index 0000000..e18c5d4 --- /dev/null +++ b/src/SB/Core/gc/isavegame.h @@ -0,0 +1,184 @@ +#ifndef ISAVEGAME_H +#define ISAVEGAME_H + +#include + +#include + +enum en_ISG_IOMODE +{ + ISG_IOMODE_READ = 0x1, + ISG_IOMODE_WRITE, + ISG_IOMODE_APPEND +}; + +enum en_ISGMC_ERRSTATUS +{ + ISGMC_ERR_NONE, + ISGMC_ERR_NOMEMCARD, + ISGMC_ERR_MKDIR, + ISGMC_ERR_OPEN, + ISGMC_ERR_CLOSE, + ISGMC_ERR_READ, + ISGMC_ERR_WRITE +}; + +enum en_ASYNC_OPCODE +{ + ISG_OPER_NOOP, + ISG_OPER_INIT, + ISG_OPER_SAVE, + ISG_OPER_LOAD +}; + +// This enum might be incorrect. The tooling choked on the enum values +// being 0xFFFFFFFF +enum en_ASYNC_OPSTAT +{ + ISG_OPSTAT_FAILURE = 0xFFFFFFFF, + ISG_OPSTAT_INPROG = 0, + ISG_OPSTAT_SUCCESS +}; + +enum en_ASYNC_OPERR +{ + ISG_OPERR_NONE, + ISG_OPERR_NOOPER, + ISG_OPERR_MULTIOPER, + ISG_OPERR_INITFAIL, + ISG_OPERR_GAMEDIR, + ISG_OPERR_NOCARD, + ISG_OPERR_NOROOM, + ISG_OPERR_DAMAGE, + ISG_OPERR_CORRUPT, + ISG_OPERR_OTHER, + ISG_OPERR_SVNOSPACE, + ISG_OPERR_SVINIT, + ISG_OPERR_SVWRITE, + ISG_OPERR_SVOPEN, + ISG_OPERR_LDINIT, + ISG_OPERR_LDREAD, + ISG_OPERR_LDOPEN, + ISG_OPERR_TGTERR, + ISG_OPERR_TGTREM, + ISG_OPERR_TGTPREP, + ISG_OPERR_UNKNOWN, + ISG_OPERR_NOMORE +}; + +enum en_CHGCODE +{ + ISG_CHG_NONE, + ISG_CHG_TARGET, + ISG_CHG_GAMELIST +}; + +/* DWARF Definitions (PS2) + +class st_ISG_MEMCARD_DATA { + // total size: 0x100 +public: + signed int mcport; // offset 0x0, size 0x4 + signed int mcslot; // offset 0x4, size 0x4 + signed int mcfp; // offset 0x8, size 0x4 + enum en_ISG_IOMODE fmode; // offset 0xC, size 0x4 + char gamepath[64]; // offset 0x10, size 0x40 + class sceMcTblGetDir finfo; // offset 0x80, size 0x40 + signed int cur_mcop; // offset 0xC0, size 0x4 + enum en_ISGMC_ERRSTATUS mcerr; // offset 0xC4, size 0x4 + signed int allow_cache; // offset 0xC8, size 0x4 +}; + +class st_ISGSESSION { + // total size: 0x9C +public: + class st_ISG_MEMCARD_DATA * mcdata; // offset 0x0, size 0x4 + char gameroot[64]; // offset 0x4, size 0x40 + char gamedir[64]; // offset 0x44, size 0x40 + enum en_ASYNC_OPCODE as_curop; // offset 0x84, size 0x4 + enum en_ASYNC_OPSTAT as_opstat; // offset 0x88, size 0x4 + enum en_ASYNC_OPERR as_operr; // offset 0x8C, size 0x4 + void * cltdata; // offset 0x90, size 0x4 + enum en_CHGCODE chgcode; // offset 0x94, size 0x4 + void (* chgfunc)(void *, enum en_CHGCODE); // offset 0x98, size 0x4 +}; + + +*/ + +// Size should be 0x130 +struct st_ISG_MEMCARD_DATA +{ + S32 unk_0; + S32 chan; + S32 sectorSize; + CARDFileInfo finfo; + CARDStat fstat; + S32 unk_pad5[3]; + S32 unk_98; + CARDFileInfo unk_9c; + CARDStat unk_b0; + S32 unk_pad6[4]; + S32 unk_12c; +}; + +#define ISG_NUM_SLOTS 2 +#define ISG_NUM_FILES 3 +struct st_ISGSESSION +{ + st_ISG_MEMCARD_DATA mcdata[ISG_NUM_SLOTS]; + S32 slot; + S32 unk_264; + en_ASYNC_OPERR unk_268; + en_ASYNC_OPSTAT unk_26c; + S32 unk_270; + void (*chgfunc)(void*, en_CHGCODE); // 0x274 + void* cltdata; // 0x278 + S32 unk_27c; +}; + +enum en_NAMEGEN_TYPE +{ + ISG_NGTYP_GAMEDIR, + ISG_NGTYP_GAMEFILE, + ISG_NGTYP_CONFIG, + ISG_NGTYP_ICONTHUM +}; + +S32 iSGStartup(); +S32 iSGShutdown(); +char* iSGMakeName(en_NAMEGEN_TYPE type, const char* base, S32 idx); +st_ISGSESSION* iSGSessionBegin(void* cltdata, void (*chgfunc)(void*, en_CHGCODE), S32 monitor); +void iSGSessionEnd(st_ISGSESSION* isgdata); +S32 iSGTgtCount(st_ISGSESSION* isgdata, S32* max); +S32 iSGTgtPhysSlotIdx(st_ISGSESSION* isgdata, S32 tidx); +U32 iSGTgtState(st_ISGSESSION* isgdata, S32 tgtidx, const char* dpath); +S32 iSGTgtFormat(st_ISGSESSION* isgdata, S32 tgtidx, S32 async, S32* canRecover); +S32 iSGTgtSetActive(st_ISGSESSION* isgdata, S32 tgtidx); +S32 iSGTgtHaveRoom(st_ISGSESSION* isgdata, S32 tidx, S32 fsize, const char* dpath, + const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile); +S32 iSGTgtHaveRoomStartup(st_ISGSESSION* isgdata, S32 tidx, S32 fsize, const char* dpath, + const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile); +U8 iSGCheckMemoryCard(st_ISGSESSION* isgdata, S32 index); +S32 iSGFileSize(st_ISGSESSION* isgdata, const char* fname); +char* iSGFileModDate(st_ISGSESSION* isgdata, const char* fname); +char* iSGFileModDate(st_ISGSESSION* isgdata, const char* fname, S32* sec, S32* min, S32* hr, + S32* mon, S32* day, S32* yr); +en_ASYNC_OPSTAT iSGPollStatus(st_ISGSESSION* isgdata, en_ASYNC_OPCODE* curop, S32 block); +en_ASYNC_OPERR iSGOpError(st_ISGSESSION* isgdata, char* errmsg); +S32 iSGReadLeader(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 numbytes, + S32 async); +S32 iSGSelectGameDir(st_ISGSESSION* isgdata, const char* dname); +void iSGMakeTimeStamp(char* str); +S32 iSGSetupGameDir(st_ISGSESSION* isgdata, const char* dname, S32 force_iconfix); +S32 iSGSaveFile(st_ISGSESSION* isgdata, const char* fname, char* data, S32 n, S32 async, char*); +S32 iSGLoadFile(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 async); +S32 iSG_mcidx2slot(S32 param1, S32* out_slot, S32* param3); +void iSGAutoSave_Startup(); +st_ISGSESSION* iSGAutoSave_Connect(S32 idx_target, void* cltdata, void (*chg)(void*, en_CHGCODE)); +void iSGAutoSave_Disconnect(st_ISGSESSION* isg); +S32 iSGAutoSave_Monitor(st_ISGSESSION* isg, S32 idx_target); +S32 iSGCheckForWrongDevice(); +S32 iSGCheckForCorruptFiles(st_ISGSESSION*, char files[][64]); + +#endif diff --git a/src/SB/Core/gc/ngcrad3d.c b/src/SB/Core/gc/ngcrad3d.c new file mode 100644 index 0000000..f69b348 --- /dev/null +++ b/src/SB/Core/gc/ngcrad3d.c @@ -0,0 +1 @@ +#include "ngcrad3d.h" diff --git a/src/SB/Core/gc/ngcrad3d.cpp b/src/SB/Core/gc/ngcrad3d.cpp new file mode 100644 index 0000000..ab9c71b --- /dev/null +++ b/src/SB/Core/gc/ngcrad3d.cpp @@ -0,0 +1,3 @@ +#include "ngcrad3d.h" + +#include diff --git a/src/SB/Core/gc/ngcrad3d.h b/src/SB/Core/gc/ngcrad3d.h new file mode 100644 index 0000000..a43ea9d --- /dev/null +++ b/src/SB/Core/gc/ngcrad3d.h @@ -0,0 +1,4 @@ +#ifndef NGCRAD3D_H +#define NGCRAD3D_H + +#endif diff --git a/src/SB/Core/x/containers.h b/src/SB/Core/x/containers.h new file mode 100644 index 0000000..05b894a --- /dev/null +++ b/src/SB/Core/x/containers.h @@ -0,0 +1,57 @@ +#ifndef CONTAINERS_H +#define CONTAINERS_H + +#include + +struct tier_queue_allocator +{ + struct block_data + { + U8 prev; + U8 next; + U16 flags; + void* data; + }; + + block_data* blocks; + U32 _unit_size; + U32 _block_size; + U32 _block_size_shift; + U32 _max_blocks; + U32 _max_blocks_shift; + U8 head; +}; + +template struct tier_queue +{ + U32 first; + U32 _size; + U32 wrap_mask; + tier_queue_allocator* alloc; + U8 blocks[256]; +}; + +template struct static_queue +{ + U32 _first; + U32 _size; + U32 _max_size; + U32 _max_size_mask; + T* _buffer; + void clear(); +}; + +template struct fixed_queue +{ + U32 _first; + U32 _last; + T _buffer[N + 1]; + + void reset(); + void push_front(const T& element); + bool full() const; + void pop_back(); + bool empty() const; +}; + +#endif diff --git a/src/SB/Core/x/iCamera.cpp b/src/SB/Core/x/iCamera.cpp new file mode 100644 index 0000000..e1e99ba --- /dev/null +++ b/src/SB/Core/x/iCamera.cpp @@ -0,0 +1,341 @@ +#include "iCamera.h" + +#include "xShadow.h" + +#include "iScrFX.h" +#include "iMath.h" + +#include "zGlobals.h" + +#include + +extern F32 sCameraNearClip; +extern F32 sCameraFarClip; +extern RwCamera* sMainGameCamera; + +extern F32 _640_0; +extern F32 _706_0; +extern F32 _707_1; +extern F32 _708_3; +extern F32 _709_1; +extern F32 _741_3; +extern F32 _742_1; +extern F32 _743_1; +extern F64 _769_1; +extern F64 _826_0; + +RwCamera* iCameraCreate(S32 width, S32 height, S32 mainGameCamera) +{ + RwV2d vw; + RwCamera* camera; + + camera = RwCameraCreate(); + + RwCameraSetFrame(camera, RwFrameCreate()); + RwCameraSetRaster(camera, RwRasterCreate(width, height, 0, rwRASTERTYPECAMERA)); + RwCameraSetZRaster(camera, RwRasterCreate(width, height, 0, rwRASTERTYPEZBUFFER)); + RwCameraSetFarClipPlane(camera, sCameraFarClip); + RwCameraSetNearClipPlane(camera, sCameraNearClip); + + vw.x = _640_0; + vw.y = _640_0; + + RwCameraSetViewWindow(camera, &vw); + + if (mainGameCamera) + { + iScrFxCameraCreated(camera); + sMainGameCamera = camera; + } + + return camera; +} + +void iCameraDestroy(RwCamera* camera) +{ + RpWorld* pWorld; + RwRaster* raster; + RwFrame* frame; + + _rwFrameSyncDirty(); + + pWorld = RwCameraGetWorld(camera); + + if (pWorld) + { + RpWorldRemoveCamera(pWorld, camera); + } + + if (camera == sMainGameCamera) + { + iScrFxCameraDestroyed(camera); + sMainGameCamera = NULL; + } + + if (camera) + { + frame = RwCameraGetFrame(camera); + + if (frame) + { + RwCameraSetFrame(camera, NULL); + RwFrameDestroy(frame); + } + + raster = RwCameraGetRaster(camera); + + if (raster) + { + RwRasterDestroy(raster); + RwCameraSetRaster(camera, NULL); + } + + raster = RwCameraGetZRaster(camera); + + if (raster) + { + RwRasterDestroy(raster); + RwCameraSetZRaster(camera, NULL); + } + + RwCameraDestroy(camera); + } +} + +void iCameraBegin(RwCamera* cam, S32 clear) +{ + if (clear) + { + if (xglobals->fog.type != rwFOGTYPENAFOGTYPE) + { + RwCameraClear(cam, &xglobals->fog.bgcolor, rwCAMERACLEARIMAGE | rwCAMERACLEARZ); + } + else + { + RwCameraClear(cam, NULL, rwCAMERACLEARZ); + } + } + + RwCameraSetNearClipPlane(cam, sCameraNearClip); + RwCameraBeginUpdate(cam); +} + +void iCameraEnd(RwCamera* cam) +{ + iScrFxCameraEndScene(cam); + RwCameraEndUpdate(cam); + iScrFxPostCameraEnd(cam); +} + +void iCameraShowRaster(RwCamera* cam) +{ + RwCameraShowRaster(cam, NULL, 0); +} + +void iCameraFrustumPlanes(RwCamera* cam, xVec4* frustplane) +{ + RwFrustumPlane* rwPlane; + + rwPlane = &cam->frustumPlanes[2]; + frustplane[0].x = rwPlane->plane.normal.x; + frustplane[1].x = rwPlane->plane.normal.y; + frustplane[2].x = rwPlane->plane.normal.z; + frustplane[3].x = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[4]; + frustplane[0].y = rwPlane->plane.normal.x; + frustplane[1].y = rwPlane->plane.normal.y; + frustplane[2].y = rwPlane->plane.normal.z; + frustplane[3].y = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[5]; + frustplane[0].z = rwPlane->plane.normal.x; + frustplane[1].z = rwPlane->plane.normal.y; + frustplane[2].z = rwPlane->plane.normal.z; + frustplane[3].z = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[3]; + frustplane[0].w = rwPlane->plane.normal.x; + frustplane[1].w = rwPlane->plane.normal.y; + frustplane[2].w = rwPlane->plane.normal.z; + frustplane[3].w = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[1]; + frustplane[4].x = rwPlane->plane.normal.x; + frustplane[5].x = rwPlane->plane.normal.y; + frustplane[6].x = rwPlane->plane.normal.z; + frustplane[7].x = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[0]; + frustplane[4].y = rwPlane->plane.normal.x; + frustplane[5].y = rwPlane->plane.normal.y; + frustplane[6].y = rwPlane->plane.normal.z; + frustplane[7].y = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[2]; + frustplane[4].z = rwPlane->plane.normal.x; + frustplane[5].z = rwPlane->plane.normal.y; + frustplane[6].z = rwPlane->plane.normal.z; + frustplane[7].z = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[4]; + frustplane[4].w = rwPlane->plane.normal.x; + frustplane[5].w = rwPlane->plane.normal.y; + frustplane[6].w = rwPlane->plane.normal.z; + frustplane[7].w = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[2]; + frustplane[8].x = rwPlane->plane.normal.x; + frustplane[9].x = rwPlane->plane.normal.y; + frustplane[10].x = rwPlane->plane.normal.z; + frustplane[11].x = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[4]; + frustplane[8].y = rwPlane->plane.normal.x; + frustplane[9].y = rwPlane->plane.normal.y; + frustplane[10].y = rwPlane->plane.normal.z; + frustplane[11].y = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[5]; + frustplane[8].z = rwPlane->plane.normal.x; + frustplane[9].z = rwPlane->plane.normal.y; + frustplane[10].z = rwPlane->plane.normal.z; + frustplane[11].z = rwPlane->plane.distance; + + rwPlane = &cam->frustumPlanes[3]; + frustplane[8].w = rwPlane->plane.normal.x; + frustplane[9].w = rwPlane->plane.normal.y; + frustplane[10].w = rwPlane->plane.normal.z; + frustplane[11].w = rwPlane->plane.distance; +} + +void iCameraUpdatePos(RwCamera* cam, xMat4x3* pos) +{ + RwFrame* f; + RwMatrix* m; + + f = RwCameraGetFrame(cam); + m = RwFrameGetMatrix(f); + + xMat4x3Copy((xMat4x3*)m, pos); + + m = RwFrameGetLTM(f); + + xMat4x3Copy((xMat4x3*)m, pos); + + RwFrameOrthoNormalize(f); + RwFrameUpdateObjects(f); +} + +void iCameraSetFOV(RwCamera* cam, F32 fov) +{ + RwV2d vw; + + vw.x = itan(_706_0 * (_707_1 * fov) / _708_3); + + // non-matching: frsp instruction is here for some reason + vw.y = _709_1 * vw.x; + + RwCameraSetViewWindow(cam, &vw); +} + +void iCameraAssignEnv(RwCamera* camera, iEnv* env_geom) +{ + globalCamera = camera; + + RpWorldAddCamera(env_geom->world, camera); + xShadowSetWorld(env_geom->world); +} + +void iCamGetViewMatrix(RwCamera* camera, xMat4x3* view_matrix) +{ + RwMatrix* rw_view; + + memset(view_matrix, 0, sizeof(xMat4x3)); + + rw_view = RwCameraGetViewMatrix(camera); + + view_matrix->right.x = rw_view->right.x; + view_matrix->right.y = rw_view->right.y; + view_matrix->right.z = rw_view->right.z; + view_matrix->up.x = rw_view->up.x; + view_matrix->up.y = rw_view->up.y; + view_matrix->up.z = rw_view->up.z; + view_matrix->at.x = rw_view->at.x; + view_matrix->at.y = rw_view->at.y; + view_matrix->at.z = rw_view->at.z; + view_matrix->pos.x = rw_view->pos.x; + view_matrix->pos.y = rw_view->pos.y; + view_matrix->pos.z = rw_view->pos.z; +} + +void iCameraSetNearFarClip(F32 nearPlane, F32 farPlane) +{ + if (nearPlane <= *(const F32*)&_742_1) + { + nearPlane = _741_3; + } + + sCameraNearClip = nearPlane; + + // non-matching: _742_1 is loaded too early + + if (farPlane <= *(const F32*)&_742_1) + { + farPlane = _743_1; + } + + sCameraFarClip = farPlane; +} + +void iCameraSetFogParams(iFogParams* fp, F32 time) +{ + if (!fp || fp->type == rwFOGTYPENAFOGTYPE) + { + xglobals->fog.type = rwFOGTYPENAFOGTYPE; + xglobals->fogA.type = rwFOGTYPENAFOGTYPE; + } + else if (_742_1 == time || fp->type != xglobals->fogA.type) + { + xglobals->fog = *fp; + xglobals->fogA = *fp; + xglobals->fog_t0 = 0; + } + else + { + xglobals->fogA = xglobals->fog; + xglobals->fogB = *fp; + + // todo + } +} + +void iCameraSetFogRenderStates() +{ + RwCamera* pCamera; + iFogParams* pFogParams; + U32 bite_me; + + pCamera = RwCameraGetCurrentCamera(); + pFogParams = &xglobals->fog; + + if (pFogParams->type == rwFOGTYPENAFOGTYPE) + { + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + + RwCameraSetFarClipPlane(pCamera, sCameraFarClip); + } + else + { + bite_me = (pFogParams->fogcolor.alpha << 24) | (pFogParams->fogcolor.red << 16) | + (pFogParams->fogcolor.green << 8) | pFogParams->fogcolor.blue; + + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)pFogParams->type); + RwRenderStateSet(rwRENDERSTATEFOGCOLOR, (void*)bite_me); + RwRenderStateSet(rwRENDERSTATEFOGDENSITY, (void*)&pFogParams->density); + + RwCameraSetFogDistance(pCamera, pFogParams->start); + RwCameraSetFarClipPlane(pCamera, pFogParams->stop); + } +} diff --git a/src/SB/Core/x/iCamera.h b/src/SB/Core/x/iCamera.h new file mode 100644 index 0000000..7a701db --- /dev/null +++ b/src/SB/Core/x/iCamera.h @@ -0,0 +1,39 @@ +#ifndef ICAMERA_H +#define ICAMERA_H + +#include +#include + +#include "xMath3.h" +#include "iEnv.h" +#include "iTime.h" + +struct iFogParams +{ + RwFogType type; + F32 start; + F32 stop; + F32 density; + RwRGBA fogcolor; + RwRGBA bgcolor; + U8* table; +}; + +extern RwCamera* globalCamera; + +RwCamera* iCameraCreate(S32 width, S32 height, S32 mainGameCamera); +void iCameraDestroy(RwCamera* camera); +void iCameraBegin(RwCamera* cam, S32 clear); +void iCameraEnd(RwCamera* cam); +void iCameraShowRaster(RwCamera* cam); +void iCameraFrustumPlanes(RwCamera* cam, xVec4* frustplane); +void iCameraUpdatePos(RwCamera* cam, xMat4x3* pos); +void iCameraSetFOV(RwCamera* cam, F32 fov); +void iCameraAssignEnv(RwCamera* camera, iEnv* env_geom); +void iCamGetViewMatrix(RwCamera* camera, xMat4x3* view_matrix); +void iCameraSetNearFarClip(F32 nearPlane, F32 farPlane); +void iCameraSetFogParams(iFogParams* fp, F32 time); +void iCameraUpdateFog(RwCamera* cam, iTime t); +void iCameraSetFogRenderStates(); + +#endif diff --git a/src/SB/Core/x/xAnim.cpp b/src/SB/Core/x/xAnim.cpp new file mode 100644 index 0000000..18a2f2c --- /dev/null +++ b/src/SB/Core/x/xAnim.cpp @@ -0,0 +1,2185 @@ +#include "xAnim.h" + +#include "iAnim.h" +#include "iModel.h" + +#include "xMemMgr.h" +#include "xMath.h" +#include "xModel.h" +#include "xMorph.h" +#include "xString.h" + +#include +#include +#include +#include + +#include +#include + +static xMemPool sxAnimTempTranPool; + +U32 gxAnimUseGrowAlloc = 0; + +static bool _xSingleCompare(char a, char b) +{ + switch (b) + { + case '?': + case '*': + case '+': + { + return true; + } + case '#': + { + return (a >= '0' && a <= '9'); + } + } + + return (a == b); +} + +static bool _xSingleCompare(char ch, const char* str) +{ + while (*str != '\0') + { + if (_xSingleCompare(ch, *str)) + { + return true; + } + + str++; + } + + return false; +} + +static bool _xCharIn(char ch, const char* str) +{ + while (*str != '\0') + { + if (ch == *str) + { + return true; + } + + str++; + } + + return false; +} + +static U8 _xCheckAnimNameInner(const char* name, const char* pattern, S32 patternSize, char* extra, + S32* nameOut, S32* extraOut) +{ + const char* startExtra = NULL; + char* initialExtra = extra; + S32 patternCurrent = 0; + S32 nameCurrent = 0; + while (patternCurrent < patternSize) + { + U32 check = pattern[patternCurrent]; + switch (check) + { + case '+': + case '?': + patternCurrent++; + if (nameCurrent == 0) + { + return 0; + } + nameCurrent++; + if (check != '?') + { + // Holy shit I hate this please tell me there's a better way + case '*': + check = patternCurrent + 1; + char nextPattern[128] = { 0 }; + nextPattern[0] = pattern[check]; + while (nextPattern[0] == '{' || nextPattern[0] == '}' || nextPattern[0] == '<' || + nextPattern[0] == '>') + { + check++; + nextPattern[0] = pattern[check]; + } + + if (nextPattern[0] == '(') + { + S32 nextPatternCount = 0; + U8 first = 1; + S32 parenCount = 0; + + while (pattern[check] != NULL && parenCount > -1) + { + if (pattern[check] == '(') + { + parenCount++; + } + else if (pattern[check] == ')') + { + parenCount--; + } + else if (parenCount == 0) + { + const char* IGNORE_PATTERNS = "{}()<>"; + if (pattern[check] == '|') + { + first = 1; + } + else if (first && _xCharIn(pattern[check], IGNORE_PATTERNS) == 0) + { + first = 0; + nextPattern[nextPatternCount++] = pattern[check]; + } + } + check++; + } + nextPattern[nextPatternCount] = NULL; + } + + while (name[nameCurrent] != NULL && + _xSingleCompare(name[nameCurrent], nextPattern) == 0) + { + nameCurrent++; + } + patternCurrent++; + } + break; + case '#': + if (name[nameCurrent] < '0' || name[nameCurrent] > '9') + { + return 0; + } + nameCurrent++; + + for (const char* x = &name[nameCurrent]; *x >= '0' && *x <= '9'; x++) + { + nameCurrent++; + } + patternCurrent++; + break; + case '{': + startExtra = &name[nameCurrent]; + patternCurrent++; + break; + case '}': + S32 length = &name[nameCurrent] - startExtra; + if (extra != NULL) + { + memcpy(extra, startExtra, length); + extra[length] = NULL; + extra = extra + length; + *++extra = '\x01'; + } + startExtra = NULL; + patternCurrent++; + break; + case '(': + patternCurrent++; + U8 done = 0; + const char* current = &pattern[patternCurrent]; + while (*current != ')' && *current != NULL) + { + const char* startPattern = current; + while (*startPattern != NULL && *startPattern != ')' && *startPattern != '|') + { + if (*startPattern == '(') + { + S32 pc = 1; + while (*startPattern != NULL && pc > 0) + { + if (*startPattern == ')') + { + pc--; + } + else if (*startPattern == '(') + { + pc++; + } + startPattern++; + } + if (*startPattern != NULL) + { + startPattern++; + } + } + else + { + startPattern++; + } + } + + if (startPattern != current) + { + S32 nameOut; + S32 extraOut; + + // NOTE (Square): There is no DWARF for an extra variable here and this programming pattern seems + // extremely wack. I think this "variable" is completely compiler generated for some reason + U8 wtfman = 0; + if (!done && + _xCheckAnimNameInner(&name[nameCurrent], current, startPattern - current, + extra, &nameOut, &extraOut)) + { + wtfman = 1; + } + + if (wtfman != 0) + { + done = 1; + nameCurrent += nameOut; + extra = extra + extraOut; + } + else if (extra != NULL) + { + *extra = '\x01'; + } + } + + current = startPattern; + if (*startPattern == '|') + { + current++; + } + } + if (*current != NULL) + { + current++; + } + patternCurrent += current - pattern; + if (!done) + { + return 0; + } + break; + case '<': + { + patternCurrent++; + const char* current = &pattern[patternCurrent]; + const char* positiveEnd = current; + while (*positiveEnd != NULL && *positiveEnd != ';' && *positiveEnd != '>') + { + positiveEnd++; + } + + const char* negative = NULL; + const char* negativeEnd = NULL; + + if (*positiveEnd == ';') + { + negativeEnd = positiveEnd + 1; + negative = negativeEnd; + while (*negativeEnd != NULL && *negativeEnd != '>') + { + negativeEnd++; + }; + positiveEnd = negativeEnd; + } + S32 nameOut; + S32 extraOut; + U8 matched = _xCheckAnimNameInner(&name[nameCurrent], current, positiveEnd - current, + extra, &nameOut, &extraOut); + if (matched != 0) + { + if (negative != NULL && + _xCheckAnimNameInner(&name[nameCurrent], negative, negativeEnd - negative, NULL, + NULL, NULL) != 0) + { + if (extra != NULL) + { + *extra = '\x01'; + } + matched = 0; + } + else + { + nameCurrent = nameCurrent + nameOut; + extra += extraOut; + } + } + + if (*positiveEnd != NULL) + { + positiveEnd++; + } + patternCurrent += &positiveEnd[patternCurrent] - &pattern[patternCurrent]; + if (matched == 0) + { + return 0; + } + break; + } + case NULL: + return 0; + case ')': + default: + if (name[nameCurrent] != pattern[patternCurrent]) + { + return 0; + } + nameCurrent++; + patternCurrent++; + break; + } + } + + if (nameOut != NULL) + { + *nameOut = nameCurrent; + } + if (extraOut != NULL) + { + *extraOut = extra - initialExtra; + } + return 1; +} + +static bool _xCheckAnimName(const char* name, const char* pattern, char* extra) +{ + S32 patternSize, nameOut; + U8 rc; + + *extra = 1; + patternSize = strlen(pattern); + + rc = _xCheckAnimNameInner(name, pattern, patternSize, extra, &nameOut, NULL); + + return (rc && name[nameOut] == '\0'); +} + +void xAnimInit() +{ + iAnimInit(); + memset(&sxAnimTempTranPool, 0, sizeof(xMemPool)); +} + +void xAnimTempTransitionInit(U32 count) +{ + xMemPoolSetup(&sxAnimTempTranPool, xMemAllocSize(count * sizeof(xAnimTransition)), 0, 0, NULL, + sizeof(xAnimTransition), count, count / 2); +} + +// TODO: move to xMathInlines.h +static F32 xatan2(F32 y, F32 x) +{ + return xAngleClampFast(std::atan2f(y, x)); +} + +#ifndef INLINE +float std::atan2f(float y, float x) +{ + return (float)atan2((double)y, (double)x); +} +#endif + +float CalcRecipBlendMax(U16* arg0) +{ + float max = 0.0f; + while (arg0[0] != 0xFFFF) + { + float f3; + if (arg0[1] == 0) + { + f3 = 0.0f; + } + else + { + f3 = 1.0f / (0.0009765625f * arg0[1]); + } + + f3 = 0.001f * arg0[0] + f3; + if (f3 > max) + { + max = f3; + } + arg0 += 2; + } + + if (max == 0.0f) + { + return 0.0f; + } + return 1.0f / max; +} + +static U32 StateHasTransition(xAnimState* state, xAnimTransition* tran) +{ + xAnimTransitionList* curr = state->List; + + while (curr) + { + if (curr->T == tran) + { + return TRUE; + } + + curr = curr->Next; + } + + return FALSE; +} + +static U32 DefaultHasTransition(xAnimState* state, xAnimTransition* tran, U32* r5) +{ + U32 r7 = 1; + xAnimTransitionList* curr = state->Default; + + while (curr) + { + if (curr->T == tran) + { + return TRUE; + } + + if (curr->T->Conditional == tran->Conditional && curr->T->UserFlags == tran->UserFlags) + { + r7 = 0; + } + + curr = curr->Next; + } + + *r5 += r7; + return FALSE; +} + +static U32 DefaultOverride(xAnimState* state, xAnimTransition* tran) +{ + xAnimTransitionList* list = state->Default; + + while (list) + { + if (list->T->Conditional == tran->Conditional && list->T->UserFlags == tran->UserFlags) + { + list->T = tran; + return TRUE; + } + + list = list->Next; + } + + return FALSE; +} + +static void TransitionTimeInit(xAnimSingle* single, xAnimTransition* tran) +{ + if (tran->Flags & 0x20) + { + if ((tran->Dest->Data->FileFlags ^ single->State->Data->FileFlags) & 0x1000) + { + single->Time = tran->Dest->Data->Duration - single->Time; + } + } + else + { + single->Time = ((tran->Dest->Flags & 0x100) && tran->DestTime == 0.0f) ? + single->State->Data->Duration * xurand() : + tran->DestTime; + } + single->LastTime = single->Time; +} + +xAnimFile* xAnimFileNewBilinear(void** rawData, const char* name, U32 flags, xAnimFile** linkedList, + U32 numX, U32 numY) +{ + xAnimFile* afile; + if (gxAnimUseGrowAlloc) + { + afile = (xAnimFile*)xMemGrowAlloc(gActiveHeap, numX * numY * 4 + sizeof(xAnimFile)); + } + else + { + afile = (xAnimFile*)xMemAlloc(gActiveHeap, numX * numY * 4 + sizeof(xAnimFile), 0); + } + + if (numX > 1 || numY > 1) + { + flags |= 0x4000; + } + + if (**(U32**)rawData == 'QSPM') + { + flags |= 0x8000; + } + + if (linkedList != NULL) + { + afile->Next = *linkedList; + *linkedList = afile; + } + else + { + afile->Next = NULL; + } + + afile->RawData = (void**)&afile[1]; + for (S32 i = 0; i < (S32)numX * (S32)numY; ++i) + { + afile->RawData[i] = rawData[i]; + } + + afile->Name = name; + afile->ID = xStrHash(name); + afile->FileFlags = flags; + + F32 dur; + if (afile->FileFlags & 0x2000) + { + if (afile->FileFlags & 0x8000) + { + dur = xMorphSeqDuration(*(xMorphSeqFile**)afile->RawData); + } + else + { + dur = iAnimDuration(*afile->RawData); + } + dur = dur * 2.0f; + } + else if (afile->FileFlags & 0x8000) + { + dur = xMorphSeqDuration(*(xMorphSeqFile**)afile->RawData); + } + else + { + dur = iAnimDuration(*afile->RawData); + } + afile->Duration = dur; + afile->TimeOffset = 0.0f; + + afile->BoneCount = flags & 0x8000 ? 0 : iAnimBoneCount(*rawData); + + afile->NumAnims[0] = numX; + afile->NumAnims[1] = numY; + + return afile; +} + +xAnimFile* xAnimFileNew(void* rawData, const char* name, U32 flags, xAnimFile** linkedList) +{ + return xAnimFileNewBilinear(&rawData, name, flags, linkedList, 1, 1); +} + +void xAnimFileSetTime(xAnimFile* data, float duration, float timeOffset) +{ + F32 rawDuration; + if (data->FileFlags & 0x8000) + { + rawDuration = xMorphSeqDuration(*(xMorphSeqFile**)data->RawData); + } + else + { + rawDuration = iAnimDuration(*data->RawData); + } + + if (timeOffset > rawDuration - 0.1f) + { + timeOffset = rawDuration - 0.1f; + } + + data->TimeOffset = timeOffset; + if (duration > rawDuration - timeOffset) + { + duration = rawDuration - timeOffset; + } + + data->Duration = (data->FileFlags & 0x2000) ? 2.0f * duration : duration; +} + +void xAnimFileEval(xAnimFile* data, F32 time, F32* bilinear, U32 flags, xVec3* tran, xQuat* quat, + F32* arg6) +{ + S32 i; + U32 numBones; + F32 bilerp[2]; + U32 biindex[2]; + U32 biplus[2]; + xQuat* q0; + xVec3* t0; + xQuat* q1; + xVec3* t1; + + time = xAnimFileRawTime(data, CLAMP(time, 0.0f, data->Duration)); + if (data->FileFlags & 0x8000) + { + return; + } + + if (flags & 0x1) + { + numBones = 1; + } + else + { + numBones = data->BoneCount; + } + + if (flags & 0x2) + { + numBones--; + } + + if (numBones == 0) + { + return; + } + + if (bilinear != NULL && data->FileFlags & 0x4000) + { + for (i = 0; i < 2; ++i) + { + F32 f30 = CLAMP(bilinear[i], 0.0f, data->NumAnims[i] - 1); + f32 t = std::floorf(f30); + bilerp[i] = f30 - t; + biindex[i] = t; + biplus[i] = MIN(biindex[i] + 1, data->NumAnims[i]); + } + + q0 = (xQuat*)(giAnimScratch + 0x1560); + t0 = (xVec3*)((U8*)q0 + 0x410); + if (bilerp[0] && bilerp[1]) + { + q1 = (xQuat*)(giAnimScratch + 0x1c80); + t1 = (xVec3*)((U8*)q1 + 0x410); + + iAnimEval(data->RawData[biindex[0] + biindex[1] * data->NumAnims[0]], time, flags, tran, + quat); + iAnimEval(data->RawData[biplus[0] + biindex[1] * data->NumAnims[0]], time, flags, t0, + q0); + iAnimBlend(bilerp[0], 1.0f, NULL, NULL, numBones, tran, quat, t0, q0, tran, quat); + + iAnimEval(data->RawData[biindex[0] + biplus[1] * data->NumAnims[0]], time, flags, t0, + q0); + iAnimEval(data->RawData[biplus[0] + biplus[1] * data->NumAnims[0]], time, flags, t1, + q1); + iAnimBlend(bilerp[0], 1.0f, NULL, NULL, numBones, t0, q0, t1, q1, t0, q0); + iAnimBlend(bilerp[1], 1.0f, NULL, NULL, numBones, tran, quat, t0, q0, tran, quat); + } + else if (bilerp[0]) + { + iAnimEval(data->RawData[biindex[0] + biindex[1] * data->NumAnims[0]], time, flags, tran, + quat); + iAnimEval(data->RawData[biplus[0] + biindex[1] * data->NumAnims[0]], time, flags, t0, + q0); + iAnimBlend(bilerp[0], 1.0f, NULL, NULL, numBones, tran, quat, t0, q0, tran, quat); + } + else if (bilerp[1]) + { + iAnimEval(data->RawData[biindex[0] + biindex[1] * data->NumAnims[0]], time, flags, tran, + quat); + iAnimEval(data->RawData[biindex[0] + biplus[1] * data->NumAnims[0]], time, flags, t0, + q0); + iAnimBlend(bilerp[0], 1.0f, NULL, NULL, numBones, tran, quat, t0, q0, tran, quat); + } + else + { + iAnimEval(data->RawData[biindex[0] + biindex[1] * data->NumAnims[0]], time, flags, tran, + quat); + } + } + else + { + iAnimEval(data->RawData[0], time, flags, tran, quat); + } +} + +#ifndef INLINE +float std::floorf(float x) +{ + return (float)floor((double)x); +} +#endif + +xAnimEffect* xAnimStateNewEffect(xAnimState* state, U32 flags, F32 startTime, F32 endTime, + xAnimEffectCallback callback, U32 userDataSize) +{ + xAnimEffect* curr; + xAnimEffect** prev; + xAnimEffect* effect; + + effect = + (gxAnimUseGrowAlloc ? (xAnimEffect*)xMemGrowAllocSize(userDataSize + sizeof(xAnimEffect)) : + (xAnimEffect*)xMemAllocSize(userDataSize + sizeof(xAnimEffect))); + + effect->Flags = flags; + effect->StartTime = startTime; + effect->EndTime = endTime; + effect->Callback = callback; + + prev = &state->Effects; + curr = state->Effects; + + while (curr && startTime > curr->StartTime) + { + prev = &curr->Next; + curr = curr->Next; + } + + effect->Next = curr; + *prev = effect; + + return effect; +} + +xAnimTable* xAnimTableNew(const char* name, xAnimTable** linkedList, U32 userFlags) +{ + xAnimTable* table; + + table = (xAnimTable*)xMemAllocSize(sizeof(xAnimTable)); + + if (linkedList) + { + table->Next = *linkedList; + *linkedList = table; + } + else + { + table->Next = NULL; + } + + table->Name = name; + table->TransitionList = NULL; + table->StateList = NULL; + table->AnimIndex = NULL; + table->MorphIndex = NULL; + table->UserFlags = userFlags; + + return table; +} + +void xAnimDefaultBeforeEnter(xAnimPlay* play, xAnimState* state) +{ + U32 entry; + + if (state->MultiFile) + { + entry = rand() % state->MultiFile->Count; + + state->Data = state->MultiFile->Files[entry].File; + } +} + +xAnimState* xAnimTableNewState(xAnimTable* table, const char* name, U32 flags, U32 userFlags, + F32 speed, F32* boneBlend, F32* timeSnap, F32 fadeRecip, + U16* fadeOffset, void* callbackData, + xAnimStateBeforeEnterCallback beforeEnter, + xAnimStateCallback stateCallback, + xAnimStateBeforeAnimMatricesCallback beforeAnimMatrices) +{ + xAnimState* state; + + state = (gxAnimUseGrowAlloc ? (xAnimState*)xMemGrowAllocSize(sizeof(xAnimState)) : + (xAnimState*)xMemAllocSize(sizeof(xAnimState))); + + if (!table->StateList) + { + state->Next = NULL; + table->StateList = state; + } + else + { + state->Next = table->StateList->Next; + table->StateList->Next = state; + } + + state->Name = name; + state->ID = xStrHash(name); + state->Flags = flags; + state->UserFlags = userFlags; + state->Speed = speed; + state->Data = NULL; + state->Effects = NULL; + state->Default = NULL; + state->List = NULL; + state->BoneBlend = boneBlend; + state->TimeSnap = timeSnap; + state->FadeRecip = (fadeOffset ? CalcRecipBlendMax(fadeOffset) : fadeRecip); + state->FadeOffset = fadeOffset; + state->MultiFile = NULL; + state->CallbackData = callbackData; + state->BeforeEnter = beforeEnter; + state->StateCallback = stateCallback; + state->BeforeAnimMatrices = beforeAnimMatrices; + + return state; +} + +static void _xAnimTableAddTransitionHelper(xAnimState* state, xAnimTransition* tran, + U32& stateCount, U32& allocCount, xAnimState** stateList) +{ + if (tran->Flags & 0x10) + { + if (!DefaultHasTransition(state, tran, &stateCount)) + { + stateList[allocCount] = state; + allocCount++; + } + } + else + { + if (!StateHasTransition(state, tran)) + { + stateList[allocCount] = state; + allocCount++; + stateCount++; + } + } +} + +// WIP +void _xAnimTableAddTransition(xAnimTable* table, xAnimTransition* tran, const char* source, + const char* dest) +{ + // unsigned char * buffer; // r29+0x110 + // class xAnimState * * stateList; // r29+0x100 + // unsigned int i; // r4 + // unsigned int stateCount; // r30 + // unsigned int allocCount; // r21 + // char * stateName; // r29+0xFC + // class xAnimTransitionList * tlist; // r29+0xE0 + // class xAnimTransition * substTransitionList[32]; // r29+0x230 + // unsigned int substTransitionCount; // r29+0xD0 + // unsigned char hasSubst; // r29+0xC0 + // signed int i; // r5 + // unsigned char isComplex; // r8 + // char * COMPLEX_PATTERNS; // r7 + // char * search; // r6 + // class xAnimState * state; // r23 + // char extra[128]; // r29+0x1B0 + // char tempName[128]; // r29+0x130 + // char * tempIterator; // r19 + // char * extraIterator; // r18 + // unsigned char allowMissingState; // r29+0xB0 + // signed int i; // r17 + // unsigned int extraIteratorLength; // r16 + // class xAnimTransition * duplicatedTransition; // r17 + // class xAnimTransitionList * curr; // r7 + + U8* buffer = (U8*)giAnimScratch; + xAnimState** stateList = (xAnimState**)(giAnimScratch + 0x400); + S32 i; + U32 stateCount = 0; + U32 allocCount = 0; + + xAnimTransitionList* tlist; + xAnimTransition* substTransitionList[32]; + + char extra[128]; + char tempName[128]; + + U8 bVar2 = false; + U8 bVar1 = false; + S32 iVar12 = 0; + + if (dest != NULL) + { + for (S32 i = 0; dest[i] != NULL; ++i) + { + if (dest[i] == '@' || dest[i] == '~') + { + bVar2 = true; + break; + } + } + } + + for (char* x = xStrTokBuffer(source, " ,\t\n\r", table); x != NULL; + x = xStrTokBuffer(source, " ,\t\n\r", table)) + { + bVar1 = dest != NULL; + if (!bVar1) + { + for (char* it = x; *it != NULL; ++it) + { + if (_xCharIn(*it, "#+*?{}()<>|;") != 0) + { + bVar1 = true; + break; + } + } + } + + if (bVar1) + { + for (xAnimState* state = table->StateList; state != NULL; state = state->Next) + { + if (_xCheckAnimName(state->Name, x, tempName)) + { + if (bVar2) + { + for (const char* tempIterator = dest; *tempIterator != NULL; ++tempIterator) + { + if (*dest == '@' || *dest == '~') + { + bVar1 = *dest == '~'; + U32 l = strlen(tempName); + strcpy(extra, tempName); + } + else + { + *extra = *dest; + } + } + *extra = NULL; + xAnimState* sp = xAnimTableGetState(table, extra); + if (bVar1 && sp == NULL) + { + continue; + } + + xAnimTransition* duplicatedTransition = tran; + if (iVar12 != 0) + { + if (gxAnimUseGrowAlloc) + { + duplicatedTransition = (xAnimTransition*)xMemGrowAlloc( + gActiveHeap, sizeof(xAnimTransition)); + } + else + { + duplicatedTransition = (xAnimTransition*)xMemAlloc( + gActiveHeap, sizeof(xAnimTransition), 0); + } + memcpy(duplicatedTransition, tran, sizeof(xAnimTransition)); + } + duplicatedTransition->Dest = sp; + iVar12++; + substTransitionList[iVar12] = duplicatedTransition; + } + if (tran->Dest != state) + { + _xAnimTableAddTransitionHelper(state, tran, stateCount, allocCount, + stateList); + } + } + } + } + else + { + xAnimState* ssp = xAnimTableGetState(table, x); + if (ssp != NULL && tran->Dest != ssp) + { + _xAnimTableAddTransitionHelper(ssp, tran, stateCount, allocCount, stateList); + } + } + } + + xAnimTransitionList* curr; + if (stateCount != 0) + { + if (gxAnimUseGrowAlloc) + { + curr = (xAnimTransitionList*)xMemGrowAlloc(gActiveHeap, + stateCount * sizeof(xAnimTransitionList)); + } + else + { + curr = (xAnimTransitionList*)xMemAlloc(gActiveHeap, + stateCount * sizeof(xAnimTransitionList), 0); + } + } + if (tran->Flags & 0x10) + { + for (S32 i = 0; i < allocCount; ++i) + { + if (DefaultOverride(stateList[i], tran) == 0) + { + if (tran->Conditional == NULL && stateList[i]->Default != NULL) + { + curr->Next = NULL; + curr->T = bVar2 ? substTransitionList[i] : tran; + } + } + else + { + curr->T = bVar2 ? substTransitionList[i] : tran; + stateList[i]->Default = curr; + } + } + } + else + { + if (bVar2) + { + for (S32 i = 0; i < allocCount; ++i) + { + curr->T = substTransitionList[i]; + curr->Next = stateList[i]->List->Next; + } + } + else + { + for (S32 i = 0; i < allocCount; ++i) + { + curr->T = tran; + curr->Next = stateList[i]->List->Next; + } + } + } +} + +void xAnimTableAddTransition(xAnimTable* table, xAnimTransition* tran, const char* source) +{ + _xAnimTableAddTransition(table, tran, source, NULL); +} + +xAnimTransition* xAnimTableNewTransition(xAnimTable* table, const char* source, const char* dest, + xAnimTransitionConditionalCallback conditional, + xAnimTransitionCallback callback, U32 flags, U32 userFlags, + F32 srcTime, F32 destTime, U16 priority, U16 queuePriority, + F32 blendRecip, U16* blendOffset) +{ + xAnimTransition* tran; + if (gxAnimUseGrowAlloc) + { + tran = (xAnimTransition*)xMemGrowAllocSize(sizeof(xAnimTransition)); + } + else + { + tran = (xAnimTransition*)xMemAllocSize(sizeof(xAnimTransition)); + } + + if (blendRecip != 0.0f) + { + blendRecip = 1.0f / blendRecip; + } + + tran->Next = table->TransitionList; + table->TransitionList = tran; + + U8 isComplex = FALSE; + if (dest == NULL || *dest == NULL) + { + tran->Dest = NULL; + } + else + { + for (S32 i = 0; dest[i] != NULL; ++i) + { + if (dest[i] == '@' || dest[i] == '~') + { + isComplex = true; + break; + } + } + tran->Dest = isComplex ? NULL : xAnimTableGetState(table, dest); + } + + tran->Conditional = conditional; + tran->Callback = callback; + tran->Flags = flags; + tran->UserFlags = userFlags; + tran->SrcTime = srcTime; + tran->DestTime = destTime; + tran->Priority = priority; + tran->QueuePriority = queuePriority; + + tran->BlendRecip = blendOffset != NULL ? CalcRecipBlendMax(blendOffset) : blendRecip; + tran->BlendOffset = blendOffset; + + _xAnimTableAddTransition(table, tran, source, isComplex ? dest : NULL); + + return tran; +} + +void xAnimTableAddFile(xAnimTable* table, xAnimFile* file, const char* states) +{ + U8* buffer = (U8*)giAnimScratch; + char* stateName = xStrTokBuffer(states, " ,\t\n\r", buffer); + while (stateName != NULL) + { + xAnimTableAddFileID(table, file, xStrHash(stateName), 0, 0); + stateName = xStrTokBuffer(NULL, " ,\t\n\r", buffer); + } +} + +xAnimState* xAnimTableGetStateID(xAnimTable* table, U32 ID); + +xAnimState* xAnimTableAddFileID(xAnimTable* table, xAnimFile* file, U32 stateID, U32 subStateID, + U32 subStateCount) +{ + xAnimState* state; + + state = xAnimTableGetStateID(table, stateID); + + if (state) + { + if (subStateID) + { + if (!state->MultiFile) + { + state->MultiFile = + (gxAnimUseGrowAlloc ? (xAnimMultiFile*)xMemGrowAllocSize( + subStateCount * sizeof(xAnimMultiFileEntry) + + sizeof(xAnimMultiFileBase)) : + (xAnimMultiFile*)xMemAllocSize( + subStateCount * sizeof(xAnimMultiFileEntry) + + sizeof(xAnimMultiFileBase))); + + state->MultiFile->Count = 0; + } + + U32 count = state->MultiFile->Count; + + state->MultiFile->Files[count].ID = subStateID; + state->MultiFile->Files[count].File = file; + + state->MultiFile->Count++; + } + + state->Data = file; + + if (file->FileFlags & 0x8000) + { + table->MorphIndex |= (1 << (state->Flags & 0xF)); + } + else + { + table->AnimIndex |= (1 << (state->Flags & 0xF)); + } + } + + return state; +} + +xAnimState* xAnimTableGetStateID(xAnimTable* table, U32 ID) +{ + xAnimState* curr; + + curr = table->StateList; + + while (curr) + { + if (curr->ID == ID) + { + return curr; + } + + curr = curr->Next; + } + + return NULL; +} + +xAnimState* xAnimTableGetState(xAnimTable* table, const char* name) +{ + return xAnimTableGetStateID(table, xStrHash(name)); +} + +static void EffectActiveInsert(xAnimSingle* single, xAnimActiveEffect* active) +{ + U32 index = 0; + U32 count = single->ActiveCount; + xAnimActiveEffect* curr = &single->ActiveList[0]; + + while (index < count && curr->Effect) + { + curr++; + index++; + } + + *curr = *active; + + if (index < count - 1) + { + (curr + 1)->Effect = NULL; + } +} + +static void EffectActiveRemove(xAnimActiveEffect* active, U32 index, U32 count) +{ + count--; + + if (index == count || !(active + 1)->Effect) + { + active->Effect = NULL; + } + else + { + xAnimActiveEffect* curr = active; + + while (index < count && (curr + 1)->Effect) + { + curr++; + index++; + } + + *active = *curr; + curr->Effect = NULL; + } +} + +static U32 EffectPlaying(xAnimSingle* single, xAnimEffect* effect) +{ + U32 index = 0; + + while (index < single->ActiveCount && single->ActiveList[index].Effect) + { + if (single->ActiveList[index].Effect == effect) + { + return TRUE; + } + + index++; + } + + return FALSE; +} + +static void EffectSingleStart(xAnimSingle* single) +{ + xAnimEffect* effect = single->State->Effects; + xAnimActiveEffect tempActive; + F32 time = single->Time; + U32 flags; + + while (effect && effect->StartTime < time) + { + flags = effect->Flags; + + if (flags & 0x1) + { + if (flags & 0x4) + { + tempActive.Effect = effect; + tempActive.Handle = effect->Callback(1, &tempActive, single, single->Play->Object); + + flags = effect->Flags; + + if (flags & 0x2) + { + if (effect->EndTime <= time) + { + effect->Callback(3, &tempActive, single, single->Play->Object); + } + else + { + EffectActiveInsert(single, &tempActive); + } + } + else if (flags & 0x20) + { + EffectActiveInsert(single, &tempActive); + } + } + else if ((flags & 0x2) && !(flags & 0x10) && effect->EndTime > time) + { + tempActive.Effect = effect; + tempActive.Handle = effect->Callback(1, &tempActive, single, single->Play->Object); + + EffectActiveInsert(single, &tempActive); + } + } + + effect = effect->Next; + } + + single->Effect = effect; +} + +static void EffectSingleDuration(xAnimSingle* single) +{ + F32 time = single->Time; + xAnimActiveEffect* alist = single->ActiveList; + U32 index = 0; + U32 count = single->ActiveCount; + + while (index < count && alist->Effect) + { + if (!(alist->Effect->Flags & 0x20) && alist->Effect->EndTime <= time) + { + alist->Effect->Callback(3, alist, single, single->Play->Object); + + EffectActiveRemove(alist, index, count); + } + else + { + alist->Effect->Callback(2, alist, single, single->Play->Object); + + alist++; + index++; + } + } +} + +static void EffectSingleRun(xAnimSingle* single) +{ + xAnimEffect* effect = single->Effect; + xAnimActiveEffect tempActive; + F32 time = single->Time; + U32 flags; + + while (effect && effect->StartTime <= time) + { + flags = effect->Flags; + + if ((flags & 0x1) && (!(flags & 0x20) || !EffectPlaying(single, effect))) + { + tempActive.Effect = effect; + tempActive.Handle = effect->Callback(1, &tempActive, single, single->Play->Object); + + if (flags & 0x2) + { + if (effect->EndTime <= time) + { + effect->Callback(3, &tempActive, single, single->Play->Object); + } + else + { + EffectActiveInsert(single, &tempActive); + } + } + else if (flags & 0x20) + { + EffectActiveInsert(single, &tempActive); + } + } + + effect = effect->Next; + } + + single->Effect = effect; +} + +static void EffectSingleLoop(xAnimSingle* single) +{ + EffectSingleRun(single); + xAnimActiveEffect* alist = single->ActiveList; + U32 index = 0; + U32 count = single->ActiveCount; + while (index < count && alist[index].Effect != NULL) + { + if (!(alist[index].Effect->Flags & 0x20)) + { + alist[index].Effect->Callback(3, &alist[index], single, single->Play->Object); + + EffectActiveRemove(&alist[index], index, count); + } + else + { + index++; + } + } + + xAnimEffect* effect = single->State->Effects; + while (effect != NULL && effect->StartTime < 0.0f) + { + effect = effect->Next; + } + single->Effect = effect; +} + +static void EffectSingleStop(xAnimSingle* single) +{ + if (single->State == NULL || single->LastTime == -1.0f) + { + return; + } + + for (U32 i = 0; single->ActiveCount > i && single->ActiveList[i].Effect != NULL; ++i) + { + if (single->ActiveList[i].Effect->Flags & 0x2) + { + single->ActiveList[i].Effect->Callback(3, &single->ActiveList[i], single, + single->Play->Object); + } + } + + single->ActiveList->Effect = NULL; + for (xAnimEffect* effect = single->Effect; effect != NULL; effect = effect->Next) + { + xAnimActiveEffect tempActive; + if ((effect->Flags & 0x9) == 0x9) + { + tempActive.Effect = effect; + tempActive.Handle = effect->Callback(1, &tempActive, single, single->Play->Object); + + if (effect->Flags & 0x2) + { + effect->Callback(3, &tempActive, single, single->Play->Object); + } + } + } + + single->Effect = NULL; +} + +static void StopUpdate(xAnimSingle* single) +{ + if (single->Time > single->State->Data->Duration) + { + single->Time = single->State->Data->Duration; + single->CurrentSpeed = 0.0f; + } +} + +static void LoopUpdate(xAnimSingle* single) +{ + F32 time = single->Time; + F32 duration = single->State->Data->Duration; + + if (time > duration) + { + single->Time = duration; + + EffectSingleLoop(single); + + single->Time = time - duration; + } +} + +void xAnimPlaySetState(xAnimSingle* single, xAnimState* state, F32 startTime) +{ + EffectSingleStop(single); + if (single->Blend) + { + EffectSingleStop(single->Blend); + single->Blend->State = NULL; + } + + single->State = state; + if (state == NULL) + { + return; + } + + single->Time = + (state->Flags & 0x100 && startTime == 0.0f) ? state->Data->Duration * xurand() : startTime; + single->CurrentSpeed = state->Speed; + single->BilinearLerp[0] = 0.0f; + single->BilinearLerp[1] = 0.0f; + single->Effect = NULL; + memset(single->ActiveList, 0, single->ActiveCount * sizeof(xAnimActiveEffect)); + single->LastTime = -1.0f; + single->Sync = NULL; + + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + + single->Tran = NULL; + single->BlendFactor = 0.0f; +} + +static void SingleUpdate(xAnimSingle* single, F32 timeDelta) +{ + U32 foundBlendstop = 0; + U32 firstStep = 1; + xAnimTransition* foundTransition = NULL; + xAnimSingle* bl = NULL; + F32 tranDelta = 0.0f; + F32 blendDelta = 0.0f; + F32 singleTime; + if (single->State == NULL) + { + return; + } + + void* object = single->Play->Object; + if (single->LastTime == -1.0f) + { + EffectSingleStart(single); + } + + single->LastTime = single->Time; + singleTime = timeDelta * single->CurrentSpeed + single->Time; + + if (single->Blend != NULL && single->Blend->State != NULL) + { + bl = single->Blend; + if (bl->LastTime == -1.0f) + { + EffectSingleStart(bl); + } + bl->LastTime = bl->Time; + } + + F32 duration = single->State->Data->Duration; + if (single->Sync != NULL) + { + // FIXME: assignment in the loop seems unlikely but assigning at the + // declaration swaps instructions. + F32 timeCmp; + if ((timeCmp = single->Sync->SrcTime) != 0.0f) + { + if (timeCmp > duration) + { + timeCmp = duration; + } + if (single->LastTime <= timeCmp && singleTime >= timeCmp) + { + foundTransition = single->Sync; + tranDelta = (singleTime - timeCmp) / single->CurrentSpeed; + timeDelta = timeDelta - tranDelta; + if (timeDelta < 0.0f) + { + timeDelta = 0.0f; + } + } + else + { + timeCmp += duration; + if (single->LastTime <= timeCmp && singleTime >= timeCmp) + { + foundTransition = single->Sync; + tranDelta = (singleTime - timeCmp) / single->CurrentSpeed; + timeDelta = timeDelta - tranDelta; + if (timeDelta < 0.0f) + { + timeDelta = 0.0f; + } + } + } + } + else if (bl == NULL) + { + foundTransition = single->Sync; + tranDelta = timeDelta; + timeDelta = 0.0f; + } + } + else + { + if ((single->State->Flags & 0x30) == 0x20) + { + F32 timeCmp = single->State->Default->T->SrcTime; + + if (timeCmp == 0.0f || timeCmp > duration) + { + timeCmp = duration; + } + + if (singleTime >= timeCmp && + ((single->State->Default->T->Flags & 0x4) == 0 || bl == NULL)) + { + xAnimTransitionList* curr = single->State->Default; + while (curr != NULL && curr->T->Conditional != NULL && + curr->T->Conditional(curr->T, single, object) == 0) + { + curr = curr->Next; + } + + if (curr == NULL) + { + fprintf(stderr, "State \"%s\" no default conditionals true!\n", + single->State->Name); + curr = single->State->Default; + } + + foundTransition = curr->T; + if (single->LastTime < timeCmp) + { + tranDelta = (singleTime - timeCmp) / single->CurrentSpeed; + timeDelta = timeDelta - tranDelta; + if (timeDelta < 0.0f) + { + timeDelta = 0.0f; + } + } + else + { + tranDelta = timeDelta; + timeDelta = 0.0f; + } + } + } + } + + if (single->BlendFactor != 0.0f) + { + F32 recip; + if (single->Tran != NULL) + { + recip = single->Tran->BlendRecip; + } + else + { + recip = single->State->FadeRecip; + } + + if (recip * (single->BlendFactor + timeDelta) > 1.0f) + { + foundBlendstop = 1; + blendDelta = (single->BlendFactor + timeDelta) - (1.0f / recip); + timeDelta = timeDelta - blendDelta; + if (timeDelta < 0.0f) + { + timeDelta = 0.0f; + } + if (blendDelta < 0.0f) + { + blendDelta = 0.01f; + } + } + } + + do + { + if (!firstStep) + { + if (foundBlendstop) + { + single->BlendFactor = 0.0f; + if (bl != NULL) + { + EffectSingleStop(bl); + bl->State = NULL; + bl = NULL; + + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + single->Tran = NULL; + } + else + { + if (single->Tran != NULL) + { + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + single->Tran = NULL; + } + else + { + EffectSingleStop(single); + single->State = NULL; + return; + } + } + timeDelta = blendDelta; + foundBlendstop = FALSE; + } + else + { + if (bl != NULL) + { + EffectSingleStop(bl); + bl->State = NULL; + bl = NULL; + single->BlendFactor = 0.0f; + } + if (foundTransition->BlendRecip == 0.0f || single->Blend == NULL) + { + EffectSingleStop(single); + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + single->Tran = NULL; + } + else + { + bl = single->Blend; + bl->State = single->State; + bl->Time = single->Time; + bl->CurrentSpeed = single->CurrentSpeed; + bl->BilinearLerp[0] = single->BilinearLerp[0]; + bl->BilinearLerp[1] = single->BilinearLerp[1]; + bl->Effect = single->Effect; + bl->LastTime = single->LastTime; + memcpy(bl->ActiveList, single->ActiveList, + single->ActiveCount * sizeof(xAnimTransitionList)); + single->ActiveList->Effect = NULL; + + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + single->Tran = foundTransition; + single->BlendFactor = 0.0000001f; + } + + TransitionTimeInit(single, foundTransition); + single->State = foundTransition->Dest; + single->CurrentSpeed = single->State->Speed; + single->BilinearLerp[0] = 0.0f; + single->BilinearLerp[1] = 0.0f; + single->Sync = NULL; + EffectSingleStart(single); + + if (foundTransition->Dest->BeforeEnter != NULL) + { + foundTransition->Dest->BeforeEnter(single->Play, foundTransition->Dest); + } + if (foundTransition->Callback != NULL) + { + foundTransition->Callback(foundTransition, single, single->Play->Object); + } + timeDelta = tranDelta; + foundTransition = NULL; + } + } + + single->Time = timeDelta * single->CurrentSpeed + single->Time; + if (single->BlendFactor != 0.0f) + { + single->BlendFactor += timeDelta; + } + if ((single->State->Flags & 0x30) == 0x10) + { + LoopUpdate(single); + } + else + { + StopUpdate(single); + } + EffectSingleRun(single); + + if (bl != NULL) + { + if ((bl->State->Flags & 0x30) == 0x10) + { + LoopUpdate(bl); + } + else + { + StopUpdate(bl); + } + EffectSingleRun(bl); + } + + firstStep = FALSE; + } while (foundBlendstop || foundTransition != NULL); + + if (single->Tran == NULL && single->BlendFactor == 0.0f) + { + if ((single->State->Flags & 0x30) == 0x30) + { + if (single->State->Flags & 0x200) + { + if (single->Time >= duration) + { + single->BlendFactor = 0.0000001f; + } + } + else if (single->State->FadeRecip * (duration - single->Time) < 1.0f) + { + single->BlendFactor = 0.0000001f; + } + } + } + EffectSingleDuration(single); + if (bl != NULL) + { + EffectSingleDuration(bl); + } +} + +static void SingleEval(xAnimSingle* single, xVec3* tran, xQuat* quat) +{ + if (single->Play->BoneCount > 1) + { + xAnimFileEval(single->State->Data, single->Time, single->BilinearLerp, 0x2, tran + 1, + quat + 1, NULL); + + if (single->Blend && single->Blend->State) + { + xQuat* qbuf = (xQuat*)(giAnimScratch + 0xE40); + xVec3* vbuf = (xVec3*)(qbuf + 0x41); + + xAnimFileEval(single->Blend->State->Data, single->Blend->Time, + single->Blend->BilinearLerp, 0x2, vbuf, qbuf, NULL); + + iAnimBlend(single->BlendFactor, single->Tran->BlendRecip, single->Tran->BlendOffset, + NULL, single->Play->BoneCount - 1, vbuf, qbuf, tran + 1, quat + 1, tran + 1, + quat + 1); + } + } +} + +void xAnimPlaySetup(xAnimPlay* play, void* object, xAnimTable* table, xModelInstance* modelInst) +{ + play->BoneCount = modelInst->BoneCount; + play->Object = object; + play->Table = table; + play->ModelInst = modelInst; + + modelInst->Anim = play; + modelInst->Flags |= 0x104; + + if (table->MorphIndex != 0) + { + modelInst->Flags |= 0x80; + } + + for (S32 i = 0; i < play->NumSingle; ++i) + { + play->Single[i].SingleFlags = (1 << i & table->MorphIndex) ? 0x8000 : 0x1; + play->Single[i].State = NULL; + play->Single[i].Tran = NULL; + if (play->Single[i].Blend != NULL) + { + play->Single[i].Blend->State = NULL; + } + } + xAnimPlaySetState(play->Single, table->StateList, 0.0f); +} + +void xAnimPlayChooseTransition(xAnimPlay* play) +{ + U32 i; + void* object = play->Object; + xAnimTransition** list = (xAnimTransition**)giAnimScratch; + xAnimTransition** found; + xAnimTransitionList* curr; + + memset(list, 0, play->NumSingle * sizeof(xAnimTransition*)); + + for (i = 0; i < play->NumSingle; i++) + { + if (play->Single[i].State) + { + curr = play->Single[i].State->List; + + if (curr && curr->T->Conditional) + { + while (curr) + { + if (curr->T->Conditional(curr->T, &play->Single[i], object)) + { + found = &list[curr->T->Dest->Flags & 0xF]; + + if (!*found || curr->T->Priority > (*found)->Priority) + { + *found = curr->T; + } + } + + curr = curr->Next; + } + } + } + } + + for (i = 0; i < play->NumSingle; i++) + { + if (list[i] && + (!play->Single[i].Sync || list[i]->Priority > play->Single[i].Sync->QueuePriority)) + { + xAnimPlayStartTransition(play, list[i]); + } + } +} + +void xAnimPlayStartTransition(xAnimPlay* play, xAnimTransition* transition) +{ + xAnimSingle* single = &play->Single[transition->Dest->Flags & 0xf]; + xAnimSingle* bl = single->Blend; + + if (transition->SrcTime != 0.0f || (transition->Flags & 0x4 && bl != NULL && bl->State)) + { + single->Sync = transition; + return; + } + + if (bl != NULL && bl->State != NULL) + { + EffectSingleStop(bl); + bl->State = NULL; + single->BlendFactor = 0.0f; + } + + if (transition->BlendRecip == 0.0f || single->Blend == NULL) + { + EffectSingleStop(single); + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + single->Tran = NULL; + } + else + { + if (single->State != NULL) + { + bl->State = single->State; + bl->Time = single->Time; + bl->CurrentSpeed = single->CurrentSpeed; + bl->BilinearLerp[0] = single->BilinearLerp[0]; + bl->BilinearLerp[1] = single->BilinearLerp[1]; + bl->Effect = single->Effect; + + bl->LastTime = single->LastTime; + + memcpy(bl->ActiveList, single->ActiveList, + single->ActiveCount * sizeof(xAnimActiveEffect)); + single->ActiveList[0].Effect = NULL; + } + + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + single->Tran = transition; + single->BlendFactor = 0.0000001f; + } + + TransitionTimeInit(single, transition); + single->State = transition->Dest; + single->CurrentSpeed = single->State->Speed; + single->BilinearLerp[0] = 0.0f; + single->BilinearLerp[1] = 0.0f; + single->Sync = NULL; + EffectSingleStart(single); + + if (transition->Dest->BeforeEnter != NULL) + { + transition->Dest->BeforeEnter(play, transition->Dest); + } + + if (transition->Callback != NULL) + { + transition->Callback(transition, single, single->Play->Object); + } +} + +void xAnimPlayUpdate(xAnimPlay* play, F32 timeDelta) +{ + U32 i; + xAnimSingle* single; + + for (i = 0; i < play->NumSingle; i++) + { + single = &play->Single[i]; + + SingleUpdate(single, timeDelta); + + if (single->State->StateCallback) + { + single->State->StateCallback(single->State, single, play->Object); + } + } +} + +void xAnimPlayEval(xAnimPlay* play) +{ + U32 i; + U32 bone; + xQuat* quatresult = (xQuat*)giAnimScratch; + xVec3* tranresult = (xVec3*)((U8*)quatresult + 0x410); + + if (play->BoneCount > 1) + { + xQuat* quatblend = (xQuat*)((U8*)quatresult + 0x720); + xVec3* tranblend = (xVec3*)((U8*)quatblend + 0x410); + SingleEval(play->Single, tranresult, (xQuat*)giAnimScratch); + for (i = 1; i < play->NumSingle; ++i) + { + xAnimSingle* si = &play->Single[i]; + if (si->State == NULL || si->SingleFlags & 0x8000) + { + continue; + } + F32 blendF = 1.0f; + F32 blendR = 1.0f; + U16* blendO = NULL; + SingleEval(si, tranblend, quatblend); + + if ((si->Blend == NULL || si->Blend->State == NULL) && si->BlendFactor) + { + if (si->Tran != NULL) + { + blendF = si->BlendFactor; + blendR = si->Tran->BlendRecip; + blendO = si->Tran->BlendOffset; + } + else + { + blendF = -si->BlendFactor; + blendR = si->State->FadeRecip; + blendO = si->State->FadeOffset; + } + } + + if ((si->SingleFlags & 0x3) == 2) + { + iAnimBlend(blendF, blendR, blendO, si->State->BoneBlend, play->BoneCount - 1, + tranblend + 1, quatblend + 1, NULL, NULL, tranblend + 1, quatblend + 1); + + for (bone = 1; bone < play->BoneCount; ++bone) + { + tranresult[bone].x += tranblend[bone].x; + tranresult[bone].y += tranblend[bone].y; + tranresult[bone].z += tranblend[bone].z; + xQuatMul(&quatresult[bone], &quatresult[bone], &quatblend[bone]); + } + } + else + { + iAnimBlend(blendF, blendR, blendO, si->State->BoneBlend, play->BoneCount - 1, + tranresult + 1, quatresult + 1, tranblend + 1, quatblend + 1, + tranresult + 1, quatresult + 1); + } + } + } + memset(tranresult, 0, sizeof(xVec3)); + memset(quatresult, 0, sizeof(xQuat)); + if (play->Single->State->BeforeAnimMatrices != NULL) + { + play->Single->State->BeforeAnimMatrices(play, quatresult, tranresult, play->BoneCount); + } + + if (play->BeforeAnimMatrices != NULL) + { + play->BeforeAnimMatrices(play, quatresult, tranresult, play->BoneCount); + } + iModelAnimMatrices(play->ModelInst->Data, quatresult, tranresult, &play->ModelInst->Mat[1]); +} + +void xAnimPoolCB(xMemPool* pool, void* data) +{ + S32 i; + xAnimPlay* clone = (xAnimPlay*)data; + xAnimPlay* play = (xAnimPlay*)pool->Buffer; + xAnimSingle* clonesingle = (xAnimSingle*)(clone + 1); + xAnimSingle* currsingle; + xAnimActiveEffect* curract; + + clone->NumSingle = play->NumSingle; + clone->Single = clonesingle; + + clonesingle += play->NumSingle; + + for (i = 0; i < play->NumSingle; i++) + { + clone->Single[i].Play = clone; + + if (play->Single[i].Blend) + { + clone->Single[i].Blend = clonesingle; + + clonesingle->Blend = NULL; + clonesingle->Play = clone; + + clonesingle++; + } + else + { + clone->Single[i].Blend = NULL; + } + } + + curract = (xAnimActiveEffect*)clonesingle; + + for (i = 0; i < clone->NumSingle; i++) + { + clonesingle = &clone->Single[i]; + currsingle = &play->Single[i]; + + while (clonesingle) + { + clonesingle->ActiveCount = currsingle->ActiveCount; + + if (currsingle->ActiveCount) + { + clonesingle->ActiveList = curract; + + curract += currsingle->ActiveCount; + } + else + { + clonesingle->ActiveList = NULL; + } + + currsingle = currsingle->Blend; + clonesingle = clonesingle->Blend; + } + } + + clone->Pool = pool; +} + +#define ADD_4_BITS(x) (((x) & 1) + (((x) >> 1) & 1) + (((x) >> 2) & 1) + (((x) >> 3) & 1)) +void xAnimPoolInit(xMemPool* pool, U32 count, U32 singles, U32 blendFlags, U32 effectMax) +{ + effectMax += effectMax & 1; + + U32 size = + (effectMax * sizeof(xAnimActiveEffect) + sizeof(xAnimSingle)) * + (ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0x0)) + + ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0x4)) + + ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0x8)) + + ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0xC)) + singles) + + sizeof(xAnimPlay); + + U32 i; + void* buffer = xMemAllocSize(count * size); + + xAnimPlay* play = (xAnimPlay*)buffer; + play->NumSingle = singles; + + xAnimSingle* currsingle; + play->Single = currsingle = (xAnimSingle*)((U32)play + sizeof(xAnimPlay)); + currsingle += singles; + + for (i = 0; i < singles; ++i) + { + if (blendFlags & (1 << i)) + { + play->Single[i].Blend = currsingle; + currsingle->Blend = NULL; + currsingle++; + } + else + { + play->Single[i].Blend = NULL; + } + } + + xAnimActiveEffect* curract = (xAnimActiveEffect*)currsingle; + for (i = 0; i < play->NumSingle; ++i) + { + currsingle = &play->Single[i]; + while (currsingle) + { + currsingle->ActiveCount = effectMax; + if (effectMax != 0) + { + currsingle->ActiveList = curract; + curract += effectMax; + } + else + { + currsingle->ActiveList = NULL; + } + + currsingle = currsingle->Blend; + } + } + + play->Pool = pool; + xMemPoolSetup(pool, buffer, 0, 1, xAnimPoolCB, size, count, count / 2); +} + +xAnimPlay* xAnimPoolAlloc(xMemPool* pool, void* object, xAnimTable* table, + xModelInstance* modelInst) +{ + xAnimPlay* play; + + play = (xAnimPlay*)xMemPoolAlloc(pool); + + xAnimPlaySetup(play, object, table, modelInst); + + return play; +} + +void xAnimPoolFree(xAnimPlay* play) +{ + U32 i; + + for (i = 0; i < play->NumSingle; i++) + { + EffectSingleStop(&play->Single[i]); + + if (play->Single[i].Blend) + { + EffectSingleStop(play->Single[i].Blend); + } + } + + xMemPoolFree(play->Pool, play); +} diff --git a/src/SB/Core/x/xAnim.h b/src/SB/Core/x/xAnim.h new file mode 100644 index 0000000..d9a5823 --- /dev/null +++ b/src/SB/Core/x/xAnim.h @@ -0,0 +1,229 @@ +#ifndef XANIM_H +#define XANIM_H + +#include + +#include "xMath3.h" +#include "xMemMgr.h" + +typedef struct xAnimState; +typedef struct xAnimTransition; +typedef struct xAnimTransitionList; +typedef struct xAnimEffect; +typedef struct xAnimActiveEffect; +typedef struct xAnimSingle; +typedef struct xAnimPlay; + +extern U32 gxAnimUseGrowAlloc; + +struct xAnimFile +{ + xAnimFile* Next; + const char* Name; + U32 ID; + U32 FileFlags; + + // 0x10 + F32 Duration; + F32 TimeOffset; + U16 BoneCount; + U8 NumAnims[2]; + + // 0x20 + void** RawData; +}; + +struct xAnimMultiFileEntry +{ + U32 ID; + xAnimFile* File; +}; + +struct xAnimMultiFileBase +{ + U32 Count; +}; + +struct xAnimMultiFile : xAnimMultiFileBase +{ + xAnimMultiFileEntry Files[1]; +}; + +typedef void (*xAnimStateBeforeEnterCallback)(xAnimPlay*, xAnimState*); +typedef void (*xAnimStateCallback)(xAnimState*, xAnimSingle*, void*); +typedef void (*xAnimStateBeforeAnimMatricesCallback)(xAnimPlay*, xQuat*, xVec3*, S32); + +struct xAnimState +{ + xAnimState* Next; + const char* Name; + U32 ID; + U32 Flags; + + // 0x10 + U32 UserFlags; + F32 Speed; + xAnimFile* Data; + xAnimEffect* Effects; + + // 0x20 + xAnimTransitionList* Default; + xAnimTransitionList* List; + F32* BoneBlend; + F32* TimeSnap; + + // 0x30 + F32 FadeRecip; + U16* FadeOffset; + void* CallbackData; + xAnimMultiFile* MultiFile; + + // 0x40 + xAnimStateBeforeEnterCallback BeforeEnter; + xAnimStateCallback StateCallback; + xAnimStateBeforeAnimMatricesCallback BeforeAnimMatrices; +}; + +typedef U32 (*xAnimTransitionConditionalCallback)(xAnimTransition*, xAnimSingle*, void*); +typedef U32 (*xAnimTransitionCallback)(xAnimTransition*, xAnimSingle*, void*); + +struct xAnimTransition +{ + xAnimTransition* Next; + xAnimState* Dest; + xAnimTransitionConditionalCallback Conditional; + xAnimTransitionCallback Callback; + U32 Flags; + U32 UserFlags; + F32 SrcTime; // 0x18 + F32 DestTime; // 0x1C + U16 Priority; + U16 QueuePriority; + F32 BlendRecip; // 0x24 + U16* BlendOffset; +}; + +struct xAnimTransitionList +{ + xAnimTransitionList* Next; + xAnimTransition* T; +}; + +struct xAnimTable +{ + xAnimTable* Next; // 0x0 + const char* Name; // 0x4 + xAnimTransition* TransitionList; // 0x8 + xAnimState* StateList; + U32 AnimIndex; + U32 MorphIndex; + U32 UserFlags; +}; + +typedef U32 (*xAnimEffectCallback)(U32, xAnimActiveEffect*, xAnimSingle*, void*); + +struct xAnimEffect +{ + xAnimEffect* Next; + U32 Flags; + F32 StartTime; + F32 EndTime; + xAnimEffectCallback Callback; +}; + +struct xAnimActiveEffect +{ + xAnimEffect* Effect; + U32 Handle; +}; + +struct xAnimSingle +{ + U32 SingleFlags; + xAnimState* State; + F32 Time; + F32 CurrentSpeed; + + // Offset: 0x10 + F32 BilinearLerp[2]; + xAnimEffect* Effect; + U32 ActiveCount; + + // Offset: 0x20 + F32 LastTime; + xAnimActiveEffect* ActiveList; + xAnimPlay* Play; + xAnimTransition* Sync; + + // Offset: 0x30 + xAnimTransition* Tran; + xAnimSingle* Blend; + F32 BlendFactor; + U32 pad; +}; + +typedef struct xModelInstance; + +struct xAnimPlay +{ + xAnimPlay* Next; + U16 NumSingle; // 0x4 + U16 BoneCount; // 0x6 + xAnimSingle* Single; // 0x8 + void* Object; // 0xC + xAnimTable* Table; // 0x10 + xMemPool* Pool; + xModelInstance* ModelInst; + void (*BeforeAnimMatrices)(xAnimPlay*, xQuat*, xVec3*, S32); +}; + +class AnimTableList { // size: 0xC +public: + char * name; // offset 0x0, size 0x4 + class xAnimTable * (* constructor)(); // offset 0x4, size 0x4 + unsigned int id; // offset 0x8, size 0x4 +}; + +void xAnimInit(); +void xAnimTempTransitionInit(U32 count); +xAnimFile* xAnimFileNew(void* rawData, const char* name, U32 flags, xAnimFile** linkedList); +xAnimTable* xAnimTableNew(const char* name, xAnimTable** linkedList, U32 userFlags); +xAnimState* xAnimTableNewState(xAnimTable* table, const char* name, U32 flags, U32 userFlags, + F32 speed, F32* boneBlend, F32* timeSnap, F32 fadeRecip, + U16* fadeOffset, void* callbackData, + xAnimStateBeforeEnterCallback beforeEnter, + xAnimStateCallback stateCallback, + xAnimStateBeforeAnimMatricesCallback beforeAnimMatrices); +xAnimTransition* xAnimTableNewTransition(xAnimTable* table, const char* source, const char* dest, + xAnimTransitionConditionalCallback conditional, + xAnimTransitionCallback callback, U32 flags, U32 userFlags, + F32 srcTime, F32 destTime, U16 priority, U16 queuePriority, + F32 blendRecip, U16* blendOffset); +void xAnimDefaultBeforeEnter(xAnimPlay* play, xAnimState* state); +void xAnimPoolInit(xMemPool* pool, U32 count, U32 singles, U32 blendFlags, U32 effectMax); +xAnimPlay* xAnimPoolAlloc(xMemPool* pool, void* object, xAnimTable* table, + xModelInstance* modelInst); +void xAnimPoolFree(xAnimPlay*); +xAnimState* xAnimTableGetState(xAnimTable* table, const char* name); +void xAnimTableAddTransition(xAnimTable* table, xAnimTransition* tran, const char* source); +void xAnimTableAddFile(xAnimTable* table, xAnimFile* file, const char* states); +xAnimState* xAnimTableAddFileID(xAnimTable* table, xAnimFile* file, U32 stateID, U32 subStateID, + U32 subStateCount); +xAnimState* xAnimTableGetStateID(xAnimTable* table, U32 ID); +void xAnimPlaySetState(xAnimSingle* single, xAnimState* state, F32 startTime); +void xAnimPlayChooseTransition(xAnimPlay* play); +void xAnimPlayStartTransition(xAnimPlay* play, xAnimTransition* transition); +void xAnimPlayUpdate(xAnimPlay* play, F32 timeDelta); +void xAnimPlayEval(xAnimPlay* play); + +inline F32 xAnimFileRawTime(xAnimFile* data, float time) +{ + if (data->FileFlags & 0x1000 || (data->FileFlags & 0x2000 && time > data->Duration * 0.5f)) + { + return data->TimeOffset + data->Duration - time; + } + return data->TimeOffset + time; +} + + +#endif diff --git a/src/SB/Core/x/xBase.cpp b/src/SB/Core/x/xBase.cpp new file mode 100644 index 0000000..59f9531 --- /dev/null +++ b/src/SB/Core/x/xBase.cpp @@ -0,0 +1,71 @@ +#include "xBase.h" + +void xBaseInit(xBase* xb, xBaseAsset* asset) +{ + xb->id = asset->id; + xb->baseType = asset->baseType; + xb->baseFlags = asset->baseFlags; + xb->linkCount = asset->linkCount; + xb->link = NULL; + + xBaseValidate(xb); +} + +void xBaseSetup(xBase* xb) +{ + return; +} + +void xBaseSave(xBase* ent, xSerial* s) +{ + if (xBaseIsEnabled(ent)) + { + s->Write_b1(1); + } + else + { + s->Write_b1(0); + } +} + +void xBaseLoad(xBase* ent, xSerial* s) +{ + S32 b = 0; + s->Read_b1(&b); + + if (b) + { + xBaseEnable(ent); + } + else + { + xBaseDisable(ent); + } +} + +void xBaseReset(xBase* xb, xBaseAsset* asset) +{ + xb->baseFlags = (xb->baseFlags & 0x10) | (asset->baseFlags & ~0x10); + + xBaseValidate(xb); +} + +void xBaseValidate(xBase* xb) +{ + xb->baseFlags |= 0x4; +} + +bool xBaseIsEnabled(const xBase* xb) +{ + return (xb->baseFlags & 0x1); +} + +void xBaseDisable(xBase* xb) +{ + xb->baseFlags &= ~0x1; +} + +void xBaseEnable(xBase* xb) +{ + xb->baseFlags |= 0x1; +} diff --git a/src/SB/Core/x/xBase.h b/src/SB/Core/x/xBase.h new file mode 100644 index 0000000..a6f3269 --- /dev/null +++ b/src/SB/Core/x/xBase.h @@ -0,0 +1,42 @@ +#ifndef XBASE_H +#define XBASE_H + +#include "xLinkAsset.h" +#include "xserializer.h" + +// Size: 0x8 +struct xBaseAsset +{ + U32 id; + U8 baseType; + U8 linkCount; + U16 baseFlags; +}; + +struct xBase; + +typedef S32 (*xBaseEventCB)(xBase*, xBase*, U32, const F32*, xBase*); + +// Size: 0x10 +struct xBase +{ + U32 id; + U8 baseType; // see en_ZBASETYPE in zBase.h + U8 linkCount; + U16 baseFlags; + xLinkAsset* link; + xBaseEventCB eventFunc; // 0xC +}; + +void xBaseInit(xBase* xb, xBaseAsset* asset); +void xBaseSetup(xBase* xb); +void xBaseSave(xBase* ent, xSerial* s); +void xBaseLoad(xBase* ent, xSerial* s); +void xBaseReset(xBase* xb, xBaseAsset* asset); +U32 xBaseIsValid(xBase* xb); +void xBaseValidate(xBase* xb); +bool xBaseIsEnabled(const xBase* xb); +void xBaseDisable(xBase* xb); +void xBaseEnable(xBase* xb); + +#endif diff --git a/src/SB/Core/x/xBehaveGoalSimple.cpp b/src/SB/Core/x/xBehaveGoalSimple.cpp new file mode 100644 index 0000000..972c528 --- /dev/null +++ b/src/SB/Core/x/xBehaveGoalSimple.cpp @@ -0,0 +1,85 @@ +#include "xBehaveGoalSimple.h" + +void xGoalSimple_RegisterTypes(xFactory* fac) +{ + fac->RegItemType('GSM\x00', GOALCreate_Generic, GOALDestroy_Generic); + fac->RegItemType('GSM\x01', GOALCreate_Generic, GOALDestroy_Generic); +} + +xFactoryInst* GOALCreate_Generic(S32 who, RyzMemGrow* growCtxt, void*) +{ + xGoal* goal = NULL; + + switch (who) + { + case 'GSM\x00': + { + goal = new (who, growCtxt) xGoalGeneric(who); + break; + } + case 'GSM\x01': + { + goal = new (who, growCtxt) xGoalEmpty(who); + break; + } + } + + return goal; +} + +void GOALDestroy_Generic(xFactoryInst* item) +{ + delete item; +} + +S32 xGoalGeneric::Enter(F32 dt, void* updCtxt) +{ + if (this->fun_enter) + { + return this->fun_enter(this, this->usrData, dt, updCtxt); + } + + return xGoal::Enter(dt, updCtxt); +} + +S32 xGoalGeneric::Exit(F32 dt, void* updCtxt) +{ + if (this->fun_exit) + { + return this->fun_exit(this, this->usrData, dt, updCtxt); + } + + return xGoal::Exit(dt, updCtxt); +} + +S32 xGoalGeneric::Suspend(F32 dt, void* updCtxt) +{ + if (this->fun_suspend) + { + return this->fun_suspend(this, this->usrData, dt, updCtxt); + } + + return xGoal::Suspend(dt, updCtxt); +} + +S32 xGoalGeneric::Resume(F32 dt, void* updCtxt) +{ + if (this->fun_resume) + { + return this->fun_resume(this, this->usrData, dt, updCtxt); + } + + return xGoal::Resume(dt, updCtxt); +} + +S32 xGoalGeneric::SysEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam, + xBase* toParamWidget, S32* handled) +{ + if (this->fun_sysevent) + { + return this->fun_sysevent(this, this->usrData, from, to, toEvent, toParam, toParamWidget, + handled); + } + + return xGoal::SysEvent(from, to, toEvent, toParam, toParamWidget, handled); +} diff --git a/src/SB/Core/x/xBehaveGoalSimple.h b/src/SB/Core/x/xBehaveGoalSimple.h new file mode 100644 index 0000000..350a6e2 --- /dev/null +++ b/src/SB/Core/x/xBehaveGoalSimple.h @@ -0,0 +1,58 @@ +#ifndef XBEHAVEGOALSIMPLE_H +#define XBEHAVEGOALSIMPLE_H + +#include "xFactory.h" +#include "xRMemData.h" +#include "xBehaviour.h" + +struct xGoalEmpty : xGoal +{ + xGoalEmpty(S32 goalID) : xGoal(goalID) + { + } + + virtual const char* Name() + { + return "xGoalEmpty"; + } + + virtual void Clear() + { + } +}; + +struct xGoalGeneric : xGoal +{ + S32 (*fun_enter)(xGoal*, void*, F32, void*); + S32 (*fun_exit)(xGoal*, void*, F32, void*); + S32 (*fun_suspend)(xGoal*, void*, F32, void*); + S32 (*fun_resume)(xGoal*, void*, F32, void*); + S32 (*fun_sysevent)(xGoal*, void*, xBase*, xBase*, U32, const F32*, xBase*, S32*); + void* usrData; + + xGoalGeneric(S32 goalID) : xGoal(goalID) + { + } + + virtual const char* Name() + { + return "xGoalGeneric"; + } + + virtual void Clear() + { + } + + virtual S32 Enter(F32 dt, void* updCtxt); + virtual S32 Exit(F32 dt, void* updCtxt); + virtual S32 Suspend(F32 dt, void* updCtxt); + virtual S32 Resume(F32 dt, void* updCtxt); + virtual S32 SysEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam, + xBase* toParamWidget, S32* handled); +}; + +void xGoalSimple_RegisterTypes(xFactory* fac); +xFactoryInst* GOALCreate_Generic(S32 who, RyzMemGrow* growCtxt, void* dat); +void GOALDestroy_Generic(xFactoryInst* item); + +#endif diff --git a/src/SB/Core/x/xBehaveMgr.cpp b/src/SB/Core/x/xBehaveMgr.cpp new file mode 100644 index 0000000..653488f --- /dev/null +++ b/src/SB/Core/x/xBehaveMgr.cpp @@ -0,0 +1,210 @@ +#include "xBehaveMgr.h" + +#include + +#include "xBehaveGoalSimple.h" +#include "xutil.h" + +extern S32 g_modinit_xBehaveMgr; +extern xBehaveMgr* g_behavmgr; + +void xBehaveMgr_Startup() +{ + if (g_modinit_xBehaveMgr++ == 0) + { + g_behavmgr = new ('BMGR', NULL) xBehaveMgr(); + g_behavmgr->Startup(0xfa, 0xfa); + } +} + +void xBehaveMgr_Shutdown() +{ + g_modinit_xBehaveMgr--; + if (g_modinit_xBehaveMgr == 0) + { + if (g_behavmgr != NULL) + { + delete g_behavmgr; + } + g_behavmgr = NULL; + } +} + +xBehaveMgr* xBehaveMgr_GetSelf() +{ + return g_behavmgr; +} + +xFactory* xBehaveMgr_GoalFactory() +{ + return g_behavmgr->GetFactory(); +} + +void xBehaveMgr_ScenePrepare() +{ + g_behavmgr->ScenePrepare(); +} + +void xBehaveMgr_SceneFinish() +{ + g_behavmgr->SceneFinish(); +} + +void xBehaveMgr_SceneReset() +{ + g_behavmgr->SceneReset(); +} + +void xBehaveMgr::RegBuiltIn() +{ + xGoalSimple_RegisterTypes(this->goalFactory); +} + +xPsyche* xBehaveMgr::Subscribe(xBase* owner, S32 i) +{ + xPsyche* psyche = &this->psypool[this->psylist.cnt]; + XOrdAppend(&this->psylist, psyche); + psyche->FreshWipe(); + psyche->SetOwner(owner, NULL); + return psyche; +} + +void xBehaveMgr::UnSubscribe(xPsyche* psy) +{ + psy->KillBrain(this->goalFactory); + XOrdRemove(&this->psylist, psy, -1); +} + +void xBehaveMgr::ScenePrepare() +{ +} + +void xBehaveMgr::SceneFinish() +{ + XOrdReset(&this->psylist); +} + +void xBehaveMgr::SceneReset() +{ + for (S32 i = 0; i < this->psylist.cnt; i++) + { + xPsyche* psyche = (xPsyche*)this->psylist.list[i]; + psyche->Amnesia(0); + } +} + +void xPsyche::BrainBegin() +{ + xFactory* factory = xBehaveMgr_GoalFactory(); + this->psystat = PSY_STAT_GROW; + factory->GrowDataEnable(&this->fakebase, false); +} + +void xPsyche::BrainExtend() +{ + xFactory* factory = xBehaveMgr_GoalFactory(); + this->psystat = PSY_STAT_EXTEND; + factory->GrowDataEnable(&this->fakebase, true); +} + +void xPsyche::BrainEnd() +{ + xBehaveMgr_GoalFactory()->GrowDataDisable(); + this->psystat = PSY_STAT_THINK; +} + +xGoal* xPsyche::AddGoal(S32 gid, void* createData) +{ + xGoal* goal = (xGoal*)xBehaveMgr_GoalFactory()->CreateItem(gid, createData, NULL); + + if (goal != NULL) + { + if (this->goallist != NULL) + { + this->goallist->Insert(goal); + } + else + { + this->goallist = goal; + } + goal->SetPsyche(this); + } + else + { + xUtil_idtag2string(gid, NULL); + } + return goal; +} + +extern F32 _750; +void xPsyche::FreshWipe() +{ + this->goalstak[0] = NULL; + this->goalstak[1] = NULL; + this->goalstak[2] = NULL; + this->goalstak[3] = NULL; + this->goalstak[4] = NULL; + this->staktop = -1; + this->gid_safegoal = 0; + this->pendgoal = 0; + this->pendtype = PEND_TRAN_NONE; + this->tmr_stack[0][0] = _750; + this->tmr_stack[0][1] = _750; + this->tmr_stack[0][2] = _750; + this->tmr_stack[0][3] = _750; + this->tmr_stack[0][4] = _750; + this->clt_owner = NULL; + this->userContext = NULL; + this->fun_remap = NULL; + this->cb_notice = NULL; + this->psystat = PSY_STAT_BLANK; + this->flg_psyche |= 1; +} + +void xPsyche::SetOwner(xBase* clt_owner, void* userContext) +{ + this->clt_owner = clt_owner; + this->userContext = userContext; + if (clt_owner == NULL) + { + return; + } + + this->fakebase.id = clt_owner->id; + this->fakebase.baseType = clt_owner->baseType + 0x80; + this->fakebase.linkCount = 0; + this->fakebase.baseFlags = 0; + this->fakebase.link = NULL; + this->fakebase.eventFunc = NULL; +} + +void xPsyche::KillBrain(xFactory* factory) +{ + this->Lobotomy(factory); + this->fun_remap = NULL; +} + +void xPsyche::Lobotomy(xFactory* factory) +{ + while (this->goallist != NULL) + { + xGoal* goal = this->goallist->RemHead(&this->goallist); + factory->DestroyItem(goal); + } +} + +void xPsyche::Amnesia(S32 i) +{ + xGoal* g = this->goallist; + while (g != NULL) + { + xGoal* thisg = g; + g = g->Next(); + // this->goallist = this->goallist->Next(); + + if (i == 0 && this->GIDInStack(thisg->GetID()) != NULL) + { + continue; + } + } +} diff --git a/src/SB/Core/x/xBehaveMgr.h b/src/SB/Core/x/xBehaveMgr.h new file mode 100644 index 0000000..c58dfd8 --- /dev/null +++ b/src/SB/Core/x/xBehaveMgr.h @@ -0,0 +1,40 @@ +#ifndef XBEHAVEMGR_H +#define XBEHAVEMGR_H + +#include "xBase.h" +#include "xBehaviour.h" +#include "xordarray.h" +#include "xFactory.h" + +struct xBehaveMgr : RyzMemData +{ + xFactory* goalFactory; + xPsyche* psypool; + st_XORDEREDARRAY psylist; + + xBehaveMgr() + { + } + + ~xBehaveMgr() + { + } + + void Startup(S32, S32); + void RegBuiltIn(); + xPsyche* Subscribe(xBase* owner, S32 i); + void UnSubscribe(xPsyche* psy); + void ScenePrepare(); + void SceneFinish(); + void SceneReset(); + xFactory* GetFactory(); +}; + +void xBehaveMgr_ScenePrepare(); +void xBehaveMgr_SceneReset(); +void xBehaveMgr_Startup(); +void xBehaveMgr_Shutdown(); +void xBehaveMgr_SceneFinish(); +xBehaveMgr* xBehaveMgr_GetSelf(); + +#endif diff --git a/src/SB/Core/x/xBehaviour.cpp b/src/SB/Core/x/xBehaviour.cpp new file mode 100644 index 0000000..a6e4e7e --- /dev/null +++ b/src/SB/Core/x/xBehaviour.cpp @@ -0,0 +1,120 @@ +#include "xBehaviour.h" + +WEAK void xGoal::SetPsyche(xPsyche* psyche) +{ + this->psyche = psyche; +} + +WEAK const char* xGoal::Name() +{ + return NULL; +} + +WEAK void xGoal::SetState(en_GOALSTATE state) +{ + this->stat = state; +} + +WEAK en_GOALSTATE xGoal::GetState() const +{ + return this->stat; +} + +WEAK xGoal* xListItem::Next() +{ + return this->next; +} + +WEAK void xListItem::Insert(xGoal* list) +{ + xGoal* node = (xGoal*)this; + + node->prev = list; + node->next = list->next; + + if (list->next) + { + list->next->prev = node; + } + + list->next = node; +} + +WEAK xGoal* xListItem::RemHead(xGoal** listhead) +{ + if (*listhead == NULL) + { + return NULL; + } + + xGoal* oldhead = (*listhead)->Head(); + + if (!oldhead) + { + *listhead = NULL; + } + else + { + *listhead = oldhead->Next(); + oldhead->Remove(); + } + + return oldhead; +} + +WEAK xGoal* xListItem::Head() +{ + xGoal* node = (xGoal*)this; + + if (!node) + { + return node; + } + + while (node->prev) + { + node = node->prev; + } + + return node; +} + +WEAK xBase* xGoal::GetOwner() const +{ + return this->psyche->GetClient(); +} + +void xGoal::Clear() +{ + this->stat = GOAL_STAT_UNKNOWN; +} + +S32 xGoal::PreCalc(F32 dt, void* updCtxt) +{ + if (this->fun_precalc) + { + return this->fun_precalc(this, this->cbdata, dt, updCtxt); + } + + return 0; +} + +S32 xGoal::EvalRules(en_trantype* trantype, F32 dt, void* updCtxt) +{ + if (this->fun_chkRule) + { + return this->fun_chkRule(this, this->cbdata, trantype, dt, updCtxt); + } + + return 0; +} + +S32 xGoal::Process(en_trantype* trantype, float dt, void* ctxt, xScene* scene) +{ + if (this->fun_process) + { + return this->fun_process(this, this->cbdata, trantype, dt, ctxt); + } + + return 0; +} diff --git a/src/SB/Core/x/xBehaviour.h b/src/SB/Core/x/xBehaviour.h index 9ea9513..0db2b72 100644 --- a/src/SB/Core/x/xBehaviour.h +++ b/src/SB/Core/x/xBehaviour.h @@ -1,29 +1,23 @@ #ifndef XBEHAVIOUR_H #define XBEHAVIOUR_H -#include "xEnt.h" +#include "xBase.h" +#include "xListItem.h" +#include "xFactory.h" +#include "xScene.h" -enum PSY_BRAIN_STATUS -{ - PSY_STAT_BLANK, - PSY_STAT_GROW, - PSY_STAT_EXTEND, - PSY_STAT_THINK, - PSY_STAT_NOMORE, - PSY_STAT_FORCE = 0x7fffffff -}; - -enum en_pendtype +enum en_GOALSTATE { - PEND_TRAN_NONE, - PEND_TRAN_SET, - PEND_TRAN_PUSH, - PEND_TRAN_POP, - PEND_TRAN_POPTO, - PEND_TRAN_POPALL, - PEND_TRAN_SWAP, - PEND_TRAN_INPROG, - PEND_TRAN_NOMORE + GOAL_STAT_UNKNOWN, + GOAL_STAT_PROCESS, + GOAL_STAT_ENTER, + GOAL_STAT_EXIT, + GOAL_STAT_SUSPEND, + GOAL_STAT_RESUME, + GOAL_STAT_PAUSED, + GOAL_STAT_DONE, + GOAL_STAT_NOMORE, + GOAL_STAT_FORCE = 0x7fffffff }; enum en_trantype @@ -41,162 +35,50 @@ enum en_trantype GOAL_TRAN_FORCE = 0x7fffffff }; -enum en_GOALSTATE +enum en_pendtype { - GOAL_STAT_UNKNOWN, - GOAL_STAT_PROCESS, - GOAL_STAT_ENTER, - GOAL_STAT_EXIT, - GOAL_STAT_SUSPEND, - GOAL_STAT_RESUME, - GOAL_STAT_PAUSED, - GOAL_STAT_DONE, - GOAL_STAT_NOMORE, - GOAL_STAT_FORCE = 0x7fffffff + PEND_TRAN_NONE, + PEND_TRAN_SET, + PEND_TRAN_PUSH, + PEND_TRAN_POP, + PEND_TRAN_POPTO, + PEND_TRAN_POPALL, + PEND_TRAN_SWAP, + PEND_TRAN_INPROG, + PEND_TRAN_NOMORE }; -enum en_npcgol +enum PSY_BRAIN_STATUS { - NME_GOAL_UNKNOWN, - NME_GOAL_CRIT_IDLE = 0x4e474300, - NME_GOAL_CRIT_PATROL, - NME_GOAL_CRIT_DYING, - NME_GOAL_CRIT_DEAD, - NME_GOAL_CRIT_BATTACK, - NME_GOAL_CRIT_JATTACK, - NME_GOAL_CRIT_JDYING, - NME_GOAL_TURR_IDLE = 0x4e474700, - NME_GOAL_TURR_RELOAD, - NME_GOAL_TURR_HURT, - NME_GOAL_TURR_DEAD, - NME_GOAL_TURR_TREADY, - NME_GOAL_TURR_TTURN, - NME_GOAL_TURR_TSHOOT, - NME_GOAL_TURR_PDORMANT, - NME_GOAL_TURR_PALERT, - NME_GOAL_TURR_PPATALPHA, - NME_GOAL_TURR_BIDLE, - NME_GOAL_TURR_BTURN, - NME_GOAL_TURR_BSHOOT, - NME_GOAL_TURR_BHURT, - NME_GOAL_TURR_SPIRAL, - NME_GOAL_IDLE = 0x4e474e00, - NME_GOAL_PATROL, - NME_GOAL_WANDER, - NME_GOAL_FIDGET, - NME_GOAL_WAITING, - NME_GOAL_DEAD, - NME_GOAL_NOMANLAND, - NME_GOAL_LIMBO, - NME_GOAL_DEV_ANIMVIEW = 0x4e474400, - NME_GOAL_DEV_HEROMODE, - NME_GOAL_TIKI_IDLE = 0x4e475400, - NME_GOAL_TIKI_PATROL, - NME_GOAL_TIKI_HIDE, - NME_GOAL_TIKI_COUNT, - NME_GOAL_TIKI_DYING, - NME_GOAL_TIKI_DEAD, - NME_GOAL_AFTERLIFE = 0x4e475300, - NME_GOAL_SPAWN, - NME_GOAL_WOUND, - NME_GOAL_SPOOKED, - NME_GOAL_NOTICE, - NME_GOAL_SCAREWAIT, - NME_GOAL_SCARE, - NME_GOAL_TAUNT, - NME_GOAL_EVILPAT = 0x4e475000, - NME_GOAL_STUNNED, - NME_GOAL_PATCARRY, - NME_GOAL_PATTWIRL, - NME_GOAL_PATTHROW, - NME_GOAL_TRIGGER_NORMAL = 0x4e475800, - NME_GOAL_TRIGGER_SCARY, - NME_GOAL_TRIGGER_DETECT, - NME_GOAL_TRIGGER_ALERT, - NME_GOAL_TRIGGER_BATTLE, - NME_GOAL_TRIGGER_WOUND, - NME_GOAL_TRIGGER_ATTACK, - NME_GOAL_TRIGGER_VINIVICIVIDI, - NME_GOAL_FOGGER_AWARE = 0x4e474500, - NME_GOAL_FOGGER_BATTLE, - NME_GOAL_FOGGER_ATTACK, - NME_GOAL_SLAMMER_AWARE, - NME_GOAL_SLAMMER_BATTLE, - NME_GOAL_SLAMMER_ATTACK, - NME_GOAL_SPINNER_AWARE, - NME_GOAL_SPINNER_BATTLE, - NME_GOAL_FLINGER_NORMAL, - NME_GOAL_FLINGER_AWARE, - NME_GOAL_FLINGER_BATTLE, - NME_GOAL_FLINGER_ATTACK, - NME_GOAL_FLINGER_BOING, - NME_GOAL_FLINGER_FLEE, - NME_GOAL_FLINGER_PANIC, - NME_GOAL_FLINGER_MOVE, - NME_GOAL_POPPER_NORMAL, - NME_GOAL_POPPER_AWARE, - NME_GOAL_POPPER_WOUND, - NME_GOAL_POPPER_EVADE, - NME_GOAL_POPPER_BATTLE, - NME_GOAL_POPPER_ATTACK, - NME_GOAL_ZAP_NORMAL, - NME_GOAL_ZAP_AWARE, - NME_GOAL_ZAP_BATTLE, - NME_GOAL_ZAP_WOUND, - NME_GOAL_ZAP_ZAP, - NME_GOAL_ZAP_MOVE, - NME_GOAL_MERV_NORMAL, - NME_GOAL_MERV_AWARE, - NME_GOAL_MERV_BATTLE, - NME_GOAL_MERV_ZAP, - NME_GOAL_MERV_BOMB, - NME_GOAL_MERV_BOWL, - NME_GOAL_MERV_WOUND, - NME_GOAL_MERV_MOVE, - NME_GOAL_BUCK_RUNNING, - NME_GOAL_BUCK_BIRTHING, - NME_GOAL_BUCK_DYING, - NME_GOAL_BUCK_DEAD, - NME_GOAL_DENNIS_NORMAL, - NME_GOAL_DENNIS_EVADE, - NME_GOAL_DENNIS_BATTLE, - NME_GOAL_DENNIS_ATTACK, - NME_GOAL_DENNIS_TAUNT, - NME_GOAL_DENNIS_DAMAGE, - NME_GOAL_DENNIS_DEAD, - NME_GOAL_DENTOO_NORMAL, - NME_GOAL_DENTOO_EVADE, - NME_GOAL_DENTOO_BATTLE, - NME_GOAL_DENTOO_ATTACK, - NME_GOAL_DENTOO_TAUNT, - NME_GOAL_DENTOO_DAMAGE, - NME_GOAL_DENTOO_DEAD, - NME_GOAL_SBBAT_IDLE, - NME_GOAL_SBBAT_DEAD, - NME_GOAL_NOMORE, - NME_GOAL_FORCE = 0x7fffffff + PSY_STAT_BLANK, + PSY_STAT_GROW, + PSY_STAT_EXTEND, + PSY_STAT_THINK, + PSY_STAT_NOMORE, + PSY_STAT_FORCE = 0x7fffffff }; -enum en_npcgspot +enum en_psynote { - NME_GSPOT_START = 0x20, - NME_GSPOT_RESUME, - NME_GSPOT_LOOP, - NME_GSPOT_FINISH, - NME_GSPOT_STARTALT, - NME_GSPOT_ALTA, - NME_GSPOT_ALTB, - NME_GSPOT_PATROLPAUSE, - NME_GSPOT_NEXT, - NME_GSPOT_NOMORE, - NME_GSPOT_FORCEINT = 0x7fffffff + PSY_NOTE_HASRESUMED, + PSY_NOTE_HASENTERED, + PSY_NOTE_ANIMCHANGED, + PSY_NOTE_NOMORE, + PSY_NOTE_FORCE = 0x7fffffff }; +struct xGoal; + struct xPSYNote { + virtual void Notice(en_psynote note, xGoal* goal, void*) + { + } }; -struct xGoal; +typedef S32 (*xGoalProcessCallback)(xGoal*, void*, en_trantype*, F32, void*); +typedef S32 (*xGoalChkRuleCallback)(xGoal*, void*, en_trantype*, F32, void*); +typedef S32 (*xGoalPreCalcCallback)(xGoal*, void*, F32, void*); struct xPsyche : RyzMemData { @@ -215,54 +97,131 @@ struct xPsyche : RyzMemData S32 cnt_transLastTimestep; PSY_BRAIN_STATUS psystat; xBase fakebase; -}; -struct xListItem_1 -{ - S32 flg_travFilter; - xGoal* next; - xGoal* prev; + xGoal* GIDInStack(S32 gid) const; + void ImmTranOn(); + void ImmTranOff(); + S32 ImmTranIsOn(); + S32 HasGoal(S32 goal); + xGoal* GetCurGoal() const; + S32 GIDOfActive() const; + S32 GIDOfPending() const; + S32 GIDOfSafety() const + { + return gid_safegoal; + } + S32 Timestep(F32 dt, void* updCtxt); + xGoal* FindGoal(S32 gid); + S32 GoalSet(S32 gid, S32 r5); + S32 GoalPop(S32 gid_popto, S32 r5); + S32 GoalNone(S32 denyExplicit); + S32 GoalSwap(S32 gid, S32 r5); + S32 GoalPopRecover(S32 overpend); + S32 GoalPopToBase(S32 overpend); + S32 GoalPush(S32 gid, S32 r5); + S32 GoalSet(S32 gid); + + void BrainBegin(); + void BrainExtend(); + void BrainEnd(); + xGoal* AddGoal(S32 gid, void* createData); + void FreshWipe(); + void SetOwner(xBase*, void*); + void KillBrain(xFactory*); + void Lobotomy(xFactory*); + void SetSafety(S32 goalID) + { + gid_safegoal = goalID; + } + void Amnesia(S32); + void SetNotify(xPSYNote* notice) + { + cb_notice = notice; + } + + xBase* GetClient() + { + return this->clt_owner; + } }; -struct xGoal : xListItem_1, xFactoryInst +struct xGoal : xListItem, xFactoryInst { - xPsyche* psyche; //0x18 + xPsyche* psyche; // 0x18 + S32 goalID; en_GOALSTATE stat; - S32 flg_able; //0x20 - S32 (*fun_process)(xGoal*, void*, en_trantype*, F32, void*); + S32 flg_able; // 0x24 + xGoalProcessCallback fun_process; + xGoalPreCalcCallback fun_precalc; + xGoalChkRuleCallback fun_chkRule; void* cbdata; - S32 Exit(); - S32 Suspend(); - S32 SysEvent(); - S32 Enter(); - S32 Resume(); - S32 Process(en_trantype* trantype, F32 dt, void* updCtxt); -}; + xGoal(S32 goalID) + { + this->goalID = goalID; + this->flg_able = 0; + this->stat = GOAL_STAT_UNKNOWN; + } -struct zNMEGoalCommon : xGoal -{ - U32 anid_played; - struct + S32 GetID() const + { + return this->goalID; + } + + void SetFlags(S32 flags) + { + flg_able = flags; + } + void AddFlags(S32 flags); + xPsyche* GetPsyche() const; + void SetCallbacks(xGoalProcessCallback process, xGoalChkRuleCallback chkRule, + xGoalPreCalcCallback precalc, void* cbdata); + S32 GetFlags() const + { + return flg_able; + } + + void SetPsyche(xPsyche* psyche); + const char* Name(); + void SetState(en_GOALSTATE state); + en_GOALSTATE GetState() const; + xBase* GetOwner() const; + + // vtable + virtual void Clear() = 0; + + virtual S32 Enter(F32 dt, void* updCtxt) { - S32 flg_npcgauto : 8; - S32 flg_npcgable : 16; - S32 bul_entered : 1; - S32 bul_resumed : 1; - S32 bul_unused : 6; - } flags; - struct + return 0; + } + + virtual S32 Exit(F32 dt, void* updCtxt) + { + return 0; + } + + virtual S32 Suspend(F32 dt, void* updCtxt) + { + return 0; + } + + virtual S32 Resume(F32 dt, void* updCtxt) + { + return 0; + } + + virtual S32 PreCalc(F32 dt, void* updCtxt); + virtual S32 EvalRules(en_trantype* trantype, F32 dt, void* updCtxt); + virtual S32 Process(en_trantype* trantype, float dt, void* ctxt, xScene* scene); + + virtual S32 SysEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam, + xBase* toParamWidget, S32* handled) { - S32 flg_info : 16; - S32 flg_user : 16; - }; + return 1; + } - S32 CollReview(); - S32 GoalHandleMail(); - void Clear(); - S32 Enter(); - S32 Resume(); - S32 Process(en_trantype* trantyp, F32 dt, void* ctxt); +protected: + ~xGoal(); // prevents implicit destructors from being generated in subclasses of xGoal }; #endif diff --git a/src/SB/Core/x/xBound.cpp b/src/SB/Core/x/xBound.cpp new file mode 100644 index 0000000..132111b --- /dev/null +++ b/src/SB/Core/x/xBound.cpp @@ -0,0 +1,495 @@ +#include "xBound.h" + +#include "xMath.h" +#include "xMathInlines.h" +#include "xDraw.h" + +#include "iMath.h" + +extern F32 _571; +extern F32 _640; +extern F32 _641; +extern F32 _642; +extern F32 _643; +extern F32 _644; + +void xBoundUpdate(xBound* b) +{ + if (b->type == XBOUND_TYPE_BOX) + { + xVec3Add(&b->box.center, &b->box.box.lower, &b->box.box.upper); + xVec3SMul(&b->box.center, &b->box.center, _571); + } + else if (b->type == XBOUND_TYPE_OBB) + { + xVec3Add(&b->box.center, &b->box.box.lower, &b->box.box.upper); + xVec3SMul(&b->box.center, &b->box.center, _571); + xMat4x3Toworld(&b->box.center, b->mat, &b->box.center); + } + + if (b->type != XBOUND_TYPE_NA) + { + xQuickCullForBound(&b->qcd, b); + } +} + +void xBoundGetBox(xBox& box, const xBound& bound) +{ + switch (bound.type) + { + case XBOUND_TYPE_SPHERE: + { + const xSphere& o = bound.sph; + + box.upper.assign(o.center.x + o.r, o.center.y + o.r, o.center.z + o.r); + box.lower.assign(o.center.x - o.r, o.center.y - o.r, o.center.z - o.r); + + break; + } + case XBOUND_TYPE_BOX: + { + box = bound.box.box; + + break; + } + case XBOUND_TYPE_OBB: + { + xBoxInitBoundOBB(&box, &bound.box.box, bound.mat); + + break; + } + } +} + +void xBoundGetSphere(xSphere& o, const xBound& bound) +{ + switch (bound.type) + { + case XBOUND_TYPE_SPHERE: + { + o = bound.sph; + + break; + } + case XBOUND_TYPE_BOX: + { + o.center = bound.box.center; + o.r = (bound.box.box.upper - bound.box.center).length(); + + break; + } + case XBOUND_TYPE_OBB: + { + const xMat4x3& mat = *bound.mat; + xVec3 v = (bound.box.box.upper - bound.box.box.lower) * _571; + + o.r = xsqrt(SQR(v.x) * mat.right.length2() + SQR(v.y) * mat.up.length2() + + SQR(v.z) * mat.at.length2()); + o.center = bound.box.center; + + break; + } + } +} + +F32 xsqrt(F32 x) +{ + const F32 half = _571; + const F32 three = _640; + + if (x <= _641 || isinf(x)) + { + return x; + } + + // non-matching: frsp instruction + + F32 guess = __frsqrte(x); + guess = half * guess * (three - guess * guess * x); + + if (guess > _644) + { + return _642 / guess; + } + + return _643; +} + +U32 xBoundSphereHitsOBB(const xSphere* s, const xBox* b, const xMat4x3* m, xCollis* coll) +{ + return xSphereHitsOBB_nu(s, b, m, coll); +} + +void xBoundHitsBound(const xBound* a, const xBound* b, xCollis* c) +{ + if (!xQuickCullIsects(&a->qcd, &b->qcd)) + { + c->flags &= ~0x1; + } + else + { + // non-matching: jumptable + + switch (a->type | (b->type << 3)) + { + case (XBOUND_TYPE_SPHERE | (XBOUND_TYPE_SPHERE << 3)): + { + xSphereHitsSphere(&a->sph, &b->sph, c); + break; + } + case (XBOUND_TYPE_SPHERE | (XBOUND_TYPE_OBB << 3)): + { + xBoundSphereHitsOBB(&a->sph, &b->box.box, b->mat, c); + break; + } + case (XBOUND_TYPE_SPHERE | (XBOUND_TYPE_BOX << 3)): + { + xSphereHitsBox(&a->sph, &b->box.box, c); + break; + } + case (XBOUND_TYPE_BOX | (XBOUND_TYPE_SPHERE << 3)): + { + xBoxHitsSphere(&a->box.box, &b->sph, c); + break; + } + case (XBOUND_TYPE_BOX | (XBOUND_TYPE_OBB << 3)): + { + xBoxHitsObb(&a->box.box, &b->box.box, b->mat, c); + break; + } + case (XBOUND_TYPE_OBB | (XBOUND_TYPE_OBB << 3)): + { + break; + } + } + } +} + +static void xBoundOBBIsectRay(const xBox* b, const xMat4x3* m, const xRay3* r, xIsect* isect) +{ + xRay3 xfr; + xBox sbox; + xVec3 scale; + xMat4x3 mnormal; + + { + F32 len2 = SQR(m->right.x) + SQR(m->right.y) + SQR(m->right.z); + + if ((F32)iabs(len2 - _642) <= _644) + { + // non-matching: incorrect instruction + order + + scale.x = *(const F32*)&_642; + + mnormal.right.x = m->right.x; + mnormal.right.y = m->right.y; + mnormal.right.z = m->right.z; + } + else if ((F32)iabs(len2) <= _644) + { + // non-matching: incorrect order + + scale.x = _641; + + mnormal.right.x = _641; + mnormal.right.y = _642; + mnormal.right.z = _641; + } + else + { + scale.x = xsqrt(len2); + + F32 len_inv = _642 / scale.x; + + mnormal.right.x = m->right.x * len_inv; + mnormal.right.y = m->right.y * len_inv; + mnormal.right.z = m->right.z * len_inv; + } + } + + { + F32 len2 = SQR(m->up.x) + SQR(m->up.y) + SQR(m->up.z); + + if ((F32)iabs(len2 - _642) <= _644) + { + // non-matching: incorrect instruction + order + + scale.y = *(const F32*)&_642; + + mnormal.up.x = m->up.x; + mnormal.up.y = m->up.y; + mnormal.up.z = m->up.z; + } + else if ((F32)iabs(len2) <= _644) + { + // non-matching: incorrect order + + scale.y = _641; + + mnormal.up.x = _641; + mnormal.up.y = _642; + mnormal.up.z = _641; + } + else + { + scale.y = xsqrt(len2); + + F32 len_inv = _642 / scale.y; + + mnormal.up.x = m->up.x * len_inv; + mnormal.up.y = m->up.y * len_inv; + mnormal.up.z = m->up.z * len_inv; + } + } + + { + F32 len2 = SQR(m->at.x) + SQR(m->at.y) + SQR(m->at.z); + + if ((F32)iabs(len2 - _642) <= _644) + { + // non-matching: incorrect instruction + order + + scale.z = *(const F32*)&_642; + + mnormal.at.x = m->at.x; + mnormal.at.y = m->at.y; + mnormal.at.z = m->at.z; + } + else if ((F32)iabs(len2) <= _644) + { + // non-matching: incorrect order + + scale.z = _641; + + mnormal.at.x = _641; + mnormal.at.y = _642; + mnormal.at.z = _641; + } + else + { + scale.z = xsqrt(len2); + + F32 len_inv = _642 / scale.z; + + mnormal.at.x = m->at.x * len_inv; + mnormal.at.y = m->at.y * len_inv; + mnormal.at.z = m->at.z * len_inv; + } + } + + mnormal.pos = m->pos; + + sbox.upper.x = b->upper.x * scale.x; + sbox.upper.y = b->upper.y * scale.y; + sbox.upper.z = b->upper.z * scale.z; + sbox.lower.x = b->lower.x * scale.x; + sbox.lower.y = b->lower.y * scale.y; + sbox.lower.z = b->lower.z * scale.z; + + xMat4x3Tolocal(&xfr.origin, &mnormal, &r->origin); + xMat3x3Tolocal(&xfr.dir, &mnormal, &r->dir); + + xfr.min_t = r->min_t; + xfr.max_t = r->max_t; + xfr.flags = r->flags; + + iBoxIsectRay(&sbox, &xfr, isect); +} + +void xRayHitsBound(const xRay3* r, const xBound* b, xCollis* c) +{ + xIsect isect; + + if (b->type == XBOUND_TYPE_SPHERE) + { + iSphereIsectRay(&b->sph, r, &isect); + } + else if (b->type == XBOUND_TYPE_OBB) + { + xBoundOBBIsectRay(&b->box.box, b->mat, r, &isect); + } + else if (b->type == XBOUND_TYPE_BOX) + { + iBoxIsectRay(&b->box.box, r, &isect); + } + + if (isect.penned <= _641) + { + c->flags |= 0x1; + c->dist = isect.dist; + } + else + { + c->flags &= ~0x1; + } +} + +void xSphereHitsBound(const xSphere* o, const xBound* b, xCollis* c) +{ + switch (b->type) + { + case XBOUND_TYPE_SPHERE: + { + xSphereHitsSphere(o, &b->sph, c); + break; + } + case XBOUND_TYPE_OBB: + { + xBoundSphereHitsOBB(o, &b->box.box, b->mat, c); + break; + } + case XBOUND_TYPE_BOX: + { + xSphereHitsBox(o, &b->box.box, c); + break; + } + } +} + +void xVecHitsBound(const xVec3* v, const xBound* b, xCollis* c) +{ + xIsect isect; + + if (b->type == XBOUND_TYPE_SPHERE) + { + iSphereIsectVec(&b->sph, v, &isect); + } + else if (b->type == XBOUND_TYPE_OBB) + { + xVec3 lv; + + xMat4x3Tolocal(&lv, b->mat, v); + iBoxIsectVec(&b->box.box, &lv, &isect); + } + else if (b->type == XBOUND_TYPE_BOX) + { + iBoxIsectVec(&b->box.box, v, &isect); + } + + if (isect.penned <= _641) + { + c->flags |= 0x1; + } + else + { + c->flags &= ~0x1; + } +} + +void xBoundDraw(const xBound* b) +{ + if (b->type == XBOUND_TYPE_SPHERE) + { + xDrawSphere2(&b->sph, 12); + } + else if (b->type == XBOUND_TYPE_OBB) + { + xDrawOBB(&b->box.box, b->mat); + } + else if (b->type == XBOUND_TYPE_BOX) + { + xDrawBox(&b->box.box); + } +} + +void xQuickCullForBound(xQCData* q, const xBound* b) +{ + xQuickCullForBound(&xqc_def_ctrl, q, b); +} + +void xMat4x3Toworld(xVec3* o, const xMat4x3* m, const xVec3* v) +{ + xMat3x3RMulVec(o, m, v); + + o->x += m->pos.x; + o->y += m->pos.y; + o->z += m->pos.z; +} + +void xMat4x3Tolocal(xVec3* o, const xMat4x3* m, const xVec3* v) +{ + o->x = v->x - m->pos.x; + o->y = v->y - m->pos.y; + o->z = v->z - m->pos.z; + + xMat3x3Tolocal(o, m, o); +} + +void xVec3SMul(xVec3* o, const xVec3* v, F32 s) +{ + o->x = v->x * s; + o->y = v->y * s; + o->z = v->z * s; +} + +void xVec3Add(xVec3* o, const xVec3* a, const xVec3* b) +{ + o->x = a->x + b->x; + o->y = a->y + b->y; + o->z = a->z + b->z; +} + +xVec3& xVec3::assign(F32 x, F32 y, F32 z) +{ + this->x = x; + this->y = y; + this->z = z; + + return *this; +} + +F32 xVec3::length2() const +{ + return this->x * this->x + this->y * this->y + this->z * this->z; +} + +xVec3 xVec3::operator*(F32 f) const +{ + xVec3 temp = *this; + temp *= f; + + return temp; +} + +xVec3& xVec3::operator*=(F32 f) +{ + this->x *= f; + this->y *= f; + this->z *= f; + + return *this; +} + +F32 xVec3::length() const +{ + return xsqrt(this->length2()); +} + +xVec3 xVec3::operator-(const xVec3& v) const +{ + xVec3 temp = *this; + temp -= v; + + return temp; +} + +xVec3& xVec3::operator-=(const xVec3& v) +{ + this->x -= v.x; + this->y -= v.y; + this->z -= v.z; + + return *this; +} + +void xDrawBox(const xBox*) +{ +} + +void xDrawOBB(const xBox*, const xMat4x3*) +{ +} + +void xDrawSphere2(const xSphere*, U32) +{ +} diff --git a/src/SB/Core/x/xBound.h b/src/SB/Core/x/xBound.h new file mode 100644 index 0000000..e6a3416 --- /dev/null +++ b/src/SB/Core/x/xBound.h @@ -0,0 +1,52 @@ +#ifndef XBOUND_H +#define XBOUND_H + +#include "xQuickCull.h" +#include "xMath3.h" +#include "xCollide.h" + +// Size: 0x4C +struct xBound +{ + xQCData qcd; + + U8 type; // Offset: 0x20 (or 0x84) + U8 pad[3]; + union + { + xSphere sph; + xBBox box; + xCylinder cyl; + }; + xMat4x3* mat; +}; + +#define XBOUND_TYPE_NA 0 // None/invalid +#define XBOUND_TYPE_SPHERE 1 // Sphere - xBound::sph +#define XBOUND_TYPE_BOX 2 // Axis aligned bounding box - xBound::box +#define XBOUND_TYPE_CYL 3 // Cylinder - xBound::cyl (unused?) +#define XBOUND_TYPE_OBB 4 // Oriented bounding box - xBound::box and xBound::mat + +void xBoundGetBox(xBox& box, const xBound& bound); +void xBoundDraw(const xBound* bound); +void xQuickCullForBound(xQCData* qc, const xBound* bound); +xVec3* xBoundCenter(xBound* bound); +const xVec3* xBoundCenter(const xBound* bound); +void xBoundUpdate(xBound* b); +void xBoundHitsBound(const xBound* a, const xBound* b, xCollis* c); +void xRayHitsBound(const xRay3* r, const xBound* b, xCollis* c); +void xSphereHitsBound(const xSphere* o, const xBound* b, xCollis* c); +void xVecHitsBound(const xVec3* v, const xBound* b, xCollis* c); +F32 xsqrt(F32 x); + +inline xVec3* xBoundCenter(xBound* bound) +{ + return &bound->sph.center; +} + +inline const xVec3* xBoundCenter(const xBound* bound) +{ + return &bound->sph.center; +} + +#endif diff --git a/src/SB/Core/x/xCM.cpp b/src/SB/Core/x/xCM.cpp new file mode 100644 index 0000000..c4a8984 --- /dev/null +++ b/src/SB/Core/x/xCM.cpp @@ -0,0 +1,115 @@ +#include "xCM.h" +#include "xEvent.h" + +#include + +volatile static F32 credits_time; +static xCreditsData* credits_data; +static U32 credits_parentID; + +F32 dtscale; + +static void xCMprep(xCreditsData* data) +{ + /* + data seems to point to this general structure: + 0x00 - xCMheader + 0x18 - xCMcredits + 0x50 - xCMpreset* presets_array[xCMcredits.num_presets] + - xCMhunk* hunk_array[?] + */ + + char* dp; // In the DWARF. Don't know what this is used for. + xCMheader* hdr = (xCMheader*)data; + + if (hdr->magic != 0xBEEEEEEF) + { + return; + } + + xCMcredits* cp = (xCMcredits *)(&hdr[1]); + while ((int)cp - (int)data < hdr->total_size) + { + xCMpreset* pp = (xCMpreset*)(&cp[1]); + xCMhunk* hp = (xCMhunk*)(&pp[cp->num_presets]); + + for ( ; (int)hp - (int)cp < cp->credits_size; hp = (xCMhunk*)((int)hp + hp->hunk_size)) + { + switch (pp[hp->preset].align) + { + case 0: + case 1: + case 2: + case 3: + + if (hdr->state == 0) + { + if (hp->text1 != NULL) + { + hp->text1 -= (int)data; + } + if (hp->text2 != NULL) + { + hp->text2 -= (int)data; + } + } + else + { + if (hp->text1 != NULL) + { + hp->text1 += (int)data; + } + if (hp->text2 != NULL) + { + hp->text2 += (int)data; + } + } + break; + } + } + cp = (xCMcredits*)hp; + } + + hdr->state = hdr->state == 0 ? 1 : 0; +} + +void xCMupdate(F32 time) +{ + if (credits_data != 0) + { + credits_time += (time * dtscale); + if (credits_time >= *(F32*)((int)&credits_data->dummy + 0x10)) + { + xCMstop(); + } + } +} + +void xCMrender() +{ + xCMrender(credits_time, credits_data); +} + +void xCMstart(xCreditsData* data, F32 time, xBase* parent) +{ + if ((credits_data = data) != NULL) + { + credits_time = 0.0f; + + if (parent != NULL) + { + credits_parentID = parent->id; + } + } +} + +// Equivalent: scheduling +void xCMstop() +{ + credits_time = 10000.0f; + credits_data = NULL; + if (credits_parentID != 0) + { + zEntEvent(credits_parentID, 0x212); + } +} diff --git a/src/SB/Core/x/xCM.h b/src/SB/Core/x/xCM.h new file mode 100644 index 0000000..e0ceb58 --- /dev/null +++ b/src/SB/Core/x/xCM.h @@ -0,0 +1,97 @@ +#ifndef XCM_H +#define XCM_H + +#include +#include "xColor.h" +#include "xBase.h" + +struct xCreditsData +{ + U32 dummy; +}; + +class xCMheader +{ + // total size: 0x18 +public: + unsigned int magic; // offset 0x0, size 0x4 + unsigned int version; // offset 0x4, size 0x4 + unsigned int crdID; // offset 0x8, size 0x4 + unsigned int state; // offset 0xC, size 0x4 + float total_time; // offset 0x10, size 0x4 + unsigned int total_size; // offset 0x14, size 0x4 +}; + +class sxy +{ + // total size: 0x8 +public: + float x; // offset 0x0, size 0x4 + float y; // offset 0x4, size 0x4 +}; + +class fade +{ + // total size: 0x8 +public: + float start; // offset 0x0, size 0x4 + float end; // offset 0x4, size 0x4 +}; + +class xCMtextbox +{ + // total size: 0x20 +public: + unsigned int font; // offset 0x0, size 0x4 + class iColor_tag color; // offset 0x4, size 0x4 + class sxy char_size; // offset 0x8, size 0x8 + class sxy char_spacing; // offset 0x10, size 0x8 + class sxy box; // offset 0x18, size 0x8 +}; + +class xCMpreset +{ + // total size: 0x4C +public: + unsigned short num; // offset 0x0, size 0x2 + unsigned short align; // offset 0x2, size 0x2 + float delay; // offset 0x4, size 0x4 + float innerspace; // offset 0x8, size 0x4 + class xCMtextbox box[2]; // offset 0xC, size 0x40 +}; + +class xCMhunk +{ + // total size: 0x18 +public: + unsigned int hunk_size; // offset 0x0, size 0x4 + unsigned int preset; // offset 0x4, size 0x4 + float t0; // offset 0x8, size 0x4 + float t1; // offset 0xC, size 0x4 + char * text1; // offset 0x10, size 0x4 + char * text2; // offset 0x14, size 0x4 +}; + +class xCMcredits +{ + // total size: 0x38 +public: + unsigned int credits_size; // offset 0x0, size 0x4 + float len; // offset 0x4, size 0x4 + unsigned int flags; // offset 0x8, size 0x4 + sxy in; // offset 0xC, size 0x8 + sxy out; // offset 0x14, size 0x8 + float scroll_rate; // offset 0x1C, size 0x4 + float lifetime; // offset 0x20, size 0x4 + fade fin; // offset 0x24, size 0x8 + fade fout; // offset 0x2C, size 0x8 + unsigned int num_presets; // offset 0x34, size 0x4 +}; + +void xCMupdate(F32 dt); +void xCMrender(); +void xCMrender(F32 time, xCreditsData* data); +void xCMstart(xCreditsData* data, F32, xBase* parent); +void xCMstop(); + +#endif diff --git a/src/SB/Core/x/xCamera.cpp b/src/SB/Core/x/xCamera.cpp index e69de29..2400691 100644 --- a/src/SB/Core/x/xCamera.cpp +++ b/src/SB/Core/x/xCamera.cpp @@ -0,0 +1,1344 @@ +#include "xCamera.h" + +#include "xstransvc.h" +#include "xMath.h" +#include "xMathInlines.h" +#include "xScene.h" +#include "xCollideFast.h" +#include "xScrFx.h" + +#include "iMath.h" + +#include +#include + +struct cameraFXShake +{ + F32 magnitude; + xVec3 dir; + F32 cycleTime; + F32 cycleMax; + F32 dampen; + F32 dampenRate; + F32 rotate_magnitude; + F32 radius; + xVec3* epicenterP; + xVec3 epicenter; + xVec3* player; +}; + +struct cameraFXZoom +{ + F32 holdTime; + F32 vel; + F32 accel; + F32 distance; + U32 mode; + F32 velCur; + F32 distanceCur; + F32 holdTimeCur; +}; + +#define CAMERAFX_ZOOM_MODE_0 0 +#define CAMERAFX_ZOOM_MODE_1 1 +#define CAMERAFX_ZOOM_MODE_2 2 +#define CAMERAFX_ZOOM_MODE_3 3 + +struct cameraFX +{ + S32 type; + S32 flags; + F32 elapsedTime; + F32 maxTime; + union + { + cameraFXShake shake; + cameraFXZoom zoom; + }; +}; + +#define CAMERAFX_TYPE_SHAKE 2 + +struct cameraFXTableEntry +{ + S32 type; + void (*func)(cameraFX*, F32, xMat4x3*, xMat4x3*); + void (*funcKill)(cameraFX*); +}; + +extern F32 _764; +extern F32 _765; +extern F32 _766; +extern F32 _785; +extern F32 _786; +extern F32 _787; +extern F32 _788; +extern F32 _789; +extern F32 _790; +extern F32 _830; +extern F32 _831; +extern F32 _873; +extern F32 _874; +extern F32 _880; +extern F32 _888; +extern F32 _895; +extern F32 _1234; +extern F32 _1235; +extern F32 _1236; +extern F32 _1237; +extern F32 _1238; +extern F32 _1239; +extern F32 _1240; +extern F32 _1241; +extern F32 _1242; +extern F32 _1283; +extern F64 _1286; +extern F32 _1404; +extern F32 _1405; +extern F32 _1534; +extern F32 _1584; +extern F32 _1585; +extern F32 _1586; +extern F32 _1757; +extern F32 _1758; +extern F32 _1766; +extern F32 _1772; + +extern S32 sCamCollis; +extern volatile S32 xcam_collis_owner_disable; +extern S32 xcam_do_collis; +extern F32 xcam_collis_radius; +extern F32 xcam_collis_stiffness; +extern RpAtomic* sInvisWallHack; +extern xMat4x3 sCameraFXMatOld; +extern cameraFX sCameraFX[10]; +extern cameraFXTableEntry sCameraFXTable[3]; + +static void xCameraFXInit(); +void add_camera_tweaks(); + +void xCameraInit(xCamera* cam, U32 width, U32 height) +{ + xCameraFXInit(); + + cam->lo_cam = iCameraCreate(width, height, 1); + + xCameraSetFOV(cam, _764); + + cam->bound.sph.center.x = _765; + cam->bound.sph.center.y = _765; + cam->bound.sph.center.z = _765; + cam->bound.sph.r = _766; + cam->tgt_mat = NULL; + cam->tgt_omat = NULL; + cam->tgt_bound = NULL; + cam->sc = NULL; + cam->tran_accum.x = _765; + cam->tran_accum.y = _765; + cam->tran_accum.z = _765; + + add_camera_tweaks(); +} + +void add_camera_tweaks() +{ +} + +void xCameraExit(xCamera* cam) +{ + if (cam->lo_cam) + { + iCameraDestroy(cam->lo_cam); + cam->lo_cam = NULL; + } +} + +void xCameraReset(xCamera* cam, F32 d, F32 h, F32 pitch) +{ + sInvisWallHack = (RpAtomic*)xSTFindAsset(0xB8895D14, NULL); + + xMat4x3Identity(&cam->mat); + + cam->omat = cam->mat; + cam->focus.x = _765; + cam->focus.y = _765; + cam->focus.z = _785; + cam->tran_accum.x = _765; + cam->tran_accum.y = _765; + cam->tran_accum.z = _765; + cam->flags = 0; + + F32 goal_p = _786; + + if (cam->tgt_mat) + { + goal_p += xatan2(cam->tgt_mat->at.x, cam->tgt_mat->at.z); + } + + xCameraMove(cam, 0x2E, d, h, goal_p, _765, _787, _787); + + cam->pitch_goal = pitch; + cam->pitch_cur = pitch; + cam->roll_cur = _765; + + xMat3x3Euler(&cam->mat, cam->yaw_cur, cam->pitch_cur, cam->roll_cur); + + cam->omat = cam->mat; + cam->yaw_ct = _788; + cam->yaw_cd = _788; + cam->yaw_ccv = _789; + cam->yaw_csv = _788; + cam->pitch_ct = _788; + cam->pitch_cd = _788; + cam->pitch_ccv = _790; + cam->pitch_csv = _788; + cam->roll_ct = _788; + cam->roll_cd = _788; + cam->roll_ccv = _790; + cam->roll_csv = _788; + cam->flags |= 0x80; + + xcam_do_collis = 1; + xcam_collis_owner_disable = 0; +} + +static void xCam_buildbasis(xCamera* cam) +{ + if (cam->tgt_mat) + { + F32 d2d; + F32 dx__ = cam->mat.pos.x - cam->tgt_mat->pos.x; + F32 dz__ = cam->mat.pos.z - cam->tgt_mat->pos.z; + + F32 dist2 = SQR(dx__) + SQR(dz__); + F32 dist_inv; + + if ((F32)iabs(dist2 - _788) <= _830) + { + cam->mbasis.at.x = dx__; + cam->mbasis.at.z = dz__; + + d2d = _788; + } + else if ((F32)iabs(dist2) <= _830) + { + cam->mbasis.at.x = _765; + cam->mbasis.at.z = _765; + + d2d = _765; + } + else + { + d2d = xsqrt(dist2); + dist_inv = _788 / d2d; + + cam->mbasis.at.x = dx__ * dist_inv; + cam->mbasis.at.z = dz__ * dist_inv; + } + + if (d2d < _830) + { + cam->mbasis.at.x = cam->mat.at.x; + cam->mbasis.at.z = cam->mat.at.z; + + dist2 = xsqrt(SQR(cam->mbasis.at.x) + SQR(cam->mbasis.at.z)); + + if (dist2 > _831) + { + // non-matching: wrong registers + dist_inv = _788 / dist2; + + cam->mbasis.at.x *= dist_inv; + cam->mbasis.at.z *= dist_inv; + } + else + { + cam->mbasis.at.x = isin(cam->pcur); + cam->mbasis.at.z = icos(cam->pcur); + } + } + + cam->mbasis.at.y = _765; + cam->mbasis.up.x = _765; + cam->mbasis.up.y = _788; + cam->mbasis.up.z = _765; + cam->mbasis.right.x = cam->mbasis.at.z; + cam->mbasis.right.y = _765; + cam->mbasis.right.z = -cam->mbasis.at.x; + } +} + +static void xCam_cyltoworld(xVec3* v, const xMat4x3* tgt_mat, F32 d, F32 h, F32 p, U32 flags) +{ + if (flags & 0x10) + { + v->y = h; + } + else + { + v->y = h + tgt_mat->pos.y; + } + + if (flags & 0x20) + { + v->x = d * isin(p) + tgt_mat->pos.x; + v->z = d * icos(p) + tgt_mat->pos.z; + } + else + { + p += xatan2(tgt_mat->at.x, tgt_mat->at.z); + + v->x = d * isin(p) + tgt_mat->pos.x; + v->z = d * icos(p) + tgt_mat->pos.z; + } +} + +static void xCam_worldtocyl(F32& d, F32& h, F32& p, const xMat4x3* tgt_mat, const xVec3* v, + U32 flags) +{ + F32 lx, lz; + + F32 dx__ = v->x - tgt_mat->pos.x; + F32 dz__ = v->z - tgt_mat->pos.z; + + F32 dist2 = SQR(dx__) + SQR(dz__); + F32 dist_inv; + + if ((F32)iabs(dist2 - _788) <= _830) + { + lx = dx__; + lz = dz__; + d = _788; + } + else if ((F32)iabs(dist2) <= _830) + { + d = lz = lx = _765; + } + else + { + d = xsqrt(dist2); + + dist_inv = _788 / d; + + lx = dx__ * dist_inv; + lz = dz__ * dist_inv; + } + + if (flags & 0x10) + { + h = v->y; + } + else + { + h = v->y - tgt_mat->pos.y; + } + + p = xatan2(lx, lz); + + if (!(flags & 0x20)) + { + F32 tgt_p = p - xatan2(tgt_mat->at.x, tgt_mat->at.z); + + p = xDangleClamp(tgt_p); + } +} + +static void xCam_CorrectD(xCamera* r3, F32 f1, F32 f2, F32 f3) +{ + // non-matching: incorrect float register + + F32 tmp1, tmp2, tmp3; + + tmp1 = _873 * (_874 * f1 - f2 * f3); + tmp1 -= f2; + tmp1 *= f3; + + tmp2 = r3->mbasis.at.x * tmp1; + tmp3 = r3->mbasis.at.z * tmp1; + + r3->mat.pos.x += tmp2; + r3->mat.pos.z += tmp3; +} + +static void xCam_CorrectH(xCamera* r3, F32 f1, F32 f2, F32 f3) +{ + F32 tmp; + + f2 = _880 * f2; + + tmp = _873 * -(f2 * f3 - f1); + tmp -= f2; + tmp *= f3; + + r3->mat.pos.y += tmp; +} + +static void xCam_CorrectP(xCamera* r3, F32 f1, F32 f2, F32 f3) +{ + F32 tmp1, tmp2, tmp3; + + f2 = _880 * f2; + + tmp1 = _888 * (_874 * f1 - f2 * f3); + tmp1 -= f2; + tmp1 *= f3; + + tmp2 = r3->mbasis.right.x * tmp1; + tmp3 = r3->mbasis.right.z * tmp1; + + r3->mat.pos.x += tmp2; + r3->mat.pos.z += tmp3; +} + +static void xCam_DampP(xCamera* r3, F32 f1, F32 f2) +{ + F32 tmp1, tmp2; + + f1 = _895 * f1; + f2 = f1 * f2 * f2; + + tmp1 = r3->mbasis.right.x * f2; + tmp2 = r3->mbasis.right.z * f2; + + r3->mat.pos.x += tmp1; + r3->mat.pos.z += tmp2; +} +static void xCam_CorrectYaw(xCamera* r3, F32 f1, F32 f2, F32 f3) +{ + // non-matching: incorrect float registers, slightly out-of-order fmsubs instruction + + F32 tmp1, tmp2; + + tmp1 = _788 / r3->yaw_ct; + + tmp2 = _874 * r3->yaw_cd * f1 - f2 * f3; + tmp2 = tmp1 * tmp2; + tmp2 -= f2; + tmp2 *= r3->yaw_csv * f3; + + r3->yaw_cur += tmp2; +} +static void xCam_CorrectPitch(xCamera* r3, F32 f1, F32 f2, F32 f3) +{ + // non-matching: same reasons as xCam_CorrectYaw + + F32 tmp1, tmp2; + + tmp1 = _788 / r3->pitch_ct; + + tmp2 = _874 * r3->pitch_cd * f1 - f2 * f3; + tmp2 = tmp1 * tmp2; + tmp2 -= f2; + tmp2 *= r3->pitch_csv * f3; + + r3->pitch_cur += tmp2; +} + +static void xCam_CorrectRoll(xCamera* r3, F32 f1, F32 f2, F32 f3) +{ + // non-matching: same reasons as xCam_CorrectYaw + + F32 tmp1, tmp2; + + tmp1 = _788 / r3->roll_ct; + + tmp2 = _874 * r3->roll_cd * f1 - f2 * f3; + tmp2 = tmp1 * tmp2; + tmp2 -= f2; + tmp2 *= r3->roll_csv * f3; + + r3->roll_cur += tmp2; +} + +void SweptSphereHitsCameraEnt(xScene*, xRay3* ray, xQCData* qcd, xEnt* ent, void* data) +{ + xSweptSphere* sws = (xSweptSphere*)data; + + if (ent->camcollModel && ent->chkby & 0x10 && xQuickCullIsects(qcd, &ent->bound.qcd)) + { + if (!xEntIsVisible(ent)) + { + if (ent->model->Data != sInvisWallHack) + { + return; + } + + if (ent->collLev != 5) + { + if (ent->bound.type == XBOUND_TYPE_BOX) + { + xSweptSphereToBox(sws, &ent->bound.box.box, NULL); + return; + } + else if (ent->bound.type == XBOUND_TYPE_OBB) + { + xSweptSphereToBox(sws, &ent->bound.box.box, ent->bound.mat); + return; + } + else + { + return; + } + } + } + + U32 result = 0; + + switch (ent->bound.type) + { + case XBOUND_TYPE_SPHERE: + { + F32 oldrad = ent->bound.sph.r; + + ent->bound.sph.r += sws->radius; + + result = xRayHitsSphereFast(ray, &ent->bound.sph); + + ent->bound.sph.r = oldrad; + + break; + } + case XBOUND_TYPE_BOX: + { + xBox tmpbox; + tmpbox.upper.x = ent->bound.box.box.upper.x + sws->radius; + tmpbox.upper.y = ent->bound.box.box.upper.y + sws->radius; + tmpbox.upper.z = ent->bound.box.box.upper.z + sws->radius; + tmpbox.lower.x = ent->bound.box.box.lower.x - sws->radius; + tmpbox.lower.y = ent->bound.box.box.lower.y - sws->radius; + tmpbox.lower.z = ent->bound.box.box.lower.z - sws->radius; + + result = xRayHitsBoxFast(ray, &tmpbox); + + break; + } + case XBOUND_TYPE_OBB: + { + xBox tmpbox; + xRay3 lr; + xMat3x3 mn; + + F32 f31 = xVec3Length(&ent->bound.mat->right); + + xMat3x3Normalize(&mn, ent->bound.mat); + xMat4x3Tolocal(&lr.origin, ent->bound.mat, &ray->origin); + xMat3x3Tolocal(&lr.dir, &mn, &ray->dir); + + lr.max_t = ray->max_t / f31; + lr.min_t = ray->min_t / f31; + lr.flags = ray->flags; + + tmpbox.upper.x = ent->bound.box.box.upper.x + sws->radius / f31; + tmpbox.upper.y = ent->bound.box.box.upper.y + sws->radius / f31; + tmpbox.upper.z = ent->bound.box.box.upper.z + sws->radius / f31; + tmpbox.lower.x = ent->bound.box.box.lower.x - sws->radius / f31; + tmpbox.lower.y = ent->bound.box.box.lower.y - sws->radius / f31; + tmpbox.lower.z = ent->bound.box.box.lower.z - sws->radius / f31; + + result = xRayHitsBoxFast(&lr, &tmpbox); + + break; + } + } + + if (result) + { + xModelInstance* collmod = ent->camcollModel; + + xSweptSphereToModel(sws, collmod->Data, collmod->Mat); + } + } +} + +static void _xCameraUpdate(xCamera* cam, F32 dt) +{ + // lol nope +} + +void xCameraUpdate(xCamera* cam, F32 dt) +{ + S32 i; + S32 num_updates; + F32 sdt; + + num_updates = std::ceilf(_1283 * dt); + + sdt = dt / num_updates; + + for (i = 0; i < num_updates; i++) + { + sCamCollis = (i == num_updates - 1); + + _xCameraUpdate(cam, sdt); + } +} + +#ifndef INLINE +float std::ceilf(float x) +{ + return (float)ceil((double)x); +} +#endif + +void xCameraBegin(xCamera* cam, S32 clear) +{ + iCameraBegin(cam->lo_cam, clear); + iCameraFrustumPlanes(cam->lo_cam, cam->frustplane); + iCameraUpdateFog(cam->lo_cam, 0); +} + +void xCameraFXBegin(xCamera* cam) +{ + xMat4x3Identity(&sCameraFXMatOld); + xMat4x3Copy(&sCameraFXMatOld, &cam->mat); +} + +static void xCameraFXInit() +{ + memset(sCameraFX, 0, sizeof(sCameraFX)); + + sCameraFX[0].flags = 0; + sCameraFX[1].flags = 0; + sCameraFX[2].flags = 0; + sCameraFX[3].flags = 0; + sCameraFX[4].flags = 0; + sCameraFX[5].flags = 0; + sCameraFX[6].flags = 0; + sCameraFX[7].flags = 0; + sCameraFX[8].flags = 0; + sCameraFX[9].flags = 0; +} + +cameraFX* xCameraFXAlloc() +{ + S32 i; + cameraFX* f; + + for (i = 0; i < sizeof(sCameraFX) / sizeof(cameraFX); i++) + { + f = &sCameraFX[i]; + + if (f->flags == 0) + { + // non-matching: _765 is only loaded once + + f->flags = 0x1; + f->elapsedTime = _765; + f->maxTime = _765; + + return f; + } + } + + return NULL; +} + +void xCameraFXZoomUpdate(cameraFX* f, F32 dt, const xMat4x3*, xMat4x3* m) +{ + switch (f->zoom.mode) + { + case CAMERAFX_ZOOM_MODE_0: + { + f->zoom.velCur += f->zoom.accel * dt; + f->zoom.distanceCur += f->zoom.velCur * dt; + + if (f->zoom.distanceCur >= f->zoom.distance) + { + f->zoom.distanceCur = f->zoom.distance; + f->zoom.mode = CAMERAFX_ZOOM_MODE_2; + f->zoom.holdTimeCur = _765; + } + + xMat4x3MoveLocalAt(m, f->zoom.distanceCur); + + break; + } + case CAMERAFX_ZOOM_MODE_2: + { + f->zoom.holdTimeCur += dt; + + if (f->zoom.holdTimeCur > f->zoom.holdTime) + { + f->zoom.mode = CAMERAFX_ZOOM_MODE_1; + f->zoom.distanceCur = f->zoom.distance; + f->zoom.velCur = f->zoom.vel; + } + + xMat4x3MoveLocalAt(m, f->zoom.distance); + + break; + } + case CAMERAFX_ZOOM_MODE_1: + { + f->zoom.velCur += f->zoom.accel * dt; + f->zoom.distanceCur -= f->zoom.velCur * dt; + + if (f->zoom.distanceCur <= 0.0f) + { + f->zoom.distanceCur = 0.0f; + f->zoom.mode = CAMERAFX_ZOOM_MODE_3; + f->flags |= 0x2; + } + + xMat4x3MoveLocalAt(m, f->zoom.distanceCur); + + break; + } + case CAMERAFX_ZOOM_MODE_3: + { + break; + } + } +} + +void xCameraFXShake(F32 maxTime, F32 magnitude, F32 cycleMax, F32 rotate_magnitude, F32 radius, + xVec3* epicenter, xVec3* player) +{ + cameraFX* f = xCameraFXAlloc(); + + if (f) + { + f->type = CAMERAFX_TYPE_SHAKE; + f->maxTime = maxTime; + f->shake.magnitude = magnitude; + f->shake.dir.x = _788; + f->shake.dir.y = _788; + f->shake.cycleMax = cycleMax; + f->shake.cycleTime = _765; + f->shake.dampen = _765; + f->shake.dampenRate = _788 / maxTime; + f->shake.rotate_magnitude = rotate_magnitude; + f->shake.radius = radius; + f->shake.epicenterP = epicenter; + + if (f->shake.epicenterP) + { + f->shake.epicenter = *f->shake.epicenterP; + } + + f->shake.player = player; + } +} + +void xCameraFXShakeUpdate(cameraFX* f, F32 dt, const xMat4x3*, xMat4x3* m) +{ + F32 x, y, scale, noise; + xVec3 var_4C, e; + + f->shake.cycleTime += dt; + + while (f->shake.cycleTime > f->shake.cycleMax) + { + f->shake.dir.x = -f->shake.dir.x; + f->shake.dir.y = -f->shake.dir.y; + f->shake.cycleTime -= f->shake.cycleMax; + } + + scale = f->shake.dampenRate * (f->maxTime - f->elapsedTime); + noise = _1404 * (xurand() - _766); + + if (f->shake.radius > _765 && f->shake.player) + { + xVec3Sub(&var_4C, f->shake.player, &f->shake.epicenter); + + F32 f1 = var_4C.length(); + + if (f1 > f->shake.radius) + { + scale = _765; + } + else + { + scale *= icos(f1 / f->shake.radius * _786 * _766); + } + } + + x = (f->shake.magnitude + noise) * f->shake.dir.x * scale / f->shake.cycleMax * + f->shake.cycleTime * isin(f->shake.cycleTime / f->shake.cycleMax * _786); + + noise = _1404 * (xurand() - _766); + + y = (f->shake.magnitude + noise) * f->shake.dir.y * scale / f->shake.cycleMax * + f->shake.cycleTime * isin(f->shake.cycleTime / f->shake.cycleMax * _786); + + xMat4x3MoveLocalRight(m, x); + xMat4x3MoveLocalUp(m, y); + + xMat3x3GetEuler(m, &e); + + e.z += + f->shake.cycleTime / f->shake.cycleMax * _1405 * _1404 * scale * f->shake.rotate_magnitude; + + xMat3x3Euler(m, &e); +} + +void xCameraFXUpdate(xCamera* cam, F32 dt) +{ + S32 i; + cameraFX* f; + cameraFXTableEntry* t; + + for (i = 0; i < 10; i++) + { + f = &sCameraFX[i]; + + if (f->flags & 0x1) + { + f->elapsedTime += dt; + + // non-matching: _765 is loaded too early + + if ((f->maxTime > _765 && f->elapsedTime > f->maxTime) || f->flags & 0x2) + { + f->flags = 0; + + t = &sCameraFXTable[f->type]; + + if (t->funcKill) + { + t->funcKill(f); + } + } + else + { + t = &sCameraFXTable[f->type]; + + if (t->func) + { + t->func(f, dt, &sCameraFXMatOld, &cam->mat); + } + } + } + } + + iCameraUpdatePos(cam->lo_cam, &cam->mat); +} + +void xCameraFXEnd(xCamera* cam) +{ + xMat4x3Copy(&cam->mat, &sCameraFXMatOld); + iCameraUpdatePos(cam->lo_cam, &sCameraFXMatOld); +} + +void xCameraEnd(xCamera* cam, F32 seconds, S32 update_scrn_fx) +{ + if (update_scrn_fx) + { + xScrFxUpdate(cam->lo_cam, seconds); + } + + iCameraEnd(cam->lo_cam); +} + +void xCameraShowRaster(xCamera* cam) +{ + iCameraShowRaster(cam->lo_cam); +} + +void xCameraSetScene(xCamera* cam, xScene* sc) +{ + cam->sc = sc; + + iCameraAssignEnv(cam->lo_cam, sc->env->geom); +} + +void xCameraSetTargetMatrix(xCamera* cam, xMat4x3* mat) +{ + cam->tgt_mat = mat; +} + +void xCameraSetTargetOMatrix(xCamera* cam, xMat4x3* mat) +{ + cam->tgt_omat = mat; +} + +void xCameraDoCollisions(S32 do_collis, S32 owner) +{ + xcam_collis_owner_disable &= ~(1 << owner); + xcam_collis_owner_disable |= !do_collis << owner; + + xcam_do_collis = (xcam_collis_owner_disable == 0); +} + +void xCameraMove(xCamera* cam, U32 flags, F32 dgoal, F32 hgoal, F32 pgoal, F32 tm, F32 tm_acc, + F32 tm_dec) +{ + cam->flags = (cam->flags & ~0x3E) | (flags & 0x3E); + cam->dgoal = dgoal; + cam->hgoal = hgoal; + cam->pgoal = pgoal; + + if (tm <= _765) + { + if (cam->tgt_mat) + { + cam->dcur = dgoal; + cam->hcur = hgoal; + cam->pcur = pgoal; + + xCam_cyltoworld(&cam->mat.pos, cam->tgt_mat, dgoal, hgoal, pgoal, cam->flags); + + cam->omat.pos = cam->mat.pos; + cam->yaw_cur = cam->yaw_goal = cam->pcur + ((cam->pcur >= _786) ? _1534 : _786); + } + } + else + { + cam->flags |= 0x1; + cam->tm_acc = tm - tm_acc; + cam->tm_dec = tm_dec; + cam->tmr = tm; + + F32 s = _788 / (tm - _766 * (tm_acc - tm_dec)); + + cam->depv = s * (dgoal - cam->dcur); + cam->hepv = s * (hgoal - cam->hcur); + cam->pepv = xDangleClamp(pgoal - cam->pcur) * s * _766 * (dgoal + cam->dcur); + } +} + +void xCameraMove(xCamera* cam, const xVec3& loc) +{ + cam->omat.pos = cam->mat.pos = loc; + cam->flags &= ~0x3E; + cam->tm_acc = cam->tm_dec = cam->tmr = _765; +} + +void xCameraMove(xCamera* cam, const xVec3& loc, F32 maxSpeed) +{ + xVec3 var_28; + F32 f1; + + xVec3Sub(&var_28, &loc, &cam->mat.pos); + + f1 = xVec3Length(&var_28); + + if (f1 > maxSpeed) + { + xVec3SMul(&var_28, &var_28, maxSpeed / f1); + xVec3Add(&cam->mat.pos, &cam->mat.pos, &var_28); + } + else + { + cam->mat.pos = loc; + } + + cam->omat.pos = cam->mat.pos; + cam->flags &= ~0x3E; + cam->tm_acc = cam->tm_dec = cam->tmr = _765; +} + +void xCameraFOV(xCamera* cam, F32 fov, F32 maxSpeed, F32 dt) +{ + F32 speed = maxSpeed * dt; + F32 currentFOV = xCameraGetFOV(cam); + + if (currentFOV != fov) + { + if (speed != _765) + { + F32 len = fov - currentFOV; + + if ((F32)iabs(len) > speed) + { + len *= speed / len; + xCameraSetFOV(cam, currentFOV + len); + } + else + { + xCameraSetFOV(cam, fov); + } + } + else + { + xCameraSetFOV(cam, fov); + } + } +} + +void xCameraLook(xCamera* cam, U32 flags, const xQuat* orn_goal, F32 tm, F32 tm_acc, F32 tm_dec) +{ + F32 s; // unused + + cam->flags = (cam->flags & ~0xF80) | (flags & 0xF80); + cam->orn_goal = *orn_goal; + + if (tm <= _765) + { + if (cam->tgt_mat) + { + xQuatToMat(orn_goal, &cam->mat); + + *(xMat3x3*)&cam->omat = *(xMat3x3*)&cam->mat; + } + } + else + { + cam->flags |= 0x40; + cam->ltm_acc = tm - tm_acc; + cam->ltm_dec = tm_dec; + cam->ltmr = tm; + + xQuatDiff(&cam->orn_diff, &cam->orn_cur, orn_goal); + + cam->orn_epv = _788 / (tm - _766 * (tm_acc - tm_dec)) * xQuatGetAngle(&cam->orn_diff); + } +} + +void xCameraLookYPR(xCamera* cam, U32 flags, F32 yaw, F32 pitch, F32 roll, F32 tm, F32 tm_acc, + F32 tm_dec) +{ + cam->flags = (cam->flags & ~0xF80) | (flags & 0xF80) | 0x80; + cam->yaw_goal = yaw; + cam->pitch_goal = pitch; + cam->roll_goal = roll; + + if (tm <= _765) + { + if (cam->tgt_mat) + { + cam->yaw_cur = yaw; + cam->pitch_cur = pitch; + cam->roll_cur = roll; + + xMat3x3Euler(&cam->mat, yaw, pitch, roll); + + *(xMat3x3*)&cam->omat = *(xMat3x3*)&cam->mat; + } + } + else + { + cam->flags |= 0x40; + cam->ltm_acc = tm - tm_acc; + cam->ltm_dec = tm_dec; + cam->ltmr = tm; + + F32 s = _788 / (tm - _766 * (tm_acc - tm_dec)); + + cam->yaw_epv = s * xDangleClamp(yaw - cam->yaw_cur); + cam->pitch_epv = s * xDangleClamp(pitch - cam->pitch_cur); + cam->roll_epv = s * xDangleClamp(roll - cam->roll_cur); + } +} + +void xCameraRotate(xCamera* cam, const xMat3x3& m, F32 time, F32 accel, F32 decl) +{ + xVec3 eu; + + cam->flags = cam->flags & ~0xF80 | 0x80; + + xMat3x3GetEuler(&m, &eu); + + cam->yaw_goal = eu.x; + cam->pitch_goal = eu.y; + cam->roll_goal = eu.z; + + if (_765 == time) + { + cam->yaw_cur = eu.x; + cam->pitch_cur = eu.y; + cam->roll_cur = eu.z; + } + + *(xMat3x3*)&cam->mat = m; + + if (_765 == time) + { + *(xMat3x3*)&cam->omat = m; + } + + if (_765 == time) + { + cam->ltm_acc = cam->ltm_dec = cam->ltmr = _765; + } + else + { + cam->ltm_acc = accel; + cam->ltm_dec = decl; + cam->ltmr = time; + } + + cam->yaw_epv = cam->pitch_epv = cam->roll_epv = _765; +} + +void xCameraRotate(xCamera* cam, const xVec3& v, F32 roll, F32 time, F32 accel, F32 decl) +{ + cam->yaw_goal = xatan2(v.x, v.z); + cam->pitch_goal = -xasin(v.y); + cam->roll_goal = roll; + + if (_765 == time) + { + cam->yaw_cur = cam->yaw_goal; + cam->pitch_cur = cam->pitch_goal; + cam->roll_cur = cam->roll_goal; + } + + cam->flags = cam->flags & ~0xF80 | 0x80; + + xMat3x3Euler(&cam->mat, cam->yaw_goal, cam->pitch_goal, cam->roll_goal); + + if (_765 == time) + { + *(xMat3x3*)&cam->omat = *(xMat3x3*)&cam->mat; + } + + if (_765 == time) + { + cam->ltm_acc = cam->ltm_dec = cam->ltmr = _765; + } + else + { + cam->ltm_acc = accel; + cam->ltm_dec = decl; + cam->ltmr = time; + } + + cam->yaw_epv = cam->pitch_epv = cam->roll_epv = _765; +} + +F32 xasin(F32 x) +{ + return std::asinf(x); +} + +#ifndef INLINE +float std::asinf(float x) +{ + return (float)asin((double)x); +} +#endif + +static void bound_sphere_xz(xVec3& r3, xVec3& r4, const xVec3& r5, F32 f1, const xVec3& r6, F32 f2) +{ + // non-matching: incorrect registers and out-of-order instructions + F32 _f31 = f1 / f2; + F32 _f3 = _f31 / xsqrt(SQR(f2) - SQR(f1)); + F32 _f5 = f1 * _f31; + F32 _f7 = _f3 * r6.z; + F32 _f8 = _f5 * r6.x; + F32 _f6 = _f3 * r6.x; + F32 _f5_2 = _f5 * r6.z; + + r3.x = r5.x + _f7 + _f8; + r3.y = r5.y; + r3.z = r5.z - _f6 + _f5_2; + + r4.x = r5.x - _f7 + _f8; + r4.y = r5.y; + r4.z = r5.z + _f6 + _f5_2; +} + +void xBinaryCamera::init() +{ + this->camera = NULL; + this->s2 = NULL; + this->s1 = NULL; +} + +void xBinaryCamera::start(xCamera& camera) +{ + this->camera = &camera; + + xQuatFromMat(&this->cam_dir, &camera.mat); + + this->stick_offset = _765; +} + +void xBinaryCamera::stop() +{ + this->camera = NULL; +} + +void xBinaryCamera::update(F32 dt) +{ +} + +void xCameraSetFOV(xCamera* cam, F32 fov) +{ + cam->fov = fov; + + iCameraSetFOV(cam->lo_cam, fov); +} + +F32 xCameraGetFOV(const xCamera* cam) +{ + return cam->fov; +} + +void xBinaryCamera::render_debug() +{ +} + +void xMat4x3Identity(xMat4x3* m) +{ + xMat4x3Copy(m, &g_I3); +} + +void xMat4x3Copy(xMat4x3* o, const xMat4x3* m) +{ + memcpy(o, m, sizeof(xMat4x3)); +} + +void xQuatConj(xQuat* o, const xQuat* q) +{ + o->s = q->s; + + xVec3Inv(&o->v, &q->v); +} + +void xMat3x3LookAt(xMat3x3* m, const xVec3* pos, const xVec3* at) +{ + xVec3 v; + + xVec3Sub(&v, at, pos); + xMat3x3LookVec(m, &v); +} + +F32 xQuatGetAngle(const xQuat* q) +{ + if (q->s > _1584) + { + return _765; + } + else if (q->s < _1586) + { + return _1585; + } + else + { + return _874 * xacos(q->s); + } +} + +U32 xEntIsVisible(const xEnt* ent) +{ + return (ent->flags & 0x81) == 0x1; +} + +F32 xVec3Length(const xVec3* v) +{ + return xsqrt(SQR(v->x) + SQR(v->y) + SQR(v->z)); +} + +void xVec3Sub(xVec3* o, const xVec3* a, const xVec3* b) +{ + o->x = a->x - b->x; + o->y = a->y - b->y; + o->z = a->z - b->z; +} + +void xVec3Inv(xVec3* o, const xVec3* v) +{ + o->x = -v->x; + o->y = -v->y; + o->z = -v->z; +} + +F32 xacos(F32 x) +{ + return std::acosf(x); +} + +#ifndef INLINE +float std::acosf(float x) +{ + return (float)acos((double)x); +} +#endif + +void xVec3AddTo(xVec3* o, const xVec3* v) +{ + o->x += v->x; + o->y += v->y; + o->z += v->z; +} + +xVec3& xVec3::invert() +{ + this->x = -this->x; + this->y = -this->y; + this->z = -this->z; + + return *this; +} + +F32 xexp(F32 x) +{ + return std::expf(x); +} + +#ifndef INLINE +float std::expf(float x) +{ + return (float)exp((double)x); +} +#endif + +F32 xrmod(F32 ang) +{ + F32 frac = _1766 * ang; + + if (frac < _765) + { + return (frac - std::ceilf(frac) + _788) * _1585; + } + else if (frac >= _788) + { + return (frac - std::floorf(frac)) * _1585; + } + + return ang; +} + +xVec3& xVec3::operator/=(F32 f) +{ + F32 f2 = _788; + + this->x *= f2 / f; + this->y *= f2 / f; + this->z *= f2 / f; + + return *this; +} + +xVec3& xVec3::right_normalize() +{ + return this->safe_normalize(xVec3::m_UnitAxisX); +} + +xVec3& xVec3::safe_normalize(const xVec3& val) +{ + F32 len = this->length2(); + + if (len < _1772) + { + return (*this = val); + } + else + { + return (*this *= _788 / xsqrt(len)); + } +} + +template <> F32 range_limit(F32 v, F32 minv, F32 maxv) +{ + if (v <= minv) + { + return minv; + } + + if (v >= maxv) + { + return maxv; + } + + return v; +} + +xVec2& xVec2::operator=(F32 f) +{ + this->x = this->y = f; + + return *this; +} diff --git a/src/SB/Core/x/xCamera.h b/src/SB/Core/x/xCamera.h new file mode 100644 index 0000000..cc609bc --- /dev/null +++ b/src/SB/Core/x/xCamera.h @@ -0,0 +1,236 @@ +#ifndef XCAMERA_H +#define XCAMERA_H + +#include "iCamera.h" + +#include "xBase.h" +#include "xMath3.h" +#include "xBound.h" +#include "xMath2.h" + +#include + +struct xScene; + +enum _tagTransType +{ + eTransType_None, + eTransType_Interp1, + eTransType_Interp2, + eTransType_Interp3, + eTransType_Interp4, + eTransType_Linear, + eTransType_Interp1Rev, + eTransType_Interp2Rev, + eTransType_Interp3Rev, + eTransType_Interp4Rev, + eTransType_Total +}; + +struct _tagxCamFollowAsset +{ + F32 rotation; + F32 distance; + F32 height; + F32 rubber_band; + F32 start_speed; + F32 end_speed; +}; + +struct _tagxCamShoulderAsset +{ + F32 distance; + F32 height; + F32 realign_speed; + F32 realign_delay; +}; + +struct _tagp2CamStaticAsset +{ + U32 unused; +}; + +struct _tagxCamPathAsset +{ + U32 assetID; + F32 time_end; + F32 time_delay; +}; + +struct _tagp2CamStaticFollowAsset +{ + F32 rubber_band; +}; + +struct xCamAsset : xBaseAsset +{ + xVec3 pos; + xVec3 at; + xVec3 up; + xVec3 right; + xVec3 view_offset; + S16 offset_start_frames; + S16 offset_end_frames; + F32 fov; + F32 trans_time; + _tagTransType trans_type; + U32 flags; + F32 fade_up; + F32 fade_down; + union + { + _tagxCamFollowAsset cam_follow; + _tagxCamShoulderAsset cam_shoulder; + _tagp2CamStaticAsset cam_static; + _tagxCamPathAsset cam_path; + _tagp2CamStaticFollowAsset cam_staticFollow; + }; + U32 valid_flags; + U32 markerid[2]; + U8 cam_type; + U8 pad[3]; +}; + +struct xCamera : xBase +{ + RwCamera* lo_cam; + // Offset: 0x14 + xMat4x3 mat; + // Offset: 0x54 + xMat4x3 omat; + xMat3x3 mbasis; + xBound bound; + xMat4x3* tgt_mat; + xMat4x3* tgt_omat; + xBound* tgt_bound; + xVec3 focus; + xScene* sc; + xVec3 tran_accum; + F32 fov; + U32 flags; + F32 tmr; + F32 tm_acc; + F32 tm_dec; + F32 ltmr; + F32 ltm_acc; + F32 ltm_dec; + F32 dmin; + F32 dmax; + F32 dcur; + F32 dgoal; + F32 hmin; + F32 hmax; + F32 hcur; + F32 hgoal; + F32 pmin; + F32 pmax; + F32 pcur; + F32 pgoal; + F32 depv; + F32 hepv; + F32 pepv; + F32 orn_epv; + F32 yaw_epv; + F32 pitch_epv; + F32 roll_epv; + xQuat orn_cur; + xQuat orn_goal; + xQuat orn_diff; + F32 yaw_cur; + F32 yaw_goal; + F32 pitch_cur; + F32 pitch_goal; + F32 roll_cur; + F32 roll_goal; + F32 dct; + F32 dcd; + F32 dccv; + F32 dcsv; + F32 hct; + F32 hcd; + F32 hccv; + F32 hcsv; + F32 pct; + F32 pcd; + F32 pccv; + F32 pcsv; + F32 orn_ct; + F32 orn_cd; + F32 orn_ccv; + F32 orn_csv; + F32 yaw_ct; + F32 yaw_cd; + F32 yaw_ccv; + F32 yaw_csv; + F32 pitch_ct; + F32 pitch_cd; + F32 pitch_ccv; + F32 pitch_csv; + F32 roll_ct; + F32 roll_cd; + F32 roll_ccv; + F32 roll_csv; + xVec4 frustplane[12]; +}; + +struct xBinaryCamera +{ + struct zone_data + { + F32 distance; + F32 height; + F32 height_focus; + }; + + struct config + { + zone_data zone_rest; + zone_data zone_above; + zone_data zone_below; + F32 move_speed; + F32 turn_speed; + F32 stick_speed; + F32 stick_yaw_vel; + F32 max_yaw_vel; + F32 margin_angle; + }; + + config cfg; + xCamera* camera; + xQuat cam_dir; + xVec3* s1; + xVec3* s2; + F32 s2_radius; + xVec2 stick_offset; + + void init(); + void start(xCamera& camera); + void stop(); + void update(F32 dt); + void add_tweaks(char const*); + void set_targets(xVec3 const& par_1, xVec3 const& par_2, F32 par_3); + void render_debug(); +}; + +F32 xVec3Length(const xVec3* vec); +void xCameraInit(xCamera* cam, U32 width, U32 height); +void xCameraSetScene(xCamera* cam, xScene* sc); +void xCameraReset(xCamera* cam, F32 d, F32 h, F32 pitch); +void xCameraExit(xCamera* cam); +void xCameraUpdate(xCamera* cam, F32 dt); +void xCameraBegin(xCamera* cam, S32); +void xCameraEnd(xCamera* cam, F32 seconds, S32 update_scrn_fx); +void xCameraShowRaster(xCamera* cam); +F32 xCameraGetFOV(const xCamera* cam); +void xCameraSetFOV(xCamera* cam, F32 fov); +void xCameraMove(xCamera* cam, U32 flags, F32 dgoal, F32 hgoal, F32 pgoal, + F32 tm, F32 tm_acc, F32 tm_dec); +void xCameraMove(xCamera* cam, const xVec3& loc); +void xCameraRotate(xCamera* cam, const xMat3x3& m, F32 time, F32 accel, F32 decl); +F32 xCameraGetFOV(const xCamera* cam); +void xCameraDoCollisions(S32 do_collis, S32 owner); +void xCameraSetTargetMatrix(xCamera* cam, xMat4x3* mat); +void xCameraFXShake(F32 maxTime, F32 magnitude, F32 cycleMax, F32 rotate_magnitude, + F32 radius, xVec3* epicenter, xVec3* player); + +#endif diff --git a/src/SB/Core/x/xClimate.cpp b/src/SB/Core/x/xClimate.cpp new file mode 100644 index 0000000..4b42249 --- /dev/null +++ b/src/SB/Core/x/xClimate.cpp @@ -0,0 +1,199 @@ +#include "xClimate.h" + +#include +#include +#include "xMath.h" +#include "xMath3.h" +#include "xString.h" +#include "xVec3.h" +#include "zGlobals.h" +#include "zParEmitter.h" +#include "zParPTank.h" + +_tagClimate* sClimate; + +const float snow_life = 3.0f; +const xVec3 snow_vel = { 0.0f, -2.0f, 0.0f }; +const xVec3 snow_dvel = { 0.1f, 0.1f, 0.1f }; + +void xClimateVecFromAngle(F32 angleDegrees, xVec3* vec) +{ + xMat3x3 Mat; + + xMat3x3Identity(&Mat); + xMat3x3Euler(&Mat, (PI * angleDegrees) / ONEEIGHTY, 0.0f, 0.0f); + xVec3Init(vec, 0.0f, 0.0f, 1.0f); + xMat3x3LMulVec(vec, &Mat, vec); +} + +void xClimateInit(_tagClimate* climate) +{ + climate->rain.strength = 0.0f; + + climate->rain.rain_emitter = zParEmitterFind(xStrHash("PAREMIT_RAIN")); + climate->rain.rain_emitter->emit_flags &= 0xfe; + + climate->rain.snow_emitter = zParEmitterFind(xStrHash("PAREMIT_SNOW")); + climate->rain.snow_emitter->emit_flags &= 0xfe; +} + +// Equivalent +// float ops are being optimized more aggressively +void xClimateInitAsset(_tagClimate* climate, xEnvAsset* asset) +{ + sClimate = climate; + climate->wind.strength = 0.0f; + xClimateVecFromAngle(climate->wind.angle, &climate->wind.dir); + + if (asset->climateFlags == 0) + { + climate->wind.strength = 0.0f; + climate->rain.strength = 0.0f; + return; + } + if (asset->climateFlags & 1) + { + climate->rain.rain = 1.0f; + climate->rain.strength = 0.5f * (asset->climateStrengthMax - asset->climateStrengthMin); + climate->rain.strength += asset->climateStrengthMin; + } + else if (asset->climateFlags & 2) + { + climate->rain.rain = 0.0f; + climate->rain.strength = 0.5f * (asset->climateStrengthMax - asset->climateStrengthMin); + climate->rain.strength += asset->climateStrengthMin; + } +} + +void xClimateSetSnow(F32 stre) +{ + sClimate->rain.rain = 0; + sClimate->rain.strength = stre; +} + +void xClimateSetRain(F32 stre) +{ + sClimate->rain.rain = 1; + sClimate->rain.strength = stre; +} + +// Equivalent +// Float literal is being loaded three separate times in the original code. +void GetPosBigDogWhattupFool(xVec3* vec) +{ + xCamera* camera = &xglobals->camera; + vec->x = 10.0f * camera->mat.at.x + camera->mat.pos.x; + vec->y = 10.0f * camera->mat.at.y + camera->mat.pos.y; + vec->z = 10.0f * camera->mat.at.z + camera->mat.pos.z; +} + +// NOTE (Square): I think it's equivalent but it's very hard to tell. Our compiler is optimizing the float ops +// much more aggresively and it's throwing the regalloc off. +void UpdateRain(_tagClimate* climate, float seconds) +{ + _tagRain* r = &climate->rain; + xParEmitterCustomSettings info; + memset(&info, 0, sizeof(xParEmitterCustomSettings)); + info.custom_flags = 0x100; + + if (r->rain != 0) + { + S32 total_rain_drops = 25.0f * r->strength; + for (S32 i = 0; i < total_rain_drops; i++) + { + GetPosBigDogWhattupFool(&info.pos); + info.pos.x += 25.0f * xurand() - 12.5f; + info.pos.y += 8.0f; + info.pos.z += 25.0f * xurand() - 12.5f; + xParEmitterEmitCustom(r->rain_emitter, seconds, &info); + } + return; + } + + xVec3 fool; + S32 total_snow_flakes = 25.0f * r->strength; + info.custom_flags |= 0x202; + GetPosBigDogWhattupFool(&fool); + if (gPTankDisable) + { + for (S32 i = 0; i < total_snow_flakes; i++) + { + info.pos = fool; + info.pos.x += 45.0f * xurand() - 22.5f; + info.pos.z += 25.0f * xurand() - 22.5f; + + F32 xx = info.pos.x - fool.x; + F32 zz = info.pos.z - fool.z; + F32 perc = 1.0f - xx * zz / 506.25f; + info.pos.y += 4.0f * perc + 4.0f; + + info.vel.x = snow_dvel.x * xurand() + snow_vel.x; + info.vel.y = snow_dvel.y * xurand() + snow_vel.y; + info.vel.z = snow_dvel.z * xurand() + snow_vel.z; + + info.life.val[0] = snow_life * perc + snow_life; + xParEmitterEmitCustom(r->snow_emitter, seconds, &info); + } + return; + } + + S32 num = (F32)total_snow_flakes * 0.1f; + if (num > 0) + { + xVec3* pos = (xVec3*)xMemPushTemp(num * 2 * sizeof(xVec3)); + xVec3* vel = pos + num; + if (pos != NULL) + { + for (S32 i = 0; i < num; i++) + { + *pos = fool; + pos->x += 45.0f * xurand() - 22.5f; + pos->z += 45.0f * xurand() - 22.5f; + + F32 zz = pos->z - fool.z; + F32 xx = pos->x - fool.x; + float perc = (1.0f - (xx * xx + zz * zz) / 506.25f); + + pos->y += 4.0f * perc + 4.0f; + + vel->x = snow_dvel.x * xurand() + snow_vel.x; + vel->y = snow_dvel.y * xurand() + snow_vel.y; + vel->z = snow_dvel.z * xurand() + snow_vel.z; + + pos++; + vel++; + } + + zParPTankSpawnSnow(pos, vel, num); + xMemPopTemp(pos); + } + } +} + +void UpdateWind(_tagClimate* climate, F32 seconds) +{ + return; +} + +void xClimateUpdate(_tagClimate* climate, F32 seconds) +{ + UpdateRain(climate, seconds); + UpdateWind(climate, seconds); +} + +void xVec3Init(xVec3* vec, F32 x, F32 y, F32 z) +{ + vec->x = x; + vec->y = y; + vec->z = z; +} + +void xMat3x3Identity(xMat3x3* matrix) +{ + xMat3x3Copy(matrix, &g_I3); +} + +void xMat3x3Copy(xMat3x3* m1, const xMat3x3* m2) +{ + memcpy(m1, m2, sizeof(xMat3x3)); +} diff --git a/src/SB/Core/x/xClimate.h b/src/SB/Core/x/xClimate.h new file mode 100644 index 0000000..868dd93 --- /dev/null +++ b/src/SB/Core/x/xClimate.h @@ -0,0 +1,41 @@ +#ifndef XCLIMATE_H +#define XCLIMATE_H + +#include +#include "xVec3.h" + +struct xEnvAsset; +struct zParEmitter; + +extern const float snow_life; + +struct _tagRain +{ + S32 rain; + F32 strength; + zParEmitter* rain_emitter; + zParEmitter* snow_emitter; +}; + +struct _tagWind +{ + F32 strength; + F32 angle; + xVec3 dir; +}; + +struct _tagClimate +{ + _tagRain rain; + _tagWind wind; +}; + +void xClimateUpdate(_tagClimate* climate, F32 seconds); +void UpdateRain(_tagClimate* climate, F32 seconds); +void UpdateWind(_tagClimate* climate, F32 seconds); +void xClimateSetRain(F32 stre); +void xClimateSetSnow(F32 stre); +void xClimateInitAsset(_tagClimate* climate, xEnvAsset* easset); +void xClimateInit(_tagClimate* climate); + +#endif diff --git a/src/SB/Core/x/xClumpColl.cpp b/src/SB/Core/x/xClumpColl.cpp new file mode 100644 index 0000000..046bb97 --- /dev/null +++ b/src/SB/Core/x/xClumpColl.cpp @@ -0,0 +1,92 @@ +#include "xClumpColl.h" + +#include + +xClumpCollBSPTree* xClumpColl_StaticBufferInit(void* data, U32 param_2) +{ + U32* header; // unused + + U32 numBranchNodes = *(U32*)((int)data + 4); + U32 numTriangles = *(U32*)((int)data + 8); + + xClumpCollBSPTree* tree = (xClumpCollBSPTree*)RwMalloc(16); + if (numBranchNodes != 0) + { + tree->branchNodes = (xClumpCollBSPBranchNode*)((int)data + 12); + tree->triangles = (xClumpCollBSPTriangle*)(tree->branchNodes + numBranchNodes); + } + else + { + tree->branchNodes = NULL; + tree->triangles = (xClumpCollBSPTriangle*)((int)data + 12); + } + tree->numBranchNodes = numBranchNodes; + tree->numTriangles = numTriangles; + return tree; +} + +void xClumpColl_InstancePointers(xClumpCollBSPTree* tree, RpClump* clump) +{ + S32 i; + S32 numAtom; + TempAtomicList* atomicList; + TempAtomicList* iterList; + TempAtomicList* alist; + S32 vertIndex; + S32 numMeshes; + S32 meshIndex; + RpMesh* mesh; +} + +//WIP +xClumpCollBSPTree* xClumpColl_ForAllBoxLeafNodeIntersections(xClumpCollBSPTree* tree, RwBBox* box, + S32 (*callBack)(xClumpCollBSPTriangle*, + void*), + void* data) +{ + S32 nStack; + nodeInfo nodeStack[33]; + xClumpCollBSPBranchNode* branch; + + U32 uVar1; + int iVar2; + int iVar3 = 0; + U32 local_124 = 0; + U32 local_128 = 1 - ((-(int)tree->branchNodes | (int)tree->branchNodes) >> 31); + while (true) + { + while (true) + { + if (iVar3 < 0) + { + return tree; + } + if (local_128 == 1) + break; + branch = tree->branchNodes + local_124; + uVar1 = branch->leftInfo; + if ((float)branch->leftValue <= *(float*)((int)&(box->inf).x + (uVar1 & 0xc))) + { + local_128 = branch->rightInfo & 3; + local_124 = branch->rightInfo >> 0xc; + } + else + { + local_128 = uVar1 & 3; + local_124 = uVar1 >> 0xc; + if ((float)branch->rightValue <= *(float*)((int)&(box->sup).x + (uVar1 & 0xc))) + { + iVar3 = iVar3 + 1; + *(int*)&nodeStack[iVar3 * 2] = branch->rightInfo & 3; + *(int*)&nodeStack[iVar3 * 2 + 1] = branch->rightInfo >> 0xc; + } + } + } + iVar2 = ((*callBack)(tree->triangles + local_124, data)); + if (iVar2 == 0) + break; + *(U32*)&nodeStack[iVar3 * 2] = local_128; + iVar3--; + } + return 0; +} diff --git a/src/SB/Core/x/xClumpColl.h b/src/SB/Core/x/xClumpColl.h index 48f66f6..982d7be 100644 --- a/src/SB/Core/x/xClumpColl.h +++ b/src/SB/Core/x/xClumpColl.h @@ -2,7 +2,7 @@ #define XCLUMPCOLL_H #include -#include + #include #include @@ -20,30 +20,46 @@ struct xClumpCollBSPVertInfo U16 meshVertIndex; }; -struct _class_26 +struct xClumpCollBSPTriangle { union { xClumpCollBSPVertInfo i; - U32 rawIdx; RwV3d* p; - }; -}; - -struct xClumpCollBSPTriangle -{ - _class_26 v; + } v; U8 flags; - U8 detailed_info_cache_index; + U8 platData; U16 matIndex; }; struct xClumpCollBSPTree { - S32 numBranchNodes; + U32 numBranchNodes; xClumpCollBSPBranchNode* branchNodes; - S32 numTriangles; + U32 numTriangles; xClumpCollBSPTriangle* triangles; }; +struct nodeInfo +{ + U32 type; + U32 index; +}; +struct RwMeshCache +{ + U32 lengthOfMeshesArray; + RwResEntry* meshes[1]; +}; + +struct TempAtomicList +{ + RpAtomic* atomic; + RpGeometry* geom; + RpMeshHeader* meshHeader; + RwMeshCache* meshCache; +}; + +void xClumpColl_InstancePointers(xClumpCollBSPTree* tree, RpClump* clump); +xClumpCollBSPTree* xClumpColl_StaticBufferInit(void* data, U32 param_2); + #endif diff --git a/src/SB/Core/x/xCollide.cpp b/src/SB/Core/x/xCollide.cpp new file mode 100644 index 0000000..61690de --- /dev/null +++ b/src/SB/Core/x/xCollide.cpp @@ -0,0 +1,242 @@ +#include "xCollide.h" +#include "zSurface.h" +#include "iCollide.h" +#include "iMath3.h" + +#include + +// extern F32 lbl_803CCAA8; // 0.0 + +_xCollsIdx xCollideGetCollsIdx(const xCollis* coll, const xVec3* tohit, const xMat3x3* mat) +{ + if (tohit->y * tohit->y > tohit->x * tohit->x + tohit->z * tohit->z) + { + if (tohit->y < 0.0f) + { + if ((coll->flags & 0x20000) == 0) + { + if (coll->optr != NULL && coll->mptr->Surf != NULL ? + zSurfaceGetStandOn(coll->mptr->Surf) : + 1) + { + return k_XCOLLS_IDX_FLOOR; + } + } + } + else + { + return k_XCOLLS_IDX_CEIL; + } + } + F32 local_x = mat->right.x * tohit->x + mat->right.z * tohit->z; + F32 local_z = mat->at.x * tohit->x + mat->at.z * tohit->z; + if (local_x > 0.0f) + { + if (local_z > 0.0f) + { + if (local_x > local_z) + { + return k_XCOLLS_IDX_LEFT; + } + else + { + return k_XCOLLS_IDX_FRONT; + } + } + else + { + if (local_x > -local_z) + { + return k_XCOLLS_IDX_LEFT; + } + else + { + return k_XCOLLS_IDX_REAR; + } + } + } + else + { + if (local_z > 0.0f) + { + if (local_x < -local_z) + { + return k_XCOLLS_IDX_RIGHT; + } + else + { + return k_XCOLLS_IDX_FRONT; + } + } + else + { + if (local_x < local_z) + { + return k_XCOLLS_IDX_RIGHT; + } + else + { + return k_XCOLLS_IDX_REAR; + } + } + } +} + +void xCollideInit(xScene* sc) +{ + iCollideInit(sc); +} + +U32 xBoxHitsSphere(const xBox* a, const xSphere* b, xCollis* coll) +{ + U32 uVar1; + + xIsect isx; + + iBoxIsectSphere(a, b, &isx); + + if (!(isx.penned <= 0.0f)) + { + uVar1 = 0; + coll->flags &= 0xfffffffe; + } + else + { + if (isx.contained <= 0.0f) + { + coll->flags |= 0x10; + } + coll->dist = isx.dist; + if (coll->flags & 0x0400) + { + xVec3Copy(&coll->tohit, &isx.norm); + } + if ((coll->flags & 0x800) != 0) + { + if (isx.dist == 0.0f) + { + xVec3Copy(&coll->depen, &g_O3); + } + else + { + xVec3SMul(&coll->depen, &isx.norm, isx.penned / isx.dist); + } + } + if ((coll->flags & 0x1200) != 0) + { + xVec3Normalize(&coll->hdng, &isx.norm); + } + if ((coll->flags & 0x200) != 0) + { + xVec3Inv(&coll->norm, &coll->hdng); + } + uVar1 = 1; + coll->flags |= 1; + } + return uVar1; +} + +U32 xSphereHitsBox(const xSphere* a, const xBox* b, xCollis* coll) +{ + U32 uVar1; + + xIsect isx; + + iBoxIsectSphere(b, a, &isx); + + if (!(isx.penned <= 0.0f)) + { + uVar1 = 0; + coll->flags &= 0xfffffffe; + } + else + { + if (isx.contained <= 0.0f) + { + coll->flags |= 0x10; + } + coll->dist = isx.dist; + if (coll->flags & 0x0400) + { + xVec3Copy(&coll->tohit, &isx.norm); + } + if ((coll->flags & 0x800) != 0) + { + if (isx.dist == 0.0f) + { + xVec3Copy(&coll->depen, &g_O3); + } + else + { + xVec3SMul(&coll->depen, &isx.norm, isx.penned / isx.dist); + } + } + if ((coll->flags & 0x1200) != 0) + { + xVec3Normalize(&coll->hdng, &isx.norm); + } + if ((coll->flags & 0x200) != 0) + { + xVec3Inv(&coll->norm, &coll->hdng); + } + uVar1 = 1; + coll->flags |= 1; + } + return uVar1; +} + +U32 xSphereHitsSphere(const xSphere* a, const xSphere* b, xCollis* coll) +{ + U32 uVar1; + + xIsect isx; + + iSphereIsectSphere(b, a, &isx); + + if (!(isx.penned <= 0.0f)) + { + uVar1 = 0; + coll->flags &= 0xfffffffe; + } + else + { + if (isx.contained <= 0.0f) + { + coll->flags |= 0x10; + } + coll->dist = a->r + isx.penned; + if ((coll->flags & 0x1600) != 0) + { + if (isx.dist == 0.0f) + { + xVec3Copy(&coll->tohit, &g_O3); + } + else + { + xVec3SMul(&coll->tohit, &isx.norm, -coll->dist / isx.dist); + } + } + if ((coll->flags & 0x800) != 0) + { + if (isx.dist == 0.0f) + { + xVec3Copy(&coll->depen, &g_O3); + } + else + { + xVec3SMul(&coll->depen, &isx.norm, -isx.penned / isx.dist); + } + } + if ((coll->flags & 0x1200) != 0) + { + xVec3Normalize(&coll->hdng, &coll->tohit); + } + if ((coll->flags & 0x200) != 0) + { + xVec3Inv(&coll->norm, &coll->hdng); + } + uVar1 = 1; + coll->flags |= 1; + } + return uVar1; +} diff --git a/src/SB/Core/x/xCollide.h b/src/SB/Core/x/xCollide.h new file mode 100644 index 0000000..c42bc32 --- /dev/null +++ b/src/SB/Core/x/xCollide.h @@ -0,0 +1,138 @@ +#ifndef XCOLLIDE_H +#define XCOLLIDE_H + +#include "xEnv.h" +#include "xModel.h" +#include "xQuickCull.h" +#include "iMath3.h" + +struct xModelInstance; + +struct xCollis +{ + struct tri_data + { + U32 index; + F32 r; + F32 d; + + tri_data& operator=(const tri_data& o) + { + index = o.index; + r = o.r; + d = o.d; + return *this; + }; + }; + + U32 flags; + U32 oid; + void* optr; + xModelInstance* mptr; + F32 dist; // 0x10 + xVec3 norm; + xVec3 tohit; + xVec3 depen; + xVec3 hdng; + union + { + struct + { + F32 t; + F32 u; + F32 v; + } tuv; + tri_data tri; + }; +}; + +struct xParabola +{ + xVec3 initPos; + xVec3 initVel; + F32 gravity; + F32 minTime; + F32 maxTime; +}; + +// Size: 0x144 +struct xSweptSphere +{ + xVec3 start; + xVec3 end; + F32 radius; + F32 dist; + // Offset: 0x20 + xiMat4x3Union basis; + xiMat4x3Union invbasis; + // Offset: 0xa0 + xBox box; + // Offset: 0xb8 + xQCData qcd; + // Offset: 0xd8 + F32 boxsize; + F32 curdist; + // Offset: 0xe0 + xVec3 contact; + xVec3 polynorm; + U32 oid; + void* optr; + // Offset: 0x100 + xModelInstance* mptr; + S32 hitIt; + xVec3 worldPos; + xVec3 worldContact; + // Offset: 0x120 + xVec3 worldNormal; + // Offset: 0x12c + xVec3 worldTangent; + // Offset: 0x138 + xVec3 worldPolynorm; +}; + +enum _xCollsIdx +{ + k_XCOLLS_IDX_FLOOR, + k_XCOLLS_IDX_CEIL, + k_XCOLLS_IDX_FRONT, + k_XCOLLS_IDX_LEFT, + k_XCOLLS_IDX_REAR, + k_XCOLLS_IDX_RIGHT, + k_XCOLLS_IDX_COUNT +}; + +struct xScene; + +void xCollideInit(xScene* sc); +S32 xSweptSphereToBox(xSweptSphere* sws, xBox* box, xMat4x3* mat); +S32 xSweptSphereToModel(xSweptSphere* sws, RpAtomic* model, RwMatrix* mat); +S32 xSweptSphereToScene(xSweptSphere* sws, xScene* sc, xEnt* mover, U8 collType); +void xSweptSpherePrepare(xSweptSphere* sws, xVec3* start, xVec3* end, F32 radius); +void xSweptSphereGetResults(xSweptSphere* sws); +U32 xSphereHitsOBB_nu(const xSphere* s, const xBox* b, const xMat4x3* m, xCollis* coll); +U32 xSphereHitsSphere(const xSphere* a, const xSphere* b, xCollis* coll); +U32 xSphereHitsBox(const xSphere* a, const xBox* b, xCollis* coll); +U32 xBoxHitsSphere(const xBox* a, const xSphere* b, xCollis* coll); +U32 xBoxHitsObb(const xBox* a, const xBox* b, const xMat4x3* mat, xCollis* coll); +bool xSphereHitsOBB(const xSphere&, const xBox&, const xMat4x3&); +bool xSphereHitsSphere(const xVec3&, F32, const xVec3&, F32); +bool xSphereHitsVCylinder(const xVec3& sc, F32 sr, const xVec3& cc, F32 cr, F32 ch); +bool xSphereHitsVCircle(const xSphere& s, const xVec3& c, F32 r); +bool xSphereHitsVCircle(const xVec3& sc, F32 sr, const xVec3& cc, F32 cr); +U32 xSphereHitsModel(const xSphere* b, const xModelInstance* m, xCollis* coll); + +S32 xParabolaHitsEnv(xParabola* p, const xEnv* env, xCollis* colls); +void xParabolaEvalPos(const xParabola*, xVec3*, F32); +void xParabolaEvalVel(const xParabola*, xVec3*, F32); + +void xVec3AddScaled(xVec3*, const xVec3*, F32); +xVec3 xCollisTriHit(const xCollis::tri_data& tri, const xModelInstance& model); +bool xModelAnimCollDirty(const xModelInstance& cm); +void xModelAnimCollRefresh(const xModelInstance& cm); + +inline bool xSphereHitsVCircle(const xSphere& s, const xVec3& c, F32 r) +{ + return xSphereHitsVCircle(s.center, s.r, c, r); +} + +#endif diff --git a/src/SB/Core/x/xCollideFast.cpp b/src/SB/Core/x/xCollideFast.cpp new file mode 100644 index 0000000..32b6f97 --- /dev/null +++ b/src/SB/Core/x/xCollideFast.cpp @@ -0,0 +1,36 @@ +#include "xCollideFast.h" +#include "iCollideFast.h" +#include "xMath.h" + +#include + +void xCollideFastInit(xScene* sc) +{ + iCollideFastInit(sc); +} + +U32 xRayHitsSphereFast(const xRay3* r, const xSphere* s) +{ + xVec3 length; + xVec3Sub(&length, &r->origin, &s->center); + F32 dVar3 = xVec3Dot(&length, &length) - SQR(s->r); + if (dVar3 <= 0.0f) + { + return 1; + } + + if (r->flags & (1 << 11) && dVar3 > r->max_t * (2.0f * s->r + r->max_t)) + { + return 0; + } + + F32 dot = xVec3Dot(&length, &r->dir); + return (dot >= 0.0f) ? 0 : (SQR(dot) >= dVar3); +} + +U32 xRayHitsBoxFast(const xRay3* r, const xBox* b) +{ + xIsect isect; + iBoxIsectRay(b, r, &isect); + return isect.penned <= 0.0f || isect.contained <= 0.0f; +} diff --git a/src/SB/Core/x/xCollideFast.h b/src/SB/Core/x/xCollideFast.h new file mode 100644 index 0000000..46867a6 --- /dev/null +++ b/src/SB/Core/x/xCollideFast.h @@ -0,0 +1,12 @@ +#ifndef XCOLLIDEFAST_H +#define XCOLLIDEFAST_H + +#include "xMath3.h" +#include "xRay3.h" +#include "xScene.h" + +void xCollideFastInit(xScene* sc); +U32 xRayHitsSphereFast(const xRay3* r, const xSphere* s); +U32 xRayHitsBoxFast(const xRay3* r, const xBox* b); + +#endif diff --git a/src/SB/Core/x/xCollis.h b/src/SB/Core/x/xCollis.h deleted file mode 100644 index de753d0..0000000 --- a/src/SB/Core/x/xCollis.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef XCOLLIS_H -#define XCOLLIS_H -#include "xModel.h" - -struct tri_data_0 -{ - U32 index; - F32 r; - F32 d; -}; - -struct _class_8 -{ - F32 t; - F32 u; - F32 v; -}; - -struct xCollis -{ - U32 flags; - U32 oid; - void* optr; - xModelInstance* mptr; - F32 dist; - F32 test_dist; - xVec3 norm; - xVec3 tohit; - xVec3 depen; - xVec3 hdng; - union - { - _class_8 tuv; - tri_data_0 tri; - }; -}; - -struct anim_coll_data -{ -}; - -#endif diff --git a/src/SB/Core/x/xColor.cpp b/src/SB/Core/x/xColor.cpp new file mode 100644 index 0000000..42f72b5 --- /dev/null +++ b/src/SB/Core/x/xColor.cpp @@ -0,0 +1,16 @@ +#include "xColor.h" + +const iColor_tag g_RED = { 255, 0, 0, 255 }; +const iColor_tag g_GREEN = { 0, 255, 0, 255 }; +const iColor_tag g_BLUE = { 0, 0, 255, 255 }; +const iColor_tag g_CYAN = { 0, 255, 255, 255 }; +const iColor_tag g_YELLOW = { 255, 255, 0, 255 }; +const iColor_tag g_WHITE = { 255, 255, 255, 255 }; +const iColor_tag g_GRAY50 = { 128, 128, 128, 255 }; +const iColor_tag g_NEON_RED = { 255, 32, 0, 255 }; +const iColor_tag g_NEON_GREEN = { 32, 255, 0, 255 }; +const iColor_tag g_NEON_BLUE = { 32, 32, 255, 255 }; +const iColor_tag g_PIMP_GOLD = { 215, 220, 19, 255 }; +const iColor_tag g_ORANGE = { 255, 165, 0, 255 }; +const iColor_tag g_LAVENDER = { 200, 105, 229, 255 }; +const iColor_tag g_PINK = { 255, 128, 255, 255 }; diff --git a/src/SB/Core/x/xColor.h b/src/SB/Core/x/xColor.h new file mode 100644 index 0000000..fcd3ef1 --- /dev/null +++ b/src/SB/Core/x/xColor.h @@ -0,0 +1,23 @@ +#ifndef XCOLOR_H +#define XCOLOR_H + +#include "iColor.h" + +extern const iColor_tag g_RED; +extern const iColor_tag g_GREEN; +extern const iColor_tag g_BLUE; +extern const iColor_tag g_CYAN; +extern const iColor_tag g_YELLOW; +extern const iColor_tag g_WHITE; +extern const iColor_tag g_GRAY50; +extern const iColor_tag g_NEON_RED; +extern const iColor_tag g_NEON_GREEN; +extern const iColor_tag g_NEON_BLUE; +extern const iColor_tag g_PIMP_GOLD; +extern const iColor_tag g_ORANGE; +extern const iColor_tag g_LAVENDER; +extern const iColor_tag g_PINK; + +iColor_tag xColorFromRGBA(U8 r, U8 g, U8 b, U8 a); + +#endif diff --git a/src/SB/Core/x/xCounter.cpp b/src/SB/Core/x/xCounter.cpp new file mode 100644 index 0000000..69b7997 --- /dev/null +++ b/src/SB/Core/x/xCounter.cpp @@ -0,0 +1,160 @@ +#include "xCounter.h" + +#include "xDebug.h" +#include "xEvent.h" + +namespace +{ + void add_tweaks(_xCounter&) + { + return; + } +} // namespace + +void xCounterInit() +{ + xDebugRemoveTweak("Widgets|Counters"); +} + +void xCounterInit(void* b, void* asset) +{ + xCounterInit((xBase*)b, (xCounterAsset*)asset); +} + +void xCounterInit(xBase* b, xCounterAsset* asset) +{ + _xCounter* t = (_xCounter*)b; + + xBaseInit(t, asset); + + t->eventFunc = xCounterEventCB; + t->asset = asset; + + if (t->linkCount) + { + t->link = (xLinkAsset*)(t->asset + 1); + } + else + { + t->link = 0; + } + + t->state = 0; + t->count = asset->count; + t->counterFlags = 0; + + add_tweaks(*t); +} + +void xCounterReset(xBase* b) +{ + _xCounter* t = (_xCounter*)b; + + xBaseInit(t, t->asset); + + if (t->linkCount) + { + t->link = (xLinkAsset*)(t->asset + 1); + } + else + { + t->link = 0; + } + + t->count = t->asset->count; + t->state = 0; +} + +void xCounterSave(_xCounter* ent, xSerial* s) +{ + xBaseSave(ent, s); + + s->Write(ent->state); + s->Write(ent->count); +} + +void xCounterLoad(_xCounter* ent, xSerial* s) +{ + xBaseLoad(ent, s); + + s->Read(&ent->state); + s->Read(&ent->count); +} + +int xCounterEventCB(xBase*, xBase* to, U32 toEvent, const F32*, xBase*) +{ + _xCounter* t = (_xCounter*)to; + + switch (toEvent) + { + case eEventDecrement: + { + if (t->state != 1 && (!(t->counterFlags & 0x1) || t->count != 2)) + { + t->count--; + + if (t->count == 0) + { + zEntEvent(t, t, eEventExpired); + } + else if (t->count > 0 && t->count <= 20) + { + zEntEvent(t, t, t->count + (eEventCount1 - 1)); + } + } + break; + } + case eEventIncrement: + { + if (t->state != 1) + { + t->count++; + + if (t->count == 0) + { + zEntEvent(t, t, eEventExpired); + } + else if (t->count > 0 && t->count <= 20) + { + zEntEvent(t, t, t->count + (eEventCount1 - 1)); + } + } + break; + } + case eEventReset: + { + t->state = 0; + t->count = t->asset->count; + break; + } + case eEventExpired: + { + if (!(t->counterFlags & 0x1) || t->count != 2) + { + t->count = 0; + t->state = 1; + } + break; + } + default: + { + if (t->state != 1 && toEvent >= eEventCount1 && toEvent <= eEventCount20) + { + S16 newCount = toEvent - (eEventCount1 - 1); + + if (!(t->counterFlags & 0x1) || t->count != 2) + { + t->count = newCount; + } + } + } + } + + return 1; +} + +// TODO: move to xDebug.cpp +inline void xDebugRemoveTweak(const char*) +{ + return; +} diff --git a/src/SB/Core/x/xCounter.h b/src/SB/Core/x/xCounter.h new file mode 100644 index 0000000..9cf2764 --- /dev/null +++ b/src/SB/Core/x/xCounter.h @@ -0,0 +1,29 @@ +#ifndef XCOUNTER_H +#define XCOUNTER_H + +#include "xBase.h" + +struct xCounterAsset : xBaseAsset +{ + S16 count; +}; + +struct _xCounter : xBase +{ + xCounterAsset* asset; + S16 count; + U8 state; + U8 counterFlags; +}; + +#define XCOUNTER_ISSPATULA 0x1 + +void xCounterInit(); +void xCounterInit(void* b, void* asset); +void xCounterInit(xBase* b, xCounterAsset* asset); +void xCounterReset(xBase* b); +void xCounterSave(_xCounter* ent, xSerial* s); +void xCounterLoad(_xCounter* ent, xSerial* s); +int xCounterEventCB(xBase*, xBase* to, U32 toEvent, const F32*, xBase*); + +#endif diff --git a/src/SB/Core/x/xCurveAsset.cpp b/src/SB/Core/x/xCurveAsset.cpp new file mode 100644 index 0000000..d7df991 --- /dev/null +++ b/src/SB/Core/x/xCurveAsset.cpp @@ -0,0 +1,38 @@ +#include "xCurveAsset.h" + +#include "xMath.h" + +#include + +F32 xCurveAssetEvaluate(const xCurveAsset* curve_asset, F32 t) +{ + F32 max_t = curve_asset->delta * (curve_asset->numPoints - 1); + + if (curve_asset->clamp == xCC_CONSTANT) + { + F32 curve_length = MIN(t, max_t); + + t = MAX(curve_length, 0.0f); + } + else + { + S32 curve_shift = t / max_t; + + if (t < 0.0f) + { + curve_shift--; + } + + t -= curve_shift * max_t; + + if (curve_asset->clamp == xCC_OSCILLATE && abs(curve_shift % 2) == 1) + { + t = max_t - t; + } + } + + U32 last_point = t / curve_asset->delta; + F32 u = (t - (last_point * curve_asset->delta)) / curve_asset->delta; + + return (1.0f - u) * curve_asset->points[last_point] + u * curve_asset->points[last_point + 1]; +} diff --git a/src/SB/Core/x/xCurveAsset.h b/src/SB/Core/x/xCurveAsset.h new file mode 100644 index 0000000..045ae42 --- /dev/null +++ b/src/SB/Core/x/xCurveAsset.h @@ -0,0 +1,29 @@ +#ifndef XCURVEASSET_H +#define XCURVEASSET_H + +#include + +enum xCurveType +{ + xCVT_BAKED +}; + +enum xCurveClamp +{ + xCC_CONSTANT, + xCC_CYCLE, + xCC_OSCILLATE +}; + +struct xCurveAsset +{ + xCurveType type; + xCurveClamp clamp; + F32 delta; + S32 numPoints; + F32* points; +}; + +F32 xCurveAssetEvaluate(const xCurveAsset* curve_asset, F32 t); + +#endif diff --git a/src/SB/Core/x/xCutscene.cpp b/src/SB/Core/x/xCutscene.cpp new file mode 100644 index 0000000..02bd422 --- /dev/null +++ b/src/SB/Core/x/xCutscene.cpp @@ -0,0 +1,185 @@ +#include "xCutscene.h" +#include "xSnd.h" +#include "xAnim.h" +#include "xDebug.h" +#include "xModelBucket.h" +#include "xSnd.h" + +#include "iCutscene.h" +#include "iModel.h" + +#include +#include + +extern xCutscene sActiveCutscene; +extern xCutsceneInfo* sCutTocInfo; +extern U32 sCutTocCount; +extern void* RwEngineInstance; +extern xModelInstance sCutsceneFakeModel[8]; + +extern F32 _672; // 1.0 + +extern F32 lbl_803CCB3C; // 0.0 +extern F32 lbl_803CCB40; // 0.033333335 + +// Non-matching: scheduling +void xCutscene_Init(void* toc) +{ + memset(&sActiveCutscene, 0, 0x198); + sCutTocCount = 0; + sCutTocInfo = 0; + if (toc != NULL) + { + sCutTocCount = *(S32*)toc; + sCutTocInfo = (xCutsceneInfo*)((S32*)toc + 1); + } + for (int i = 0; i < 8; i++) + { + *(volatile int*)&sCutsceneFakeModel[i].Mat = + (volatile int)xMemAlloc(gActiveHeap, sizeof(RwMatrixTag) * 65, 0); + *(volatile int*)&sCutsceneFakeModel[i].Bucket = + (volatile int)xMemAlloc(gActiveHeap, sizeof(xModelBucket*) * 2, 0); + *(volatile int*)sCutsceneFakeModel[i].Bucket = + (volatile int)xMemAlloc(gActiveHeap, sizeof(xModelBucket), 0); + *(volatile int*)&sCutsceneFakeModel[i].Bucket[1] = + (volatile int)*sCutsceneFakeModel[i].Bucket; + *(volatile int*)&sCutsceneFakeModel[i].PipeFlags = (volatile int)0x6530; + *(volatile float*)&sCutsceneFakeModel[i].RedMultiplier = (volatile float)1.0f; + *(volatile float*)&sCutsceneFakeModel[i].GreenMultiplier = (volatile float)1.0f; + *(volatile float*)&sCutsceneFakeModel[i].BlueMultiplier = (volatile float)1.0f; + *(volatile float*)&sCutsceneFakeModel[i].Alpha = (volatile float)1.0f; + } +} + +// Damn RwEngineInstance ruining this (as well as the members being accessed incorrectly by Ghidra) +xCutscene* xCutscene_Create(U32 id) +{ + xCutscene* csn; + xCutsceneInfo* cnfo; + U32 maxload; + + xSndPauseAll(1, 1); + memset(&sActiveCutscene, 0, 0x198); + sActiveCutscene.PlaybackSpeed = _672; + + for (int i = 0; i < sCutTocCount; i++) + { + cnfo = &sCutTocInfo[i]; + if (sCutTocInfo[i].AssetID == id) + { + break; + } + } + maxload = cnfo->MaxBufEven + cnfo->MaxBufOdd; + if (cnfo->MaxModel > maxload) + { + maxload = cnfo->MaxModel; + } + // sActiveCutscene.RawBuf = RwFree(maxload + 0x3c); + sActiveCutscene.AlignBuf = sActiveCutscene.RawBuf; + while ((int)sActiveCutscene.AlignBuf & 0x3f != 0) + { + sActiveCutscene.AlignBuf = (void*)((int)sActiveCutscene.AlignBuf + 4); + } + sActiveCutscene.TimeChunkOffs = (U32*)(cnfo[1].SoundLeft + cnfo->NumData * 0x10 + -0x30); + sActiveCutscene.Info = cnfo; + sActiveCutscene.Data = (xCutsceneData*)(cnfo + 1); + sActiveCutscene.Visibility = sActiveCutscene.TimeChunkOffs + cnfo->NumTime + 1; + sActiveCutscene.BreakList = + (xCutsceneBreak*)(sActiveCutscene.TimeChunkOffs + cnfo->NumTime + 1 + cnfo->VisSize); + sActiveCutscene.Play = (xCutsceneTime*)sActiveCutscene.AlignBuf; + sActiveCutscene.Stream = (xCutsceneTime*)((int)sActiveCutscene.AlignBuf + cnfo->MaxBufEven); + return &sActiveCutscene; +} + +S32 xCutscene_Destroy(xCutscene* csn) +{ + csn->Ready = 0; + xSndSetExternalCallback(0); + if (csn->SndStarted != 0) + { + xSndStop(csn->SndHandle[0]); + if (csn->SndNumChannel == 2) + { + xSndStop(csn->SndHandle[1]); + } + xSndUpdate(); + csn->SndStarted = 0; + } + xSndPauseAll(0, 0); + xSndUpdate(); + if (csn->Opened != 0) + { + iCSFileClose(csn); + } + for (int i = 0; i < csn->Info->NumData; i++) + { + // if ((((U32*)csn->Data->DataType + i) & 0x80000000) && + // ((RpAtomic*)((U32*)((U32*)csn->Data->DataType + i) + 3) != NULL)) + // { + // if ((((U32*)csn->Data->DataType + i) & 0xfffffff) == 6) + // { + // RwFree(); + // } + // else + // { + // iModelUnload((RpAtomic*)((U32*)((U32*)csn->Data->DataType + i) + 3)); + // } + // (U32)((U32*)csn->Data->DataType + i) = (((U32*)csn->Data->DataType + i) & 0xfffffff); + // } + } + RwFree(csn->RawBuf); + memset(csn, 0, sizeof(xCutscene)); + return 1; +} + +S32 xCutscene_LoadStart(xCutscene* csn) +{ + U32 cnt; + + cnt = iCSFileOpen(csn); + + if (cnt <= 0) + { + return 0; + } + + csn->Opened = 1; + return 1; +} + +F32 xCutsceneConvertBreak(float param_1, xCutsceneBreak* param_2, U32 param_3, int param_4) +{ + int i = 0; + if (param_3 == 0) + { + return param_1; + } + while (true) + { + if (param_4 != param_2[i].Index) + { + break; + } + if (param_2[i].Time - param_1 <= lbl_803CCB3C) + { + break; + } + if (lbl_803CCB40 <= param_2[i].Time - param_1) + { + break; + } + i++; + param_3--; + if (param_3 == 0) + { + return param_1; + } + } + return param_2[i].Time - lbl_803CCB40; +} + +xCutscene* xCutscene_CurrentCutscene() +{ + return &sActiveCutscene; +} diff --git a/src/SB/Core/x/xCutscene.h b/src/SB/Core/x/xCutscene.h new file mode 100644 index 0000000..3dac4c6 --- /dev/null +++ b/src/SB/Core/x/xCutscene.h @@ -0,0 +1,108 @@ +#ifndef XCUTSCENE_H +#define XCUTSCENE_H + +#include "xFile.h" + +struct xCutsceneInfo +{ + U32 Magic; + U32 AssetID; + U32 NumData; + U32 NumTime; + U32 MaxModel; + U32 MaxBufEven; + U32 MaxBufOdd; + U32 HeaderSize; + U32 VisCount; + U32 VisSize; + U32 BreakCount; + U32 pad; + char SoundLeft[16]; + char SoundRight[16]; +}; + +struct xCutsceneData +{ + U32 DataType; + U32 AssetID; + U32 ChunkSize; + union + { + U32 FileOffset; + void* DataPtr; + }; +}; + +#define XCUTSCENEDATA_TYPE_SOUND 5 +#define XCUTSCENEDATA_TYPE_6 6 + +struct xCutsceneBreak +{ + F32 Time; + S32 Index; +}; + +struct xCutsceneTime +{ + F32 StartTime; + F32 EndTime; + U32 NumData; + U32 ChunkIndex; +}; + +struct XCSNNosey +{ + void* userdata; + S32 flg_nosey; +}; + +struct xCutscene +{ + xCutsceneInfo* Info; + xCutsceneData* Data; + U32* TimeChunkOffs; + U32* Visibility; + xCutsceneBreak* BreakList; + xCutsceneTime* Play; + xCutsceneTime* Stream; + U32 Waiting; + U32 BadReadPause; + F32 BadReadSpeed; + void* RawBuf; + void* AlignBuf; + F32 Time; + F32 CamTime; + U32 PlayIndex; + U32 Ready; + S32 DataLoading; + U32 GotData; + U32 ShutDownWait; + F32 PlaybackSpeed; + U32 Opened; + tag_xFile File; + S32 AsyncID; + void* MemBuf; + void* MemCurr; + U32 SndStarted; + U32 SndNumChannel; + U32 SndChannelReq[2]; + U32 SndAssetID[2]; + U32 SndHandle[2]; + XCSNNosey* cb_nosey; + void NoseySet(XCSNNosey* nosey); +}; + +struct xEnt; + +extern U32 gFrameCount; + +void xCutscene_Init(void* toc); +xCutscene* xCutscene_CurrentCutscene(); +void xCutscene_Render(xCutscene* csn, xEnt**, S32*, F32*); +U32 iCSFileOpen(xCutscene* csn); +xCutscene* xCutscene_Create(U32 id); +S32 xCutscene_Destroy(xCutscene* csn); +S32 xCutscene_LoadStart(xCutscene* csn); +S32 xCutscene_Update(xCutscene* csn, F32 dt); + +#endif diff --git a/src/SB/Core/x/xCutsceneMgr.h b/src/SB/Core/x/xCutsceneMgr.h new file mode 100644 index 0000000..7b287f8 --- /dev/null +++ b/src/SB/Core/x/xCutsceneMgr.h @@ -0,0 +1,40 @@ +#ifndef XCUTSCENEMGR_H +#define XCUTSCENEMGR_H + +#include "xBase.h" +#include "xCutscene.h" + +struct xCutsceneMgrAsset : xBaseAsset +{ + U32 cutsceneAssetID; + U32 flags; + F32 interpSpeed; + F32 startTime[15]; + F32 endTime[15]; + U32 emitID[15]; +}; + +struct xCutsceneZbuffer +{ + F32 start; + F32 end; + F32 nearPlane; + F32 farPlane; +}; + +struct xCutsceneZbufferHack +{ + char* name; + xCutsceneZbuffer times[4]; +}; + +struct xCutsceneMgr : xBase +{ + xCutsceneMgrAsset* tasset; + xCutscene* csn; // 0x14 + U32 stop; // 0x18 + xCutsceneZbufferHack* zhack; + F32 oldfov; +}; + +#endif diff --git a/src/SB/Core/x/xDebug.cpp b/src/SB/Core/x/xDebug.cpp new file mode 100644 index 0000000..1d0a099 --- /dev/null +++ b/src/SB/Core/x/xDebug.cpp @@ -0,0 +1,56 @@ +#include "xDebug.h" +#include "xFont.h" + +#include "iColor.h" + +#include + +U32 gFrameCount; + +// Remaining weak definitions will match once referenced e.g. iColor_tag::operator= + +void xprintf(const char* msg, ...) +{ + // Redacted. :} +} + +S32 xDebugModeAdd(const char* mode, void(*debugFunc)()) +{ + // Redacted. :} + return -1; +} + +void xDebugInit() +{ + // Redacted. :} +} + +void xDebugUpdate() +{ + // Redacted. :} +} + +void xDebugExit() +{ + // Redacted. :} +} + +void xDebugTimestampScreen() +{ + // Redacted. :} +} + +void xtextbox::render(bool cache) const +{ + render(temp_layout(cache), 0, -1); +} + +F32 NSCREENY(F32 scale) +{ + return (1.0f / 480) * scale; +} + +F32 NSCREENX(F32 scale) +{ + return (1.0f / 640) * scale; +} \ No newline at end of file diff --git a/src/SB/Core/x/xDebug.h b/src/SB/Core/x/xDebug.h new file mode 100644 index 0000000..d9ca11d --- /dev/null +++ b/src/SB/Core/x/xDebug.h @@ -0,0 +1,105 @@ +#ifndef XDEBUG_H +#define XDEBUG_H + +#include "xFont.h" + +#include + +extern U32 gFrameCount; + +struct uint_data +{ + U32 value_def; + U32 value_min; + U32 value_max; +}; + +struct float_data +{ + F32 value_def; + F32 value_min; + F32 value_max; +}; + +struct bool_data +{ + U8 value_def; +}; + +struct select_data +{ + U32 value_def; + U32 labels_size; + char** labels; + void* values; +}; + +struct flag_data +{ + U32 value_def; + U32 mask; +}; + +struct raw_data +{ + U8 pad[16]; +}; + +struct int_data +{ + S32 value_def; + S32 value_min; + S32 value_max; +}; + +struct tweak_callback; +struct tweak_info +{ + substr name; + void* value; + tweak_callback* cb; + void* context; + U8 type; + U8 value_size; + U16 flags; + union + { + int_data int_context; + uint_data uint_context; + float_data float_context; + bool_data bool_context; + select_data select_context; + flag_data flag_context; + raw_data all_context; + }; +}; + +struct tweak_callback +{ + void (*on_change)(tweak_info&); + void (*on_select)(tweak_info&); + void (*on_unselect)(tweak_info&); + void (*on_start_edit)(tweak_info&); + void (*on_stop_edit)(tweak_info&); + void (*on_expand)(tweak_info&); + void (*on_collapse)(tweak_info&); + void (*on_update)(tweak_info&); + void (*convert_mem_to_tweak)(tweak_info&, void*); + void (*convert_tweak_to_mem)(tweak_info&, void*); +}; + +void xprintf(const char* msg, ...); +S32 xDebugModeAdd(char* mode, void(*debugFunc)); +void xDebugInit(); +void xDebugUpdate(); +void xDebugExit(); +void xDebugTimestampScreen(); + +void xDebugAddTweak(const char*, F32*, F32, F32, const tweak_callback*, void*, U32); +void xDebugRemoveTweak(const char*); +void xDebugUpdate(); + +F32 NSCREENY(F32 scale); +F32 NSCREENX(F32 scale); + +#endif diff --git a/src/SB/Core/x/xDecal.cpp b/src/SB/Core/x/xDecal.cpp new file mode 100644 index 0000000..b459468 --- /dev/null +++ b/src/SB/Core/x/xDecal.cpp @@ -0,0 +1,11 @@ +#include "xDecal.h" + +#include + +//Doesn't OK if you use it from header, so assuming it's global. +extern U32 active_emitters_size; + +void xDecalInit() +{ + active_emitters_size = 0; +} diff --git a/src/SB/Core/x/xDecal.h b/src/SB/Core/x/xDecal.h new file mode 100644 index 0000000..958d5c3 --- /dev/null +++ b/src/SB/Core/x/xDecal.h @@ -0,0 +1,84 @@ +#ifndef XDECAL_H +#define XDECAL_H + +#include "xMath2.h" +#include "xMath3.h" +#include "containers.h" +#include "iColor.h" + +#include +#include + +struct xDecalEmitter +{ + enum texture_mode + { + TM_DEFAULT, + TM_RANDOM, + TM_CYCLE, + MAX_TM, + FORCE_INT_TM = 0xffffffff + }; + + struct config + { + U32 flags; + F32 life_time; + U32 blend_src; + U32 blend_dst; + struct + { + xVec2 uv[2]; + U8 rows; + U8 cols; + texture_mode mode; + } texture; + }; + + struct unit_data + { + U8 flags; + U8 curve_index; + U8 u; + U8 v; + F32 frac; + F32 age; + F32 cull_size; + xMat4x3 mat; + }; + + struct curve_node + { + F32 time; + iColor_tag color; + F32 scale; + }; + + config cfg; + struct + { + RwTexture* asset; + U32 units; + xVec2 size; + xVec2 isize; + S32 prev; + } texture; + static_queue units; + curve_node* curve; + U32 curve_size; + U32 curve_index; + F32 ilife; + + void set_curve(const curve_node* curve, size_t size); + void refresh_config(); + void set_texture(const char* name); + void set_default_config(); + void init(S32 max_size, const char*); +}; + +void xDecalInit(); +void xDecalUpdate(F32 dt); +void xDecalDestroy(); +void xDecalRender(); + +#endif diff --git a/src/SB/Core/x/xDraw.h b/src/SB/Core/x/xDraw.h new file mode 100644 index 0000000..6e91c87 --- /dev/null +++ b/src/SB/Core/x/xDraw.h @@ -0,0 +1,12 @@ +#ifndef XDRAW_H +#define XDRAW_H + +#include "iColor.h" +#include "xMath3.h" + +void xDrawSetColor(iColor_tag); +void xDrawSphere2(const xSphere*, U32); +void xDrawOBB(const xBox*, const xMat4x3*); +void xDrawBox(const xBox*); + +#endif diff --git a/src/SB/Core/x/xDynAsset.h b/src/SB/Core/x/xDynAsset.h new file mode 100644 index 0000000..2aae649 --- /dev/null +++ b/src/SB/Core/x/xDynAsset.h @@ -0,0 +1,13 @@ +#ifndef XDYNASSET_H +#define XDYNASSET_H + +#include "xBase.h" + +struct xDynAsset : xBaseAsset +{ + U32 type; + U16 version; + U16 handle; +}; + +#endif diff --git a/src/SB/Core/x/xEnt.cpp b/src/SB/Core/x/xEnt.cpp new file mode 100644 index 0000000..903687a --- /dev/null +++ b/src/SB/Core/x/xEnt.cpp @@ -0,0 +1,1979 @@ +#include "xEnt.h" + +#include "xEvent.h" +#include "xString.h" +#include "xGroup.h" +#include "xstransvc.h" +#include "xFX.h" +#include "xShadow.h" +#include "xMathInlines.h" +#include "xMath.h" + +#include "zBase.h" +#include "zPlatform.h" +#include "zEntDestructObj.h" +#include "zCollGeom.h" +#include "zSurface.h" +#include "zLight.h" +#include "zGrid.h" + +#include "iMath3.h" +#include "iCollide.h" +#include "iModel.h" +#include "iMath.h" + +#include + +static F32 nsn_angle = DEG2RAD(30); +static F32 sEntityTimePassed; +static xBox all_ents_box; +static S32 all_ents_box_init; + +namespace +{ + namespace anim_coll + { + void reset(xEnt& ent) + { + if (!ent.anim_coll) + { + ent.anim_coll = (xEnt::anim_coll_data*)xMemAllocSize(sizeof(xEnt::anim_coll_data)); + ent.anim_coll->flags = 0; + ent.anim_coll->verts = NULL; + } + + xModelInstance& model = *ent.model; + xMat4x3& mat = *(xMat4x3*)model.Mat; + xEnt::anim_coll_data& ac = *ent.anim_coll; + + if (!(ac.flags & 0x8)) + { + switch (model.BoneCount) + { + case 1: + { + ac.flags |= 0x1; + ac.old_mat = mat; + ac.new_mat = g_I3; + break; + } + case 0: + { + break; + } + default: + { + ac.flags |= 0x2; + ac.old_mat = mat; + ac.new_mat = g_I3; + + xModelAnimCollStart(model); + + xBox& box = ent.bound.box.box; + xVec3 size = box.upper - box.lower; + F32 max_size = size.x; + + if (max_size < size.y) + { + max_size = size.y; + } + + if (max_size < size.z) + { + max_size = size.z; + } + + max_size += 1.0f; + + box.upper += max_size; + box.lower -= max_size; + + model.Data->boundingSphere.radius *= 3.0f; + } + } + } + } + + void refresh(xEnt& ent) + { + xEnt::anim_coll_data& ac = *ent.anim_coll; + xMat4x3& bone_mat = *(xMat4x3*)(ent.model->Mat + 1); + + xMat4x3Mul((xMat4x3*)ent.model->Mat, &bone_mat, &ac.old_mat); + + ac.new_mat = bone_mat; + bone_mat = g_I3; + } + + void pre_move(xEnt& ent); + void post_move(xEnt& ent); + } // namespace anim_coll +} // namespace + +void xEntSetTimePassed(F32 sec) +{ + sEntityTimePassed = sec; +} + +void xEntSceneInit() +{ + all_ents_box_init = 1; +} + +void xEntSceneExit() +{ +} + +void xEntAddHittableFlag(xEnt* ent) +{ + if (ent->baseType == eBaseTypeNPC || ent->baseType == eBaseTypeDestructObj || + ent->baseType == eBaseTypeButton || ent->baseType == eBaseTypeBoulder || + (ent->baseType == eBaseTypePlatform && ent->subType == ZPLATFORM_SUBTYPE_PADDLE)) + { + ent->moreFlags |= 0x10; + } + else + { + for (U32 i = 0; i < ent->linkCount; i++) + { + if (ent->link[i].srcEvent == eEventHit || ent->link[i].srcEvent == eEventHit_Cruise || + ent->link[i].srcEvent == eEventHit_Melee || + ent->link[i].srcEvent == eEventHit_BubbleBounce || + ent->link[i].srcEvent == eEventHit_BubbleBash || + ent->link[i].srcEvent == eEventHit_BubbleBowl || + ent->link[i].srcEvent == eEventHit_PatrickSlam || + ent->link[i].srcEvent == eEventHit_Throw || + ent->link[i].srcEvent == eEventHit_PaddleLeft || + ent->link[i].srcEvent == eEventHit_PaddleRight) + { + ent->moreFlags |= 0x10; + break; + } + } + } +} + +static const char* __deadstripped() +{ + return ""; +} + +static void hack_receive_shadow(xEnt* ent) +{ + static U32 receive_models[15] = { + xStrHash("db03_path_a"), xStrHash("db03_path_b"), xStrHash("db03_path_c"), + xStrHash("db03_path_d"), xStrHash("db03_path_e"), xStrHash("db03_path_f"), + xStrHash("db03_path_g"), xStrHash("db03_path_h"), xStrHash("db03_path_i"), + xStrHash("db03_path_j"), xStrHash("db03_path_k"), xStrHash("db03_path_l"), + xStrHash("db03_path_m"), // No db03_path_n, odd + xStrHash("db03_path_o"), xStrHash("db03_path_p"), + }; + + U32* end = receive_models + sizeof(receive_models) / sizeof(U32); + U32* cur = receive_models; + + while (cur != end) + { + if (ent->asset->modelInfoID == *cur) + { + ent->baseFlags |= 0x10; + ent->asset->baseFlags |= 0x10; + break; + } + + cur++; + } +} + +static const char* __deadstripped2() +{ + return "%s.DFF\0" + "%s.SKA\0" + "ent-table\0" + "idle\0" + "anim-file\0" + "anim-table"; +} + +static void xEntAddShadowRecFlag(xEnt* ent) +{ + switch (ent->baseType - 6) + { + case eBaseTypeUnknown: + case eBaseTypeEnv: + case eBaseTypePendulum: + case eBaseTypeVFX: + case eBaseTypeLight: + case eBaseTypeEGenerator: + { + if (ent->model->PipeFlags & 0x0000ff00) + { + ent->baseFlags &= 0xffef; + } + break; + } + case eBaseTypeTrigger: + case eBaseTypeVillain: + case eBaseTypePlayer: + case eBaseTypePickup: + case eBaseTypePlatform: + case eBaseTypeCamera: + case eBaseTypeDoor: + case eBaseTypeSavePoint: + case eBaseTypeItem: + case eBaseTypeStatic: + case eBaseTypeDynamic: + case eBaseTypeMovePoint: + case eBaseTypeTimer: + case eBaseTypeBubble: + case eBaseTypePortal: + case eBaseTypeGroup: + case eBaseTypeSFX: + case eBaseTypeFFX: + case eBaseTypeCounter: + case eBaseTypeHangable: + case eBaseTypeButton: + case eBaseTypeProjectile: + case eBaseTypeSurface: + case eBaseTypeDestructObj: + case eBaseTypeGust: + case eBaseTypeVolume: + case eBaseTypeDispatcher: + case eBaseTypeCond: + case eBaseTypeUI: + case eBaseTypeUIFont: + case eBaseTypeProjectileType: + case eBaseTypeLobMaster: + case eBaseTypeFog: + case eBaseTypeParticleEmitter: + case eBaseTypeParticleSystem: + case eBaseTypeCutsceneMgr: + default: + { + ent->baseFlags &= 0xffef; + break; + } + } + + hack_receive_shadow(ent); +} + +void xEntInit(xEnt* ent, xEntAsset* asset) +{ + xBaseInit(ent, asset); + + // non-matching: instruction order + + ent->asset = asset; + ent->update = xEntUpdate; + ent->bupdate = xEntDefaultBoundUpdate; + ent->render = xEntRender; + ent->move = NULL; + ent->transl = xEntDefaultTranslate; + ent->flags = asset->flags; + ent->miscflags = 0; + ent->moreFlags = asset->moreFlags; + ent->subType = asset->subtype; + ent->pflags = asset->pflags; + ent->ffx = NULL; + ent->num_ffx = 0; + ent->driver = NULL; + ent->model = NULL; + ent->collModel = NULL; + ent->camcollModel = NULL; + ent->frame = NULL; + ent->collis = NULL; + ent->lightKit = NULL; + ent->simpShadow = NULL; + ent->entShadow = NULL; + ent->baseFlags |= 0x20; + + xGridBoundInit(&ent->gridb, ent); + + ent->anim_coll = NULL; + + if (all_ents_box_init) + { + iBoxInitBoundVec(&all_ents_box, &asset->pos); + all_ents_box_init = 0; + } + else + { + iBoxBoundVec(&all_ents_box, &all_ents_box, &asset->pos); + } +} + +void xEntInitForType(xEnt* ent) +{ + ent->update = xEntUpdate; + ent->render = xEntRender; + + if (ent->collType == XENT_COLLTYPE_TRIG) + { + ent->pflags &= ~0x3; + ent->chkby = XENT_COLLTYPE_NPC | XENT_COLLTYPE_PLYR; + ent->penby = 0; + } + else if (ent->collType == XENT_COLLTYPE_STAT) + { + ent->pflags &= ~0x3; + ent->chkby = XENT_COLLTYPE_NPC | XENT_COLLTYPE_PLYR; + ent->penby = XENT_COLLTYPE_NPC | XENT_COLLTYPE_PLYR; + } + else if (ent->collType == XENT_COLLTYPE_DYN) + { + ent->pflags |= 0x1; + ent->move = NULL; + ent->frame = (xEntFrame*)xMemAllocSize(sizeof(xEntFrame)); + + memset(ent->frame, 0, sizeof(xEntFrame)); + + ent->pflags &= (U8)~0x2; + ent->chkby = XENT_COLLTYPE_NPC | XENT_COLLTYPE_PLYR; + ent->penby = XENT_COLLTYPE_NPC | XENT_COLLTYPE_PLYR; + } + else if (ent->collType == XENT_COLLTYPE_NPC) + { + ent->pflags |= 0x1; + ent->move = NULL; + ent->pflags |= 0x2; + ent->chkby = XENT_COLLTYPE_PLYR; + ent->penby = XENT_COLLTYPE_PLYR; + } + else if (ent->collType == XENT_COLLTYPE_PLYR) + { + ent->pflags |= 0x1; + ent->move = NULL; + ent->frame = (xEntFrame*)xMemAllocSize(sizeof(xEntFrame)); + + memset(ent->frame, 0, sizeof(xEntFrame)); + + ent->pflags |= 0x2; + ent->chkby = 0; + ent->penby = 0; + + ent->collis = (xEntCollis*)xMemAllocSize(sizeof(xEntCollis)); + ent->collis->chk = 0x2F; + ent->collis->pen = 0x2E; + ent->collis->post = 0; + ent->collis->depenq = 0; + } + + if ((ent->moreFlags & 0x20 || ent->flags & 0x2) && !ent->frame) + { + ent->frame = (xEntFrame*)xMemAllocSize(sizeof(xEntFrame)); + + memset(ent->frame, 0, sizeof(xEntFrame)); + } + + ent->baseFlags |= 0x20; + + // non-matching: instruction order in epilogue :| + // no idea how to fix that +} + +namespace +{ + F32 get_lower_extent(const xBound& bound) + { + switch (bound.type) + { + case XBOUND_TYPE_SPHERE: + { + return bound.sph.r; + } + case XBOUND_TYPE_BOX: + { + return bound.box.center.y - bound.box.box.lower.y; + } + case XBOUND_TYPE_OBB: + { + if (0.0f == bound.mat->up.x && 0.0f == bound.mat->up.z) + { + return bound.box.center.y - + (bound.mat->up.y * bound.box.box.lower.y + bound.mat->pos.y); + } + else + { + xBox box; + xBoundGetBox(box, bound); + + return bound.box.center.y - box.lower.y; + } + } + case XBOUND_TYPE_CYL: + default: + { + return 0.0f; + } + } + } + + bool collide_downward(xVec3& loc, xEnt*& hit, xScene& s, xEnt& ent, F32 max_dist) + { + xRay3 ray; + U8 old_bound_type; + F32 old_bound_radius; + xCollis coll; + + F32 f31 = get_lower_extent(ent.bound); + xVec3* r30 = xBoundCenter(&ent.bound); + + ray.origin = *r30; + ray.dir.assign(0.0f, -1.0f, 0.0f); + ray.min_t = 0.0f; + ray.max_t = max_dist + f31; + ray.flags = 0xC00; + + old_bound_type = ent.bound.type; + old_bound_radius = ent.bound.sph.r; + + ent.bound.type = XBOUND_TYPE_SPHERE; + ent.bound.sph.r = 0.0f; + + r30->y = FLOAT_MAX; + + coll.flags = 0x100; + + xRayHitsSceneFlags(&s, &ray, &coll, XENT_COLLTYPE_PLYR, 0x26); + + ent.bound.type = old_bound_type; + ent.bound.sph.r = old_bound_radius; + + r30->y = ray.origin.y; + + if (!(coll.flags & 0x1)) + { + return false; + } + + loc = *(xVec3*)&ent.model->Mat->pos; + loc.y -= coll.dist - f31; + + hit = (xEnt*)coll.optr; + + return true; + } + + void drop_stacked_entity(xEnt&); + + void stacked_owner_destroyed(zEntDestructObj&, void* context) + { + drop_stacked_entity(*(xEnt*)context); + } + + void mount_stacked_entity(xEnt& ent, xEnt& driver) + { + if (driver.collType == XENT_COLLTYPE_DYN) + { + if (ent.driver) + { + ent.driver->driving_count--; + } + + ent.driver = &driver; + + driver.driving_count++; + + if (driver.baseType == eBaseTypeDestructObj) + { + zEntDestructObj* d = (zEntDestructObj*)&driver; + d->destroy_notify = stacked_owner_destroyed; + d->notify_context = &ent; + } + } + } + + void dismount_stacked_entity(xEnt& ent) + { + if (ent.driver) + { + if (ent.driver->baseType == eBaseTypeDestructObj) + { + zEntDestructObj* d = (zEntDestructObj*)ent.driver; + d->destroy_notify = NULL; + d->notify_context = NULL; + } + + ent.driver = NULL; + } + } + + void setup_stacked_entity(xEnt& ent) + { + ent.pflags = 0x4; + } + + void drop_stacked_entity(xEnt& ent) + { + ent.pflags = 0x4; + + dismount_stacked_entity(ent); + } + + void stop_stacked_entity(xEnt& ent) + { + ent.pflags = 0; + } + + void update_stacked_entity(xScene& sc, xEnt& ent, F32 dt) + { + xEntApplyPhysics(&ent, &sc, dt); + xEntMove(&ent, &sc, dt); + + F32 dist = ent.model->Mat->pos.y - ent.frame->mat.pos.y; + xVec3 loc; + xEnt* hit; + + if (!(dist <= 0.0f) && collide_downward(loc, hit, sc, ent, dist)) + { + ent.frame->mat.pos.y = loc.y; + stop_stacked_entity(ent); + + if (hit) + { + mount_stacked_entity(ent, *hit); + } + } + } +} // namespace + +void xEntSetup(xEnt* ent) +{ + xSurface* surf; + xModelInstance* minst; + S32 i; + xLinkAsset* la; + xEnt* dent; + + xBaseSetup(ent); + + ent->baseFlags |= 0x20; + + if (ent->asset->surfaceID) + { + surf = (xSurface*)xSceneResolvID(g_xSceneCur, ent->asset->surfaceID); + + if (surf) + { + surf->type = XSURFACE_TYPE_1; + surf->ent = ent; + + minst = ent->model; + + while (minst) + { + minst->Surf = surf; + minst = minst->Next; + } + } + } + + for (i = 0; i < ent->linkCount; i++) + { + la = &ent->link[i]; + + if (la->dstEvent == eEventDrivenby) + { + dent = (xEnt*)xSceneResolvID(g_xSceneCur, la->dstAssetID); + + if (dent) + { + ent->driver = dent; + ent->driveMode = (S32)la->param[0]; + + dent->driving_count++; + } + } + } + + ent->model->RedMultiplier = ent->asset->redMult; + ent->model->GreenMultiplier = ent->asset->greenMult; + ent->model->BlueMultiplier = ent->asset->blueMult; + ent->model->Alpha = ent->asset->seeThru; + + xEntAddHittableFlag(ent); + xEntAddShadowRecFlag(ent); + + zCollGeom_EntSetup(ent); + + if (ent->model) + { + if (ent->bound.type == XBOUND_TYPE_BOX) + { + iBoxForModel(&ent->bound.box.box, (ent->collModel) ? ent->collModel : ent->model); + } + else if (ent->bound.type == XBOUND_TYPE_OBB) + { + iBoxForModelLocal(&ent->bound.box.box, (ent->collModel) ? ent->collModel : ent->model); + } + } + + if (ent->moreFlags & 0x20) + { + anim_coll::reset(*ent); + } + + if (ent->flags & 0x2) + { + setup_stacked_entity(*ent); + } +} + +void xEntSave(xEnt* ent, xSerial* s) +{ + xBaseSave(ent, s); + + if (xEntIsVisible(ent)) + { + s->Write_b1(1); + } + else + { + s->Write_b1(0); + } +} + +void xEntLoad(xEnt* ent, xSerial* s) +{ + S32 b; + + xBaseLoad(ent, s); + + b = 0; + s->Read_b1(&b); + + if (b) + { + xEntShow(ent); + } + else + { + xEntHide(ent); + } +} + +void xEntReset(xEnt* ent) +{ + xMat4x3 frame; + xModelInstance* minst; + + xBaseReset(ent, ent->asset); + + ent->baseFlags |= 0x20; + ent->flags = ent->asset->flags; + ent->miscflags = 0; + ent->moreFlags = ent->asset->moreFlags; + + xEntAddHittableFlag(ent); + xEntAddShadowRecFlag(ent); + + xMat3x3Euler(&frame, ent->asset->ang.x, ent->asset->ang.y, ent->asset->ang.z); + + xVec3SMulBy(&frame.right, ent->asset->scale.x); + xVec3SMulBy(&frame.up, ent->asset->scale.y); + xVec3SMulBy(&frame.at, ent->asset->scale.z); + xVec3Copy(&frame.pos, &ent->asset->pos); + + frame.flags = 0; + + if (ent->model) + { + xModelSetFrame(ent->model, &frame); + + if (ent->collModel) + { + xModelSetFrame(ent->collModel, &frame); + } + + if (ent->moreFlags & 0x20) + { + anim_coll::reset(*ent); + } + + minst = ent->model; + + while (minst) + { + minst->RedMultiplier = ent->asset->redMult; + minst->GreenMultiplier = ent->asset->greenMult; + minst->BlueMultiplier = ent->asset->blueMult; + + minst->Alpha = minst->Data->geometry->matList.materials[0]->color.alpha / 255.0f; + minst->Scale.x = 0.0f; + minst->Scale.y = 0.0f; + minst->Scale.z = 0.0f; + + minst = minst->Next; + } + } + + if (ent->frame) + { + xMat4x3Copy(&ent->frame->mat, &frame); + + ent->frame->oldmat = ent->frame->mat; + + xVec3Copy(&ent->frame->dpos, &g_O3); + xVec3Copy(&ent->frame->dvel, &g_O3); + xVec3Copy(&ent->frame->vel, &g_O3); + xVec3Copy(&ent->frame->oldvel, &g_O3); + xVec3Copy(&ent->frame->rot.axis, &ent->asset->ang); + + ent->frame->rot.angle = 0.0f; + + xRotCopy(&ent->frame->oldrot, &ent->frame->rot); + } + + if (ent->bupdate && ent->model) + { + ent->bupdate(ent, (xVec3*)&ent->model->Mat->pos); + } + + ent->num_updates = xrand() & 127; + + if (ent->flags & 0x2) + { + setup_stacked_entity(*ent); + } +} + +xModelInstance* xEntLoadModel(xEnt* ent, RpAtomic* imodel) +{ + xModelInstance* model; + + model = xModelInstanceAlloc(imodel, ent, 0, 0, NULL); + + while (imodel = iModelFile_RWMultiAtomic(imodel)) + { + xModelInstanceAttach(xModelInstanceAlloc(imodel, ent, 0x8, 0, NULL), model); + } + + if (ent) + { + ent->model = model; + } + + return model; +} + +void xEntAddToPos(xEnt* ent, const xVec3* v) +{ + xVec3AddTo(&ent->frame->mat.pos, v); +} + +void xEntSetupPipeline(xModelInstance* model) +{ + xEntSetupPipeline(model->Surf, model->Data); +} + +static S32 setMaterialTextureRestore; +S32 sSetPipeline; +static RxPipeline* oldPipe; + +void xEntSetupPipeline(xSurface* surf, RpAtomic* model) +{ + setMaterialTextureRestore = 0; + sSetPipeline = 0; + + if (surf) + { + zSurfaceProps* pp = (zSurfaceProps*)surf->moprops; + + if (pp) + { + if (pp->texanim_flags & 0x1) + { + xGroup* g = (xGroup*)zSceneFindObject(pp->texanim[0].group); + + if (g) + { + U32 texid = xGroupGetItem(g, pp->texanim[0].group_idx); + RwTexture* texptr = (RwTexture*)xSTFindAsset(texid, NULL); + + if (texptr) + { + iModelSetMaterialTexture(model, texptr); + setMaterialTextureRestore = 1; + } + } + } + + if (pp->texanim_flags & 0x2) + { + xGroup* g = (xGroup*)zSceneFindObject(pp->texanim[1].group); + + if (g) + { + U32 texid = xGroupGetItem(g, pp->texanim[1].group_idx); + RwTexture* texptr = (RwTexture*)xSTFindAsset(texid, NULL); + + if (texptr) + { + xFXanimUV2PSetTexture(texptr); + sSetPipeline = 1; + } + } + } + else if (pp->uvfx_flags & 0x2) + { + RwTexture* texptr = (RwTexture*)xSTFindAsset(pp->asset->matfx.dualmapID, NULL); + + if (texptr) + { + xFXanimUV2PSetTexture(texptr); + sSetPipeline = 1; + } + } + else + { + xFXanimUV2PSetTexture(NULL); + } + + if (pp->uvfx_flags & 0x3) + { + sSetPipeline = 1; + + xFXanimUVSetTranslation(&pp->uvfx[0].trans); + xFXanimUV2PSetTranslation(&pp->uvfx[1].trans); + xFXanimUVSetScale(&pp->uvfx[0].scale); + xFXanimUV2PSetScale(&pp->uvfx[1].scale); + xFXanimUVSetAngle(RAD2DEG(PI * 0.9824379f / 100000) * pp->uvfx[0].rot); + xFXanimUV2PSetAngle(RAD2DEG(PI * 0.9824379f / 100000) * pp->uvfx[1].rot); + } + + if (sSetPipeline) + { + oldPipe = model->pipeline; + xFXanimUVAtomicSetup(model); + } + } + } +} + +void xEntRestorePipeline(xModelInstance* model) +{ + xEntRestorePipeline(model->Surf, model->Data); +} + +void xEntRestorePipeline(xSurface*, RpAtomic* model) +{ + if (setMaterialTextureRestore) + { + iModelResetMaterial(model); + setMaterialTextureRestore = 0; + } + + if (sSetPipeline) + { + model->pipeline = oldPipe; + sSetPipeline = 0; + } +} + +void xEntRender(xEnt* ent) +{ + S32 shadowOutside; + xVec3 shadVec; + + if (ent->model == NULL || !xEntIsVisible(ent) || ent->model->Flags & 0x400) + { + return; + } + + ent->isCulled = 0; + + if (ent->baseType == eBaseTypePlayer || (ent->baseType == eBaseTypeNPC && !(ent->flags & 0x40))) + { + // non-matching: 10.0f is loaded too early + + shadVec.x = ent->model->Mat->pos.x; + shadVec.y = ent->model->Mat->pos.y - 10.0f; + shadVec.z = ent->model->Mat->pos.z; + + if (iModelCullPlusShadow(ent->model->Data, ent->model->Mat, &shadVec, &shadowOutside)) + { + if (shadowOutside) + { + ent->isCulled = 1; + return; + } + else + { + goto postrender; + } + } + } + else + { + if (iModelCull(ent->model->Data, ent->model->Mat)) + { + ent->isCulled = 1; + return; + } + } + + xModelRender(ent->model); + +postrender: + + if ((ent->baseType == eBaseTypeNPC && !(ent->flags & 0x40)) || ent->baseType == eBaseTypePlayer) + { + zLightAddLocal(ent); + xShadow_ListAdd(ent); + } +} + +void xEntUpdate(xEnt* ent, xScene* sc, F32 dt) +{ + xEntBeginUpdate(ent, sc, dt); + + if (ent->pflags & 0x2) + { + xEntApplyPhysics(ent, sc, dt); + } + + if (ent->pflags & 0x1) + { + xEntMove(ent, sc, dt); + } + + xFFXApply(ent, sc, dt); + + if (ent->collis) + { + xEntCollide(ent, sc, dt); + } + + if (ent->flags & 0x2 && ent->pflags & 0x4) + { + update_stacked_entity(*sc, *ent, dt); + } + + xEntEndUpdate(ent, sc, dt); +} + +void xEntBeginUpdate(xEnt* ent, xScene* sc, F32 dt) +{ + if (ent->model) + { + xModelUpdate(ent->model, dt); + + if (ent->frame) + { + xVec3Copy(&ent->frame->oldvel, &ent->frame->vel); + + ent->frame->oldmat = ent->frame->mat; + + xRotCopy(&ent->frame->oldrot, &ent->frame->rot); + xMat4x3Copy(&ent->frame->mat, xModelGetFrame(ent->model)); + + ent->frame->mode = 0; + } + } +} + +void xEntEndUpdate(xEnt* ent, xScene* sc, F32 dt) +{ + ent->num_updates++; + + if (ent->model) + { + if (ent->frame) + { + if (!(ent->frame->mode & 0x20000)) + { + xMat3x3Copy((xMat4x3*)ent->model->Mat, &ent->frame->mat); + } + + if (!(ent->frame->mode & 0x10000)) + { + xVec3* mpos = (xVec3*)&ent->model->Mat->pos; + xVec3Copy(mpos, &ent->frame->mat.pos); + } + } + + if (ent->bupdate) + { + xVec3* upos = (xVec3*)&ent->model->Mat->pos; + ent->bupdate(ent, upos); + } + + xModelEval(ent->model); + + if (ent->moreFlags & 0x20) + { + anim_coll::refresh(*ent); + } + + if (ent->endUpdate) + { + ent->endUpdate(ent, sc, dt); + } + } +} + +void xEntDefaultBoundUpdate(xEnt* ent, xVec3* pos) +{ + xBound* bound = &ent->bound; + + if (bound->type == XBOUND_TYPE_SPHERE) + { + xVec3Copy(&bound->sph.center, pos); + + bound->sph.center.y += 0.7f; + bound->sph.r = 0.7f; + } + + xBoundUpdate(bound); + zGridUpdateEnt(ent); +} + +void xEntDefaultTranslate(xEnt* ent, xVec3* dpos, xMat4x3* dmat) +{ + if (dmat) + { + if (ent->model) + { + xMat4x3Mul((xMat4x3*)ent->model->Mat, (xMat4x3*)ent->model->Mat, dmat); + } + + if (ent->frame) + { + xMat4x3Mul(&ent->frame->mat, &ent->frame->mat, dmat); + } + + xMat4x3Toworld(xEntGetCenter(ent), dmat, xEntGetCenter(ent)); + } + else + { + if (ent->model) + { + xVec3AddTo(xEntGetPos(ent), dpos); + } + + if (ent->frame) + { + xVec3AddTo(&ent->frame->mat.pos, dpos); + } + + xVec3AddTo(xEntGetCenter(ent), dpos); + } +} + +static void xEntRotationToMatrix(xEntFrame* frame) +{ + if (frame->mode & 0x20) + { + if (frame->mode & 0x400) + { + xVec3AddTo(&frame->rot.axis, &frame->drot.axis); + xMat3x3Euler(&frame->mat, frame->rot.axis.x, frame->rot.axis.y, frame->rot.axis.z); + } + else + { + frame->rot.angle = xAngleClamp(frame->rot.angle + frame->drot.angle); + + xMat3x3Rot(&frame->mat, &frame->rot.axis, frame->rot.angle); + } + } +} + +void xEntMotionToMatrix(xEnt* ent, xEntFrame* frame) +{ + if (frame->mode & 0x1000) + { + xEntRotationToMatrix(frame); + } + + if (frame->mode & 0x2) + { + if (frame->mode & 0x800) + { + xMat3x3RMulVec(&frame->dpos, &frame->mat, &frame->dpos); + } + + xEntAddToPos(ent, &frame->dpos); + } + + if (frame->mode & 0x8) + { + if (frame->mode & 0x800) + { + xMat3x3RMulVec(&frame->dvel, &frame->mat, &frame->dvel); + } + + xVec3AddTo(&frame->vel, &frame->dvel); + } + + if (!(frame->mode & 0x1000)) + { + xEntRotationToMatrix(frame); + } +} + +void xEntMove(xEnt* ent, xScene* sc, F32 dt) +{ + if (ent->moreFlags & 0x20) + { + anim_coll::pre_move(*ent); + } + + ent->move(ent, sc, dt, ent->frame); + + xEntMotionToMatrix(ent, ent->frame); + + if (ent->driver) + { + xEntFrame* dframe = ent->driver->frame; + + if (ent->driveMode == 0) + { + xVec3 dpos; + xVec3Sub(&dpos, &dframe->mat.pos, &dframe->oldmat.pos); + + ent->transl(ent, &dpos, NULL); + } + else if (ent->driveMode == 1) + { + RwMatrixUpdate((RwMatrix*)&dframe->oldmat); + + xMat4x3 invOldmat; + RwMatrixInvert((RwMatrix*)&invOldmat, (RwMatrix*)&dframe->oldmat); + + xMat4x3 deltaMat; + xMat4x3Mul(&deltaMat, &invOldmat, &dframe->mat); + + ent->transl(ent, NULL, &deltaMat); + } + } + + if (ent->moreFlags & 0x20) + { + anim_coll::post_move(*ent); + } +} + +namespace +{ + namespace anim_coll + { + void post_move(xEnt& ent) + { + xMat4x3& mat = *(xMat4x3*)ent.model->Mat; + xEnt::anim_coll_data& ac = *ent.anim_coll; + + ac.old_mat = ent.frame->mat; + + xMat4x3Mul(&mat, &ac.new_mat, &ac.old_mat); + + ent.frame->mat = mat; + } + + void pre_move(xEnt& ent) + { + xMat4x3& mat = *(xMat4x3*)ent.model->Mat; + xEnt::anim_coll_data& ac = *ent.anim_coll; + + ent.frame->mat = mat = ac.old_mat; + } + } // namespace anim_coll +} // namespace + +void xEntApplyPhysics(xEnt* ent, xScene* sc, F32 dt) +{ + xVec3 dposvel = { 0, 0, 0 }; + + if (ent->pflags & 0x4 && sc->flags & 0x1) + { + ent->frame->vel.y += sc->gravity * dt; + } + + if (ent->pflags & 0x10 && sc->flags & 0x2) + { + F32 tfric = -(sc->friction * dt - 1.0f); + xVec3SMulBy(&ent->frame->vel, tfric); + } + + if (ent->pflags & 0x8 && sc->flags & 0x4) + { + F32 tdrag = -(sc->drag * dt - 1.0f); + xVec3SMulBy(&ent->frame->vel, tdrag); + } + + xVec3Add(&dposvel, &ent->frame->vel, &ent->frame->oldvel); + xVec3SMulBy(&dposvel, 0.5f * dt); + + if (dposvel.y < 0.0f) + { + F32 dposXZ = xsqrt(SQR(dposvel.x) + SQR(dposvel.z)); + F32 scaleXZ = (dposXZ > 0.00001f) ? ((0.63f * (30.0f * dt)) / dposXZ) : 0.0f; + F32 scaleY = (0.63f * (30.0f * dt)) / (F32)iabs(dposvel.y); + + if (scaleXZ < 1.0f) + { + dposvel.x *= scaleXZ; + dposvel.z *= scaleXZ; + } + + if (scaleY < 1.0f) + { + dposvel.y *= scaleY; + } + } + + xEntAddToPos(ent, &dposvel); +} + +void xEntCollide(xEnt* ent, xScene* sc, F32 dt) +{ + if (ent->model) + { + if (ent->collis->chk & 0x2E) + { + xEntBeginCollide(ent, sc, dt); + } + + if (ent->collis->chk & 0x8) + { + xEntCollCheckNPCsByGrid(ent, sc, xEntCollCheckOneEntNoDepen); + } + + if (ent->collis->chk & 0x6) + { + xEntCollCheckByGrid(ent, sc, xEntCollCheckOneEntNoDepen); + } + + if (ent->collis->chk & 0x20) + { + xEntCollCheckEnv(ent, sc); + } + + xCollis* coll = &ent->collis->colls[0]; + + if (ent->collis->chk & 0x2E) + { + F32 h_dot_n; + + if (ent->bound.type == XBOUND_TYPE_SPHERE) + { + h_dot_n = ent->bound.sph.r; + } + else + { + h_dot_n = 0.7f; + } + + if (ent->pflags & 0x80 && coll->flags & 0x1) + { + F32 depen_len = xVec3Dot(&coll->hdng, &coll->norm); + + if (depen_len > 0.0f) + { + xVec3Inv(&coll->norm, &coll->norm); + depen_len = -depen_len; + } + + depen_len = depen_len * coll->dist + h_dot_n; + + if (depen_len < 0.0f || depen_len > h_dot_n) + { + depen_len = CLAMP(depen_len, 0.0f, h_dot_n); + } + + xVec3SMul(&coll->depen, &coll->norm, depen_len); + } + + if (ent->frame->vel.y <= 0.0f) + { + xEntCollideFloor(ent, sc, dt); + } + else + { + xEntCollideCeiling(ent, sc, dt); + } + + xEntCollideWalls(ent, sc, dt); + xEntEndCollide(ent, sc, dt); + } + } +} + +void xEntBeginCollide(xEnt* ent, xScene*, F32) +{ + U8 idx; + xCollis* coll; + + if (ent->bupdate) + { + ent->bupdate(ent, &ent->frame->mat.pos); + } + + for (idx = 0; idx < 18; idx++) + { + coll = &ent->collis->colls[idx]; + + coll->flags = 0x1F00; + coll->optr = NULL; + coll->mptr = NULL; + coll->dist = FLOAT_MAX; + } + + ent->collis->idx = 6; + ent->collis->stat_sidx = 6; + ent->collis->stat_eidx = 6; + ent->collis->dyn_sidx = 6; + ent->collis->dyn_eidx = 6; + ent->collis->npc_sidx = 6; + ent->collis->npc_eidx = 6; + ent->collis->env_sidx = 6; + ent->collis->env_eidx = 6; +} + +void xEntEndCollide(xEnt* ent, xScene* sc, F32 dt) +{ + if (ent->collis->post) + { + ent->collis->post(ent, sc, dt, ent->collis); + } +} + +void xEntCollCheckEnv(xEnt* p, xScene* sc) +{ + xCollis* coll; + U8 ncolls; + + p->collis->env_sidx = p->collis->idx; + + coll = &p->collis->colls[p->collis->idx]; + coll->flags = 0x1F00; + + ncolls = 18 - p->collis->idx; + + p->collis->idx += (U8)iSphereHitsEnv3(&p->bound.sph, sc->env, coll, ncolls, 0.78539819f); + p->collis->env_eidx = p->collis->idx; +} + +static void xEntCollCheckOneGrid(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*), + xGrid* grid) +{ + xVec3* r26 = xEntGetCenter(p); + xGridIterator it; + S32 px, pz; + + xGridBound* cell = xGridIterFirstCell(grid, r26->x, r26->y, r26->z, px, pz, it); + + while (cell) + { + if (xQuickCullIsects(&p->bound.qcd, (xQCData*)(cell + 1))) + { + hitIt((xEnt*)cell->data, sc, p); + } + + cell = xGridIterNextCell(it); + } + + // non-matching: float scheduling + + F32 halfsizez = (grid->csizez * 0.5f); + F32 halfsizex = (grid->csizex * 0.5f); + + F32 clcenterx = grid->csizex * px; + F32 clcenterz = grid->csizez * pz; + + clcenterx += grid->minx; + clcenterx += halfsizex; + + clcenterz += halfsizez; + clcenterz += grid->minz; + + static S32 k; + + if (r26->x < clcenterx) + { + if (r26->z < clcenterz) + { + k = 0; + } + else + { + k = 1; + } + } + else + { + if (r26->z < clcenterz) + { + k = 3; + } + else + { + k = 2; + } + } + + static S32 offs[4][3][2] = { + { { -1, 0 }, { -1, -1 }, { 0, -1 } }, + { { 0, -1 }, { 1, -1 }, { 1, 0 } }, + { { 1, 0 }, { 1, 1 }, { 0, 1 } }, + { { 0, 1 }, { -1, 1 }, { -1, 0 } }, + }; + + for (S32 i = 0; i < 3; i++) + { + S32 _x = px + offs[k][i][1]; + S32 _z = pz + offs[k][i][0]; + + cell = xGridIterFirstCell(grid, _x, _z, it); + + while (cell) + { + if (xQuickCullIsects(&p->bound.qcd, (xQCData*)(cell + 1))) + { + hitIt((xEnt*)cell->data, sc, p); + } + + cell = xGridIterNextCell(it); + } + } + + cell = xGridIterFirstCell(&grid->other, it); + + while (cell) + { + if (xQuickCullIsects(&p->bound.qcd, (xQCData*)(cell + 1))) + { + hitIt((xEnt*)cell->data, sc, p); + } + + cell = xGridIterNextCell(it); + } +} + +void xEntCollCheckByGrid(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*)) +{ + p->collis->stat_sidx = p->collis->idx; + p->collis->dyn_sidx = p->collis->idx; + + xEntCollCheckOneGrid(p, sc, hitIt, &colls_grid); + xEntCollCheckOneGrid(p, sc, hitIt, &colls_oso_grid); + + p->collis->stat_eidx = p->collis->idx; + p->collis->dyn_eidx = p->collis->idx; +} + +void xEntCollCheckNPCsByGrid(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*)) +{ + p->collis->npc_sidx = p->collis->idx; + + xEntCollCheckOneGrid(p, sc, hitIt, &npcs_grid); + + p->collis->npc_eidx = p->collis->idx; +} + +void xEntCollCheckStats(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*)) +{ + p->collis->stat_sidx = p->collis->idx; + + xSceneForAllStatics(sc, hitIt, p); + + p->collis->stat_eidx = p->collis->idx; +} + +void xEntCollCheckDyns(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*)) +{ + p->collis->dyn_sidx = p->collis->idx; + + xSceneForAllDynamics(sc, hitIt, p); + + p->collis->dyn_eidx = p->collis->idx; +} + +void xEntCollCheckNPCs(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*)) +{ + p->collis->npc_sidx = p->collis->idx; + + xSceneForAllNPCs(sc, hitIt, p); + + p->collis->npc_eidx = p->collis->idx; +} + +S32 xent_entent = 0; +xEnt* xEntCollCheckOneEntNoDepen(xEnt* ent, xScene* sc, void* data) +{ + xent_entent = 1; + + xEnt* p = (xEnt*)data; + xCollis* coll; + U32 modl_coll = 0; + + if (p->collis->idx >= 15) + { + xent_entent = 0; + return NULL; + } + + if ((ent->chkby & p->collType) == 0) + { + xent_entent = 0; + return ent; + } + + if (ent->id == p->id && (ent == p || ent->baseType != eBaseTypeBoulder)) + { + xent_entent = 0; + return ent; + } + + coll = &p->collis->colls[p->collis->idx]; + + if (ent->collLev == 5 && p->collType & (XENT_COLLTYPE_NPC | XENT_COLLTYPE_PLYR)) + { + modl_coll = 1; + } + + if (modl_coll) + { + coll->flags = 0; + } + else + { + coll->flags = 0x1F00; + } + + xBoundHitsBound(&p->bound, &ent->bound, coll); + + if (coll->flags & 0x1) + { + if (modl_coll) + { + xBound tmp; + xBound* bptr; // unused + U8 ncolls; + xVec3 *upper, *lower; + U8 idx; + + coll->flags = 0x1F00; + + if (p->bound.type == XBOUND_TYPE_SPHERE) + { + xModelInstance* r4 = (ent->collModel) ? ent->collModel : ent->model; + ncolls = 15 - p->collis->idx; + idx = iSphereHitsModel3(&p->bound.sph, r4, coll, ncolls, 0.78539819f); + } + else if (p->bound.type == XBOUND_TYPE_BOX) + { + upper = &p->bound.box.box.upper; + lower = &p->bound.box.box.lower; + + tmp.type = XBOUND_TYPE_SPHERE; + + xVec3Add(&tmp.sph.center, upper, lower); + xVec3SMulBy(&tmp.sph.center, 0.5f); + + tmp.sph.r = + 0.167f * (upper->x + upper->y + upper->z - lower->x - lower->y - lower->z); + + // none of the code above is used for anything... maybe debug stuff + + xModelInstance* r4 = (ent->collModel) ? ent->collModel : ent->model; + ncolls = 15 - p->collis->idx; + idx = iSphereHitsModel3(&p->bound.sph, r4, coll, ncolls, 0.78539819f); + } + + // idx might be undefined here...! + + for (U8 i = 0; i < idx; i++) + { + coll[i].optr = ent; + coll[i].mptr = ent->model; + + p->collis->idx++; + } + + xent_entent = 0; + return ent; + } + else + { + coll->oid = ent->id; + coll->optr = ent; + coll->mptr = ent->model; + + p->collis->idx++; + + if (ent->pflags & 0x20 && ent->bound.type == XBOUND_TYPE_SPHERE && + p->bound.type == XBOUND_TYPE_SPHERE && coll->hdng.y < -0.866025f) + { + F32 rsum = p->bound.sph.r + ent->bound.sph.r; + F32 dx = p->bound.sph.center.x - ent->bound.sph.center.x; + F32 dy = p->bound.sph.center.y - ent->bound.sph.center.y; + F32 dz = p->bound.sph.center.z - ent->bound.sph.center.z; + + F32 hsqr = SQR(rsum) - (SQR(dx) + SQR(dz)); + + if (hsqr >= 0.0f) + { + coll->depen.x = 0.0f; + coll->depen.y = xsqrt(hsqr) - dy; + coll->depen.z = 0.0f; + coll->dist = 0.7f - coll->depen.y; + coll->hdng.x = 0.0f; + coll->hdng.y = -1.0f; + coll->hdng.z = 0.0f; + } + } + } + } + + xent_entent = 0; + return ent; +} + +void xEntCollideFloor(xEnt* p, xScene* sc, F32 dt) +{ + xCollis* coll = &p->collis->colls[0]; + U8 idx; + xCollis* ml = coll; + xVec3 motion; + F32 mlen; + S32 stepping = 0; + F32 sbr; + + if (p->bound.type == XBOUND_TYPE_SPHERE) + { + sbr = p->bound.sph.r; + } + else + { + sbr = 0.7f; + } + + xVec3Copy(&motion, &p->frame->mat.pos); + xVec3SubFrom(&motion, &p->frame->oldmat.pos); + + motion.y = 0.0f; + mlen = xVec3Length(&motion); + + for (idx = 6; idx < p->collis->idx; idx++) + { + xCollis* mf = &p->collis->colls[idx]; + + if (mf->flags & 0x1) + { + xEnt* fent = (xEnt*)mf->optr; + + if (fent) + { + if ((fent->collType == XENT_COLLTYPE_DYN || fent->collType == XENT_COLLTYPE_STAT) || + (fent->pflags & 0x20 && 0.0f == mf->hdng.x && 0.0f == mf->hdng.z)) + { + if (!((p->collis->depenq) ? + p->collis->depenq(p, fent, sc, dt, mf) : + (fent->collType & p->collis->pen && fent->penby & p->collType))) + { + continue; + } + } + else + { + continue; + } + } + else if (!(p->collis->pen & 0x20)) + { + continue; + } + + if (mf->dist < ml->dist) + { + if (mf->hdng.y < -icos(PI / 3) && + (mf->norm.y > icos(nsn_angle) || + p->frame->oldmat.pos.y > dt * (sc->gravity * dt) + p->frame->mat.pos.y)) + { + ml = mf; + stepping = 0; + } + else if (mlen > 0.001f && mf->hdng.y < 0.65f / sbr - 1.0f && + mf->norm.y > icos(nsn_angle)) + { + stepping = 1; + ml = mf; + } + } + } + } + + if (ml != coll) + { + F32 flr_dist = ml->dist * (F32)iabs(ml->hdng.y); + xEnt* fent; // unused + + *coll = *ml; + + if (flr_dist < sbr) + { + ml->flags |= 0x6; + + if (stepping) + { + p->frame->mat.pos.y += 1.5f * dt; + p->frame->mat.pos.x += ml->depen.x; + p->frame->mat.pos.z += ml->depen.z; + } + else + { + p->frame->mat.pos.y += ml->depen.y; + } + + p->frame->vel.y = 0.0f; + } + } +} + +void xEntCollideCeiling(xEnt* p, xScene* sc, F32 dt) +{ + xCollis* coll = &p->collis->colls[1]; + U8 idx; + xCollis* ml = coll; + F32 sbr; + + if (p->bound.type == XBOUND_TYPE_SPHERE) + { + sbr = p->bound.sph.r; + } + else + { + sbr = 0.7f; + } + + for (idx = 6; idx < p->collis->idx; idx++) + { + xCollis* mf = &p->collis->colls[idx]; + xEnt* fent = (xEnt*)mf->optr; + + if (fent) + { + if (!((p->collis->depenq) ? + p->collis->depenq(p, fent, sc, dt, mf) : + (fent->collType & p->collis->pen && fent->penby & p->collType))) + { + continue; + } + } + else if (!(p->collis->pen & 0x20)) + { + continue; + } + + if (mf->hdng.y > icos(0.78539819f) && mf->dist < ml->dist) + { + ml = mf; + } + } + + if (ml != coll) + { + F32 ceil_dist = ml->dist * (F32)iabs(ml->hdng.y); + + *coll = *ml; + + ml->flags |= 0xA; + + if (ceil_dist < sbr) + { + p->frame->mat.pos.y -= sbr - ceil_dist; + p->frame->vel.y = 0.0f; + } + } +} + +void xEntCollideWalls(xEnt* p, xScene* sc, F32 dt) +{ + xCollis* coll; + xEnt* cent; + U8 idx, sidx; + F32 sbr; + + if (p->bound.type == XBOUND_TYPE_SPHERE) + { + sbr = p->bound.sph.r; + } + else + { + sbr = 0.7f; + } + + if (p->collis->pen & 0x8) + { + idx = p->collis->npc_eidx; + sidx = p->collis->npc_sidx; + + while (sidx < idx) + { + coll = &p->collis->colls[sidx]; + cent = (xEnt*)coll->optr; + + if (!(coll->flags & 0x2) && coll->dist < sbr && + ((p->collis->depenq) ? p->collis->depenq(p, cent, sc, dt, coll) : + cent->penby & p->collType)) + { + if (0.0f != coll->depen.x || 0.0f != coll->depen.z) + { + coll->depen.y = 0.0f; + } + + xEntAddToPos(p, &coll->depen); + } + + sidx++; + } + } + + if (p->collis->pen & 0x4) + { + idx = p->collis->dyn_eidx; + sidx = p->collis->dyn_sidx; + + while (sidx < idx) + { + coll = &p->collis->colls[sidx]; + cent = (xEnt*)coll->optr; + + if (!(coll->flags & 0x2) && coll->dist < sbr && + ((p->collis->depenq) ? p->collis->depenq(p, cent, sc, dt, coll) : + cent->penby & p->collType)) + { + coll->depen.y = 0.0f; + + xEntAddToPos(p, &coll->depen); + } + + sidx++; + } + } + + if (p->collis->pen & 0x2) + { + idx = p->collis->stat_eidx; + sidx = p->collis->stat_sidx; + + while (sidx < idx) + { + coll = &p->collis->colls[sidx]; + cent = (xEnt*)coll->optr; + + if (!(coll->flags & 0x2) && coll->dist < sbr && + ((p->collis->depenq) ? p->collis->depenq(p, cent, sc, dt, coll) : + cent->penby & p->collType)) + { + coll->depen.y = 0.0f; + + xEntAddToPos(p, &coll->depen); + } + + sidx++; + } + } + + if (p->collis->pen & 0x20) + { + idx = p->collis->env_eidx; + sidx = p->collis->env_sidx; + + while (sidx < idx) + { + coll = &p->collis->colls[sidx]; + cent = (xEnt*)coll->optr; + + if (!(coll->flags & 0x2) && coll->dist < sbr) + { + coll->depen.y = 0.0f; + + xEntAddToPos(p, &coll->depen); + } + + sidx++; + } + } +} + +void xEntSetNostepNormAngle(F32 angle) +{ + nsn_angle = angle; +} + +xBox* xEntGetAllEntsBox() +{ + return &all_ents_box; +} + +void xEntAnimateCollision(xEnt& ent, bool on) +{ + if (on && !(ent.moreFlags & 0x20)) + { + ent.moreFlags |= 0x20; + + if (!ent.frame) + { + ent.frame = (xEntFrame*)xMemAllocSize(sizeof(xEntFrame)); + + memset(ent.frame, 0, sizeof(xEntFrame)); + } + + anim_coll::reset(ent); + } + else if (!on && ent.moreFlags & 0x20) + { + ent.moreFlags &= (U8)~0x20; + } +} + +bool xEntValidType(U8 type) +{ + return type == eBaseTypeTrigger || type == eBaseTypeVillain || type == eBaseTypePlayer || + type == eBaseTypePickup || type == eBaseTypePlatform || type == eBaseTypeDoor || + type == eBaseTypeSavePoint || type == eBaseTypeItem || type == eBaseTypeStatic || + type == eBaseTypeDynamic || type == eBaseTypeBubble || type == eBaseTypePendulum || + type == eBaseTypeHangable || type == eBaseTypeButton || type == eBaseTypeProjectile || + type == eBaseTypeDestructObj || type == eBaseTypeUI || type == eBaseTypeUIFont || + type == eBaseTypeProjectileType || type == eBaseTypeEGenerator || type == eBaseTypeNPC || + type == eBaseTypeBoulder || type == eBaseTypeTeleportBox || type == eBaseTypeZipLine; +} + +void xEntReposition(xEnt& ent, const xMat4x3& mat) +{ + *(xMat4x3*)ent.model->Mat = mat; + + if (ent.collModel && ent.collModel != ent.model) + { + *(xMat4x3*)ent.collModel->Mat = mat; + } + + if (ent.frame) + { + ent.frame->mat = mat; + } + + if (ent.bound.mat) + { + *ent.bound.mat = mat; + } + + ent.bound.sph.center = mat.pos; + + xBoundUpdate(&ent.bound); + zGridUpdateEnt(&ent); +} + +void xEntInitShadow(xEnt& ent, xEntShadow& shadow) +{ + ent.entShadow = &shadow; + + shadow.vec.assign(0.0f, 1.0f, 0.0f); + shadow.pos = ent.asset->pos; + shadow.shadowModel = NULL; + shadow.dst_cast = -1.0f; + shadow.radius[0] = -1.0f; + shadow.radius[1] = -1.0f; +} diff --git a/src/SB/Core/x/xEnt.h b/src/SB/Core/x/xEnt.h index bab5d78..e097784 100644 --- a/src/SB/Core/x/xEnt.h +++ b/src/SB/Core/x/xEnt.h @@ -1,88 +1,84 @@ #ifndef XENT_H #define XENT_H -#include -#include "xEnv.h" -#include "xCollis.h" +#include +#include +#include + +#include "xBase.h" +#include "xMath3.h" +#include "xModel.h" +#include "xLightKit.h" #include "xGrid.h" -#include "xFX.h" -#include "xShadow.h" +#include "xBound.h" +#include "xFFX.h" +#include "xCollide.h" struct xEntAsset : xBaseAsset { + // Offset: 0x8 U8 flags; U8 subtype; U8 pflags; U8 moreFlags; + U8 pad; + //U8 padding[3]; // this padding is added automatically. it should not be here + + // Offset: 0x10 U32 surfaceID; + + // Offset: 0x14 xVec3 ang; + + // Offset: 0x20 xVec3 pos; + + // Offset: 0x2C xVec3 scale; + + // Offset: 0x38 F32 redMult; F32 greenMult; F32 blueMult; F32 seeThru; + + // Offset: 0x48 F32 seeThruSpeed; U32 modelInfoID; U32 animListID; }; -struct xModelInstance; - -struct xAnimPlay -{ - xAnimPlay* Next; - U16 NumSingle; - U16 BoneCount; - xAnimSingle* Single; - void* Object; - xAnimTable* Table; - xMemPool* Pool; - xModelInstance* ModelInst; - void (*BeforeAnimMatrices)(xAnimPlay*, xQuat*, xVec3*, S32); -}; - -struct xScene -{ - U32 sceneID; - U16 flags; - U16 num_trigs; - U16 num_stats; - U16 num_dyns; - U16 num_npcs; - U16 num_act_ents; - F32 gravity; - F32 drag; - F32 friction; - U16 num_ents_allocd; - U16 num_trigs_allocd; - U16 num_stats_allocd; - U16 num_dyns_allocd; - U16 num_npcs_allocd; - xEnt** trigs; - xEnt** stats; - xEnt** dyns; - xEnt** npcs; - xEnt** act_ents; - xEnv* env; - xMemPool mempool; - xBase* (*resolvID)(U32); - unsigned char* (*base2Name)(xBase*); - unsigned char* (*id2Name)(U32); -}; +struct xEnt; +struct xScene; struct xEntFrame { xMat4x3 mat; + + // Offset: 0x40 xMat4x3 oldmat; + + // Offset: 0x80 xVec3 oldvel; + + // Offset: 0x8C xRot oldrot; + + // Offset: 0x9C xRot drot; xRot rot; + + // Offset: 0xBC + xVec3 dpos; + + // Offset: 0xC8 xVec3 dvel; + + // Offset: 0xD4 xVec3 vel; + + // Offset: 0xE0 U32 mode; - xVec3 dpos; }; struct xEntCollis @@ -91,92 +87,200 @@ struct xEntCollis U8 pen; U8 env_sidx; U8 env_eidx; + U8 npc_sidx; U8 npc_eidx; U8 dyn_sidx; U8 dyn_eidx; + U8 stat_sidx; U8 stat_eidx; U8 idx; + xCollis colls[18]; void (*post)(xEnt*, xScene*, F32, xEntCollis*); U32 (*depenq)(xEnt*, xEnt*, xScene*, F32, xCollis*); }; -struct xEntShadow +struct xShadowSimpleCache; +struct xEntShadow; + +typedef void (*xEntUpdateCallback)(xEnt*, xScene*, F32); +typedef void (*xEntBoundUpdateCallback)(xEnt*, xVec3*); +typedef void (*xEntMoveCallback)(xEnt*, xScene*, F32, xEntFrame*); +typedef void (*xEntRenderCallback)(xEnt*); +typedef void (*xEntTranslateCallback)(xEnt*, xVec3*, xMat4x3*); + +// Size: 0xD0 +struct xEnt : xBase { - xVec3 pos; - xVec3 vec; - RpAtomic* shadowModel; - F32 dst_cast; - F32 radius[2]; - struct + struct anim_coll_data { - S32 flg_castOnOneDFF : 1; - S32 flg_castOnAllDFF : 1; - S32 flg_disableEnvCast : 1; - S32 flg_shadowUnused : 29; + U32 flags; + U32 bones; + xMat4x3 old_mat; + xMat4x3 new_mat; + U32 verts_size; + xVec3* verts; + xVec3* normals; }; -}; -struct xEnt : xBase -{ + // Offset: 0x10 xEntAsset* asset; - U16 idx; + U16 idx; //0x14 + U16 num_updates; + + // Offset: 0x18 U8 flags; U8 miscflags; U8 subType; - U8 pflags; - U16 moreFlags; - struct - { - U8 _isCulled : 2; - U8 collisionEventReceived : 2; - }; + + // Offset: 0x1B + U8 pflags; // p -> physics flags + U8 moreFlags; //0x1c + U8 isCulled; U8 driving_count; U8 num_ffx; - U8 collType; + + // Offset: 0x20 + U8 collType; // XENT_COLLTYPE_* (defined below) U8 collLev; - U8 chkby; - U8 penby; - void (*visUpdate)(xEnt*); + U8 chkby; // XENT_COLLTYPE_* bitmask + U8 penby; // XENT_COLLTYPE_* bitmask + + // Offset: 0x24 xModelInstance* model; xModelInstance* collModel; xModelInstance* camcollModel; - void (*update)(xEnt*, xScene*, F32); - void (*endUpdate)(xEnt*, xScene*, F32); - void (*bupdate)(xEnt*, xVec3*); - void (*move)(xEnt*, xScene*, F32, xEntFrame*); - void (*render)(xEnt*); + xLightKit* lightKit; + + // Offset: 0x34 + xEntUpdateCallback update; + xEntUpdateCallback endUpdate; + xEntBoundUpdateCallback bupdate; + xEntMoveCallback move; + + // Offset: 0x44 + xEntRenderCallback render; xEntFrame* frame; - xEntCollis* collis; + xEntCollis* collis; //0x4c + + // Offset: 0x50 xGridBound gridb; + + // Offset: 0x64 xBound bound; - void (*transl)(xEnt*, xVec3*, xMat4x3*); - xFFX* ffx; + + // Offset: 0xB0 + xEntTranslateCallback transl; //0xb0 + xFFX* ffx; //0xb4 xEnt* driver; - xEnt* driven; S32 driveMode; + + // Offset: 0xC0 xShadowSimpleCache* simpShadow; xEntShadow* entShadow; anim_coll_data* anim_coll; - void* user_data; + void* user_data; // 0xCC }; -struct xEntNPCAsset +// collision types +#define XENT_COLLTYPE_NONE 0x0 +#define XENT_COLLTYPE_TRIG 0x1 // trigger (TRIG) +#define XENT_COLLTYPE_STAT 0x2 // static (SIMP) +#define XENT_COLLTYPE_DYN 0x4 // dynamic (PLAT) +#define XENT_COLLTYPE_NPC 0x8 // npc/enemy (VIL) +#define XENT_COLLTYPE_PLYR 0x10 // player (PLYR) + +// Size: 0x40 +struct xEntShadow { - S32 npcFlags; - S32 npcModel; - S32 npcProps; - U32 movepoint; - U32 taskWidgetPrime; - U32 taskWidgetSecond; + enum radius_enum + { + RADIUS_CACHE, + RADIUS_RASTER, + MAX_RADIUS + }; + + xVec3 pos; + xVec3 vec; + RpAtomic* shadowModel; + F32 dst_cast; + F32 radius[2]; }; -struct xEntNPCAssetIN : xEntNPCAsset +extern S32 xent_entent; + +xMat4x3* xEntGetFrame(const xEnt* ent); +void xEntEnable(xEnt* ent); +xVec3* xEntGetCenter(const xEnt* ent); +xVec3* xEntGetPos(const xEnt* ent); +U32 xEntIsVisible(const xEnt* ent); +void xEntHide(xEnt* ent); +void xEntShow(xEnt* ent); +void xEntInitShadow(xEnt& ent, xEntShadow& shadow); +void xEntReposition(xEnt& ent, const xMat4x3& mat); +bool xEntValidType(U8 type); +void xEntAnimateCollision(xEnt& ent, bool on); +xBox* xEntGetAllEntsBox(); +void xEntSetNostepNormAngle(F32 angle); +void xEntCollideWalls(xEnt* p, xScene* sc, F32 dt); +void xEntCollideCeiling(xEnt* p, xScene* sc, F32 dt); +void xEntCollideFloor(xEnt* p, xScene* sc, F32 dt); +xEnt* xEntCollCheckOneEntNoDepen(xEnt* ent, xScene* sc, void* data); +void xEntCollCheckNPCs(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*)); +void xEntCollCheckDyns(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*)); +void xEntCollCheckStats(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*)); +void xEntCollCheckNPCsByGrid(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*)); +void xEntCollCheckByGrid(xEnt* p, xScene* sc, xEnt* (*hitIt)(xEnt*, xScene*, void*)); +void xEntCollCheckEnv(xEnt* p, xScene* sc); +void xEntEndCollide(xEnt* ent, xScene* sc, F32 dt); +void xEntBeginCollide(xEnt* ent, xScene* sc, F32 dt); +void xEntCollide(xEnt* ent, xScene* sc, F32 dt); +void xEntApplyPhysics(xEnt* ent, xScene* sc, F32 dt); +void xEntMove(xEnt* ent, xScene* sc, F32 dt); +void xEntMotionToMatrix(xEnt* ent, xEntFrame* frame); +void xEntDefaultTranslate(xEnt* ent, xVec3* dpos, xMat4x3* dmat); +void xEntDefaultBoundUpdate(xEnt* ent, xVec3* pos); +void xEntEndUpdate(xEnt* ent, xScene* sc, F32 dt); +void xEntBeginUpdate(xEnt* ent, xScene* sc, F32 dt); +void xEntUpdate(xEnt* ent, xScene* sc, F32 dt); +void xEntRender(xEnt* ent); +void xEntRestorePipeline(xSurface*, RpAtomic* model); +void xEntRestorePipeline(xModelInstance* model); +void xEntSetupPipeline(xSurface* surf, RpAtomic* model); +void xEntSetupPipeline(xModelInstance* model); +void xEntAddToPos(xEnt* ent, const xVec3* v); +xModelInstance* xEntLoadModel(xEnt* ent, RpAtomic* imodel); +void xEntReset(xEnt* ent); +void xEntLoad(xEnt* ent, xSerial* s); +void xEntSave(xEnt* ent, xSerial* s); +void xEntSetup(xEnt* ent); +void xEntInitForType(xEnt* ent); +void xEntInit(xEnt* ent, xEntAsset* asset); +void xEntAddHittableFlag(xEnt* ent); +void xEntSceneExit(); +void xEntSceneInit(); +void xEntSetTimePassed(F32 sec); + +inline void xEntHide(xEnt* ent) { - U32 navigation_mesh_id; - U32 settings; -}; + ent->flags &= ~0x1; +} + +inline void xEntShow(xEnt* ent) +{ + ent->flags |= 0x1; +} + +inline xVec3* xEntGetPos(const xEnt* ent) +{ + return &xModelGetFrame(ent->model)->pos; +} + +inline xVec3* xEntGetCenter(const xEnt* ent) +{ + return (xVec3*)xBoundCenter(&ent->bound); +} #endif diff --git a/src/SB/Core/x/xEntBoulder.cpp b/src/SB/Core/x/xEntBoulder.cpp new file mode 100644 index 0000000..e585d94 --- /dev/null +++ b/src/SB/Core/x/xEntBoulder.cpp @@ -0,0 +1,63 @@ +#include "xMath3.h" +#include "xVec3.h" +#include "xEntBoulder.h" + +#include + +void xEntBoulder_FitToModel(xEntBoulder* ent) +{ + xVec3Copy(&ent->bound.cyl.center, (xVec3*)(&ent->model->Data->boundingSphere.center)); + ent->bound.cyl.r = ent->model->Data->boundingSphere.radius; + xVec3Copy(&ent->localCenter, &ent->bound.cyl.center); + xVec3AddTo(&ent->bound.cyl.center, (xVec3*)&ent->model->Mat->pos); +} + +void xEntBoulder_Init(void* ent, void* asset) +{ + xEntBoulder_Init((xEntBoulder*)ent, (xEntAsset*)asset); +} + +void xEntBoulder_AddInstantForce(xEntBoulder* ent, xVec3* force) +{ + if (ent->update != 0) + { + xVec3* frcptr = &ent->instForce; + xVec3AddTo(frcptr, force); + } +} + +void xEntBoulder_AddForce(xEntBoulder* ent, xVec3* force) +{ + if (ent->update != 0) + { + xVec3* frcptr = &ent->force; + xVec3AddTo(frcptr, force); + } +} + +void xEntBoulder_BUpdate() +{ + //For some reason this seems to be a completely empty function +} + +void xEntBoulder_BUpdate(xEnt*, xVec3*) +{ +} + +void xEntBoulder_Setup(xEntBoulder* ent) +{ + ent->asset->redMult = 0.0f; + ent->asset->greenMult = 0.0f; + ent->asset->blueMult = 0.0f; + + if (ent->model != NULL) + { + ent->asset->seeThru = ent->model->Alpha; + } + else + { + ent->asset->seeThru = 1.0f; + } + + xEntSetup(ent); +} diff --git a/src/SB/Core/x/xEntBoulder.h b/src/SB/Core/x/xEntBoulder.h new file mode 100644 index 0000000..4564ba3 --- /dev/null +++ b/src/SB/Core/x/xEntBoulder.h @@ -0,0 +1,87 @@ +#ifndef XENTBOULDER_H +#define XENTBOULDER_H + +#include "xEnt.h" +#include "xDynAsset.h" +#include "xShadowSimple.h" + +struct xEntBoulderAsset +{ + F32 gravity; + F32 mass; + F32 bounce; + F32 friction; + F32 statFric; + F32 maxVel; + F32 maxAngVel; + F32 stickiness; + F32 bounceDamp; + U32 flags; + F32 killtimer; + U32 hitpoints; + U32 soundID; + F32 volume; + F32 minSoundVel; + F32 maxSoundVel; + F32 innerRadius; + F32 outerRadius; +}; + +struct xEntBoulder : xEnt +{ + xEntBoulderAsset* basset; + xShadowSimpleCache simpShadow_embedded; + xEntShadow entShadow_embedded; + xVec3 localCenter; + xVec3 vel; + xVec3 rotVec; + xVec3 force; + xVec3 instForce; + F32 angVel; + F32 timeToLive; + S32 hitpoints; + F32 lastRolling; + U32 rollingID; + U8 collis_chk; + U8 collis_pen; + U8 pad1[2]; +}; + +struct xBoulderGeneratorAsset : xDynAsset +{ + U32 object; + xVec3 offset; + F32 offsetRand; + xVec3 initvel; + F32 velAngleRand; + F32 velMagRand; + xVec3 initaxis; + F32 angvel; +}; + +struct xBoulderGenerator : xBase +{ + xBoulderGeneratorAsset* bgasset; + S32 numBoulders; + S32 nextBoulder; + xEntBoulder** boulderList; + S32* boulderAges; + U32 isMarker; + void* objectPtr; + F32 lengthOfInitVel; + xVec3 perp1; + xVec3 perp2; +}; + +void xEntBoulder_Init(void* ent, void* asset); +void xEntBoulder_Init(xEntBoulder* ent, xEntAsset* asset); +void xEntBoulder_BubbleBowl(F32 multiplier); +void xEntBoulder_Setup(xEntBoulder* ent); +void xEntBoulder_Reset(xEntBoulder* ent, xScene* scene); +void xEntBoulder_RealBUpdate(xEnt* ent, xVec3* pos); +void xEntBoulder_Kill(xEntBoulder* ent); +void xBoulderGenerator_Init(xBase& data, xDynAsset& asset, size_t); +void xBoulderGenerator_Init(xBoulderGenerator* bg, xBoulderGeneratorAsset* asset); +void xBoulderGenerator_Init(xBase& data, xDynAsset& asset); + +#endif diff --git a/src/SB/Core/x/xEntDrive.cpp b/src/SB/Core/x/xEntDrive.cpp new file mode 100644 index 0000000..03ca310 --- /dev/null +++ b/src/SB/Core/x/xEntDrive.cpp @@ -0,0 +1,422 @@ +#include "xEntDrive.h" + +#include "xMath.h" + +#include + +void xEntDriveInit(xEntDrive* drv, xEnt* driven) +{ + if (drv == NULL) + { + return; + } + + drv->flags = 0; + drv->driven = driven; + drv->driver = NULL; + drv->s = 0.0f; + drv->tm = 0.0f; + drv->tmr = 0.0f; + drv->odriver = NULL; + drv->os = 0.0f; + drv->otm = 0.0f; + drv->otmr = 0.0f; +} + +void xEntDriveMount(xEntDrive* drv, xEnt* driver, F32 mt, const xCollis* coll) +{ + if (drv->driven == NULL || drv->driven->frame == NULL || driver == NULL || + driver->frame == NULL) + { + xEntDriveInit(drv, drv->driven); + return; + } + drv->dloc = 0.0f; + if (driver == drv->odriver && drv->os) + { + drv->driver = driver; + driver->driving_count++; + if (mt < 0.0f) + { + drv->s = 1.0f; + drv->tmr = 0.0f; + } + else + { + drv->s = drv->os; + drv->tmr = mt * (1.0f - drv->s); + } + + drv->tm = mt; + drv->odriver = NULL; + drv->os = 0.0f; + drv->otm = 0.0f; + drv->otmr = 0.0f; + } + else + { + drv->driver = driver; + driver->driving_count++; + if (mt < 0.0f) + { + drv->s = 1.0f; + drv->tmr = 0.0f; + } + else + { + drv->s = 0.0f; + drv->tmr = mt; + } + drv->tm = mt; + } + + xVec3 euler; + xMat3x3 a_descaled; + if (drv->flags & 1) + { + { + F32 len2 = SQR(drv->driver->frame->mat.right.x) + SQR(drv->driver->frame->mat.right.y) + + SQR(drv->driver->frame->mat.right.z); + if (xabs(len2 - 1) <= 0.00001f) + { + a_descaled.right.x = drv->driver->frame->mat.right.x; + a_descaled.right.y = drv->driver->frame->mat.right.y; + a_descaled.right.z = drv->driver->frame->mat.right.z; + } + else if (xabs(len2) <= 0.00001f) + { + a_descaled.right.x = 0.0f; + a_descaled.right.y = 1.0f; + a_descaled.right.z = 0.0f; + } + else + { + F32 len_inv = 1.0f / xsqrt(len2); + a_descaled.right.x = drv->driver->frame->mat.right.x * len_inv; + a_descaled.right.y = drv->driver->frame->mat.right.y * len_inv; + a_descaled.right.z = drv->driver->frame->mat.right.z * len_inv; + } + } + + { + F32 len2 = SQR(drv->driver->frame->mat.up.x) + SQR(drv->driver->frame->mat.up.y) + + SQR(drv->driver->frame->mat.up.z); + if (xabs(len2 - 1.0f) <= 0.00001f) + { + a_descaled.up.x = drv->driver->frame->mat.up.x; + a_descaled.up.y = drv->driver->frame->mat.up.y; + a_descaled.up.z = drv->driver->frame->mat.up.z; + } + else if (xabs(len2) <= 0.00001f) + { + a_descaled.up.x = 0.0f; + a_descaled.up.y = 1.0f; + a_descaled.up.z = 0.0f; + } + else + { + F32 len_inv = 1.0f / xsqrt(len2); + a_descaled.up.x = drv->driver->frame->mat.up.x * len_inv; + a_descaled.up.y = drv->driver->frame->mat.up.y * len_inv; + a_descaled.up.z = drv->driver->frame->mat.up.z * len_inv; + } + } + + { + F32 len2 = SQR(drv->driver->frame->mat.at.x) + SQR(drv->driver->frame->mat.at.y) + + SQR(drv->driver->frame->mat.at.z); + if (xabs(len2 - 1.0f) <= 0.00001f) + { + a_descaled.at.x = drv->driver->frame->mat.at.x; + a_descaled.at.y = drv->driver->frame->mat.at.y; + a_descaled.at.z = drv->driver->frame->mat.at.z; + } + else if (xabs(len2) <= 0.00001f) + { + a_descaled.at.x = 0.0f; + a_descaled.at.y = 1.0f; + a_descaled.at.z = 0.0f; + } + else + { + F32 len_inv = 1.0f / xsqrt(len2); + a_descaled.at.x = drv->driver->frame->mat.at.x * len_inv; + a_descaled.at.y = drv->driver->frame->mat.at.y * len_inv; + a_descaled.at.z = drv->driver->frame->mat.at.z * len_inv; + } + } + xMat3x3GetEuler(&a_descaled, &euler); + drv->yaw = euler.x; + } + + if (coll != NULL && coll->flags & 0x2000) + { + drv->flags |= 0x2; + + *(xCollis::tri_data*)&drv->tri = coll->tri; + drv->tri.loc = xCollisTriHit(drv->tri, *driver->model); + xMat4x3Tolocal(&drv->tri.loc, &drv->driver->frame->mat, &drv->tri.loc); + drv->tri.coll = coll; + } + + xVec3Copy(&drv->q, &drv->driven->frame->mat.pos); + xMat4x3Tolocal(&drv->p, &drv->driver->frame->mat, &drv->q); +} + +void xEntDriveDismount(xEntDrive* drv, F32 dmt) +{ + if (drv == NULL) + { + return; + } + + if (drv->driver == NULL) + { + return; + } + + if (drv->driven == NULL || drv->driven->frame == NULL || drv->driver->frame == NULL) + { + xEntDriveInit(drv, drv->driven); + return; + } + drv->odriver = drv->driver; + drv->os = drv->s; + drv->otm = dmt; + drv->otmr = dmt * drv->os; + if (drv->driver != NULL) + { + drv->driver->driving_count--; + } + + drv->driver = NULL; + drv->s = 0.0f; + drv->tm = 0.0f; + drv->tmr = 0.0f; + drv->flags &= ~2; + xVec3Copy(&drv->q, &drv->driven->frame->mat.pos); + xMat4x3Tolocal(&drv->op, &drv->odriver->frame->mat, &drv->q); +} + +void xEntDriveUpdate(xEntDrive* drv, xScene* s, F32 dt, const xCollis* coll) +{ + if ((drv != NULL && (drv->odriver != NULL || drv->driver != NULL))) + { + if (drv->driven == NULL || drv->driven->frame == NULL || + (drv->odriver != NULL && drv->odriver->frame == NULL)) + { + xEntDriveInit(drv, drv->driven); + return; + } + + if (drv->otmr > 0.0f) + { + drv->otmr -= dt; + if (drv->otmr <= 0.0f) + { + drv->os = 0.0f; + drv->otmr = 0.0f; + } + else + { + drv->os = drv->otmr / drv->otm; + } + } + + if (drv->tmr > 0.0f) + { + drv->tmr -= dt; + if (drv->tmr <= 0.0f) + { + drv->s = 1.0f; + drv->tmr = 0.0f; + } + else + { + drv->s = 1.0f - drv->tmr / drv->tm; + } + } + + if (!drv->os && !drv->s) + { + return; + } + + xVec3 euler; + xMat3x3 rot; + xMat3x3 a_descaled; + if (drv->s && drv->flags & 1) + { + if (drv->driver == NULL || drv->driver->frame == NULL) + { + xEntDriveInit(drv, drv->driven); + return; + } + + { + F32 len2 = SQR(drv->driver->frame->mat.right.x) + + SQR(drv->driver->frame->mat.right.y) + + SQR(drv->driver->frame->mat.right.z); + if (xabs(len2 - 1) <= 0.00001f) + { + a_descaled.right.x = drv->driver->frame->mat.right.x; + a_descaled.right.y = drv->driver->frame->mat.right.y; + a_descaled.right.z = drv->driver->frame->mat.right.z; + } + else if (xabs(len2) <= 0.00001f) + { + a_descaled.right.x = 0.0f; + a_descaled.right.y = 1.0f; + a_descaled.right.z = 0.0f; + } + else + { + F32 len_inv = 1.0f / xsqrt(len2); + a_descaled.right.x = drv->driver->frame->mat.right.x * len_inv; + a_descaled.right.y = drv->driver->frame->mat.right.y * len_inv; + a_descaled.right.z = drv->driver->frame->mat.right.z * len_inv; + } + } + + { + F32 len2 = SQR(drv->driver->frame->mat.up.x) + SQR(drv->driver->frame->mat.up.y) + + SQR(drv->driver->frame->mat.up.z); + if (xabs(len2 - 1.0f) <= 0.00001f) + { + a_descaled.up.x = drv->driver->frame->mat.up.x; + a_descaled.up.y = drv->driver->frame->mat.up.y; + a_descaled.up.z = drv->driver->frame->mat.up.z; + } + else if (xabs(len2) <= 0.00001f) + { + a_descaled.up.x = 0.0f; + a_descaled.up.y = 1.0f; + a_descaled.up.z = 0.0f; + } + else + { + F32 len_inv = 1.0f / xsqrt(len2); + a_descaled.up.x = drv->driver->frame->mat.up.x * len_inv; + a_descaled.up.y = drv->driver->frame->mat.up.y * len_inv; + a_descaled.up.z = drv->driver->frame->mat.up.z * len_inv; + } + } + + { + F32 len2 = SQR(drv->driver->frame->mat.at.x) + SQR(drv->driver->frame->mat.at.y) + + SQR(drv->driver->frame->mat.at.z); + if (xabs(len2 - 1.0f) <= 0.00001f) + { + a_descaled.at.x = drv->driver->frame->mat.at.x; + a_descaled.at.y = drv->driver->frame->mat.at.y; + a_descaled.at.z = drv->driver->frame->mat.at.z; + } + else if (xabs(len2) <= 0.00001f) + { + a_descaled.at.x = 0.0f; + a_descaled.at.y = 1.0f; + a_descaled.at.z = 0.0f; + } + else + { + F32 len_inv = 1.0f / xsqrt(len2); + a_descaled.at.x = drv->driver->frame->mat.at.x * len_inv; + a_descaled.at.y = drv->driver->frame->mat.at.y * len_inv; + a_descaled.at.z = drv->driver->frame->mat.at.z * len_inv; + } + } + xMat3x3GetEuler(&a_descaled, &euler); + xMat3x3RotY(&rot, drv->s * (euler.x - drv->yaw)); + xMat3x3Mul(&drv->driven->frame->mat, &drv->driven->frame->mat, &rot); + drv->yaw = euler.x; + } + + drv->dloc = 0.0f; + xVec3 newq; + if (drv->os) + { + if (drv->odriver == NULL || drv->odriver->frame == NULL) + { + xEntDriveInit(drv, drv->driven); + return; + } + + xMat4x3Toworld(&newq, &drv->odriver->frame->mat, &drv->op); + xVec3Sub(&drv->driven->frame->dpos, &newq, &drv->q); + xVec3SMulBy(&drv->driven->frame->dpos, drv->os); + xVec3AddTo(&drv->driven->frame->mat.pos, &drv->driven->frame->dpos); + drv->dloc += drv->driven->frame->dpos; + } + + if (drv->s) + { + if (drv->driver == NULL || drv->driver->frame == NULL) + { + xEntDriveInit(drv, drv->driven); + return; + } + + if (drv->flags & 0x2) + { + xModelInstance& m = *drv->driver->model; + if (xModelAnimCollDirty(m)) + { + xModelAnimCollRefresh(m); + } + xVec3 world_loc; + xMat4x3Toworld(&world_loc, &drv->driver->frame->mat, &drv->tri.loc); + + xVec3 new_loc; + new_loc = xCollisTriHit(drv->tri, m); + drv->driven->frame->dpos = new_loc - world_loc; + + if (drv->tri.index != drv->tri.coll->tri.index || + !(xabs(drv->tri.r - drv->tri.coll->tri.r) <= 0.1f) || + !(xabs(drv->tri.d - drv->tri.coll->tri.d) <= 0.1f)) + { + *(xCollis::tri_data*)&drv->tri = drv->tri.coll->tri; + } + + xMat4x3 oldmat = *(xMat4x3*)m.Mat; + *(xMat4x3*)m.Mat = drv->driver->frame->mat; + + drv->tri.loc = xCollisTriHit(drv->tri, m); + xMat4x3Tolocal(&drv->tri.loc, &drv->driver->frame->mat, &drv->tri.loc); + *(xMat4x3*)m.Mat = oldmat; + } + else + { + xMat4x3Toworld(&newq, &drv->driver->frame->mat, &drv->p); + xVec3Sub(&drv->driven->frame->dpos, &newq, &drv->q); + } + + drv->driven->frame->dpos *= drv->s; + drv->dloc += drv->driven->frame->dpos; + drv->driven->frame->mat.pos += drv->driven->frame->dpos; + if (drv->driven->model != NULL) + { + *(xVec3*)&drv->driven->model->Mat->pos = drv->driven->frame->mat.pos; + } + } + + xVec3Copy(&drv->q, &drv->driven->frame->mat.pos); + if (drv->os) + { + if (drv->odriver == NULL || drv->odriver->frame == NULL) + { + xEntDriveInit(drv, drv->driven); + return; + } + xMat4x3Tolocal(&drv->op, &drv->odriver->frame->mat, &drv->q); + } + if (drv->s) + { + if (drv->driver == NULL || drv->driver->frame == NULL) + { + xEntDriveInit(drv, drv->driven); + return; + } + xMat4x3Tolocal(&drv->p, &drv->driver->frame->mat, &drv->q); + } + } +} diff --git a/src/SB/Core/x/xEntDrive.h b/src/SB/Core/x/xEntDrive.h new file mode 100644 index 0000000..b2a6f6b --- /dev/null +++ b/src/SB/Core/x/xEntDrive.h @@ -0,0 +1,41 @@ +#ifndef XENTDRIVE_H +#define XENTDRIVE_H + +#include "xEnt.h" +#include "xCollide.h" + +struct xEntDrive +{ + struct tri_data : xCollis::tri_data + { + xVec3 loc; + F32 yaw; + const xCollis* coll; + }; + + U32 flags; + F32 otm; + F32 otmr; + F32 os; + F32 tm; + F32 tmr; + F32 s; + xEnt* odriver; + xEnt* driver; + xEnt* driven; + xVec3 op; + xVec3 p; + xVec3 q; + F32 yaw; + xVec3 dloc; + + // 0x5c + tri_data tri; +}; + +void xEntDriveInit(xEntDrive* drv, xEnt* driven); +void xEntDriveMount(xEntDrive* drv, xEnt* driver, F32 mt, const xCollis* coll); +void xEntDriveDismount(xEntDrive* drv, F32 dmt); +void xEntDriveUpdate(xEntDrive* drv, xScene* s, F32 dt, xCollis* coll); + +#endif diff --git a/src/SB/Core/x/xEntMotion.cpp b/src/SB/Core/x/xEntMotion.cpp new file mode 100644 index 0000000..8b51220 --- /dev/null +++ b/src/SB/Core/x/xEntMotion.cpp @@ -0,0 +1,224 @@ +#include "xDebug.h" +#include "xEntMotion.h" +#include "xMath.h" + +#include + +// Artificial +enum en_MOTIONTYPE +{ + MOTION_TYPE_EXRT, + MOTION_TYPE_ORBT, + MOTION_TYPE_SPLN, + MOTION_TYPE_MVPT, + MOTION_TYPE_MECH, + MOTION_TYPE_PEND +}; + +void xEntMotionInit(xEntMotion* a, xEnt* b, xEntMotionAsset* c) +{ + a->asset = c; + a->type = c->type; + a->flags = c->flags; + + if (a->type == MOTION_TYPE_EXRT) + { + xVec3Copy(&a->er.a, &c->er.ret_pos); + xVec3Add(&a->er.b, &c->er.ret_pos, &c->er.ext_dpos); + + a->er.et = c->er.ext_tm; + a->er.wet = c->er.ext_wait_tm; + a->er.rt = c->er.ret_tm; + a->er.wrt = c->er.ret_wait_tm; + + if (a->er.p <= 0) + { + a->er.p = 10.0f; + } + + a->er.brt = a->er.et + a->er.wet; + a->er.ert = a->er.brt + a->er.rt; + a->er.p = a->er.ert + a->er.wrt; + } + else if (a->type == MOTION_TYPE_ORBT) + { + xVec3Copy((xVec3*)(&a->er.b), &c->er.ret_pos); + + a->orb.a = c->orb.w; + a->orb.b = c->orb.h; + + if (c->orb.period <= 0.0f) + { + c->orb.period = 10.0f; + } + + a->orb.p = c->orb.period; + a->orb.w = (2 * PI) / c->orb.period; + } + else if (a->type == MOTION_TYPE_MVPT) + { + // literally nothing + } + else if (a->type == MOTION_TYPE_PEND) + { + if (c->pen.period <= 1e-5f) + { + c->pen.period = 0; + } + + a->pen.w = (2 * PI) / c->pen.period; + } + else if (a->type == MOTION_TYPE_MECH) + { + if (c->mp.speed < 1e-5f) + { + c->mp.speed = 0; + } + + if (c->mech.sld_acc_tm + c->mech.sld_dec_tm > c->mech.sld_tm) + { + c->mech.sld_dec_tm = c->mech.sld_acc_tm = c->mech.sld_tm * 0.5f; + } + + if (c->mech.rot_tm < 3.0f) + { + c->mech.rot_tm = 1.0f; + } + + if (c->mech.type == 2) + { + if (c->mech.rot_tm != c->mech.sld_tm) + { + c->mech.rot_tm = c->mech.sld_tm; + } + } + if (c->mech.rot_acc_tm + c->mech.rot_dec_tm > c->mech.rot_tm) + { + c->mech.rot_dec_tm = c->mech.rot_acc_tm = c->mech.rot_tm * 0.5f; + } + } + + a->owner = b; + a->target = NULL; + + xEntMotionDebugAdd(a); +} + +void xEntMechForward(xEntMotion* motion) +{ + xEntMotionMechData* mech = &(motion->asset->mech); + xEntMotionAsset* mkasst = motion->asset; + + xEntMotionRun(motion); + + if ((motion->mech.state != 0) && (motion->mech.state != 1) && (motion->mech.state != 2)) + { + if (motion->mech.state == 3) + { + motion->mech.ss = -motion->mech.ss; + motion->mech.sr = -motion->mech.sr; + motion->tmr = mkasst->mech.sld_tm - motion->tmr; + motion->mech.state = 0; + } + else if (motion->mech.state == 4) + { + motion->mech.ss = -motion->mech.ss; + motion->mech.sr = -motion->mech.sr; + motion->tmr = mkasst->mech.rot_tm - motion->tmr; + motion->mech.state = 1; + } + else if ((motion->mech.state != 5) && (motion->mech.state != 6) && + (motion->mech.state == 7)) + { + motion->mech.ss = -motion->mech.ss; + motion->mech.sr = -motion->mech.sr; + motion->tmr = 0.0f; + + if ((mech->type == 0) || (mech->type == 2) || (mech->type == 4)) + { + motion->mech.state = 0; + } + else + { + motion->mech.state = 1; + } + } + } +} + +void xEntMechReverse(xEntMotion* motion) +{ + xEntMotionMechData* mech = &(motion->asset->mech); + xEntMotionAsset* mkasst = motion->asset; + + xEntMotionRun(motion); + + if (motion->mech.state == 0) + { + motion->mech.ss = -motion->mech.ss; + motion->mech.sr = -motion->mech.sr; + motion->tmr = mkasst->mech.sld_tm - motion->tmr; + motion->mech.state = 3; + } + else if (motion->mech.state == 1) + { + motion->mech.ss = -motion->mech.ss; + motion->mech.sr = -motion->mech.sr; + motion->tmr = mkasst->mech.rot_tm - motion->tmr; + motion->mech.state = 4; + } + else if ((motion->mech.state != 2) && (motion->mech.state != 3) && (motion->mech.state != 4) && + (motion->mech.state != 5) && (motion->mech.state == 6)) + { + motion->mech.ss = -motion->mech.ss; + motion->mech.sr = -motion->mech.sr; + motion->tmr = 0.0f; + + if ((mech->type == 0) || (mech->type == 2) || (mech->type == 4)) + { + motion->mech.state = 3; + } + else + { + motion->mech.state = 4; + } + } +} + +static xEntMotion** dbg_xems; +static U16 dbg_num; +static U16 dbg_num_allocd; +static S16 dbg_idx; + +void xEntMotionDebugCB(); + +// Non-matching: scheduling +void xEntMotionDebugInit(U16 num_xems) +{ + if (num_xems != 0) + { + xDebugModeAdd("DBG_XENTMOTION", xEntMotionDebugCB); + dbg_num = 0; + dbg_xems = (xEntMotion**)xMemAlloc(gActiveHeap, num_xems << 2, 0); + dbg_num_allocd = num_xems; + dbg_idx = 0; + } +} + +// This scheduling is absolutely shambolic +void xEntMotionDebugAdd(xEntMotion* motion) +{ + if (dbg_num < dbg_num_allocd) + { + dbg_num++; + dbg_xems[dbg_num] = motion; + } +} + +void xEntMotionDebugExit() +{ + dbg_num = 0; + dbg_xems = NULL; + dbg_num_allocd = 0; + dbg_idx = -1; +} diff --git a/src/SB/Core/x/xEntMotion.h b/src/SB/Core/x/xEntMotion.h new file mode 100644 index 0000000..379e5b3 --- /dev/null +++ b/src/SB/Core/x/xEntMotion.h @@ -0,0 +1,183 @@ +#ifndef XENTMOTION_H +#define XENTMOTION_H + +#include "xEnt.h" +#include "xMovePoint.h" +#include "xColor.h" + +struct xEntMotionERData +{ + xVec3 ret_pos; + xVec3 ext_dpos; + F32 ext_tm; + F32 ext_wait_tm; + F32 ret_tm; + F32 ret_wait_tm; +}; + +struct xEntMotionOrbitData +{ + xVec3 center; + F32 w; + F32 h; + F32 period; +}; + +struct xEntMotionSplineData +{ + S32 unknown; +}; + +struct xEntMotionMPData +{ + U32 flags; + U32 mp_id; + F32 speed; +}; + +struct xEntMotionMechData +{ + U8 type; + U8 flags; + U8 sld_axis; + U8 rot_axis; + F32 sld_dist; + F32 sld_tm; + F32 sld_acc_tm; + F32 sld_dec_tm; + F32 rot_dist; + F32 rot_tm; + F32 rot_acc_tm; + F32 rot_dec_tm; + F32 ret_delay; + F32 post_ret_delay; +}; + +struct xEntMotionPenData +{ + U8 flags; + U8 plane; + U8 pad[2]; + F32 len; + F32 range; + F32 period; + F32 phase; +}; + +struct xEntMotionAsset +{ + U8 type; + U8 use_banking; + U16 flags; + union + { + xEntMotionERData er; + xEntMotionOrbitData orb; + xEntMotionSplineData spl; + xEntMotionMPData mp; + xEntMotionMechData mech; + xEntMotionPenData pen; + }; +}; + +struct xEntERData +{ + xVec3 a; + xVec3 b; + xVec3 dir; + F32 et; + F32 wet; + F32 rt; + F32 wrt; + F32 p; + F32 brt; + F32 ert; + S32 state; +}; + +struct xEntOrbitData +{ + xVec3 orig; + xVec3 c; + F32 a; + F32 b; + F32 p; + F32 w; +}; + +struct xEntSplineData +{ + S32 unknown; +}; + +struct xEntMPData +{ + F32 curdist; + F32 speed; + xMovePoint* dest; + xMovePoint* src; + xSpline3* spl; + F32 dist; + U32 padalign; + xQuat aquat; + xQuat bquat; +}; + +struct xEntMechData +{ + xVec3 apos; + xVec3 bpos; + xVec3 dir; + F32 arot; + F32 brot; + F32 ss; + F32 sr; + S32 state; + F32 tsfd; + F32 trfd; + F32 tsbd; + F32 trbd; + F32* rotptr; +}; + +struct xEntPenData +{ + xVec3 top; + F32 w; + xMat4x3 omat; +}; + +struct xEntMotion // Size: 0x70 +{ + xEntMotionAsset* asset; + U8 type; + U8 pad; + U16 flags; + F32 t; + F32 tmr; + F32 d; + union + { + xEntERData er; + xEntOrbitData orb; + xEntSplineData spl; + xEntMPData mp; + xEntMechData mech; + xEntPenData pen; + }; + xEnt* owner; + xEnt* target; +}; + +void xEntMotionInit(xEntMotion* motion, xEnt*, xEntMotionAsset* asset); +void xEntMotionReset(xEntMotion* motion, xScene* sc); +void xEntMotionMove(xEntMotion* motion, xScene* sc, F32 dt, xEntFrame* frame); +void xEntMotionTranslate(xEntMotion* motion, const xVec3* dpos, xMat4x3* dmat); +void xEntMotionDebugInit(U16 num_xems); +void xEntMotionDebugAdd(xEntMotion*); +void xEntMotionDebugExit(); +void xEntMotionStop(xEntMotion* motion); +void xEntMotionRun(xEntMotion* motion); +U32 xEntMotionIsStopped(const xEntMotion* motion); + +#endif diff --git a/src/SB/Core/x/xEnv.cpp b/src/SB/Core/x/xEnv.cpp new file mode 100644 index 0000000..6899de6 --- /dev/null +++ b/src/SB/Core/x/xEnv.cpp @@ -0,0 +1,38 @@ +#include "xEnv.h" + +xEnv* gCurXEnv; + +void xEnvLoadBsp(xEnv* env, const void* data, U32 datasize, S32 dataType) +{ + if (dataType == 0) + { + env->geom = &env->ienv; + } + + iEnvLoad(env->geom, data, datasize, dataType); + gCurXEnv = env; +} + +void xEnvSetup(xEnv* env) +{ + iEnvDefaultLighting(env->geom); + env->lightKit = NULL; + gCurXEnv = env; +} + +void xEnvFree(xEnv* env) +{ + if (env->geom != NULL) + { + iEnvFree(env->geom); + env->geom = NULL; + } +} + +void xEnvRender(xEnv* env) +{ + if (env->geom != NULL) + { + iEnvRender(env->geom); + } +} diff --git a/src/SB/Core/x/xEnv.h b/src/SB/Core/x/xEnv.h index e10a85f..a64c5b1 100644 --- a/src/SB/Core/x/xEnv.h +++ b/src/SB/Core/x/xEnv.h @@ -1,37 +1,9 @@ #ifndef XENV_H #define XENV_H -#include "xModel.h" -#include "xJSP.h" - -struct iEnvMatOrder -{ - U16 jspIndex; - U16 nodeIndex; - S32 matGroup; - RpAtomic* atomic; - xJSPNodeInfo* nodeInfo; -}; - -struct iEnv -{ - RpWorld* world; - RpWorld* collision; - RpWorld* fx; - RpWorld* camera; - S32 jsp_count; - U32* jsp_aid; - xJSPHeader** jsp_list; - xBox* jsp_bound; - S32* jsp_visibilityCount; - S32 jspMatOrderCount; - iEnvMatOrder* jspMatOrderList; - RpLight* light[2]; - RwFrame* light_frame[2]; - S32 memlvl; - U16 numOpaque; - U16 numTransparent; -}; +#include "iEnv.h" +#include "xLightKit.h" +#include "xBase.h" struct xEnv { @@ -40,4 +12,28 @@ struct xEnv xLightKit* lightKit; }; +struct xEnvAsset : xBaseAsset +{ + U32 bspAssetID; + U32 startCameraAssetID; + U32 climateFlags; + F32 climateStrengthMin; + F32 climateStrengthMax; + U32 bspLightKit; + U32 objectLightKit; + F32 padF1; + U32 bspCollisionAssetID; + U32 bspFXAssetID; + U32 bspCameraAssetID; + U32 bspMapperID; + U32 bspMapperCollisionID; + U32 bspMapperFXID; + F32 loldHeight; +}; + +void xEnvLoadBsp(xEnv* env, const void* data, U32 datasize, S32 dataType); +void xEnvFree(xEnv* env); +void xEnvSetup(xEnv* env); +void xEnvRender(xEnv* env); + #endif diff --git a/src/SB/Core/x/xEvent.cpp b/src/SB/Core/x/xEvent.cpp new file mode 100644 index 0000000..e1b07c7 --- /dev/null +++ b/src/SB/Core/x/xEvent.cpp @@ -0,0 +1,138 @@ +#include + +#include "xEvent.h" +#include "xString.h" +#include "xstransvc.h" + +#include "zScene.h" + +char zEventLogBuf[256][20]; + +void zEntEvent(char* to, U32 toEvent) +{ + U32 id = xStrHash(to); + xBase* sendTo = zSceneFindObject(id); + + if (sendTo) + { + zEntEvent(sendTo, toEvent); + } +} + +void zEntEvent(U32 toID, U32 toEvent) +{ + xBase* sendTo = zSceneFindObject(toID); + + if (sendTo) + { + zEntEvent(sendTo, toEvent); + } +} + +void zEntEvent(U32 toID, U32 toEvent, F32 toParam0, F32 toParam1, F32 toParam2, + F32 toParam3) +{ + xBase* sendTo; + F32 toParam[4]; + + toParam[0] = toParam0; + toParam[1] = toParam1; + toParam[2] = toParam2; + toParam[3] = toParam3; + + sendTo = zSceneFindObject(toID); + + if (sendTo) + { + zEntEvent(sendTo, toEvent, toParam); + } +} + +void zEntEvent(xBase* to, U32 toEvent) +{ + zEntEvent(NULL, 0, to, toEvent, NULL, NULL, 0); +} + +void zEntEvent(xBase* to, U32 toEvent, F32 toParam0, F32 toParam1, F32 toParam2, + F32 toParam3) +{ + F32 toParam[4]; + + toParam[0] = toParam0; + toParam[1] = toParam1; + toParam[2] = toParam2; + toParam[3] = toParam3; + + zEntEvent(to, toEvent, toParam, NULL); +} + +void zEntEvent(xBase* to, U32 toEvent, const F32* toParam) +{ + zEntEvent(NULL, 0, to, toEvent, toParam, NULL, 0); +} + +void zEntEvent(xBase* to, U32 toEvent, const F32* toParam, xBase* toParamWidget) +{ + zEntEvent(NULL, 0, to, toEvent, toParam, toParamWidget, 0); +} + +void zEntEvent(xBase* from, xBase* to, U32 toEvent) +{ + zEntEvent(from, 0, to, toEvent, NULL, NULL, 0); +} + +void zEntEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam) +{ + zEntEvent(from, 0, to, toEvent, toParam, NULL, 0); +} + +void zEntEvent(xBase* from, U32 fromEvent, xBase* to, U32 toEvent, const F32* toParam, + xBase* toParamWidget, S32 forceEvent) +{ + if (toEvent == eEventDisable) + { + xBaseDisable(to); + } + else if (toEvent == eEventEnable) + { + xBaseEnable(to); + } + + if (to->eventFunc && (xBaseIsEnabled(to) || forceEvent)) + { + to->eventFunc(from, to, toEvent, toParam, toParamWidget); + } + + if (xBaseIsEnabled(to) && to->linkCount) + { + xLinkAsset* idx = to->link; + + for (S32 i = 0; i < to->linkCount; i++, idx++) + { + if (toEvent == idx->srcEvent) + { + if (!idx->chkAssetID || (from && idx->chkAssetID == from->id)) + { + xBase* sendTo = zSceneFindObject(idx->dstAssetID); + + if (sendTo) + { + xBase* b = NULL; + + if (idx->paramWidgetAssetID) + { + b = zSceneFindObject(idx->paramWidgetAssetID); + + if (!b) + { + b = (xBase*)xSTFindAsset(idx->paramWidgetAssetID, NULL); + } + } + + zEntEvent(to, toEvent, sendTo, idx->dstEvent, idx->param, b, 0); + } + } + } + } + } +} diff --git a/src/SB/Core/x/xMail.h b/src/SB/Core/x/xEvent.h similarity index 56% rename from src/SB/Core/x/xMail.h rename to src/SB/Core/x/xEvent.h index 775c85e..87b739b 100644 --- a/src/SB/Core/x/xMail.h +++ b/src/SB/Core/x/xEvent.h @@ -1,5 +1,7 @@ -#ifndef XMAIL_H -#define XMAIL_h +#ifndef XEVENT_H +#define XEVENT_H + +#include "xBase.h" enum en_xEventTags { @@ -182,14 +184,14 @@ enum en_xEventTags eEventAttackOn, eEventAttackOff, eEventDrop, - eEventUIAddChar, - eEventUIDelChar, - eEventUIStringEmpty, - eEventUIStringFull, - eEventUISendStringAsCheat, - eEventUISetMaxChars, - eEventUICheatOK, - eEventUICheatBad, + eEventVilReport_StartingIdle, + eEventVilReport_StartingSleep, + eEventVilReport_StartingGuard, + eEventVilReport_StartingPatrol, + eEventVilReport_StartingDazed, + eEventVilReport_StartingLook, + eEventVilReport_StartingListen, + eEventVilReport_StartingInvestigate, eEventVilReport_StartingChase, eEventVilReport_StartingAttack, eEventVilReport_StartingRetreat, @@ -210,11 +212,11 @@ enum en_xEventTags eEventAccelerate, eEventMoveToTarget, eEventSwingerFollow, - eEventImpact, - eEventStartTimer, - eEventFinishedTimer, - eEventUIReset, - eEventSetScaleFactor, + eEventShaggyMount, + eEventShaggyWitchDrop, + eEventShaggySwap, + eEventShaggyState, + eEventShaggyAction, eEventEnterEntity, eEventExitEntity, eEventEnterEntityFLAG, @@ -223,23 +225,23 @@ enum en_xEventTags eEventFollowTarget, eEventFaceTarget, eEventWatchTarget, - eEventCarChangeLaneRight, - eEventCarChangeLaneLeft, - eEventCarStart, - eEventCarSetSwerveMode, - eEventIncreaseSpeed, - eEventDecreaseSpeed, + eEventShaggyCollideOnly, + eEventShaggy1_ThrowTarget, + eEventShaggy8_CallEnable, + eEventShaggy8_CallDisable, + eEventShaggy8_SetMagnet, + eEventShaggy8_ClearMagnet, eEventStartMoving, eEventStopMoving, eEventSwoosh, - eEventTurretDestroyed, - eEventNPCSpeakStop, - eEventStartRumbleEffect, - eEventNavigateTo, - eEventNPCSpeakStart, - eEventNPCAlert, - eEventNPCPatrolDelay, - eEventNPCScrambleActionEnd, + eEventShaggySetDown, + eEventShaggyGrabEnable, + eEventShaggyGrabDisable, + eEventShaggyGrabbed, + eEventShaggyThrown, + eEventVilDoAction, + eEventGangDoBossAction, + eEventVilFakeChaseOn, eEventVilFakeChaseOff, eEventBossMMPushButton, eEventVilReport_DecayComplete, @@ -258,35 +260,35 @@ enum en_xEventTags eEventTranslucentOn, eEventTranslucentOff, eEventTranslucentToggle, - eEventZipLineEnvDamage, + eEventVilGangTalkOn, eEventVilGangTalkOff, eEventGivePowerUp, - eEventRaceTimerReset, - eEventFireCruiseBubble, - eEventCarSuccessAnimPlay, - eEventCarFailureAnimPlay, + eEventUnlockR001, + eEventUnlockS001, + eEventUnlockE001, + eEventUnlockF001, eEventDisableGroupContents, - eEventNPCCharge, + eEventShaggyPhysHack, eEventOccludeOn, eEventOccludeOff, - eEventRaceTimerPause, - eEventRaceTimerResume, - eEventRaceTimerSetBestTime, - eEventRaceTimerWarning1, - eEventRaceTimerWarning2, - eEventRaceTimerWarning3, - eEventRingChallengeStart, - eEventCarStop, - eEventRingChallengeRun, - eEventRingChallengeReset, - eEventRingChallengeSuccess, - eEventRingChallengeFailed, - eEventFormationChanged, - eEventChargeResume, - eEventChargePause, - eEventNPCChargeStop, - eEventNPCChargeCompleted, - eEventFormationChargeStart, + eEventWaveSetLinear, + eEventWaveSetRipple, + eEventSituationLaugh, + eEventSituationBossBattleGreenGhost, + eEventSituationBossBattleRedBeard, + eEventSituationBossBattleMasterMind, + eEventSituationBossBattleBlacknight, + eEventSituationPlayerScare, + eEventSituationPlayerSafe, + eEventSituationPlayerDanger, + eEventSituationPlayerChaseBegin, + eEventSituationPlayerChaseEnd, + eEventSituationPlayerSeeShaggy, + eEventSituationPlayerSeeFood, + eEventSituationPlayerSeeToken, + eEventSituationPlayerSeeScoobySnack, + eEventSituationPlayerSeePowerup, + eEventSituationPlayerSeeMonster, eEventSituationPlayerSuccess, eEventSituationPlayerFailure, eEventDispatcher_ShowHud, @@ -294,19 +296,19 @@ enum en_xEventTags eEventDispatcher_FadeOut, eEventSetRain, eEventSetSnow, - eEventScriptNoop, + eEventShaggyMowerStopMode, eEventScriptReset, eEventWaitForInput, eEventPlayMovie, - eEventCelebrationAnimPlay, + eEventDefeatedMM, eEventDispatcher_SetGameState_GameStats, - eEventMusicNewSong, + eEventPlayMusic, eEventForward, eEventReverse, - eEventDeprecatedRumbleTest, - eEventDeprecatedRumbleLight, - eEventDeprecatedRumbleMedium, - eEventDeprecatedRumbleHeavy, + eEventPlayerRumbleTest, + eEventPlayerRumbleLight, + eEventPlayerRumbleMedium, + eEventPlayerRumbleHeavy, eEventDispatcherScreenAdjustON, eEventDispatcherScreenAdjustOFF, eEventSetSkyDome, @@ -428,10 +430,10 @@ enum en_xEventTags eEventSetState, eEventEnterSpongeBob, eEventEnterPatrick, - eEventEnterSandyUNUSED, + eEventEnterSandy, eEventExitSpongeBob, eEventExitPatrick, - eEventExitSandyUNUSED, + eEventExitSandy, eEventNPCSpecial_PlatformSnap, eEventNPCSpecial_PlatformFall, eEventGooSetWarb, @@ -500,7 +502,7 @@ enum en_xEventTags eEventSituationSeeKingJellyfish, eEventSituationSeePrawn, eEventSituationSeeDutchman, - eEventSituationSeeSandyBossUNUSED, + eEventSituationSeeSandyBoss, eEventSituationSeePatrickBoss, eEventSituationSeeSpongeBobBoss, eEventSituationSeeRobotPlankton, @@ -515,7 +517,7 @@ enum en_xEventTags eEventCameraFXShake, eEventBulletTime, eEventThrown, - eEventNPCPatrol, + eEventUpdateAnimMatrices, eEventEnterCruise, eEventExitCruise, eEventCruiseFired, @@ -537,19 +539,6 @@ enum en_xEventTags eEventBubbleWipe, eEventSetLightKit, eEventSetOpacity, - eEventDispatcher_SetSoundEffect, - eEventScale, - eEventSetReference, - eEventWarpSetWorld, - eEventWarpSetTask, - eEventWarpGo, - eEventSetCount, - eEventGetDashSpeed, - eEventDashTrip, - eEventDashBurst, - eEventDashFast, - eEventDashNormal, - eEventDashSlow, eEventTakeSocks, eEventDispatcherAssert, eEventBorn, @@ -557,319 +546,22 @@ enum en_xEventTags eEventPlatUnpause, eEventStoreOptions, eEventRestoreOptions, - eEventUISetMotion, - eEventUIMotionFinished, - eEventUIMotionLoop, - eEventDestructibleLaunch, - eEventDestructibleRespawn, - eEventKaboomStart, - eEventKaboomStop, - eEventNPCAttack, - eEventNPCDefend, - eEventTrainCarSpeed, - eEventTrainJunctOut1, - eEventTrainJunctOut2, - eEventTrainJunctSwitch, - eEventTrainJunctPassed, - eEventTrainCarDetach, - eEventTrainCarExplode, - eEventNet_InitNetAPI, - eEventNet_UpdateConnection, - eEventNet_UpdateOnlineTask, - eEventNet_UpdateUserList, - eEventNet_CheckForNewContent, - eEventNet_SelectDevice, - eEventNet_SelectContent, - eEventNet_VerifyContent, - eEventNet_RemoveContent, - eEventNet_SelectDeviceAfterRemove, - eEventNet_ConfirmUseContentIdx, - eEventNet_ConfirmNoUseContentIdx, - eEventNet_NoContentInstalled, - eEventNet_NoContentAvailable, - eEventNet_NewContentAvailable, - eEventSceneEnableDraw, - eEventSceneDisableDraw, - eEventLightningStart, - eEventLightningStop, - eEventChangeBossUIStage, - eEventStaticCameraStart, - eEventStaticCameraEnd, - eEventSetCameraStartOrientation, - eEventNMESetMovepointPath, - eEventNMEScareBegin, - eEventNMEScareSkip, - eEventNMESetMovepointGroup, - eEventVentSetStateIdle, - eEventVentSetStateWarn, - eEventVentSetStateDamage, - eEventVentSetStateOff, - eEventWaterhoseStart, - eEventWaterhoseStop, - eEventWaterhoseSetLength, - eEventCarried, - eEventExplode, - eEventJumpTo, - eEventJumpOnSpawn, - eEventPlayerHit, - eEventStartFade, - eEventFadeDownDone, - eEventFadeUpDone, - eEventBounce, - eEventLaunchNPC, - eEventUpgradePowerUp, - eEventBulletStreak, - eEventSetFollowCameraOrientation, - eEventHDRFade, - eEventStart, - eEventSuccess, - eEventFailure, - eEventEnableRestore, - eEventDisableRestore, - eEventNPCSpawn, - eEventSpawnDone, - eEventSpawnedNPCKilled, - eEventSpawnedNPCNoHealth, - eEventSpawnedNPCAllKilled, - eEventSpawnedNPCAllNoHealth, - eEventDashTimerSet, - eEventDashNotOutOfTime, - eEventDashOutOfTime, - eEventForceSceneReset, - eEventNPCActive, - eEventNPCInactive, - eEventDuplicatorActive, - eEventDuplicatorInactive, - eEventDashEnterTunnel, - eEventDashExitTunnel, - eEventStopRumbleEffect, - eEventDashChaseLasersOn, - eEventDashChaseLasersOff, - eEventJumpRandomOnSpawn, - eEventHit_Cartwheel, - eEventUIVisible_FocusOn_Select, - eEventUIFocusOff_Unselect_Invisible, - eEventCopyReference, - eEventUIMotionFinishedIn, - eEventUIMotionFinishedOut, - eEventUISignalActivateScreen, - eEventUISignalDeactivateScreen, - eEventUISignalActivatedScreen, - eEventUISignalSwitchScreens, - eEventUISignalStartFadeOut, - eEventUISignalStartFadeIn, - eEventUISignalScreenMotionInDone, - eEventUISignalScreenMotionOutDone, - eEventUISignalMainBoxInDone, - eEventUISignalMainBoxOutDone, - eEventUIResetMotion, - eEventUIEnableHDR, - eEventUIDisableHDR, - eEventUIBrighten, - eEventUIUnbrighten, - eEventUISignalDeactivatedScreen, - eEventNPCDetectAlways, - eEventNPCDetectNever, - eEventNPCDetectNormal, - eEventNPCFightDefault, - eEventCameraCollidePartial, - eEventMusicTempSong, - eEvaluateCounterValue, - eEventCount0, - eEventRotToAbsoluteX, - eEventRotToAbsoluteY, - eEventRotToAbsoluteZ, - eEventTriggerAnim, - eEventTriggeredAnimDone, - eEventUISignalMore, - eEventUISignalNoMore, - eEventUISignalLess, - eEventUISignalNoLess, - eEventUISignalUp, - eEventUISignalDown, - eEventUISignalSyncToCurrent, - eEventUISignalEffect, - eEventFreezePlayer, - eEventUnfreezePlayer, - eEventUISignalMapStart, - eEventUISignalMapEnd, - eEventTransToAbsoluteX, - eEventTransToAbsoluteY, - eEventTransToAbsoluteZ, - eEventJSPVisibilityIncrement, - eEventJSPVisibilityDecrement, - eEventEnterCamera, - eEventExitCamera, - eEventPadPressE, - eEventSetDashJumpParameters, - eEventViperFacePlayer, - eEventViperFaceMovement, - eEventRequestStart, - eEventUIAutoMenuRun, - eEventUIAutoMenuRunUp, - eEventUIAutoMenuRunDown, - eEventUIAutoMenuRunLeft, - eEventUIAutoMenuRunRight, - eEventIncrementSuccess, - eEventDecrementSuccess, - eEventIncrementFailed, - eEventDecrementFailed, - eEventMusicTempSongStop, - eEventNPCScrambleActionBegin, - eEventNPCScrambleAlert, - eEventNPCSetTurretAttackRadius, - eEventGooFreezeStart, - eEventGooMeltStart, - eEventNPCNotice, - eEventBossStageSet, - eEventBossStageBegan, - eEventBossStageEnded, - eEventBossStageBeganA, - eEventBossStageEndedA, - eEventBossStageBeganB, - eEventBossStageEndedB, - eEventBossStageBeganC, - eEventBossStageEndedC, - eEventVisibilityCullOn, - eEventVisibilityCullOff, - eEventRBandCameraStart, - eEventRBandCameraEnd, - eEventMindyStart, - eEventMindyEnd, - eEventFlamethrowerStart, - eEventFlamethrowerStop, - eEventFlamethrowerSetLength, - eEventNPCTakeNoDamageOn, - eEventNPCTakeNoDamageOff, - eEventStaticCameraStartFOVFilter, - eEventStaticCameraRestoreFOV, - eEventUIXboxDemoExitToLauncher, - eEventSpawn, - eEventSpawned, - eEventCreditsSetDest, - eEventAllowAttractMode, - eEventDisallowAttractMode, - eEventRocketAttack, - eEventCollisionReset, - eEventAutoSave, - eEventOpenBonus, - eEventFlagLevel, - eEventLevelEnd, - eEventNet_GetLocalContentDevice, - eEventDispatcher_PauseGame_Safe, - eEventOverrideFreqency, - eEventResetFrequency, - eEventSetShotDelay, - eEventSetShotsInGroup, - eEventDispatcher_UserSelectYes, - eEventDispatcher_UserSelectNo, - eEventDispatcher_UserSelectBack, - eEventLaunchFireWorks, - eEventDispatcher_UserSelectionReset, - eEventSetAsBounceBack, - eEventUIResetUnlockables, - eEventUISysMessageWaitResponse, - eEventUISysMessageWaitConfirm, - eEventUISysMessageConfirm, - eEventUISysMessageAccept, - eEventUISysMessageDecline, - eEventSetAsBounceBack_Cancel, - eEventDispatcher_PauseGame, - eEventPattyWagonStartEngine, - eEventPattyWagonStopEngine, - eEventSpawnBubblesOn, - eEventSpawnBubblesOff, - eEventNet_XBLiveToggleSignIn, - eEventNet_XBLiveManageFriends, - eEventApplyOnResetOn, - eEventApplyOnResetOff, - eEventSnapTo, - eEventThrow, - eEventFirstZipLine, - eEventFirstLedgeGrab, - eEventFirstIncredimeterPickup, - eEventUISparkTrail, - eEventUIGetBattleScenes, - eEventUIBattleScenesAvailable, - eEventUIBattleScenesNotAvailable, - eEventNet_XBLiveToggleAppearOnline, - eEventSys_ReturnPrevScreen, - eEventSys_Nope, - eEventDispatcher_SubtitlesOn, - eEventDispatcher_SubtitlesOff, - eEventUISetBoxMapping, - eEventTBoxPlayerEjected, - eEventDamagePlayer, - eEventFirstHealthPickup, - eEventTokenPickupComplete, - eEventDispatcher_LoadSavePromptDead, - eEventUIFlipVisibility, - eEventNet_XBLiveRebootToDashboard, - eEventFirstPowerupPoint, eEventCount }; -enum en_npcmsg -{ - NME_MID_NONE, - NME_MID_SYSEVENT, - NME_MID_RESPAWN, - NME_MID_DAMAGE, - NME_MID_EXPLOSION, - NME_MID_BUNNYHOP, - NME_MID_NEWDEST, - NME_MID_DTRON_NMEEMIT, - NME_MID_DTRON_NMEAVAIL, - NME_MID_DTRON_ISDEAD, - NME_MID_CHAT_REQUEST, - NME_MID_CHAT_DECLINE, - NME_MID_CHAT_ACCEPT, - NME_MID_CHAT_DONE, - NME_MID_CHAT_ABORT, - NME_MID_TALKSTART, - NME_MID_TALKON, - NME_MID_TALKOFF, - NME_MID_SAWPLYR, - NME_MID_NEEDMEDIC, - NME_MID_UNDERATTACK, - NME_MID_NMEDIED, - NME_MID_PLYRSPATULA, - NME_MID_BECOMESCARED, - NME_MID_NOLONGERSCARED, - NME_MID_CELEBRATE, - NME_MID_STUN, - NME_MID_SCRIPTBEGIN, - NME_MID_SCRIPTEND, - NME_MID_SCRIPTHALT, - NME_MID_NOMORE, - NME_MID_FORCE = 0x7fffffff -}; - -enum en_msgdata -{ - NME_MDAT_BLANK, - NME_MDAT_SYSEVENT, - NME_MDAT_BLAST, - NME_MDAT_CHAT, - NME_MDAT_SPAWN, - NME_MDAT_TARGET, - NME_MDAT_DAMAGE, - NME_MDAT_STUN, - NME_MDAT_SCRIPT, - NME_MDAT_MOUNT, - NME_MDAT_AREANOTIFY, - NME_MDAT_NOMORE, - NME_MDAT_FORCE = 0x7fffffff -}; - -enum en_carystat -{ - zNMECARRY_NONE, - zNMECARRY_PICKUP, - zNMECARRY_TWIRL, - zNMECARRY_THROW, - zNMECARRY_ATTEMPTPICKUP, - zNMECARRY_FORCEINT = 0x7fffffff -}; +// Oddly, all the zEntEvent functions are in xEvent, not zEvent +void zEntEvent(char* to, U32 toEvent); +void zEntEvent(U32 toID, U32 toEvent); +void zEntEvent(U32 toID, U32 toEvent, F32 toParam0, F32 toParam1, F32 toParam2, + F32 toParam3); +void zEntEvent(xBase* to, U32 toEvent); +void zEntEvent(xBase* to, U32 toEvent, F32 toParam0, F32 toParam1, F32 toParam2, + F32 toParam3); +void zEntEvent(xBase* to, U32 toEvent, const F32* toParam); +void zEntEvent(xBase* to, U32 toEvent, const F32* toParam, xBase* toParamWidget); +void zEntEvent(xBase* from, xBase* to, U32 toEvent); +void zEntEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam); +void zEntEvent(xBase* from, U32 fromEvent, xBase* to, U32 toEvent, const F32* toParam, + xBase* toParamWidget, S32 forceEvent); #endif diff --git a/src/SB/Core/x/xFColor.h b/src/SB/Core/x/xFColor.h new file mode 100644 index 0000000..3e0596f --- /dev/null +++ b/src/SB/Core/x/xFColor.h @@ -0,0 +1,14 @@ +#ifndef XFCOLOR_H +#define XFCOLOR_H + +#include + +struct _xFColor +{ + F32 r; + F32 g; + F32 b; + F32 a; +}; + +#endif diff --git a/src/SB/Core/x/xFFX.cpp b/src/SB/Core/x/xFFX.cpp new file mode 100644 index 0000000..8ac6465 --- /dev/null +++ b/src/SB/Core/x/xFFX.cpp @@ -0,0 +1,166 @@ +#include "xFFX.h" +#include "xEnt.h" +#include "xMemMgr.h" + +#include + +extern xFFX* alist; +extern xFFXShakeState* shake_alist; +extern U32 rot_match_psize; +extern xFFXRotMatchState* rot_match_pool; +extern xFFXRotMatchState* rot_match_alist; + +// Structure same as the bottom function, get that one, you get this one. +//void xFFXPoolInit(U32 num_ffx); + +xFFX* xFFXAlloc() +{ + xFFX* alist2; + alist2 = alist; + if (alist == NULL) + { + return NULL; + } + alist = alist->next; + return alist2; +} + +void xFFXFree(xFFX* ffx) +{ + ffx->next = alist; + alist = ffx; +} + +void xFFXTurnOn(xFFX* f) +{ + f->flags |= 1; +} + +void xFFXTurnOff(xFFX* f) +{ + f->flags &= 0xfffffffe; +} + +S16 xFFXAddEffect(xEnt* ent, xFFX* f) +{ + U8 numFFX; + f->next = (xFFX*)ent->ffx; + f->flags = f->flags | 1; + *(xFFX**)&ent->ffx = f; + numFFX = ent->num_ffx; + ent->num_ffx = numFFX + 1; + return numFFX; +} + +S16 xFFXAddEffect(xEnt* ent, void (*dof)(xEnt*, xScene*, F32, void*), void* fd) +{ + xFFX* f = (xFFX*)xFFXAlloc(); + S16 effectID; + if (f == NULL) + { + effectID = -1; + } + else + { + f->doEffect = dof; + f->fdata = fd; + effectID = xFFXAddEffect(ent, f); + } + return effectID; +} + +// WIP. +U32 xFFXRemoveEffectByFData(xEnt* ent, void* fdata) +{ + xFFX* ffx; + xFFX** found; + + found = (xFFX**)&ent->ffx; + while (true) + { + ffx = *found; + if (ffx == NULL) + { + return 0; + } + if (fdata == ffx->fdata) + break; + found = &ffx->next; + } + ffx = ffx->next; + ent->num_ffx--; + xFFXFree(*found); + *found = ffx; + return 1; +} + +void xFFXApplyOne(xFFX* ffx, xEnt* ent, xScene* sc, F32 dt) +{ + if (ffx->next != NULL) + { + xFFXApplyOne(ffx->next, ent, sc, dt); + } + if ((ffx->flags & 1) != 0) + { + ffx->doEffect(ent, sc, dt, ffx->fdata); + } +} + +void xFFXApply(xEnt* ent, xScene* sc, F32 dt) +{ + if ((xFFX*)ent->ffx != NULL) + { + xFFXApplyOne((xFFX*)ent->ffx, ent, sc, dt); + } +} + +// The structure of this is identical to the pool init below. Figure out that one, you get this one as well. +//void xFFXShakePoolInit(U32 num); + +xFFXShakeState* xFFXShakeAlloc() +{ + xFFXShakeState* alist2; + alist2 = shake_alist; + if (shake_alist == NULL) + { + return NULL; + } + shake_alist = shake_alist->next; + return alist2; +} + +void xFFXShakeFree(xFFXShakeState* s) +{ + s->next = shake_alist; + shake_alist = s; +} + +// Some instructions are in the wrong order. +void xFFXRotMatchPoolInit(U32 num) +{ + rot_match_psize = num; + rot_match_pool = (xFFXRotMatchState*)xMemAllocSize(num * sizeof(xFFXRotMatchState)); + U32 i = 1; + rot_match_pool->next = NULL; + S32 ind = sizeof(xFFXRotMatchState); + while (i < rot_match_psize) + { + S32 nextAddr = ind - 1; + i++; + *(xFFXRotMatchState**)((S32)&rot_match_pool->next + ind) = rot_match_pool + nextAddr; + ind += sizeof(xFFXRotMatchState); + } + rot_match_alist = rot_match_pool + (rot_match_psize - 1); +} + +xFFXRotMatchState* xFFXRotMatchAlloc() +{ + xFFXRotMatchState* alist2; + alist2 = rot_match_alist; + if (rot_match_alist == NULL) + { + return NULL; + } + rot_match_alist = rot_match_alist->next; + return alist2; +} diff --git a/src/SB/Core/x/xFFX.h b/src/SB/Core/x/xFFX.h new file mode 100644 index 0000000..17499f6 --- /dev/null +++ b/src/SB/Core/x/xFFX.h @@ -0,0 +1,60 @@ +#ifndef XFFX_H +#define XFFX_H + +#include "xMath3.h" + +struct xScene; +struct xEnt; + +struct xFFX +{ + U32 flags; + void (*doEffect)(xEnt*, xScene*, F32, void*); + void* fdata; + xFFX* next; +}; + +struct xFFXShakeState +{ + xVec3 disp; + F32 dur; + F32 freq; + F32 tmr; + F32 alpha; + F32 lval; + xFFXShakeState* next; +}; + +struct xFFXRotMatchState +{ + S32 lgrounded; + xVec3 lfup; + xVec3 lfat; + xVec3 plfat; + F32 tmr; + F32 mrate; + F32 tmatch; + F32 rrate; + F32 trelax; + F32 max_decl; + xFFXRotMatchState* next; +}; + +void xFFXPoolInit(U32 num_ffx); +xFFX* xFFXAlloc(); +void xFFXFree(xFFX* ffx); +void xFFXTurnOn(xFFX* f); +void xFFXTurnOff(xFFX* f); +S16 xFFXAddEffect(xEnt* ent, xFFX* f); +S16 xFFXAddEffect(xEnt* ent, void (*dof)(xEnt*, xScene*, F32, void*), void* fd); +U32 xFFXRemoveEffectByFData(xEnt* ent, void* fdata); +void xFFXApplyOne(xFFX* ffx, xEnt* ent, xScene* sc, F32 dt); +void xFFXApply(xEnt* ent, xScene* sc, F32 dt); +void xFFXShakeUpdateEnt(xEnt* ent, xScene* sc, F32 dt, void* fdata); +void xFFXShakePoolInit(U32 num); +xFFXShakeState* xFFXShakeAlloc(); +void xFFXShakeFree(xFFXShakeState* s); +void xFFXRotMatchPoolInit(U32 num); +xFFXRotMatchState* xFFXRotMatchAlloc(); + +#endif diff --git a/src/SB/Core/x/xFX.cpp b/src/SB/Core/x/xFX.cpp new file mode 100644 index 0000000..92c74bc --- /dev/null +++ b/src/SB/Core/x/xFX.cpp @@ -0,0 +1,549 @@ +#include "xFX.h" + +#include "xstransvc.h" + +#include "iMath.h" +#include "zParEmitter.h" +#include "zSurface.h" +#include "zFX.h" +#include "zGlobals.h" + +#include +#include + +/* boot.HIP texture IDs */ +#define ID_gloss_edge 0xB8C2351E +#define ID_rainbowfilm_smooth32 0x741B0566 + +extern const char _stringBase0_7[]; + +extern F32 _957_0; +extern F32 _958; +extern F32 _995; +extern F32 _1132; +extern F32 _1171; + +RpAtomicCallBackRender gAtomicRenderCallBack = NULL; +F32 EnvMapShininess = 1.0f; +RpLight* MainLight = NULL; + +static U32 num_fx_atomics = 0; + +static U32 xfx_initted = 0; + +static void LightResetFrame(RpLight* light); + +void xFXInit() +{ + if (!xfx_initted) + { + xfx_initted = 1; + + RpLight* light = RpLightCreate(rpLIGHTDIRECTIONAL); + + if (light) + { + RwFrame* frame = RwFrameCreate(); + + if (frame) + { + RpLightSetFrame(light, frame); + LightResetFrame(light); + + MainLight = light; + } + else + { + RpLightDestroy(light); + } + } + + xFXanimUVCreate(); + xFXAuraInit(); + } +} + +static U32 Im3DBufferPos = 0; +static RwTexture* g_txtr_drawRing = NULL; + +static void DrawRingSetup() +{ + g_txtr_drawRing = (RwTexture*)xSTFindAsset(ID_rainbowfilm_smooth32, NULL); +} + +static void DrawRingSceneExit() +{ + g_txtr_drawRing = NULL; +} + +static void DrawRing(xFXRing* m) +{ + // todo: uses int-to-float conversion +} + +xFXRing* xFXRingCreate(const xVec3* pos, const xFXRing* params) +{ + xFXRing* ring = &ringlist[0]; + + if (!pos || !params) + { + return NULL; + } + + for (S32 i = 0; i < RING_COUNT; i++, ring++) + { + if (ring->time <= _957_0) + { + // non-matching: _958 is only loaded once + + memcpy(ring, params, sizeof(xFXRing)); + + ring->time = _995; + ring->pos = *pos; + ring->ring_radius_delta *= _958 / ring->lifetime; + ring->ring_height_delta *= _958 / ring->lifetime; + ring->ring_tilt_delta *= _958 / ring->lifetime; + + return ring; + } + } + + return NULL; +} + +static void xFXRingUpdate(F32 dt) +{ + xFXRing* ring = &ringlist[0]; + + if ((F32)iabs(dt) < _995) + { + return; + } + + for (S32 i = 0; i < RING_COUNT; i++, ring++) + { + if (ring->time <= _957_0) + { + continue; + } + + F32 lifetime = ring->lifetime; + + if (lifetime < dt) + { + lifetime = dt; + } + + ring->time += dt; + + F32 t = ring->time / lifetime; + + // non-matching: float scheduling + + if (t > _958) + { + ring->time = _957_0; + + if (ring->parent) + { + *ring->parent = NULL; + } + + ring->parent = NULL; + } + } +} + +void xFXRingRender() +{ + S32 i; + xFXRing* ring = &ringlist[0]; + + for (i = 0; i < RING_COUNT; i++, ring++) + { + if (ring->time > _957_0) + { + DrawRing(ring); + } + } +} + +static RpMaterial* MaterialSetEnvMap(RpMaterial* material, void* data); +static RpMaterial* MaterialSetBumpMap(RpMaterial* material, void* data); +static RpMaterial* MaterialSetBumpEnvMap(RpMaterial* material, RwTexture* env, F32 shininess, + RwTexture* bump, F32 bumpiness); + +void xFX_SceneEnter(RpWorld* world) +{ + S32 i; + S32 num = RpWorldGetNumMaterials(world); + + for (i = 0; i < num; i++) + { + xSurface* sp = zSurfaceGetSurface(i); + zSurfaceProps* pp = (zSurfaceProps*)sp->moprops; + + if (pp && pp->asset) + { + zSurfMatFX* fxp = &pp->asset->matfx; + + if (fxp->flags) + { + if (fxp->flags == 0x10) + { + fxp->flags |= 0x1; + } + + RpMaterial* mp = RpWorldGetMaterial(world, i); + + if (RpMaterialGetTexture(mp)) + { + gFXSurfaceFlags = fxp->flags; + + if (fxp->flags & 0x1) + { + RwTexture* env = (RwTexture*)xSTFindAsset(fxp->envmapID, NULL); + + if (!env) + { + continue; + } + + MaterialSetEnvMap(mp, env); + RpMatFXMaterialSetEnvMapCoefficient(mp, _1132 * fxp->shininess); + } + + if (fxp->flags & 0x2) + { + RwTexture* bump = (RwTexture*)xSTFindAsset(fxp->bumpmapID, NULL); + + if (!bump) + { + continue; + } + + MaterialSetBumpMap(mp, bump); + RpMatFXMaterialSetBumpMapCoefficient(mp, fxp->bumpiness); + } + + if (fxp->flags & 0x4) + { + RwTexture* env = (RwTexture*)xSTFindAsset(fxp->envmapID, NULL); + RwTexture* bump = (RwTexture*)xSTFindAsset(fxp->bumpmapID, NULL); + + if (!env || !bump) + { + continue; + } + + MaterialSetBumpEnvMap(mp, env, fxp->shininess, bump, fxp->bumpiness); + } + } + } + } + } + + zScene* sc = globals.sceneCur; + + for (i = 0; i < sc->num_act_ents; i++) + { + xEnt* ent = sc->act_ents[i]; + + if (!gAtomicRenderCallBack && ent->model) + { + RpAtomicCallBackRender tmp = RpAtomicGetRenderCallBack(ent->model->Data); + + RpAtomicSetRenderCallBack(ent->model->Data, NULL); + + gAtomicRenderCallBack = RpAtomicGetRenderCallBack(ent->model->Data); + + RpAtomicSetRenderCallBack(ent->model->Data, tmp); + } + + if (ent->model) + { + // non-matching: strings are getting cached for some reason + + U32 bubble; + + bubble = (ent->id == xStrHash(_stringBase0_7)); + bubble |= (ent->id == xStrHash(_stringBase0_7 + 13)); + bubble |= (ent->id == xStrHash(_stringBase0_7 + 28)); + bubble |= (ent->id == xStrHash(_stringBase0_7 + 42)); + bubble |= (ent->id == xStrHash(_stringBase0_7 + 62)); + bubble |= (ent->id == xStrHash(_stringBase0_7 + 75)); + + if (bubble) + { + xSTAssetName(ent->id); + + RpAtomicSetRenderCallBack(ent->model->Data, xFXBubbleRender); + } + } + } + + num_fx_atomics = 0; +} + +void xFX_SceneExit(RpWorld*) +{ +} + +void xFXUpdate(F32 dt) +{ + xFXRingUpdate(dt); + xFXRibbonUpdate(dt); + xFXAuraUpdate(dt); +} + +static const RwV3d _1168 = { 1, 0, 0 }; +static const RwV3d _1169 = { 0, 1, 0 }; + +static void LightResetFrame(RpLight* light) +{ + // non-matching: lwzu instruction + + RwV3d v1 = { 1, 0, 0 }; + RwV3d v2 = { 0, 1, 0 }; + + RwFrame* frame = RpLightGetFrame(light); + + RwFrameRotate(frame, &v1, _1171, rwCOMBINEREPLACE); + RwFrameRotate(frame, &v2, _1171, rwCOMBINEPOSTCONCAT); +} + +static RpMaterial* MaterialDisableMatFX(RpMaterial* material, void*) +{ + RpMatFXMaterialSetEffects(material, rpMATFXEFFECTNULL); + return material; +} + +RpAtomic* AtomicDisableMatFX(RpAtomic* atomic) +{ + RpMatFXAtomicEnableEffects(atomic); + + RpGeometry* geometry = RpAtomicGetGeometry(atomic); + + if (geometry) + { + RpGeometryForAllMaterials(geometry, MaterialDisableMatFX, NULL); + } + + return atomic; +} + +static RpAtomic* PreAllocMatFX_cb(RpAtomic* atomic, void*) +{ + AtomicDisableMatFX(atomic); + return atomic; +} + +void xFXPreAllocMatFX(RpClump* clump) +{ + RpClumpForAllAtomics(clump, PreAllocMatFX_cb, NULL); +} + +RpMaterial* MaterialSetShininess(RpMaterial* material, void*) +{ + RpMatFXMaterialFlags flags = RpMatFXMaterialGetEffects(material); + + if (flags == rpMATFXEFFECTENVMAP || flags == rpMATFXEFFECTBUMPENVMAP) + { + RpMatFXMaterialSetEnvMapCoefficient(material, EnvMapShininess); + } + + return material; +} + +static RpAtomic* AtomicSetShininess(RpAtomic* atomic, void* data) +{ + RpGeometry* geometry = RpAtomicGetGeometry(atomic); + + if (geometry) + { + RpGeometryForAllMaterials(geometry, MaterialSetShininess, data); + } + + return atomic; +} + +struct xFXBubbleParams +{ + U32 pass1 : 1; + U32 pass2 : 1; + U32 pass3 : 1; + U32 padding : 5; + U8 pass1_alpha; + U8 pass2_alpha; + U8 pass3_alpha; + U32 pass1_fbmsk; + U32 fresnel_map; + F32 fresnel_map_coeff; + U32 env_map; + F32 env_map_coeff; +}; + +static xFXBubbleParams defaultBFX = { + // pass1, pass2, pass3, padding + 1, 1, 1, 0, + // pass1_alpha, pass2_alpha, pass3_alpha, pass1_fbsk + 0, 0, 192, 0xFFFFFFFF, + // fresnel_map, fresnel_map_coeff + ID_gloss_edge, 0.75f, + // env_map, env_map_coeff + ID_rainbowfilm_smooth32, 0.5f +}; + +static U32 bfx_curr = 0; +static xFXBubbleParams* BFX = &defaultBFX; + +static U32 sFresnelMap = 0; +static U32 sEnvMap = 0; +static S32 sTweaked = 0; + +static RxPipeline* xFXanimUVPipeline = NULL; +F32 xFXanimUVRotMat0[2] = { 1.0f, 0.0f }; +F32 xFXanimUVRotMat1[2] = { 0.0f, 1.0f }; +F32 xFXanimUVTrans[2] = { 0.0f, 0.0f }; +F32 xFXanimUVScale[2] = { 1.0f, 1.0f }; +F32 xFXanimUV2PRotMat0[2] = { 1.0f, 0.0f }; +F32 xFXanimUV2PRotMat1[2] = { 0.0f, 1.0f }; +F32 xFXanimUV2PTrans[2] = { 0.0f, 0.0f }; +F32 xFXanimUV2PScale[2] = { 1.0f, 1.0f }; +RwTexture* xFXanimUV2PTexture = NULL; + +namespace +{ +#define ALPHA_COUNT 300 + + U8 alpha_count0[ALPHA_COUNT]; + U8 alpha_count1[ALPHA_COUNT]; +} // namespace + +// clip_triangle jumptable +static U32 _1933[] = { 0x80028610, 0x80028640, 0x80028640, 0x80028640, 0x80028640, 0x80028640, + 0x80028640, 0x80028620, 0x80028640, 0x80028640, 0x80028640, 0x80028640, + 0x80028640, 0x80028640, 0x80028630, 0x80028640, 0x80028640, 0x80028640, + 0x80028640, 0x80028640, 0x80028640, 0x80028630, 0x80028640, 0x80028640, + 0x80028640, 0x80028640, 0x80028640, 0x80028640, 0x80028620, 0x80028640, + 0x80028640, 0x80028640, 0x80028640, 0x80028640, 0x80028640, 0x80028610 }; + +static const U8 segments_1637[43] = { 0, 1, 3, 0, 1, 2, 4, 0, 3, 4, 3, 0, 0, 0, 0, + 0, 1, 2, 4, 0, 2, 1, 2, 0, 4, 2, 1, 0, 0, 0, + 0, 0, 3, 4, 3, 0, 4, 2, 1, 0, 3, 1, 0 }; + +struct _tagFirework +{ + S32 state; + F32 timer; + xVec3 vel; + xVec3 pos; + F32 fuel; +}; + +#define FIREWORK_COUNT 10 + +static _tagFirework sFirework[FIREWORK_COUNT]; +static zParEmitter* sFireworkTrailEmit = NULL; +static zParEmitter* sFirework1Emit = NULL; +static zParEmitter* sFirework2Emit = NULL; +static U32 sFireworkSoundID = 0; +static U32 sFireworkLaunchSoundID = 0; + +static RwIm3DVertex sStripVert_2188[4]; + +static RwIm3DVertex blah_2485[4]; + +namespace +{ +#define RIBBON_COUNT 64 + + xFXRibbon* active_ribbons[RIBBON_COUNT]; + U32 active_ribbons_size = 0; + bool ribbons_dirty = false; +} // namespace + +struct _xFXAuraAngle +{ + F32 angle; + F32 cc; + F32 ss; +}; + +struct _xFXAura +{ + xVec3 pos; + iColor_tag color; + F32 size; + void* parent; + U32 frame; + F32 dangle[2]; +}; + +#define AURA_COUNT 32 + +static F32 sAuraPulse[2]; +static F32 sAuraPulseAng[2]; +static _xFXAuraAngle sAuraAngle[2]; +static RwTexture* gAuraTex = NULL; +static _xFXAura sAura[AURA_COUNT]; + +__declspec(section ".rodata") static const char _stringBase0_7[] = "bubble buddy\0" + "bubble missile\0" + "bubble helmet\0" + "bubble bowling ball\0" + "bubble shoeL\0" + "bubble shoeR\0" + "spec3\0" + "default_env_map.RW3\0" + "gloss_edge\0" + "update frame\n\0" + "fx_streak1\0" + "BLENDZERO\0" + "BLENDONE\0" + "BLENDSRCCOLOR\0" + "BLENDINVSRCCOLOR\0" + "BLENDSRCALPHA\0" + "BLENDINVSRCALPHA\0" + "BLENDDESTALPHA\0" + "BLENDINVDESTALPHA\0" + "BLENDDESTCOLOR\0" + "BLENDINVDESTCOLOR\0" + "BLENDSRCALPHASAT\0" + "FX|Ribbon"; + +void xFXStartup() +{ +} + +void xFXShutdown() +{ +} + +void xFXSceneInit() +{ +} + +void xFXSceneReset() +{ +} + +void xFXScenePrepare() +{ +} + +void xFXRibbon::update_curve_tweaks() +{ +} + +void xFXRibbon::debug_init(const char*, const char*) +{ +} + +void xFXRibbon::debug_update_curve() +{ +} + +void xFXRibbon::debug_update(F32) +{ +} diff --git a/src/SB/Core/x/xFX.h b/src/SB/Core/x/xFX.h index 1b1232c..4f85a47 100644 --- a/src/SB/Core/x/xFX.h +++ b/src/SB/Core/x/xFX.h @@ -1,10 +1,133 @@ #ifndef XFX_H #define XFX_H -#include "xMath.h" +#include "xMath3.h" +#include "containers.h" +#include "iColor.h" -struct xFFX +#include +#include + +class xModelInstance; + +struct xFXRing { + U32 texture; + F32 lifetime; + xVec3 pos; + F32 time; // 0x14 + F32 ring_radius; + F32 ring_radius_delta; // 0x1c + F32 ring_tilt; + F32 ring_tilt_delta; // 0x24? + F32 ring_height; // 0x28 + F32 ring_height_delta; + iColor_tag ring_color; + U16 ring_segs; + U8 u_repeat; + U8 v_repeat; + xFXRing** parent; +}; + +struct xFXRibbon +{ + struct config + { + F32 life_time; + U32 blend_src; + U32 blend_dst; + F32 pivot; + }; + + struct joint_data + { + U32 flags; + U32 born; + xVec3 loc; + xVec3 norm; + F32 orient; + F32 scale; + F32 alpha; + }; + + struct curve_node + { + F32 time; + iColor_tag color; + F32 scale; + }; + + config cfg; + bool activated; + RwRaster* raster; + tier_queue joints; + curve_node* curve; + U32 curve_size; + U32 curve_index; + F32 ilife; + U32 mtime; + U32 mlife; + + void init(const char*, const char*); + void set_texture(const char* name); + void set_curve(const curve_node* curve, size_t size); + void refresh_config(); + void set_default_config(); + void update_curve_tweaks(); + void debug_init(const char*, const char*); + void debug_update_curve(); + void debug_update(F32); }; +#define RING_COUNT 8 + +extern xFXRing ringlist[RING_COUNT]; + +void xFXInit(); +xFXRing* xFXRingCreate(const xVec3* pos, const xFXRing* params); +void xFXRingRender(); +void xFX_SceneEnter(RpWorld* world); +void xFX_SceneExit(RpWorld* world); +void xFXUpdate(F32 dt); +RpAtomic* AtomicDisableMatFX(RpAtomic* atomic); +void xFXPreAllocMatFX(RpClump* clump); + +RpAtomic* xFXBubbleRender(RpAtomic* atomic); + +void xFXanimUV2PSetTexture(RwTexture* texture); +void xFXanimUVSetTranslation(const xVec3* trans); +void xFXanimUV2PSetTranslation(const xVec3* trans); +void xFXanimUVSetScale(const xVec3* scale); +void xFXanimUV2PSetScale(const xVec3* scale); +void xFXanimUVSetAngle(F32 angle); +void xFXanimUV2PSetAngle(F32 angle); +RpAtomic* xFXanimUVAtomicSetup(RpAtomic* atomic); +U32 xFXanimUVCreate(); +void xFXFireworksInit(const char* fireworksTrailEmitter, const char* fireworksEmitter1, + const char* fireworksEmitter2, const char* fireworksSound, + const char* fireworksLaunchSound); +void xFXFireworksLaunch(F32 countdownTime, const xVec3* pos, F32 fuelTime); +void xFXFireworksUpdate(F32 dt); +void xFXStreakInit(); +void xFXStreakUpdate(F32 dt); +void xFXStreakUpdate(U32 streakID, const xVec3*, const xVec3*); +void xFXStreakRender(); +void xFXStreakStop(U32); +void xFXShineInit(); +void xFXShineUpdate(F32 dt); +void xFXShineRender(); +RpAtomic* xFXAtomicEnvMapSetup(RpAtomic* atomic, U32 envmapID, F32 shininess); +void xFXRibbonSceneEnter(); +void xFXRibbonUpdate(F32 dt); +void xFXRibbonRender(); +void xFXAuraInit(); +void xFXAuraUpdate(F32 dt); +void xFXAuraRender(); +void xFXRenderProximityFade(const xModelInstance& model, F32 near_dist, F32 far_dist); +void xFXSceneInit(); +void xFXSceneSetup(); +void xFXSceneReset(); +void xFXScenePrepare(); +void xFXSceneFinish(); + #endif diff --git a/src/SB/Core/x/xFactory.cpp b/src/SB/Core/x/xFactory.cpp new file mode 100644 index 0000000..a98ec73 --- /dev/null +++ b/src/SB/Core/x/xFactory.cpp @@ -0,0 +1,247 @@ +#include "xFactory.h" +#include "xMemMgr.h" + +#include +#include + +xFactory::xFactory(S32 maxTypes) +{ + U32 amt = maxTypes * sizeof(XGOFTypeInfo); + this->infopool = (XGOFTypeInfo*)xMemAllocSize(amt); + memset(this->infopool, 0, amt); + XOrdInit(&this->infolist, maxTypes, 0); +} + +xFactory::~xFactory() +{ + this->infopool = NULL; + XOrdDone(&this->infolist, 0); +} + +static S32 OrdTest_infotype(const void* vkey, void* vitem); +static S32 OrdComp_infotype(void* vkey, void* vitem); + +S32 xFactory::RegItemType(XGOFTypeInfo* info) +{ + S32 rc = 0; + XGOFTypeInfo* tptr = info; + XGOFTypeInfo* nextrec; + + while (tptr->tid) + { + rc = 1; + + if (!tptr->creator) + { + rc = 0; + break; + } + + if (!tptr->destroyer) + { + rc = 0; + break; + } + + if (infolist.cnt >= infolist.max) + { + rc = -2; + break; + } + + S32 idx = XOrdLookup(&infolist, tptr, OrdTest_infotype); + + if (idx >= 0) + { + rc = -1; + break; + } + + nextrec = &infopool[infolist.cnt]; + nextrec->tid = tptr->tid; + nextrec->creator = tptr->creator; + nextrec->destroyer = tptr->destroyer; + + XOrdInsert(&infolist, nextrec, OrdComp_infotype); + + tptr++; + } + + return rc; +} + +S32 xFactory::RegItemType(S32 tid, XGOFTypeInfoCreator create, XGOFTypeInfoDestroyer destroy) +{ + XGOFTypeInfo typerec[2] = {}; + + typerec[0].tid = tid; + typerec[0].creator = create; + typerec[0].destroyer = destroy; + + return RegItemType(typerec); +} + +void xFactory::GrowDataEnable(xBase* user, S32 isResume) +{ + if (isResume) + { + growContextData.Resume(user); + } + else + { + growContextData.Init(user); + } +} + +void xFactory::GrowDataDisable() +{ + growContextData.Done(); +} + +xFactoryInst* xFactory::CreateItem(S32 typeID, void* userdata, RyzMemGrow* callerzgrow) +{ + S32 idx; + xFactoryInst* item; + XGOFTypeInfo pattern = {}; + XGOFTypeInfo* darec = NULL; + RyzMemGrow* grow = callerzgrow; + + pattern.tid = typeID; + + idx = XOrdLookup(&infolist, &pattern, OrdTest_infotype); + + if (idx >= 0) + { + darec = (XGOFTypeInfo*)infolist.list[idx]; + } + + if (!darec) + { + return NULL; + } + + if (!darec->creator) + { + return NULL; + } + + if (!darec->destroyer) + { + return NULL; + } + + if (!grow && growContextData.IsEnabled()) + { + grow = &growContextData; + } + + item = darec->creator(darec->tid, grow, userdata); + + if (!item) + { + return item; + } + + item->itemType = darec->tid; + item->prevprod = NULL; + item->nextprod = NULL; + + if (products) + { + item->nextprod = products; + products->prevprod = item; + products = item; + } + else + { + products = item; + } + + return item; +} + +void xFactory::DestroyAll() +{ + while (products) + { + DestroyItem(products); + } +} + +void xFactory::DestroyItem(xFactoryInst* item) +{ + S32 idx; + XGOFTypeInfo pattern = {}; + + pattern.tid = item->itemType; + + if (item) + { + if (products == item) + { + products = item->nextprod; + + if (products) + { + products->prevprod = NULL; + } + } + + if (item->prevprod) + { + item->prevprod->nextprod = item->nextprod; + } + + if (item->nextprod) + { + item->nextprod->prevprod = item->prevprod; + } + + item->prevprod = NULL; + item->nextprod = NULL; + + idx = XOrdLookup(&infolist, &pattern, OrdTest_infotype); + + ((XGOFTypeInfo*)infolist.list[idx])->destroyer(item); + } +} + +static S32 OrdTest_infotype(const void* vkey, void* vitem) +{ + S32 rc; + + if (((XGOFTypeInfo*)vkey)->tid < ((XGOFTypeInfo*)vitem)->tid) + { + rc = -1; + } + else if (((XGOFTypeInfo*)vkey)->tid > ((XGOFTypeInfo*)vitem)->tid) + { + rc = 1; + } + else + { + rc = 0; + } + + return rc; +} + +static S32 OrdComp_infotype(void* vkey, void* vitem) +{ + S32 rc; + + if (((XGOFTypeInfo*)vkey)->tid < ((XGOFTypeInfo*)vitem)->tid) + { + rc = -1; + } + else if (((XGOFTypeInfo*)vkey)->tid > ((XGOFTypeInfo*)vitem)->tid) + { + rc = 1; + } + else + { + rc = 0; + } + + return rc; +} diff --git a/src/SB/Core/x/xFactory.h b/src/SB/Core/x/xFactory.h new file mode 100644 index 0000000..b3ed128 --- /dev/null +++ b/src/SB/Core/x/xFactory.h @@ -0,0 +1,55 @@ +#ifndef XFACTORY_H +#define XFACTORY_H + +#include + +#include "xRMemData.h" +#include "xordarray.h" + +struct xFactoryInst : RyzMemData +{ + S32 itemType; + xFactoryInst* nextprod; + xFactoryInst* prevprod; + + xFactoryInst() + { + itemType = 0; + prevprod = NULL; + nextprod = NULL; + } + + ~xFactoryInst() + { + } +}; + +typedef xFactoryInst* (*XGOFTypeInfoCreator)(S32, RyzMemGrow*, void*); +typedef void (*XGOFTypeInfoDestroyer)(xFactoryInst*); + +struct XGOFTypeInfo +{ + S32 tid; + XGOFTypeInfoCreator creator; + XGOFTypeInfoDestroyer destroyer; +}; + +struct xFactory : RyzMemData +{ + XGOFTypeInfo* infopool; + st_XORDEREDARRAY infolist; + xFactoryInst* products; + RyzMemGrow growContextData; + + xFactory(S32 maxTypes); + void DestroyItem(xFactoryInst* item); + void DestroyAll(); + xFactoryInst* CreateItem(S32 typeID, void* userdata, RyzMemGrow* callerzgrow); + void GrowDataDisable(); + void GrowDataEnable(xBase* user, S32 isResume); + S32 RegItemType(S32 tid, XGOFTypeInfoCreator create, XGOFTypeInfoDestroyer destroy); + S32 RegItemType(XGOFTypeInfo* info); + ~xFactory(); +}; + +#endif diff --git a/src/SB/Core/x/xFile.h b/src/SB/Core/x/xFile.h new file mode 100644 index 0000000..3ff4e2b --- /dev/null +++ b/src/SB/Core/x/xFile.h @@ -0,0 +1,26 @@ +#ifndef XFILE_H +#define XFILE_H + +#include "iFile.h" + +enum XFILE_READSECTOR_STATUS +{ + XFILE_RDSTAT_NOOP, + XFILE_RDSTAT_INPROG, + XFILE_RDSTAT_DONE, + XFILE_RDSTAT_FAIL, + XFILE_RDSTAT_QUEUED, + XFILE_RDSTAT_EXPIRED +}; + +struct tag_xFile +{ + char relname[32]; + tag_iFile ps; + void* user_data; +}; + +void xFileSetUserData(tag_xFile* file, void* userdata); +XFILE_READSECTOR_STATUS xFileReadAsyncStatus(S32 key, S32* amtToFar); + +#endif diff --git a/src/SB/Core/x/xFog.cpp b/src/SB/Core/x/xFog.cpp new file mode 100644 index 0000000..e0a2f44 --- /dev/null +++ b/src/SB/Core/x/xFog.cpp @@ -0,0 +1,82 @@ +#include "xFog.h" +#include "xEvent.h" + +#include "iCamera.h" + +#include + +void xFogClearFog() +{ + iCameraSetFogParams(NULL, 0.0f); +} + +void xFogInit(void* b, void* tasset) +{ + xFogInit((xBase*)b, (xFogAsset*)tasset); +} + +void xFogInit(xBase* ent, xFogAsset* tasset) +{ + xBaseInit(ent, (xBaseAsset*)tasset); + ent->eventFunc = xFogEventCB; + ((_xFog*)ent)->tasset = tasset; + if (ent->linkCount != 0) + { + ent->link = (xLinkAsset*)(((_xFog*)ent)->tasset + 1); + } + else + { + ent->link = NULL; + } +} + +void xFogReset(_xFog* ent) +{ + xBaseReset((xBase*)ent, (xBaseAsset*)ent->tasset); +} + +void xFogSave(_xFog* ent, xSerial* s) +{ + xBaseSave((xBase*)ent, s); +} + +void xFogLoad(_xFog* ent, xSerial* s) +{ + xBaseLoad((xBase*)ent, s); +} + +S32 xFogEventCB(xBase* to, xBase* from, U32 toEvent, const F32* toParam, xBase* b3) +{ + switch (toEvent) + { + case eEventOn: + iFogParams fog; + fog.type = rwFOGTYPELINEAR; + xFogAsset* fromFog = ((_xFog*)from)->tasset; + fog.start = fromFog->fogStart; + fog.stop = fromFog->fogStop; + fog.density = fromFog->fogDensity; + fog.fogcolor.red = fromFog->fogColor[0]; + fog.fogcolor.green = fromFog->fogColor[1]; + fog.fogcolor.blue = fromFog->fogColor[2]; + fog.fogcolor.alpha = fromFog->fogColor[3]; + fog.bgcolor.red = fromFog->bkgndColor[0]; + fog.bgcolor.green = fromFog->bkgndColor[1]; + fog.bgcolor.blue = fromFog->bkgndColor[2]; + fog.bgcolor.alpha = fromFog->bkgndColor[3]; + fog.table = NULL; + iCameraSetFogParams(&fog, fromFog->transitionTime); + break; + case eEventOff: + iCameraSetFogParams(NULL, 0.0f); + break; + case eEventReset: + xFogReset((_xFog*)from); + break; + } + return eEventEnable; +} + +void xFogUpdate(xBase* ent, xScene* sc, F32 dt) +{ +} diff --git a/src/SB/Core/x/xFog.h b/src/SB/Core/x/xFog.h new file mode 100644 index 0000000..d7fd9f1 --- /dev/null +++ b/src/SB/Core/x/xFog.h @@ -0,0 +1,35 @@ +#ifndef XFOG_H +#define XFOG_H + +#include "xEnt.h" +#include "xBase.h" + +#include + +struct xFogAsset : xBaseAsset +{ + U8 bkgndColor[4]; + U8 fogColor[4]; + F32 fogDensity; + F32 fogStart; + F32 fogStop; + F32 transitionTime; + U8 fogType; + U8 padFog[3]; +}; + +struct _xFog : xBase +{ + xFogAsset* tasset; +}; + +void xFogClearFog(); +void xFogInit(void* b, void* tasset); +void xFogInit(xBase* ent, xFogAsset* tasset); +void xFogReset(_xFog* ent); +void xFogSave(_xFog* ent, xSerial* s); +void xFogLoad(_xFog* ent, xSerial* s); +S32 xFogEventCB(xBase* to, xBase* from, U32 toEvent, const F32* toParam, xBase* b3); +void xFogUpdate(xBase* ent, xScene* sc, F32 dt); + +#endif diff --git a/src/SB/Core/x/xFont.cpp b/src/SB/Core/x/xFont.cpp new file mode 100644 index 0000000..594658a --- /dev/null +++ b/src/SB/Core/x/xFont.cpp @@ -0,0 +1,3705 @@ +#include "xFont.h" + +#include "xMath.h" +#include "xstransvc.h" +#include "xModel.h" +#include "xColor.h" +#include "xTimer.h" +#include "xTextAsset.h" +#include "xModelBucket.h" + +#include "iTime.h" +#include "zScene.h" + +#include +#include + +/* xtextbox flags */ + +#define FLAG_UNK40 0x40 +#define FLAG_UNK80 0x80 + +#define WRAP_WORD 0x0 +#define WRAP_CHAR 0x10 +#define WRAP_NONE 0x20 +#define WRAP_MASK (WRAP_WORD | WRAP_CHAR | WRAP_NONE) + +#define XJUSTIFY_LEFT 0x0 +#define XJUSTIFY_RIGHT 0x1 +#define XJUSTIFY_CENTER 0x2 +#define XJUSTIFY_MASK (XJUSTIFY_LEFT | XJUSTIFY_RIGHT | XJUSTIFY_CENTER) + +#define YJUSTIFY_TOP 0x0 +#define YJUSTIFY_BOTTOM 0x4 +#define YJUSTIFY_CENTER 0x8 +#define YJUSTIFY_MASK (YJUSTIFY_TOP | YJUSTIFY_BOTTOM | YJUSTIFY_CENTER) + +extern substr _1615; +extern substr _1616; +extern xtextbox::tag_entry_list _1642; + +static const basic_rect screen_bounds = { 0, 0, 1, 1 }; + +namespace +{ + struct font_asset + { + U32 tex_id; + U16 u; + U16 v; + U8 du; + U8 dv; + U8 line_size; + U8 baseline; + struct + { + S16 x; + S16 y; + } space; // 0xC + U32 flags; // 0x10 + U8 char_set[128]; // 0x14 + struct + { + U8 offset; + U8 size; + } char_pos[127]; // 0x94 + }; + + struct font_data + { + font_asset* asset; + U32 index_max; + U8 char_index[256]; + F32 iwidth; + F32 iheight; + basic_rect tex_bounds[127]; + basic_rect bounds[127]; + xVec2 dstfrac[127]; + RwTexture* texture; + RwRaster* raster; + }; + + struct model_cache_entry + { + U32 id; + U32 order; + xModelInstance* model; + }; + + // clang-format off + const char* default_font_texture[] = + { + "font_sb", + "font1_sb", +#if 1 // needed until .sdata2 is decomped + "font_numbers\0 \t\n{}=*+:;," +#else + "font_numbers" +#endif + }; + + font_asset default_font_assets[4] = + { + // font1_sb (SpongeBob font) + 1, 0, 0, 18, 22, 14, 0, 0, 0, 0x1, + { + '~', '{', '}', '#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '?', '!', + '.', ',', '-', ':', '_', '"', '\'', '&', '(', ')', '<', '>', '/', '%', + '\xFC', '\xFB', '\xF9', '\xE2', '\xE4', '\xE0', '\xEA', '\xE8', '\xE9', + '\xEE', '\xF6', '\xF4', '\xE7', '\xDF', '\x2B' + }, + {}, + + // font_sb (Arial font) + 0, 0, 0, 18, 22, 14, 0, 1, 0, 0, + { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '?', '!', '.', ',', ';', ':', '+', '-', + '=', '/', '&', '(', ')', '%', '"', '\'', '_', '<', '>', '*', '[', ']', + '\xDC', '\xDB', '\xD9', '\xC2', '\xC4', '\xC0', '\xCA', '\xC8', '\xC9', + '\xCE', '\xD6', '\xD4', '\xC7', '\xDF', '\xFC', '\xFB', '\xF9', '\xE2', + '\xE4', '\xE0', '\xEA', '\xE8', '\xE9', '\xEE', '\xF6', '\xF4', '\xE7', + '~', '\xA9', '\xAE', '\x99', '@', '\x7C' + }, + {}, + + // font1_sb (System font) + 1, 148, 232, 6, 8, 18, 0, 0, 0, 0x9, + { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ',', '.', '/', '*', '+', '-', + '=', ':', ';', '%', '<', '>', '[', ']', '|', '(', ')', '_' + }, + {}, + + // font_numbers (SpongeBob numbers font) + 2, 0, 0, 32, 32, 4, 0, 0, 0, 0, + { + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '/' + }, + {} + }; + // clang-format on + + font_data active_fonts[4]; + U32 active_fonts_size = 0; + +#define VERT_BUFFER_SIZE 120 + + RwIm2DVertex vert_buffer[VERT_BUFFER_SIZE]; + U32 vert_buffer_used = 0; + + F32 rcz = 0; + F32 nsz = 0; + +#define MODEL_CACHE_SIZE 8 + + model_cache_entry model_cache[MODEL_CACHE_SIZE]; + bool model_cache_inited = false; + + basic_rect find_bounds(const iColor_tag* bits, const basic_rect& r, S32 pitch) + { + S32 diff = pitch - r.w; + const iColor_tag* endp = bits + pitch * r.h; + const iColor_tag* p = bits; + S32 pmode = (p->r == p->g && p->g == p->b && p->r >= 240); + + S32 minx = r.x + r.w; + S32 maxx = r.x - 1; + S32 miny = r.y + r.h; + S32 maxy = r.y - 1; + + S32 y = r.y; + + while (p != endp) + { + const iColor_tag* endline = p + r.w; + S32 x = r.x; + + while (p != endline) + { + if ((pmode && p->a) || (!pmode && p->r)) + { + minx = MIN(x, minx); + maxx = MAX(x, maxx); + miny = MIN(y, miny); + maxy = MAX(y, maxy); + } + + p++; + x++; + } + + p += diff; + y++; + } + + basic_rect b; + b.x = minx; + b.y = miny; + b.w = maxx + 1 - minx; + b.h = maxy + 1 - miny; + + return b; + } + + bool reset_font_spacing(font_asset& a) + { + RwTexture* tex = (RwTexture*)xSTFindAsset(a.tex_id, NULL); + + if (!tex) + { + return false; + } + + basic_rect char_bounds; + char_bounds.w = a.du; + char_bounds.h = a.dv; + + U8 baseline_count[256]; + memset(baseline_count, 0, 256); + + a.baseline = 0; + + S32 width = RwRasterGetWidth(RwTextureGetRaster(tex)); + RwImage* image = RwImageCreate(width, RwRasterGetHeight(RwTextureGetRaster(tex)), 32); + + if (!image) + { + return false; + } + + RwImageAllocatePixels(image); + RwImageSetFromRaster(image, RwTextureGetRaster(tex)); + + iColor_tag* bits = (iColor_tag*)RwImageGetPixels(image); + + for (S32 i = 0; a.char_set[i] != '\0'; i++) + { + if (a.flags & 0x4) + { + char_bounds.x = a.u + char_bounds.w * (i / a.line_size); + char_bounds.y = a.v + char_bounds.h * (i % a.line_size); + } + else + { + char_bounds.x = a.u + char_bounds.w * (i % a.line_size); + char_bounds.y = a.v + char_bounds.h * (i / a.line_size); + } + + basic_rect r = + find_bounds(bits + width * char_bounds.y + char_bounds.x, char_bounds, width); + + if (a.flags & 0x8) + { + a.char_pos[i].offset = 0; + a.char_pos[i].size = char_bounds.w; + } + else + { + a.char_pos[i].offset = r.x - char_bounds.x; + a.char_pos[i].size = r.w; + } + + S32 baseline = r.y - char_bounds.y + r.h + 1; + + if (++baseline_count[baseline] > baseline_count[a.baseline]) + { + a.baseline = baseline; + } + } + + RwImageDestroy(image); + return true; + } + + // FIXME: Float conversions seem to need work + basic_rect get_tex_bounds(const font_data& fd, U8 c) + { + typedef __typeof__(((struct font_asset){ 0 }).char_pos[0]) char_pos_t; + + F32 boundX; + F32 boundY; + F32 boundW; + F32 boundH; + char_pos_t* temp_r8; + + if (fd.asset->flags & 0x4) + { + boundX = (F32)(c / fd.asset->line_size); + boundY = (F32)(c % fd.asset->line_size); + } + else + { + boundY = (F32)(c / fd.asset->line_size); + boundX = (F32)(c % fd.asset->line_size); + } + + temp_r8 = &fd.asset->char_pos[c]; + boundX = (F32)(temp_r8->offset + (fd.asset->du * boundX + (F32)fd.asset->u)); + boundW = (F32)temp_r8->size - 0.5f; + boundY = ((F32)fd.asset->dv * boundY) + (F32)fd.asset->v; + boundH = (F32)fd.asset->dv - 0.5f; + + basic_rect result = { boundX, boundY, boundW, boundH }; + result.scale((F32)fd.asset->dv, (F32)fd.asset->v); + return result; + } + +#if 1 + basic_rect get_bounds(const font_data& fd, U8 c); +#else + basic_rect get_bounds(const font_data& fd, U8 c) + { + // todo: uses int-to-float conversion + } +#endif + +#if 1 + bool init_font_data(font_data& fd); +#else + bool init_font_data(font_data& fd) + { + // todo: uses int-to-float conversion + } +#endif + + void start_tex_render(U32 font_id) + { + font_data& fd = active_fonts[font_id]; + + rcz = 1.0f / RwCameraGetNearClipPlane(RwCameraGetCurrentCamera()); + nsz = RwIm2DGetNearScreenZ(); + + xfont::set_render_state(fd.raster); + } + + void tex_flush() + { + if (vert_buffer_used) + { + RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, vert_buffer, vert_buffer_used); + vert_buffer_used = 0; + } + } + + void stop_tex_render() + { + tex_flush(); + xfont::restore_render_state(); + } + + void set_vert(RwIm2DVertex& vert, F32 x, F32 y, F32 u, F32 v, iColor_tag c); + + void tex_render(const basic_rect& src, const basic_rect& dst, + const basic_rect& clip, iColor_tag color) + { + basic_rect r = dst; + basic_rect rt = src; + + clip.clip(r, rt); + + if (r.empty()) + { + return; + } + + if (vert_buffer_used == VERT_BUFFER_SIZE) + { + RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, vert_buffer, VERT_BUFFER_SIZE); + vert_buffer_used = 0; + } + + RwIm2DVertex* vert = &vert_buffer[vert_buffer_used]; + + r.scale(640.0f, 480.0f); + + set_vert(vert[0], r.x, r.y, rt.x, rt.y, color); + set_vert(vert[1], r.x, r.y + r.h, rt.x, rt.y + rt.h, color); + set_vert(vert[2], r.x + r.w, r.y, rt.x + rt.w, rt.y, color); + + vert[3] = vert[2]; + vert[4] = vert[1]; + + set_vert(vert[5], r.x + r.w, r.y + r.h, rt.x + rt.w, rt.y + rt.h, color); + + vert_buffer_used += 6; + } +} // namespace + +namespace +{ + void set_vert(RwIm2DVertex& vert, F32 x, F32 y, F32 u, F32 v, iColor_tag c) + { + RwIm2DVertexSetScreenX(&vert, x); + RwIm2DVertexSetScreenY(&vert, y); + RwIm2DVertexSetScreenZ(&vert, nsz); + RwIm2DVertexSetU(&vert, u, rcz); + RwIm2DVertexSetV(&vert, v, rcz); + RwIm2DVertexSetIntRGBA(&vert, c.r, c.g, c.b, c.a); + } + + void init_model_cache() + { + struct model_pool + { + RwMatrix mat[MODEL_CACHE_SIZE]; + xModelInstance model[MODEL_CACHE_SIZE]; + }; + + // non-matching: two instructions swapped + + model_cache_inited = true; + + void* data = xMemAlloc(gActiveHeap, sizeof(model_pool), 16); + memset(data, 0, sizeof(model_pool)); + + model_pool& pool = *(model_pool*)data; + + for (U32 i = 0; i < MODEL_CACHE_SIZE; i++) + { + xModelInstance& model = pool.model[i]; + model_cache_entry& e = model_cache[i]; + + e.order = 0; + e.id = 0; + e.model = &model; + + model.Mat = &pool.mat[i]; + model.Flags = 0x1; + model.BoneCount = 1; + model.shadowID = 0xDEADBEEF; + } + } + +#ifndef NON_MATCHING + static U32 next_order_967; + static signed char init_968; + + xModelInstance* load_model(U32 id); +#else + xModelInstance* load_model(U32 id) + { + static U32 next_order = 0; + U32 oldest = 0; + + next_order++; + + for (U32 i = 0; i < MODEL_CACHE_SIZE; i++) + { + model_cache_entry& e = model_cache[i]; + + if (e.id == id) + { + e.order = next_order; + return e.model; + } + + if (e.order < model_cache[oldest].order) + { + oldest = i; + } + } + + RpAtomic* mf = (RpAtomic*)xSTFindAsset(id, NULL); + + if (!mf) + { + return NULL; + } + + // non-matching: instruction order + + model_cache_entry& e = model_cache[oldest]; + + e.id = id; + e.order = next_order; + + xModelInstance& model = *e.model; + + xMat4x3Identity((xMat4x3*)model.Mat); + + model.Data = mf; + model.Bucket = xModelBucket_GetBuckets(model.Data); + model.PipeFlags = + (model.Bucket) ? model.Bucket[0]->PipeFlags : xModelGetPipeFlags(model.Data); + + return &model; + } +#endif +} // namespace + +void xfont::init() +{ + active_fonts_size = 0; + + for (size_t i = 0; i < sizeof(default_font_assets) / sizeof(font_asset); i++) + { + if (default_font_assets[i].tex_id < sizeof(default_font_texture) / sizeof(const char*)) + { + default_font_assets[i].tex_id = + xStrHash(default_font_texture[default_font_assets[i].tex_id]); + } + + xSTFindAsset(default_font_assets[i].tex_id, NULL); + + if (reset_font_spacing(default_font_assets[i])) + { + font_data& fd = active_fonts[active_fonts_size]; + fd.asset = &default_font_assets[i]; + + if (init_font_data(fd)) + { + active_fonts_size++; + } + } + } + + init_model_cache(); +} + +namespace +{ + struct + { + S32 fogenable; + S32 vertexalphaenable; + S32 zwriteenable; + S32 ztestenable; + U32 srcblend; + U32 destblend; + U32 shademode; + RwRaster* textureraster; + RwTextureFilterMode filter; + } oldrs; +} // namespace + +void xfont::set_render_state(RwRaster* raster) +{ + RwRenderStateGet(rwRENDERSTATEFOGENABLE, (void*)&oldrs.fogenable); + RwRenderStateGet(rwRENDERSTATESRCBLEND, (void*)&oldrs.srcblend); + RwRenderStateGet(rwRENDERSTATEDESTBLEND, (void*)&oldrs.destblend); + RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)&oldrs.vertexalphaenable); + RwRenderStateGet(rwRENDERSTATETEXTURERASTER, (void*)&oldrs.textureraster); + RwRenderStateGet(rwRENDERSTATESHADEMODE, (void*)&oldrs.shademode); + RwRenderStateGet(rwRENDERSTATEZWRITEENABLE, (void*)&oldrs.zwriteenable); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)&oldrs.ztestenable); // RwRenderStateSet lol + RwRenderStateGet(rwRENDERSTATETEXTUREFILTER, (void*)&oldrs.filter); + + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)raster); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); +} + +void xfont::restore_render_state() +{ + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)oldrs.fogenable); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)oldrs.srcblend); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)oldrs.destblend); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)oldrs.vertexalphaenable); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)oldrs.textureraster); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)oldrs.shademode); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)oldrs.zwriteenable); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)oldrs.ztestenable); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)oldrs.filter); +} + +basic_rect xfont::bounds(char c) const +{ + font_data& fd = active_fonts[id]; + U32 char_index = fd.char_index[c]; + + if (fd.char_index[c] == 0xFF) + { + // non-matching: scheduling + return basic_rect::m_Null; + } + + basic_rect r = fd.bounds[char_index]; + r.scale(width, height); + return r; +} + +basic_rect xfont::bounds(const char* text) const +{ + size_t size; + return bounds(text, 0x40000000, 1.0e38f, size); +} + +basic_rect xfont::bounds(const char* text, size_t text_size, F32 max_width, size_t& size) const +{ + font_data& fd = active_fonts[id]; + basic_rect r; + + r.x = 0.0f; + r.y = fd.bounds[0].y * height; + r.w = 0.0f; + r.h = fd.bounds[0].h * height; + + if (!text || !text_size) + { + size = 0; + return r; + } + + const char* s = text; + U32 i = 0; + + while (i < text_size && *s != '\0') + { + U32 charIndex = fd.char_index[*s]; + + if (charIndex != 0xFF) + { + F32 dx = fd.bounds[charIndex].w * width; + + if (r.w + dx > max_width) + { + break; + } + + r.w += dx + space; + } + + i++; + s++; + } + + if (r.w > 0.0f) + { + r.w -= space; + } + + size = s - text; + return r; +} + +void xfont::start_render() const +{ + start_tex_render(id); +} + +void xfont::stop_render() const +{ + stop_tex_render(); +} + +namespace +{ + void char_render(U8 c, U32 font_index, const basic_rect& bounds, + const basic_rect& clip, iColor_tag color) + { + font_data& fd = active_fonts[font_index]; + U32 char_index = fd.char_index[c]; + + if (char_index >= fd.index_max) + { + return; + } + + basic_rect dst = fd.bounds[char_index]; + dst.scale(bounds.w, bounds.h); + dst.x += bounds.x; + dst.y += bounds.y; + dst.w *= fd.dstfrac[char_index].x; + dst.h *= fd.dstfrac[char_index].y; + + tex_render(fd.tex_bounds[char_index], dst, clip, color); + } + + RwRaster* set_tex_raster(RwRaster* raster) + { + RwRaster* r; + RwRenderStateGet(rwRENDERSTATETEXTURERASTER, (void*)&r); + + if (raster == r) + { + return raster; + } + + tex_flush(); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)raster); + + return r; + } +} // namespace + +void xfont::irender(const char* text, F32 x, F32 y) const +{ + irender(text, 0x40000000, x, y); +} + +static const basic_rect _1107 = {}; + +void xfont::irender(const char* text, size_t text_size, F32 x, F32 y) const +{ + if (!text) + { + return; + } + + font_data& fd = active_fonts[id]; + + set_tex_raster(fd.raster); + + basic_rect bounds = { x, y, width, height }; + U32 i = 0; + + // non-matching: color not stored in r28 + + while (i < text_size && text[i] != '\0') + { + char c = text[i]; + + char_render(c, id, bounds, clip, color); + + U32 charIndex = fd.char_index[c]; + + if (charIndex != 255) + { + bounds.x += fd.bounds[charIndex].w * width + space; + } + + i++; + } +} + +extern substr text_delims; + +namespace +{ + + size_t parse_split_tag(xtextbox::split_tag& ti) + { + ti.value.size = 0; + ti.action.size = 0; + ti.name.size = 0; + + // non-matching: scheduling + + substr s; + + s.text = ti.tag.text; + s.size = ti.tag.size; + + s.text++; + s.size--; + + ti.name.text = skip_ws(s); + s.text = find_char(s, text_delims); + + if (!s.text) + { + return 0; + } + + ti.name.size = s.text - ti.name.text; + s.size -= ti.name.size; + ti.action.text = skip_ws(s); + + if (!s.size) + { + return 0; + } + + char c = s.text[0]; + + if (c == '\0' || c == '{') + { + return 0; + } + + s.text++; + s.size--; + + if (c == '}') + { + return ti.tag.size - s.size; + } + + ti.action.size = 1; + ti.value.text = skip_ws(s); + s.text = find_char(s, '}'); + s.size -= s.text - ti.value.text; + + if (!s.text) + { + return 0; + } + + ti.value.size = s.text - ti.value.text; + + rskip_ws(ti.value); + + s.text++; + s.size--; + + return ti.tag.size - s.size; + } + + const char* parse_next_tag_jot(xtextbox::jot& a, const xtextbox& tb, const xtextbox& ctb, + const char* text, size_t text_size) + { + xtextbox::split_tag ti = {}; + ti.tag.text = text; + ti.tag.size = text_size; + + size_t size = parse_split_tag(ti); + + if (!size) + { + return NULL; + } + + a.s.text = text; + a.s.size = size; + a.flag.invisible = a.flag.ethereal = true; + + if (icompare(ti.name, substr::create("~", 1)) == 0 || + icompare(ti.name, substr::create("reset", 5)) == 0) + { + a.tag = xtextbox::find_format_tag(ti.value); + + if (a.tag && a.tag->reset_tag) + { + a.tag->reset_tag(a, tb, ctb, ti); + } + } + else + { + a.tag = xtextbox::find_format_tag(ti.name); + + if (a.tag && a.tag->parse_tag) + { + a.tag->parse_tag(a, tb, ctb, ti); + } + } + + return text + size; + } + + const char* parse_next_text_jot(xtextbox::jot& a, const xtextbox& tb, const xtextbox& ctb, + const char* text, size_t text_size) + { + char c = text[0]; + + a.s.text = text; + a.s.size = 1; + a.flag.merge = true; + + if (c == '\n') + { + a.flag.line_break = true; + } + else if (c == '\t') + { + a.flag.tab = true; + } + else if (c == '-') + { + a.flag.word_end = true; + } + + if (is_ws(c)) + { + a.flag.invisible = a.flag.word_break = true; + } + + a.bounds = tb.font.bounds(c); + a.cb = &xtextbox::text_cb; + a.context = NULL; + a.context_size = 0; + + return a.s.text + a.s.size; + } + + const char* parse_next_jot(xtextbox::jot& a, const xtextbox& tb, const xtextbox& ctb, + const char* text, size_t text_size) + { + const char* ret; + + if (text[0] != '{' || !(ret = parse_next_tag_jot(a, tb, ctb, text, text_size))) + { + ret = parse_next_text_jot(a, tb, ctb, text, text_size); + } + + a.flag.merge = a.flag.merge && !(tb.flags & FLAG_UNK80); + return ret; + } + + struct tex_args + { + RwRaster* raster; + F32 rot; + basic_rect src; + basic_rect dst; + xVec2 off; + enum + { + SCALE_FONT, + SCALE_SCREEN, + SCALE_SIZE, + SCALE_FONT_WIDTH, + SCALE_FONT_HEIGHT, + SCALE_SCREEN_WIDTH, + SCALE_SCREEN_HEIGHT + } scale; + }; + + struct model_args + { + xModelInstance* model; + xVec3 rot; + basic_rect dst; + xVec2 off; + enum + { + SCALE_FONT, + SCALE_SCREEN, + SCALE_SIZE + } scale; + }; + + tex_args def_tex_args; + model_args def_model_args; + + void reset_tex_args(tex_args& ta) + { + ta.raster = NULL; + ta.rot = 0.0f; + ta.src = ta.dst = basic_rect::m_Unit; + ta.off.x = ta.off.y = 1.0f; + ta.scale = tex_args::SCALE_FONT; + } + + void load_tex_args(tex_args& ta, const substr& s) + { + xtextbox::tag_entry_list el = xtextbox::read_tag(s); + xtextbox::tag_entry* e; + + if (el.size == 0) + { + return; + } + + e = &el.entries[0]; + + if (e->op == ':' || (e->args_size == 1 && e->args[0].size)) + { + substr& name = e->args[0]; + U32 id; + + if (name.size == 10 && imemcmp(name.text, "0x", 2) == 0) + { + id = atox(substr::create(name.text + 2, 8)); + } + else + { + id = xStrHash(name.text, name.size); + } + + RwTexture* texture = (RwTexture*)xSTFindAsset(id, NULL); + + if (texture && texture->raster && texture->raster->width > 0 && + texture->raster->height > 0 && texture->raster->width <= 4096 && + texture->raster->height <= 4096) + { + RwTextureSetFilterMode(texture, rwFILTERLINEAR); + ta.raster = texture->raster; + } + } + + el.entries++; + el.size--; + + e = xtextbox::find_entry(el, substr::create("rot", 3)); + + if (e && e->op == '=' && e->args_size == 1) + { + xtextbox::read_list(*e, &ta.rot, 1); + } + + e = xtextbox::find_entry(el, substr::create("src", 3)); + + if (e && e->op == '=' && e->args_size == 4) + { + xtextbox::read_list(*e, (F32*)&ta.src, 4); + } + + e = xtextbox::find_entry(el, substr::create("dst", 3)); + + if (e && e->op == '=' && e->args_size == 4) + { + xtextbox::read_list(*e, (F32*)&ta.dst, 4); + } + + e = xtextbox::find_entry(el, substr::create("off", 3)); + + if (e && e->op == '=' && e->args_size == 2) + { + xtextbox::read_list(*e, (F32*)&ta.off, 2); + } + + e = xtextbox::find_entry(el, substr::create("scale", 5)); + + if (e && e->op == '=' && e->args_size == 1) + { + if (icompare(e->args[0], substr::create("font", 4)) == 0) + { + ta.scale = tex_args::SCALE_FONT; + } + else if (icompare(e->args[0], substr::create("screen", 6)) == 0) + { + ta.scale = tex_args::SCALE_SCREEN; + } + else if (icompare(e->args[0], substr::create("size", 4)) == 0) + { + ta.scale = tex_args::SCALE_SIZE; + } + else if (icompare(e->args[0], substr::create("font_width", 10)) == 0) + { + ta.scale = tex_args::SCALE_FONT_WIDTH; + } + else if (icompare(e->args[0], substr::create("font_height", 11)) == 0) + { + ta.scale = tex_args::SCALE_FONT_HEIGHT; + } + else if (icompare(e->args[0], substr::create("screen_width", 12)) == 0) + { + ta.scale = tex_args::SCALE_SCREEN_WIDTH; + } +#if 1 // needed until .sdata2 is decomped + else if (icompare(e->args[0], substr::create("screen_height\0=:+*;}\0,;}", 13)) == +#else + else if (icompare(e->args[0], substr::create("screen_height", 13)) == +#endif + 0) // screen_height + { + ta.scale = tex_args::SCALE_SCREEN_HEIGHT; + } + else + { + ta.scale = tex_args::SCALE_FONT; + } + } + } + + void reset_model_args(model_args& ma) + { + ma.model = NULL; + ma.rot = xVec3::m_Null; + ma.dst = basic_rect::m_Unit; + ma.off.x = ma.off.y = 1.0f; + ma.scale = model_args::SCALE_FONT; + } + + void load_model_args(model_args& ma, const substr& s) + { + xtextbox::tag_entry_list el = xtextbox::read_tag(s); + xtextbox::tag_entry* e; + + if (!el.size) + { + return; + } + + e = &el.entries[0]; + + if (e->op == ':' || (e->args_size == 1 && e->args[0].size)) + { + substr& name = e->args[0]; + + ma.model = load_model(xStrHash(name.text, name.size)); + } + + el.entries++; + el.size--; + + e = xtextbox::find_entry(el, substr::create("rot", 3)); + + if (e && e->op == '=' && e->args_size == 3) + { + xtextbox::read_list(*e, (F32*)&ma.rot, 3); + } + + e = xtextbox::find_entry(el, substr::create("dst", 3)); + + if (e && e->op == '=' && e->args_size == 4) + { + xtextbox::read_list(*e, (F32*)&ma.dst, 4); + } + + e = xtextbox::find_entry(el, substr::create("off", 3)); + + if (e && e->op == '=' && e->args_size == 2) + { + xtextbox::read_list(*e, (F32*)&ma.off, 2); + } + + e = xtextbox::find_entry(el, substr::create("scale", 5)); + + if (e && e->op == '=' && e->args_size == 1) + { + if (icompare(e->args[0], substr::create("screen", 6)) == 0) + { + ma.scale = model_args::SCALE_SCREEN; + } + else + { + ma.scale = model_args::SCALE_FONT; + } + } + } + + void start_layout(const xtextbox&) + { + reset_tex_args(def_tex_args); + reset_model_args(def_model_args); + } + + void stop_layout(const xtextbox&) + { + } + + void start_render(const xtextbox& tb) + { + tb.font.start_render(); + } + + void stop_render(const xtextbox& tb) + { + tb.font.stop_render(); + } +} // namespace + +void xtextbox::text_render(const jot& j, const xtextbox& tb, F32 x, F32 y) +{ + tb.font.irender(j.s.text, j.s.size, x, y); +} + +void xtextbox::set_text(const char* text) +{ + set_text(text, 0x40000000); +} + +void xtextbox::set_text(const char* text, size_t text_size) +{ + if (!text || !text_size) + { + texts_size = 0; + text_hash = 0; + return; + } + + this->text.text = text; + this->text.size = text_size; + + set_text(&this->text.text, &this->text.size, 1); +} + +void xtextbox::set_text(const char** texts, size_t size) +{ + set_text(texts, NULL, size); +} + +void xtextbox::set_text(const char** texts, const size_t* text_sizes, size_t size) +{ + this->texts_size = size; + this->text_hash = 0; + + if (!size) + { + return; + } + + this->texts = texts; + this->text_sizes = text_sizes; + + if (!text_sizes) + { + for (size_t i = 0; i < size; i++) + { + this->text_hash = this->text_hash * 131 + xStrHash(texts[i]); + } + } + else + { + for (size_t i = 0; i < size; i++) + { + this->text_hash = this->text_hash * 131 + xStrHash(texts[i], text_sizes[i]); + } + } +} + +namespace tweaker +{ + namespace + { + void log_cache(bool) + { + } + } // namespace +} // namespace tweaker + +namespace +{ + struct tl_cache_entry + { + U32 used; + iTime last_used; + xtextbox::layout tl; + }; + +#ifdef GAMECUBE +#define TL_CACHE_COUNT 1 +#else +#ifdef PS2 +#define TL_CACHE_COUNT 3 +#endif +#endif + + tl_cache_entry tl_cache[TL_CACHE_COUNT]; +} // namespace + +#if 1 + +#else +xtextbox::layout& xtextbox::temp_layout(bool cache) const +{ + // todo: uses int-to-float conversion +} +#endif + +void xtextbox::render(layout& l, S32 begin_jot, S32 end_jot) const +{ + l.render(*this, begin_jot, end_jot); +} + +F32 xtextbox::yextent(F32 max, S32& size, const layout& l, S32 begin_jot, S32 end_jot) const +{ + return l.yextent(max, size, begin_jot, end_jot); +} + +xtextbox::callback xtextbox::text_cb = { xtextbox::text_render, NULL, NULL }; + +#define skip_char_ptr(s, p) \ + { \ + const char* temp = (s).text; \ + (s).text = (p) + 1; \ + (s).size -= (p) + 1 - temp; \ + } + +#define skip_char(s, c) \ + { \ + const char* p = find_char((s), (c)); \ + if (p) \ + { \ + skip_char_ptr((s), p); \ + } \ + } + +#ifndef NON_MATCHING +static substr arg_buffer_1611[32]; +static xtextbox::tag_entry entry_buffer_1612[16]; + +#else +xtextbox::tag_entry_list xtextbox::read_tag(const substr& s) +{ + static substr arg_buffer[32]; + static xtextbox::tag_entry entry_buffer[16]; + + U32 entries_used = 0; + U32 args_used = 0; + + substr it = s; + + skip_char(it, '{'); + + substr delims = _1615; + substr sub_delims = _1616; + + while (it.size) + { + tag_entry& entry = entry_buffer[entries_used]; + + entry.args_size = 0; + entry.op = 0; + entry.name.text = it.text; + + const char* d = find_char(it, delims); + + entry.name.size = (d) ? it.size : d - it.text; + + trim_ws(entry.name); + + if (entry.name.size) + { + entries_used++; + } + + if (!d || *d == '}') + { + break; + } + + skip_char_ptr(it, d); + + if (*d != ';') + { + substr& arg = arg_buffer[args_used]; + + entry.op = *d; + entry.args = &arg; + + while (it.size) + { + arg.text = it.text; + + const char* d = find_char(it, sub_delims); + + if (!d) + { + arg.size = it.size; + it.size = 0; + } + else + { + arg.size = d - it.text; + it.size -= arg.size + 1; + it.text += arg.size + 1; + } + + trim_ws(arg); + + if (arg.size) + { + // non-matching: missing addi instruction + args_used++; + entry.args_size++; + } + + if (!d || *d == '}') + { + it.size = 0; + break; + } + else if (*d == ';') + { + break; + } + } + } + } + + tag_entry_list ret = _1642; + ret.size = entries_used; + + return ret; +} +#endif + +xtextbox::tag_entry* xtextbox::find_entry(const tag_entry_list& el, const substr& name) +{ + // non-matching: el.size and el.entries are not cached at the beginning + + for (size_t i = 0; i < el.size; i++) + { + tag_entry& e = el.entries[i]; + + if (icompare(name, e.name) == 0) + { + return &e; + } + } + + return NULL; +} + +size_t xtextbox::read_list(const tag_entry& e, F32* v, size_t vsize) +{ + size_t total = e.args_size; + + if (vsize < total) + { + total = vsize; + } + + // non-matching: e.args is not stored in r31 + + for (size_t i = 0; i < total; i++) + { + v[i] = xatof(e.args[i].text); + } + + return total; +} + +size_t xtextbox::read_list(const tag_entry& e, S32* v, size_t vsize) +{ + size_t total = e.args_size; + + if (vsize < total) + { + total = vsize; + } + + // non-matching: e.args is not stored in r31 + + for (size_t i = 0; i < total; i++) + { + v[i] = atoi(e.args[i].text); + } + + return total; +} + +void xtextbox::clear_layout_cache() +{ + for (U32 index = 0; index < TL_CACHE_COUNT; index++) + { + tl_cache[index].tl.clear(); + } +} + +void xtextbox::layout::refresh(const xtextbox& tb, bool force) +{ + if (force || changed(tb)) + { + this->tb = tb; + calc(tb, 0); + } +} + +void xtextbox::layout::refresh_end(const xtextbox& tb) +{ + size_t texts_size = this->tb.texts_size; + + if (texts_size > tb.texts_size) + { + this->tb = tb; + calc(tb, texts_size); + } +} + +void xtextbox::layout::clear() +{ + dynamics_size = 0; + context_buffer_size = 0; + _lines_size = 0; + _jots_size = 0; + tb = xtextbox::create(); +} + +void xtextbox::layout::trim_line(jot_line& line) +{ + // non-matching: mtctr and bdnz not generated + + for (S32 i = line.last - 1; i >= line.first; i--) + { + jot& a = _jots[i]; + + if (!a.flag.ethereal) + { + if (a.flag.invisible) + { + erase_jots(i, i + 1); + line.last--; + } + + break; + } + } + + for (S32 i = line.first; i < line.last; i++) + { + jot& a = _jots[i]; + + if (!a.flag.ethereal) + { + if (a.flag.invisible) + { + erase_jots(i, i + 1); + } + + break; + } + } +} + +void xtextbox::layout::erase_jots(size_t begin_jot, size_t end_jot) +{ + if (end_jot >= _jots_size) + { + _jots_size = begin_jot; + return; + } + + size_t erase_size = end_jot - begin_jot; + + _jots_size -= erase_size; + + for (size_t i = begin_jot; i < _jots_size; i++) + { + _jots[i] = _jots[i + erase_size]; + } +} + +void xtextbox::layout::merge_line(jot_line& line) +{ + size_t d = line.first; + size_t i = line.first + 1; + + while (i != line.last) + { + jot& a1 = _jots[d]; + jot& a2 = _jots[i]; + + if (!a1.flag.ethereal && !a2.flag.ethereal && a1.flag.merge && a2.flag.merge && + a1.cb == a2.cb) + { + a1.s.size = a2.s.text - a1.s.text + a2.s.size; + a1.bounds |= a2.bounds; + a1.intersect_flags(a2); + } + else + { + d++; + + if (d != i) + { + _jots[d] = a2; + } + } + + i++; + } + + erase_jots(d + 1, line.last); + line.last = d + 1; +} + +void xtextbox::layout::bound_line(jot_line& line) +{ + line.bounds.w = line.bounds.h = line.baseline = 0.0f; + + for (size_t i = line.first; i != line.last; i++) + { + jot& a = _jots[i]; + + if (!a.flag.ethereal && -a.bounds.y > line.baseline) + { + line.baseline = -a.bounds.y; + } + } + + for (size_t i = line.first; i != line.last; i++) + { + jot& a = _jots[i]; + + if (!a.flag.ethereal) + { + a.bounds.x = line.bounds.w; + line.bounds.w += a.bounds.w; + + F32 total_height = line.baseline + a.bounds.y + a.bounds.h; + + if (total_height > line.bounds.h) + { + line.bounds.h = total_height; + } + } + } + + line.page_break = (line.last > line.first && _jots[line.last - 1].flag.page_break); +} + +bool xtextbox::layout::fit_line() +{ + jot_line& line = _lines[_lines_size]; + + if (line.bounds.w > tb.bounds.w) + { + switch (tb.flags & WRAP_MASK) + { + case WRAP_CHAR: + { + if (line.last > line.first + 1) + { + line.last--; + } + + break; + } + case WRAP_NONE: + { + return false; + } + default: + { + for (S32 i = (S32)line.last - 1; i > (S32)line.first; i--) + { + if (_jots[i].flag.word_break) + { + line.last = i + 1; + break; + } + else if (_jots[i - 1].flag.word_end) + { + line.last = i; + break; + } + } + + if (line.last <= line.first) + { + line.last = line.first + 1; + } + + trim_line(line); + break; + } + } + } + + merge_line(line); + bound_line(line); + + return true; +} + +void xtextbox::layout::next_line() +{ + jot_line& line1 = _lines[_lines_size]; + + _lines_size++; + + jot_line& line2 = _lines[_lines_size]; + + line2.first = line1.last; + line2.last = _jots_size; + line2.bounds.x = 0.0f; + line2.bounds.y = line1.bounds.y + line1.bounds.h; + + bound_line(line2); +} + +void xtextbox::layout::calc(const xtextbox& ctb, size_t start_text) +{ + if (!start_text) + { + dynamics_size = 0; + context_buffer_size = 0; + _lines_size = 0; + _jots_size = 0; + } + + if (!tb.texts_size) + { + return; + } + + start_layout(ctb); + + jot_line& first_line = _lines[_lines_size]; + first_line.first = 0; + first_line.bounds.w = 0.0f; + first_line.bounds.x = 0.0f; + first_line.bounds.y = 0.0f; + first_line.baseline = 0.0f; + + struct + { + const char* s; + const char* end; + } text_stack[16]; + + size_t text_stack_size = 0; + size_t size = ((!tb.text_sizes) ? 0x40000000 : tb.text_sizes[start_text]); + size_t text_index = start_text + 1; + const char* s = tb.texts[start_text]; + const char* end = s + size; + const char* r25; + + while (true) + { + jot& a = _jots[_jots_size]; + jot_line& line = _lines[_lines_size]; + + a.context = &context_buffer[context_buffer_size]; + a.context_size = 0; + a.reset_flags(); + a.cb = NULL; + a.tag = NULL; + + if (s == end || *s == '\0') + { + if (text_stack_size) + { + text_stack_size--; + s = text_stack[text_stack_size].s; + end = text_stack[text_stack_size].end; + } + else if (text_index < tb.texts_size) + { + size = ((!tb.text_sizes) ? 0x40000000 : tb.text_sizes[text_index]); + + s = tb.texts[text_index]; + end = s + size; + text_index++; + } + else + { + break; + } + + a.flag.invisible = a.flag.ethereal = true; + a.s = substr::create(NULL, 0); + + _jots_size++; + } + else + { + r25 = parse_next_jot(a, tb, ctb, s, end - s); + + if (a.context == &context_buffer[context_buffer_size]) + { + context_buffer_size += ALIGN(a.context_size, 4); + } + + _jots_size++; + + if (a.cb && a.cb->layout_update) + { + a.cb->layout_update(a, tb, ctb); + } + + if (a.flag.stop) + { + break; + } + + if (!a.flag.ethereal) + { + a.bounds.x += line.bounds.w; + line.bounds.w += a.bounds.w; + + if (line.bounds.w >= tb.bounds.w) + { + line.last = _jots_size; + + if (!fit_line()) + { + break; + } + + next_line(); + } + } + + if (a.flag.line_break || a.flag.page_break) + { + line.last = _jots_size; + + if (!fit_line()) + { + break; + } + + next_line(); + } + + s = r25; + + if (a.flag.insert) + { + s = (const char*)a.context; + text_stack[text_stack_size].s = r25; + text_stack[text_stack_size].end = end; + text_stack_size++; + end = s + a.context_size; + } + } + } + + jot_line& last_line = _lines[_lines_size]; + + if (last_line.first < _jots_size) + { + last_line.last = _jots_size; + + if (fit_line()) + { + _lines_size++; + } + } + + for (size_t i = 0; i < _jots_size; i++) + { + if (_jots[i].flag.dynamic) + { + dynamics[dynamics_size++] = i; + } + } + + stop_layout(ctb); +} + +void xtextbox::layout::render(const xtextbox& ctb, S32 begin_jot, S32 end_jot) +{ + if (begin_jot < 0) + { + begin_jot = 0; + } + + if (end_jot < begin_jot) + { + end_jot = _jots_size; + } + + if (begin_jot >= end_jot) + { + return; + } + + tb = ctb; + start_render(ctb); + + S32 begin_line = 0; + + while (true) + { + if (begin_line >= (S32)_lines_size) + { + stop_render(ctb); + return; + } + + if ((S32)_lines[begin_line].last > begin_jot) + { + break; + } + + begin_line++; + } + + for (S32 i = 0; i < begin_jot; i++) + { + jot& j = _jots[i]; + + if (j.cb && j.cb->render_update) + { + j.cb->render_update(j, tb, ctb); + } + } + + F32 top = _lines[begin_line].bounds.y; + U32 li = begin_line - 1; + S32 line_last = -1; + F32 x, y; + + for (S32 i = begin_jot; i < end_jot; i++) + { + if (i >= line_last) + { + li++; + jot_line& line = _lines[li]; + + line_last = line.last; + + x = tb.bounds.x + line.bounds.x; + y = tb.bounds.y + line.bounds.y + line.baseline - top; + + U32 xj = tb.flags & XJUSTIFY_MASK; + + if (xj == XJUSTIFY_CENTER) + { + x += 0.5f * (tb.bounds.w - line.bounds.w); + } + else if (xj == XJUSTIFY_RIGHT) + { + x += tb.bounds.w - line.bounds.w; + } + + if (line.page_break && end_jot > line_last) + { + end_jot = line_last; + } + } + + jot& j = _jots[i]; + + if (j.cb) + { + if (j.cb->render_update) + { + j.cb->render_update(j, tb, ctb); + } + + if (!j.flag.ethereal && !j.flag.invisible && j.cb->render) + { + j.cb->render(j, tb, x + j.bounds.x, y); + } + } + } + + stop_render(ctb); +} + +// this is different than the one in xMath.h +#define min(a, b) ((a) >= (b) ? (b) : (a)) + +F32 xtextbox::layout::yextent(F32 max, S32& size, S32 begin_jot, S32 end_jot) const +{ + size = 0; + + if (begin_jot < 0) + { + begin_jot = 0; + } + + if (end_jot < begin_jot) + { + end_jot = _jots_size; + } + + if (begin_jot >= end_jot) + { + return 0.0f; + } + + S32 begin_line = 0; + + while (true) + { + if (begin_line >= (S32)_lines_size) + { + return 0.0f; + } + + if ((S32)_lines[begin_line].last > begin_jot) + { + break; + } + + begin_line++; + } + + // non-matching: wrong float registers + F32 top = _lines[begin_line].bounds.y; + S32 i = begin_line; + + while (true) + { + if (i == (S32)_lines_size) + { + break; + } + + // non-matching: r11 missing + const jot_line& line = _lines[i]; + + if (line.bounds.y + line.bounds.h > max + top) + { + i--; + break; + } + + if ((S32)line.last >= end_jot) + { + break; + } + + if (line.page_break) + { + break; + } + + i++; + } + + if (i < begin_line) + { + return 0.0f; + } + + const jot_line& line = _lines[i]; + + size = min((S32)line.last, end_jot) - begin_jot; + + return line.bounds.y + line.bounds.h - top; +} + +bool xtextbox::layout::changed(const xtextbox& ctb) +{ + U32 flags1 = tb.flags & (WRAP_MASK | FLAG_UNK40); + U32 flags2 = ctb.flags & (WRAP_MASK | FLAG_UNK40); + + if (tb.text_hash != ctb.text_hash || tb.font.id != ctb.font.id || + tb.font.width != ctb.font.width || tb.font.height != ctb.font.height || + tb.font.space != ctb.font.space || tb.bounds.w != ctb.bounds.w || flags1 != flags2 || + tb.line_space != ctb.line_space) + { + return true; + } + + S32 i = dynamics_size; + + while (i > 0) + { + i--; + + jot& j = _jots[dynamics[i]]; + U32 oldval = xStrHash((char*)j.context, j.context_size); + + parse_next_jot(j, tb, ctb, j.s.text, j.s.size); + + U32 val = xStrHash((char*)j.context, j.context_size); + + if (val != oldval) + { + return true; + } + } + + return false; +} + +namespace +{ + void update_tag_alpha(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.font.color.a = 255.0f * (F32&)j.context + 0.5f; + } + + void update_tag_reset_alpha(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.font.color.a = ctb.font.color.a; + } + + static const xtextbox::callback cb_2178 = { NULL, update_tag_alpha, update_tag_alpha }; + +#if 1 + void parse_tag_alpha(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti); +#else + void parse_tag_alpha(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + // todo: uses int-to-float conversion + } +#endif + + void reset_tag_alpha(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_alpha, + update_tag_reset_alpha }; + a.cb = &cb; + } + + void update_tag_red(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.font.color.r = 255.0f * (F32&)j.context + 0.5f; + } + + void update_tag_reset_red(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.font.color.r = ctb.font.color.r; + } + + static const xtextbox::callback cb_2217 = { NULL, update_tag_red, update_tag_red }; + +#if 1 + void parse_tag_red(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti); +#else + void parse_tag_red(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + // todo: uses int-to-float conversion + } +#endif + + void reset_tag_red(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_red, update_tag_reset_red }; + a.cb = &cb; + } + + void update_tag_green(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.font.color.g = 255.0f * (F32&)j.context + 0.5f; + } + + void update_tag_reset_green(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.font.color.g = ctb.font.color.g; + } + + static const xtextbox::callback cb_2255 = { NULL, update_tag_green, update_tag_green }; + +#if 1 + void parse_tag_green(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti); +#else + void parse_tag_green(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + // todo: uses int-to-float conversion + } +#endif + + void reset_tag_green(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_green, + update_tag_reset_green }; + a.cb = &cb; + } + + void update_tag_blue(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.font.color.b = 255.0f * (F32&)j.context + 0.5f; + } + + void update_tag_reset_blue(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.font.color.b = ctb.font.color.b; + } + + static const xtextbox::callback cb_2293 = { NULL, update_tag_blue, update_tag_blue }; + +#if 1 + void parse_tag_blue(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti); +#else + void parse_tag_blue(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + // todo: uses int-to-float conversion + } +#endif + + void reset_tag_blue(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_blue, update_tag_reset_blue }; + a.cb = &cb; + } + + void update_tag_width(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.font.width = (F32&)j.context; + } + + void update_tag_reset_width(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.font.width = ctb.font.width; + } + + void parse_tag_width(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, update_tag_width, update_tag_width }; + F32& v = (F32&)a.context; + + if (ti.value.size == 0 || ti.action.size == 0) + { + return; + } + + v = xatof(ti.value.text); + + switch (ti.action.text[0]) + { + case '=': + { + break; + } + case '+': + { + v += tb.font.width; + break; + } + case '*': + { + v *= tb.font.width; + break; + } + default: + { + return; + } + } + + if (v < 0.0f) + { + v = 0.0f; + } + else if (v > 1.0f) + { + v = 1.0f; + } + + a.cb = &cb; + } + + void reset_tag_width(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_width, + update_tag_reset_width }; + a.cb = &cb; + } + + void update_tag_height(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.font.height = (F32&)j.context; + } + + void update_tag_reset_height(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.font.height = ctb.font.height; + } + + void parse_tag_height(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, update_tag_height, update_tag_height }; + F32& v = (F32&)a.context; + + if (ti.value.size == 0 || ti.action.size == 0) + { + return; + } + + v = xatof(ti.value.text); + + switch (ti.action.text[0]) + { + case '=': + { + break; + } + case '+': + { + v += tb.font.height; + break; + } + case '*': + { + v *= tb.font.height; + break; + } + default: + { + return; + } + } + + if (v < 0.0f) + { + v = 0.0f; + } + else if (v > 1.0f) + { + v = 1.0f; + } + + a.cb = &cb; + } + + void reset_tag_height(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_height, + update_tag_reset_height }; + a.cb = &cb; + } + + void update_tag_left_indent(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.left_indent = (F32&)j.context; + } + + void update_tag_reset_left_indent(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.left_indent = ctb.left_indent; + } + + void parse_tag_left_indent(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, update_tag_left_indent, NULL }; + F32& v = (F32&)a.context; + + if (ti.value.size == 0 || ti.action.size == 0) + { + return; + } + + v = xatof(ti.value.text); + + switch (ti.action.text[0]) + { + case '=': + { + break; + } + case '+': + { + v += tb.left_indent; + break; + } + case '*': + { + v *= tb.left_indent; + break; + } + default: + { + return; + } + } + + if (v < -1.0f) + { + v = -1.0f; + } + else if (v > 1.0f) + { + v = 1.0f; + } + + a.cb = &cb; + } + + void reset_tag_left_indent(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_left_indent, NULL }; + a.cb = &cb; + } + + void update_tag_right_indent(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.right_indent = (F32&)j.context; + } + + void update_tag_reset_right_indent(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.right_indent = ctb.right_indent; + } + + void parse_tag_right_indent(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, update_tag_right_indent, NULL }; + F32& v = (F32&)a.context; + + if (ti.value.size == 0 || ti.action.size == 0) + { + return; + } + + v = xatof(ti.value.text); + + switch (ti.action.text[0]) + { + case '=': + { + break; + } + case '+': + { + v += tb.right_indent; + break; + } + case '*': + { + v *= tb.right_indent; + break; + } + default: + { + return; + } + } + + if (v < -1.0f) + { + v = -1.0f; + } + else if (v > 1.0f) + { + v = 1.0f; + } + + a.cb = &cb; + } + + void reset_tag_right_indent(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_right_indent, NULL }; + a.cb = &cb; + } + + void update_tag_tab_stop(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.tab_stop = (F32&)j.context; + } + + void update_tag_reset_tab_stop(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.tab_stop = ctb.tab_stop; + } + + void parse_tag_tab_stop(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, update_tag_tab_stop, NULL }; + F32& v = (F32&)a.context; + + if (ti.value.size == 0 || ti.action.size == 0) + { + return; + } + + v = xatof(ti.value.text); + + switch (ti.action.text[0]) + { + case '=': + { + break; + } + case '+': + { + v += tb.tab_stop; + break; + } + case '*': + { + v *= tb.tab_stop; + break; + } + default: + { + return; + } + } + + if (v < 0.0f) + { + v = 0.0f; + } + else if (v > 1.0f) + { + v = 1.0f; + } + + a.cb = &cb; + } + + void reset_tag_tab_stop(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_tab_stop, NULL }; + a.cb = &cb; + } + + void update_tag_xspace(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.font.space = (F32&)j.context; + } + + void update_tag_reset_xspace(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.font.space = ctb.font.space; + } + + void parse_tag_xspace(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, update_tag_xspace, update_tag_xspace }; + F32& v = (F32&)a.context; + + if (ti.value.size == 0 || ti.action.size == 0) + { + return; + } + + v = xatof(ti.value.text); + + switch (ti.action.text[0]) + { + case '=': + { + break; + } + case '+': + { + v += tb.font.space; + break; + } + case '*': + { + v *= tb.font.space; + break; + } + default: + { + return; + } + } + + if (v < -1.0f) + { + v = -1.0f; + } + else if (v > 1.0f) + { + v = 1.0f; + } + + a.cb = &cb; + } + + void reset_tag_xspace(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_xspace, + update_tag_reset_xspace }; + a.cb = &cb; + } + + void update_tag_yspace(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.line_space = (F32&)j.context; + } + + void update_tag_reset_yspace(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.line_space = ctb.line_space; + } + + void parse_tag_yspace(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, update_tag_yspace, NULL }; + F32& v = (F32&)a.context; + + if (ti.value.size == 0 || ti.action.size == 0) + { + return; + } + + v = xatof(ti.value.text); + + switch (ti.action.text[0]) + { + case '=': + { + break; + } + case '+': + { + v += tb.line_space; + break; + } + case '*': + { + v *= tb.line_space; + break; + } + default: + { + return; + } + } + + if (v < -1.0f) + { + v = -1.0f; + } + else if (v > 1.0f) + { + v = 1.0f; + } + + a.cb = &cb; + } + + void reset_tag_yspace(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_yspace, NULL }; + a.cb = &cb; + } + + void update_tag_reset_all(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb = ctb; + } + + void reset_tag_all(xtextbox::jot& j, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_all, update_tag_reset_all }; + j.cb = &cb; + } + + void update_tag_color(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.font.color = (iColor_tag&)j.context; + } + + void update_tag_reset_color(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.font.color = ctb.font.color; + } + + void parse_tag_color(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, update_tag_color, update_tag_color }; + iColor_tag& color = (iColor_tag&)a.context; + + if (ti.value.size < 6 || ti.action.size == 0) + { + return; + } + + size_t v = atox(ti.value); + + if (ti.value.size < 8) + { + v = (v & 0xff000000) | (tb.font.color.a << 24); + } + + switch (ti.action.text[0]) + { + case '=': + { + color.a = v >> 24 & 0xff; + color.r = v >> 16 & 0xff; + color.g = v >> 8 & 0xff; + color.b = v & 0xff; + break; + } + case '+': + { + U32 temp; + + temp = (v >> 24 & 0xff) + tb.font.color.a; + color.a = (temp <= 255) ? temp : 255; + + temp = (v >> 16 & 0xff) + tb.font.color.r; + color.r = (temp <= 255) ? temp : 255; + + temp = (v >> 8 & 0xff) + tb.font.color.g; + color.g = (temp <= 255) ? temp : 255; + + temp = (v & 0xff) + tb.font.color.b; + color.b = (temp <= 255) ? temp : 255; + + break; + } + case '*': + { + color.a = (v >> 24 & 0xff) * tb.font.color.a / 255; + color.r = (v >> 16 & 0xff) * tb.font.color.r / 255; + color.g = (v >> 8 & 0xff) * tb.font.color.g / 255; + color.b = (v & 0xff) * tb.font.color.b / 255; + break; + } + default: + { + return; + } + } + + a.cb = &cb; + } + + void reset_tag_color(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_color, + update_tag_reset_color }; + a.cb = &cb; + } + + void update_tag_font(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.font.id = (U32&)j.context; + } + + void update_tag_reset_font(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.font.id = ctb.font.id; + } + + void parse_tag_font(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, update_tag_font, update_tag_font }; + U32& id = (U32&)a.context; + + if (ti.action.size < 1 || ti.action.text[0] != '=' || ti.value.size == 0) + { + return; + } + + id = atoi(ti.value.text); + + if (id < active_fonts_size) + { + a.cb = &cb; + } + } + + void reset_tag_font(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_font, update_tag_reset_font }; + a.cb = &cb; + } + + void update_tag_wrap(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.flags = (tb.flags & ~WRAP_MASK) | ((U32&)j.context & WRAP_MASK); + } + + void update_tag_reset_wrap(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.flags = (tb.flags & ~WRAP_MASK) | (ctb.flags & WRAP_MASK); + } + + void parse_tag_wrap(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, update_tag_wrap, NULL }; + U32& flags = (U32&)a.context; + + if (ti.action.size < 1 || ti.action.text[0] != '=' || ti.value.size != 4) + { + return; + } + + if (imemcmp(ti.value.text, "word", 4) == 0) + { + flags = WRAP_WORD; + } + else if (imemcmp(ti.value.text, "char", 4) == 0) + { + flags = WRAP_CHAR; + } + else if (imemcmp(ti.value.text, "none", 4) == 0) + { + flags = WRAP_NONE; + } + else + { + return; + } + + a.cb = &cb; + } + + void reset_tag_wrap(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, update_tag_reset_wrap, NULL }; + a.cb = &cb; + } + + void update_tag_xjustify(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.flags = (tb.flags & ~XJUSTIFY_MASK) | ((U32&)j.context & XJUSTIFY_MASK); + } + + void update_tag_reset_xjustify(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.flags = (tb.flags & ~XJUSTIFY_MASK) | (ctb.flags & XJUSTIFY_MASK); + } + + void parse_tag_xjustify(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, NULL, update_tag_xjustify }; + U32& flags = (U32&)a.context; + + if (ti.action.size < 1 || ti.action.text[0] != '=') + { + return; + } + + if (icompare(ti.value, substr::create("left", 4)) == 0) + { + flags = XJUSTIFY_LEFT; + } + else if (icompare(ti.value, substr::create("center", 6)) == 0) + { + flags = XJUSTIFY_CENTER; + } + else if (icompare(ti.value, substr::create("right", 5)) == 0) + { + flags = XJUSTIFY_RIGHT; + } + else + { + return; + } + + a.cb = &cb; + } + + void reset_tag_xjustify(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, NULL, update_tag_reset_xjustify }; + a.cb = &cb; + } + + void update_tag_yjustify(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) + { + tb.flags = (tb.flags & ~YJUSTIFY_MASK) | ((U32&)j.context & YJUSTIFY_MASK); + } + + void update_tag_reset_yjustify(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) + { + tb.flags = (tb.flags & ~YJUSTIFY_MASK) | (ctb.flags & YJUSTIFY_MASK); + } + + void parse_tag_yjustify(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { NULL, NULL, update_tag_yjustify }; + U32& flags = (U32&)a.context; + + if (ti.action.size < 1 || ti.action.text[0] != '=') + { + return; + } + + if (icompare(ti.value, substr::create("top", 4)) == 0) + { + flags = YJUSTIFY_TOP; + } + else if (icompare(ti.value, substr::create("center", 4)) == 0) + { + flags = YJUSTIFY_CENTER; + } + else if (icompare(ti.value, substr::create("bottom", 4)) == 0) + { + flags = YJUSTIFY_BOTTOM; + } + else + { + return; + } + + a.cb = &cb; + } + + void reset_tag_yjustify(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + static const xtextbox::callback cb = { NULL, NULL, update_tag_reset_yjustify }; + a.cb = &cb; + } + + void parse_tag_open_curly(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + a.s.text = ti.tag.text; + a.s.size = 1; + + char c = a.s.text[0]; + + a.reset_flags(); + a.bounds = tb.font.bounds(c); + a.cb = tb.cb; + a.context = NULL; + } + + void parse_tag_newline(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag&) + { + a.flag.line_break = true; + a.flag.ethereal = false; + a.bounds = tb.font.bounds('\n'); + } + + void parse_tag_tab(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + a.flag.tab = true; + } + + void parse_tag_word_break(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + a.flag.word_break = true; + } + + void parse_tag_page_break(xtextbox::jot& a, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + a.flag.page_break = true; + } + + struct model_tag_context + { + xModelInstance* model; + xVec3 rot; + basic_rect dst; + xSphere o; + }; + + void render_tag_model(const xtextbox::jot& j, const xtextbox& tb, F32 x, F32 y) + { + model_tag_context& mtc = *(model_tag_context*)j.context; + + basic_rect dst = mtc.dst; + dst.move(x, y); + + xVec3 from = { 0, 0, 1.0f }; + xVec3 to = { 0, 0, -0.001f }; + + xMat4x3 frame; + + xMat3x3Euler(&frame, &mtc.rot); + + F32 scale = 1.001f * ((mtc.o.r <= 0.0f) ? 1.0f : 0.5f / mtc.o.r); + + frame.right *= scale; + frame.up *= scale; + frame.at *= scale; + frame.pos = mtc.o.center; + frame.flags = 0; + + xModelSetFrame(mtc.model, &frame); + xModelSetMaterialAlpha(mtc.model, tb.font.color.a); + + tex_flush(); + + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); + + xModelRender2D(*mtc.model, dst, from, to); + + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); + } + + void parse_tag_model(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { render_tag_model, NULL, NULL }; + + load_model_args(def_model_args, ti.tag); + + if (def_model_args.model) + { + model_tag_context& mtc = *(model_tag_context*)a.context; + + mtc.model = def_model_args.model; + mtc.rot = def_model_args.rot; + mtc.rot *= 0.017453292f; + mtc.dst = def_model_args.dst; + + xSphere& o = *xModelGetLocalSBound(mtc.model); + mtc.o = o; + + mtc.dst.y -= def_model_args.off.y; + + a.bounds.assign(0.0f, -def_model_args.off.y, def_model_args.off.x, + def_model_args.off.y); + + switch (def_model_args.scale) + { + case model_args::SCALE_SIZE: + { + mtc.dst.scale(mtc.o.r); + a.bounds.scale(mtc.o.r); + break; + } + case model_args::SCALE_SCREEN: + { + break; + } + default: + { + mtc.dst.scale(tb.font.width, tb.font.height); + a.bounds.scale(tb.font.width, tb.font.height); + break; + } + } + + a.reset_flags(); + a.context_size = sizeof(model_tag_context); + a.cb = &cb; + } + } + + void reset_tag_model(xtextbox::jot&, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + reset_model_args(def_model_args); + } + + struct tex_tag_context + { + RwRaster* raster; + F32 rot; + basic_rect src; + basic_rect dst; + }; + + void render_tag_tex(const xtextbox::jot& j, const xtextbox& tb, F32 x, F32 y) + { + tex_tag_context& ttc = *(tex_tag_context*)j.context; + + set_tex_raster(ttc.raster); + + basic_rect dst = ttc.dst; + dst.move(x, y); + + tex_render(ttc.src, dst, tb.font.clip, tb.font.color); + } + + xVec2 get_texture_size(RwRaster& raster); + + void parse_tag_tex(xtextbox::jot& j, const xtextbox& tb, const xtextbox&, + const xtextbox::split_tag& ti) + { + static const xtextbox::callback cb = { render_tag_tex, NULL, NULL }; + + load_tex_args(def_tex_args, ti.tag); + + if (def_tex_args.raster) + { + tex_tag_context& ttc = *(tex_tag_context*)j.context; + + ttc.raster = def_tex_args.raster; + ttc.rot = def_tex_args.rot; + ttc.src = def_tex_args.src; + ttc.dst = def_tex_args.dst; + ttc.dst.y -= def_tex_args.off.y; + + j.bounds.assign(0.0f, -def_tex_args.off.y, def_tex_args.off.x, def_tex_args.off.y); + + xVec2 size; + + switch (def_tex_args.scale) + { + case tex_args::SCALE_SCREEN: + { + size.assign(1.0f, 1.0f); + break; + } + case tex_args::SCALE_SIZE: + { + size = get_texture_size(*ttc.raster); + break; + } + case tex_args::SCALE_FONT_WIDTH: + { + size = get_texture_size(*ttc.raster); + size.y *= tb.font.width / size.x; + size.x = tb.font.width; + break; + } + case tex_args::SCALE_FONT_HEIGHT: + { + size = get_texture_size(*ttc.raster); + size.x *= tb.font.height / size.y; + size.y = tb.font.height; + break; + } + case tex_args::SCALE_SCREEN_WIDTH: + { + size = get_texture_size(*ttc.raster); + size.y *= 1.0f / size.x; + size.x = 1.0f; + break; + } + case tex_args::SCALE_SCREEN_HEIGHT: + { + size = get_texture_size(*ttc.raster); + size.x *= 1.0f / size.y; + size.y = 1.0f; + break; + } + default: + { + size.assign(tb.font.width, tb.font.height); + break; + } + } + + ttc.dst.scale(size.x, size.y); + j.bounds.scale(size.x, size.y); + j.reset_flags(); + j.context_size = sizeof(tex_tag_context); + j.cb = &cb; + } + } +} // namespace + +namespace +{ + xVec2 get_texture_size(RwRaster& raster) + { + xVec2 vec = { raster.width / 640.0f, raster.height / 480.0f }; + return vec; + } + + void reset_tag_tex(xtextbox::jot&, const xtextbox&, const xtextbox&, const xtextbox::split_tag&) + { + reset_tex_args(def_tex_args); + } + + void parse_tag_insert(xtextbox::jot& j, const xtextbox&, const xtextbox&, + const xtextbox::split_tag& ti) + { + j.reset_flags(); + j.flag.invisible = j.flag.ethereal = true; + + if (ti.action.size != 1 || ti.action.text[0] != ':' || ti.value.size == 0) + { + return; + } + + U32 id = xStrHash(ti.value.text, ti.value.size); + + if (id) + { + xTextAsset* ta = (xTextAsset*)xSTFindAsset(id, NULL); + + if (ta) + { + j.context = (char*)xTextAssetGetText(ta); + j.context_size = ta->len; + j.flag.insert = true; + } + } + } + + void parse_tag_insert_hash(xtextbox::jot& j, const xtextbox&, const xtextbox&, + const xtextbox::split_tag& ti) + { + j.reset_flags(); + j.flag.invisible = j.flag.ethereal = true; + + if (ti.action.size != 1 || ti.action.text[0] != ':' || ti.value.size == 0) + { + return; + } + + U32 id = atox(ti.value); + + if (id) + { + xTextAsset* ta = (xTextAsset*)xSTFindAsset(id, NULL); + + if (ta) + { + j.context = (char*)xTextAssetGetText(ta); + j.context_size = ta->len; + j.flag.insert = true; + } + } + } + + void parse_tag_pop(xtextbox::jot&, const xtextbox&, const xtextbox&, + const xtextbox::split_tag& ti) + { + if (ti.action.size != 1 || ti.action.text[0] != ':' || ti.value.size == 0) + { + return; + } + } + + void parse_tag_timer(xtextbox::jot& j, const xtextbox&, const xtextbox&, + const xtextbox::split_tag& ti) + { + j.reset_flags(); + j.flag.invisible = j.flag.ethereal = true; + + if (ti.action.size != 1 || ti.action.text[0] != ':' || ti.value.size == 0) + { + return; + } + + U32 id = xStrHash(ti.value.text, ti.value.size); + + if (id) + { + xTimer* ta = (xTimer*)zSceneFindObject(id); + + if (ta) + { + j.flag.insert = j.flag.dynamic = true; + + char buffer[64]; + U32 sec = (U32)ta->secondsLeft + 1; + U32 mn = sec / 60; + + if (mn) + { + sprintf(buffer, "%d:%02d", mn, sec - mn * 60); + } + else + { + sprintf(buffer, "%02d", sec); + } + + sprintf((char*)j.context, "%.*s", 15, buffer); + j.context_size = 16; + } + } + } + + // clang-format off + xtextbox::tag_type format_tags_buffer[2][128] = + { + SUBSTR(""), parse_tag_open_curly, NULL, NULL, + SUBSTR("a"), parse_tag_alpha, reset_tag_alpha, NULL, + SUBSTR("all"), NULL, reset_tag_all, NULL, + SUBSTR("alpha"), parse_tag_alpha, reset_tag_alpha, NULL, + SUBSTR("b"), parse_tag_blue, reset_tag_blue, NULL, + SUBSTR("blue"), parse_tag_blue, reset_tag_blue, NULL, + SUBSTR("c"), parse_tag_color, reset_tag_color, NULL, + SUBSTR("color"), parse_tag_color, reset_tag_color, NULL, + SUBSTR("f"), parse_tag_font, reset_tag_font, NULL, + SUBSTR("font"), parse_tag_font, reset_tag_font, NULL, + SUBSTR("g"), parse_tag_green, reset_tag_green, NULL, + SUBSTR("green"), parse_tag_green, reset_tag_green, NULL, + SUBSTR("h"), parse_tag_height, reset_tag_height, NULL, + SUBSTR("height"), parse_tag_height, reset_tag_height, NULL, + SUBSTR("i"), parse_tag_insert, NULL, NULL, + SUBSTR("ih"), parse_tag_insert_hash, NULL, NULL, + SUBSTR("insert"), parse_tag_insert, NULL, NULL, + SUBSTR("left_indent"), parse_tag_left_indent, reset_tag_left_indent, NULL, + SUBSTR("li"), parse_tag_left_indent, reset_tag_left_indent, NULL, + SUBSTR("model"), parse_tag_model, reset_tag_model, NULL, + SUBSTR("n"), parse_tag_newline, NULL, NULL, + SUBSTR("newline"), parse_tag_newline, NULL, NULL, + SUBSTR("page_break"), parse_tag_page_break, NULL, NULL, + SUBSTR("pb"), parse_tag_page_break, NULL, NULL, + SUBSTR("pop"), parse_tag_pop, NULL, NULL, + SUBSTR("r"), parse_tag_red, reset_tag_red, NULL, + SUBSTR("red"), parse_tag_red, reset_tag_red, NULL, + SUBSTR("ri"), parse_tag_right_indent, reset_tag_right_indent, NULL, + SUBSTR("right_indent"), parse_tag_right_indent, reset_tag_right_indent, NULL, + SUBSTR("t"), parse_tag_tab, NULL, NULL, + SUBSTR("tab"), parse_tag_tab, NULL, NULL, + SUBSTR("tab_stop"), parse_tag_tab_stop, reset_tag_tab_stop, NULL, + SUBSTR("tex"), parse_tag_tex, reset_tag_tex, NULL, + SUBSTR("timer"), parse_tag_timer, NULL, NULL, + SUBSTR("ts"), parse_tag_tab_stop, reset_tag_tab_stop, NULL, + SUBSTR("w"), parse_tag_width, reset_tag_width, NULL, + SUBSTR("wb"), parse_tag_word_break, NULL, NULL, + SUBSTR("width"), parse_tag_width, reset_tag_width, NULL, + SUBSTR("word_break"), parse_tag_word_break, NULL, NULL, + SUBSTR("wrap"), parse_tag_wrap, reset_tag_wrap, NULL, + SUBSTR("xj"), parse_tag_xjustify, reset_tag_xjustify, NULL, + SUBSTR("xjustify"), parse_tag_xjustify, reset_tag_xjustify, NULL, + SUBSTR("xs"), parse_tag_xspace, reset_tag_xspace, NULL, + SUBSTR("xspace"), parse_tag_xspace, reset_tag_xspace, NULL, + SUBSTR("yj"), parse_tag_yjustify, reset_tag_yjustify, NULL, + SUBSTR("yjustify"), parse_tag_yjustify, reset_tag_yjustify, NULL, + SUBSTR("ys"), parse_tag_yspace, reset_tag_yspace, NULL, + SUBSTR("yspace"), parse_tag_yspace, reset_tag_yspace, NULL + }; + // clang-format on + + xtextbox::tag_type* format_tags = format_tags_buffer[0]; + U32 format_tags_size = 48; +} // namespace + +void xtextbox::register_tags(const tag_type* t, size_t size) +{ + const tag_type *s1, *s2, *end1, *end2; + + s1 = format_tags; + end1 = s1 + format_tags_size; + s2 = t; + end2 = t + size; + + tag_type* d = (s1 == format_tags_buffer[0]) ? format_tags_buffer[1] : format_tags_buffer[0]; + + format_tags = d; + + while (s1 < end1 && s2 < end2) + { + S32 c = icompare(s1->name, s2->name); + + if (c < 0) + { + *d = *s1; + s1++; + } + else if (c > 0) + { + *d = *s2; + s2++; + } + else + { + *d = *s2; + s1++; + s2++; + } + + d++; + } + + while (s1 < end1) + { + *d = *s1; + d++; + s1++; + } + + while (s2 < end2) + { + *d = *s2; + d++; + s2++; + } + + format_tags_size = d - format_tags; +} + +xtextbox::tag_type* xtextbox::find_format_tag(const substr& s, S32& index) +{ + S32 start = 0; + S32 end = format_tags_size; + + while (start != end) + { + index = (start + end) / 2; + + tag_type& t = format_tags[index]; + S32 c = icompare(s, t.name); + + if (c < 0) + { + end = index; + } + else if (c > 0) + { + start = index + 1; + } + else + { + return &t; + } + } + + index = -1; + return NULL; +} + +namespace +{ + void set_rect_verts(RwIm2DVertex* verts, F32 x, F32 y, F32 w, F32 h, iColor_tag c, F32 rcz, + F32 nsz); + void set_rect_vert(RwIm2DVertex& vert, F32 x, F32 y, F32 z, iColor_tag c, F32 rcz); +} // namespace + +void render_fill_rect(const basic_rect& bounds, iColor_tag color) +{ + if (!bounds.empty()) + { + F32 rcz = 1.0f / RwCameraGetNearClipPlane(RwCameraGetCurrentCamera()); + F32 nsz = RwIm2DGetNearScreenZ(); + + xfont::set_render_state(NULL); + + RwIm2DVertex vert[4]; + basic_rect r = bounds; + + // non-matching: float scheduling + + r.scale(640.0f, 480.0f); + + set_rect_verts(vert, r.x, r.y, r.w, r.h, color, rcz, nsz); + RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vert, 4); + xfont::restore_render_state(); + } +} + +namespace +{ + void set_rect_verts(RwIm2DVertex* verts, F32 x, F32 y, F32 w, F32 h, iColor_tag c, F32 rcz, + F32 nsz) + { + set_rect_vert(verts[0], x, y, nsz, c, rcz); + set_rect_vert(verts[1], x, y + h, nsz, c, rcz); + set_rect_vert(verts[2], x + w, y, nsz, c, rcz); + set_rect_vert(verts[3], x + w, y + h, nsz, c, rcz); + } + + void set_rect_vert(RwIm2DVertex& vert, F32 x, F32 y, F32 z, iColor_tag c, F32 rcz) + { + RwIm2DVertexSetScreenX(&vert, x); + RwIm2DVertexSetScreenY(&vert, y); + RwIm2DVertexSetScreenZ(&vert, z); + RwIm2DVertexSetIntRGBA(&vert, c.r, c.g, c.b, c.a); + RwIm2DVertexSetRecipCameraZ(&vert, rcz); + } +} // namespace + +basic_rect& basic_rect::scale(F32 x, F32 y) +{ + return scale(x, y, x, y); +} + +basic_rect& basic_rect::scale(F32 x, F32 y, F32 w, F32 h) +{ + this->x *= x; + this->y *= y; + this->w *= w; + this->h *= h; + return *this; +} + +basic_rect& basic_rect::assign(F32 x, F32 y, F32 w, F32 h) +{ + this->x = x; + this->y = y; + this->w = w; + this->h = h; + return *this; +} + +bool basic_rect::empty() const +{ + return (w <= 0.0f || h <= 0.0f); +} + +void basic_rect::clip(basic_rect& a, basic_rect& b) const +{ + F32 bwaw = b.w / a.w; + F32 bwah = b.h / a.h; + + if (a.x < x) + { + F32 xax = x - a.x; + F32 bwawxax = bwaw * xax; + a.x = x; + a.w -= xax; + b.x += bwawxax; + b.w -= bwawxax; + } + + if (a.y < y) + { + F32 yay = y - a.y; + F32 bwahyay = bwah * yay; + a.y = y; + a.h -= yay; + b.y += bwahyay; + b.h -= bwahyay; + } + + F32 axaw = a.x + a.w; + F32 xw = x + w; + + if (axaw > xw) + { + F32 bwawaxawxw = bwaw * (axaw - xw); + b.w -= bwawaxawxw; + a.w = x + w - a.x; + } + + F32 ayah = a.y + a.h; + F32 yh = y + h; + + if (ayah > yh) + { + F32 bwahayahyh = bwah * (ayah - yh); + b.h -= bwahayahyh; + a.h = y + h - a.y; + } +} + +basic_rect& basic_rect::operator|=(const basic_rect& other) +{ + F32 x1, y1, x2, y2; + F32 _x1, _y1, _x2, _y2; + + this->get_bounds(x1, y1, x2, y2); + other.get_bounds(_x1, _y1, _x2, _y2); + + if (x1 > _x1) + { + x1 = _x1; + } + + if (y1 > _y1) + { + y1 = _y1; + } + + if (x2 < _x2) + { + x2 = _x2; + } + + if (y2 < _y2) + { + y2 = _y2; + } + + set_bounds(x1, y1, x2, y2); + + return *this; +} + +void basic_rect::set_bounds(F32 x1, F32 y1, F32 x2, F32 y2) +{ + x = x1; + w = x2 - x1; + y = y1; + h = y2 - y1; +} + +void basic_rect::get_bounds(F32& x1, F32& y1, F32& x2, F32& y2) const +{ + x1 = x; + x2 = x + w; + y1 = y; + y2 = y + h; +} + +basic_rect& basic_rect::move(F32 x, F32 y) +{ + this->x += x; + this->y += y; + return *this; +} + +basic_rect& basic_rect::scale(F32 s) +{ + return scale(s, s, s, s); +} + +xVec2& xVec2::assign(F32 x, F32 y) +{ + this->x = x; + this->y = y; + return *this; +} + +extern substr _427; + +substr substr::create(const char* text, size_t size) +{ + substr s = _427; + s.text = text; + s.size = size; + return s; +} + +size_t rskip_ws(substr& s) +{ + return rskip_ws(s.text, s.size); +} + +size_t rskip_ws(const char*& text, size_t& size) +{ + while (size && is_ws(text[size - 1])) + { + size--; + } + + return size; +} + +bool is_ws(char c) +{ + return (c == ' ' || c == '\t' || c == '\n'); +} + +const char* find_char(const substr& s, char c) +{ + if (!s.text) + { + return NULL; + } + + const char* text = s.text; + S32 size = s.size; + + while (size > 0 && *text != '\0') + { + if (*text == c) + { + return text; + } + + size--; + text++; + } + + return NULL; +} + +const char* skip_ws(substr& s) +{ + return skip_ws(s.text, s.size); +} + +const char* skip_ws(const char*& text, size_t& size) +{ + size_t i = 0; + + while (i < size && *text != '\0') + { + if (!is_ws(*text)) + { + size -= i; + break; + } + + text++; + i++; + } + + return text; +} + +size_t atox(const substr& s) +{ + size_t read_size; + return atox(s, read_size); +} + +size_t trim_ws(substr& s) +{ + return trim_ws(s.text, s.size); +} + +size_t trim_ws(const char*& text, size_t& size) +{ + skip_ws(text, size); + return rskip_ws(text, size); +} + +xtextbox::tag_type* xtextbox::find_format_tag(const substr& s) +{ + S32 index; + return find_format_tag(s, index); +} + +size_t xtextbox::layout::jots_size() const +{ + return _jots_size; +} + +xtextbox xtextbox::create() +{ + return create(xfont::create(), screen_bounds, 0, 0.0f, 0.0f, 0.0f, 0.0f); +} + +xfont xfont::create() +{ + return create(0, 0.0f, 0.0f, 0.0f, g_WHITE, screen_bounds); +} + +void xtextbox::jot::intersect_flags(const jot& other) +{ + *(U16*)&flag &= *(U16*)&other.flag; +} + +void xtextbox::jot::reset_flags() +{ + *(U16*)&flag = 0; +} + +xSphere* xModelGetLocalSBound(xModelInstance* model) +{ + return (xSphere*)RpAtomicGetBoundingSphere(model->Data); +} diff --git a/src/SB/Core/x/xFont.h b/src/SB/Core/x/xFont.h new file mode 100644 index 0000000..055fa11 --- /dev/null +++ b/src/SB/Core/x/xFont.h @@ -0,0 +1,219 @@ +#ifndef XFONT_H +#define XFONT_H + +#include "xMath2.h" +#include "iColor.h" +#include "xString.h" + +#include + +struct xfont +{ + U32 id; + F32 width; + F32 height; + F32 space; + iColor_tag color; + basic_rect clip; + + static void init(); + static void set_render_state(RwRaster* raster); + static void restore_render_state(); + static xfont create(); + static xfont create(U32 id, F32 width, F32 height, F32 space, iColor_tag color, + const basic_rect& clip); + + basic_rect bounds(char c) const; + basic_rect bounds(const char* text) const; + basic_rect bounds(const char* text, size_t text_size, F32 max_width, + size_t& size) const; + void start_render() const; + void stop_render() const; + void irender(const char* text, F32 x, F32 y) const; + void irender(const char* text, size_t text_size, F32 x, F32 y) const; + void render(const char* text, F32 x, F32 y) const; + + xfont& operator=(const xfont& rhs) + { + id = rhs.id; + width = rhs.width; + height = rhs.height; + space = rhs.space; + + *(U32*)(&color) = *(U32*)(&rhs.color); + + *(U32*)(&clip.x) = *(U32*)(&rhs.clip.x); + *(U32*)(&clip.y) = *(U32*)(&rhs.clip.y); + *(U32*)(&clip.w) = *(U32*)(&rhs.clip.w); + *(U32*)(&clip.h) = *(U32*)(&rhs.clip.h); + + return *this; + } +}; + +struct xtextbox +{ + struct callback; + struct tag_type; + struct layout; + + struct jot + { + substr s; + + struct + { + // Offset: 0x8 + bool invisible : 1; // bit 24 + bool ethereal : 1; // bit 25 + bool merge : 1; // bit 26 + bool word_break : 1; // bit 27 + bool word_end : 1; // bit 28 + bool line_break : 1; // bit 29 + bool stop : 1; // bit 30 + bool tab : 1; // bit 31 + + // Offset: 0x9 + bool insert : 1; // bit 24 + bool dynamic : 1; // bit 25 + bool page_break : 1; // bit 26 + bool stateful : 1; // bit 27 + U16 dummy : 4; // bits 28-31 + } flag; + // Offset: 0xC + U16 context_size; + + // Offset: 0x10 + void* context; + basic_rect bounds; + basic_rect render_bounds; + const callback* cb; + tag_type* tag; + + void intersect_flags(const jot& other); + void reset_flags(); + }; + + struct split_tag + { + substr tag; + substr name; + substr action; + substr value; + }; + + struct tag_type + { + substr name; + void (*parse_tag)(jot&, const xtextbox&, const xtextbox&, const split_tag&); + void (*reset_tag)(jot&, const xtextbox&, const xtextbox&, const split_tag&); + void* context; + }; + + struct callback + { + void (*render)(const jot&, const xtextbox&, F32, F32); + void (*layout_update)(const jot&, xtextbox&, const xtextbox&); + void (*render_update)(const jot&, xtextbox&, const xtextbox&); + }; + + struct jot_line + { + basic_rect bounds; + F32 baseline; + size_t first; + size_t last; + U8 page_break; + }; + + struct tag_entry + { + substr name; + char op; + substr* args; + size_t args_size; + }; + + struct tag_entry_list + { + tag_entry* entries; + size_t size; + }; + + xfont font; + basic_rect bounds; + U32 flags; + F32 line_space; + F32 tab_stop; + F32 left_indent; + F32 right_indent; + callback* cb; + void* context; + const char** texts; + const size_t* text_sizes; + size_t texts_size; + substr text; + size_t text_hash; + + static callback text_cb; + + static void text_render(const jot& j, const xtextbox& tb, F32 x, F32 y); + static tag_entry_list read_tag(const substr& s); + static tag_entry* find_entry(const tag_entry_list& el, const substr& name); + static size_t read_list(const tag_entry& e, F32* v, size_t vsize); + static size_t read_list(const tag_entry& e, S32* v, size_t vsize); + static void clear_layout_cache(); + static void register_tags(const tag_type* tag, size_t count); + static tag_type* find_format_tag(const substr& s); + static tag_type* find_format_tag(const substr& s, S32& index); + static xtextbox create(); + static xtextbox create(const xfont& font, const basic_rect& bounds, U32 flags, + F32 line_space, F32 tab_stop, F32 left_indent, + F32 right_indent); + + void set_text(const char* text); + void set_text(const char* text, size_t text_size); + void set_text(const char** texts, size_t size); + void set_text(const char** texts, const size_t* text_sizes, size_t size); + layout& temp_layout(bool cache) const; + void render(bool cache) const; + void render(layout& l, S32 begin_jot, S32 end_jot) const; + F32 yextent(F32 max, S32& size, bool cache) const; + F32 yextent(F32 max, S32& size, const layout& l, S32 begin_jot, + S32 end_jot) const; +}; + +struct xtextbox::layout +{ + xtextbox tb; + jot _jots[512]; + size_t _jots_size; + jot_line _lines[128]; + size_t _lines_size; + U8 context_buffer[1024]; + size_t context_buffer_size; + U16 dynamics[64]; + size_t dynamics_size; + + void refresh(const xtextbox& tb, bool force); + void refresh_end(const xtextbox& tb); + void clear(); + void trim_line(jot_line& line); + void erase_jots(size_t begin_jot, size_t end_jot); + void merge_line(jot_line& line); + void bound_line(jot_line& line); + bool fit_line(); + void next_line(); + void calc(const xtextbox& ctb, size_t start_text); + void render(const xtextbox& ctb, S32 begin_jot, S32 end_jot); + F32 yextent(F32 max, S32& size, S32 begin_jot, S32 end_jot) const; + bool changed(const xtextbox& ctb); + size_t jots_size() const; +}; + +void render_fill_rect(const basic_rect& bounds, iColor_tag color); + +F32 NSCREENX(F32); +F32 NSCREENY(F32); + +#endif diff --git a/src/SB/Core/x/xFrag.h b/src/SB/Core/x/xFrag.h deleted file mode 100644 index a49cfe9..0000000 --- a/src/SB/Core/x/xFrag.h +++ /dev/null @@ -1,370 +0,0 @@ -#ifndef XFRAG_H -#define XFRAG_H - -#include "xMath.h" -#include "xEnt.h" -#include "xPar.h" - -enum zFragType -{ - eFragInactive, - eFragGroup, - eFragShrapnel, - eFragParticle, - eFragProjectile, - eFragLightning, - eFragSound, - eFragShockwave, - eFragExplosion, - eFragDistortion, - eFragFire, - eFragCount, - eFragForceSize = 0x7fffffff -}; - -enum zFragLocType -{ - eFragLocBone, - eFragLocBoneUpdated, - eFragLocBoneLocal, - eFragLocBoneLocalUpdated, - eFragLocTag, - eFragLocTagUpdated, - eFragLocCount, - eFragLocForceSize = 0x7fffffff -}; - -struct zFragAsset -{ - zFragType type; - U32 id; - U32 parentID[2]; - F32 lifetime; - F32 delay; -}; - -struct zFragBone -{ - S32 index; - xVec3 offset; -}; - -struct zFragLocInfo -{ - union - { - zFragBone bone; - xModelTag tag; - }; -}; - -struct zFragLocation -{ - zFragLocType type; - zFragLocInfo info; - F32 rand_radius; -}; - -struct presence_volume -{ - F32 knockback; - xVec3 center; - F32 radius; - F32 damage_player; - F32 damage_npc; - F32 damage_other; -}; - -struct trail_emitter -{ - S32 type; - xVec3 loc; - F32 emitted; - S32 glare_id; - F32 streak_delay; - F32 streaks_emitted; - F32 spark_delay; - F32 sparks_emitted; - presence_volume* presence; - iSndHandle tracking_sound; -}; - -struct zFrag; - -struct zFragGroup -{ - zFrag* list[21]; -}; - -struct zShrapnelAsset; - -struct zFragShrapnelAsset : zFragAsset -{ - U32 shrapnelID; - zShrapnelAsset* shrapAsset; -}; - -struct zFragShrapnel -{ - zFragShrapnelAsset* fasset; -}; - -struct zFragParticleAsset : zFragAsset -{ - zFragLocation source; - zFragLocation vel; - xParEmitterCustomSettings emit; - U32 flags; - U32 parEmitterID; - zParEmitter* parEmitter; -}; - -struct zFragParticle -{ - zFragParticleAsset* fasset; -}; - -struct xCurveAsset -{ -}; - -struct zFragProjectileAsset : zFragAsset -{ - U32 modelInfoID; - RpAtomic* modelFile; - zFragLocation launch; - zFragLocation vel; - zFragLocation velPlusMinus; - zFragLocation rot; - zFragLocation rotPlusMinus; - F32 bounce; - S32 maxBounces; - U32 flags; - U32 childID; - zShrapnelAsset* child; - F32 minScale; - F32 maxScale; - U32 scaleCurveID; - xCurveAsset* scaleCurve; - F32 gravity; -}; - -struct zFragProjectile -{ - zFragProjectileAsset* fasset; - xModelInstance* model; - xParabola path; - F32 angVel; - F32 t; - F32 tColl; - S32 numBounces; - F32 scale; - F32 alpha; - F32 bounceC1; - F32 bounceC2; - xVec3 N; - xVec3 axis; -}; - -struct zFragLightningAsset : zFragAsset -{ - zFragLocation start; - zFragLocation end; - U32 startParentID; - U32 endParentID; -}; - -struct zLightning; - -struct zFragLightning -{ - zFragLightningAsset* fasset; - xModelInstance* startParent; - xModelInstance* endParent; - zLightning* lightning; -}; - -struct zFragSoundAsset : zFragAsset -{ - U32 assetID; - zFragLocation source; -}; - -struct zFragSound -{ - zFragSoundAsset* fasset; - iSndHandle soundID; -}; - -struct zFragShockwaveAsset : zFragAsset -{ - U32 modelInfoID; - F32 birthRadius; - F32 deathRadius; - F32 birthVelocity; - F32 deathVelocity; - F32 birthSpin; - F32 deathSpin; - F32 birthColor[4]; - F32 deathColor[4]; -}; - -struct zFragShockwave -{ - zFragShockwaveAsset* fasset; - F32 currSize; - F32 currVelocity; - F32 deltVelocity; - F32 currSpin; - F32 deltSpin; - F32 currColor[4]; - F32 deltColor[4]; -}; - -struct zFragExplosionAsset : zFragAsset -{ - U32 type; - zFragLocation loc; - U32 flags; -}; - -struct zFragExplosion -{ - zFragExplosionAsset* fasset; - trail_emitter trail; - xVec3 initPos; -}; - -struct zFragDistortionAsset : zFragAsset -{ - U32 type; - zFragLocation loc; - U32 flags; - F32 radius; - F32 duration; - F32 intensity; - F32 freq; - F32 repeat_delay; -}; - -struct zFragDistortion -{ - zFragDistortionAsset* fasset; - xVec3 loc; - S32 type; - F32 repeat_time; -}; - -struct zFragFireAsset : zFragAsset -{ - zFragLocation loc; - U32 flags; - F32 radius; - F32 scale; - F32 fuel; - F32 heat; - F32 damage; - F32 knockback; -}; - -struct zFragFire -{ - zFragFireAsset* fasset; -}; - -struct zFragInfo -{ - union - { - zFragGroup group; - zFragShrapnel shrapnel; - zFragParticle particle; - zFragProjectile projectile; - zFragLightning lightning; - zFragSound sound; - zFragShockwave shockwave; - zFragExplosion explosion; - zFragDistortion distortion; - zFragFire fire; - }; -}; - -struct zFrag -{ - zFragType type; - zFragInfo info; - F32 delay; - F32 alivetime; - F32 lifetime; - void (*update)(zFrag*, F32); - void (*destroy)(zFrag*); - xModelInstance* parent[2]; - zFrag* prev; - zFrag* next; -}; - -struct _class_9 -{ - xVec3 endPoint[2]; - xVec3 endPointB; - xVec3 direction; - F32 length; - F32 scale; - F32 width; - F32 endParam[2]; - F32 endVel[2]; - F32 paramSpan[2]; -}; - -struct xColor_tag // Will need moved after we fill other files -{ - U8 r; - U8 g; - U8 b; - U8 a; - RwRGBA rgba; -}; - -struct zLightning -{ - U32 type; - U32 flags; - _class_9 func; - U32 numStrips; - F32 alphaRamp; - xColor_tag color; - F32 time_left; - F32 time_total; - zLightning* nextBranch; - zLightning* prevBranch; - F32 parentSegment; - F32 lastParentSegment; - F32 segmentsPerMeter; - F32 branchSpeed; - S32 damage; - F32 knockBackSpeed; - RwRaster* mainTexture; - RwRaster* branchTexture; - F32 sparkTimer; - xVec3 collisionPoint; - F32 genTime; - U8 randomizeBranchEndPoint; - U8 collisionEnabled; - iSndHandle sndHandle; - xEnt* followStart; - xVec3 followStartOffset; - xEnt* followEnd; - xVec3 followEndOffset; - void (*renderCB)(zLightning*, RxObjSpace3DVertex*, RxObjSpace3DVertex*, U32); - void* context; - F32 weightParam[12]; -}; - -struct zShrapnelAsset -{ - S32 fassetCount; - U32 shrapnelID; - void (*initCB)(zShrapnelAsset*, xModelInstance*, xVec3*, void (*)(zFrag*, zFragAsset*)); -}; - -#endif diff --git a/src/SB/Core/x/xGlobals.h b/src/SB/Core/x/xGlobals.h new file mode 100644 index 0000000..b254ffe --- /dev/null +++ b/src/SB/Core/x/xGlobals.h @@ -0,0 +1,60 @@ +#ifndef XGLOBALS_H +#define XGLOBALS_H + +#include "xCamera.h" +#include "xPad.h" +#include "xUpdateCull.h" +#include "iCamera.h" +#include "iTime.h" + +#include +#include + +struct xGlobals +{ + // 0x00 in globals + xCamera camera; + + // 0x31C in globals + _tagxPad* pad0; + _tagxPad* pad1; + _tagxPad* pad2; + _tagxPad* pad3; + S32 profile; + + // 0x330 in globals + char profFunc[6][128]; + + // 0x630 in globals + xUpdateCullMgr* updateMgr; + S32 sceneFirst; + char sceneStart[32]; + RpWorld* currWorld; + + // 0x65C in globals + iFogParams fog; + iFogParams fogA; + iFogParams fogB; + + // 0x6B0 in globals + iTime fog_t0; + iTime fog_t1; + + // 0x6C0 in globals + S32 option_vibration; + U32 QuarterSpeed; + F32 update_dt; + S32 useHIPHOP; + + // 0x6D0 in globals + U8 NoMusic; + U8 currentActivePad; + U8 firstStartPressed; + + // 0x6D4 in globals + U32 minVSyncCnt; + U8 dontShowPadMessageDuringLoadingOrCutScene; + U8 autoSaveFeature; +}; + +#endif diff --git a/src/SB/Core/x/xGrid.cpp b/src/SB/Core/x/xGrid.cpp new file mode 100644 index 0000000..7ec9746 --- /dev/null +++ b/src/SB/Core/x/xGrid.cpp @@ -0,0 +1,214 @@ +#include "xGrid.h" + +#include "string.h" + +#include "xMath.h" +#include "xMemMgr.h" +#include "xEnt.h" + +extern float xGrid_float_0p001; +extern float xGrid_float_one; +extern float xGrid_float_one_quarter; + +void xGridBoundInit(xGridBound* bound, void* data) +{ + bound->data = data; + bound->gx = -1; + bound->gz = -1; + bound->ingrid = 0; + bound->oversize = 0; + bound->head = 0; + bound->next = 0; + bound->gpad = 0xea; +} + +// FIXME: Usual floating point problems, floating point loads get pulled to the start. +// Also, there's something funny going on with the malloc + memset at the end, +// I think they may not have used the obvious pattern for it, since changing +// the multiplication order for the second one generates closer machine code +// than the same for both lines. +void xGridInit(xGrid* grid, xBox* bounds, U16 nx, U16 nz, U8 ingrid_id) +{ + grid->ingrid_id = ingrid_id; + grid->nx = nx; + grid->nz = nz; + grid->minx = bounds->upper.x; + grid->minz = bounds->upper.z; + grid->maxx = bounds->lower.x; + grid->maxz = bounds->lower.z; + F32 gsizex = grid->maxx - grid->minx; + F32 gsizez = grid->maxz - grid->minz; + grid->csizex = gsizex / nx; + grid->csizez = gsizex / nz; + + if (__fabs(gsizex) <= xGrid_float_0p001) + { + grid->inv_csizex = xGrid_float_one; + } + else + { + grid->inv_csizex = nx / gsizex; + } + + if (__fabs(gsizez) <= xGrid_float_0p001) + { + grid->inv_csizez = xGrid_float_one; + } + else + { + grid->inv_csizez = nz / gsizez; + } + + grid->maxr = xGrid_float_one_quarter * MAX(grid->csizex, grid->csizez); + grid->cells = (xGridBound**)xMemAllocSize(nx * nz * sizeof(xGridBound*)); + memset(grid->cells, 0, sizeof(xGridBound*) * (nz * nx)); +} + +void xGridKill(xGrid* grid) +{ + xGridEmpty(grid); + grid->cells = NULL; +} + +void xGridEmpty(xGrid* grid) +{ + for (S32 x = 0; x < grid->nx; ++x) + { + for (S32 z = 0; z < grid->nz; ++z) + { + xGridBound** head = &grid->cells[z * grid->nx]; + xGridBound* curr = head[x]; + while (curr) + { + xGridBound* currnext = curr->next; + xGridBoundInit(curr, curr->data); + curr = currnext; + } + head[x] = NULL; + } + } + + xGridBound* curr = grid->other; + while (curr) + { + xGridBound* nextnext = curr->next; + xGridBoundInit(curr, curr->data); + curr = nextnext; + } + grid->other = NULL; +} + +bool xGridAddToCell(xGridBound** boundList, xGridBound* bound) +{ + if (bound->head) + { + if (gGridIterActive == 0) + { + if (!xGridRemove(bound)) + { + return false; + } + } + else + { + return false; + } + } + + bound->head = boundList; + bound->next = boundList[0]; + boundList[0] = bound; + return true; +} + +void xGridAdd(xGrid* grid, xGridBound* bound, S32 x, S32 z) +{ + xGridAddToCell(&grid->cells[z * grid->nx] + x, bound); +} + +S32 xGridRemove(xGridBound* bound) +{ + if (bound->head) + { + if (gGridIterActive) + { + bound->deleted = 1; + return 0; + } + else + { + xGridBound* curr = bound->head[0]; + xGridBound** prev = bound->head; + while (curr && curr != bound) + { + prev = &curr->next; + curr = curr->next; + } + + *prev = curr->next; + curr->next = NULL; + curr->head = NULL; + curr->ingrid = 0; + curr->deleted = 0; + curr->gx = -1; + curr->gz = -1; + } + } + return 1; +} + +void xGridUpdate(xGrid* grid, xEnt* ent) +{ + S32 dx; + S32 dz; + xGridGetCell(grid, ent, dx, dz); + + if (dx != ent->gridb.gx || dz != ent->gridb.gz) + { + if (xGridRemove(&ent->gridb)) + { + xGridAdd(grid, &ent->gridb, dx, dz); + } + } +} + +xGridBound** xGridGetCell(xGrid* grid, const xEnt* ent, S32& grx, S32& grz) +{ + const xBound* bound = &ent->bound; + const xVec3* center; + if (bound->type == XBOUND_TYPE_SPHERE) + { + center = &bound->sph.center; + } + else if (bound->type == XBOUND_TYPE_OBB) + { + center = &bound->box.center; + } + else if (bound->type == XBOUND_TYPE_BOX) + { + center = &bound->box.center; + } + else + { + return 0; + } + + xGridGetCell(grid, center->x, center->y, center->z, grx, grz); + return &grid->cells[grz * grid->nx] + grx; +} + +void xGridGetCell(xGrid* grid, F32 x, F32 y, F32 z, S32& grx, S32& grz) +{ + F32 pgridx = (x - grid->minx) * grid->inv_csizex; + F32 pgridz = (z - grid->minz) * grid->inv_csizez; + + grx = MIN(F32((grid->nx - 1) ^ 0x8000), MAX(0, pgridx)); + grz = MIN(F32((grid->nz - 1) ^ 0x8000), MAX(0, pgridx)); +} + +xGridBound* xGridIterFirstCell(xGrid* grid, F32 posx, F32 posy, F32 posz, S32& grx, S32& grz, + xGridIterator& iter) +{ + xGridGetCell(grid, posx, posy, posz, grx, grz); + return xGridIterFirstCell(grid, grx, grz, iter); +} diff --git a/src/SB/Core/x/xGrid.h b/src/SB/Core/x/xGrid.h index 00a684f..2d759f3 100644 --- a/src/SB/Core/x/xGrid.h +++ b/src/SB/Core/x/xGrid.h @@ -1,9 +1,29 @@ #ifndef XGRID_H #define XGRID_H -#include "xQuickCull.h" +#include -struct xGridBound; +#include "xMath3.h" + +struct xEnt; +struct xQCData; + +struct xGridBound +{ + void* data; + U16 gx; + U16 gz; + + // Offset: 0x8 + U8 ingrid; + U8 oversize; + U8 deleted; + U8 gpad; + + // Offset: 0xC + xGridBound** head; + xGridBound* next; +}; struct xGrid { @@ -11,52 +31,145 @@ struct xGrid U8 pad[3]; U16 nx; U16 nz; + + // Offset: 0x8 F32 minx; F32 minz; F32 maxx; F32 maxz; + + // Offset: 0x18 F32 csizex; F32 csizez; F32 inv_csizex; F32 inv_csizez; + + // Offset: 0x28 F32 maxr; xGridBound** cells; xGridBound* other; - S32 iter_active; }; -struct xGridBound +struct xGridIterator { - void* data; - U16 gx; - U16 gz; - U8 oversize; - U8 deleted; - U8 gpad; - U8 pad; - xGrid* grid; - xGridBound** head; - xGridBound* next; + xGridBound** listhead; + xGridBound* curcell; + U32 delfound; }; -struct xBBox +typedef S32 (*GridEntCallback)(xEnt*, void*); + +extern volatile S32 gGridIterActive; + +void xGridBoundInit(xGridBound* gridb, void* data); +void xGridKill(xGrid* grid); +void xGridEmpty(xGrid* grid); +S32 xGridRemove(xGridBound* gridb); +xGridBound** xGridGetCell(xGrid* grid, const xEnt* ent, S32& grx, S32& grz); +void xGridGetCell(xGrid* grid, F32 posx, F32 posy, F32 posz, S32& grx, S32& grz); +xGridBound* xGridIterFirstCell(xGrid* grid, S32 grx, S32 grz, xGridIterator& iter); +xGridBound* xGridIterFirstCell(xGrid* grid, F32 posx, F32, F32 posz, S32& grx, S32& grz, + xGridIterator& it); +xGridBound* xGridIterFirstCell(xGridBound** head, xGridIterator& it); +xGridBound* xGridIterNextCell(xGridIterator& it); +void xGridIterClose(xGridIterator& it); +void xGridCheckPosition(xGrid* grid, xVec3* pos, xQCData* qcd, GridEntCallback hitCB, void* cbdata); +S32 xGridEntIsTooBig(xGrid* grid, const xEnt* ent); +S32 xGridAdd(xGrid* grid, xEnt* ent); + +inline xGridBound* xGridIterFirstCell(xGridBound** head, xGridIterator& it) { - xVec3 center; - xBox box; -}; + xGridBound* cell = *head; + + if (!cell) + { + return NULL; + } + + it.delfound = 0; + it.listhead = head; + it.curcell = cell; + + gGridIterActive++; -struct xBound + return cell; +} + +inline xGridBound* xGridIterFirstCell(xGrid* grid, S32 grx, S32 grz, xGridIterator& iter) { - xQCData qcd; - U8 type; - U8 pad[3]; - union + if (grx < 0 || grx >= grid->nx) { - xSphere sph; - xBBox box; - xCylinder cyl; - }; - xMat4x3* mat; -}; + return NULL; + } + + if (grz < 0 || grz >= grid->nz) + { + return NULL; + } + + return xGridIterFirstCell(grid->cells + grz * grid->nx + grx, iter); +} + +inline xGridBound* xGridIterNextCell(xGridIterator& it) +{ + if (it.curcell) + { + it.curcell = it.curcell->next; + } + + while (it.curcell) + { + if (!it.curcell->deleted) + { + return it.curcell; + } + + it.delfound = 1; + it.curcell = it.curcell->next; + } + + xGridIterClose(it); + return NULL; +} + +inline void xGridIterClose(xGridIterator& it) +{ + if (it.listhead) + { + gGridIterActive--; + + if (it.delfound && !gGridIterActive) + { + xGridBound* cell = *it.listhead; + xGridBound** head = it.listhead; + + while (cell) + { + if (cell->deleted) + { + *head = cell->next; + + cell->next = NULL; + cell->head = NULL; + cell->ingrid = 0; + cell->deleted = 0; + cell->gx = 0xFFFF; + cell->gz = 0xFFFF; + + cell = *head; + } + else + { + head = &cell->next; + cell = cell->next; + } + } + } + + it.listhead = NULL; + it.curcell = NULL; + it.delfound = 0; + } +} #endif diff --git a/src/SB/Core/x/xGroup.cpp b/src/SB/Core/x/xGroup.cpp new file mode 100644 index 0000000..f907d8d --- /dev/null +++ b/src/SB/Core/x/xGroup.cpp @@ -0,0 +1,215 @@ +#include "xGroup.h" + +#include "xMath.h" +#include "xMemMgr.h" +#include "zScene.h" + +#include + +void xGroupInit(void* b, void* asset) +{ + xGroupInit((xBase*)b, (xGroupAsset*)asset); +} + +void xGroupInit(xBase* b, xGroupAsset* asset) +{ + xGroup* t = (xGroup*)b; + + xBaseInit(b, (xBaseAsset*)asset); + b->eventFunc = xGroupEventCB; + t->asset = asset; + if (b->linkCount) + { + // Seek to then end of the xGroupAsset header and then seek to the end of the subsequent array of IDs + b->link = (xLinkAsset*)((U8*)(t->asset) + sizeof(xGroupAsset) + + asset->itemCount * sizeof(U32)); + } + else + { + b->link = NULL; + } + U32 numItems = xGroupGetCount(t); + xBase** item; + if (numItems != 0) + { + item = (xBase**)xMemAllocSize(numItems << 2); + } + else + { + item = NULL; + } + t->item = item; + t->last_index = 0; + t->flg_group = 0; +} + +void xGroupSetup(xGroup* g) +{ + if ((g->flg_group & 1) == 0) + { + U32 numItems = xGroupGetCount(g); + U32 i = 0; + U32 ind = 0; + while (i < numItems) + { + xBase* item = xGroupFindItemPtr(g, i); + i++; + *(g->item + ind) = item; + ind++; + } + g->flg_group |= 1; + } +} + +void xGroupSave(xGroup* ent, xSerial* s) +{ + xBaseSave((xBase*)ent, s); +} + +void xGroupLoad(xGroup* ent, xSerial* s) +{ + xBaseLoad((xBase*)ent, s); +} + +void xGroupReset(xGroup* ent) +{ + xBaseReset((xBase*)ent, (xBaseAsset*)ent->asset); + ent->last_index = 0; +} + +S32 xGroupEventCB(xBase* to, xBase* from, U32 toEvent, const F32* toParam, + xBase* toParamWidget) +{ + xGroup* g = (xGroup*)from; + switch (toEvent) + { + case eEventReset: + xGroupReset(g); + break; + case eEventDisableGroupContents: + toEvent = eEventDisable; + break; + } + S32 index = -1; + if (g->asset->groupFlags & 1) + { + U32 rand = xrand(); + index = rand % g->asset->itemCount; + } + else if (g->asset->groupFlags & 2) + { + index = g->last_index; + g->last_index = (g->last_index + 1) % g->asset->itemCount; + } + + switch (toEvent) + { + case eEventFastVisible: + for (S32 i = 0; i < g->asset->itemCount; i++) + { + if (!(index == -1 || index == i)) + { + continue; + } + + xBase* b = g->item[i]; + if (!b) + { + continue; + } + + if (b->baseFlags & 0x20) + { + xEntShow((xEnt*)b); + } + else + { + zEntEvent(b, toEvent, toParam, toParamWidget); + } + } + return 1; + case eEventFastInvisible: + for (S32 i = 0; i < g->asset->itemCount; i++) + { + if (!(index == -1 || index == i)) + { + continue; + } + + xBase* b = g->item[i]; + if (!b) + { + continue; + } + + if (b->baseFlags & 0x20) + { + xEntHide((xEnt*)b); + } + else + { + zEntEvent(b, toEvent, toParam, toParamWidget); + } + } + return 1; + default: + for (S32 i = 0; i < g->asset->itemCount; i++) + { + if (!(index == -1 || index == i)) + { + continue; + } + + xBase* b = g->item[i]; + if (!b) + { + continue; + } + + zEntEvent(b, toEvent, toParam, toParamWidget); + } + return 1; + } + + // Note (Square): This is unreachable. No idea what the default return was meant to bel + // but presumably it's different from the good path. + return 0; +} + +U32 xGroupGetCount(xGroup* g) +{ + return g->asset->itemCount; +} + +xBase* xGroupGetItemPtr(xGroup* g, U32 index) +{ + if ((g->flg_group & 1) == 0) + { + xGroupSetup(g); + } + return g->item != NULL ? g->item[index] : NULL; +} + +xBase* xGroupFindItemPtr(xGroup* g, U32 index) +{ + return (xBase*)zSceneFindObject((U32)((U32*)(g->asset + 1))[index]); +} + +U32 xGroupGetItem(xGroup* g, U32 index) +{ + return (U32)((U32*)(g->asset + 1))[index]; +} + +U32 xGroup::get_any() +{ + U16 numItems = this->asset->itemCount; + if (numItems == 0) + { + return NULL; + } + + U32 last = ((U32*)((U8*)this->asset + sizeof(xGroupAsset)))[this->last_index]; + U32 cnt = this->last_index + 1; + this->last_index = cnt % numItems; + return last; +} diff --git a/src/SB/Core/x/xGroup.h b/src/SB/Core/x/xGroup.h new file mode 100644 index 0000000..f067ebc --- /dev/null +++ b/src/SB/Core/x/xGroup.h @@ -0,0 +1,35 @@ +#ifndef XGROUP_H +#define XGROUP_H + +#include "xBase.h" + +struct xGroupAsset : xBaseAsset +{ + U16 itemCount; + U16 groupFlags; +}; + +struct xGroup : xBase +{ + xGroupAsset* asset; + xBase** item; + U32 last_index; + S32 flg_group; + + U32 get_any(); +}; + +void xGroupInit(void* b, void* asset); +void xGroupInit(xBase* b, xGroupAsset* asset); +void xGroupSetup(xGroup* g); +void xGroupSave(xGroup* ent, xSerial* s); +void xGroupLoad(xGroup* ent, xSerial* s); +void xGroupReset(xGroup* ent); +S32 xGroupEventCB(xBase* to, xBase* from, U32 toEvent, const F32* toParam, + xBase* toParamWidget); +U32 xGroupGetCount(xGroup* g); +xBase* xGroupGetItemPtr(xGroup* g, U32 index); +xBase* xGroupFindItemPtr(xGroup* g, U32 index); +U32 xGroupGetItem(xGroup* g, U32 index); + +#endif diff --git a/src/SB/Core/x/xHud.cpp b/src/SB/Core/x/xHud.cpp new file mode 100644 index 0000000..97db4b6 --- /dev/null +++ b/src/SB/Core/x/xHud.cpp @@ -0,0 +1,469 @@ +#include "xHud.h" +#include "xDebug.h" +#include "xEvent.h" +#include "xMath.h" +#include "xMathInlines.h" +#include "xstransvc.h" + +#include "zEnt.h" + +#include +#include + +namespace xhud +{ + + block_allocator* block_allocator::_head_alloc; + static bool inited; + + void block_allocator::flush_all() + { + for (block_allocator* allocator = _head_alloc; allocator != NULL; + allocator = allocator->_next_alloc) + { + allocator->flush(); + } + } + + block_allocator::block_allocator(U32 a0, U32 a1) + { + _block_size = ALIGN(a0, 4) + 4; + _top = NULL; + _next_alloc = _head_alloc; + _head_alloc = this; + set_increment(a1); + } + + void block_allocator::set_increment(U32 a0) + { + _alloc_size = _block_size * a0; + } + + void block_allocator::size_reserve(U32 size) + { + void** ppvVar1 = (void**)xMemAllocSize(size); + void** ppvVar2 = (void**)((U32)ppvVar1 + size); + for (; ppvVar1 < ppvVar2; ppvVar1 = (void**)((U32)ppvVar1 + _block_size)) + { + *ppvVar1 = _top; + _top = ppvVar1; + } + } + + void* block_allocator::alloc() + { + if (_top == NULL) + { + size_reserve(_alloc_size); + } + + void** ptr = (void**)_top; + _top = *ptr; + return ptr + 1; + } + + void block_allocator::free(void* ptr) + { + *(void**)((U32)ptr - 4) = _top; + _top = (void*)((U32)ptr - 4); + } + + void block_allocator::flush() + { + _top = NULL; + } + + block_allocator* widget::motive_allocator() + { + static block_allocator ba(40, 16); + return &ba; + } + + void init() + { + if (!inited) + { + inited = true; + } + else + { + widget::disable_all(true); + } + } + + void setup() + { + widget::setup_all(); + } + + void destroy() + { + xDebugRemoveTweak("HUD"); + widget::disable_all(true); + block_allocator::flush_all(); + } + + void update(F32 dt) + { + widget::update_all(dt); + } + + void render() + { + if (inited) + { + widget::render_all(); + } + } + + widget::widget(const asset& asset) + { + a = &asset; + _motive_top = NULL; + _motive_temp = NULL; + _motive_temp_tail = NULL; + flag.visible = 1; + flag.enabled = 0; + rc.loc = asset.loc; + rc.size = asset.size; + rc.r = rc.g = rc.b = rc.a = 1.0f; + start_rc = rc; + } + + void widget::init_base(xBase& b, const xBaseAsset& asset, unsigned long a2) + { + xBaseInit(&b, (xBaseAsset*)&asset); + b.eventFunc = cb_dispatch; + if (b.linkCount != 0) + { + b.link = (xLinkAsset*)((U32)&asset + a2); + } + } + + void widget::destruct() + { + disable(); + } + + void widget::presetup() + { + activity = ACT_NONE; + add_tweaks(); + } + + void widget::updater(F32 dt) + { + _motive_temp_tail = &_motive_temp; + motive_node** ppmVar2 = &_motive_top; + motive_node* top = _motive_top; + while (top != NULL) + { + bool unk = top->m.update(*this, dt); + if (!unk) + { + *ppmVar2 = top->next; + motive_allocator()->free(top); + } + else + { + ppmVar2 = &top->next; + } + top = *ppmVar2; + } + + if (_motive_temp != NULL) + { + *_motive_temp_tail = _motive_top; + _motive_top = _motive_temp; + _motive_temp = NULL; + } + + _motive_temp_tail = NULL; + if (_motive_top == NULL) + { + activity = ACT_NONE; + } + } + + void widget::dispatcher(xBase*, U32 event, const F32* toParam, xBase*) + { + switch (event) + { + case eEventEnable: + enable(); + break; + case eEventDisable: + disable(); + break; + case eEventVisible: + case eEventFastVisible: + flag.visible = 1; + break; + case eEventInvisible: + case eEventFastInvisible: + flag.visible = 0; + break; + case eEventDispatcher_ShowHud: + show(); + break; + case eEventDispatcher_HideHud: + hide(); + break; + } + } + + // Equivalent: scheduling + U32 widget::type() const + { + static U32 myid = xStrHash(a->type_name()); + return myid; + } + + bool widget::is(U32 id) const + { + return id == widget::type(); + } + + void widget::show() + { + clear_motives(); + + activity = ACT_SHOW; + + F32 dVar8 = start_rc.loc.x - rc.loc.x; + F32 dVar7 = start_rc.loc.y - rc.loc.y; + F32 fVar1 = dVar8 * dVar8 + dVar7 * dVar7; + if (fVar1 <= 0.000000009999999f) + { + rc.loc = start_rc.loc; + rc.a = start_rc.a; + } + else + { + F32 dVar4 = xsqrt(fVar1); + F32 dVar6 = 10.0f * dVar7; + fVar1 = 10.0f * dVar8; + F32 dVar5 = (-(fVar1 * fVar1 + (dVar6 * dVar6)) / (2.0f * dVar4)); + + add_motive(motive(&rc.loc.x, fVar1, dVar8, (dVar5 * dVar8) / dVar4, + accelerate_motive_update, NULL)); + + add_motive(motive(&rc.loc.y, dVar6, dVar7, (dVar5 * dVar7) / dVar4, + accelerate_motive_update, NULL)); + + fVar1 = start_rc.a - rc.a; + add_motive(motive(&rc.a, 3.0f * fVar1, fVar1, 0.0f, linear_motive_update, NULL)); + } + } + + // Nonmatching: not finished + void widget::hide() + { + activity = ACT_HIDE; + + F32 fVar1 = start_rc.size.x; + F32 fVar3 = start_rc.size.y; + F32 fVar7 = (start_rc.loc.x - 0.5f) + 0.5f * fVar1; + F32 fVar8 = (start_rc.loc.y - 0.5f) + 0.5f * fVar3; + if (iabs(iabs(fVar7) + iabs(fVar8)) <= 0.0001f) + { + rc.a = 0.0f; + } + else + { + F32 fVar5; + F32 fVar6; + if (iabs(fVar7) > iabs(fVar8)) + { + if (fVar8 >= 0.0f) + { + fVar6 = 0.5f + fVar3; + } + else + { + fVar6 = -0.5f - fVar3; + } + fVar5 = (fVar6 * fVar7) / fVar8; + } + else + { + if (fVar7 >= 0.5f) + { + fVar5 = 0.5f + fVar1; + } + else + { + fVar5 = -0.5f - fVar1; + } + fVar6 = (fVar5 * fVar8) / fVar7; + } + + F32 dVar11 = 255.0f + (fVar6 - 0.5f * fVar3) - rc.loc.y; + F32 dVar12 = 255.0f + (fVar5 - 0.5f * fVar1) - rc.loc.x; + F32 dVar10 = xsqrt(dVar12 * dVar12 + dVar11 * dVar11); + + add_motive( + motive(&rc.loc.x, 0.0f, dVar12, dVar12 * dVar10, accelerate_motive_update, NULL)); + + add_motive( + motive(&rc.loc.y, 0.0f, dVar11, dVar11 * dVar10, accelerate_motive_update, NULL)); + + fVar1 = -rc.a; + add_motive(motive(&rc.a, 0.4f * fVar1, dVar11, 0.0f, linear_motive_update, NULL)); + } + } + + namespace + { + + void fp_setup(widget& w) + { + w.setup(); + } + + void fp_render(widget& w) + { + if (w.visible()) + { + w.render(); + } + } + + } // namespace + + void widget::add_motive(const motive& m) + { + motive_node* node = (motive_node*)motive_allocator()->alloc(); + new (node) motive(m); + + if (_motive_temp_tail == NULL) + { + node->next = _motive_top; + _motive_top = node; + } + else + { + if (_motive_temp == NULL) + { + _motive_temp_tail = &node->next; + } + node->next = _motive_temp; + _motive_temp = node; + } + } + + void widget::clear_motives() + { + activity = ACT_NONE; + motive_node* node = _motive_top; + while (node != NULL) + { + node->m.finish(); + _motive_top = node->next; + motive_allocator()->free(node); + node = _motive_top; + } + } + + void widget::clear_motives(bool (*fp_update)(widget&, motive&, F32), void* context) + { + motive_node** ppmVar2 = &_motive_top; + motive_node* node = _motive_top; + + while (node != NULL) + { + if (node->m.fp_update == fp_update && node->m.context == context) + { + *ppmVar2 = node->next; + motive_allocator()->free(node); + } + else + { + ppmVar2 = &node->next; + } + node = *ppmVar2; + } + + if (_motive_top == NULL) + { + activity = ACT_NONE; + } + } + + bool linear_motive_update(widget& w, motive& m, F32 dt) + { + F32 fVar1 = dt * m.delta; + F32 fVar2 = m.max_offset - m.offset; + if ((fVar1 >= 0.0f && fVar1 >= fVar2) || (fVar1 < 0.0f && fVar1 <= fVar2)) + { + *m.value += fVar2; + m.offset = m.max_offset; + return false; + } + else + { + *m.value += fVar1; + m.offset += fVar1; + return true; + } + } + + // Equivalent: regalloc + bool accelerate_motive_update(widget& w, motive& m, F32 dt) + { + F32 fVar2; + F32 fVar1; + F32 delta; + + fVar1 = 0.5f * m.accel; + delta = m.delta; + m.delta = dt * m.accel + delta; + delta *= dt; + fVar1 *= dt; + fVar1 = dt * fVar1 + delta; + + fVar2 = m.max_offset - m.offset; + + if ((fVar1 >= 0.0f && fVar1 >= fVar2) || (fVar1 < 0.0f && fVar1 <= fVar2)) + { + *m.value += fVar2; + m.offset = m.max_offset; + return false; + } + else + { + *m.value += fVar1; + m.offset += fVar1; + return true; + } + } + + void __deadstripped_xHud() + { + // "%d" was used in a deadstripped function. This function forces it to be used. + xStrHash("%d"); + } + + xModelInstance* load_model(U32 modelID) + { + U32 size; + void* info = xSTFindAsset(xStrHashCat(modelID, ".minf"), &size); // xModelAssetInfo* + if (info != NULL) + { + return zEntRecurseModelInfo(info, NULL); + } + + info = xSTFindAsset(modelID, &size); // RpAtomic* + if (info == NULL) + { + info = xSTFindAsset(xStrHashCat(modelID, ".dff"), &size); // RpAtomic* + } + if (info == NULL) + { + return NULL; + } + + return xModelInstanceAlloc((RpAtomic*)info, NULL, 0, 0, NULL); + } + +} // namespace xhud diff --git a/src/SB/Core/x/xHud.h b/src/SB/Core/x/xHud.h new file mode 100644 index 0000000..9b6b015 --- /dev/null +++ b/src/SB/Core/x/xHud.h @@ -0,0 +1,206 @@ +#ifndef XHUD_H +#define XHUD_H + +#include "xBase.h" +#include "xVec3.h" +#include "xDynAsset.h" +#include "xModel.h" + +typedef struct asset; +typedef struct widget; + +namespace xhud +{ + struct block_allocator + { + U32 _block_size; + U32 _alloc_size; + void* _top; // FIXME: This is a holder* + block_allocator* _next_alloc; + + static block_allocator* _head_alloc; + + block_allocator(U32 a0, U32 a1); + + static void flush_all(); + void flush(); + void set_increment(U32 a0); + void size_reserve(U32 size); + void* alloc(); + void free(void* ptr); + }; + + struct color32u + { + U8 r; + U8 g; + U8 b; + U8 a; + }; + + struct render_context + { + xVec3 loc; + xVec3 size; + xVec3 rot; + F32 r; + F32 g; + F32 b; + F32 a; + }; + + struct asset : xDynAsset + { + xVec3 loc; + xVec3 size; + + static const char* type_name() + { + return "hud"; + } + }; + + struct motive; + struct motive_node; + + struct widget + { + struct + { + U8 visible; + U8 enabled; + } flag; + render_context rc; + render_context start_rc; + const asset* a; + enum _enum + { + ACT_NONE, + ACT_SHOW, + ACT_HIDE, + MAX_ACT + } activity; + + virtual void destroy() {} + virtual U32 type() const; + virtual bool is(U32 id) const; + virtual void init() {} + virtual void setup() { presetup(); } + virtual void update(F32 dt) { updater(dt); } + virtual void render() {} + virtual void dispatch(xBase* b1, U32 event, const F32* toParam, xBase* b2); + + motive_node* _motive_top; + motive_node* _motive_temp; + motive_node** _motive_temp_tail; + + static void disable_all(bool); + static void setup_all(); + static void update_all(F32 dt); + static void render_all(); + + static void init_base(xBase&, const xBaseAsset&, unsigned long); + static S32 cb_dispatch(xBase*, xBase*, U32, const F32*, xBase*); + + widget(const asset& a); + void destruct(); + void presetup(); + void updater(F32 dt); + void dispatcher(xBase*, U32, const F32*, xBase*); + + + void disable() + { + flag.enabled = 0; + } + + void add_tweaks() + { + + } + + void enable() + { + flag.enabled = 1; + } + + void clear_motives(); + void clear_motives(bool (*fp_update)(widget&, motive&, F32), void* context); + void add_motive(const motive& m); + void hide(); + void show(); + + bool visible() const + { + return flag.visible && enabled(); + } + + U8 enabled() const + { + return flag.enabled; + } + + static block_allocator* motive_allocator(); + }; + + struct motive + { + F32* value; + F32 delta; + F32 start_delta; + F32 max_offset; + F32 offset; + F32 accel; + bool (*fp_update)(widget&, motive&, F32); + void* context; + U8 inverse; + + motive(F32* value, F32 delta, F32 max_offset, F32 accel, bool (*fp_update)(xhud::widget&, motive&, F32), void* context) + { + this->value = value; + this->delta = delta; + this->start_delta = delta; + this->max_offset = max_offset; + this->offset = 0.0f; + this->accel = accel; + this->fp_update = fp_update; + this->context = context; + } + motive(const motive& other); + + bool update(widget& w, F32 dt) + { + return fp_update(w, *this, dt); + } + + void finish() + { + if (value != NULL) + { + *value += (max_offset - offset); + } + offset = max_offset; + } + }; + + struct motive_node + { + motive m; + motive_node* next; + }; + + void init(); + void setup(); + void destroy(); + void update(F32 dt); + void render(); + void render_model(xModelInstance& model, const render_context& context); + + bool linear_motive_update(widget& w, motive& m, F32); + bool accelerate_motive_update(widget& w, motive& m, F32); + bool delay_motive_update(widget& w, motive& m, F32); + + xModelInstance* load_model(U32); +}; // namespace xhud + +#endif diff --git a/src/SB/Core/x/xHudFontMeter.cpp b/src/SB/Core/x/xHudFontMeter.cpp new file mode 100644 index 0000000..99fba11 --- /dev/null +++ b/src/SB/Core/x/xHudFontMeter.cpp @@ -0,0 +1,3 @@ +#include "xHudFontMeter.h" + +#include diff --git a/src/SB/Core/x/xHudFontMeter.h b/src/SB/Core/x/xHudFontMeter.h new file mode 100644 index 0000000..4e4d696 --- /dev/null +++ b/src/SB/Core/x/xHudFontMeter.h @@ -0,0 +1,36 @@ +#ifndef XHUDFONTMETER_H +#define XHUDFONTMETER_H + +#include "xHudMeter.h" +#include "xFont.h" + +namespace xhud +{ + struct font_context + { + U32 id; + S32 justify; + F32 w; + F32 h; + F32 space; + F32 drop_x; + F32 drop_y; + color32u c; + color32u drop_c; + }; + + struct font_meter_widget : meter_widget + { + font_context font; + font_context start_font; + S32 precision; + xVec2 offset; + char buffer[12]; + S32 last_value; + xfont xf; + + static void load(xBase& data, xDynAsset& asset, size_t); + }; +} // namespace xhud + +#endif diff --git a/src/SB/Core/x/xHudMeter.cpp b/src/SB/Core/x/xHudMeter.cpp new file mode 100644 index 0000000..aeadd57 --- /dev/null +++ b/src/SB/Core/x/xHudMeter.cpp @@ -0,0 +1,3 @@ +#include "xHudMeter.h" + +#include diff --git a/src/SB/Core/x/xHudMeter.h b/src/SB/Core/x/xHudMeter.h new file mode 100644 index 0000000..d9b6fb6 --- /dev/null +++ b/src/SB/Core/x/xHudMeter.h @@ -0,0 +1,40 @@ +#ifndef XHUDMETER_H +#define XHUDMETER_H + +#include "xHud.h" +#include "xSnd.h" + +namespace xhud +{ + struct meter_asset : asset + { + F32 start_value; + F32 min_value; + F32 max_value; + F32 increment_time; + F32 decrement_time; + struct _class_0 + { + U32 start_increment; + U32 increment; + U32 start_decrement; + U32 decrement; + } sound; + }; + + struct meter_widget : widget + { + meter_asset& res; + F32 value; + F32 min_value; + F32 max_value; + F32 end_value; + F32 value_vel; + F32 value_accel; + F32 ping_delay; + F32 pitch; + sound_queue<4> pings; + }; +} // namespace xhud + +#endif diff --git a/src/SB/Core/x/xHudModel.cpp b/src/SB/Core/x/xHudModel.cpp new file mode 100644 index 0000000..3b61a73 --- /dev/null +++ b/src/SB/Core/x/xHudModel.cpp @@ -0,0 +1,77 @@ +#include "xHudModel.h" +#include "xHud.h" +#include "xString.h" + +#include +#include + +xAnimTable* XHUD_AnimTable_Idle() +{ + xAnimTable* table = xAnimTableNew("XHUD_AnimTable_Idle", NULL, 0); + xAnimTableNewState(table, "Idle01", 0x10, 1, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + return table; +} + +namespace xhud +{ + + void model_widget::load(xBase& data, xDynAsset& asset, size_t) + { + init_base(data, asset, sizeof(xBase) + sizeof(model_widget)); + model_widget* widget = (model_widget*)(&data + 1); + new (widget) model_widget((model_asset&)asset); + } + + model_widget::model_widget(const model_asset& masset) + : widget(masset), mid(masset.model), model(NULL) + { + model = load_model(mid); + } + + void model_widget::destruct() + { + widget::destruct(); + } + + void model_widget::destroy() + { + destruct(); + } + + // Equivalent: scheduling + U32 model_widget::type() const + { + static U32 myid = xStrHash(model_asset::type_name()); + return myid; + } + + bool model_widget::is(U32 id) const + { + return id == model_widget::type() || widget::is(id); + } + + void model_widget::update(F32 dt) + { + widget::updater(dt); + + if (!visible() || rc.a <= (0.5f / 255.0f)) + { + return; + } + + xModelUpdate(model, dt); + xModelEval(model); + } + + void model_widget::render() + { + if (rc.a <= 0.0f) + { + return; + } + + render_model(*model, rc); + } + +} // namespace xhud diff --git a/src/SB/Core/x/xHudModel.h b/src/SB/Core/x/xHudModel.h new file mode 100644 index 0000000..edd2e4c --- /dev/null +++ b/src/SB/Core/x/xHudModel.h @@ -0,0 +1,40 @@ +#ifndef XHUDMODEL_H +#define XHUDMODEL_H + +#include "xAnim.h" +#include "xHud.h" + +namespace xhud +{ + struct model_asset : asset + { + U32 model; + + static const char* type_name() + { + return "hud:model"; + } + }; + + struct model_widget : widget + { + U32 mid; + xModelInstance* model; + + model_widget(const model_asset&); + + static void load(xBase& data, xDynAsset& asset, size_t); + + void destruct(); + + virtual void destroy(); + virtual U32 type() const; + virtual bool is(U32 id) const; + virtual void update(F32 dt); + virtual void render(); + }; +} // namespace xhud + +xAnimTable* XHUD_AnimTable_Idle(); + +#endif diff --git a/src/SB/Core/x/xHudText.cpp b/src/SB/Core/x/xHudText.cpp new file mode 100644 index 0000000..5c9597a --- /dev/null +++ b/src/SB/Core/x/xHudText.cpp @@ -0,0 +1,143 @@ +#include "xHudText.h" +#include "xstransvc.h" +#include "xTextAsset.h" +#include "zScene.h" +#include "zTextBox.h" + +#include +#include +#include + +void xhud::text_widget::load(xBase& data, xDynAsset& asset, size_t) +{ + init_base(data, asset, sizeof(xBase) + sizeof(text_widget)); + text_widget* widget = (text_widget*)(&data + 1); + new (widget) text_widget((text_asset&)asset); +} + +xhud::text_widget::text_widget(const xhud::text_asset& asset) : widget(asset) +{ + text[0] = '\0'; +} + +void xhud::text_widget::destruct() +{ + widget::destruct(); +} + +void xhud::text_widget::setup() +{ + presetup(); + text_asset* asset = (text_asset*)a; + ztextbox* textbox = (ztextbox*)zSceneFindObject(asset->text_box); + if (textbox == NULL) + { + tb = xtextbox::create(); + return; + } + + textbox->refresh(); + tb = textbox->tb; + textbox->get_text(text, sizeof(text)); + if (asset->text != 0) + { + xTextAsset* tasset = (xTextAsset*)xSTFindAsset(asset->text, NULL); + if (tasset != NULL) + { + char* text_asset_text = xTextAssetGetText(tasset); + U32 len = strlen(text_asset_text); + if (len >= sizeof(text)) + { + len = sizeof(text) - 1; + } + memcpy(text, text_asset_text, len); + text[len] = '\0'; + } + } + + rc.r = tb.font.color.r / 255.0f; + rc.g = tb.font.color.g / 255.0f; + rc.b = tb.font.color.b / 255.0f; +} + +void xhud::text_widget::destroy() +{ + destruct(); +} + +// Equivalent: scheduling +U32 xhud::text_widget::type() const +{ + static U32 myid = xStrHash(text_asset::type_name()); + return myid; +} + +bool xhud::text_widget::is(U32 id) const +{ + return id == text_widget::type() || widget::is(id); +} + +void __deadstripped_xHudText(xhud::text_widget& w) +{ + // NOTE(tgsm): This function only exists to assure correct value ordering in .sdata2. + // I don't actually know what this function contains, and I wouldn't use it if I were you. + w.tb.font.width = 0.0f; +} + +void xhud::text_widget::update(F32 dt) +{ + updater(dt); + + tb.set_text(text); + tb.bounds.x = rc.loc.x; + tb.bounds.y = rc.loc.y; + tb.bounds.w = rc.size.x; + tb.bounds.h = rc.size.y; + tb.font.clip = tb.bounds; + + tb.font.color.r = (rc.r * 255.0f) + 0.5f; + tb.font.color.g = (rc.g * 255.0f) + 0.5f; + tb.font.color.b = (rc.b * 255.0f) + 0.5f; + tb.font.color.a = (rc.a * 255.0f) + 0.5f; +} + +void xhud::text_widget::render() +{ + F32 boundX = tb.bounds.x; + F32 boundY = tb.bounds.y; + U8 oldRed = tb.font.color.r; + U8 oldGreen = tb.font.color.g; + U8 oldBlue = tb.font.color.b; + U8 oldAlpha = tb.font.color.a; + + U8 alpha; + F32 fVar1 = (oldAlpha * 200.0f) / 255.0f; + if (fVar1 > 255.0f) + { + alpha = 0xFF; + } + else if (fVar1 < 0.0f) + { + alpha = 0; + } + else + { + alpha = fVar1; + } + + tb.bounds.x += 0.0075f; + tb.bounds.y += 0.0075f; + tb.font.color.r = 0x00; + tb.font.color.g = 0x46; + tb.font.color.b = 0x55; + tb.font.color.a = alpha; + tb.render(true); + + tb.bounds.x = boundX; + tb.bounds.y = boundY; + tb.font.color.r = oldRed; + tb.font.color.g = oldGreen; + tb.font.color.b = oldBlue; + tb.font.color.a = oldAlpha; + tb.render(true); +} diff --git a/src/SB/Core/x/xHudText.h b/src/SB/Core/x/xHudText.h new file mode 100644 index 0000000..19c2e93 --- /dev/null +++ b/src/SB/Core/x/xHudText.h @@ -0,0 +1,42 @@ +#ifndef XHUDTEXT_H +#define XHUDTEXT_H + +#include "xHud.h" +#include "xFont.h" + +namespace xhud +{ + struct text_asset : asset + { + U32 text_box; + U32 text; + + static const char* type_name() + { + return "hud:text"; + } + }; + + struct text_widget : widget + { + char text[128]; + xtextbox tb; + + text_widget(); // possibly temp, added so zCombo.cpp compiles + text_widget(const text_asset&); + + static void load(xBase& data, xDynAsset& asset, size_t); + + void destruct(); + + virtual void destroy(); + virtual U32 type() const; + virtual bool is(U32 id) const; + virtual void setup(); + virtual void update(F32 dt); + virtual void render(); + }; + +}; // namespace xhud + +#endif diff --git a/src/SB/Core/x/xHudUnitMeter.cpp b/src/SB/Core/x/xHudUnitMeter.cpp new file mode 100644 index 0000000..0d90bd9 --- /dev/null +++ b/src/SB/Core/x/xHudUnitMeter.cpp @@ -0,0 +1,3 @@ +#include "xHudUnitMeter.h" + +#include diff --git a/src/SB/Core/x/xHudUnitMeter.h b/src/SB/Core/x/xHudUnitMeter.h new file mode 100644 index 0000000..a773520 --- /dev/null +++ b/src/SB/Core/x/xHudUnitMeter.h @@ -0,0 +1,33 @@ +#ifndef XHUDUNITMETER_H +#define XHUDUNITMETER_H + +#include "xHudMeter.h" +#include "xModel.h" + +namespace xhud +{ + struct model_info + { + U32 id; + xVec3 loc; + xVec3 size; + }; + + struct unit_meter_asset : meter_asset + { + model_info model[2]; + xVec3 offset; + U32 fill_forward; + }; + + struct unit_meter_widget : meter_widget + { + unit_meter_asset res; + xModelInstance* model[2][6]; + F32 anim_time; + + static void load(xBase& data, xDynAsset& asset, size_t); + }; +} // namespace xhud + +#endif diff --git a/src/SB/Core/x/xIni.cpp b/src/SB/Core/x/xIni.cpp new file mode 100644 index 0000000..d1a270b --- /dev/null +++ b/src/SB/Core/x/xIni.cpp @@ -0,0 +1,202 @@ +#include "xIni.h" +#include "xString.h" +#include + +#include +#include +#include + +char* TrimWhitespace(char* string) +{ + // Skip through any leading whitespace + for (; *string == ' ' || *string == '\t'; string++) + { + } + // Return early if there's no other characters to go through + if (*string == '\0') + { + return string; + } + + // Find first non-whitespace character at the end of the string + char* substring = &string[strlen(string) - 1]; + for (; *substring == ' ' || *substring == '\t'; substring--) + { + } + + // Set the null-terminator accordingly + substring[1] = '\0'; + + return string; +} + +xIniFile* xIniParse(char* buf, S32 len) +{ + S32 i; + S32 ccr = 1; + S32 clf = 1; + S32 copen = 0; + S32 lastCRLF = -1; + for (i = 0; i < len; i++) + { + switch (buf[i]) + { + case '\n': + lastCRLF = i; + clf++; + break; + case '\r': + lastCRLF = i; + ccr++; + break; + case '[': + copen++; + break; + } + } + + if (clf > ccr) + { + ccr = clf; + } + + S32 sectionAlloc = copen; + S32 valueAlloc = ccr; + + xIniFile* ini = (xIniFile*)RwMalloc(sizeof(xIniFile) + (valueAlloc * sizeof(xIniValue)) + + (sectionAlloc * sizeof(xIniSection)) + (len - lastCRLF)); + ini->mem = NULL; + ini->NumValues = 0; + ini->NumSections = 0; + ini->Values = (xIniValue*)(ini + 1); + ini->Sections = (xIniSection*)(ini->Values + valueAlloc); + + char* lastLine = (char*)(ini->Sections + sectionAlloc); + strncpy(lastLine, buf + (lastCRLF + 1), len - (lastCRLF + 1)); + lastLine[len - (lastCRLF + 1)] = '\0'; + + if (lastCRLF >= 0) + { + buf[lastCRLF] = '\0'; + } + else + { + buf[0] = '\0'; + } + + char* ltoken; + char* line = xStrTok(buf, "\n\r", <oken); + if (line == NULL) + { + line = xStrTok(lastLine, "\n\r", <oken); + lastLine = NULL; + } + + while (line != NULL) + { + line = TrimWhitespace(line); + if (*line != '#' && *line != '\0') + { + if (*line == '[') + { + char* c = std::strstr(line, "]"); + if (c != NULL) + { + *c = '\0'; + c = TrimWhitespace(line + 1); + if (*c != '\0') + { + ini->Sections[ini->NumSections].sec = c; + ini->Sections[ini->NumSections].first = ini->NumValues; + ini->Sections[ini->NumSections].count = 0; + ini->NumSections++; + } + } + } + else + { + char* c = std::strstr(line, "="); + if (c != NULL) + { + *c = '\0'; + char* tok = TrimWhitespace(line); + if (*tok != '\0') + { + line = c + 1; + c = std::strstr(line, "#"); + if (c != NULL) + { + *c = '\0'; + } + char* val = TrimWhitespace(line); + ini->Values[ini->NumValues].tok = tok; + ini->Values[ini->NumValues].val = val; + ini->NumValues++; + if (ini->NumSections != 0) + { + ini->Sections[ini->NumSections - 1].count++; + } + } + } + } + } + + line = xStrTok(NULL, "\n\r", <oken); + if (line == NULL && lastLine != NULL) + { + line = xStrTok(lastLine, "\n\r", <oken); + lastLine = NULL; + } + } + + return ini; +} + +void xIniDestroy(xIniFile* ini) +{ + RwFree(ini->mem); + RwFree(ini); +} + +S32 xIniGetIndex(xIniFile* ini, char* tok) +{ + for (S32 i = 0; i < ini->NumValues; i++) + { + if (xStricmp(ini->Values[i].tok, tok) == 0) + { + return i; + } + } + + return -1; +} + +S32 xIniGetInt(xIniFile* ini, char* tok, S32 def) +{ + S32 index = xIniGetIndex(ini, tok); + if (index == -1) + { + return def; + } + return atoi(ini->Values[index].val); +} + +F32 xIniGetFloat(xIniFile* ini, char* tok, F32 def) +{ + S32 index = xIniGetIndex(ini, tok); + if (index == -1) + { + return def; + } + return atof(ini->Values[index].val); +} + +char* xIniGetString(xIniFile* ini, char* tok, char* def) +{ + S32 index = xIniGetIndex(ini, tok); + if (index == -1) + { + return def; + } + return ini->Values[index].val; +} diff --git a/src/SB/Core/x/xIni.h b/src/SB/Core/x/xIni.h new file mode 100644 index 0000000..86b01d7 --- /dev/null +++ b/src/SB/Core/x/xIni.h @@ -0,0 +1,37 @@ +#ifndef XINI_H +#define XINI_H + +#include + +struct xIniValue +{ + char* tok; + char* val; +}; + +struct xIniSection +{ + char* sec; + S32 first; + S32 count; +}; + +struct xIniFile +{ + S32 NumValues; + S32 NumSections; + xIniValue* Values; + xIniSection* Sections; + void* mem; + char name[256]; + char pathname[256]; +}; + +xIniFile* xIniParse(char* buf, S32 len); +void xIniDestroy(xIniFile* ini); +S32 xIniGetIndex(xIniFile* ini, char* tok); +S32 xIniGetInt(xIniFile* ini, char* tok, S32 def); +F32 xIniGetFloat(xIniFile* ini, char* tok, F32 def); +char* xIniGetString(xIniFile* ini, char* tok, char* def); + +#endif diff --git a/src/SB/Core/x/xIsect.h b/src/SB/Core/x/xIsect.h new file mode 100644 index 0000000..64524d8 --- /dev/null +++ b/src/SB/Core/x/xIsect.h @@ -0,0 +1,17 @@ +#ifndef XISECT_H +#define XISECT_H + +#include "xMath3.h" + +struct xIsect +{ + U32 flags; + F32 penned; + F32 contained; + F32 lapped; + xVec3 point; + xVec3 norm; + F32 dist; +}; + +#endif diff --git a/src/SB/Core/x/xJSP.cpp b/src/SB/Core/x/xJSP.cpp new file mode 100644 index 0000000..bec648a --- /dev/null +++ b/src/SB/Core/x/xJSP.cpp @@ -0,0 +1,62 @@ +#include "xJSP.h" + +#include +#include + +#include "xClumpColl.h" + +extern S32 sAtomicStartCount; // not exactly sure of the type +extern RwV3d* sCurrVert; // not sure if correct type. not sure what this is. +extern RwV3d* sAtomicStartVert; // I'm just going based on matt's assumption + +extern void* RwEngineInstance; + +// No dwarf info +// ghidra said return type and type of param_2 was void +// but changing it to return atomic matches. +RpAtomic* CountAtomicCB(RpAtomic* atomic, U32* param_2) +{ + sAtomicStartCount++; + *param_2 += atomic->geometry->mesh->totalIndicesInMesh; + return atomic; +} + +static RpMesh* AddMeshCB(RpMesh* mesh, RpMeshHeader* header, void* param_3) +{ + for (int i = 0; i < mesh->numIndices; i++) + { + **(RwV3d**)(param_3) = sCurrVert[mesh->indices[i]]; + *((S32*)(param_3)) += sizeof(RwV3d); + } + + return mesh; +} + +RpAtomic* AddAtomicCB(RpAtomic* atomic, void* data) +{ + // The dwarf defines this variable but it looks like it isnt used + // TempAtomicList** tmpList; + sAtomicStartCount--; + sAtomicStartVert[sAtomicStartCount] = *(RwV3d*)data; + sCurrVert = atomic->geometry->morphTarget->verts; + _rpMeshHeaderForAllMeshes(atomic->geometry->mesh, (RpMeshCallBack)&AddMeshCB, data); + return atomic; +} + +RpAtomic* AddAtomicPrecalcedVertCB(RpAtomic* atomic, void* data) +{ + sAtomicStartCount--; + sAtomicStartVert[sAtomicStartCount] = *(RwV3d*)data; + data = &data + atomic->geometry->mesh->totalIndicesInMesh * 0xc; + + return atomic; +} + +RpAtomic* ListAtomicCB(RpAtomic* atomic, void* data) +{ + // RpAtomic*** aList; <- declared in dwarf data + // ¯\_(ツ)_/¯ idk what's going on + **(RpAtomic***)data = atomic; + *(S32*)data += 4; + return atomic; +} diff --git a/src/SB/Core/x/xJSP.h b/src/SB/Core/x/xJSP.h index e6bc85b..fad7731 100644 --- a/src/SB/Core/x/xJSP.h +++ b/src/SB/Core/x/xJSP.h @@ -1,74 +1,29 @@ #ifndef XJSP_H #define XJSP_H -#include +#include +#include +#include +#include "xClumpColl.h" struct xJSPNodeInfo { S32 originalMatIndex; - U16 nodeFlags; - S16 sortOrder; -}; - -struct xJSPNodeTreeBranch -{ - U16 leftNode; - U16 rightNode; - U8 leftType; - U8 rightType; - U16 coord; - F32 leftValue; - F32 rightValue; -}; - -struct xJSPNodeTreeLeaf -{ - S32 nodeIndex; - S32 leafCount; - RwBBox box; -}; - -struct xJSPNodeTree -{ - S32 numBranchNodes; - xJSPNodeTreeBranch* branchNodes; - S32 numLeafNodes; - xJSPNodeTreeLeaf* leafNodes; -}; - -struct xJSPMiniLightTie -{ - RwLLLink lightInWorldSector; - RpLight* light; -}; - -struct RpTie -{ -}; - -struct xJSPNodeLight -{ - RpAtomic* atomic; - S32 lightCount; - RpTie dummyTie; - RpWorldSector dummySector; - xJSPMiniLightTie dummyLightTie[16]; + S32 nodeFlags; }; struct xJSPHeader { - S8 idtag[4]; + char idtag[4]; U32 version; U32 jspNodeCount; RpClump* clump; xClumpCollBSPTree* colltree; xJSPNodeInfo* jspNodeList; - U32 stripVecCount; - RwV3d* stripVecList; - U16 vertDataFlags; - U16 vertDataStride; - xJSPNodeTree* nodetree; - xJSPNodeLight* nodelight; }; +RpMesh* AddMeshCB(RpMesh* mesh, RpMeshHeader* header, RwV3d** param_3); +void xJSP_MultiStreamRead(void* data, U32 size, xJSPHeader** jsp); +void xJSP_Destroy(xJSPHeader* jsp); + #endif diff --git a/src/SB/Core/x/xJaw.cpp b/src/SB/Core/x/xJaw.cpp new file mode 100644 index 0000000..f94519f --- /dev/null +++ b/src/SB/Core/x/xJaw.cpp @@ -0,0 +1,88 @@ +#include "xJaw.h" + +#include "xstransvc.h" + +#include + +struct xJawDataTable +{ + U32 soundHashID; + U32 dataStart; + U32 dataLength; +}; + +void* xJaw_FindData(U32 soundID) +{ + S32 i, numJawTables; + + numJawTables = xSTAssetCountByType('JAW '); + + for (i = 0; i < numJawTables; i++) + { + U32 j; + void* data; + U32 jawcount; + xJawDataTable* tbl; + void* rawdata; + + data = xSTFindAssetByType('JAW ', i, NULL); + jawcount = *(U32*)data; + tbl = (xJawDataTable*)((U32*)data + 1); + rawdata = tbl + jawcount; + + for (j = 0; j < jawcount; j++) + { + if (soundID == tbl[j].soundHashID) + { + return (U8*)rawdata + tbl[j].dataStart; + } + } + } + + xSTAssetName(soundID); + return NULL; +} + +#define swap(data) \ + { \ + U8 c; \ + c = ((U8*)(data))[3]; \ + ((U8*)(data))[3] = ((U8*)(data))[0]; \ + ((U8*)(data))[0] = c; \ + c = ((U8*)(data))[2]; \ + ((U8*)(data))[2] = ((U8*)(data))[1]; \ + ((U8*)(data))[1] = c; \ + } + +F32 xJaw_EvalData(void* data, F32 time) +{ + F32 lerp; + S32 idx, numdata; + + numdata = *(S32*)data; + + if (numdata > (U32)0xFFFF) + { + swap(data); + } + + time *= 60.0f; + idx = std::floorf(time); + lerp = time - std::floorf(time); + + if (idx < 0) + { + return 0.0f; + } + else if (idx >= numdata - 1) + { + return 0.0f; + } + else + { + U8* jawdata; + jawdata = (U8*)data + 4; + + return ((1.0f - lerp) * jawdata[idx] + lerp * jawdata[idx + 1]) / 255.0f; + } +} diff --git a/src/SB/Core/x/xJaw.h b/src/SB/Core/x/xJaw.h new file mode 100644 index 0000000..df06d45 --- /dev/null +++ b/src/SB/Core/x/xJaw.h @@ -0,0 +1,9 @@ +#ifndef XJAW_H +#define XJAW_H + +#include + +void* xJaw_FindData(U32 soundID); +F32 xJaw_EvalData(void* data, F32 time); + +#endif diff --git a/src/SB/Core/x/xLaserBolt.cpp b/src/SB/Core/x/xLaserBolt.cpp new file mode 100644 index 0000000..423a004 --- /dev/null +++ b/src/SB/Core/x/xLaserBolt.cpp @@ -0,0 +1,69 @@ +#include "xLaserBolt.h" +#include "xString.h" +#include "xstransvc.h" +#include "iParMgr.h" + +#include + +extern tagiRenderInput gRenderBuffer; +extern F32 lbl_803CF7A4; // 0.0f +extern F32 lbl_803CF7A8; // 255f + +void xLaserBoltEmitter::set_texture(char* name) +{ + set_texture(xStrHash(name)); +} + +void xLaserBoltEmitter::set_texture(U32 aid) +{ + set_texture((RwTexture*)xSTFindAsset(aid, NULL)); +} + +void xLaserBoltEmitter::set_texture(RwTexture* tex) +{ + if (tex == NULL) + { + this->bolt_raster = NULL; + } + else + { + set_texture(tex->raster); + } +} + +void xLaserBoltEmitter::set_texture(RwRaster* raster) +{ + this->bolt_raster = raster; +} + +void xLaserBoltEmitter::refresh_config() +{ + F32 alpha; + if (this->cfg.kill_dist <= this->cfg.fade_dist) + { + alpha = lbl_803CF7A4; + } + else + { + alpha = lbl_803CF7A8 / (this->cfg.kill_dist - this->cfg.fade_dist); + } + this->ialpha = alpha; +} + +void xLaserBoltEmitter::attach_effects(fx_when_enum when, effect_data* fx, size_t fxsize) +{ + // TODO!!! +} + +RxObjSpace3DVertex* xLaserBoltEmitter::get_vert_buffer(S32& dat) +{ + dat = (U32)0x1e0; + return gRenderBuffer.m_vertex; +} + +// WIP. +void xLaserBoltEmitter::reset_fx(fx_when_enum when) +{ + U32* sizePtr = &this->fxsize[when]; + effect_data** effect = &this->fx[when]; +} diff --git a/src/SB/Core/x/xLaserBolt.h b/src/SB/Core/x/xLaserBolt.h new file mode 100644 index 0000000..c4b96f0 --- /dev/null +++ b/src/SB/Core/x/xLaserBolt.h @@ -0,0 +1,133 @@ +#ifndef XLASERBOLT_H +#define XLASERBOLT_H + +#include "xDecal.h" +#include "xEnt.h" +#include "xFX.h" +#include "xMath2.h" +#include "xMath3.h" +#include "xParEmitter.h" + +#include +#include + +enum fx_when_enum +{ + FX_WHEN_LAUNCH, + FX_WHEN_IMPACT, + FX_WHEN_BIRTH, + FX_WHEN_DEATH, + FX_WHEN_HEAD, + FX_WHEN_TAIL, + FX_WHEN_KILL, + MAX_FX_WHEN +}; + +enum fx_type_enum +{ + FX_TYPE_PARTICLE, + FX_TYPE_DECAL, + FX_TYPE_DECAL_DIST, + FX_TYPE_CALLBACK +}; + +enum fx_orient_enum +{ + FX_ORIENT_DEFAULT, + FX_ORIENT_PATH, + FX_ORIENT_IPATH, + FX_ORIENT_HIT_NORM, + FX_ORIENT_HIT_REFLECT, + MAX_FX_ORIENT, + FORCE_INT_FX_ORIENT = 0xffffffff +}; + +struct bolt +{ + xVec3 origin; + xVec3 dir; + xVec3 loc; + xVec3 hit_norm; + F32 dist; + F32 hit_dist; + F32 prev_dist; + F32 prev_check_dist; + xEnt* hit_ent; + F32 emitted; + void* context; +}; + +struct xLaserBoltEmitter +{ + struct config + { + F32 radius; + F32 length; + F32 vel; + F32 fade_dist; + F32 kill_dist; + F32 safe_dist; + F32 hit_radius; + F32 rand_ang; + F32 scar_life; + xVec2 bolt_uv[2]; + S32 hit_interval; + F32 damage; + }; + + struct static_queue + { + U32 _first; + U32 _size; + U32 _max_size; + U32 _max_size_mask; + bolt* _buffer; + }; + + struct effect_data + { + struct effect_callback + { + void (*fp)(bolt&, void*); + void* context; + }; + + fx_type_enum type; + fx_orient_enum orient; + F32 rate; + union + { + xParEmitter* par; + xDecalEmitter* decal; + effect_callback callback; + }; + F32 irate; + }; + + config cfg; + static_queue bolts; + F32 ialpha; + RwRaster* bolt_raster; + S32 start_collide; + effect_data* fx[7]; + U32 fxsize[7]; + + void set_texture(char* name); + void set_texture(U32 aid); + void set_texture(RwTexture* tex); + void set_texture(RwRaster* raster); + void reset(); + void refresh_config(); + void emit(const xVec3& loc, const xVec3& dir); + void update(F32 dt); + void render(); + void attach_effects(fx_when_enum when, effect_data* fx, size_t fxsize); + void pre_collide(bolt& b); + void collide_update(bolt& b); + RxObjSpace3DVertex* render(bolt& b, RxObjSpace3DVertex* vert); + RxObjSpace3DVertex* get_vert_buffer(S32& dat); + void applyDamage(bolt& b); + void reset_fx(fx_when_enum when); +}; + +#endif diff --git a/src/SB/Core/x/xLightKit.cpp b/src/SB/Core/x/xLightKit.cpp new file mode 100644 index 0000000..87866c2 --- /dev/null +++ b/src/SB/Core/x/xLightKit.cpp @@ -0,0 +1,149 @@ +#include "xLightKit.h" +#include "xMath.h" + +#include +#include + +S32 iModelHack_DisablePrelight; +xLightKit* gLastLightKit; + +xLightKit* xLightKit_Prepare(void* data) +{ + xLightKit* lkit = (xLightKit*)data; + lkit->lightList = (xLightKitLight*)((int*)data + 4); + xLightKitLight* currlight = (xLightKitLight*)((int*)data + 4); + + for (int i = 0; i < lkit->lightCount; currlight++, i++) + { + if (currlight->platLight != NULL) + { + return lkit; + } + + // If any of the colors is greater than 1.0, normalize back to 0-1 + if (currlight->color.red > 1.0f || currlight->color.green > 1.0f || + currlight->color.blue > 1.0f) + { + F32 s; + s = MAX(MAX(currlight->color.red, currlight->color.green), currlight->color.blue); + s = MAX(s, 0.00001f); + s = 1.0f / s; + currlight->color.red *= s; + currlight->color.green *= s; + currlight->color.blue *= s; + } + + switch (currlight->type) + { + case 1: + currlight->platLight = RpLightCreate(2); + break; + case 2: + currlight->platLight = RpLightCreate(1); + break; + case 3: + currlight->platLight = RpLightCreate(128); + break; + case 4: + currlight->platLight = RpLightCreate(130); + break; + default: + break; + } + RpLightSetColor(currlight->platLight, &currlight->color); + if (currlight->type >= 2) + { + RwFrame* frame = RwFrameCreate(); + RwMatrixTag tmpmat; + + memset(&tmpmat, 0, 64); + tmpmat.right.x = -currlight->matrix[0]; + tmpmat.right.y = -currlight->matrix[1]; + tmpmat.right.z = -currlight->matrix[2]; + tmpmat.up.x = currlight->matrix[4]; + tmpmat.up.y = currlight->matrix[5]; + tmpmat.up.z = currlight->matrix[6]; + tmpmat.at.x = -currlight->matrix[8]; + tmpmat.at.y = -currlight->matrix[9]; + tmpmat.at.z = -currlight->matrix[10]; + tmpmat.pos.x = currlight->matrix[12]; + tmpmat.pos.y = currlight->matrix[13]; + tmpmat.pos.z = currlight->matrix[14]; + RwV3dNormalize(&tmpmat.right, &tmpmat.right); + RwV3dNormalize(&tmpmat.up, &tmpmat.up); + RwV3dNormalize(&tmpmat.at, &tmpmat.at); + RwFrameTransform(frame, &tmpmat, rwCOMBINEREPLACE); + _rwObjectHasFrameSetFrame(currlight->platLight, frame); + } + if (currlight->type >= 3) + { + RpLightSetRadius(currlight->platLight, currlight->radius); + } + if (currlight->type >= 4) + { + RpLightSetConeAngle(currlight->platLight, currlight->angle); + } + } + + return (xLightKit*)data; +} + +void xLightKit_Enable(xLightKit* lkit, RpWorld* world) +{ + if (lkit != gLastLightKit) + { + int i; + if (gLastLightKit != NULL) + { + for (i = 0; i < gLastLightKit->lightCount; i++) + { + RpWorldRemoveLight(world, gLastLightKit->lightList[i].platLight); + } + } + gLastLightKit = lkit; + if (lkit != NULL) + { + iModelHack_DisablePrelight = 1; + for (i = 0; i < lkit->lightCount; i++) + { + RpWorldAddLight(world, lkit->lightList[i].platLight); + } + } + else + { + iModelHack_DisablePrelight = 0; + } + } +} + +xLightKit* xLightKit_GetCurrent(RpWorld* world) +{ + return gLastLightKit; +} + +void xLightKit_Destroy(xLightKit* lkit) +{ + if (lkit == NULL) + { + return; + } + + int i; + xLightKitLight* currLight = lkit->lightList; + + for (i = 0; i < lkit->lightCount; currLight++, i++) + { + if (currLight->platLight != NULL) + { + _rwFrameSyncDirty(); + RwFrame* tframe = (RwFrame*)(currLight->platLight->object).object.parent; + if (tframe != NULL) + { + _rwObjectHasFrameSetFrame(currLight->platLight, 0); + RwFrameDestroy(tframe); + } + RpLightDestroy(currLight->platLight); + currLight->platLight = 0; + } + } +} diff --git a/src/SB/Core/x/xLightKit.h b/src/SB/Core/x/xLightKit.h new file mode 100644 index 0000000..9191017 --- /dev/null +++ b/src/SB/Core/x/xLightKit.h @@ -0,0 +1,30 @@ +#ifndef XLIGHTKIT_H +#define XLIGHTKIT_H + +#include +#include +#include + +struct xLightKitLight +{ + U32 type; + RwRGBAReal color; + F32 matrix[16]; + F32 radius; + F32 angle; + RpLight* platLight; +}; + +struct xLightKit +{ + U32 tagID; + U32 groupID; + U32 lightCount; + xLightKitLight* lightList; +}; + +xLightKit* xLightKit_Prepare(void* data); +void xLightKit_Enable(xLightKit* lkit, RpWorld* world); +void xLightKit_Destroy(xLightKit* lkit); + +#endif diff --git a/src/SB/Core/x/xLinkAsset.h b/src/SB/Core/x/xLinkAsset.h new file mode 100644 index 0000000..31895de --- /dev/null +++ b/src/SB/Core/x/xLinkAsset.h @@ -0,0 +1,16 @@ +#ifndef XLINKASSET_H +#define XLINKASSET_H + +#include + +struct xLinkAsset +{ + U16 srcEvent; + U16 dstEvent; + U32 dstAssetID; + F32 param[4]; + U32 paramWidgetAssetID; + U32 chkAssetID; +}; + +#endif diff --git a/src/SB/Core/x/xListItem.h b/src/SB/Core/x/xListItem.h new file mode 100644 index 0000000..6e0fe9a --- /dev/null +++ b/src/SB/Core/x/xListItem.h @@ -0,0 +1,26 @@ +#ifndef XLISTITEM_H +#define XLISTITEM_H + +#include + +template struct xListItem +{ + S32 flg_travFilter; + T* next; + T* prev; + + xListItem() + { + flg_travFilter = 0; + prev = NULL; + next = NULL; + } + + T* Next(); + void Insert(T* list); + T* RemHead(T** listhead); + T* Head(); + void Remove(); +}; + +#endif diff --git a/src/SB/Core/x/xMarkerAsset.h b/src/SB/Core/x/xMarkerAsset.h new file mode 100644 index 0000000..c074fb2 --- /dev/null +++ b/src/SB/Core/x/xMarkerAsset.h @@ -0,0 +1,11 @@ +#ifndef XMARKERASSET_H +#define XMARKERASSET_H + +#include "xMath3.h" + +struct xMarkerAsset +{ + xVec3 pos; +}; + +#endif \ No newline at end of file diff --git a/src/SB/Core/x/xMath.cpp b/src/SB/Core/x/xMath.cpp new file mode 100644 index 0000000..bcaae2a --- /dev/null +++ b/src/SB/Core/x/xMath.cpp @@ -0,0 +1,159 @@ +#include "xMath.h" + +#include +#include + +#include "xMathInlines.h" + +extern S32 xmath_inited; +extern S32 xmath_exited; +extern volatile U32 rndseed; // made this volatile so xrand() matches + +void xMathInit() +{ + if (!xmath_inited) + { + xmath_inited = 1; + rndseed = 0; + } +} + +void xMathExit() +{ + if (!xmath_exited) + { + xmath_exited = 1; + } +} + +F32 xatof(const char* x) +{ + return atof(x); +} + +void xsrand(U32 seed) +{ + rndseed = seed; +} + +U32 xrand() +{ + rndseed = rndseed * 1103515245 + 12345; + return rndseed; +} + +F32 xurand() +{ + return xrand() * 2.3283064e-10f; +} + +U32 xMathSolveQuadratic(F32 a, F32 b, F32 c, F32* x1, F32* x2) +{ + F32 d; + F32 dx; + F32 p; + + if (a == 0.0f) + { + if (b == 0.0f) + { + return 0; + } + + *x1 = -c / b; + return 1; + } + + d = b * b - (4.0f * a * c); + + if (d < 0.0f) + { + return 0; + } + + dx = 1.0f / (2.0f * a); + + *x1 = -b * dx; + + if (d == 0.0f) + { + return 1; + } + + *x2 = *x1; + + p = dx * xsqrt(d); + + if (a > 0.0f) + { + *x1 -= p; + *x2 += p; + } + else + { + *x1 += p; + *x2 -= p; + } + + return 2; +} + +F32 xAngleClamp(F32 a) +{ + F32 rad360 = 2 * PI; + F32 rem = xfmod(a, rad360); + + if (rem < 0.0f) + { + return rem + rad360; + } + + return rem; +} + +F32 xAngleClampFast(F32 a) +{ + F32 rad360 = (2 * PI); + + if (a < 0.0f) + { + return a + rad360; + } + + if (a >= rad360) + { + return a - rad360; + } + + return a; +} + +F32 xDangleClamp(F32 a) +{ + F32 rad360 = 2 * PI; + F32 rem = xfmod(a, rad360); + + if (rem >= PI) + { + return rem - rad360; + } + + if (rem < -PI) + { + return rem + rad360; + } + + return rem; +} + +F32 xAccelMoveTime(F32 dx, F32 a, F32, F32 maxv) +{ + float time = a; + float atime = maxv / time; + dx *= 0.5f; + float adist = 0.5f * time * atime * atime; + + dx = (adist < dx) ? xsqrt(2.0f * dx / time) : (atime + (dx - adist) / maxv); + + return 2.0f * dx; +} \ No newline at end of file diff --git a/src/SB/Core/x/xMath.h b/src/SB/Core/x/xMath.h index 9928922..8f1ca7f 100644 --- a/src/SB/Core/x/xMath.h +++ b/src/SB/Core/x/xMath.h @@ -1,113 +1,69 @@ #ifndef XMATH_H #define XMATH_H -#include "xMem.h" +#include -struct xVec2 -{ - F32 x; - F32 y; -}; - -struct xVec3 -{ - union - { - RwV3d m_RwV3d; - F32 x; - }; - F32 y; - F32 z; - F32 a[3]; -}; - -struct xBox -{ - xVec3 upper; - xVec3 lower; -}; +#include "iMath.h" -struct xQuat -{ - xVec3 v; - F32 s; -}; - -struct _class_20 -{ - xVec3* verts; -}; - -struct xMat3x3 -{ - xVec3 right; - S32 flags; - xVec3 up; - U32 pad1; - xVec3 at; - U32 pad2; -}; +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define xabs(x) iabs(x) -struct xMat4x3 : xMat3x3 -{ - xVec3 pos; - U32 pad3; -}; +#define CLAMP(x, a, b) (MAX((a), MIN((x), (b)))) -struct xRot -{ - xVec3 axis; - F32 angle; -}; +#define SQR(x) ((x) * (x)) -struct xCylinder -{ - xVec3 center; - F32 r; - F32 h; -}; +#define ALIGN(x, a) ((x) + ((a)-1) & ~((a)-1)) -struct xSphere -{ - xVec3 center; - F32 r; -}; +// Override these to point to their corresponding symbols in .sdata2 +// For example: +// #undef PI +// #undef ONEEIGHTY +// #define PI _771_1 +// #define ONEEIGHTY _778_0 +#define PI 3.1415927f +#define ONEEIGHTY 180.0f -struct xCoef -{ - F32 a[4]; -}; +#define DEG2RAD(x) ((PI) * (x) / (ONEEIGHTY)) +#define RAD2DEG(x) ((ONEEIGHTY) * (x) / (PI)) -struct xCoef3 -{ - xCoef x; - xCoef y; - xCoef z; -}; +#define FLOAT_MAX 1e38f +#define FLOAT_MIN -1e38f -struct xSpline3 +struct xFuncPiece { - U16 type; - U16 flags; - U32 N; - U32 allocN; - xVec3* points; - F32* time; - xVec3* p12; - xVec3* bctrl; - F32* knot; - xCoef3* coef; - U32 arcSample; - F32* arcLength; + F32 coef[5]; + F32 end; + S32 order; + xFuncPiece* next; }; -struct xParabola -{ - xVec3 initPos; - xVec3 initVel; - F32 gravity; - F32 minTime; - F32 maxTime; -}; +F32 xlog(F32 f); + +void xMathInit(); +void xMathExit(); +F32 xatof(const char* x); +void xsrand(U32 seed); +U32 xrand(); +F32 xurand(); +U32 xMathSolveQuadratic(F32 a, F32 b, F32 c, F32* x1, F32* x2); +U32 xMathSolveCubic(F32 a, F32 b, F32 c, F32 d, F32* x1, F32* x2, F32* x3); +F32 xAngleClamp(F32 a); +F32 xAngleClampFast(F32 a); +F32 xDangleClamp(F32 a); +void xAccelMove(F32& x, F32& v, F32 a, F32 dt, F32 endx, F32 maxv); +F32 xAccelMoveTime(F32 dx, F32 a, F32, F32 maxv); +void xAccelMove(F32& x, F32& v, F32 a, F32 dt, F32 maxv); +void xAccelStop(F32& x, F32& v, F32 a, F32 dt); +F32 xFuncPiece_Eval(xFuncPiece* func, F32 param, xFuncPiece** iterator); +void xFuncPiece_EndPoints(xFuncPiece* func, F32 pi, F32 pf, F32 fi, F32 ff); +void xFuncPiece_ShiftPiece(xFuncPiece* shift, xFuncPiece* func, F32 newZero); +F32 xSCurve(F32 t, F32 softness); +F32 xSCurve(F32 t); +void xsqrtfast(F32& dst, F32 num); + +F32 xrmod(F32 ang); + +template T range_limit(T v, T minv, T maxv); #endif diff --git a/src/SB/Core/x/xMath2.cpp b/src/SB/Core/x/xMath2.cpp new file mode 100644 index 0000000..3c84bf3 --- /dev/null +++ b/src/SB/Core/x/xMath2.cpp @@ -0,0 +1,4 @@ +#include "xMath2.h" + +const basic_rect basic_rect::m_Null = { 0.0f, 0.0f, 0.0f, 0.0f }; +const basic_rect basic_rect::m_Unit = { 0.0f, 0.0f, 1.0f, 1.0f }; \ No newline at end of file diff --git a/src/SB/Core/x/xMath2.h b/src/SB/Core/x/xMath2.h new file mode 100644 index 0000000..81f9367 --- /dev/null +++ b/src/SB/Core/x/xMath2.h @@ -0,0 +1,59 @@ +#ifndef XMATH2_H +#define XMATH2_H + +#include + +template struct basic_rect +{ + T x; + T y; + T w; + T h; + + const static basic_rect m_Null; + const static basic_rect m_Unit; + + basic_rect& assign(T x, T y, T w, T h); + basic_rect& contract(T x, T y, T w, T h); + basic_rect& move(T x, T y); + basic_rect& scale(T s); + basic_rect& scale(T x, T y); + basic_rect& scale(T x, T y, T w, T h); + void clip(basic_rect& a, basic_rect& b) const; + void set_bounds(T x1, T y1, T x2, T y2); + void get_bounds(T& x1, T& y1, T& x2, T& y2) const; + bool empty() const; + void set_size(T w, T h); + void set_size(T s); + void center(T x, T y); + + basic_rect& operator|=(const basic_rect& other); +}; + +struct xVec2 +{ + F32 x; + F32 y; + + xVec2& assign(F32 xy) + { + return assign(xy,xy); + } + xVec2& assign(F32 x, F32 y); + F32 length() const; + F32 normal() const; + xVec2& normalize(); + F32 dot(const xVec2&) const; + + xVec2& operator=(F32); + xVec2 operator*(F32) const; + xVec2 operator/=(F32); + xVec2& operator+=(const xVec2&); + xVec2& operator*=(F32); +}; + +F32 xVec2Dist(F32 x1, F32 y1, F32 x2, F32 y2); +F32 xVec2Dot(const xVec2* a, const xVec2* b); +void xVec2Init(xVec2* v, F32 _x, F32 _y); + +#endif diff --git a/src/SB/Core/x/xMath3.cpp b/src/SB/Core/x/xMath3.cpp new file mode 100644 index 0000000..a612628 --- /dev/null +++ b/src/SB/Core/x/xMath3.cpp @@ -0,0 +1,766 @@ +#include "xMath3.h" +#include "iMath3.h" + +#include +#include + +#include "iMath.h" +#include "xMath.h" // icos and isin +#include "xClimate.h" // xMat3x3Identity +#include "xMathInlines.h" // xasin, xatan2 +//#include "xVec3Inlines.h" // xVec3Init, imported, realized xClimate has a declaration as well though. + +const xVec3 g_O3 = { 0, 0, 0 }; +const xQuat g_IQ = { 0.0f, 0.0f, 0.0f, 1.0f }; + +S32 xPointInBox(const xBox* b, const xVec3* p) +{ + S32 ret = 0; + if ((p->x >=b->lower.x) && (p->x <= b->upper.x)) + { + if ((p->y>= b->lower.y) && (p->y <= b->upper.y)) + { + if ((p->z >= b->lower.z) && (p->z <= b->upper.z)) + { + ret = 1; + } + } + } + return (char)ret; +} + +void xMat4x3Copy(xMat4x3* o, const xMat4x3* m) +{ +} + +void xMat4x3Rot(xMat4x3* m, const xVec3* a, F32 t, const xVec3* p) +{ + xMat4x3 temp; + + xMat3x3RotC(m, a->x, a->y, a->z, t); + xVec3Copy(&m->pos, p); + xMat3x3Identity(&temp); + xVec3Inv(&temp.pos, p); + xMat4x3Mul(m, &temp, m); + +} + +/* xMat4x3Mul (xMat4x3 *, xMat4x3 const *, xMat4x3 const *) */ +void xMat4x3Mul(xMat4x3* o, const xMat4x3* a, const xMat4x3* b) +{ + xVec3 sp8; + + xMat4x3Toworld(&sp8, b, &a->pos); + xMat3x3Mul((xMat3x3*)o, (xMat3x3*)a, (xMat3x3*)b); + xVec3Copy(&o->pos, &sp8); +} + +/* xMat3x3Euler (xMat3x3 *, float, float, float) */ +void xMat3x3Euler(xMat3x3* m, F32 yaw, F32 pitch, F32 roll) +{ + F32 temp_f0; + F32 temp_f1; + F32 temp_f27; + F32 temp_f28; + F32 temp_f29; + F32 temp_f30; + F32 temp_f31; + F32 temp_f7; + + temp_f27 = isin(yaw); + temp_f28 = icos(yaw); + temp_f29 = isin(pitch); + temp_f30 = icos(pitch); + temp_f31 = isin(roll); + temp_f1 = icos(roll); + temp_f7 = temp_f27 * temp_f29; + temp_f0 = temp_f28 * temp_f29; + m->right.x = (temp_f28 * temp_f1) + (temp_f31 * temp_f7); + m->right.y = temp_f30 * temp_f31; + m->right.z = (-temp_f27 * temp_f1) + (temp_f31 * temp_f0); + m->up.x = (-temp_f28 * temp_f31) + (temp_f1 * temp_f7); + m->up.y = temp_f30 * temp_f1; + m->up.z = (temp_f27 * temp_f31) + (temp_f1 * temp_f0); + m->at.x = temp_f27 * temp_f30; + m->at.y = -temp_f29; + m->at.z = temp_f28 * temp_f30; + m->flags = 0; +} + +void xMat4x3Toworld(xVec3* o, const xMat4x3* m, const xVec3* v) +{ +} + +/* xMat3x3RotC (xMat3x3 *, float, float, float, float) */ +void xMat3x3RotC(xMat3x3* m, F32 _x, F32 _y, F32 _z, F32 t) +{ + F32 temp_f0; + F32 temp_f0_2; + F32 temp_f1; + F32 temp_f28; + F32 temp_f2; + F32 temp_f3; + F32 temp_f4; + F32 temp_f5; + F32 temp_f6; + F32 temp_f7; + F32 temp_f8; + + if (t == 0.0f) + { + xMat3x3Identity(m); + return; + } + temp_f28 = icos(t); + temp_f1 = isin(t); + temp_f5 = -temp_f1; + temp_f2 = 1.0f - temp_f28; + temp_f0 = temp_f2 * _x; + temp_f8 = temp_f2 * _z; + temp_f4 = temp_f2 * _y; + temp_f3 = _y * temp_f0; + temp_f6 = _x * temp_f8; + temp_f0_2 = (temp_f1 * _z) + temp_f3; + m->right.x = (_x * temp_f0) + temp_f28; + temp_f7 = _z * temp_f4; + m->right.y = temp_f0_2; + m->right.z = (temp_f5 * _y) + temp_f6; + m->up.x = (temp_f5 * _z) + temp_f3; + m->up.y = (_y * temp_f4) + temp_f28; + m->up.z = (temp_f1 * _x) + temp_f7; + m->at.x = (temp_f1 * _y) + temp_f6; + m->at.y = (temp_f5 * _x) + temp_f7; + m->at.z = (_z * temp_f8) + temp_f28; + m->flags = 0; +} + +void xMat3x3RotX(xMat3x3* m, F32 t) +{ + F32 cos = icos(t); + F32 sin = isin(t); + + xVec3Copy(&m->right, &g_X3); + xVec3Init(&m->up, 0.0f, cos, sin); + xVec3Init(&m->at, 0.0f, -sin, cos); + m->flags = 0; +} + +void xMat3x3RotY(xMat3x3* m, F32 t) +{ + F32 temp_f31; + F32 temp_f1; + + temp_f31 = icos(t); + temp_f1 = isin(t); + xVec3Init((xVec3*)m, temp_f31, 0.0f, -temp_f1); + xVec3Copy(&m->up, &g_Y3); + xVec3Init(&m->at, temp_f1, 0.0f, temp_f31); + m->flags = 0; +} + +void xMat3x3RotZ(xMat3x3* m, F32 t) +{ + F32 cos = icos(t); + F32 sin = isin(t); + + xVec3Init(&m->right, cos, sin, 0.0f); + xVec3Init(&m->up, -sin, cos, 0.0f); + xVec3Copy(&m->at, &g_Z3); + m->flags = 0; +} + +void xMat3x3MulRotC(xMat3x3* o, xMat3x3* m, F32 _x, F32 _y, F32 _z, F32 t) +{ +} + +void xMat4x3Identity(xMat4x3* m) +{ +} + +/* xMat3x3Normalize (xMat3x3 *, xMat3x3 const *) */ +void xMat3x3Normalize(xMat3x3* o, const xMat3x3* m) +{ + xVec3Normalize((xVec3*)o, (xVec3*)m); + xVec3Normalize(&o->up, &m->up); + xVec3Normalize(&o->at, &m->at); +} + +void xMat4x3Tolocal(xVec3* o, const xMat4x3* m, const xVec3* v) +{ +} + +/* xMat3x3Tolocal (xVec3 *, xMat3x3 const *, xVec3 const *) */ +void xMat3x3Tolocal(xVec3* o, const xMat3x3* m, const xVec3* v) +{ + F32 temp_f0; + F32 temp_f0_2; + F32 temp_f1; + F32 temp_f1_2; + F32 temp_f29; + F32 temp_f2; + F32 temp_f30; + F32 temp_f31; + F32 temp_f6; + F32 temp_f7; + F32 temp_f8; + F32 temp_f8_2; + + temp_f1 = m->right.x; + temp_f0 = m->right.y; + temp_f2 = m->up.x; + temp_f1_2 = m->up.y; + temp_f8 = m->at.x; + temp_f0_2 = m->at.y; + temp_f6 = m->right.z; + temp_f7 = m->up.z; + temp_f8_2 = m->at.z; + temp_f31 = (temp_f6 * temp_f6) + ((temp_f1 * temp_f1) + (temp_f0 * temp_f0)); + temp_f30 = (temp_f7 * temp_f7) + ((temp_f2 * temp_f2) + (temp_f1_2 * temp_f1_2)); + temp_f29 = (temp_f8_2 * temp_f8_2) + ((temp_f8 * temp_f8) + (temp_f0_2 * temp_f0_2)); + xMat3x3LMulVec(o, m, v); + o->x /= temp_f31; + o->y /= temp_f30; + o->z /= temp_f29; +} + +/* xMat4x3MoveLocalRight (xMat4x3 *, float) */ +void xMat4x3MoveLocalRight(xMat4x3* m, F32 mag) +{ + m->pos.x += m->right.x * mag; + m->pos.y += m->right.y * mag; + m->pos.z += m->right.z * mag; +} + +/* xMat4x3MoveLocalAt (xMat4x3 *, float) */ +void xMat4x3MoveLocalAt(xMat4x3* m, F32 mag) +{ + m->pos.x += m->at.x * mag; + m->pos.y += m->at.y * mag; + m->pos.z += m->at.z * mag; +} + +/* xMat4x3MoveLocalUp (xMat4x3 *, float) */ +void xMat4x3MoveLocalUp(xMat4x3* m, F32 mag) +{ + m->pos.x += m->up.x * mag; + m->pos.y += m->up.y * mag; + m->pos.z += m->up.z * mag; +} + +/* xMat3x3GetEuler (xMat3x3 const *, xVec3 *) */ +void xMat3x3GetEuler(const xMat3x3* m, xVec3* a) +{ + F32 yaw = -xasin(m->at.y); + + F32 roll; + F32 pitch; + + if (yaw < (PI / 2)) + { + if (yaw > -(PI / 2)) + { + pitch = xatan2(m->at.x, m->at.z); + roll = xatan2(m->right.y, m->up.y); + } + else + { + pitch = -xatan2(-m->up.x, m->right.x); + roll = 0.0f; + } + } + else + { + pitch = xatan2(-m->up.x, m->right.x); + roll = 0.0f; + } + + a->x = pitch; + a->y = yaw; + a->z = roll; +} + +/* xMat3x3Euler (xMat3x3 *, xVec3 const *) */ +void xMat3x3Euler(xMat3x3* m, const xVec3* ypr) +{ + xMat3x3Euler(m, ypr->x, ypr->y, ypr->z); +} + +/* xQuatToMat (xQuat const *, xMat3x3 *) */ +void xQuatToMat(const xQuat* q, xMat3x3* m) +{ + F32 tx = (2.0f * q->v.x); + F32 ty = (2.0f * q->v.y); + F32 tz = (2.0f * q->v.z); + F32 tsx = tx * q->s; + F32 tsy = ty * q->s; + F32 tsz = tz * q->s; + F32 txx = tx * q->v.x; + F32 txy = ty * q->v.x; + F32 txz = tz * q->v.x; + F32 tyy = ty * q->v.y; + F32 tyz = tz * q->v.y; + F32 tzz = tz * q->v.z; + + m->right.x = (1.0f - tyy) - tzz; + m->right.y = txy - tsz; + m->right.z = txz + tsy; + + m->up.x = txy + tsz; + m->up.y = (1.0f - tzz) - txx; + m->up.z = tyz - tsx; + + m->at.x = txz - tsy; + m->at.y = tyz + tsx; + m->at.z = (1.0f - txx) - tyy; + + m->flags = 0; +} + +/* xQuatDiff (xQuat *, xQuat const *, xQuat const *) */ +void xQuatDiff(xQuat* o, const xQuat* a, const xQuat* b) +{ + xQuatConj(o, a); + xQuatMul(o, o, b); + if (o->s < 0.0f) + { + xQuatFlip(o, o); + } +} + +F32 xQuatGetAngle(const xQuat* q) +{ + F32 angle; + angle = 5.0; + return angle; +} + +/* xQuatFromMat (xQuat *, xMat3x3 const *) */ +void xQuatFromMat(xQuat* q, const xMat3x3* m) +{ + static S32 nxt[3] = { 1, 2, 0 }; + + F32 temp_f1; + F32 temp_f1_2; + F32 temp_f1_3; + F32 temp_f5; + F32 temp_f6; + S32 temp_r25; + F32 temp_r28; + F32 temp_r30; + F32 temp_r31; + F32 temp_r8; + S32 var_r29; + + temp_f1 = m->at.z + (m->right.x + m->up.y); + if (temp_f1 > 0.0f) + { + temp_f1_2 = xsqrt(1.0f + temp_f1); + q->s = 0.5f * temp_f1_2; + temp_f5 = 0.5f / temp_f1_2; + q->v.x = temp_f5 * (m->at.y - m->up.z); + q->v.y = temp_f5 * (m->right.z - m->at.x); + q->v.z = temp_f5 * (m->up.x - m->right.y); + return; + } + var_r29 = 0; + if (m->up.y > m->right.x) + { + var_r29 = 1; + } + // if (m->at.z > F32 (*(m + (var_r29 * 0x14)))) { + // var_r29 = 2; + // } + // temp_r31 = var_r29 * 4; + // temp_r25 = nxt[var_r29]; + // temp_r30 = temp_r25 * 4; + // temp_r28 = nxt[temp_r25]; + // temp_f1_3 = xsqrt(1.0f + ((*(m + (var_r29 * 0x14)) - *(m + (temp_r25 * 0x14))) - *(m + (temp_r28 * 0x14)))); + // if ((F32) fabs(temp_f1_3) < 0.00001f) { + // xQuatCopy(q, &g_IQ); + // return; + // } + // temp_r8 = temp_r28 * 4; + // *(q + temp_r31) = 0.5f * temp_f1_3; + // temp_f6 = 0.5f / temp_f1_3; + // q->unkC = temp_f6 * (*(m + ((temp_r25 + temp_r8) * 4)) - *(m + ((temp_r28 + temp_r30) * 4))); + // *(q + temp_r30) = temp_f6 * (*(m + ((var_r29 + temp_r30) * 4)) + *(m + ((temp_r25 + temp_r31) * 4))); + // *(q + temp_r8) = temp_f6 * (*(m + ((var_r29 + temp_r8) * 4)) + *(m + ((temp_r28 + temp_r31) * 4))); + // if (q->unkC < 0.0f) { + // xQuatFlip(q, q); + // } +} + +void xQuatFromAxisAngle(xQuat* q, const xVec3* a, F32 t) +{ + F32 t_2; + + if (t == 0.0f) + { + xQuatCopy(q, &g_IQ); + } + else + { + t_2 = isin(t * 0.5f); + q->s = icos((t * 0.5f)); + xVec3SMul(&q->v, a, t_2); + } +} + +void xQuatToAxisAngle(const xQuat* q, xVec3* a, F32* t) +{ + *t = 2.0f * xacos(q->s); + xVec3Normalize(a, &q->v); +} + +/* xQuatSlerp (xQuat *, xQuat const *, xQuat const *, float) */ +void xQuatSlerp(xQuat* q, const xQuat* a, const xQuat* b, F32 t) +{ + xQuat sp28; + xQuat sp18; + F32 sp14; + F32 sp10; + F32 spC; + F32 sp8; + F32 temp_f0; + F32 temp_f1; + F32 temp_f28; + F32 temp_f2; + F32 temp_f3; + F32 temp_f4; + F32 var_f1; + F32 var_f29; + F32 var_f30; + const xQuat* var_r31; + + var_r31 = b; + var_f1 = xQuatDot(a, var_r31); + if (var_f1 < 0.0f) + { + var_f1 = -var_f1; + temp_f4 = -var_r31->v.x; + temp_f0 = var_r31->s; + temp_f3 = -var_r31->v.y; + temp_f2 = -var_r31->v.z; + var_r31 = (xQuat*)&sp8; + sp8 = temp_f4; + spC = temp_f3; + sp10 = temp_f2; + sp14 = -temp_f0; + } + //M2C_ERROR(/* unknown instruction: cror eq, gt, eq */); + if (var_f1 == 0.999f) + { + var_f30 = t; + var_f29 = 1.0f - t; + } + else + { + temp_f1 = xacos(var_f1); + temp_f28 = 1.0f / isin(temp_f1); + var_f29 = temp_f28 * isin((1.0f - t) * temp_f1); + var_f30 = temp_f28 * isin(t * temp_f1); + } + xQuatSMul(&sp28, a, var_f29); + xQuatSMul(&sp18, var_r31, var_f30); + xQuatAdd(q, &sp28, &sp18); + xQuatNormalize(q, q); +} + +/* xQuatMul (xQuat *, xQuat const *, xQuat const *) */ +void xQuatMul(xQuat* o, const xQuat* a, const xQuat* b) +{ + F32 temp_f10; + F32 temp_f11; + F32 temp_f4; + F32 temp_f5; + F32 temp_f6; + F32 temp_f7; + F32 temp_f8; + F32 temp_f9; + + temp_f4 = b->s; + temp_f11 = a->v.x; + temp_f5 = a->v.y; + temp_f8 = b->v.x; + temp_f7 = a->s; + temp_f9 = a->v.z; + temp_f6 = b->v.y; + temp_f10 = b->v.z; + o->v.x = -((temp_f9 * temp_f6) - + ((temp_f5 * temp_f10) + ((temp_f7 * temp_f8) + (temp_f11 * temp_f4)))); + o->v.y = -((temp_f11 * temp_f10) - + ((temp_f9 * temp_f8) + ((temp_f7 * temp_f6) + (temp_f5 * temp_f4)))); + o->v.z = -((temp_f5 * temp_f8) - + ((temp_f11 * temp_f6) + ((temp_f7 * temp_f10) + (temp_f9 * temp_f4)))); + o->s = -((temp_f9 * temp_f10) - + -((temp_f5 * temp_f6) - ((temp_f7 * temp_f4) - (temp_f11 * temp_f8)))); + xQuatNormalize(o, o); +} + +void xQuatConj(xQuat* o, const xQuat* q) +{ +} + +/* xQuatSMul (xQuat *, xQuat const *, float) */ +void xQuatSMul(xQuat* q, const xQuat* a, F32 t) +{ + q->s = a->s * t; + xVec3SMul((xVec3*)q, (xVec3*)a, t); +} + +/* xQuatAdd (xQuat *, xQuat const *, xQuat const *) */ +void xQuatAdd(xQuat* q, const xQuat* a, const xQuat* b) +{ + q->s = a->s + b->s; + xVec3Add((xVec3*)q, (xVec3*)a, (xVec3*)b); +} + +void xMat3x3LookAt(xMat3x3* m, const xVec3* pos, const xVec3* at) +{ +} + +/* xMat3x3LookVec (xMat3x3 *, xVec3 const *) */ +F32 xMat3x3LookVec(xMat3x3* m, const xVec3* at) +{ + F32 temp_f2; + F32 temp_f31; + xVec3* temp_r3; + + temp_f31 = xVec3Normalize(&m->at, at); + temp_r3 = &m->at; + xVec3Inv(temp_r3, temp_r3); + if ((F32)__fabs(1.0f - m->at.y) < 0.00001f) + { + m->right.x = 1.0f; + m->right.y = 0.0f; + m->right.z = 0.0f; + m->up.x = 0.0f; + m->up.y = 0.0f; + m->up.z = 1.0f; + m->at.x = 0.0f; + m->at.y = -1.0f; + m->at.z = 0.0f; + return temp_f31; + } + if ((F32)__fabs(1.0f + m->at.y) < 0.00001f) + { + m->right.x = -1.0f; + m->right.y = 0.0f; + m->right.z = 0.0f; + m->up.x = 0.0f; + m->up.y = 0.0f; + m->up.z = -1.0f; + m->at.x = 0.0f; + m->at.y = 1.0f; + m->at.z = 0.0f; + return temp_f31; + } + if (((F32)__fabs(at->z) < 0.00001f) && ((F32)__fabs(at->x) < 0.00001f)) + { + m->right.x = 1.0f; + m->right.y = 0.0f; + m->right.z = 0.0f; + m->up.x = 0.0f; + m->up.y = 1.0f; + m->up.z = 0.0f; + m->at.x = 0.0f; + m->at.y = 0.0f; + m->at.z = 1.0f; + return 0.0f; + } + m->right.x = m->at.z; + m->right.y = 0.0f; + m->right.z = -m->at.x; + xVec3Normalize((xVec3*)m, (xVec3*)m); + xVec3Cross(&m->up, &m->at, (xVec3*)m); + xVec3Cross((xVec3*)m, &m->up, &m->at); + m->flags = 0; + return temp_f31; +} + +void xBoxInitBoundOBB(xBox* o, const xBox* b, const xMat4x3* m) +{ +} + +void xMat3x3Scale(xMat3x3* m, const xVec3* s) +{ +} + +/* xMat3x3ScaleC (xMat3x3 *, float, float, float) */ +void xMat3x3ScaleC(xMat3x3* m, F32 x, F32 y, F32 z) +{ + xVec3Init((xVec3*)m, x, 0.0f, 0.0f); + xVec3Init(&m->up, 0.0f, y, 0.0f); + xVec3Init(&m->at, 0.0f, 0.0f, z); + m->flags = 0; +} + +void xMat3x3RMulRotY(xMat3x3* o, const xMat3x3* m, F32 t) +{ + F32 cos = icos(t); + F32 sin = isin(t); + if (o == m) + { + F32 temp = o->right.z; + o->right.z = ((cos * o->right.z) - (sin * o->right.x)); + o->right.x = ((cos * o->right.x) + (sin * temp)); + + temp = o->up.z; + o->up.z = ((cos * temp) - (sin * o->up.x)); + o->up.x = ((cos * o->up.x) + (sin * temp)); + + temp = o->at.z; + o->at.z = ((cos * temp) - (sin * o->at.x)); + o->at.x = ((cos * o->at.x) + (sin * temp)); + } + else + { + o->right.x = (cos * m->right.x + (sin * m->right.z)); + o->right.y = m->right.y; + o->right.z = (cos * m->right.z - (sin * m->right.x)); + + o->up.x = (cos * m->up.x + (sin * m->up.z)); + o->up.y = m->up.y; + o->up.z = (cos * m->up.z - (sin * m->up.x)); + + o->at.x = (cos * m->at.x + (sin * m->at.z)); + o->at.y = m->at.y; + o->at.z = (cos * m->at.z - (sin * m->at.x)); + + o->flags = 0; + } +} + +void xMat3x3Transpose(xMat3x3* o, const xMat3x3* m) +{ + F32 temp; + + if (o == m) + { + temp = o->right.y; + o->right.y = o->up.x; + o->up.x = temp; + + temp = o->right.z; + o->right.z = o->at.x; + o->at.x = temp; + + temp = o->up.z; + o->up.z = o->at.y; + o->at.y = temp; + + return; + } + + o->right.x = m->right.x; + o->right.y = m->up.x; + o->right.z = m->at.x; + + o->up.x = m->right.y; + o->up.y = m->up.y; + o->up.z = m->at.y; + + o->at.x = m->right.z; + o->at.y = m->up.z; + o->at.z = m->at.z; + + o->flags = 0; +} + +/* xMat3x3Mul (xMat3x3 *, xMat3x3 const *, xMat3x3 const *) */ +void xMat3x3Mul(xMat3x3* o, const xMat3x3* a, const xMat3x3* b) +{ + xMat3x3 sp8; + F32 temp_f0; + F32 temp_f0_2; + F32 temp_f10; + F32 temp_f10_2; + F32 temp_f12; + F32 temp_f13; + F32 temp_f1; + F32 temp_f25; + F32 temp_f26; + F32 temp_f27; + F32 temp_f29; + F32 temp_f2; + F32 temp_f30; + F32 temp_f3; + F32 temp_f4; + F32 temp_f4_2; + F32 temp_f5; + F32 temp_f9; + U8 var_r0; + xMat3x3* var_r6; + + var_r0 = 0; + if ((o == a) || (o == b)) + { + var_r0 = 1; + } + if (var_r0 != 0) + { + var_r6 = &sp8; + } + else + { + var_r6 = o; + } + temp_f4 = a->right.y; + temp_f3 = b->up.x; + temp_f2 = b->up.y; + temp_f1 = a->up.y; + temp_f10 = b->up.z; + temp_f0 = a->at.y; + temp_f26 = a->right.x; + temp_f27 = b->right.x; + temp_f30 = b->right.y; + temp_f9 = a->up.x; + temp_f12 = b->right.z; + temp_f4_2 = a->at.x; + temp_f25 = a->right.z; + temp_f0_2 = b->at.x; + temp_f29 = b->at.y; + temp_f13 = b->at.z; + temp_f10_2 = a->up.z; + temp_f5 = a->at.z; + var_r6->right.x = (temp_f25 * temp_f0_2) + ((temp_f26 * temp_f27) + (temp_f4 * temp_f3)); + var_r6->flags = 0; + var_r6->right.y = (temp_f25 * temp_f29) + ((temp_f26 * temp_f30) + (temp_f4 * temp_f2)); + var_r6->right.z = (temp_f25 * temp_f13) + ((temp_f26 * temp_f12) + (temp_f4 * temp_f10)); + var_r6->up.x = (temp_f10_2 * temp_f0_2) + ((temp_f9 * temp_f27) + (temp_f1 * temp_f3)); + var_r6->up.y = (temp_f10_2 * temp_f29) + ((temp_f9 * temp_f30) + (temp_f1 * temp_f2)); + var_r6->up.z = (temp_f10_2 * temp_f13) + ((temp_f9 * temp_f12) + (temp_f1 * temp_f10)); + var_r6->at.x = (temp_f5 * temp_f0_2) + ((temp_f4_2 * temp_f27) + (temp_f0 * temp_f3)); + var_r6->at.y = (temp_f5 * temp_f29) + ((temp_f4_2 * temp_f30) + (temp_f0 * temp_f2)); + var_r6->at.z = (temp_f5 * temp_f13) + ((temp_f4_2 * temp_f12) + (temp_f0 * temp_f10)); + // if (var_r0 != 0) { + // xMat3x3Copy__FP7xMat3x3PC7xMat3x3(o, var_r6); + // } +} + +void xMat3x3SMul(xMat3x3*, const xMat3x3*, F32) +{ +} + +void xBoxFromLine(xBox& box, const xLine3& line) +{ +} + +void xBoxFromRay(xBox& box, const xRay3& ray) +{ +} + +void xBoxUnion(xBox& a, const xBox& b, const xBox& c) +{ + a.upper.x = MAX(b.upper.x, c.upper.x); + a.upper.y = MAX(b.upper.y, c.upper.y); + a.upper.z = MAX(b.upper.z, c.upper.z); + + a.lower.x = MIN(b.lower.x, c.lower.x); + a.lower.y = MIN(b.lower.y, c.lower.y); + a.lower.z = MIN(b.lower.z, c.lower.z); +} + +void xMat3x3LMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) +{ +} diff --git a/src/SB/Core/x/xMath3.h b/src/SB/Core/x/xMath3.h new file mode 100644 index 0000000..1e2b2ed --- /dev/null +++ b/src/SB/Core/x/xMath3.h @@ -0,0 +1,163 @@ +#ifndef XMATH3_H +#define XMATH3_H + +#include "xMath.h" + +#include "xVec3.h" +#include "xVec3Inlines.h" + +// Size: 0x30 +struct xMat3x3 +{ + xVec3 right; + S32 flags; + xVec3 up; + U32 pad1; + xVec3 at; + U32 pad2; +}; + +// Size: 0x40 +struct xMat4x3 : xMat3x3 +{ + xVec3 pos; + U32 pad3; +}; + +struct xSphere +{ + xVec3 center; + F32 r; +}; + +// Size: 0x18 +struct xBox +{ + xVec3 upper; + xVec3 lower; +}; + +struct xBBox +{ + xVec3 center; + xBox box; +}; + +struct xCylinder +{ + xVec3 center; + F32 r; + F32 h; +}; + +struct xQuat +{ + xVec3 v; + F32 s; +}; + +struct xVec4 +{ + F32 x; + F32 y; + F32 z; + F32 w; +}; + +struct xRot +{ + xVec3 axis; + F32 angle; +}; + +struct xLine3 +{ + xVec3 p1; + xVec3 p2; +}; + +struct xRay3; + +extern const xQuat g_IQ; +extern const xVec3 g_O3; +extern xVec3 g_X3; +extern xVec3 g_Y3; +extern xVec3 g_Z3; +extern xMat4x3 g_I3; +extern xVec3 g_Onez; + +void xMat3x3Copy(xMat3x3* o, const xMat3x3* m); // TODO: These functions should be inline +void xMat4x3Copy(xMat4x3* o, const xMat4x3* m); +void xMat4x3Mul(xMat4x3* o, const xMat4x3* a, const xMat4x3* b); +void xMat3x3Euler(xMat3x3* m, F32 yaw, F32 pitch, F32 roll); +void xMat4x3Toworld(xVec3* o, const xMat4x3* m, const xVec3* v); +void xMat3x3RotC(xMat3x3* m, F32 _x, F32 _y, F32 _z, F32 t); +void xMat3x3RotY(xMat3x3* m, F32 t); +void xMat3x3MulRotC(xMat3x3* o, xMat3x3* m, F32 _x, F32 _y, F32 _z, F32 t); +void xMat4x3Identity(xMat4x3* m); +void xMat3x3Normalize(xMat3x3* o, const xMat3x3* m); +void xMat4x3Tolocal(xVec3* o, const xMat4x3* m, const xVec3* v); +void xMat3x3Tolocal(xVec3* o, const xMat3x3* m, const xVec3* v); +void xMat4x3MoveLocalRight(xMat4x3* m, F32 mag); +void xMat4x3MoveLocalAt(xMat4x3* m, F32 mag); +void xMat4x3MoveLocalUp(xMat4x3* m, F32 mag); +void xMat4x3OrthoInv(xMat4x3* o, const xMat4x3* m); +void xMat3x3GetEuler(const xMat3x3* m, xVec3* a); +void xMat3x3Euler(xMat3x3* m, const xVec3* ypr); +void xQuatToMat(const xQuat* q, xMat3x3* m); +void xQuatDiff(xQuat* o, const xQuat* a, const xQuat* b); +F32 xQuatGetAngle(const xQuat* q); +void xQuatFromMat(xQuat* q, const xMat3x3* m); +void xQuatSlerp(xQuat* q, const xQuat* a, const xQuat* b, F32 t); +void xQuatConj(xQuat* o, const xQuat* q); +void xQuatCopy(xQuat*, const xQuat*); +void xMat3x3LookAt(xMat3x3* m, const xVec3* pos, const xVec3* at); +F32 xMat3x3LookVec(xMat3x3* m, const xVec3* at); +void xBoxInitBoundOBB(xBox* o, const xBox* b, const xMat4x3* m); +void xBoxUnion(xBox& a, const xBox& b, const xBox& c); +void xMat3x3Scale(xMat3x3* m, const xVec3* s); +void xMat3x3ScaleC(xMat3x3* m, F32 x, F32 y, F32 z); +void xMat3x3RMulRotY(xMat3x3* o, const xMat3x3* m, F32 t); +void xMat3x3Mul(xMat3x3* o, const xMat3x3* a, const xMat3x3* b); +void xMat3x3SMul(xMat3x3*, const xMat3x3*, F32); +void xBoxFromLine(xBox& box, const xLine3& line); +void xBoxFromRay(xBox& box, const xRay3& ray); +void xMat3x3Identity(xMat3x3* matrix); // TODO: These functions should be inline +S32 xPointInBox(const xBox* b, const xVec3* p); +void xMat3x3LMulVec(xVec3* o, const xMat3x3* m, const xVec3* v); + +void xQuatMul(xQuat* o, const xQuat* a, const xQuat* b); +void xQuatFlip(xQuat* o1, xQuat* o2); +void xQuatNormalize(xQuat* arg01, xQuat* arg02); + +void xQuatSMul(xQuat* q, const xQuat* a, F32 t); +void xQuatAdd(xQuat* q, const xQuat* a, const xQuat* b); +F32 xQuatDot(const xQuat* a, const xQuat* b); + +F32 fabs(F32 x); // Unsure where this should come from. + +inline void xRotCopy(xRot* o, const xRot* r) +{ + o->axis.x = r->axis.x; + o->axis.y = r->axis.y; + o->axis.z = r->axis.z; + o->angle = r->angle; +} + +static inline void xMat3x3RMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) +{ + F32 x = m->right.x * v->x + m->up.x * v->y + m->at.x * v->z; + F32 y = m->right.y * v->x + m->up.y * v->y + m->at.y * v->z; + F32 z = m->right.z * v->x + m->up.z * v->y + m->at.z * v->z; + + o->x = x; + o->y = y; + o->z = z; +} + +inline void xMat3x3Rot(xMat3x3* m, const xVec3* a, F32 t) +{ + xMat3x3RotC(m, a->x, a->y, a->z, t); +} + +#endif diff --git a/src/SB/Core/x/xMathInlines.h b/src/SB/Core/x/xMathInlines.h new file mode 100644 index 0000000..4aec695 --- /dev/null +++ b/src/SB/Core/x/xMathInlines.h @@ -0,0 +1,18 @@ +#ifndef XMATHINLINES_H +#define XMATHINLINES_H + +#include + +F32 xsqrt(F32 x); +F32 xfmod(F32 a, F32 b); +F32 xatan2(F32 y, F32 x); +F32 xasin(F32 x); +F32 xacos(F32 x); +F32 xexp(F32 x); +F32 xpow(F32 x, F32 y); + +F32 SQ(F32 x); + +void xsqrtfast(F32& out, F32 x); + +#endif diff --git a/src/SB/Core/x/xMem.h b/src/SB/Core/x/xMem.h deleted file mode 100644 index 9ae262e..0000000 --- a/src/SB/Core/x/xMem.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef XMEM_H -#define XMEM_H - -#include -#include -#include -#include - -struct xBase; - -struct RyzMemGrow -{ - S32 flg_grow; - S32 amt; - signed char* ptr; - xBase* user; - S32 amt_last; - signed char* ptr_last; - xBase* user_last; -}; - -struct RyzMemData -{ - void __dl(); - void* __nw(U32 amt, RyzMemGrow* growCtxt); -}; - -struct xFactoryInst : RyzMemData -{ - S32 itemType; - xFactoryInst* nextprod; - xFactoryInst* prevprod; -}; - -struct xMemPool -{ - void* FreeList; - U16 NextOffset; - U16 Flags; - void* UsedList; - void (*InitCB)(xMemPool*, void*); - void* Buffer; - U16 Size; - U16 NumRealloc; - U32 Total; -}; - -#endif diff --git a/src/SB/Core/x/xMemMgr.cpp b/src/SB/Core/x/xMemMgr.cpp new file mode 100644 index 0000000..f9cae4e --- /dev/null +++ b/src/SB/Core/x/xMemMgr.cpp @@ -0,0 +1,395 @@ +#include "xMemMgr.h" + +#include +#include +#include + +#include "iSystem.h" +#include "iMemMgr.h" + +extern xMemInfo_tag gMemInfo; +extern xMemHeap_tag gxHeap[3]; +extern void (*sMemBaseNotifyFunc)(); + +void xMemDebug_SoakLog(const char*) +{ +} + +// The instructions putting 0/1/2 into registers happen in the wrong order. +void xMemInit() +{ + iMemInit(); + xMemInitHeap(&gxHeap[0], gMemInfo.DRAM.addr, gMemInfo.DRAM.size, 0x8826); + xMemInitHeap(&gxHeap[1], gMemInfo.DRAM.addr + gMemInfo.DRAM.size, gMemInfo.DRAM.size, 0x8925); + xMemInitHeap(&gxHeap[2], gMemInfo.DRAM.addr + gMemInfo.DRAM.size, gMemInfo.DRAM.size, 0x892A); + gxHeap[0].opp_heap[0] = 1; + gxHeap[0].opp_heap[1] = 2; + gxHeap[1].opp_heap[0] = 0; + gxHeap[1].opp_heap[1] = 2; + gxHeap[2].opp_heap[0] = 0; + gxHeap[2].opp_heap[1] = 1; + gActiveHeap = 0; +} + +void xMemExit() +{ + iMemExit(); +} + +void xMemInitHeap(xMemHeap_tag* heap, U32 base, U32 size, U32 flags) +{ + U32 old_base = base; + S32 align = 1 << ((flags >> 9) & 0x1F); + if (flags & 0x100) + { + base = base & -align; + size -= (old_base - base); + } + else + { + base = (old_base + align - 1) & -align; + size -= (base - old_base); + } + + heap->state_idx = 0; + heap->hard_base = base; + heap->size = size; + heap->flags = flags; + heap->lastblk = NULL; + xHeapState_tag* sp = &heap->state[heap->state_idx]; + sp->curr = base; + sp->blk_ct = 0; + + if (flags & 0x10000) + { + heap->max_blks = (1 << ((flags >> 14) & 0x1)); + heap->blk = (xMemBlock_tag*)malloc(heap->max_blks * sizeof(xMemBlock_tag)); + memset(heap->blk, 0, heap->max_blks * sizeof(xMemBlock_tag)); + } + else + { + heap->max_blks = -1; + heap->blk = 0; + } + heap->opp_heap[0] = -1; + heap->opp_heap[1] = -1; +} + +#if 0 +// Not particularly close. This function is a nightmare, it has so many +// variables to untangle. +void xMemGetBlockInfo(xMemHeap_tag* heap, U32 size, S32 align, xMemBlkInfo_tag* info) +{ + S32 hdr = 1; + xHeapState_tag* sp = &heap->state[heap->state_idx]; + if (heap->flags & 0x100) + { + hdr = -1; + } + + S32 remainder = 0xc & -(heap->flags & 0x10000); + S32 pre; + S32 post; + S32 block; + S32 r8; + if (heap->flags & 0x100) + { + block = -remainder; + pre = -(remainder + size + ((sp->curr - remainder - size) & (align - 1))); + post = pre + size; + r8 = -pre; + } + else + { + block = 0; + if (r8 = (align - 1) & (sp->curr + remainder)) + { + r8 = align; + } + pre = (align + remainder) - r8; + post = pre + size; + r8 = post; + } + + S32 total = (r8 + 3) & 0xFFFFFFFE; + if (heap->flags & 0x10000) + { + info->header = &heap->blk[sp->curr]; + } + else + { + info->header = (xMemBlock_tag*)(sp->curr + block); + } + info->pre = sp->curr + pre; + info->block = sp->curr + pre; + info->post = sp->curr + post; + info->curr = sp->curr + hdr * total; + info->waste = total - (remainder + size); + info->total = total; +} +#endif + +#if 0 +// Not particularly close. Not 100% confident that I understand what's going on, +// in particular the bit that goes: +// (heap->lastblk->size + size) - heap->lastblk->size; +// It really seems like the assembly code is adding and then immediately +// subtracting again, and I don't see why it would want to do that. +#undef xMemGrowAlloc +void* xMemGrowAlloc(U32 heapID, U32 size) +{ + size = (size + 3) & 0xFFFFFFFC; + xMemHeap_tag* heap = &gxHeap[heapID]; + xHeapState_tag* sp = &heap->state[heap->state_idx]; + // pad size to multiple of 4 bytes + xMemBlock_tag* hdr = heap->lastblk; + U32 anotherVar = (heap->lastblk->size + size) - heap->lastblk->size; + if (sp->used + anotherVar > heap->size) + { + return 0; + } + else + { + void* memptr; + if (heap->flags & 0x100) + { + memptr = (void*)(hdr->addr - size); + hdr->addr = (U32)memptr; + sp->curr -= anotherVar; + } + else + { + sp->curr += anotherVar; + memptr = (void*)(hdr->addr + heap->lastblk->size); + } + sp->used += anotherVar; + hdr->size += size; + memset(memptr, 0, size); + return memptr; + } +} +#endif + +// +void* xMemAlloc(U32 heapID, U32 size, S32 align) +{ + // This variable not in DWARF + S32 true_align; + + xMemHeap_tag* heap; + xMemBlock_tag* hdr; + xHeapState_tag* sp; + + heap = &gxHeap[heapID]; + sp = &heap->state[heap->state_idx]; + + true_align = 1 << (heap->flags >> 9 & 0x1f); + if (align > true_align) + { + true_align = align; + } + + if (size == 0) + { + return (void*)0xDEADBEEF; + } + + xMemBlkInfo_tag info; + U32 total = xMemGetBlockInfo(heap, size, true_align, &info); + hdr = info.header; + + if (sp->used + total > heap->size) + { + return NULL; + } + + sp->curr = info.curr; + sp->blk_ct += 1; + if (heap->flags & 0x10000) + { + return NULL; + } + + hdr->addr = info.block; + hdr->size = size; + hdr->align = true_align; + sp->used += total; + sp->wasted += info.waste; + + memset((void*)hdr->addr, 0, size); + heap->lastblk = hdr; + return (void*)hdr->addr; +} + +void* xMemPushTemp(U32 size) +{ + return RwMalloc(size); +} + +void xMemPopTemp(void* memory) +{ + RwFree(memory); +} + +S32 xMemPushBase(U32 heapID) +{ + xMemHeap_tag* heap = &gxHeap[heapID]; + + heap->state_idx += 1; + xHeapState_tag* sp = &heap->state[heap->state_idx]; + *sp = *(sp - 1); + + if (sMemBaseNotifyFunc != NULL) + { + sMemBaseNotifyFunc(); + } + return heap->state_idx - 1; +} + +S32 xMemPushBase() +{ + return xMemPushBase(gActiveHeap); +} + +// Load/Store swap of sMemBaseNotifyFunc and state_idx +S32 xMemPopBase(U32 heapID, S32 depth) +{ + xMemHeap_tag* heap = &gxHeap[heapID]; + if (depth < 0) + { + depth = heap->state_idx + depth; + } + + heap->state_idx = depth; + if (sMemBaseNotifyFunc != NULL) + { + sMemBaseNotifyFunc(); + } + + return heap->state_idx; +} + +S32 xMemPopBase(S32 depth) +{ + return xMemPopBase(gActiveHeap, depth); +} + +S32 xMemGetBase(U32 heapID) +{ + return gxHeap[heapID].state_idx; +} + +void xMemRegisterBaseNotifyFunc(void (*func)()) +{ + sMemBaseNotifyFunc = func; +} + +S32 xMemGetBase() +{ + return xMemGetBase(gActiveHeap); +} + +void xMemPoolAddElements(xMemPool* pool, void* buffer, U32 count) +{ + S32 i; + void* curr; + void (*initCB)(xMemPool*, void*); + U32 next; + U32 size; + + initCB = pool->InitCB; + next = pool->NextOffset; + size = pool->Size; + + curr = buffer; + for (i = 0; i < (S32)count - 1; i++) + { + *(void**)((U32)curr + next) = (void*)((U32)curr + size); + if (initCB != NULL) + { + initCB(pool, curr); + } + curr = (void*)((U32)curr + size); + } + + *(void**)((U32)curr + next) = pool->FreeList; + if (initCB != NULL) + { + initCB(pool, curr); + } + pool->FreeList = buffer; + pool->Total += count; +} + +void xMemPoolSetup(xMemPool* pool, void* buffer, U32 nextOffset, U32 flags, xMemPoolInitCB initCB, + U32 size, U32 count, U32 numRealloc) +{ + pool->FreeList = NULL; + pool->NextOffset = nextOffset; + pool->Flags = flags; + pool->UsedList = NULL; + pool->InitCB = initCB; + pool->Buffer = buffer; + pool->Size = size; + pool->NumRealloc = numRealloc; + pool->Total = 0; + xMemPoolAddElements(pool, buffer, count); +} + +void* xMemPoolAlloc(xMemPool* pool) +{ + void* retval = pool->FreeList; + U32 next = pool->NextOffset; + U32 flags = pool->Flags; + + if (retval == NULL) + { + xMemPoolAddElements(pool, xMemAlloc(gActiveHeap, pool->NumRealloc * pool->Size, 0), + pool->NumRealloc); + retval = pool->FreeList; + } + + pool->FreeList = *(void**)((U32)retval + next); + if (flags & 1) + { + *(void**)((U32)retval + next) = pool->UsedList; + pool->UsedList = retval; + } + + return retval; +} + +void xMemPoolFree(xMemPool* pool, void* data) +{ + void** prev; + void* freeList; + U32 next; + void* curr; + + if (data == NULL) + { + return; + } + + freeList = pool->FreeList; + next = pool->NextOffset; + if (pool->Flags & 1) + { + prev = &pool->UsedList; + curr = pool->UsedList; + + while (curr != NULL && curr != data) + { + prev = (void**)((U32)curr + next); + curr = *prev; + } + + if (curr != NULL) + { + *prev = *(void**)((U32)curr + next); + } + } + + *(void**)((U32)data + next) = freeList; + pool->FreeList = data; +} diff --git a/src/SB/Core/x/xMemMgr.h b/src/SB/Core/x/xMemMgr.h new file mode 100644 index 0000000..0e03b48 --- /dev/null +++ b/src/SB/Core/x/xMemMgr.h @@ -0,0 +1,114 @@ +#ifndef XMEMMGR_H +#define XMEMMGR_H + +#include + +// Size: 0x10 +struct xHeapState_tag +{ + U32 curr; + U16 blk_ct; + U16 pad; + U32 used; + U32 wasted; +}; + +struct xMemBlock_tag +{ + U32 addr; + U32 size; + S32 align; +}; + +struct xMemBlkInfo_tag +{ + xMemBlock_tag* header; + U32 pre; + U32 block; + U32 post; + U32 curr; + U32 waste; + U32 total; +}; + +struct xMemHeap_tag +{ + U32 flags; + U32 hard_base; + U32 size; + S16 opp_heap[2]; + + // Offset: 0x10 + xHeapState_tag state[12]; + + // Offset: 0xD0 + U16 state_idx; + U16 max_blks; + xMemBlock_tag* blk; + xMemBlock_tag* lastblk; +}; + +struct xMemArea_tag +{ + U32 addr; + U32 size; + U32 flags; +}; + +struct xMemInfo_tag +{ + xMemArea_tag system; + + // Offset: 0xC + xMemArea_tag stack; + + // Offset: 0x18 + xMemArea_tag DRAM; + + // Offset: 0x24 + xMemArea_tag SRAM; +}; + +struct xMemPool; +typedef void (*xMemPoolInitCB)(xMemPool*, void*); +struct xMemPool +{ + void* FreeList; + U16 NextOffset; + U16 Flags; + void* UsedList; + xMemPoolInitCB InitCB; + void* Buffer; + U16 Size; + U16 NumRealloc; + U32 Total; +}; + +extern U32 gActiveHeap; + +void xMemInit(); +void xMemExit(); +void xMemInitHeap(xMemHeap_tag* heap, U32 base, U32 size, U32 flags); +U32 xMemGetBlockInfo(xMemHeap_tag* heap, U32 size, S32 align, xMemBlkInfo_tag* info); +void* xMemGrowAlloc(U32 heapID, U32 size); +void* xMemAlloc(U32 heapID, U32 size, S32 align); +void* xMemPushTemp(U32 size); +void xMemPopTemp(void* memory); +S32 xMemPushBase(U32 heapID); +S32 xMemPushBase(); +S32 xMemPopBase(U32 heapID, S32 depth); +S32 xMemPopBase(S32 depth); +S32 xMemGetBase(U32 heapID); +void xMemRegisterBaseNotifyFunc(void (*func)()); +S32 xMemGetBase(); +void xMemPoolAddElements(xMemPool* pool, void* buffer, U32 count); +void xMemPoolSetup(xMemPool* pool, void* buffer, U32 nextOffset, U32 flags, + xMemPoolInitCB initCB, U32 size, U32 count, U32 numRealloc); +void* xMemPoolAlloc(xMemPool* pool); +void xMemPoolFree(xMemPool* pool, void* data); + +#define xMemGrowAllocSize(size) xMemGrowAlloc(gActiveHeap, size) +#define xMemAllocSize(size) xMemAlloc(gActiveHeap, size, 0) +#define xMemAllocSizeAlign(size, align) xMemAlloc(gActiveHeap, size, align) + +#endif diff --git a/src/SB/Core/x/xMgr.h b/src/SB/Core/x/xMgr.h new file mode 100644 index 0000000..4c1b6ae --- /dev/null +++ b/src/SB/Core/x/xMgr.h @@ -0,0 +1,8 @@ +#ifndef XMGR_H +#define XMGR_H + +struct xMgr +{ +}; + +#endif \ No newline at end of file diff --git a/src/SB/Core/x/xModel.cpp b/src/SB/Core/x/xModel.cpp new file mode 100644 index 0000000..4991a48 --- /dev/null +++ b/src/SB/Core/x/xModel.cpp @@ -0,0 +1,229 @@ +#include "iModel.h" +#include "xModel.h" + +#include + +static xModelPool* sxModelPoolList; +static RwCamera* subcamera; +S32 xModelBucketEnabled; + +static RwCamera* CameraCreate(int a, int b, int c); +void CameraDestroy(RwCamera* cam); + +U32 xModelGetPipeFlags(RpAtomic* model) +{ + for (int i = 0; i < xModelLookupCount; i++) + { + if (xModelLookupList[i].model == model) + { + return xModelLookupList[i].PipeFlags; + } + } + return NULL; +} + +// Equivalent (regalloc) +void xModelInit() +{ + iModelInit(); + sxModelPoolList = NULL; + if (subcamera == NULL) + { + subcamera = CameraCreate(0,0,1); + } + xModelPipeNumTables = 0; +} + +static xModelInstance* FindChild(xModelInstance* model) +{ + xModelInstance* child = model->Next; + while (child != NULL) + { + if (child->Parent == model) + { + return child; + } + child = child->Next; + } + return NULL; +} + +void xModelInstanceFree(xModelInstance* model) +{ + xModelInstance* prev; + xModelInstance* curr; + + while (prev = FindChild(model), prev != NULL) + { + xModelInstanceFree(prev); + } + prev = model->Parent; + if (prev != NULL) + { + for (curr = prev->Next; (curr != NULL) && (curr != model); curr = curr->Next) + { + prev = curr; + } + prev->Next = curr->Next; + } + if (model->Anim != NULL) + { + xAnimPoolFree(model->Anim); + model->Anim = NULL; + } + if (model->Pool != NULL) + { + model->Next = model->Pool->List; + model->Pool->List = model; + } +} + +void xModelInstanceAttach(xModelInstance* inst, xModelInstance* parent) +{ + xModelInstance* curr = parent; + while (curr->Next != NULL) + { + curr = curr->Next; + } + curr->Next = inst; + inst->Parent = parent; + if ((inst->Flags & 0x2000) != 0) + { + inst->Mat = parent->Mat; + } +} + +void xModelUpdate(xModelInstance* modelInst, F32 timeDelta) +{ + for (; modelInst != NULL; modelInst = modelInst->Next) + { + if (modelInst->Anim != NULL) + { + if ((modelInst->Flags & 4) != 0) + { + if ((modelInst->Flags & 0x100) != 0) + { + xAnimPlayChooseTransition(modelInst->Anim); + } + xAnimPlayUpdate(modelInst->Anim, timeDelta); + } + } + } +} + +void xModelEvalSingle(xModelInstance* model); + +void xModelEval(xModelInstance* model) +{ + while (model != NULL) + { + xModelEvalSingle(model); + model = model->Next; + } +} + +void xModelRender(xModelInstance* model) +{ + while (model != NULL) + { + if (xModelBucketEnabled) + { + xModelBucket_Add(model); + } + else + { + xModelRenderSingle(model); + } + model = model->Next; + } +} + +static RwCamera* CameraCreate(int a, int b, int c) +{ + RwCamera* camera = RwCameraCreate(); + if (camera != NULL) + { + _rwObjectHasFrameSetFrame(camera, RwFrameCreate()); + camera->frameBuffer = RwRasterCreate(a, b, 0, 2); + if (c != 0) + { + camera->zBuffer = RwRasterCreate(a, b, 0, 1); + } + if (camera->object.object.parent != NULL) + { + if (camera->frameBuffer != NULL) + { + if ((c == 0) || (camera->zBuffer != NULL)) + { + return camera; + } + } + } + } + CameraDestroy(camera); + return NULL; +} + +void CameraDestroy(RwCamera* cam) +{ + RwFrame* frame; + if (cam != NULL) + { + _rwFrameSyncDirty(); + frame = (RwFrame*)cam->object.object.parent; + if (frame != NULL) + { + _rwObjectHasFrameSetFrame(cam, 0); + RwFrameDestroy(frame); + } + if (cam->frameBuffer != NULL) + { + RwRasterDestroy(cam->frameBuffer); + cam->frameBuffer = NULL; + } + if (cam->zBuffer != NULL) + { + RwRasterDestroy(cam->zBuffer); + cam->zBuffer = NULL; + } + RwCameraDestroy(cam); + } +} + +void xModelSetMaterialAlpha(xModelInstance* model, U8 alpha) +{ + iModelSetMaterialAlpha(model->Data, alpha); +} + +void xModelMaterialMul(xModelInstance* model, F32 rm, F32 gm, F32 bm) +{ + iModelMaterialMul(model->Data, rm, gm, bm); +} + +void xModelResetMaterial(xModelInstance* model) +{ + iModelResetMaterial(model->Data); +} + +void xModel_SceneEnter(RpWorld* world) +{ + RpWorldAddCamera(world, subcamera); +} + +void xModel_SceneExit(RpWorld* world) +{ + RpWorldRemoveCamera(world, subcamera); +} + +void xModelAnimCollStart(xModelInstance& model) +{ + model.Flags = (model.Flags & ~0x1000) | 0x800; + if (model.anim_coll.verts == NULL) + { + U32 size = iModelVertCount(model.Data); + if (size != 0) + { + model.anim_coll.verts = (xVec3*)xMemAlloc(gActiveHeap, size * sizeof(xVec3), 0); + } + } +} \ No newline at end of file diff --git a/src/SB/Core/x/xModel.h b/src/SB/Core/x/xModel.h index f02d33f..9ff8f9d 100644 --- a/src/SB/Core/x/xModel.h +++ b/src/SB/Core/x/xModel.h @@ -1,225 +1,17 @@ #ifndef XMODEL_H #define XMODEL_H -#include -#include #include #include -#include "xMath.h" -#include "xSound.h" - -struct xLinkAsset -{ - U16 srcEvent; - U16 dstEvent; - U32 dstAssetID; - F32 param[4]; - U32 paramWidgetAssetID; - U32 chkAssetID; -}; - -struct xBase -{ - U32 id; - U8 baseType; - U8 linkCount; - U16 baseFlags; - xLinkAsset* link; - void (*eventFunc)(xBase*, xBase*, U32, F32*, xBase*, U32); -}; - -struct xBaseAsset -{ - U32 id; - U8 baseType; - U8 linkCount; - U16 baseFlags; -}; - -struct xMovePointAsset : xBaseAsset -{ - xVec3 pos; - U16 wt; - U8 on; - U8 bezIndex; - U8 flg_props; - U8 pad; - U16 numPoints; - F32 delay; - F32 zoneRadius; - F32 arenaRadius; -}; - -struct xMovePoint : xBase -{ - xMovePointAsset* asset; - xVec3* pos; - xMovePoint** nodes; - xMovePoint* prev; - U32 node_wt_sum; - U8 on; - U8 pad[3]; - F32 delay; - xSpline3* spl; -}; - -struct xAnimPhysicsData -{ - xVec3* tranTable; - F32* yawTable; - S32 tranCount; -}; - -struct xAnimFile -{ - xAnimFile* Next; - unsigned char* Name; - U32 ID; - U32 FileFlags; - F32 Duration; - F32 TimeOffset; - U16 BoneCount; - U8 NumAnims[2]; - void** RawData; - xAnimPhysicsData* PhysicsData; -}; - -struct xAnimSingle; -struct xAnimActiveEffect; - -struct xAnimEffect -{ - xAnimEffect* Next; - U16 Flags; - U16 Probability; - F32 StartTime; - F32 EndTime; - U32 (*Callback)(U32, xAnimActiveEffect*, xAnimSingle*, void*); -}; - -struct xAnimActiveEffect -{ - xAnimEffect* Effect; - union - { - U32 Handle; - iSndHandle SndHandle; - }; -}; - -struct xAnimState; - -struct xAnimTransition -{ - xAnimTransition* Next; - xAnimState* Dest; - U32 (*Conditional)(xAnimTransition*, xAnimSingle*, void*); - U32 (*Callback)(xAnimTransition*, xAnimSingle*, void*); - U32 Flags; - U32 UserFlags; - F32 SrcTime; - F32 DestTime; - U16 Priority; - U16 QueuePriority; - F32 BlendRecip; - U16* BlendOffset; -}; - -struct xAnimTransitionList -{ - xAnimTransitionList* Next; - xAnimTransition* T; -}; - -struct xAnimMultiFileBase -{ - U32 Count; -}; - -struct xAnimMultiFileEntry -{ - U32 ID; - xAnimFile* File; -}; - -struct xAnimMultiFile : xAnimMultiFileBase -{ - xAnimMultiFileEntry Files[1]; -}; - -struct xAnimPlay; - -struct xAnimState -{ - xAnimState* Next; - unsigned char* Name; - U32 ID; - U32 Flags; - U32 UserFlags; - F32 Speed; - xAnimFile* Data; - xAnimEffect* Effects; - xAnimTransitionList* Default; - xAnimTransitionList* List; - F32* BoneBlend; - F32* TimeSnap; - F32 FadeRecip; - U16* FadeOffset; - void* CallbackData; - xAnimMultiFile* MultiFile; - void (*BeforeEnter)(xAnimPlay*, xAnimState*, void*); - void (*StateCallback)(xAnimState*, xAnimSingle*, void*); - void (*BeforeAnimMatrices)(xAnimPlay*, xQuat*, xVec3*, S32); -}; - -struct xAnimSingle -{ - U32 SingleFlags; - xAnimState* State; - F32 Time; - F32 CurrentSpeed; - F32 BilinearLerp[2]; - xAnimEffect* Effect; - U32 ActiveCount; - F32 LastTime; - xAnimActiveEffect* ActiveList; - xAnimPlay* Play; - xAnimTransition* Sync; - xAnimTransition* Tran; - xAnimSingle* Blend; - F32 BlendFactor; - xVec3 PhysDisp; - F32 YawDisp; - U32 pad[1]; -}; - -struct xAnimTable -{ - signed char* Name; - xAnimTransition* TransitionList; - xAnimState* StateList; - U32 AnimIndex; - U32 MorphIndex; - U32 UserFlags; -}; -struct xModelAssetParam -{ - U32 HashID; - U8 WordLength; - U8 String[3]; -}; - -struct xModelAssetInfo -{ - U32 Magic; - U32 NumModelInst; - U32 AnimTableID; - U32 CombatID; - U32 BrainID; -}; +#include "xAnim.h" +#include "xLightKit.h" +#include "xSurface.h" +#include "xMath3.h" +#include "xMath2.h" +#include "xModelBucket.h" -struct xModelInstance; +struct xModelBucket; struct xModelPool { @@ -228,100 +20,55 @@ struct xModelPool xModelInstance* List; }; -struct xModelPipe -{ - U32 Flags; - U8 Layer; - U8 AlphaDiscard; - U16 PipePad; -}; - -struct xEnt; - -struct xSurface : xBase -{ - U32 idx; - U32 type; - union - { - U32 mat_idx; - xEnt* ent; - void* obj; - }; - F32 friction; - U8 state; - U8 pad[3]; - void* moprops; -}; - -struct xModelBucket -{ - RpAtomic* Data; - RpAtomic* OriginalData; - union - { - xModelInstance* List; - xModelBucket** BackRef; - }; - S32 ClipFlags; - xModelPipe Pipe; -}; - -struct xLightKitLight -{ - U32 type; - RwRGBAReal color; - F32 matrix[16]; - F32 radius; - F32 angle; - RpLight* platLight; -}; - -struct xLightKit -{ - U32 tagID; - U32 groupID; - U32 lightCount; - xLightKitLight* lightList; -}; - struct xModelInstance { xModelInstance* Next; xModelInstance* Parent; xModelPool* Pool; - xAnimPlay* Anim; + xAnimPlay* Anim; // 0xC + + // Offset: 0x10 RpAtomic* Data; - xModelPipe Pipe; - U8 InFrustum; - U8 TrueClip; - S8 sortBias; - U8 modelpad; + U32 PipeFlags; F32 RedMultiplier; F32 GreenMultiplier; + + // Offset: 0x20 F32 BlueMultiplier; F32 Alpha; F32 FadeStart; F32 FadeEnd; + + // Offset: 0x30 xSurface* Surf; xModelBucket** Bucket; xModelInstance* BucketNext; xLightKit* LightKit; + + // Offset: 0x40 void* Object; - U16 Flags; - U8 BoneCount; - U8 BoneIndex; - U8* BoneRemap; - RwMatrixTag* Mat; + U16 Flags; // 0x44 + U8 BoneCount; // 0x46 + U8 BoneIndex; // 0x47 + U8* BoneRemap; // 0x48 + RwMatrix* Mat; // 0x4C + + // Offset: 0x50 xVec3 Scale; - xBox animBound; - xBox combinedAnimBound; U32 modelID; U32 shadowID; RpAtomic* shadowmapAtomic; - _class_20 anim_coll; + struct + { + xVec3* verts; + } anim_coll; }; +// NOTE (Square): Theses are based on the access pattern found in zUI_Render. +// I doubt they wrote this out by hand every time, but I'm just guessing on the macro here. +#define XMODELINSTANCE_GET_SRCBLEND(inst) (((inst)->PipeFlags >> 0x8) & 0xf) +#define XMODELINSTANCE_GET_DSTBLEND(inst) (((inst)->PipeFlags >> 0xc) & 0xf) + struct xModelTag { xVec3 v; @@ -329,20 +76,90 @@ struct xModelTag F32 wt[4]; }; -struct activity_data_1 +struct xModelTagWithNormal : xModelTag { + xVec3 normal; }; -struct xModelBlur +struct xModelAssetParam { - activity_data_1* activity; + U32 HashID; + U8 WordLength; + U8 String[3]; +}; - void render_enable(U8 enabled); - void render_all(); - void update_all(F32 dt); - void reset_all(); - void scene_exit(); - void scene_enter(); +struct xModelAssetInfo +{ + U32 Magic; + U32 NumModelInst; + U32 AnimTableID; + U32 CombatID; + U32 BrainID; }; +struct xModelAssetInst +{ + U32 ModelID; + U16 Flags; + U8 Parent; + U8 Bone; + F32 MatRight[3]; + F32 MatUp[3]; + F32 MatAt[3]; + F32 MatPos[3]; +}; + +struct xModelPipeLookup +{ + RpAtomic* model; + U32 PipeFlags; +}; + +struct xModelPipeInfo +{ + U32 ModelHashID; + U32 SubObjectBits; + U32 PipeFlags; +}; + +extern S32 xModelPipeNumTables; +extern S32 xModelPipeCount[16]; +extern xModelPipeInfo* xModelPipeData[16]; +extern S32 xModelLookupCount; +extern xModelPipeLookup* xModelLookupList; +extern S32 xModelInstStaticAlloc; + +U32 xModelGetPipeFlags(RpAtomic* model); +void xModelInit(); +void xModelPoolInit(U32 count, U32 numMatrices); +void xModelAnimCollStart(xModelInstance& m); +void xModelSetFrame(xModelInstance* modelInst, const xMat4x3* frame); +xModelInstance* xModelInstanceAlloc(RpAtomic* data, void* object, U16 flags, U8 boneIndex, + U8* boneRemap); +void xModelInstanceFree(xModelInstance* modelInst); +void xModelInstanceAttach(xModelInstance* inst, xModelInstance* parent); +void xModelRender(xModelInstance* modelInst); +void xModelRenderSingle(xModelInstance* modelInst); +void xModelRender2D(const xModelInstance& model, const basic_rect& r, const xVec3& from, + const xVec3& to); +void xModelSetMaterialAlpha(xModelInstance* modelInst, U8 alpha); +void xModelUpdate(xModelInstance* modelInst, F32 timeDelta); +xMat4x3* xModelGetFrame(xModelInstance* modelInst); +void xModelEval(xModelInstance* modelInst); +void xModel_SceneEnter(RpWorld* world); +void xModel_SceneExit(RpWorld* world); +xSphere* xModelGetLocalSBound(xModelInstance* model); +void xModelGetBoneMat(xMat4x3& mat, const xModelInstance& model, size_t index); +void xModelInstanceUpgradeBrotherShared(xModelInstance* inst, U32 flags); + +inline void xModelSetFrame(xModelInstance* modelInst, const xMat4x3* frame) +{ + xMat4x3Copy((xMat4x3*)modelInst->Mat, frame); +} + +inline xMat4x3* xModelGetFrame(xModelInstance* modelInst) +{ + return (xMat4x3*)modelInst->Mat; +} + #endif diff --git a/src/SB/Core/x/xModelBucket.cpp b/src/SB/Core/x/xModelBucket.cpp new file mode 100644 index 0000000..790ebfd --- /dev/null +++ b/src/SB/Core/x/xModelBucket.cpp @@ -0,0 +1,109 @@ +#include "xModelBucket.h" + +#include "iCamera.h" + +#include +#include + +extern RpWorld* sBucketDummyWorld; +extern RwCamera* sBucketDummyCamera; +extern S32 xModelBucketEnabled; +extern S32 sBucketCurr; +extern S32 sBucketCount; +extern xModelBucket* sBucketList; +extern S32 sBucketClipCullCurr; +extern S32 sBucketClipCullCount; +extern xModelBucket** sBucketClipCullList; +extern S32 sAlphaCurr; +extern S32 sAlphaStart; +extern S32 sAlphaCount; +extern xModelAlphaBucket* sAlphaList; +extern F32 xModelBucket_f675; // 100000.0f +extern F32 xModelBucket_f676; // -100000.0f + +S32 CmpAlphaBucket(const void* _a, const void* _b) +{ + xModelAlphaBucket* a = (xModelAlphaBucket*)_a; + xModelAlphaBucket* b = (xModelAlphaBucket*)_b; + if (a->Layer > b->Layer) + { + return 1; + } + if (a->Layer < b->Layer) + { + return -1; + } + if (a->SortValue < b->SortValue) + { + return 1; + } + if (a->SortValue > b->SortValue) + { + return -1; + } + return 0; +} + +void xModelBucket_PreCountReset() +{ + sBucketCurr = 0; + sBucketCount = 0; + sBucketList = NULL; + sBucketClipCullCurr = 0; + sBucketClipCullCount = 0; + sBucketClipCullList = NULL; + sAlphaCurr = 0; + sAlphaCount = 0; + sAlphaList = NULL; +} + +void xModelBucket_PreCountAlloc(S32 maxAlphaModels) +{ + sAlphaCount = maxAlphaModels; + sBucketList = (xModelBucket*)xMemAllocSize(sBucketCount * sizeof(xModelBucket)); + sBucketClipCullList = + (xModelBucket**)xMemAllocSize(sBucketClipCullCount * sizeof(xModelBucket*)); + sAlphaList = (xModelAlphaBucket*)xMemAllocSize(sAlphaCount * sizeof(xModelAlphaBucket)); + RwBBox boundingBox; + boundingBox.sup.x = xModelBucket_f675; + boundingBox.sup.y = xModelBucket_f675; + boundingBox.sup.z = xModelBucket_f675; + boundingBox.inf.x = xModelBucket_f676; + boundingBox.inf.y = xModelBucket_f676; + boundingBox.inf.z = xModelBucket_f676; + sBucketDummyWorld = RpWorldCreate(&boundingBox); + sBucketDummyCamera = iCameraCreate(0, 0, 0); + RpWorldAddCamera(sBucketDummyWorld, sBucketDummyCamera); +} + +void xModelBucket_Init() +{ + if (sBucketDummyCamera != NULL) + { + RpWorldRemoveCamera(sBucketDummyWorld, sBucketDummyCamera); + iCameraDestroy(sBucketDummyCamera); + RpWorldDestroy(sBucketDummyWorld); + sBucketDummyCamera = NULL; + sBucketDummyWorld = NULL; + } +} + +void xModelBucket_Begin() +{ + for (S32 i = 0; i < sBucketCount; i++) + { + sBucketList[i].List = NULL; + } + xModelBucketEnabled = 1; +} + +// Scheduling! +void xModelBucket_RenderAlphaBegin() +{ + sAlphaStart = 0; + xModelBucketEnabled = 0; + if (sAlphaCurr) + { + qsort(sAlphaList, sAlphaCurr, sizeof(xModelAlphaBucket), CmpAlphaBucket); + } +} diff --git a/src/SB/Core/x/xModelBucket.h b/src/SB/Core/x/xModelBucket.h new file mode 100644 index 0000000..40f4cf2 --- /dev/null +++ b/src/SB/Core/x/xModelBucket.h @@ -0,0 +1,43 @@ +#ifndef XMODELBUCKET_H +#define XMODELBUCKET_H + +#include "xModel.h" + +struct xModelBucket +{ + RpAtomic* Data; + RpAtomic* OriginalData; + xModelInstance* List; + S32 ClipFlags; + U32 PipeFlags; +}; + +struct xModelAlphaBucket +{ + RpAtomic* Data; + xModelInstance* MInst; + F32 AlphaFade; + F32 SortValue; + U32 Layer; +}; + +extern S32 xModelBucketEnabled; + +void xModelBucket_RenderAlpha(); + +S32 CmpAlphaBucket(const void* _a, const void* _b); +void xModelBucket_PreCountReset(); +void xModelBucket_PreCountBucket(RpAtomic* data, U32 pipeFlags, U32 subObjects); +void xModelBucket_PreCountAlloc(S32 maxAlphaModels); +void xModelBucket_InsertBucket(RpAtomic* data, U32 pipeFlags, U32 subObjects); +void xModelBucket_Init(); +void xModelBucket_Deinit(); +xModelBucket** xModelBucket_GetBuckets(RpAtomic* data); +void xModelBucket_Begin(); +void xModelBucket_Add(xModelInstance* minst); +void xModelBucket_RenderOpaque(); +void xModelBucket_RenderAlphaBegin(); +void xModelBucket_RenderAlphaLayer(S32 maxLayer); +void xModelBucket_RenderAlphaEnd(); + +#endif diff --git a/src/SB/Core/x/xMorph.cpp b/src/SB/Core/x/xMorph.cpp new file mode 100644 index 0000000..ad2f91b --- /dev/null +++ b/src/SB/Core/x/xMorph.cpp @@ -0,0 +1,122 @@ +#include "xMorph.h" + +#include "xDebug.h" +#include "iModel.h" + +#include + +xMorphSeqFile* xMorphSeqSetup(void* data, xMorphFindAssetCallback FindAssetCB) +{ + S32 i, j; + RpAtomic* model; + xMorphTargetFile* mphtgt; + xMorphSeqFile* header; + F32* timelist; + xMorphFrame* framelist; + U32* assetlist; + char* namelist; + void* assetPtr; + U32 skipsize; + + header = (xMorphSeqFile*)data; + timelist = (F32*)(header + 1); + framelist = (xMorphFrame*)(timelist + header->TimeCount); + assetlist = (U32*)(framelist + header->TimeCount); + namelist = (char*)(assetlist + header->ModelCount * 2); + + if (header->Flags & 0x80000000) { + return header; + } + + header->Flags |= 0x80000000; + if (!(header->Flags & 0x1)) { + namelist = NULL; + } + + for (i = 0; i < (S32)header->ModelCount * 2; i++) { + if (assetlist[i]) { + assetPtr = FindAssetCB(assetlist[i], namelist); + assetlist[i] = (U32)assetPtr; + } + if (namelist) { + namelist = strlen(namelist) + 1 + namelist; + } + } + + for (i = 0; i < (S32)header->ModelCount; i++) { + if (assetlist[i*2+1]) { + model = (RpAtomic*)assetlist[i*2]; + mphtgt = (xMorphTargetFile*)assetlist[i*2+1]; + iMorphOptimize(model, mphtgt->Flags & 0x1); + } + } + + for (i = 0; i < (S32)header->TimeCount; i++) { + model = (RpAtomic*)assetlist[(U32)framelist[i].Model*2]; + mphtgt = (xMorphTargetFile*)assetlist[(U32)framelist[i].Model*2+1]; + framelist[i].Model = model; + for (j = 0; j < 4; j++) { + if ((U32)framelist[i].Targets[j] + 0x10000 == 0xFFFF) { + framelist[i].Targets[j] = NULL; + } else { + skipsize = (mphtgt->NumVerts * 3 + 7) & ~7; + if (mphtgt->Flags & 0x1) { + skipsize *= 2; + } + if (j == 0) { + framelist[i].Flags = mphtgt->Flags; + framelist[i].NumVerts = mphtgt->NumVerts; + framelist[i].Scale *= mphtgt->Scale; + } + framelist[i].Targets[j] = (S16*)((U8*)(mphtgt + 1) + skipsize * (U32)framelist[i].Targets[j] * 2); + } + } + } + + return header; +} + +void xMorphRender(xMorphSeqFile* seq, RwMatrix* mat, F32 time) +{ + F32 lerp; + U32 tidx, tcount; + S16 weight[4]; + S16* wptr; + F32* times; + xMorphFrame* frame; + + times = (F32*)(seq + 1); + tcount = seq->TimeCount; + frame = (xMorphFrame*)(times + seq->TimeCount); + + if (time < 0.0f) time = 0.0f; + if (time > times[tcount-1]) time = times[tcount-1]; + + tidx = (tcount-1) & 0x3; + while (times[tidx] < time) tidx += 4; + while (tidx && time < times[tidx]) tidx--; + + frame += tidx; + + if (!frame->Targets[0]) { + iModelRender(frame->Model, mat); + } else { + lerp = frame->RecipTime * (time - times[tidx]); + if (lerp == 0.0f) { + wptr = frame->WeightStart; + } else { + weight[0] = (S32)(lerp * (frame->WeightEnd[0] - frame->WeightStart[0])) + frame->WeightStart[0], + weight[1] = (S32)(lerp * (frame->WeightEnd[1] - frame->WeightStart[1])) + frame->WeightStart[1], + weight[2] = (S32)(lerp * (frame->WeightEnd[2] - frame->WeightStart[2])) + frame->WeightStart[2], + weight[3] = (S32)(lerp * (frame->WeightEnd[3] - frame->WeightStart[3])) + frame->WeightStart[3]; + wptr = weight; + } + + iMorphRender(frame->Model, mat, frame->Targets, wptr, frame->Flags & 0x1, frame->Scale); + } +} + +F32 xMorphSeqDuration(xMorphSeqFile* seq) +{ + return ((F32*)(seq+1))[seq->TimeCount-1]; +} diff --git a/src/SB/Core/x/xMorph.h b/src/SB/Core/x/xMorph.h new file mode 100644 index 0000000..3ee24ac --- /dev/null +++ b/src/SB/Core/x/xMorph.h @@ -0,0 +1,47 @@ +#ifndef XMORPH_H +#define XMORPH_H + +#include "iMorph.h" +#include "xMath3.h" + +#include +#include + +struct xMorphSeqFile +{ + U32 Magic; + U32 Flags; + U32 TimeCount; + U32 ModelCount; +}; + +struct xMorphFrame +{ + RpAtomic* Model; + F32 RecipTime; + F32 Scale; + U16 Flags; + U16 NumVerts; + S16* Targets[4]; + S16 WeightStart[4]; + S16 WeightEnd[4]; +}; + +struct xMorphTargetFile +{ + U32 Magic; + U16 NumTargets; + U16 NumVerts; + U32 Flags; + F32 Scale; + xVec3 Center; + F32 Radius; +}; + +typedef void*(*xMorphFindAssetCallback)(U32, char*); + +xMorphSeqFile* xMorphSeqSetup(void* data, xMorphFindAssetCallback FindAssetCB); +void xMorphRender(xMorphSeqFile* seq, RwMatrix* mat, F32 time); +F32 xMorphSeqDuration(xMorphSeqFile* seq); + +#endif \ No newline at end of file diff --git a/src/SB/Core/x/xMovePoint.cpp b/src/SB/Core/x/xMovePoint.cpp new file mode 100644 index 0000000..ce6682f --- /dev/null +++ b/src/SB/Core/x/xMovePoint.cpp @@ -0,0 +1,180 @@ +#include "xMovePoint.h" + +#include + +#include "xMath.h" +#include "xScene.h" +#include "xMemMgr.h" + +F32 xVec3Hdng(xVec3* a, const xVec3* b, const xVec3* c); + +void xMovePointInit(xMovePoint* ent, xMovePointAsset* asset) +{ + xBaseInit(ent, asset); + ent->asset = asset; + + // They didn't use `&asset->pos` here as that doesn't generate a 100% match. + ent->pos = &ent->asset->pos; + ent->on = asset->on; + ent->delay = asset->delay; + ent->spl = NULL; + + if (asset->numPoints != 0) + { + ent->nodes = (xMovePoint**)xMemAllocSize(asset->numPoints * sizeof(xMovePoint*)); + } + else + { + ent->nodes = NULL; + } +} + +void xMovePointSave(xMovePoint* ent, xSerial* s) +{ + xBaseSave(ent, s); +} + +void xMovePointLoad(xMovePoint* ent, xSerial* s) +{ + xBaseLoad(ent, s); +} + +void xMovePointReset(xMovePoint* m) +{ + xBaseReset(m, m->asset); + + m->on = m->asset->on; + m->delay = m->asset->delay; +} + +void xMovePointSetup(xMovePoint* m, xScene* sc) +{ + m->node_wt_sum = 0; + U32* pointIds = (U32*)(m->asset + 1); + for (U16 idx = 0; idx < m->asset->numPoints; ++idx) + { + U32 id = pointIds[idx]; + m->nodes[idx] = (xMovePoint*)xSceneResolvID(sc, id); + m->node_wt_sum += m->nodes[idx]->asset->wt; + m->nodes[idx]->prev = m; + } +} + +void xMovePointSplineDestroy(xMovePoint* m) +{ + if (m->spl != NULL) + { + m->spl = NULL; + } +} + +void xMovePointSplineSetup(xMovePoint* m) +{ + xMovePoint *w0, *w1, *w2, *w3; + xVec3 points[2]; + xVec3 p1, p2; + + if (m->asset->bezIndex != 1) + return; + if (m->spl) + return; + + w0 = m->prev; + w1 = m; + w2 = m->nodes[0]; + + points[0] = *w0->pos; + if (w2->asset->bezIndex > 0) + { + w3 = w2->nodes[0]; + p1 = *w1->pos; + p2 = *w2->pos; + points[1] = *w3->pos; + } + else + { + p1.x = (1 / 3.f) * w0->pos->x + (2 / 3.f) * w1->pos->x; + p1.y = (1 / 3.f) * w0->pos->y + (2 / 3.f) * w1->pos->y; + p1.z = (1 / 3.f) * w0->pos->z + (2 / 3.f) * w1->pos->z; + p2.x = (2 / 3.f) * w1->pos->x + (1 / 3.f) * w2->pos->x; + p2.y = (2 / 3.f) * w1->pos->y + (1 / 3.f) * w2->pos->y; + p2.z = (2 / 3.f) * w1->pos->z + (1 / 3.f) * w2->pos->z; + points[1] = *w2->pos; + } + + m->spl = xSpline3_Bezier(points, NULL, 2, 0, &p1, &p2); + xSpline3_ArcInit(m->spl, 20); +} + +// If you uncomment the numPoints variable then this function is a perfect match +// minus ordering. In the original assembly some variable fetches are lifted to +// places earlier in the assembly listing than what this comiles to for some +// reason. +// The r27-30 registers used to hold the main varibles of the function are all +// perfect matches with this code. +extern float xMovePoint_float_0; +F32 xMovePointGetNext(xMovePoint* m, xMovePoint* prev, xMovePoint** next, xVec3* hdng) +{ + if (m->asset->numPoints < 1) + { + *next = NULL; + return xMovePoint_float_0; + } + + xMovePoint* previousOption = NULL; + + S32 rnd = xrand() % m->node_wt_sum; + + // The debug symbols don't show a dedicated numPoints var, but if it isn't + // present, then getting numPoints isn't lifted outside of the loop, which + // it is in the original assembly. + U16 numPoints = m->asset->numPoints; + + for (U16 idx = 0; idx < m->asset->numPoints; ++idx) + { + *next = m->nodes[idx]; + rnd -= (*next)->asset->wt; + if ((*next)->on == 0) + { + *next = NULL; + } + else + { + previousOption = *next; + if (*next == prev) + { + *next = NULL; + } + else if (rnd < 0) + { + break; + } + } + } + + if (*next == NULL) + { + if (previousOption != NULL) + { + *next = previousOption; + } + else + { + return xMovePoint_float_0; + } + } + + if (hdng) + { + return xVec3Hdng(hdng, m->pos, (*next)->pos); + } + else + { + return xMovePoint_float_0; + } +} + +xVec3* xMovePointGetPos(const xMovePoint* m) +{ + return m->pos; +} diff --git a/src/SB/Core/x/xMovePoint.h b/src/SB/Core/x/xMovePoint.h new file mode 100644 index 0000000..4e0af7c --- /dev/null +++ b/src/SB/Core/x/xMovePoint.h @@ -0,0 +1,56 @@ +#ifndef XMOVEPOINT_H +#define XMOVEPOINT_H + +#include "xBase.h" +#include "xMath3.h" +#include "xSpline.h" + +struct xScene; + +struct xMovePointAsset : xBaseAsset +{ + xVec3 pos; + U16 wt; + + U8 on; + U8 bezIndex; + U8 flg_props; + U8 pad; + U16 numPoints; + + F32 delay; + F32 zoneRadius; + F32 arenaRadius; +}; + +struct xMovePoint : xBase +{ + xMovePointAsset* asset; + + // Offset: 0x14 + xVec3* pos; + xMovePoint** nodes; + xMovePoint* prev; + U32 node_wt_sum; + + // Offset: 0x24 + U8 on; + U8 pad[3]; + + // Offset: 0x28 + F32 delay; + xSpline3* spl; +}; + +xVec3* xMovePointGetPos(xMovePoint* m); +F32 xMovePointGetNext(const xMovePoint* m, const xMovePoint* prev, xMovePoint** next, + xVec3* hdng); +void xMovePointSplineDestroy(xMovePoint* m); +void xMovePointSplineSetup(xMovePoint* m); +void xMovePointSetup(xMovePoint* m, xScene* sc); +void xMovePointReset(xMovePoint* m); +void xMovePointLoad(xMovePoint* ent, xSerial* s); +void xMovePointSave(xMovePoint* ent, xSerial* s); +void xMovePointInit(xMovePoint* m, xMovePointAsset* asset); + +#endif diff --git a/src/SB/Core/x/xNME.h b/src/SB/Core/x/xNME.h deleted file mode 100644 index 9f7e7a2..0000000 --- a/src/SB/Core/x/xNME.h +++ /dev/null @@ -1,613 +0,0 @@ -#ifndef XNME_H -#define XNME_H - -#include "xEnt.h" -#include "xModel.h" -#include "xBehaviour.h" -#include "xFrag.h" -#include "xPar.h" -#include "xMail.h" -#include "xSound.h" - -enum en_allow -{ - ALLOW_NEVER, - ALLOW_NORMAL, - ALLOW_ALWAYS, - ALLOW_NOMORE -}; - -enum en_nmesimp -{ - NME_SIMP_HAPPY, - NME_SIMP_DEAD, - NME_SIMP_IGNORANT, - NME_SIMP_WARYDETECT, - NME_SIMP_WARY, - NME_SIMP_WORRIED, - NME_SIMP_CONFUSED, - NME_SIMP_BIGBULLY, - NPC_STAT_NOMORE -}; - -enum en_haztyp -{ - HAZ_TYP_UNKNOWN, - HAZ_TYP_EXPLODE, - HAZ_TYP_IMPACT, - HAZ_TYP_IMPACTWET, - HAZ_TYP_IMPACTBOOM, - HAZ_TYP_DAZED, - HAZ_TYP_SPAWNBALL_XX, - HAZ_TYP_SPAWNBALL_GG, - HAZ_TYP_SPAWNBALL_TR, - HAZ_TYP_SPAWNBALL_PT, - HAZ_TYP_SPAWNGROW, - HAZ_TYP_BUCKOBOOM_V1, - HAZ_TYP_TIKIBOOM, - HAZ_TYP_SLAMWAVE_V1, - HAZ_TYP_SLAMWAVE_V2, - HAZ_TYP_SLAMWAVE_V3, - HAZ_TYP_FLING_V1, - HAZ_TYP_FLING_V2, - HAZ_TYP_FLING_V3, - HAZ_TYP_FLING_FROGFISH, - HAZ_TYP_SPITPUDDLE_V1, - HAZ_TYP_SPITPUDDLE_V2, - HAZ_TYP_SPITPUDDLE_V3, - HAZ_TYP_ICECREAMSPLAT, - HAZ_TYP_SPITSTEAM, - HAZ_TYP_SPITSPLASH, - HAZ_TYP_POPPER_V1, - HAZ_TYP_POPPER_V2, - HAZ_TYP_POPPER_V3, - HAZ_TYP_MERVBOMB_V1, - HAZ_TYP_MERVBOMB_V2, - HAZ_TYP_MERVBOMB_V3, - HAZ_TYP_MERVLET_V1, - HAZ_TYP_MERVLET_V2, - HAZ_TYP_MERVLET_V3, - HAZ_TYP_ZAPBALL_V1, - HAZ_TYP_ZAPBALL_V2, - HAZ_TYP_ZAPBOOM_V1, - HAZ_TYP_ZAPBOOM_V2, - HAZ_TYP_TURBALL_V1, - HAZ_TYP_TURBALL_V2, - HAZ_TYP_TURBALL_V3, - HAZ_TYP_TURBOOM, - HAZ_TYP_GOLFBALL, - HAZ_TYP_GOLFBOOM, - HAZ_TYP_GOLFJUNK_A, - HAZ_TYP_GOLFJUNK_B, - HAZ_TYP_GOLFJUNK_C, - HAZ_TYP_GOLFJUNK_D, - HAZ_TYP_GOLFJUNK_E, - HAZ_TYP_DENNIS_KNIFE, - HAZ_TYP_DENNIS_KNIFEBOOM, - HAZ_TYP_TUNEBORN, - HAZ_TYP_TUNEBANG, - HAZ_TYP_TUNEBOOM, - HAZ_TYP_TUNEFLYT, - HAZ_TYP_SWIMWAKE, - HAZ_TYP_BOWWAVE, - HAZ_TYP_SPLASH_RING, - HAZ_TYP_SPLISH_DROP, - HAZ_TYP_VISSPLASH_WAVE, - HAZ_TYP_VISSPLASH_DROP, - HAZ_TYP_VISSPLASH_WATER, - HAZ_TYP_VISSPLASH_CHOC, - HAZ_TYP_VISSPLASH_LAVA, - HAZ_TYP_VISSPLASH_BILE, - HAZ_TYP_VISSPLASH_OIL, - HAZ_TYP_VISSPLASH_SAUCE, - HAZ_TYP_VISSPLASH_TOXIC, - HAZ_TYP_REFLECT_V1, - HAZ_TYP_PLYRBANG_V1, - HAZ_TYP_POWERUP_EXPLOSION_V1, - HAZ_TYP_NOMORE, - HAZ_TYP_FORCE = 0x7fffffff -}; - -enum en_npcdmg -{ - DMGTYP_UNDECIDED, - DMGTYP_ABOVE, - DMGTYP_BELOW, - DMGTYP_SIDE, - DMGTYP_INSTAKILL, - DMGTYP_WOUNDEVENT, - DMGTYP_KILLEVENT, - DMGTYP_NMEATTACK, - DMGTYP_HITBYTOSS, - DMGTYP_NMEKNOCKED, - DMGTYP_ROPE, - DMGTYP_CRUISEBUBBLE, - DMGTYP_FRIENDLYFIRE, - DMGTYP_REFLECTED, - DMGTYP_BOULDER, - DMGTYP_BUBBOWL, - DMGTYP_THUNDER_TIKI_EXPLOSION, - DMGTYP_DAMAGE_SURFACE, - DMGTYP_BUNGEED, - DMGTYP_SURFACE, - DMGTYP_CARTWHEEL, - DMGTYP_CARSMASH, - DMGTYP_SLIDE, - DMGTYP_EXPLOSION, - DMGTYP_BBOWLZAP, - DMGTYP_NOMORE, - DMGTYP_FORCEINT = 0x7fffffff -}; - -enum en_plyrpup -{ - ePowerupLevelDisabled, - ePowerupLevelNormal, - ePowerupLevelLevelMax, - ePowerupLevelHealthMax, - ePowerupLevelCount -}; - -enum en_denstage -{ - DEN_STAGE_UNKNOWN, - DEN_STAGE_INTRO, - DEN_STAGE_A, - DEN_STAGE_B, - DEN_STAGE_C, - DEN_STAGE_OUTRO, - DEN_STAGE_NOMORE -}; - -enum en_dbcmode -{ - DEN_CAMMOD_UNKNOWN, - DEN_CAMMOD_NORMAL, - DEN_CAMMOD_BINARY, - DEN_CAMMOD_NOMORE -}; - -enum en_vis -{ - VIS_PREPARE_TO_DIE, - VIS_HORROR_FLIK, - VIS_OH_DEAR_GAHD, - VIS_GET_BACK_HERE, - VIS_I_SEEE_YOUUU, - VIS_GREY_AND_FOGGY, - VIS_LIKE_A_BIRDIE, - VIS_EARTHWORM_JIM, - VIS_NOBODY_AROUND, - VIS_NOMORE -}; - -enum en_dtbcmode -{ - DENT_CAMMOD_UNKNOWN, - DENT_CAMMOD_NORMAL, - DENT_CAMMOD_BINARY, - DENT_CAMMOD_NOMORE -}; - -enum en_dentstage -{ - DENT_STAGE_UNKNOWN, - DENT_STAGE_INTRO, - DENT_STAGE_A, - DENT_STAGE_B, - DENT_STAGE_C, - DENT_STAGE_OUTRO, - DENT_STAGE_NOMORE -}; - -struct xGroupAsset : xBaseAsset -{ - U16 itemCount; - U16 groupFlags; -}; - -struct xGroup : xBase // Move after filling in more headers -{ - xGroupAsset* asset; - xBase** item; - U32 last_index; - S32 flg_group; -}; - -struct OriginalBackupData -{ - struct - { - S32 flg_enableWander : 1; - S32 flg_enablePatrol : 1; - S32 flg_enableDetect : 1; - S32 flg_activeOn : 1; - S32 flg_takeNoDamage : 1; - S32 flg_unused : 27; - }; - union - { - en_allow overrideDetect; - S32 alignmeproperly; - }; - union - { - en_allow overrideAttack; - S32 alignmeproperlyToo; - }; -}; - -struct Restore -{ - U8 chkby; - U8 penby; - U8 padpad[2]; - union - { - en_npcgol gid_compare; - S32 gid_COMPARE; - }; -}; - -struct NMERuntime -{ - struct - { - S32 flg_enableWander : 1; - S32 flg_enablePatrol : 1; - S32 flg_enableDetect : 1; - S32 flg_activeOn : 1; - S32 flg_takeNoDamage : 1; - S32 flg_unused : 27; - }; - union - { - en_allow overrideDetect; - S32 alignmeproperly; - }; - union - { - en_allow overrideAttack; - S32 alignmeproperlyToo; - }; - OriginalBackupData orig; - Restore restore; -}; - -struct zNMEDriver -{ - xEnt* ent_driver; - F32 tym_mount; - xMat4x3 mat_parLast; - xMat4x3 mat_ownerLast; - struct - { - S32 flg_inContact : 1; - S32 flg_matchOrient : 1; - S32 flg_unused : 30; - }; - - void WheelTurnsYou_C(xMat4x3* mat_owner); - void ReviewCollide(xEntCollis* npccol); -}; - -struct zNMECommon; - -struct zMovePoint : xMovePoint -{ -}; - -struct zNMENavNet -{ - zMovePoint* nav_past; - zMovePoint* nav_curr; - zMovePoint* nav_dest; - zMovePoint* nav_lead; - xSpline3* spl_mvptspline; - F32 len_mvptspline; - F32 dst_curspline; - zNMECommon* nme_owner; - - S32 MvptCycle(); -}; - -struct zNMESoundTable -{ - iSndGroupHandle sndGroupHandle[10]; - unsigned char* assetNames[10]; - F32 timer[10]; - F32 time[10]; - S32 flags[10]; -}; - -struct xDynAsset : xBaseAsset -{ - U32 type; - U16 version; - U16 handle; -}; - -struct zNMEAsset : xDynAsset -{ - xEntAsset ent_asset; -}; - -struct Damage_1 -{ - F32 tym_invuln; -}; - -struct Physics -{ - F32 acc_grav; - F32 spd_maxFall; -}; - -struct Movement_1 -{ - F32 spd_move; - F32 acc_move; - F32 dst_deviant; - F32 spd_turnrate; -}; - -struct NMECfgCommon -{ - Damage_1 damage; - Physics physics; - Movement_1 movement; -}; - -struct SimpShadParm -{ - F32 rad_shadow; - unsigned char* nam_shadowTexture; - RwRaster* rast_shadow; -}; - -struct FullShadParm -{ - S32 tobeDetermined; -}; - -struct ShadowRadii -{ - F32 rad_noShadow; - F32 rad_complexShadow; -}; - -struct NMEShadParms -{ - SimpShadParm simpshad; - FullShadParm fullshad; - ShadowRadii shadrad; -}; - -struct zNMEArena -{ - S32 flg_arena; - xVec3 pos_arena; - F32 rad_arena; - zMovePoint* nav_arena; - zMovePoint* nav_refer_dest; - zMovePoint* nav_refer_curr; - - zMovePoint* NextBestNav(zMovePoint* nav_from); - S32 Cycle(zNMECommon* npc, S32 peek); -}; - -struct NMESysEvent -{ - S32 doLinkEvents; - S32 handled; - xBase* from; - xBase* to; - union - { - U32 toEvent; - en_xEventTags toEvent_asEnum; - }; - F32 toParam[4]; - xBase* toParamWidget; - U32 toParamWidgetID; -}; - -struct NMEBlastInfo -{ - xVec3 pos_blast; - F32 rad_blast; - F32 spd_expand; -}; - -struct NMEChatInfo -{ - xVec3 pos_chat; - F32 tym_chat; -}; - -struct NMESpawnInfo -{ - xVec3 pos_spawn; - zMovePoint* nav_firstMovepoint; - zMovePoint* nav_spawnReference; - S32 spawnSuccess; -}; - -struct NMETargetInfo -{ - xBase* bas_tgt; - xVec3 pos_tgt; -}; - -struct NMEDamageInfo -{ - en_npcdmg dmg_type; - xBase* dmg_from; - xVec3 vec_dmghit; - S32 amt_damage; - union - { - S32 fac_powerup; - en_plyrpup pup_player; - }; -}; - -struct NMEStunInfo -{ - F32 tym_stuntime; - en_carystat carrystate; - S32 allowStun; -}; - -struct NMEScriptInfo -{ - U32 aid_playanim; -}; - -struct NMEMountInfo -{ - xEnt* ent_toMount; - xCollis* col_forMount; -}; - -struct NMEDestInfo -{ - xVec3 pos_there; - zMovePoint* nav_there; -}; - -struct NMEAreaInfo -{ - zNMECommon* npc_origin; - xVec3 pos_origin; -}; - -struct NMEMsg -{ - en_npcmsg msgid; - U32 sendto; - U32 from; - en_msgdata infotype; - union - { - NMESysEvent sysevent; - NMEBlastInfo blastarea; - NMEChatInfo chatter; - NMESpawnInfo spawning; - NMETargetInfo target; - NMEDamageInfo dmgdata; - NMEStunInfo stundata; - NMEScriptInfo scriptdata; - NMEMountInfo mountdata; - NMEDestInfo destdata; - NMEAreaInfo areadata; - }; - void* attached; - NMEMsg* next; - F32 tmr_delay; -}; - -struct Health_3 -{ - S32 pts_healthMax; -}; - -struct Ranges_2 -{ - F32 rad_tooclose[2]; - F32 rad_lob; - F32 rad_lobgrey; - F32 rad_aware; - F32 rad_awaregrey; -}; - -struct Attack_3 -{ - F32 spd_proj; - S32 num_salvo; - F32 tym_shoot; - F32 dst_spreadHorz; -}; - -struct Battle_6 -{ - F32 tym_reload; - F32 tym_leapDelay; - S32 num_atakPerLeap; -}; - -struct NMECfgDennis -{ - Health_3 health; - Ranges_2 ranges; - Attack_3 attack; - Battle_6 battle; -}; - -struct DennisLetMeKnow : xPSYNote -{ -}; - -// DenTooMeter : BarMeter FIX LATER -struct DenTooMeter -{ - U8 lastPaused; - //TextureScroller denTooTexureScroller; FIX LATER - - void update(); - void setup(); - void* ct(); -}; - -struct Health_8 -{ - S32 pts_healthMax; -}; - -struct Ranges_5 -{ - F32 rad_tooclose; - F32 rad_lob; - F32 rad_lobgrey; - F32 rad_aware; - F32 rad_awaregrey; -}; - -struct Attack_0 -{ -}; - -struct ThrowSide -{ - F32 spd_proj; - S32 num_salvo; - F32 dst_spreadHorz; -}; - -struct ThrowToes -{ - F32 spd_proj; - S32 num_salvo; - F32 dst_nearTgt; - F32 dst_farTgt; - F32 hyt_elevate; -}; - -struct Battle_2 -{ - F32 tym_reload; - F32 tym_leapDelay; - S32 num_atakPerLeap; -}; - -struct NMECfgDenToo -{ - Health_8 health; - Ranges_5 ranges; - Attack_0 attack; - ThrowSide throwSide; - ThrowToes throwToes; - Battle_2 battle; -}; - -#endif diff --git a/src/SB/Core/x/xNPCBasic.cpp b/src/SB/Core/x/xNPCBasic.cpp new file mode 100644 index 0000000..3b6cfbb --- /dev/null +++ b/src/SB/Core/x/xNPCBasic.cpp @@ -0,0 +1,366 @@ +#include "xNPCBasic.h" + +#include +#include + +// Weird... why does x depend on z here? +#include "zEnt.h" +#include "zGrid.h" + +#include "xMath.h" +#include "xModel.h" +#include "xEntMotion.h" +#include "xCamera.h" +#include "xDraw.h" + +#include "iColor.h" +#include "xColor.h" +#include "iCollide.h" + +extern float xNPCBasic_float_0; +extern float xNPCBasic_float_1; +extern float xNPCBasic_float_onehalf; +extern float xNPCBasic_float_onequarter; +extern float xNPCBasic_float_15; +extern float xNCPBasic_float_0p10000000; +extern float xNPCBasic_float_0p75; +extern float xNPCBasic_float_1eminus5; +extern float xNPCBasic_float_0p2; +extern float xNPCBasic_float_thirty; +extern float xNPCBasic_float_0p04; +extern float xNPCBasic_float_0p025; + +extern xEntCollis g_colrec; +extern xVec3 lbl_8026A3F8; + +void NPC_alwaysUseSphere(xEnt*, xVec3*); +void NPC_entwrap_setup(xEnt*); +void NPC_entwrap_reset(xEnt*); +S32 NPC_entwrap_event(xBase*, xBase*, U32, const F32*, xBase*); +void NPC_entwrap_update(xEnt*, xScene*, F32); +void NPC_entwrap_bupdate(xEnt*, xVec3*); +void NPC_entwrap_move(xEnt*, xScene*, F32, xEntFrame*); +void NPC_entwrap_render(xEnt*); + +// The order of the function pointer assignment instructions at the end of the +void xNPCBasic::Init(xEntAsset* asset) +{ + if (xNPCBasic_float_0 == asset->scale.x) + { + asset->scale.x = xNPCBasic_float_1; + } + if (xNPCBasic_float_0 == asset->scale.y) + { + asset->scale.y = xNPCBasic_float_1; + } + if (xNPCBasic_float_0 == asset->scale.z) + { + asset->scale.z = xNPCBasic_float_1; + } + + xEnt* thisEnt = this; + xEntInit(thisEnt, asset); + collType = 8; + collLev = 4; + bound.type = XBOUND_TYPE_SPHERE; // [S8] 0x84 + moreFlags |= 0x10; + zEntParseModelInfo(thisEnt, asset->modelInfoID); + xEntInitForType(thisEnt); + xEntInitShadow(*thisEnt, entShadow_embedded); + simpShadow = &simpShadow_embedded; + xShadowSimple_CacheInit(simpShadow, thisEnt, 0x50); + if (bound.type == XBOUND_TYPE_BOX) + { + iBoxForModel(&bound.box.box, collModel ? collModel : model); + } + else if (bound.type == XBOUND_TYPE_OBB) + { + iBoxForModelLocal(&bound.box.box, collModel ? collModel : model); + } + + if (flags1.flg_basenpc & 0x1) + { + collis = (xEntCollis*)xMemAllocSize(sizeof(xEntCollis)); + memset(collis, 0, sizeof(xEntCollis)); + } + + if ((flags1.flg_basenpc & 0x2) == 0) + { + frame = (xEntFrame*)xMemAllocSize(sizeof(xEntFrame)); + memset(frame, 0, sizeof(xEntFrame)); + } + + RestoreColFlags(); + + f_setup = &NPC_entwrap_setup; + f_reset = &NPC_entwrap_reset; + eventFunc = &NPC_entwrap_event; + update = &NPC_entwrap_update; + bupdate = &NPC_entwrap_bupdate; + move = &NPC_entwrap_move; + render = &NPC_entwrap_render; + + baseFlags &= 0xffef; +} + +void xNPCBasic::Reset() +{ + xEntReset(this); + DBG_PStatClear(); + if (!(U32(flags1.flg_basenpc) & 0x2)) + { + xVec3Copy(&frame->drot.axis, &g_Y3); + frame->drot.angle = 0.0f; + xVec3Copy(&frame->rot.axis, &g_Y3); + frame->rot.angle = asset->ang.x; + } + + flags1.flg_basenpc |= 4; + colFreq = -1; + + colFreqReset = (15.0f * (0.25f * (xurand() - 0.5f))) + 15.0f; + RestoreColFlags(); +} + +void NPC_alwaysUseSphere(xEnt* ent, xVec3* value) +{ + xNPCBasic* npc = (xNPCBasic*)ent; + xVec3 bndcent = lbl_8026A3F8; + + xVec3Copy(&bndcent, xEntGetPos(npc)); + bndcent.y += xNPCBasic_float_0p75; + + npc->bound.type = XBOUND_TYPE_SPHERE; + xVec3Copy(&npc->bound.sph.center, &bndcent); + npc->bound.sph.r = xNPCBasic_float_0p75; + if (npc->bound.type != XBOUND_TYPE_NA) + { + xQuickCullForBound(&npc->bound.qcd, &npc->bound); + } + + zGridUpdateEnt(npc); + if (npc->DBG_IsNormLog(eNPCDCAT_Eight, 2) || npc->DBG_IsNormLog(eNPCDCAT_Seven, 2)) + { + xDrawSetColor(g_PIMP_GOLD); + xBoundDraw(&npc->bound); + } +} + +void NPC_spdBasedColFreq(xNPCBasic* npc, F32 dt) +{ + if (dt < xNPCBasic_float_1eminus5) + { + return; + } + F32 d = xVec3Length(&npc->frame->vel); + if (d < xNPCBasic_float_0p2) + { + return; + } + + F32 radius; + if (npc->bound.type == XBOUND_TYPE_SPHERE) + { + radius = npc->bound.sph.r; + } + else + { + radius = MAX(npc->bound.box.box.upper.x - npc->bound.box.box.lower.x, + npc->bound.box.box.upper.z - npc->bound.box.box.lower.z); + } + + S32 nf = xNPCBasic_float_thirty * (radius / d); + npc->colFreq = MIN(npc->colFreq, nf); +} + +void xNPCBasic::Process(xScene* xscn, F32 dt) +{ + xEnt* thisEnt = this; + void (*bak_bupdate)(xEnt*, xVec3*); + S32 hasgrav = 0; + + if (flags2.flg_colCheck || flags2.flg_penCheck) + { + colFreq -= 1; + } + else + { + colFreq = 1; + } + + if (pflags & 0x4) + { + hasgrav = 1; + } + + if (colFreq >= 0) + { + pflags &= 0xfb; + } + + if (pflags & 0x2) + { + xEntApplyPhysics(thisEnt, xscn, dt); + } + + if (pflags & 0x1) + { + xEntMove(thisEnt, xscn, dt); + } + + if (ffx != NULL) + { + xFFXApply(this, xscn, dt); + } + + if (frame != NULL && (flags1.flg_upward & 0x2)) + { + frame->dpos.y = MAX(xNPCBasic_float_0, frame->dpos.y); + frame->dvel.y = MAX(xNPCBasic_float_0, frame->dvel.y); + frame->vel.y = MAX(xNPCBasic_float_0, frame->vel.y); + frame->oldvel.y = MAX(xNPCBasic_float_0, frame->oldvel.y); + model->Mat->pos.y = MAX(model->Mat->pos.y, frame->oldmat.pos.y); + } + + if (colFreq < 0) + { + colFreq = colFreqReset; + + DBG_PStatCont(eNPCPerfEnable); + DBG_PStatOn(eNPCPerfDisable); + + if (collis == NULL) + { + memset(&g_colrec, 0, sizeof(g_colrec)); + collis = &g_colrec; + } + + collis->chk = flags2.flg_colCheck; + collis->pen = flags2.flg_penCheck; + + bak_bupdate = bupdate; + bupdate = &NPC_alwaysUseSphere; + xEntCollide(thisEnt, xscn, dt); + bupdate = bak_bupdate; + + CollideReview(); + + if ((flags1.flg_basenpc & 0x1) == 0) + { + collis = NULL; + } + + DBG_PStatCont(eNPCPerfDisable); + DBG_PStatOn(eNPCPerfEnable); + } + + if ((pflags & (0x2 | 0x1)) != 0 && xVec3Length2(&frame->vel) > xNCPBasic_float_0p10000000) + { + NPC_spdBasedColFreq(this, dt); + } + + if (hasgrav) + { + pflags |= 0x4; + } + + if (DBG_IsNormLog(eNPCDCAT_Seven, 2)) + { + xDrawSetColor(g_BLUE); + xBoundDraw(&bound); + } +} + +void xNPCBasic::CollideReview() +{ + if (DBG_IsNormLog(eNPCDCAT_Eight, 2)) + { + xDrawSetColor(g_LAVENDER); + xBoundDraw(&bound); + } +} + +void xNPCBasic::NewTime(xScene*, F32) +{ + flags1.flg_basenpc &= ~0x4; +} + +void NPC_entwrap_setup(xEnt* ent) +{ + xNPCBasic* npc = (xNPCBasic*)ent; + npc->DBG_HaltOnMe(0, NULL); + npc->Setup(); +} + +void NPC_entwrap_reset(xEnt* ent) +{ + xNPCBasic* npc = (xNPCBasic*)ent; + npc->DBG_HaltOnMe(0, NULL); + npc->Reset(); +} + +void NPC_entwrap_update(xEnt* ent, xScene* scn, F32 dt_caller) +{ + F32 dt = dt_caller; + if (dt > xNPCBasic_float_0p04) + { + dt = xNPCBasic_float_0p025; + } + + xNPCBasic* npc = (xNPCBasic*)ent; + xEntBeginUpdate(npc, scn, dt); + npc->flags1.inUpdate = 1; + npc->DBG_HaltOnMe(0, NULL); + npc->DBG_PStatOn(eNPCPerfEnable); + + if (npc->isCulled) + { + npc->model->Flags &= 0xfffd; + } + else if ((npc->flags1.flg_upward & 0x1) == 0) + { + npc->model->Flags |= 0x2; + } + + npc->Process(scn, dt); + + npc->DBG_PStatCont(eNPCPerfEnable); + npc->flags1.inUpdate = 0; + xEntEndUpdate(npc, scn, dt); + + npc->NewTime(scn, dt); +} + +void NPC_entwrap_bupdate(xEnt* ent, xVec3* pos) +{ + ((xNPCBasic*)ent)->BUpdate(pos); +} + +void NPC_entwrap_move(xEnt* ent, xScene* scn, F32 dt, xEntFrame* frame) +{ + ((xNPCBasic*)ent)->Move(scn, dt, frame); +} + +S32 NPC_entwrap_event(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* toParamWidget) +{ + S32 handled = 0; + return ((xNPCBasic*)to)->SysEvent(from, to, toEvent, toParam, toParamWidget, &handled); +} + +void NPC_entwrap_render(xEnt* ent) +{ + ((xNPCBasic*)ent)->Render(); +} + +void xNPCBasic::DBG_PStatClear() +{ +} + +void xNPCBasic::DBG_HaltOnMe(U32, char*) +{ +} + +void xNPCBasic::BUpdate(xVec3* v) +{ + xEntDefaultBoundUpdate(this, v); +} diff --git a/src/SB/Core/x/xNPCBasic.h b/src/SB/Core/x/xNPCBasic.h new file mode 100644 index 0000000..121f313 --- /dev/null +++ b/src/SB/Core/x/xNPCBasic.h @@ -0,0 +1,131 @@ +#ifndef XNPCBASIC_H +#define XNPCBASIC_H + +#include "xEnt.h" +#include "xFactory.h" +#include "xShadowSimple.h" +#include "xColor.h" + +enum en_npcperf +{ + eNPCPerfZero, + + // These two are only guesses! Need more info to be sure. + eNPCPerfEnable, + eNPCPerfDisable, +}; + +// Values names in this enum not known at all, it is not present in the dwarf +// debug info. +enum en_npcdcat +{ + eNPCDCAT_Zero, + eNPCDCAT_Seven = 7, + eNPCDCAT_Eight = 8, + eNPCDCAT_Eleven = 11, +}; + +struct xNPCBasic : xEnt, xFactoryInst +{ + // Offset: 0xDC + void (*f_setup)(xEnt*); + void (*f_reset)(xEnt*); + + // Offset: 0xE4 + struct + { + S32 flg_basenpc : 16; + S32 inUpdate : 8; + S32 flg_upward : 8; + } flags1; + + // Offset: 0xE8 + S32 colFreq; + S32 colFreqReset; + + // Offset: 0xF0 + struct + { + U32 flg_colCheck : 8; + U32 flg_penCheck : 8; + U32 flg_unused : 16; + } flags2; + + // Offset: 0xF4 + S32 myNPCType; + + // Offset: 0xF8 + xEntShadow entShadow_embedded; + + // Offset: 0x138 + xShadowSimpleCache simpShadow_embedded; + + xNPCBasic(S32); + + S32 SelfType() const; + void RestoreColFlags() + { + flags2.flg_colCheck = ColChkFlags(); + flags2.flg_penCheck = ColPenFlags(); + chkby = ColChkByFlags(); + penby = ColPenByFlags(); + pflags = PhysicsFlags(); + colFreq = -1; + } + + void DBG_PStatClear(); + void DBG_PStatCont(en_npcperf stat); + void DBG_PStatOn(en_npcperf stat); + S32 DBG_IsNormLog(en_npcdcat input, S32 input2); + void DBG_HaltOnMe(U32, char*); + + // DO NOT CHANGE THE ORDER OF THESE, the order determines the + // vtable layout which needs to remain fixed. + virtual void Init(xEntAsset* asset); + virtual void PostInit(); + virtual void Setup(); + virtual void PostSetup(); + virtual void Reset(); + virtual void Process(xScene* xscn, F32 dt); + virtual void BUpdate(xVec3*); + virtual void NewTime(xScene* xscn, F32 dt); + virtual void Move(xScene* xscn, F32 dt, xEntFrame* frm); + virtual S32 SysEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam, + xBase* toParamWidget, S32* handled); + virtual void Render(); + virtual void Save(xSerial*) const; + virtual void Load(xSerial*); + virtual void CollideReview(); + + /* These most likely return a combination of XENT_COLLTYPE_* values */ + virtual U8 ColChkFlags() const + { + return 0; + } + + virtual U8 ColPenFlags() const + { + return 0; + } + + virtual U8 ColChkByFlags() const + { + return 0; + } + + virtual U8 ColPenByFlags() const + { + return 0; + } + + virtual U8 PhysicsFlags() const + { + return 0; + } + + virtual void Destroy(); +}; + +void NPC_spdBasedColFreq(xNPCBasic* npc, F32 dt); + +#endif diff --git a/src/SB/Core/x/xPad.cpp b/src/SB/Core/x/xPad.cpp new file mode 100644 index 0000000..81b34d6 --- /dev/null +++ b/src/SB/Core/x/xPad.cpp @@ -0,0 +1,122 @@ +#include "xPad.h" + +#include +#include + +S32 xPadInit() +{ + memset(mPad, 0, sizeof(mPad)); + memset(mRumbleList, 0, sizeof(mRumbleList)); + S32 code = iPadInit(); + if (!code) + { + return 0; + } + gPlayerPad = mPad; + return 1; +} + +// WIP. +_tagxPad* xPadEnable(S32 idx) +{ + _tagxPad* p = mPad + idx; + if (p->state == ePad_Disabled && idx == 0) + { + p = iPadEnable(mPad + idx, 0); + } + return p; +} + +void xPadRumbleEnable(S32 idx, S32 enable) +{ + _tagxPad* p = mPad + idx; + if (p->state != 2) + { + enable = 0; + } + if (enable) + { + if (p->flags & 4) + { + p->flags |= 8; + } + } + else + { + if (p->flags & 8) + { + p->flags ^= 8; + xPadDestroyRumbleChain(mPad + idx); + } + } +} + +void xPadAnalogIsDigital(S32 idx, S32 enable) +{ + if (idx != 0) + return; + + _tagxPad* pad = &mPad[idx]; + + if (enable) + { + pad->flags |= 0x10; + } + else + { + pad->flags &= ~0x10; + } + + if (pad->al2d_timer >= 0.35f) + { + pad->al2d_timer = 0.35f; + } + + if (pad->ar2d_timer >= 0.35f) + { + pad->ar2d_timer = 0.35f; + } + + if (pad->d_timer >= 0.35f) + { + pad->d_timer = 0.35f; + } +} + +void xPadKill() +{ + iPadKill(); +} + +// WIP. +_tagxRumble* xPadGetRumbleSlot() +{ + _tagxRumble* rum = mRumbleList; + for (S32 i = 0x20; i > 0; i--) + { + if (rum->active == 0) + { + memset(rum, 0, sizeof(_tagxRumble)); + return rum; + } + rum++; + } + return NULL; +} + +void xPadDestroyRumbleChain(_tagxPad* pad) +{ + iPadStopRumble(pad); + _tagxRumble* curr = pad->rumble_head.next; + while (curr != NULL) + { + memset(curr, 0, sizeof(_tagxRumble)); + curr = curr->next; + } + pad->rumble_head.next = NULL; +} + +void xPadDestroyRumbleChain(S32 idx) +{ + xPadDestroyRumbleChain(mPad + idx); +} diff --git a/src/SB/Core/x/xPad.h b/src/SB/Core/x/xPad.h new file mode 100644 index 0000000..c4ef619 --- /dev/null +++ b/src/SB/Core/x/xPad.h @@ -0,0 +1,113 @@ +#ifndef XPAD_H +#define XPAD_H + +#include "xRumble.h" +#include "xMath2.h" +#include "iPad.h" + +enum _tagPadState +{ + ePad_Disabled, + ePad_DisabledError, + ePad_Enabled, + ePad_Missing, + ePad_Total +}; + +enum _tagPadInit +{ + ePadInit_Open1, + ePadInit_WaitStable2, + ePadInit_EnableAnalog3, + ePadInit_EnableAnalog3LetsAllPissOffChris, + ePadInit_EnableRumble4, + ePadInit_EnableRumbleTest5, + ePadInit_PressureS6, + ePadInit_PressureSTest7, + ePadInit_Complete8a, + ePadInit_Complete8b, + ePadInit_Finished9 +}; + +struct _tagPadAnalog +{ + S8 x; + S8 y; +}; + +struct analog_data +{ + xVec2 offset; + xVec2 dir; + F32 mag; + F32 ang; +}; + +struct _tagxPad +{ + S8 value[22]; + + // Offset: 0x16 + S8 last_value[22]; + + // Offset: 0x2C + U32 on; + + // Offset: 0x30 + U32 pressed; + U32 released; + + // Offset: 0x38 + _tagPadAnalog analog1; + _tagPadAnalog analog2; + _tagPadState state; + U32 flags; + _tagxRumble rumble_head; + S16 port; + S16 slot; + _tagiPad context; + F32 al2d_timer; + F32 ar2d_timer; + F32 d_timer; + F32 up_tmr[22]; + F32 down_tmr[22]; + analog_data analog[2]; +}; + +// Named after PS2 buttons to match the "PadPress*" events +#define XPAD_BUTTON_START 0x1 +#define XPAD_BUTTON_SELECT 0x2 +#define XPAD_BUTTON_UP 0x10 +#define XPAD_BUTTON_RIGHT 0x20 +#define XPAD_BUTTON_DOWN 0x40 +#define XPAD_BUTTON_LEFT 0x80 +#define XPAD_BUTTON_L1 0x100 // L on gamecube +#define XPAD_BUTTON_L2 0x200 +#define XPAD_BUTTON_R1 0x1000 // R on gamecube +#define XPAD_BUTTON_R2 0x2000 +#define XPAD_BUTTON_X 0x10000 // A on gamecube +#define XPAD_BUTTON_O 0x20000 // X on gamecube +#define XPAD_BUTTON_SQUARE 0x40000 // Y on gamecube +#define XPAD_BUTTON_TRIANGLE 0x80000 // B on gamecube + +// GameCube +#define XPAD_BUTTON_Z 0x100000 + +extern _tagxPad mPad[4]; +extern _tagxRumble mRumbleList[32]; +extern _tagxPad* gPlayerPad; + +S32 xPadInit(); +_tagxPad* xPadEnable(S32 idx); +void xPadRumbleEnable(S32 idx, S32 enable); +S32 xPadUpdate(S32 idx, F32 time_passed); +void xPadNormalizeAnalog(_tagxPad& pad, S32 inner_zone, S32 outer_zone); +void xPadKill(); +_tagxRumble* xPadGetRumbleSlot(); +void xPadDestroyRumbleChain(_tagxPad* pad); +void xPadDestroyRumbleChain(S32 idx); +S32 xPadAddRumble(S32 idx, _tagRumbleType type, F32 time, S32 replace, U32 fxflags); + +void xPadAnalogIsDigital(F32, F32); + +#endif diff --git a/src/SB/Core/x/xPar.cpp b/src/SB/Core/x/xPar.cpp new file mode 100644 index 0000000..91c48bd --- /dev/null +++ b/src/SB/Core/x/xPar.cpp @@ -0,0 +1,97 @@ +#include "xPar.h" + +#include + +#define PAR_POOL_SIZE 2000 + +extern xPar gParPool[PAR_POOL_SIZE]; +extern xPar* gParDead; +extern F32 lbl_803CCF10; // 0.0f +extern F32 lbl_803CCF14; // 255f + +// For some reason, it does not recompare gParDead and assumes the first comparison is valid for all. +void xParMemInit() +{ + for (S32 i = 0; i < PAR_POOL_SIZE; i++) + { + xPar* curr = &gParPool[i]; + curr->m_next = NULL; + curr->m_prev = NULL; + if (gParDead != NULL) + { + gParDead->m_prev = curr; + curr->m_next = gParDead; + } + gParDead = curr; + } +} + +xPar* xParAlloc() +{ + xPar* dead = gParDead; + if (gParDead == NULL) + { + return NULL; + } + if (gParDead->m_next != NULL) + { + gParDead->m_next->m_prev = NULL; + } + xPar** next = &dead->m_next; + gParDead = *next; + *next = NULL; + dead->m_prev = NULL; + return dead; +} + +void xParFree(xPar* par) +{ + if (par->m_next != NULL) + { + par->m_next->m_prev = par->m_prev; + } + if (par->m_prev != NULL) + { + par->m_prev->m_next = par->m_next; + } + if (gParDead != NULL) + { + gParDead->m_prev = par; + } + par->m_next = gParDead; + par->m_prev = NULL; + gParDead = par; +} + +void xParInit(xPar* p) +{ + p->m_pos.x = lbl_803CCF10; + p->m_pos.y = lbl_803CCF10; + p->m_pos.z = lbl_803CCF10; + p->m_vel.x = lbl_803CCF10; + p->m_vel.y = lbl_803CCF10; + p->m_vel.z = lbl_803CCF10; + p->m_size = lbl_803CCF10; + p->m_sizeVel = lbl_803CCF10; + p->m_lifetime = lbl_803CCF10; + p->m_cvel[0] = lbl_803CCF10; + p->m_cvel[1] = lbl_803CCF10; + p->m_cvel[2] = lbl_803CCF10; + p->m_cvel[3] = lbl_803CCF10; + p->m_cfl[0] = lbl_803CCF14; + p->m_cfl[1] = lbl_803CCF14; + p->m_cfl[2] = lbl_803CCF14; + p->m_cfl[3] = lbl_803CCF14; + p->m_c[0] = 0xff; + p->m_c[1] = 0xff; + p->m_c[2] = 0xff; + p->m_c[3] = 0xff; + p->m_flag = 0; + p->m_rotdeg[0] = 0; + p->m_rotdeg[1] = 0; + p->m_rotdeg[2] = 0; + p->m_next = NULL; + p->m_prev = NULL; + p->m_texIdx[0] = 0; + p->m_texIdx[1] = 0; +} diff --git a/src/SB/Core/x/xPar.h b/src/SB/Core/x/xPar.h index 3cee0af..77b0878 100644 --- a/src/SB/Core/x/xPar.h +++ b/src/SB/Core/x/xPar.h @@ -1,176 +1,34 @@ #ifndef XPAR_H #define XPAR_H -#include "xMath.h" -#include "xEnt.h" - -struct xPECircle -{ - F32 radius; - F32 deflection; - xVec3 dir; -}; - -struct xPESphere -{ - F32 radius; -}; - -struct xPERect -{ - F32 x_len; - F32 z_len; -}; - -struct xPELine -{ - xVec3 pos1; - xVec3 pos2; - F32 radius; -}; - -struct xPEVolume -{ - U32 emit_volumeID; -}; - -struct xPEOffsetPoint -{ - xVec3 offset; -}; - -struct xPEVCyl -{ - F32 height; - F32 radius; - F32 deflection; -}; - -struct xPEEntBone -{ - U8 flags; - U8 type; - U8 bone; - U8 pad1; - xVec3 offset; - F32 radius; - F32 deflection; -}; - -struct xPEEntBound -{ - U8 flags; - U8 type; - U8 pad1; - U8 pad2; - F32 expand; - F32 deflection; -}; - -struct xParEmitterAsset : xBaseAsset -{ - U8 emit_flags; - U8 emit_type; - U16 pad; - U32 propID; - union - { - xPECircle e_circle; - xPESphere e_sphere; - xPERect e_rect; - xPELine e_line; - xPEVolume e_volume; - xPEOffsetPoint e_offsetp; - xPEVCyl e_vcyl; - xPEEntBone e_entbone; - xPEEntBound e_entbound; - }; - U32 attachToID; - xVec3 pos; - xVec3 vel; - F32 vel_angle_variation; - U32 cull_mode; - F32 cull_dist_sqr; -}; - -struct xParGroup -{ -}; - -struct xParInterp -{ - F32 val[2]; - U32 interp; - F32 freq; - F32 oofreq; -}; - -struct xParEmitterPropsAsset : xBaseAsset -{ - U32 parSysID; - union - { - xParInterp rate; - xParInterp value[1]; - }; - xParInterp life; - xParInterp size_birth; - xParInterp size_death; - xParInterp color_birth[4]; - xParInterp color_death[4]; - xParInterp vel_scale; - xParInterp vel_angle; - xVec3 vel; - U32 emit_limit; - F32 emit_limit_reset_time; -}; - -struct xParEmitterCustomSettings : xParEmitterPropsAsset -{ - U32 custom_flags; - U32 attachToID; - xVec3 pos; - xVec3 last_emit_position; - xVec3 vel; - xVec3 last_emit_velocity; - F32 vel_angle_variation; - U8 rot[3]; - U8 padding; - F32 radius; - F32 emit_interval_current; - xBase* emit_volume; -}; - -struct xParSys -{ -}; - -struct xParEmitter : xBase -{ - xParEmitterAsset* tasset; - xParGroup* group; - xParEmitterPropsAsset* prop; - U8 rate_mode; - xVec3 last_emit_position; - xVec3 last_emit_velocity; - F32 rate; - F32 rate_time; - F32 rate_fraction; - F32 rate_fraction_cull; - U8 emit_flags; - U8 emit_pad[3]; - U8 rot[3]; - xModelTag tag; - F32 oocull_distance_sqr; - F32 distance_to_cull_sqr; - void* attachTo; - xParSys* parSys; - xBase* emit_volume; - xVec3 last_attach_loc; -}; - -struct zParEmitter : xParEmitter -{ -}; +#include "xMath3.h" + +struct xParEmitterAsset; + +struct xPar +{ + xPar* m_next; + xPar* m_prev; + F32 m_lifetime; + U8 m_c[4]; + xVec3 m_pos; + F32 m_size; + xVec3 m_vel; + F32 m_sizeVel; + U8 m_flag; + U8 m_mode; + U8 m_texIdx[2]; + U8 m_rotdeg[3]; + U8 pad8; + F32 totalLifespan; + xParEmitterAsset* m_asset; + F32 m_cvel[4]; + F32 m_cfl[4]; +}; + +void xParMemInit(); +xPar* xParAlloc(); +void xParFree(xPar* par); +void xParInit(xPar* p); #endif diff --git a/src/SB/Core/x/xParCmd.cpp b/src/SB/Core/x/xParCmd.cpp new file mode 100644 index 0000000..572e9a2 --- /dev/null +++ b/src/SB/Core/x/xParCmd.cpp @@ -0,0 +1,800 @@ +#include "xParCmd.h" + +#include "xParGroup.h" +#include "xVec3Inlines.h" +#include "xMath.h" +#include "xMathInlines.h" + +struct xCmdInfo +{ + U32 type; + U32 size; + xParCmdUpdateFunc func; +}; + +static xCmdInfo sCmdInfo[XPARCMD_TYPE_COUNT] = {}; + +extern F32 _658_0; +extern F32 _691; +extern F32 _760; +extern F32 _772; +extern F32 _812; +extern F32 _830_1; +extern F32 _831_0; +extern F32 _857_0; +extern F32 _858; +extern F32 _1075; +extern F32 _1076; +extern F32 _1077; + +void xParCmdInit() +{ + xParCmdRegister(XPARCMD_TYPE_MOVE, sizeof(xParCmdMove), xParCmdMove_Update); + xParCmdRegister(XPARCMD_TYPE_MOVERANDOM, sizeof(xParCmdMove), xParCmdMoveRandom_Update); + xParCmdRegister(XPARCMD_TYPE_ACCELERATE, sizeof(xParCmdAccelerate), xParCmdAccelerate_Update); + xParCmdRegister(XPARCMD_TYPE_VELOCITYAPPLY, sizeof(xParCmdAsset), xParCmdVelocityApply_Update); + xParCmdRegister(XPARCMD_TYPE_UNK5, sizeof(xParCmdUnk5), NULL); + xParCmdRegister(XPARCMD_TYPE_KILLSLOW, sizeof(xParCmdKillSlow), xParCmdKillSlow_Update); + xParCmdRegister(XPARCMD_TYPE_FOLLOW, sizeof(xParCmdFollow), xParCmdFollow_Update); + xParCmdRegister(XPARCMD_TYPE_ORBITPOINT, sizeof(xParCmdOrbitPoint), xParCmdOrbitPoint_Update); + xParCmdRegister(XPARCMD_TYPE_ORBITLINE, sizeof(xParCmdOrbitLine), xParCmdOrbitLine_Update); + xParCmdRegister(XPARCMD_TYPE_MOVERANDOMPAR, sizeof(xParCmdMoveRandomPar), + xParCmdMoveRandomPar_Update); + xParCmdRegister(XPARCMD_TYPE_SCALE3RDPOLYREG, sizeof(xParCmdScale3rdPolyReg), + xParCmdScale3rdPolyReg_Update); + xParCmdRegister(XPARCMD_TYPE_TEX, sizeof(xParCmdTex), xParCmdTex_Update); + xParCmdRegister(XPARCMD_TYPE_TEXANIM, sizeof(xParCmdTexAnim), xParCmdTexAnim_Update); + xParCmdRegister(XPARCMD_TYPE_RANDOMVELOCITYPAR, sizeof(xParCmdRandomVelocityPar), + xParCmdRandomVelocityPar_Update); + xParCmdRegister(XPARCMD_TYPE_AGE, sizeof(xParCmdAge), xParCmdAge_Update); + xParCmdRegister(XPARCMD_TYPE_ALPHA3RDPOLYREG, sizeof(xParCmdAlpha3rdPolyReg), + xParCmdAlpha3rdPolyReg_Update); + xParCmdRegister(XPARCMD_TYPE_APPLYWIND, sizeof(xParCmdApplyWind), xParCmdApplyWind_Update); + xParCmdRegister(XPARCMD_TYPE_ROTPAR, sizeof(xParCmdRotPar), xParCmdRotPar_Update); + xParCmdRegister(XPARCMD_TYPE_ROTATEAROUND, sizeof(xParCmdRotateAround), + xParCmdRotateAround_Update); + xParCmdRegister(XPARCMD_TYPE_SMOKEALPHA, sizeof(xParCmdSmokeAlpha), xParCmdSmokeAlpha_Update); + xParCmdRegister(XPARCMD_TYPE_SCALE, sizeof(xParCmdScale), xParCmdScale_Update); + xParCmdRegister(XPARCMD_TYPE_COLLIDEFALL, sizeof(xParCmdCollideFall), + xParCmdCollideFall_Update); + xParCmdRegister(XPARCMD_TYPE_COLLIDEFALLSTICKY, sizeof(xParCmdCollideFallSticky), + xParCmdCollideFallSticky_Update); + xParCmdRegister(XPARCMD_TYPE_SHAPER, sizeof(xParCmdShaperData), xParCmd_Shaper_Update); + xParCmdRegister(XPARCMD_TYPE_ALPHAINOUT, sizeof(xParCmdAlphaInOutData), + xParCmd_AlphaInOut_Update); + xParCmdRegister(XPARCMD_TYPE_SIZEINOUT, sizeof(xParCmdSizeInOutData), xParCmd_SizeInOut_Update); + xParCmdRegister(XPARCMD_TYPE_DAMPENSPEED, sizeof(xParCmdDampenData), + xParCmd_DampenSpeed_Update); +} + +void xParCmdRegister(U32 parType, U32 size, xParCmdUpdateFunc func) +{ + sCmdInfo[parType].type = parType; + sCmdInfo[parType].size = size; + sCmdInfo[parType].func = func; +} + +U32 xParCmdGetSize(U32 parType) +{ + for (S32 i = 0; i < XPARCMD_TYPE_COUNT; i++) + { + if (sCmdInfo[i].type == parType) + { + return sCmdInfo[i].size; + } + } + + return 0; +} + +xParCmdUpdateFunc xParCmdGetUpdateFunc(U32 parType) +{ + for (S32 i = 0; i < XPARCMD_TYPE_COUNT; i++) + { + if (sCmdInfo[i].type == parType) + { + return sCmdInfo[i].func; + } + } + + return NULL; +} + +void xParCmdKillSlow_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + xParCmdKillSlow* cmd = (xParCmdKillSlow*)c->tasset; + F32 speedLimit = cmd->speedLimitSqr * dt; + + if (cmd->kill_less_than) + { + while (p) + { + if (xVec3Length2(&p->m_vel) < speedLimit) + { + p->m_lifetime = _658_0; + } + + p = p->m_next; + } + } + else + { + while (p) + { + if (xVec3Length2(&p->m_vel) > speedLimit) + { + p->m_lifetime = _658_0; + } + + p = p->m_next; + } + } +} + +void xParCmdAge_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + F32 age_rate = ((xParCmdAge*)c->tasset)->unknown * dt; + + while (p) + { + p->m_lifetime -= age_rate; + p = p->m_next; + } +} + +void xParCmdFollow_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + xParCmdFollow* cmd = (xParCmdFollow*)c->tasset; + F32 mdt = cmd->gravity * dt; + + while (p && p->m_next) + { + xVec3 var_38; + + xVec3Sub(&var_38, &p->m_next->m_pos, &p->m_pos); + + F32 f31 = xVec3Length2(&var_38); + F32 f1 = xVec3LengthFast(var_38.x, var_38.y, var_38.z); + + F32 force = mdt / (f1 * (f31 + cmd->epsilon)); + + p->m_vel.x += var_38.x * force; + p->m_vel.y += var_38.y * force; + p->m_vel.z += var_38.z * force; + + p = p->m_next; + } +} + +void xParCmdOrbitPoint_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + xParCmdOrbitPoint* cmd = (xParCmdOrbitPoint*)c->tasset; + F32 mdt = cmd->gravity * dt; + + while (p) + { + xVec3 var_38; + + xVec3Sub(&var_38, &cmd->center, &p->m_pos); + + F32 f31 = xVec3Length2(&var_38); + + if (f31 < cmd->maxRadiusSqr) + { + F32 f1 = xVec3LengthFast(var_38.x, var_38.y, var_38.z); + + F32 force = mdt / (f1 + (f31 + cmd->epsilon)); + + p->m_vel.x += var_38.x * force; + p->m_vel.y += var_38.y * force; + p->m_vel.z += var_38.z * force; + } + + p = p->m_next; + } +} + +void xParCmdOrbitLine_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + xParCmdOrbitLine* cmd = (xParCmdOrbitLine*)c->tasset; + F32 mdt = cmd->gravity * dt; + + while (p) + { + xVec3 var_34, var_40, var_4C, var_58; + + xVec3Sub(&var_34, &p->m_pos, &cmd->p); + xVec3Cross(&var_4C, &var_34, &cmd->axis); + xVec3Cross(&var_40, &cmd->axis, &var_4C); + xVec3Sub(&var_58, &var_40, &var_34); + + F32 f31 = xVec3Length2(&var_58); + + if (f31 < cmd->maxRadiusSqr) + { + F32 f1 = xVec3LengthFast(var_58.x, var_58.y, var_58.z); + + F32 force = mdt / (f1 + (f31 + cmd->epsilon)); + + p->m_vel.x += var_58.x * force; + p->m_vel.y += var_58.y * force; + p->m_vel.z += var_58.z * force; + } + + p = p->m_next; + } +} + +void xParCmdAccelerate_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p; + xParCmdAccelerate* cmd = (xParCmdAccelerate*)c->tasset; + + xVec3 var_28; + var_28 = cmd->acc; + + xVec3SMulBy(&var_28, dt); + + p = ps->m_root; + + while (p) + { + p->m_vel.x += var_28.x; + p->m_vel.y += var_28.y; + p->m_vel.z += var_28.z; + + p = p->m_next; + } +} + +void xParCmdMove_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p; + xParCmdMove* cmd = (xParCmdMove*)c->tasset; + + xVec3 var_28; + var_28 = cmd->dir; + + xVec3SMulBy(&var_28, dt); + + p = ps->m_root; + + while (p) + { + xVec3Add(&p->m_pos, &p->m_pos, &var_28); + + p = p->m_next; + } +} + +void xParCmdMoveRandom_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p; + xParCmdMove* cmd = (xParCmdMove*)c->tasset; + + xVec3 var_28; + var_28 = cmd->dir; + + var_28.x *= _760 * xurand(); + var_28.y *= _760 * xurand(); + var_28.z *= _760 * xurand(); + + xVec3Sub(&var_28, &var_28, &cmd->dir); + xVec3SMulBy(&var_28, dt); + + p = ps->m_root; + + while (p) + { + xVec3Add(&p->m_pos, &p->m_pos, &var_28); + + p = p->m_next; + } +} + +void xParCmdMoveRandomPar_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + xParCmdMoveRandomPar* cmd = (xParCmdMoveRandomPar*)c->tasset; + F32 f31 = cmd->dim.x * (dt * _772); + F32 f30 = cmd->dim.z * (dt * _772); + + while (p) + { + p->m_pos.x += f31 * (xurand() - _772); + p->m_pos.z += f30 * (xurand() - _772); + + p = p->m_next; + } +} + +void xParCmdScale3rdPolyReg_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ +} + +void xParCmdSmokeAlpha_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ +} + +void xParCmdScale_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ +} + +void xParCmdAlpha3rdPolyReg_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ +} + +void xParCmdRandomVelocityPar_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + xParCmdRandomVelocityPar* cmd = (xParCmdRandomVelocityPar*)c->tasset; + F32 f31 = cmd->x * dt; + F32 f30 = cmd->y * dt; + F32 f29 = cmd->z * dt; + + while (p) + { + xMat3x3 var_88; + + F32 y = _760 * (f31 * xurand()) - f31; + F32 x = _760 * (f30 * xurand()) - f30; + F32 z = _760 * (f29 * xurand()) - f29; + + xMat3x3Euler(&var_88, x, y, z); + xMat3x3LMulVec(&p->m_vel, &var_88, &p->m_vel); + + p = p->m_next; + } +} + +void xParCmdApplyWind_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + + // non-matching: f2 and f3 are combined into one register + F32 f2 = _812 * (((xParCmdApplyWind*)c->tasset)->unknown * dt); + F32 f3 = _812 * (((xParCmdApplyWind*)c->tasset)->unknown * dt); + + while (p) + { + p->m_vel.x += f2; + p->m_vel.z += f3; + + p = p->m_next; + } +} + +void xParCmdRotPar_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + xParCmdRotPar* cmd = (xParCmdRotPar*)c->tasset; + F32 f30 = _830_1 * ((cmd->max.x - cmd->min.x) / _831_0); + F32 f29 = _830_1 * ((cmd->max.y - cmd->min.y) / _831_0); + F32 f28 = _830_1 * ((cmd->max.z - cmd->min.z) / _831_0); + F32 f27 = _830_1 * (cmd->min.x / _831_0); + F32 f26 = _830_1 * (cmd->min.y / _831_0); + F32 f25 = _830_1 * (cmd->min.z / _831_0); + + while (p) + { + p->m_rotdeg[0] += (U8)(dt * (f30 * xurand() + f27)); + p->m_rotdeg[1] += (U8)(dt * (f29 * xurand() + f26)); + p->m_rotdeg[2] += (U8)(dt * (f28 * xurand() + f25)); + + p = p->m_next; + } +} + +void xParCmdVelocityApply_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + + while (p) + { + xVec3Add(&p->m_pos, &p->m_pos, &p->m_vel); + + p = p->m_next; + } +} + +void xParCmdRotateAround_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p = ps->m_root; + xParCmdRotateAround* cmd = (xParCmdRotateAround*)c->tasset; + + F32 yaw = _857_0 * (dt * cmd->yaw) / _858; + F32 radius_growth = dt * cmd->radius_growth; + + while (p) + { + xVec3 at; + xVec3Sub(&at, &cmd->pos, &p->m_pos); + + at.y = _691; + + xMat3x3 lookmat; + + F32 radius = xMat3x3LookVec(&lookmat, &at); + + xVec3 angles; + xMat3x3GetEuler(&lookmat, &angles); + + angles.x += yaw; + + xMat3x3 rotmat; + xMat3x3Euler(&rotmat, angles.x, angles.y, angles.z); + + xVec3 var_BC, var_C8; + + // non-matching: f0 and f1 swapped + + var_BC.x = _691; + var_BC.y = _691; + var_BC.z = radius + radius_growth; + + xMat3x3RMulVec(&var_C8, &rotmat, &var_BC); + + p->m_pos.x = var_C8.x + cmd->pos.x; + p->m_pos.z = var_C8.z + cmd->pos.z; + + p = p->m_next; + } +} + +void xParCmdTex_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ +} + +void xParCmdTexAnim_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p; + xParCmdTexAnim* cmd = (xParCmdTexAnim*)c->tasset; + xParCmdTex* tex = ps->m_cmdTex; + + if (!tex) + { + return; + } + + if (cmd->throttle_time > _691) + { + cmd->throttle_time_elapsed -= dt; + + if (cmd->throttle_time_elapsed > _691) + { + return; + } + + cmd->throttle_time_elapsed = cmd->throttle_time; + } + + p = ps->m_root; + + if (cmd->anim_mode == 0) + { + while (p) + { + p->m_texIdx[0] = xrand() % tex->cols; + p->m_texIdx[1] = xrand() % tex->rows; + + p = p->m_next; + } + } + else if (cmd->anim_mode == 1) + { + if (tex->cols > 1) + { + while (p) + { + p->m_texIdx[0]++; + + if (p->m_texIdx[0] >= tex->cols) + { + p->m_texIdx[0] = 0; + + if (cmd->anim_wrap_mode == 1) + { + p->m_texIdx[1]++; + + if (p->m_texIdx[1] >= tex->rows) + { + p->m_texIdx[1] = 0; + } + } + else if (cmd->anim_wrap_mode == 2) + { + if (p->m_texIdx[1] == 0) + { + p->m_texIdx[1] = tex->rows - 1; + } + else + { + p->m_texIdx[1]--; + } + } + else if (cmd->anim_wrap_mode == 3) + { + p->m_texIdx[1]++; + + if (p->m_texIdx[1] >= tex->rows) + { + p->m_texIdx[1] = tex->rows - 1; + p->m_texIdx[0] = tex->cols - 1; + } + } + } + + p = p->m_next; + } + } + } + else if (cmd->anim_mode == 2) + { + if (tex->cols > 1) + { + while (p) + { + if (p->m_texIdx[0] == 0) + { + p->m_texIdx[0] = tex->cols - 1; + + if (cmd->anim_wrap_mode == 1) + { + p->m_texIdx[1]++; + + if (p->m_texIdx[1] >= tex->rows) + { + p->m_texIdx[1] = 0; + } + } + else if (cmd->anim_wrap_mode == 2) + { + if (p->m_texIdx[1] == 0) + { + p->m_texIdx[1] = tex->rows - 1; + } + else + { + p->m_texIdx[1]--; + } + } + } + else + { + p->m_texIdx[0]--; + } + + p = p->m_next; + } + } + } + else if (cmd->anim_mode == 3) + { + if (tex->rows > 1) + { + while (p) + { + if (p->m_texIdx[1] == 0) + { + p->m_texIdx[1] = tex->rows - 1; + + if (cmd->anim_wrap_mode == 1) + { + p->m_texIdx[0]++; + + if (p->m_texIdx[0] >= tex->cols) + { + p->m_texIdx[0] = 0; + } + } + else if (cmd->anim_wrap_mode == 2) + { + if (p->m_texIdx[0] == 0) + { + p->m_texIdx[0] = tex->cols - 1; + } + else + { + p->m_texIdx[0]--; + } + } + } + else + { + p->m_texIdx[1]--; + } + + p = p->m_next; + } + } + } + else if (cmd->anim_mode == 4) + { + if (tex->rows > 1) + { + while (p) + { + p->m_texIdx[1]++; + + if (p->m_texIdx[1] >= tex->rows) + { + p->m_texIdx[1] = 0; + + if (cmd->anim_wrap_mode == 1) + { + p->m_texIdx[0]++; + + if (p->m_texIdx[0] >= tex->cols) + { + p->m_texIdx[0] = 0; + } + } + else if (cmd->anim_wrap_mode == 2) + { + if (p->m_texIdx[0] == 0) + { + p->m_texIdx[0] = tex->cols - 1; + } + else + { + p->m_texIdx[0]--; + } + } + } + + p = p->m_next; + } + } + } +} + +void xParCmdCollideFall_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xParCmdCollideFall& cmd = *(xParCmdCollideFall*)c->tasset; + xPar* p = ps->m_root; + + while (p) + { + F32& loc = p->m_pos.y; + F32& vel = p->m_vel.y; + F32 dloc = cmd.y - loc; + + if (dloc < _691) + { + // lol + } + else + { + loc = dloc * cmd.bounce + cmd.y; + + if (vel < _691) + { + vel = -vel * cmd.bounce; + } + } + + p = p->m_next; + } +} + +void xParCmdCollideFallSticky_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xParCmdCollideFallSticky& cmd = *(xParCmdCollideFallSticky*)c->tasset; + F32 xzdamp = _812 - cmd.sticky; + xPar* p = ps->m_root; + + while (p) + { + F32& loc = p->m_pos.y; + F32& vel = p->m_vel.y; + F32 dloc = cmd.y - loc; + + if (dloc < _691) + { + // lol + } + else + { + loc = dloc * cmd.bounce + cmd.y; + + if (vel < _691) + { + vel = -vel * cmd.bounce; + } + + p->m_vel.x *= xzdamp; + p->m_vel.z *= xzdamp; + } + + p = p->m_next; + } +} + +void xParCmd_DampenSpeed_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p; + xParCmdDampenData* cmd = (xParCmdDampenData*)c->tasset; + + if (cmd->enabled) + { + p = ps->m_root; + + F32 damp = dt * cmd->dampSpeed; + + while (p) + { + xVec3AddScaled(&p->m_vel, &p->m_vel, damp); + + p = p->m_next; + } + } +} + +void xParCmd_SizeInOut_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + xPar* p; + xParCmdSizeInOutData* cmd = (xParCmdSizeInOutData*)c->tasset; + + if (cmd->enabled) + { + p = ps->m_root; + + S32 i, seg; + F32 slope_size[3]; + + slope_size[0] = _1075 * (cmd->custSize[1] - cmd->custSize[0]); + slope_size[1] = _1075 * (cmd->custSize[2] - cmd->custSize[1]); + slope_size[2] = _1075 * (cmd->custSize[3] - cmd->custSize[2]); + + while (p) + { + // non-matching: there is definitely a clamp happening here, but it isn't using the CLAMP macro. + F32 frac = CLAMP(_812 - p->m_lifetime / p->totalLifespan, _691, _812); + + if (frac < _1076) + { + seg = 0; + } + else if (frac < _1077) + { + seg = 1; + } + else + { + seg = 2; + } + + for (S32 i = seg; i > 0; i--) + { + // non-matching: _1076 is cached before loop + frac -= _1076; + } + + p->m_size = frac * slope_size[seg] + cmd->custSize[seg]; + + p = p->m_next; + } + } +} + +void xParCmd_AlphaInOut_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + // todo: this is very similar to xParCmd_SizeInOut_Update +} + +void xParCmd_Shaper_Update(xParCmd* c, xParGroup* ps, F32 dt) +{ + // todo: part of this is very similar to xParCmd_SizeInOut_Update +} + +WEAK F32 xVec3LengthFast(F32 x, F32 y, F32 z) +{ + F32 len; + xsqrtfast(len, SQR(x) + SQR(y) + SQR(z)); + return len; +} diff --git a/src/SB/Core/x/xParCmd.h b/src/SB/Core/x/xParCmd.h new file mode 100644 index 0000000..2f6660e --- /dev/null +++ b/src/SB/Core/x/xParCmd.h @@ -0,0 +1,366 @@ +#ifndef XPARCMD_H +#define XPARCMD_H + +#include "xParGroup.h" + +#define XPARCMD_TYPE_MOVE 0 +#define XPARCMD_TYPE_MOVERANDOM 1 +#define XPARCMD_TYPE_ACCELERATE 2 +#define XPARCMD_TYPE_VELOCITYAPPLY 3 +#define XPARCMD_TYPE_JET 4 +#define XPARCMD_TYPE_UNK5 5 +#define XPARCMD_TYPE_KILLSLOW 6 +#define XPARCMD_TYPE_FOLLOW 7 +#define XPARCMD_TYPE_ORBITPOINT 8 +#define XPARCMD_TYPE_ORBITLINE 9 +#define XPARCMD_TYPE_MOVERANDOMPAR 10 +#define XPARCMD_TYPE_SCALE3RDPOLYREG 11 +#define XPARCMD_TYPE_TEX 12 +#define XPARCMD_TYPE_TEXANIM 13 +#define XPARCMD_TYPE_PLAYERCOLLISION 14 +#define XPARCMD_TYPE_RANDOMVELOCITYPAR 15 +#define XPARCMD_TYPE_CUSTOM 16 +#define XPARCMD_TYPE_KILLDISTANCE 17 +#define XPARCMD_TYPE_AGE 18 +#define XPARCMD_TYPE_ALPHA3RDPOLYREG 19 +#define XPARCMD_TYPE_APPLYWIND 20 +#define XPARCMD_TYPE_ROTPAR 21 +#define XPARCMD_TYPE_APPLYCAMMAT 22 +#define XPARCMD_TYPE_ROTATEAROUND 23 +#define XPARCMD_TYPE_SMOKEALPHA 24 +#define XPARCMD_TYPE_SCALE 25 +#define XPARCMD_TYPE_CLIPVOLUMES 26 +#define XPARCMD_TYPE_ANIMALMAGENTISM 27 +#define XPARCMD_TYPE_DAMAGEPLAYER 28 +#define XPARCMD_TYPE_COLLIDEFALL 29 +#define XPARCMD_TYPE_SHAPER 30 +#define XPARCMD_TYPE_ALPHAINOUT 31 +#define XPARCMD_TYPE_SIZEINOUT 32 +#define XPARCMD_TYPE_DAMPENSPEED 33 +#define XPARCMD_TYPE_COLLIDEFALLSTICKY 34 +#define XPARCMD_TYPE_COUNT 35 + +struct xParCmdAsset +{ + U32 type; + U8 enabled; + U8 mode; + U8 pad[2]; +}; + +struct xParCmd +{ + U32 flag; + xParCmdAsset* tasset; +}; + +struct xParGroup; + +typedef void (*xParCmdUpdateFunc)(xParCmd* c, xParGroup* ps, F32 dt); + +void xParCmdInit(); +void xParCmdRegister(U32 parType, U32 size, xParCmdUpdateFunc func); +U32 xParCmdGetSize(U32 parType); +xParCmdUpdateFunc xParCmdGetUpdateFunc(U32 parType); + +// XPARCMD_TYPE_MOVE +void xParCmdMove_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdMove : xParCmdAsset +{ + xVec3 dir; +}; + +// XPARCMD_TYPE_MOVERANDOM +void xParCmdMoveRandom_Update(xParCmd* c, xParGroup* ps, F32 dt); + +// XPARCMD_TYPE_ACCELERATE +void xParCmdAccelerate_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdAccelerate : xParCmdAsset +{ + xVec3 acc; +}; + +// XPARCMD_TYPE_VELOCITYAPPLY +void xParCmdVelocityApply_Update(xParCmd* c, xParGroup* ps, F32 dt); + +// XPARCMD_TYPE_JET +void xParCmdJet_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdJet : xParCmdAsset +{ + xVec3 center; + xVec3 acc; + F32 gravity; + F32 epsilon; + F32 radiusSqr; +}; + +// XPARCMD_TYPE_UNK5 +struct xParCmdUnk5 : xParCmdAsset // not in dwarf +{ + S32 unknown; +}; + +// XPARCMD_TYPE_KILLSLOW +void xParCmdKillSlow_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdKillSlow : xParCmdAsset +{ + F32 speedLimitSqr; + U32 kill_less_than; +}; + +// XPARCMD_TYPE_FOLLOW +void xParCmdFollow_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdFollow : xParCmdAsset +{ + F32 gravity; + F32 epsilon; +}; + +// XPARCMD_TYPE_ORBITPOINT +void xParCmdOrbitPoint_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdOrbitPoint : xParCmdAsset +{ + xVec3 center; + F32 gravity; + F32 epsilon; + F32 maxRadiusSqr; +}; + +// XPARCMD_TYPE_ORBITLINE +void xParCmdOrbitLine_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdOrbitLine : xParCmdAsset +{ + xVec3 p; + xVec3 axis; + F32 gravity; + F32 epsilon; + F32 maxRadiusSqr; +}; + +// XPARCMD_TYPE_MOVERANDOMPAR +void xParCmdMoveRandomPar_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdMoveRandomPar : xParCmdAsset +{ + xVec3 dim; +}; + +// XPARCMD_TYPE_SCALE3RDPOLYREG +void xParCmdScale3rdPolyReg_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdScale3rdPolyReg : xParCmdAsset // not in dwarf +{ + S32 unknown[4]; +}; + +// XPARCMD_TYPE_TEX +void xParCmdTex_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdTex : xParCmdAsset +{ + F32 x1; + F32 y1; + F32 x2; + F32 y2; + U8 birthMode; + U8 rows; + U8 cols; + U8 unit_count; + F32 unit_width; + F32 unit_height; +}; + +// XPARCMD_TYPE_TEXANIM +void xParCmdTexAnim_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdTexAnim : xParCmdAsset +{ + U8 anim_mode; + U8 anim_wrap_mode; + U8 pad_anim; + U8 throttle_spd_less_than; + F32 throttle_spd_sqr; + F32 throttle_time; + F32 throttle_time_elapsed; +}; + +// XPARCMD_TYPE_PLAYERCOLLISION +void xParCmdPlayerCollision_Update(xParCmd* c, xParGroup* ps, F32 dt); + +// XPARCMD_TYPE_RANDOMVELOCITYPAR +void xParCmdRandomVelocityPar_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdRandomVelocityPar : xParCmdAsset +{ + F32 x; + F32 y; + F32 z; +}; + +// XPARCMD_TYPE_CUSTOM +void xParCmdCustom_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdCustom : xParCmdAsset // not in dwarf +{ + U32 unknown; +}; + +void xParCmdCustom_Grass_Update(xParCmd* c, xParGroup* ps, F32 dt); + +// XPARCMD_TYPE_KILLDISTANCE +void xParCmdKillDistance_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdKillDistance : xParCmdAsset +{ + F32 dSqr; + U32 kill_greater_than; +}; + +// XPARCMD_TYPE_AGE +void xParCmdAge_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdAge : xParCmdAsset // not in dwarf +{ + F32 unknown; +}; + +// XPARCMD_TYPE_ALPHA3RDPOLYREG +void xParCmdAlpha3rdPolyReg_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdAlpha3rdPolyReg : xParCmdAsset // not in dwarf +{ + S32 unknown[4]; +}; + +// XPARCMD_TYPE_APPLYWIND +void xParCmdApplyWind_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdApplyWind : xParCmdAsset // not in dwarf +{ + F32 unknown; +}; + +// XPARCMD_TYPE_ROTPAR +void xParCmdRotPar_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdRotPar : xParCmdAsset +{ + xVec3 min; + xVec3 max; +}; + +// XPARCMD_TYPE_APPLYCAMMAT +void xParCmdApplyCamMat_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdApplyCamMat : xParCmdAsset +{ + xVec3 apply; +}; + +// XPARCMD_TYPE_ROTATEAROUND +void xParCmdRotateAround_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdRotateAround : xParCmdAsset +{ + xVec3 pos; + F32 unused1; + F32 radius_growth; + F32 yaw; +}; + +// XPARCMD_TYPE_SMOKEALPHA +void xParCmdSmokeAlpha_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdSmokeAlpha : xParCmdAsset // not in dwarf +{ + S32 unknown; +}; + +// XPARCMD_TYPE_SCALE +void xParCmdScale_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdScale : xParCmdAsset // not in dwarf +{ + S32 unknown; +}; + +// XPARCMD_TYPE_CLIPVOLUMES +void xParCmdClipVolumes_Update(xParCmd* c, xParGroup* ps, F32 dt); + +// XPARCMD_TYPE_ANIMALMAGENTISM +void xParCmdAnimalMagentism_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdAnimalMagnetism : xParCmdAsset // not in dwarf +{ + F32 unknown; +}; + +// XPARCMD_TYPE_DAMAGEPLAYER +void xParCmdDamagePlayer_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdDamagePlayer : xParCmdAsset +{ + S32 damage; + S32 granular; +}; + +// XPARCMD_TYPE_COLLIDEFALL +void xParCmdCollideFall_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdCollideFall : xParCmdAsset +{ + F32 y; + F32 bounce; +}; + +// XPARCMD_TYPE_SHAPER +void xParCmd_Shaper_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdShaperData : xParCmdAsset +{ + F32 custAlpha[4]; + F32 custSize[4]; + F32 dampSpeed; + F32 gravity; +}; + +// XPARCMD_TYPE_ALPHAINOUT +void xParCmd_AlphaInOut_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdAlphaInOutData : xParCmdAsset +{ + F32 custAlpha[4]; +}; + +// XPARCMD_TYPE_SIZEINOUT +void xParCmd_SizeInOut_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdSizeInOutData : xParCmdAsset +{ + F32 custSize[4]; +}; + +// XPARCMD_TYPE_DAMPENSPEED +void xParCmd_DampenSpeed_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdDampenData : xParCmdAsset +{ + F32 dampSpeed; +}; + +// XPARCMD_TYPE_COLLIDEFALLSTICKY +void xParCmdCollideFallSticky_Update(xParCmd* c, xParGroup* ps, F32 dt); + +struct xParCmdCollideFallSticky : xParCmdCollideFall +{ + F32 sticky; +}; + +#endif diff --git a/src/SB/Core/x/xParEmitter.cpp b/src/SB/Core/x/xParEmitter.cpp new file mode 100644 index 0000000..debde9e --- /dev/null +++ b/src/SB/Core/x/xParEmitter.cpp @@ -0,0 +1,3 @@ +#include "xParEmitter.h" + +#include diff --git a/src/SB/Core/x/xParEmitter.h b/src/SB/Core/x/xParEmitter.h new file mode 100644 index 0000000..7a208a4 --- /dev/null +++ b/src/SB/Core/x/xParEmitter.h @@ -0,0 +1,113 @@ +#ifndef XPAREMITTER_H +#define XPAREMITTER_H + +#include "xBase.h" +#include "xModel.h" +#include "xParEmitterType.h" +#include "xParGroup.h" +#include "xParSys.h" + +struct xParInterp +{ + F32 val[2]; + U32 interp; + F32 freq; + F32 oofreq; + + void set(F32, F32, F32, U32); +}; + +// Size 0x138 +struct xParEmitterPropsAsset : xBaseAsset +{ + U32 parSysID; + union + { + xParInterp rate; + xParInterp value[1]; + }; + xParInterp life; + xParInterp size_birth; + xParInterp size_death; + xParInterp color_birth[4]; + xParInterp color_death[4]; + xParInterp vel_scale; + xParInterp vel_angle; + xVec3 vel; + U32 emit_limit; + F32 emit_limit_reset_time; +}; + +// Size 0x16c +struct xParEmitterCustomSettings : xParEmitterPropsAsset +{ + U32 custom_flags; + U32 attachToID; + xVec3 pos; + xVec3 vel; + F32 vel_angle_variation; + U8 rot[3]; + U8 padding; + F32 radius; + F32 emit_interval_current; + void* emit_volume; +}; + +struct xParEmitterAsset : xBaseAsset +{ + U8 emit_flags; + U8 emit_type; + U16 pad; + U32 propID; + union + { + xPECircle e_circle; + _tagEmitSphere e_sphere; + _tagEmitRect e_rect; + _tagEmitLine e_line; + _tagEmitVolume e_volume; + _tagEmitOffsetPoint e_offsetp; + xPEVCyl e_vcyl; + xPEEntBone e_entbone; + xPEEntBound e_entbound; + }; + U32 attachToID; + xVec3 pos; + xVec3 vel; + F32 vel_angle_variation; + U32 cull_mode; + F32 cull_dist_sqr; +}; + +struct xParEmitter : xBase +{ + xParEmitterAsset* tasset; + xParGroup* group; + xParEmitterPropsAsset* prop; + U8 rate_mode; + F32 rate; + F32 rate_time; + F32 rate_fraction; + F32 rate_fraction_cull; + U8 emit_flags; + U8 emit_pad[3]; + U8 rot[3]; + xModelTag tag; + F32 oocull_distance_sqr; + F32 distance_to_cull_sqr; + void* attachTo; + xParSys* parSys; + void* emit_volume; + xVec3 last_attach_loc; +}; + +struct xScene; + +void xParEmitterInit(void* b, void* tasset); +void xParEmitterSetup(xParEmitter* t); +void xParEmitterDestroy(); +void xParEmitterUpdate(xBase* to, xScene*, F32 dt); +xPar* xParEmitterEmitCustom(xParEmitter* p, F32 dt, xParEmitterCustomSettings* info); +F32 xParInterpCompute(S32 interp_mode, xParInterp* r, F32 time, S32 time_has_elapsed, F32 last_val); + +#endif diff --git a/src/SB/Core/x/xParEmitterType.cpp b/src/SB/Core/x/xParEmitterType.cpp new file mode 100644 index 0000000..9b94ea5 --- /dev/null +++ b/src/SB/Core/x/xParEmitterType.cpp @@ -0,0 +1,3 @@ +#include "xParEmitterType.h" + +#include diff --git a/src/SB/Core/x/xParEmitterType.h b/src/SB/Core/x/xParEmitterType.h new file mode 100644 index 0000000..8f494c2 --- /dev/null +++ b/src/SB/Core/x/xParEmitterType.h @@ -0,0 +1,69 @@ +#ifndef XPAREMITTERTYPE_H +#define XPAREMITTERTYPE_H + +#include "xMath3.h" + +struct xPECircle +{ + F32 radius; + F32 deflection; + xVec3 dir; +}; + +struct _tagEmitSphere +{ + F32 radius; +}; + +struct _tagEmitRect +{ + F32 x_len; + F32 z_len; +}; + +struct _tagEmitLine +{ + xVec3 pos1; + xVec3 pos2; + F32 radius; +}; + +struct _tagEmitVolume +{ + U32 emit_volumeID; +}; + +struct _tagEmitOffsetPoint +{ + xVec3 offset; +}; + +struct xPEVCyl +{ + F32 height; + F32 radius; + F32 deflection; +}; + +struct xPEEntBone +{ + U8 flags; + U8 type; + U8 bone; + U8 pad1; + xVec3 offset; + F32 radius; + F32 deflection; +}; + +struct xPEEntBound +{ + U8 flags; + U8 type; + U8 pad1; + U8 pad2; + F32 expand; + F32 deflection; +}; + +#endif diff --git a/src/SB/Core/x/xParGroup.cpp b/src/SB/Core/x/xParGroup.cpp new file mode 100644 index 0000000..328593a --- /dev/null +++ b/src/SB/Core/x/xParGroup.cpp @@ -0,0 +1,303 @@ +#include "xParGroup.h" + +#include "xMath.h" + +#define REG_TABLE_SIZE 255 + +S32 sParGroupRegTableInit = 0; +S32 sParGroupRegTableCount = 0; +extern xParGroup* sParGroupRegTable[REG_TABLE_SIZE]; // todo: move from bss.s + +extern F32 _708; +extern F32 _709; + +void xParGroupInit(xParGroup* ps) +{ + ps->m_root = NULL; + ps->m_dead = NULL; + ps->m_alive = 0; + ps->m_num_of_particles = 0; + ps->m_killWhenDead = 0; + ps->m_flags = 0; + ps->m_active = 1; + ps->m_culled = 0; + ps->m_visible = 1; + ps->m_cmdTex = NULL; + ps->m_priority = 0; + ps->m_next = NULL; + ps->m_prev = NULL; + + ps->m_flags |= XPARGROUP_ALLOCPARS; + ps->m_flags |= XPARGROUP_UNK1; +} + +static void xParGroupRegisterInit() +{ + for (S32 i = 0; i < REG_TABLE_SIZE; i++) + { + sParGroupRegTable[i] = NULL; + } + + sParGroupRegTableInit = 1; + sParGroupRegTableCount = 0; +} + +void xParGroupSetAging(xParGroup* ps, S32 age) +{ + if (age) + { + if (ps->m_flags & XPARGROUP_NOAGING) + { + ps->m_flags ^= XPARGROUP_NOAGING; + } + } + else + { + ps->m_flags |= XPARGROUP_NOAGING; + } +} + +void xParGroupSetBack2Life(xParGroup* ps, S32 b2l) +{ + if (b2l) + { + if (ps->m_flags & XPARGROUP_NOBACK2LIFE) + { + ps->m_flags ^= XPARGROUP_NOBACK2LIFE; + } + } + else + { + ps->m_flags |= XPARGROUP_NOBACK2LIFE; + } +} + +void xParGroupSetVisibility(xParGroup* ps, S32 vis) +{ + ps->m_visible = vis; +} + +void xParGroupSetPriority(xParGroup* ps, U8 val) +{ + ps->m_priority = val; +} + +void xParGroupRegister(xParGroup* ps) +{ + if (!sParGroupRegTableInit) + { + xParGroupRegisterInit(); + } + + for (U8 i = 0; i < REG_TABLE_SIZE; i++) + { + if (!sParGroupRegTable[i]) + { + sParGroupRegTable[i] = ps; + ps->m_regidx = i; + break; + } + } +} + +void xParGroupUnregister(xParGroup* ps) +{ + for (U8 i = 0; i < REG_TABLE_SIZE; i++) + { + if (sParGroupRegTable[i] == ps) + { + sParGroupRegTable[i] = NULL; + ps->m_regidx = 0; + break; + } + } +} + +void xParGroupSetActive(xParGroup* ps, U32 isActive) +{ + ps->m_active = isActive; +} + +void xParGroupKillAllParticles(xParGroup* ps) +{ + xPar* i = ps->m_root; + + while (i) + { + xPar* tmp = i; + + i = i->m_next; + + xParGroupKillPar(ps, tmp); + } +} + +#define clamp(x, a, b) (((x) < (a)) ? (a) : (((x) > (b)) ? (b) : (x))) + +void xParGroupAnimate(xParGroup* ps, F32 dt) +{ + xPar* i = ps->m_root; + xPar* tmp; + F32 age = dt; + + if (ps->m_flags & XPARGROUP_NOAGING) + { + age = _708; + } + + if (!ps->m_root) + { + ps->m_alive = 0; + } + + while (i) + { + if (i->m_lifetime < _708) + { + tmp = i; + + i = i->m_next; + + xParGroupKillPar(ps, tmp); + } + else + { + // non-matching: stack isn't resizing for each float-to-U8 conversion + i->m_c[0] = i->m_cfl[0] = clamp(i->m_cvel[0] * dt + i->m_cfl[0], _708, _709); + i->m_c[1] = i->m_cfl[1] = clamp(i->m_cvel[1] * dt + i->m_cfl[1], _708, _709); + i->m_c[2] = i->m_cfl[2] = clamp(i->m_cvel[2] * dt + i->m_cfl[2], _708, _709); + i->m_c[3] = i->m_cfl[3] = clamp(i->m_cvel[3] * dt + i->m_cfl[3], _708, _709); + i->m_size += i->m_sizeVel * dt; + i->m_lifetime -= age; + + i = i->m_next; + } + } +} + +void xParGroupAddParP(xParGroup* ps, xPar* p) +{ + ps->m_alive = 1; + ps->m_num_of_particles++; + + p->m_prev = NULL; + p->m_next = NULL; + + if (ps->m_root) + { + p->m_next = ps->m_root; + ps->m_root->m_prev = p; + ps->m_root = p; + } + else + { + ps->m_root = p; + } +} + +xPar* xParGroupAddPar(xParGroup* ps) +{ + xPar* p; + + if (ps->m_flags & XPARGROUP_ALLOCPARS) + { + p = xParAlloc(); + + if (!p) + { + S32 myPriority = ps->m_priority; + + for (U8 i = 0; i < REG_TABLE_SIZE; i++) + { + if (sParGroupRegTable[i] && sParGroupRegTable[i] != ps && + (sParGroupRegTable[i]->m_flags & XPARGROUP_ALLOCPARS) && + !(sParGroupRegTable[i]->m_flags & XPARGROUP_UNK10) && + sParGroupRegTable[i]->m_priority < myPriority && sParGroupRegTable[i]->m_root) + { + xParGroupKillPar(sParGroupRegTable[i], sParGroupRegTable[i]->m_root); + + p = xParAlloc(); + + break; + } + } + } + } + else if (ps->m_dead) + { + p = ps->m_dead; + ps->m_dead = p->m_next; + + if (ps->m_dead) + { + ps->m_dead->m_prev = NULL; + } + } + else + { + p = NULL; + } + + if (p) + { + xParInit(p); + xParGroupAddParP(ps, p); + } + + return p; +} + +void xParGroupKillPar(xParGroup* ps, xPar* p) +{ + if (p == ps->m_root) + { + ps->m_root = p->m_next; + + if (ps->m_root) + { + ps->m_root->m_prev = NULL; + } + + p->m_next = NULL; + p->m_prev = NULL; + } + else + { + if (p->m_next) + { + p->m_next->m_prev = p->m_prev; + } + + if (p->m_prev) + { + p->m_prev->m_next = p->m_next; + } + + p->m_prev = NULL; + p->m_next = NULL; + } + + ps->m_num_of_particles--; + + if (ps->m_flags & XPARGROUP_ALLOCPARS) + { + xParFree(p); + } + else + { + xParGroupAddParToDeadList(ps, p); + } +} + +void xParGroupAddParToDeadList(xParGroup* ps, xPar* p) +{ + if (ps->m_dead) + { + ps->m_dead->m_prev = p; + } + + p->m_next = ps->m_dead; + p->m_prev = NULL; + + ps->m_dead = p; +} diff --git a/src/SB/Core/x/xParGroup.h b/src/SB/Core/x/xParGroup.h new file mode 100644 index 0000000..3fbad09 --- /dev/null +++ b/src/SB/Core/x/xParGroup.h @@ -0,0 +1,48 @@ +#ifndef XPARGROUP_H +#define XPARGROUP_H + +#include "xPar.h" + +struct xParCmdTex; + +struct xParGroup +{ + xPar* m_root; + xPar* m_dead; + S32 m_num_of_particles; + U8 m_alive; + U8 m_killWhenDead; + U8 m_active; + U8 m_visible; + U8 m_culled; + U8 m_priority; + U8 m_flags; + U8 m_regidx; + xParGroup* m_next; + xParGroup* m_prev; + void (*draw)(void*, xParGroup*); + xParCmdTex* m_cmdTex; +}; + +#define XPARGROUP_UNK1 0x1 +#define XPARGROUP_ALLOCPARS 0x2 +#define XPARGROUP_NOAGING 0x4 +#define XPARGROUP_NOBACK2LIFE 0x8 +#define XPARGROUP_UNK10 0x10 + +void xParGroupInit(xParGroup* ps); +void xParGroupSetAging(xParGroup* ps, S32 age); +void xParGroupSetBack2Life(xParGroup* ps, S32 b2l); +void xParGroupSetVisibility(xParGroup* ps, S32 vis); +void xParGroupSetPriority(xParGroup* ps, U8 val); +void xParGroupRegister(xParGroup* ps); +void xParGroupUnregister(xParGroup* ps); +void xParGroupSetActive(xParGroup* ps, U32 isActive); +void xParGroupKillAllParticles(xParGroup* ps); +void xParGroupAnimate(xParGroup* ps, F32 dt); +void xParGroupAddParP(xParGroup* ps, xPar* p); +xPar* xParGroupAddPar(xParGroup* ps); +void xParGroupKillPar(xParGroup* ps, xPar* p); +void xParGroupAddParToDeadList(xParGroup* ps, xPar* p); + +#endif diff --git a/src/SB/Core/x/xParMgr.cpp b/src/SB/Core/x/xParMgr.cpp new file mode 100644 index 0000000..0a5a3f9 --- /dev/null +++ b/src/SB/Core/x/xParMgr.cpp @@ -0,0 +1,49 @@ +#include "iParMgr.h" + +#include "xPar.h" +#include "xParMgr.h" + +#include + +volatile static U32 sFrameCount; +static S32 sParMgrInit; + +void xParMgrInit() +{ + if (sParMgrInit == 0) + { + xParMemInit(); + iParMgrInit(); + sParMgrInit = 1; + } + else + { + xParMgrKillAllParticles(); + iParMgrInit(); + } +} + +void xParMgrKillAllParticles() +{ +} + +void xParMgrUpdate(F32 elapsedTime) +{ + iParMgrUpdate(elapsedTime); + + sFrameCount++; + + if (sFrameCount > 10) + { + sFrameCount = 1; + } + + U32 i; + for (i = sFrameCount; i >= 1; i--); + sFrameCount = i; +} + +void xParMgrRender() +{ + iParMgrRender(); +} diff --git a/src/SB/Core/x/xParMgr.h b/src/SB/Core/x/xParMgr.h new file mode 100644 index 0000000..52e0d3e --- /dev/null +++ b/src/SB/Core/x/xParMgr.h @@ -0,0 +1,11 @@ +#ifndef XPARMGR_H +#define XPARMGR_H + +#include + +void xParMgrInit(); +void xParMgrKillAllParticles(); +void xParMgrUpdate(F32 elapsedTime); +void xParMgrRender(); + +#endif diff --git a/src/SB/Core/x/xParSys.cpp b/src/SB/Core/x/xParSys.cpp new file mode 100644 index 0000000..f53a8f3 --- /dev/null +++ b/src/SB/Core/x/xParSys.cpp @@ -0,0 +1,3 @@ +#include "xParSys.h" + +#include diff --git a/src/SB/Core/x/xParSys.h b/src/SB/Core/x/xParSys.h new file mode 100644 index 0000000..2b94a8f --- /dev/null +++ b/src/SB/Core/x/xParSys.h @@ -0,0 +1,44 @@ +#ifndef XPARSYS_H +#define XPARSYS_H + +#include "xBase.h" +#include "xParCmd.h" +#include "xParGroup.h" + +#include + +struct xScene; + +struct xParSysAsset : xBaseAsset +{ + U32 type; + U32 parentParSysID; + U32 textureID; + U8 parFlags; + U8 priority; + U16 maxPar; + U8 renderFunc; + U8 renderSrcBlendMode; + U8 renderDstBlendMode; + U8 cmdCount; + U32 cmdSize; +}; + +struct xParSys : xBase +{ + xParSysAsset* tasset; + U32 cmdCount; + xParCmd* cmd; + xParSys* parent; + xParGroup* group; + U8 visible; + RwTexture* txtr_particle; +}; + +void xParSysInit(void* b, void* tasset); +void xParSysSetup(xParSys* t); +void xParSysExit(xParSys* t); +void xParSysRender(xBase* b); +void xParSysUpdate(xBase* to, xScene*, F32 dt); + +#endif diff --git a/src/SB/Core/x/xPartition.cpp b/src/SB/Core/x/xPartition.cpp new file mode 100644 index 0000000..8d7f412 --- /dev/null +++ b/src/SB/Core/x/xPartition.cpp @@ -0,0 +1,42 @@ +#include "xPartition.h" +#include "xMemMgr.h" +#include + +void xPartitionReset() +{ +} + +_tagPartLink* PartitionGetFreeLink() +{ + return (_tagPartLink*)xMemAllocSize(sizeof(_tagPartLink)); +} + +void PartitionSpaceReset(_tagPartSpace* space) +{ + memset(space, 0, sizeof(_tagPartSpace)); +} + +void PartitionSpaceInsert(_tagPartSpace* space, void* data) +{ + space->total++; + _tagPartLink* head = &space->head; + _tagPartLink* tmp = head; + while (tmp->next != NULL) + { + tmp = tmp->next; + } + head = PartitionGetFreeLink(); + tmp->next = head; + tmp->next->data = data; + tmp->next->next = NULL; +} + +// Need to figure out the correct order. +S32 xPartitionGetTrueIdx(_tagPartition* part, S32 x_spaces, S32 y_spaces, S32 z_spaces) +{ + return part->total_x * z_spaces + part->total_x * y_spaces * part->total_z + x_spaces; +} + +void xPartitionDump(_tagPartition*, char*) +{ +} diff --git a/src/SB/Core/x/xPartition.h b/src/SB/Core/x/xPartition.h new file mode 100644 index 0000000..6a6edd1 --- /dev/null +++ b/src/SB/Core/x/xPartition.h @@ -0,0 +1,46 @@ +#ifndef XPARTITION_H +#define XPARTITION_H + +#include +#include "xMath3.h" +#include "xEnv.h" +#include "xVolume.h" + +struct _tagPartLink +{ + void* data; + _tagPartLink* next; +}; + +struct _tagPartSpace +{ + S32 total; + _tagPartLink head; +}; + +struct _tagPartition +{ + xVec3 min; + xVec3 max; + xVec3 space_dim; + S32 total_x; + S32 total_y; + S32 total_z; + _tagPartSpace* space; + _tagPartSpace global; +}; + +void xPartitionReset(); +_tagPartLink* PartitionGetFreeLink(); +void PartitionSpaceReset(_tagPartSpace* space); +void PartitionSpaceInsert(_tagPartSpace* space, void* data); +S32 xPartitionGetTrueIdx(_tagPartition* part, S32 x_spaces, S32 y_spaces, S32 z_spaces); +void xPartitionWorld(_tagPartition* part, xEnv* env, S32 x_spaces, S32 y_spaces, + S32 z_spaces); +void xPartitionVolume(_tagPartition* part, xVolume* volume, S32 x_spaces, S32 y_spaces, + S32 z_spaces); +void xPartitionDump(_tagPartition* part, char* string); +S32 xPartitionUpdate(_tagPartition* part, void* data, S32 old_idx, xVec3* current_pos); +S32 xPartitionInsert(_tagPartition* part, void* insert_data, xVec3* insert_pos); + +#endif diff --git a/src/SB/Core/x/xPlayer.h b/src/SB/Core/x/xPlayer.h deleted file mode 100644 index fb908fc..0000000 --- a/src/SB/Core/x/xPlayer.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef XPLAYER_H -#define XPLAYER_H - -#include "xEnt.h" - -struct zEnt : xEnt -{ - xAnimTable* atbl; -}; - -struct zPlayer : zEnt -{ - xVec3 trigLastFramePos; - S32 zPlayerFlags; - U32 lorezModelID; - xModelInstance* lorezModel; - xModelInstance* hirezModel; - - void PostRenderCleanup(); - void RenderCustomUI(); - void zPlayerEventCB(xBase* from, xBase* to, U32 toEvent, F32* toParam, xBase* toParamWidget, - U32 toParamWidgetID); - U32 TalkDoneCheck(xAnimTransition* tran); - U32 TalkCheck(xAnimTransition* tran); - U8 AllowInteraction(); - void AttackHit(); - xEnt* GetGrabbed(); -}; - -#endif diff --git a/src/SB/Core/x/xPtankPool.cpp b/src/SB/Core/x/xPtankPool.cpp new file mode 100644 index 0000000..df352bb --- /dev/null +++ b/src/SB/Core/x/xPtankPool.cpp @@ -0,0 +1,3 @@ +#include "xPtankPool.h" + +#include diff --git a/src/SB/Core/x/xPtankPool.h b/src/SB/Core/x/xPtankPool.h new file mode 100644 index 0000000..56b6429 --- /dev/null +++ b/src/SB/Core/x/xPtankPool.h @@ -0,0 +1,65 @@ +#ifndef XPTANKPOOL_H +#define XPTANKPOOL_H + +#include +#include +#include +#include + +struct iColor_tag; +struct xVec2; +struct xVec3; + +enum ptank_group_type +{ + PGT_COLOR_MAT_UV2, + PGT_POS_COLOR_SIZE_UV2, + MAX_PGT +}; + +struct render_state +{ + RwTexture* texture; + U32 src_blend; + U32 dst_blend; + U32 flags; +}; + +struct _class +{ + U8* data; + S32 stride; + U32 size; +}; + +struct ptank_pool +{ + render_state rs; + U32 used; + RpAtomic* ptank; + _class hide; + + bool valid() const; + void reset(); + void flush(); + void grab_block(ptank_group_type type); +}; + +// total size: 0x38 +struct ptank_pool__pos_color_size_uv2 : public ptank_pool +{ + xVec3* pos; + iColor_tag* color; + xVec2* size; + xVec2* uv; + S32 stride; + + void next(); + void flush(); +}; + +void xPTankPoolSceneEnter(); +void xPTankPoolSceneExit(); +void xPTankPoolRender(); + +#endif diff --git a/src/SB/Core/x/xQuickCull.cpp b/src/SB/Core/x/xQuickCull.cpp new file mode 100644 index 0000000..8feb55c --- /dev/null +++ b/src/SB/Core/x/xQuickCull.cpp @@ -0,0 +1,41 @@ +#include "xQuickCull.h" + +#include + +void xQuickCullInit(xQCControl* ctrl, F32 xmin, F32 ymin, F32 zmin, F32 xmax, F32 ymax, F32 zmax) +{ + ctrl->world_xmin = xmin; + ctrl->world_ymin = ymin; + ctrl->world_zmin = zmin; + ctrl->world_xmax = xmax; + ctrl->world_ymax = ymax; + ctrl->world_zmax = zmax; + ctrl->world_xsz = xmax - xmin; + ctrl->world_ysz = ymax - ymin; + ctrl->world_zsz = zmax - zmin; + if (((ctrl->world_xsz <= 0.0f) || (ctrl->world_ysz <= 0.0f)) || (ctrl->world_zsz <= 0.0f)) + { + ctrl->world_zsz = 1.0f; + ctrl->world_ysz = 1.0f; + ctrl->world_xsz = 1.0f; + } + ctrl->scale_x = 127.0f / ctrl->world_xsz; + ctrl->scale_y = 127.0f / ctrl->world_ysz; + ctrl->scale_z = 127.0f / ctrl->world_zsz; + ctrl->center_x = 0.5f * (xmax + xmin) + 0.5f / ctrl->scale_x; + ctrl->center_y = 0.5f * (ymax + ymin) + 0.5f / ctrl->scale_y; + ctrl->center_z = 0.5f * (zmax + zmin) + 0.5f / ctrl->scale_z; +} + +void xQuickCullInit(xQCControl* ctrl, const xBox* box) +{ + xQuickCullInit(ctrl, box->lower.x, box->lower.y, box->lower.z, box->upper.x, box->upper.y, + box->upper.z); +} + +// WIP. +S32 xQuickCullIsects(const xQCData* a, const xQCData* b) +{ + return a->xmin <= b->xmax && a->ymin <= b->ymax && a->zmin <= b->zmax && b->xmin <= a->xmax && + b->ymin <= a->ymax && b->zmin <= a->zmax; +} diff --git a/src/SB/Core/x/xQuickCull.h b/src/SB/Core/x/xQuickCull.h index 6a445bc..cff957b 100644 --- a/src/SB/Core/x/xQuickCull.h +++ b/src/SB/Core/x/xQuickCull.h @@ -1,15 +1,64 @@ -#include "xMath.h" +#ifndef XQUICKCULL_H +#define XQUICKCULL_H +#include "xVec3.h" +#include "xMath3.h" + +// Size: 0x20 struct xQCData { - U8 xmin; - U8 ymin; - U8 zmin; - U8 zmin_dup; - U8 xmax; - U8 ymax; - U8 zmax; - U8 zmax_dup; + S8 xmin; + S8 ymin; + S8 zmin; + S8 zmin_dup; + S8 xmax; + S8 ymax; + S8 zmax; + S8 zmax_dup; xVec3 min; xVec3 max; }; + +struct xQCControl +{ + F32 world_xmin; + F32 world_ymin; + F32 world_zmin; + F32 world_xmax; + F32 world_ymax; + F32 world_zmax; + F32 world_xsz; + F32 world_ysz; + F32 world_zsz; + F32 scale_x; + F32 scale_y; + F32 scale_z; + F32 center_x; + F32 center_y; + F32 center_z; +}; + +extern xQCControl xqc_def_ctrl; + +struct xBound; +struct xBox; + +void xQuickCullInit(const xBox* box); +void xQuickCullInit(xQCControl* ctrl, const xBox* box); + +void xQuickCullInit(xQCControl* ctrl, F32 xmin, F32 ymin, F32 zmin, F32 xmax, + F32 ymax, F32 zmax); +void xQuickCullInit(xQCControl* ctrl, const xBox* box); +S32 xQuickCullIsects(const xQCData* a, const xQCData* b); +void xQuickCullForBound(xQCControl* ctrl, xQCData* q, const xBound* b); +void xQuickCullCellForVec(xQCControl* ctrl, xQCData* c, const xVec3* v); +void xQuickCullCellMerge(xQCData* dest, const xQCData* a, const xQCData* b); +void xQuickCullForLine(xQCControl* ctrl, xQCData* q, const xLine3* ln); +void xQuickCullForRay(xQCControl* ctrl, xQCData* q, const xRay3* r); +void xQuickCullForSphere(xQCControl* ctrl, xQCData* q, const xSphere* s); +void xQuickCullForBox(xQCControl* ctrl, xQCData* q, const xBox* box); +void xQuickCullForOBB(xQCControl* ctrl, xQCData* q, const xBox* b, const xMat4x3* m); +void xQuickCullForEverything(xQCData* q); +void xQuickCullForBound(xQCData* q, const xBound* b); + +#endif diff --git a/src/SB/Core/x/xRMemData.cpp b/src/SB/Core/x/xRMemData.cpp new file mode 100644 index 0000000..7a748e0 --- /dev/null +++ b/src/SB/Core/x/xRMemData.cpp @@ -0,0 +1,72 @@ +#include "xRMemData.h" +#include "xMemMgr.h" + +#include +#include + +void* RyzMemData::operator new(size_t size, S32 amt, RyzMemGrow* growCtxt) +{ + S32 dogrow = true; + if (growCtxt == NULL) + { + dogrow = false; + } + else if (growCtxt->IsEnabled() == 0) + { + dogrow = false; + } + + void* mem; + if (dogrow) + { + mem = xMemGrowAllocSize(size); + } + else + { + mem = xMemAllocSize(size); + } + memset(mem, 0, 4); + return mem; +} + +void RyzMemData::operator delete(void* p) +{ +} + +RyzMemGrow* RyzMemGrow::Init(xBase* growuser) +{ + char* dat; + if (this->ptr != NULL) + { + return this; + } + this->amt_last = 0; + this->ptr_last = NULL; + this->user_last = NULL; + this->amt = 0x20; + dat = (char*)xMemAllocSize(this->amt); + this->ptr = dat; + this->user = growuser; + this->flg_grow = 1; + return this; +} + +RyzMemGrow* RyzMemGrow::Resume(xBase*) +{ + this->amt = this->amt_last; + this->ptr = this->ptr_last; + this->user = this->user_last; + this->flg_grow = 0b11; + return this; +} + +void RyzMemGrow::Done() +{ + this->amt_last = this->amt; + this->ptr_last = this->ptr; + this->user_last = this->user; + this->amt = 0; + this->ptr = NULL; + this->user = NULL; + this->flg_grow = 0; +} diff --git a/src/SB/Core/x/xRMemData.h b/src/SB/Core/x/xRMemData.h new file mode 100644 index 0000000..9d0a94b --- /dev/null +++ b/src/SB/Core/x/xRMemData.h @@ -0,0 +1,33 @@ +#ifndef XRMEMDATA_H +#define XRMEMDATA_H + +#include "xBase.h" + +#include + +struct RyzMemGrow +{ + S32 flg_grow; + S32 amt; + char* ptr; + xBase* user; + S32 amt_last; + char* ptr_last; + xBase* user_last; + + RyzMemGrow* Init(xBase* growuser); + RyzMemGrow* Resume(xBase*); + void Done(); + S32 IsEnabled() + { + return this->flg_grow & 1; + } +}; + +struct RyzMemData +{ + void* operator new(size_t amt, S32, RyzMemGrow* growCtxt); + void operator delete(void*); +}; + +#endif diff --git a/src/SB/Core/x/xRay3.h b/src/SB/Core/x/xRay3.h new file mode 100644 index 0000000..5a2698b --- /dev/null +++ b/src/SB/Core/x/xRay3.h @@ -0,0 +1,15 @@ +#ifndef XRAY3_H +#define XRAY3_H + +#include "xMath3.h" + +struct xRay3 +{ + xVec3 origin; + xVec3 dir; + F32 min_t; + F32 max_t; + S32 flags; +}; + +#endif diff --git a/src/SB/Core/x/xRenderState.cpp b/src/SB/Core/x/xRenderState.cpp new file mode 100644 index 0000000..4a17ae2 --- /dev/null +++ b/src/SB/Core/x/xRenderState.cpp @@ -0,0 +1,31 @@ +#include "xRenderState.h" + +static int sBlendTable[11] = +{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +}; + +void xRenderStateSetTexture(RwTexture* texture) +{ + if (texture != NULL) + { + if (texture->raster != NULL) + { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)texture->raster); + } + } + else + { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)NULL); + } +} + +void xRenderStateSetSrcBlendMode(int xmode) +{ + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)sBlendTable[xmode]); +} + +void xRenderStateSetDstBlendMode(int xmode) +{ + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)sBlendTable[xmode]); +} \ No newline at end of file diff --git a/src/SB/Core/x/xRenderState.h b/src/SB/Core/x/xRenderState.h new file mode 100644 index 0000000..9bb8c57 --- /dev/null +++ b/src/SB/Core/x/xRenderState.h @@ -0,0 +1,11 @@ +#ifndef XRENDERSTATE_H +#define XRENDERSTATE_H + +#include +#include + +void xRenderStateSetDstBlendMode(S32 xmode); +void xRenderStateSetSrcBlendMode(S32 xmode); +void xRenderStateSetTexture(RwTexture* texture); + +#endif diff --git a/src/SB/Core/x/xRumble.h b/src/SB/Core/x/xRumble.h new file mode 100644 index 0000000..f161cf1 --- /dev/null +++ b/src/SB/Core/x/xRumble.h @@ -0,0 +1,33 @@ +#ifndef XRUMBLE_H +#define XRUMBLE_H + +#include + +enum _tagRumbleType +{ + eRumble_Off, + eRumble_Hi, + eRumble_VeryLightHi, + eRumble_VeryLight, + eRumble_LightHi, + eRumble_Light, + eRumble_MediumHi, + eRumble_Medium, + eRumble_HeavyHi, + eRumble_Heavy, + eRumble_VeryHeavyHi, + eRumble_VeryHeavy, + eRumble_Total, + eRumbleForceU32 = 0x7fffffff +}; + +struct _tagxRumble +{ + _tagRumbleType type; + F32 seconds; + _tagxRumble* next; + S16 active; + U16 fxflags; +}; + +#endif diff --git a/src/SB/Core/x/xSFX.cpp b/src/SB/Core/x/xSFX.cpp new file mode 100644 index 0000000..acf1e0a --- /dev/null +++ b/src/SB/Core/x/xSFX.cpp @@ -0,0 +1,103 @@ +#include "xSFX.h" + +#include "xSnd.h" +#include "xEvent.h" + +#include +#include + +extern xSFX* s_managedEnvSFX[1]; + +void xSFXEnvironmentalStreamSceneExit(void) +{ + memset(&s_managedEnvSFX, 0, 4); +} + +S32 xSFXWillSendDone(xSFX* param_1) +{ + S32 iLink = param_1->linkCount; + + if ((U32)iLink != 0) + { + xLinkAsset* pLink = param_1->link; + + for (; iLink > 0; iLink--) + { + if (pLink->srcEvent == 0xbf) + { + return 1; + } + pLink++; + } + } + + return 0; +} + +void xSFXInit(void* t, void* asset) + +{ + xSFXInit((xSFX*)t, (xSFXAsset*)asset); +} + +void xSFXInit(xSFX* t, xSFXAsset* asset) +{ + xBaseInit(t, asset); + + // S32 xSFXEventCB(xBase* to, xBase* from, U32 toEvent, const F32* toParam, xBase*) + t->eventFunc = &xSFXEventCB; + t->asset = asset; + + if (t->linkCount) + { + t->link = (xLinkAsset*)(t->asset + 1); + } + else + { + t->link = 0; + } + if (xSFXWillSendDone(t)) + { + asset->flagsSFX = asset->flagsSFX | 0x800; + } + t->sndID = 0; + t->asset->flagsSFX = t->asset->flagsSFX & 0xefff; + t->cachedOuterDistSquared = (t->asset->outerRadius * t->asset->outerRadius); +} + +void xSFXSave(xSFX* ent, xSerial* s) +{ + xBaseSave(ent, s); +} + +void xSFXLoad(xSFX* ent, xSerial* s) +{ + xBaseLoad(ent, s); +} + +void xSFXReset(xSFX* param_1) +{ + xBaseReset(param_1, param_1->asset); +} + +U32 xSFXConvertFlags(U32 param_1) +{ + return param_1 & 4 ? 0 : 0x800; +} + +void xSFXUpdate(xSFX* param_1) +{ + if ((param_1->asset->flagsSFX & 0x800) && (param_1->sndID) && + (!xSndIDIsPlaying(param_1->sndID))) + { + param_1->sndID = 0; + param_1->asset->flagsSFX = param_1->asset->flagsSFX & 0xefff; + zEntEvent(param_1, param_1, 0xbf); + } +} + +void xSFXStop(xSFX* param_1) +{ + xSndStop(param_1->sndID); + param_1->sndID = 0; +} diff --git a/src/SB/Core/x/xSFX.h b/src/SB/Core/x/xSFX.h new file mode 100644 index 0000000..355d8cc --- /dev/null +++ b/src/SB/Core/x/xSFX.h @@ -0,0 +1,41 @@ +#ifndef XSFX_H +#define XSFX_H + +#include "xBase.h" +#include "xMath3.h" + +#include "iColor.h" + +struct xSFXAsset : xBaseAsset +{ + U16 flagsSFX; + U16 freq; + F32 freqm; + U32 soundAssetID; + U32 attachID; + U8 loopCount; + U8 priority; + U8 volume; + U8 pad; + xVec3 pos; + F32 innerRadius; + F32 outerRadius; +}; + +struct xSFX : xBase +{ + xSFXAsset* asset; + U32 sndID; + F32 cachedOuterDistSquared; +}; + +void xSFXInit(void* t, void* asset); +void xSFXInit(xSFX* t, xSFXAsset* asset); +void xSFXSave(xSFX* ent, xSerial* s); +void xSFXLoad(xSFX* ent, xSerial* s); +void xSFXEnvironmentalStreamSceneExit(); +void xSFXUpdateEnvironmentalStreamSounds(xSFX* pSFXList, U32 numSounds); +S32 xSFXEventCB(xBase* to, xBase* from, U32 toEvent, const F32* toParam, xBase*); +S32 xSFXWillSendDone(xSFX*); + +#endif diff --git a/src/SB/Core/x/xScene.cpp b/src/SB/Core/x/xScene.cpp new file mode 100644 index 0000000..e2b6655 --- /dev/null +++ b/src/SB/Core/x/xScene.cpp @@ -0,0 +1,433 @@ +#include "xScene.h" + +#include "xMemMgr.h" +#include "xCollideFast.h" +#include "xMath.h" + +#include "iMath.h" +#include "iCollide.h" +#include "zBase.h" + +#include +#include +#include + +#include + +extern F32 lbl_803CCF78; + +namespace +{ + struct cb_ray_hits_ent + { + const xRay3& ray; + xCollis& coll; + U8 chkby; + U8 collType; + + cb_ray_hits_ent(const xRay3& ray, xCollis& coll, U8 chkby, U8 collType); + bool operator()(xEnt& ent, xGridBound& gridb); + }; +} // namespace + +void xSceneInit(xScene* sc, U16 num_trigs, U16 num_stats, U16 num_dyns, U16 num_npcs) +{ + sc->flags = 0; + sc->num_trigs_allocd = num_trigs; + sc->trigs = (xEnt**)xMemAllocSize(num_trigs * sizeof(xEnt*)); + sc->num_stats_allocd = num_stats; + sc->stats = (xEnt**)xMemAllocSize(num_stats * sizeof(xEnt*)); + sc->num_dyns_allocd = num_dyns; + sc->dyns = (xEnt**)xMemAllocSize(num_dyns * sizeof(xEnt*)); + sc->num_npcs_allocd = num_npcs; + sc->npcs = (xEnt**)xMemAllocSize(num_npcs * sizeof(xEnt*)); + sc->num_ents_allocd = (U32)num_trigs + (U32)num_stats + (U32)num_dyns + (U32)num_npcs; + sc->num_act_ents = 0; + sc->act_ents = (xEnt**)xMemAllocSize(sc->num_ents_allocd * sizeof(xEnt*)); + sc->num_nact_ents = 0; + sc->nact_ents = (xEnt**)xMemAllocSize(sc->num_ents_allocd * sizeof(xEnt*)); + sc->num_ents = 0; + sc->num_trigs = 0; + sc->num_stats = 0; + sc->num_dyns = 0; + sc->num_npcs = 0; + sc->resolvID = NULL; + + xAnimInit(); + xModelInit(); + xAnimPoolInit(&sc->mempool, 50, 1, 0x1, 4); + xModelPoolInit(49, 64); + xModelPoolInit(74, 8); + xModelPoolInit(164, 1); + xAnimTempTransitionInit(16); + xCollideInit(sc); + xCollideFastInit(sc); +} + +void xSceneExit(xScene* sc) +{ +} + +void xSceneSave(xScene* sc, xSerial* s) +{ +} + +void xSceneLoad(xScene* sc, xSerial* s) +{ +} + +void xSceneSetup(xScene* sc) +{ + xEnvSetup(sc->env); +} + +void xSceneAddEnt(xScene* sc, xEnt* ent) +{ + if (ent->collType == XENT_COLLTYPE_TRIG) + { + sc->trigs[sc->num_trigs++] = ent; + } + else if (ent->collType == XENT_COLLTYPE_STAT) + { + sc->stats[sc->num_stats++] = ent; + } + else if (ent->collType == XENT_COLLTYPE_DYN) + { + sc->dyns[sc->num_dyns++] = ent; + } + else if (ent->collType == XENT_COLLTYPE_NPC) + { + sc->npcs[sc->num_npcs++] = ent; + } + + sc->act_ents[sc->num_act_ents++] = ent; +} + +xBase* xSceneResolvID(xScene* sc, U32 id) +{ + if (sc->resolvID) + { + return sc->resolvID(id); + } + + return NULL; +} + +const char* xSceneID2Name(xScene* sc, U32 id) +{ + if (sc->id2Name) + { + return sc->id2Name(id); + } + + return NULL; +} + +void xSceneForAllEnts(xScene* sc, xSceneEntCallback func, void* data) +{ + for (U16 i = 0; i < sc->num_act_ents; i++) + { + if (!func(sc->act_ents[i], sc, data)) + { + break; + } + } +} + +void xSceneForAllStatics(xScene* sc, xSceneEntCallback func, void* data) +{ + for (U16 i = 0; i < sc->num_stats; i++) + { + if (!func(sc->stats[i], sc, data)) + { + break; + } + } +} + +void xSceneForAllDynamics(xScene* sc, xSceneEntCallback func, void* data) +{ + for (U16 i = 0; i < sc->num_dyns; i++) + { + if (!func(sc->dyns[i], sc, data)) + { + break; + } + } +} + +void xSceneForAllNPCs(xScene* sc, xSceneEntCallback func, void* data) +{ + for (U16 i = 0; i < sc->num_npcs; i++) + { + if (!func(sc->npcs[i], sc, data)) + { + break; + } + } +} + +void xRayHitsTikiLandableEnt(xScene* sc, xRay3* r, xQCData* qcr, xEnt* ent, void* colldata) +{ + xCollis* coll = (xCollis*)colldata; + xCollis c; + + if (ent->chkby == XENT_COLLTYPE_NONE) + { + return; + } + + if (ent->collType == XENT_COLLTYPE_NPC) + { + return; + } + + if (ent->baseType == eBaseTypeBoulder) + { + return; + } + + if (qcr && !xQuickCullIsects(qcr, &ent->bound.qcd)) + { + return; + } + + xRayHitsBound(r, &ent->bound, &c); + + if (!(c.flags & 0x1)) + { + return; + } + + if (ent->collLev == 0x5) + { + iRayHitsModel(r, ent->model, &c); + + if (!(c.flags & 0x1)) + { + return; + } + } + + if (c.dist < coll->dist) + { + coll->dist = c.dist; + coll->oid = ent->id; + coll->optr = ent; + coll->mptr = ent->model; + } +} + +void xRayHitsEnt(xScene* sc, xRay3* r, xQCData* qcr, xEnt* ent, void* colldata) +{ + xCollis* coll = (xCollis*)colldata; + xCollis c; + + if (ent->chkby == XENT_COLLTYPE_NONE) + { + return; + } + + if (qcr && !xQuickCullIsects(qcr, &ent->bound.qcd)) + { + return; + } + + xRayHitsBound(r, &ent->bound, &c); + + if (!(c.flags & 0x1)) + { + return; + } + + if (c.dist < coll->dist) + { + coll->dist = c.dist; + coll->oid = ent->id; + coll->optr = ent; + coll->mptr = ent->model; + } +} + +cb_ray_hits_ent::cb_ray_hits_ent(const xRay3& ray, xCollis& coll, U8 chkby, U8 collType) + : ray(ray), coll(coll), chkby(chkby), collType(collType) +{ +} + +void ProjectTriangle(xVec3* param_1, xVec3* param_2, float* param_3, float* param_4) +{ + float fVar1; + + *param_3 = param_1->x * param_2->x + param_1->y * param_2->y + param_1->z * param_2->z; + *param_4 = *param_3; + fVar1 = param_1->x * param_2[1].x + param_1->y * param_2[1].y + param_1->z * param_2[1].z; + if (fVar1 < *param_3) + { + *param_3 = fVar1; + } + else + { + if (fVar1 > *param_4) + { + *param_4 = fVar1; + } + } + fVar1 = param_1->x * param_2[2].x + param_1->y * param_2[2].y + param_1->z * param_2[2].z; + if (fVar1 < *param_3) + { + *param_3 = fVar1; + return; + } + if (fVar1 > *param_4) + { + *param_4 = fVar1; + } + return; +} + +void ProjectBox(xVec3* param_1, xBox* param_2, float* param_3, float* param_4) +{ + F32 fVar7 = lbl_803CCF78 * (param_1->x * ((param_2->upper).x + (param_2->lower).x) + + param_1->y * ((param_2->upper).y + (param_2->lower).y) + + param_1->z * ((param_2->upper).z + (param_2->lower).z)); + F32 fVar1 = lbl_803CCF78 * (iabs(param_1->x * ((param_2->upper).x - (param_2->lower).x)) + + iabs(param_1->y * ((param_2->upper).y - (param_2->lower).y)) + + iabs(param_1->z * ((param_2->upper).z - (param_2->lower).z))); + *param_3 = fVar7 - fVar1; + *param_4 = fVar7 + fVar1; +} + +static RpCollisionTriangle* nearestFloorCB(RpIntersection*, RpCollisionTriangle* collTriangle, F32, + void* data); + +static RpCollisionTriangle* sectorNearestFloorCB(RpIntersection* intersection, RpWorldSector*, + RpCollisionTriangle* collTriangle, F32 distance, + void* data) +{ + return nearestFloorCB(intersection, collTriangle, distance, data); +} + +bool cb_ray_hits_ent::operator()(xEnt& ent, xGridBound& gridb) +{ + xCollis c; + + if (!(ent.chkby & chkby)) + { + return true; + } + + if (!(ent.collType & collType)) + { + return true; + } + + c.flags = coll.flags; + + xRayHitsBound(&ray, &ent.bound, &c); + + if (!(c.flags & 0x1)) + { + return true; + } + + if (c.dist > coll.dist) + { + return true; + } + + if (ent.collLev == 0x5) + { + iRayHitsModel(&ray, ent.model, &c); + + if (!(c.flags & 0x1)) + { + return true; + } + + if (c.dist > coll.dist) + { + return true; + } + } + + memcpy(&coll, &c, sizeof(xCollis)); + + coll.oid = ent.id; + coll.optr = &ent; + coll.mptr = ent.model; + + return true; +} + +void xEntEnable(xEnt* ent) +{ + xBaseEnable(ent); +} + +template <> U16 range_limit(U16 v, U16 minv, U16 maxv) +{ + if (v <= minv) + { + return minv; + } + + if (v >= maxv) + { + return maxv; + } + + return v; +} + +void xBoxFromRay(xBox& box, const xRay3& ray) +{ + xLine3 line; + + if (ray.flags & 0x400) + { + F32 x = ray.dir.x * ray.min_t; + F32 y = ray.dir.y * ray.min_t; + F32 z = ray.dir.z * ray.min_t; + + line.p1.x = ray.origin.x + x; + line.p1.y = ray.origin.y + y; + line.p1.z = ray.origin.z + z; + } + else + { + line.p1.x = ray.origin.x; + line.p1.y = ray.origin.y; + line.p1.z = ray.origin.z; + } + + if (ray.flags & 0x800) + { + F32 dist = (ray.flags & 0x400) ? ray.max_t - ray.min_t : ray.max_t; + + line.p2.x = ray.dir.x * dist; + line.p2.y = ray.dir.y * dist; + line.p2.z = ray.dir.z * dist; + } + else + { + line.p2.x = ray.dir.x; + line.p2.y = ray.dir.y; + line.p2.z = ray.dir.z; + } + + line.p2.x = line.p1.x + line.p2.x; + line.p2.y = line.p1.y + line.p2.y; + line.p2.z = line.p1.z + line.p2.z; + + xBoxFromLine(box, line); +} + +void xBoxFromLine(xBox& box, const xLine3& line) +{ + box.upper.x = MAX(line.p1.x, line.p2.x); + box.upper.y = MAX(line.p1.y, line.p2.y); + box.upper.z = MAX(line.p1.z, line.p2.z); + box.lower.x = MIN(line.p1.x, line.p2.x); + box.lower.y = MIN(line.p1.y, line.p2.y); + box.lower.z = MIN(line.p1.z, line.p2.z); +} diff --git a/src/SB/Core/x/xScene.h b/src/SB/Core/x/xScene.h new file mode 100644 index 0000000..c883872 --- /dev/null +++ b/src/SB/Core/x/xScene.h @@ -0,0 +1,66 @@ +#ifndef XSCENE_H +#define XSCENE_H + +#include "xBase.h" +#include "xEnt.h" +#include "xEnv.h" +#include "xMemMgr.h" +#include "xRay3.h" + +typedef const char* (*xSceneBase2NameCallback)(xBase*); +typedef const char* (*xSceneID2NameCallback)(U32); +typedef xBase* (*xSceneResolvIDCallback)(U32); +typedef xEnt* (*xSceneEntCallback)(xEnt* ent, xScene* sc, void* data); + +struct xScene +{ + U32 sceneID; + U16 flags; + U16 num_ents; + U16 num_trigs; + U16 num_stats; + U16 num_dyns; + U16 num_npcs; + U16 num_act_ents; + U16 num_nact_ents; + F32 gravity; + F32 drag; + F32 friction; + U16 num_ents_allocd; + U16 num_trigs_allocd; + U16 num_stats_allocd; + U16 num_dyns_allocd; + U16 num_npcs_allocd; + xEnt** trigs; + xEnt** stats; + xEnt** dyns; + xEnt** npcs; + xEnt** act_ents; + xEnt** nact_ents; + xEnv* env; + xMemPool mempool; + xSceneResolvIDCallback resolvID; + xSceneBase2NameCallback base2Name; + xSceneID2NameCallback id2Name; +}; + +extern xScene* g_xSceneCur; + +void xSceneInit(xScene* sc, U16 num_trigs, U16 num_stats, U16 num_dyns, U16 num_npcs); +void xSceneExit(xScene* sc); +void xSceneSave(xScene* sc, xSerial* s); +void xSceneLoad(xScene* sc, xSerial* s); +void xSceneSetup(xScene* sc); +void xSceneAddEnt(xScene* sc, xEnt* ent); +xBase* xSceneResolvID(xScene* sc, U32 id); +const char* xSceneID2Name(xScene* sc, U32 id); +void xSceneForAllEnts(xScene* sc, xSceneEntCallback func, void* data); +void xSceneForAllStatics(xScene* sc, xSceneEntCallback func, void* data); +void xSceneForAllDynamics(xScene* sc, xSceneEntCallback func, void* data); +void xSceneForAllNPCs(xScene* sc, xSceneEntCallback func, void* data); +void xRayHitsTikiLandableEnt(xScene* sc, xRay3* r, xQCData* qcr, xEnt* ent, void* colldata); +void xRayHitsEnt(xScene* sc, xRay3* r, xQCData* qcr, xEnt* ent, void* colldata); +void xRayHitsScene(xScene* sc, xRay3* r, xCollis* coll); +void xRayHitsSceneFlags(xScene* sc, xRay3* r, xCollis* coll, U8 collType, U8 chk); + +#endif diff --git a/src/SB/Core/x/xScrFx.cpp b/src/SB/Core/x/xScrFx.cpp new file mode 100644 index 0000000..deb1139 --- /dev/null +++ b/src/SB/Core/x/xScrFx.cpp @@ -0,0 +1,11 @@ +#include "xScrFx.h" + +#include + +void xScrFxDistortionAdd(xVec3*, xVec3*, S32) +{ +} + +void xScrFxDistortionRender(RwCamera*) +{ +} diff --git a/src/SB/Core/x/xScrFx.h b/src/SB/Core/x/xScrFx.h new file mode 100644 index 0000000..2d1162f --- /dev/null +++ b/src/SB/Core/x/xScrFx.h @@ -0,0 +1,23 @@ +#ifndef XSCRFX_H +#define XSCRFX_H + +#include "xCamera.h" +#include "iColor.h" + +#include + +void xScrFxUpdate(RwCamera* cam, F32 dt); +void xScrFxRender(RwCamera*); +void xScrFxDrawScreenSizeRectangle(); +void xScrFxFade(iColor_tag* base, iColor_tag* dest, F32 seconds, void (*callback)(), + S32 hold); +S32 xScrFxIsLetterbox(); +void xScrFxLetterboxReset(); +S32 xScrFXGlareAdd(xVec3* pos, F32 life, F32 intensity, F32 size, F32 r, + F32 g, F32 b, F32 a, RwRaster* raster); +void xScrFXFullScreenGlareRender(); +void xScrFXGlareRender(xCamera* cam); +void xScrFxLetterbox(S32 enable); +void xScrFxReset(); + +#endif diff --git a/src/SB/Core/x/xShadow.cpp b/src/SB/Core/x/xShadow.cpp new file mode 100644 index 0000000..455668d --- /dev/null +++ b/src/SB/Core/x/xShadow.cpp @@ -0,0 +1,272 @@ +#include "xShadow.h" + +#include "rpworld.h" + +#include "xMath.h" +#include "iModel.h" +#include "zGlobals.h" + +#include + +RwRGBAReal ShadowLightColor = { 1.0f, 1.0f, 1.0f, 1.0f }; + +RpLight* ShadowLight; +static F32 SHADOW_BOTH; +RwCamera* ShadowCamera; +RwRaster* ShadowCameraRaster; +static RwRaster* ShadowRenderRaster; +F32 gShadowObjectRadius; +static S32 shadow_ent_count; +static RwRaster* gc_saveraster; +static xShadowMgr* sMgrList; +static S32 sMgrCount; +static S32 sMgrTotal; + +void xShadowInit(); +static void ShadowCameraDestroy(RwCamera* shadowCamera); +static S32 SetupShadow(); +static RwRaster* ShadowRasterCreate(S32 res); +static RwCamera* ShadowCameraCreatePersp(S32 param); +U32 xShadowCameraCreate(); +void xShadowRenderWorld(xVec3* a, F32 b, F32 c); +void xShadow_ListAdd(xEnt* ent); +void xShadowManager_Add(xEnt* ent); +static void GCSaveFrameBuffer(); +RwCamera* ShadowCameraSetSpherePersp(RwCamera* camera, RwV3d* center, float radius); +int Im2DRenderQuad(float x1, float y1, float x2, float y2, float z, float recipCamZ, float uvOffset); + +/* Three more params than in DWARF. +RwCamera* ShadowCameraUpdate(RwCamera* shadowCamera, void* model, void(*renderCB)(void*)) +*/ +RwCamera* ShadowCameraUpdate(RwCamera* shadowCamera, void* model, void(*renderCB)(void*), RwV3d* center, float radius, int); + +void xShadowInit() +{ + xShadowCameraCreate(); + gc_saveraster = RwRasterCreate(256, 256, 32, 0x504); + shadow_ent_count = 0; + ShadowLight = RpLightCreate(1); + RpLightSetColor(ShadowLight, &ShadowLightColor); + RwFrame* frame = RwFrameCreate(); + _rwObjectHasFrameSetFrame(ShadowLight, frame); +} + +void xShadowRender(xVec3* a, F32 b, F32 c) +{ + xShadowRenderWorld(a, b, c); +} + +static S32 SetupShadow() +{ + S32 res = 256; + + // Continuously halve res until it is less than or + // equal to either display width or height. + // On GCN, this routine normally won't happen, + // as we're already below both dimensions. + for (; (res > 640) || (res > 480); res >>= 1); + + ShadowCamera = ShadowCameraCreatePersp(res); + if (ShadowCamera == NULL) + { + return 0; + } + ShadowCameraRaster = ShadowRasterCreate(res); + if (ShadowCameraRaster == NULL) + { + return 0; + } + ShadowCamera->frameBuffer = ShadowCameraRaster; + return 1; +} + +void xShadowSetWorld(RpWorld* world) +{ + RpWorldAddCamera(world, ShadowCamera); + SHADOW_BOTH = 2.0f; +} + +U32 xShadowCameraCreate() +{ + U32 setup = SetupShadow(); + return ((-setup | setup) >> 0x1f); +} + +void xShadowCameraUpdate(void* model, void(*renderCB)(void*), xVec3* center, float radius, int shadowMode) +{ + ShadowCameraSetSpherePersp(ShadowCamera, (RwV3d*)center, radius); + ShadowCameraUpdate(ShadowCamera, model, renderCB, (RwV3d*)center, radius, shadowMode); + ShadowRenderRaster = ShadowCameraRaster; +} + +static void modelRenderCB(void* param) +{ + xModelRender((xModelInstance*)param); +} + +S32 xShadowReceiveShadowSetup(xEnt* ent) +{ + if + ( + (ent->model != NULL) && + (xEntIsVisible(ent)) && + (ent->baseFlags & 0x10) && + (!iModelCull(ent->model->Data, ent->model->Mat)) + ) + { + return 1; + } + return 0; +} + +void xShadow_ListAdd(xEnt* ent) +{ + xShadowManager_Add(ent); +} + +void ShadowCameraDestroy(RwCamera* shadowCamera) +{ + if (shadowCamera == NULL) + { + return; + } + + _rwFrameSyncDirty(); + RwFrame* parent = (RwFrame*)shadowCamera->object.object.parent; + if (parent != NULL) + { + _rwObjectHasFrameSetFrame(shadowCamera, NULL); + RwFrameDestroy(parent); + } + + // Scheduling issue with RwRasterDestroy calls + + if (shadowCamera->zBuffer != NULL) + { + RwRasterDestroy(shadowCamera->zBuffer); + shadowCamera->zBuffer = NULL; + } + + if (shadowCamera->frameBuffer != NULL) + { + RwRasterDestroy(shadowCamera->frameBuffer); + shadowCamera->frameBuffer = NULL; + } + + RwCameraDestroy(shadowCamera); +} + +static RwRaster* ShadowRasterCreate(S32 res) +{ + return RwRasterCreate(res, res, 0, 5); +} + +void GCSaveFrameBuffer() +{ + RwGameCubeCameraTextureFlush(gc_saveraster, 0); +} + +static void GCRestoreFrameBuffer() +{ + RwCamera* cam = *(RwCamera**)RwEngineInstance; + F32 recipCamZ = (1.0f / cam->farPlane); + + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)2); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)1); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)0); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)0); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)1); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gc_saveraster); + + Im2DRenderQuad(0.0f, 0.0f, 256.0f, 256.0f, RwIm2DGetFarScreenZ(), recipCamZ, 0.001953125f); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)1); + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6); +} + +static RwCamera* ShadowCameraCreatePersp(S32 param) +{ + RwCamera* cam = RwCameraCreate(); + if (cam != NULL) + { + _rwObjectHasFrameSetFrame(cam, RwFrameCreate()); + + RwV2d viewWin; + viewWin.x = DEG2RAD(10); + viewWin.y = DEG2RAD(10); + + RwCameraSetViewWindow(cam, &viewWin); + + if (cam->object.object.parent != NULL) + { + RwRaster* raster = RwRasterCreate(param, param, 0, 1); + if (raster != NULL) + { + cam->zBuffer = raster; + return cam; + } + } + } + ShadowCameraDestroy(cam); + return NULL; +} + +void xShadowManager_Init(S32 numEnts) +{ + sMgrList = (xShadowMgr*)xMemAlloc(gActiveHeap, numEnts << 4, 0); + sMgrTotal = numEnts; + sMgrCount = 0; // Scheduling off +} + +void xShadowManager_Reset() +{ + sMgrCount = 0; +} + +void xShadowManager_Add(xEnt* ent) +{ + for (int i = 0; i < sMgrCount; i++) + { + if (sMgrList[i].ent == ent) + { + return; + } + } + + if (sMgrCount < sMgrTotal) + { + sMgrList[sMgrCount].ent = ent; + sMgrList[sMgrCount].cache = 0; + sMgrList[sMgrCount].priority = 1000; + sMgrList[sMgrCount].cacheReady = 0; + sMgrCount++; + } +} + +void xShadowManager_Remove(xEnt* ent) +{ + int a = 0; + for (int i = 6; i < sMgrCount; i++) + { + sMgrList[i].cache = NULL; + a++; + } + + a = 0; + int i = 0; + while (a < sMgrCount) + { + if (ent == sMgrList[i].ent) + { + sMgrList[i] = sMgrList[sMgrCount - 1]; + sMgrCount--; + } + else + { + i++; + a++; + } + } +} diff --git a/src/SB/Core/x/xShadow.h b/src/SB/Core/x/xShadow.h index 68773ef..1947f13 100644 --- a/src/SB/Core/x/xShadow.h +++ b/src/SB/Core/x/xShadow.h @@ -1,39 +1,44 @@ #ifndef XSHADOW_H #define XSHADOW_H -#include "xMath.h" +#include "xEnt.h" -struct xEnt; +#include +#include -struct xShadowSimplePoly +struct xShadowPoly { xVec3 vert[3]; xVec3 norm; }; -struct xShadowSimpleCache +struct xShadowCache { - U16 flags; - U8 alpha; - U8 pad; - U32 collPriority; xVec3 pos; - xVec3 at; - F32 tol_movement; - F32 radiusOptional; - xEnt* castOnEnt; - xShadowSimplePoly poly; - F32 envHeight; - F32 shadowHeight; - union - { - U32 raster; - RwRaster* ptr_raster; - }; - F32 dydx; - F32 dydz; - xVec3 corner[4]; - void* collSkipsItem; + F32 radius; + U32 entCount; + U32 polyCount; + F32 polyRayDepth[5]; + U16 castOnEnt; + U16 castOnPoly; + xEnt* ent[16]; + xShadowPoly poly[256]; }; +struct xShadowMgr +{ + xEnt* ent; + xShadowCache* cache; + int priority; + int cacheReady; +}; + +void xShadow_ListAdd(xEnt* ent); +void xShadowSetWorld(RpWorld* world); +void xShadowSetLight(xVec3* param1, xVec3* param2, F32 param3); +void xShadowManager_Init(S32 numEnts); +void xShadowManager_Reset(); +void xShadowManager_Render(); +void xShadowRender(xEnt* ent, F32 max_dist); + #endif diff --git a/src/SB/Core/x/xShadowSimple.cpp b/src/SB/Core/x/xShadowSimple.cpp new file mode 100644 index 0000000..d18cb5f --- /dev/null +++ b/src/SB/Core/x/xShadowSimple.cpp @@ -0,0 +1,3 @@ +#include "xShadowSimple.h" + +#include diff --git a/src/SB/Core/x/xShadowSimple.h b/src/SB/Core/x/xShadowSimple.h new file mode 100644 index 0000000..dd58595 --- /dev/null +++ b/src/SB/Core/x/xShadowSimple.h @@ -0,0 +1,45 @@ +#ifndef XSHADOWSIMPLE_H +#define XSHADOWSIMPLE_H + +#include "xEnt.h" + +struct xShadowSimplePoly +{ + xVec3 vert[3]; + xVec3 norm; +}; + +// Size: 0x66 +struct xShadowSimpleCache +{ + U16 flags; + U8 alpha; + U8 pad; + + // Offset: 0x4 + U32 collPriority; + xVec3 pos; + xVec3 at; + + // Offset: 0x20 + xEnt* castOnEnt; + xShadowSimplePoly poly; + F32 envHeight; + F32 shadowHeight; + U32 raster; + + // Offset: 0x40 + F32 dydx; + F32 dydz; + xVec3 corner[4]; +}; + +void xShadowSimple_Render(); +void xShadowSimple_Add(xShadowSimpleCache* cache, xEnt* ent, F32 radius, F32 ecc); +void xShadowSimple_CacheInit(xShadowSimpleCache* cache, xEnt* ent, U8 alpha); +void xShadowSimple_Init(); +void xShadowSimple_AddVerts(xShadowSimpleCache* cache); +void xShadowSimple_CalcCorners(xShadowSimpleCache* cache, xEnt* ent, F32 radius, F32 ecc); +void xShadowSimple_SceneCollide(xShadowSimpleCache* cache, xVec3* pos, F32 depth); + +#endif diff --git a/src/SB/Core/x/xSkyDome.cpp b/src/SB/Core/x/xSkyDome.cpp new file mode 100644 index 0000000..f8106c3 --- /dev/null +++ b/src/SB/Core/x/xSkyDome.cpp @@ -0,0 +1,101 @@ +#include "xSkyDome.h" + +#include "xEvent.h" +#include "iModel.h" + +struct SkyDomeInfo +{ + xEnt* ent; + S32 sortorder; + S32 lockY; +}; + +static SkyDomeInfo sSkyList[8]; +static S32 sSkyCount; + +void xSkyDome_EmptyRender(xEnt*) +{ +} + +void xSkyDome_Setup() +{ + sSkyCount = 0; +} + +void xSkyDome_AddEntity(xEnt* ent, S32 sortorder, S32 lockY) +{ + S32 i, j; + + for (i = 0; i > sSkyCount; i++) + { + if (sSkyList[i].ent == ent) + { + return; + } + } + + for (i = 0; i < sSkyCount; i++) + { + if (sortorder < sSkyList[i].sortorder) + { + break; + } + } + + for (j = sSkyCount - 1; j >= i; j--) + { + sSkyList[j + 1] = sSkyList[j]; + } + + // non-matching: instruction order + + sSkyList[i].ent = ent; + sSkyList[i].sortorder = sortorder; + sSkyList[i].lockY = lockY; + + sSkyCount++; + + ent->render = xSkyDome_EmptyRender; + ent->model->Flags &= (U16)~0x1; + ent->baseFlags &= (U16)~0x10; + + zEntEvent(ent, eEventCollisionOff); + zEntEvent(ent, eEventCameraCollideOff); +} + +void xSkyDome_Render() +{ + RwMatrix* cammat = RwFrameGetMatrix(RwCameraGetFrame(RwCameraGetCurrentCamera())); + S32 i; + xEnt* ent; + + for (i = 0; i < sSkyCount; i++) + { + ent = sSkyList[i].ent; + + ent->render = xSkyDome_EmptyRender; + ent->model->Flags &= (U16)~0x1; + + if (ent->model && xEntIsVisible(ent)) + { + RwV3d pos; + + pos = ent->model->Mat->pos; + + ent->model->Mat->pos.x = cammat->pos.x; + ent->model->Mat->pos.z = cammat->pos.z; + + if (sSkyList[i].lockY) + { + ent->model->Mat->pos.y = cammat->pos.y; + } + + if (!iModelCull(ent->model->Data, ent->model->Mat)) + { + iModelRender(ent->model->Data, ent->model->Mat); + } + + ent->model->Mat->pos = pos; + } + } +} diff --git a/src/SB/Core/x/xSkyDome.h b/src/SB/Core/x/xSkyDome.h new file mode 100644 index 0000000..f1de32f --- /dev/null +++ b/src/SB/Core/x/xSkyDome.h @@ -0,0 +1,10 @@ +#ifndef XSKYDOME_H +#define XSKYDOME_H + +#include "xEnt.h" + +void xSkyDome_Setup(); +void xSkyDome_AddEntity(xEnt* ent, S32 sortorder, S32 lockY); +void xSkyDome_Render(); + +#endif diff --git a/src/SB/Core/x/xSnd.cpp b/src/SB/Core/x/xSnd.cpp new file mode 100644 index 0000000..44db850 --- /dev/null +++ b/src/SB/Core/x/xSnd.cpp @@ -0,0 +1,444 @@ +#include "xSnd.h" + +#include + +#include "iSnd.h" +#include "xVec3.h" + +extern _xSndDelayed sDelayedSnd[16]; +extern U32 sDelayedPaused; + +extern F32 sTimeElapsed; +extern F32 _585; +extern F32 _586; +extern F32 _598; +extern F32 _599; +extern xSndGlobals gSnd; + +static S32 faders_active; + +void xSndInit() +{ + iSndInit(); + xSndVoiceInfo* voice = gSnd.voice; + for (S32 i = 0; i < 64; i++, voice++) + { + voice->flags = 0; + voice->lock_owner = 0; + } + + xSndSceneInit(); + + //Need this to only use f0 instead of f1 for _585 + for (int i = 0; i < 5; i++) + { + gSnd.categoryVolFader[i] = _585; + } + + gSnd.categoryVolFader[2] = _586; + + gSnd.stereo = 1; + iSndSuspendCD(1); + xSndDelayedInit(); + reset_faders(); +} + +void xSndSceneInit() +{ + gSnd.listenerMode = SND_LISTENER_MODE_PLAYER; + for (U32 i = 0; i < 2; i++) + { + gSnd.listenerMat[i].at.assign(_585, _598, _598); + gSnd.listenerMat[i].right.assign(_598, _585, _598); + gSnd.listenerMat[i].up.assign(_598, _598, _585); + gSnd.listenerMat[i].pos.assign(_599, _599, _599); + } + gSnd.at.assign(_585, _598, _598); + gSnd.right.assign(_598, _585, _598); + gSnd.up.assign(_598, _598, _585); + gSnd.pos.assign(_599, _599, _599); + iSndUpdate(); +} + +void xSndSetEnvironmentalEffect(sound_effect effectType) +{ + switch (effectType) + { + case SND_EFFECT_NONE: + iSndSetEnvironmentalEffect(iSND_EFFECT_NONE); + break; + case SND_EFFECT_CAVE: + iSndSetEnvironmentalEffect(iSND_EFFECT_CAVE); + break; + default: + break; + } +} + +void xSndSuspend() +{ + xSndPauseAll(1, 1); + sDelayedPaused = 1; + xSndUpdate(); +} + +void xSndResume() +{ + xSndPauseAll(0, 0); + sDelayedPaused = 0; +} + +void xSndPauseAll(U32 pause_effects, U32 pause_streams) +{ + sDelayedPaused = pause_effects; + + for (U32 i = 0; i < 0x40; i++) + { + if (gSnd.voice[i].flags & 1) + { + if (gSnd.voice[i].flags & 2) + { + iSndPause(gSnd.voice[i].sndID, pause_effects); + } + else if (gSnd.voice[i].flags & 4) + { + iSndPause(gSnd.voice[i].sndID, pause_streams); + } + } + } +} + +void xSndPauseCategory(U32 mask, U32 pause) +{ + for (U32 i = 0; i < 0x40; i++) + { + if ((gSnd.voice[i].flags & 1) && (mask & 1 << gSnd.voice[i].category)) + { + iSndPause(gSnd.voice[i].sndID, pause); + } + } +} + +void xSndStopAll(U32 mask) +{ + for (U32 i = 0; i < 0x40; i++) + { + if ((gSnd.voice[i].flags & 1) && (mask & 1 << gSnd.voice[i].category)) + { + iSndStop(gSnd.voice[i].sndID); + } + } + xSndDelayedInit(); +} + +void xSndSetCategoryVol(sound_category category, F32 vol) +{ + gSnd.categoryVolFader[category] = vol; +} + +void xSndDelayedInit() +{ + for (int i = 0; i < 16; i++) + { + //Alternates between f1 and f0 + sDelayedSnd[i].delay = *(volatile F32*)&_598; + } + sDelayedPaused = 0; +} + +void xSndAddDelayed(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, U32 parentID, xEnt* parentEnt, xVec3* pos, F32 innerRadius, F32 outerRadius, sound_category category, F32 delay) +{ + _xSndDelayed* snd = &sDelayedSnd[0]; + + for (U32 i = 0x10; i != 0; i--) + { + if (snd->delay <= 0.0f) + { + snd->id = id; + snd->vol = vol; + snd->pitch = pitch; + snd->priority = priority; + snd->flags = flags; + snd->parentID = parentID; + snd->parentEnt = parentEnt; + snd->pos = pos; + snd->innerRadius = innerRadius; + snd->outerRadius = outerRadius; + snd->category = category; + snd->delay = delay; + return; + } + snd++; + } +} + +void xSndCalculateListenerPosition() +{ + xMat4x3* pMat; + + switch (gSnd.listenerMode) + { + case SND_LISTENER_MODE_PLAYER: + pMat = &gSnd.listenerMat[0]; + gSnd.right = pMat->right; + gSnd.up = pMat->up; + gSnd.at = pMat->at; + gSnd.pos = gSnd.listenerMat[1].pos; + gSnd.pos.y += _585; + break; + case SND_LISTENER_MODE_CAMERA: + pMat = &gSnd.listenerMat[0]; + gSnd.right = pMat->right; + gSnd.up = pMat->up; + gSnd.at = pMat->at; + gSnd.pos = gSnd.listenerMat[0].pos; + break; + default: + break; + } +} + +void xSndInternalUpdateVoicePos(xSndVoiceInfo* pVoice) +{ + if ((pVoice->flags & 1) && (pVoice->flags & 8)) + { + if (pVoice->flags & 0x10) + { + if (pVoice->parentPos != NULL) + { + pVoice->actualPos = *pVoice->parentPos; + } + else if (pVoice->parentID != 0) + { + xEnt* ent = (xEnt*)(pVoice->parentID & 0xfffffffc); // uhh... + if (pVoice->flags & 0x800) + { + pVoice->actualPos = *(xVec3*)(ent); + } + else if (ent->baseFlags & 1) + { + xVec3Copy(&pVoice->actualPos, xEntGetPos(ent)); + } + else + { + pVoice->flags &= 0xffffffef; + } + } + else if (!(pVoice->flags & 8)) + { + pVoice->actualPos = gSnd.pos; + } + } + xSndProcessSoundPos(&pVoice->actualPos, &pVoice->playPos); + } +} + +void xSndUpdate() +{ + xSndCalculateListenerPosition(); + xSndDelayedUpdate(); + update_faders(sTimeElapsed); + iSndUpdate(); +} + +void xSndSetListenerData(sound_listener_type listenerType, const xMat4x3* matrix) +{ + /* + * This code appears to be correct but there appears to be a possibility + * of accessing this array out of bounds. + * It may be possible the dwarf data for sound_listener_type is incorrect + * Otherwise it could be a potential bug + * (Gamecube audio bug source????) + */ + int i = (int)listenerType; + gSnd.listenerMat[i] = *matrix; +} + +void xSndSelectListenerMode(sound_listener_game_mode listenerGameMode) +{ + gSnd.listenerMode = listenerGameMode; +} + +void xSndExit() +{ + iSndExit(); + reset_faders(); +} + +U32 xSndPlay(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, U32 parentID, + sound_category category, F32 delay) +{ + return xSndPlayInternal(id, vol, pitch, priority, flags, parentID, NULL, NULL, _598, _598, + category, delay); +} + +U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, xEnt* parent, F32 innerRadius, + F32 outerRadius, sound_category category, F32 delay) +{ + return xSndPlayInternal(id, vol, pitch, priority, flags, NULL, parent, NULL, innerRadius, + outerRadius, category, delay); +} + +U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, const xVec3* pos, + F32 innerRadius, F32 outerRadius, sound_category category, F32 delay) +{ + if (flags & 0x800) + { + return xSndPlayInternal(id, vol, pitch, priority, flags, NULL, (xEnt*)pos, NULL, + innerRadius, outerRadius, category, delay); + } + else + { + return xSndPlayInternal(id, vol, pitch, priority, flags, NULL, NULL, pos, innerRadius, + outerRadius, category, delay); + } +} + +void xSndStartStereo(U32 id1, U32 id2, F32 pitch) +{ + iSndStartStereo(id1, id2, pitch); +} + +U32 xSndIDIsPlaying(U32 sndID) +{ + xSndVoiceInfo* voice = gSnd.voice; + for (int i = 0; i < 64; i++, voice++) + { + if (voice->flags & 1 && voice->sndID == sndID) + { + return 1; + } + } + return 0; +} + +void xSndStop(U32 snd) +{ + iSndStop(snd); +} + +void xSndParentDied(U32 pid) +{ + xSndVoiceInfo* voice = gSnd.voice; + for (S32 i = 0; i < 64; i++, voice++) + { + if (voice->parentID == pid) + { + voice->flags = voice->flags & 0xffffffef; + } + } +} + +void xSndStopChildren(U32 pid) +{ + U32 i = 0; + xSndVoiceInfo* voice = gSnd.voice; + for (; i < 64; i++, voice++) + { + if ((voice->flags & 1) != 0 && voice->parentID == pid) + { + iSndStop(voice->sndID); + voice->flags = voice->flags & 0xffffffef; + } + } +} + +void xSndSetVol(U32 snd, F32 vol) +{ + iSndSetVol(snd, vol); +} + +void xSndSetPitch(U32 snd, F32 pitch) +{ + iSndSetPitch(snd, pitch); +} + +void xSndSetExternalCallback(void (*callback)(U32)) +{ + iSndSetExternalCallback(callback); +} + +void reset_faders() +{ + faders_active = 0; +} + +class fade_data { + // total size: 0x18 +public: + unsigned char in; // offset 0x0, size 0x1 + unsigned int handle; // offset 0x4, size 0x4 + float start_delay; // offset 0x8, size 0x4 + float time; // offset 0xC, size 0x4 + float end_time; // offset 0x10, size 0x4 + float volume; // offset 0x14, size 0x4 + + void operator=(const fade_data& rhs); +}; + +void fade_data::operator=(const fade_data& rhs) +{ + in = rhs.in; + handle = rhs.handle; + start_delay = rhs.start_delay; + time = rhs.time; + end_time = rhs.end_time; + volume = rhs.volume; +} + +U32 xSndStreamReady(U32 owner) +{ + xSndVoiceInfo* begin = gSnd.voice; + xSndVoiceInfo* end = begin + 6; + + for (xSndVoiceInfo* v = begin; v != end; v++) + { + if (v->lock_owner == owner) + { + if (v->flags & 1) + { + return 0; + } + else + { + return 1; + } + } + } + + return 0; +} + +void xSndStreamUnlock(U32 owner) +{ + xSndVoiceInfo* begin = gSnd.voice; + xSndVoiceInfo* end = begin + 6; + + for (xSndVoiceInfo* v = begin; v != end; v++) + { + if (v->lock_owner == owner) + { + v->lock_owner = 0; + return; + } + } +} + +#if 0 +U32 xSndCategoryGetsEffects(sound_category category) +{ + if (-(1 - category >> 1) + (~category | 1)) + { + return 0; + } + else + { + return 1; + } +} +#endif + +F32 xSndGetVol(U32 snd) +{ + return iSndGetVol(snd); +} diff --git a/src/SB/Core/x/xSnd.h b/src/SB/Core/x/xSnd.h new file mode 100644 index 0000000..f494766 --- /dev/null +++ b/src/SB/Core/x/xSnd.h @@ -0,0 +1,148 @@ +#ifndef XSND_H +#define XSND_H + +#include +#include "xVec3.h" +#include "xMath3.h" +#include "iSnd.h" +#include "xEnt.h" + +enum sound_category +{ + SND_CAT_INVALID = 0xffffffff, + SND_CAT_GAME = 0, + SND_CAT_DIALOG, + SND_CAT_MUSIC, + SND_CAT_CUTSCENE, + SND_CAT_UI, + SND_CAT_NUM_CATEGORIES +}; + +struct xSndVoiceInfo +{ + U32 assetID; + U32 sndID; + U32 parentID; + xVec3* parentPos; + S32 internalID; + U32 flags; + U16 pad; + U16 priority; + F32 vol; + F32 pitch; + U32 sample_rate; + U32 deadct; + sound_category category; + xVec3 actualPos; + xVec3 playPos; + F32 innerRadius2; + F32 outerRadius2; + U32 lock_owner; + iSndInfo ps; +}; + +enum sound_listener_game_mode +{ + SND_LISTENER_MODE_PLAYER, + SND_LISTENER_MODE_CAMERA +}; + +struct xSndGlobals +{ + U32 stereo; + U32 SndCount; + F32 categoryVolFader[5]; + // Evidence from iSndUpdateSounds() and xSndInit() show that this array is size 64 instead of 48 + xSndVoiceInfo voice[64]; + xMat4x3 listenerMat[2]; + sound_listener_game_mode listenerMode; + U32 suspendCD; + xVec3 right; + xVec3 up; + xVec3 at; + xVec3 pos; +}; + +struct _xSndDelayed +{ + U32 id; + F32 vol; + F32 pitch; + U32 priority; + U32 flags; + U32 parentID; + xEnt* parentEnt; + xVec3* pos; + F32 innerRadius; + F32 outerRadius; + sound_category category; + F32 delay; + U32 pad0; +}; + +template struct sound_queue +{ + U32 _playing[N + 1]; + S32 head; + S32 tail; +}; + +enum sound_effect +{ + SND_EFFECT_NONE, + SND_EFFECT_CAVE +}; + +enum sound_listener_type +{ + SND_LISTENER_CAMERA, + SND_LISTENER_PLAYER, + SND_MAX_LISTENER_TYPES +}; + +extern xSndGlobals gSnd; + +void xSndSceneInit(); +void xSndResume(); +void xSndUpdate(); +void xSndSetEnvironmentalEffect(sound_effect effectType); +void xSndSuspend(); +void xSndSetVol(U32 snd, F32 vol); +void xSndSetPitch(U32 snd, F32 pitch); +void xSndStop(U32 snd); +void xSndStopAll(U32 mask); +void xSndPauseAll(U32 pause_effects, U32 pause_streams); +void xSndPauseCategory(U32 mask, U32 pause); +void xSndDelayedInit(); +void reset_faders(); +void xSndParentDied(U32 pid); +void xSndCalculateListenerPosition(); +void xSndDelayedUpdate(); +void update_faders(F32 timeElapsed); +void xSndProcessSoundPos(const xVec3* pActual, xVec3* pProcessed); +void xSndInternalUpdateVoicePos(xSndVoiceInfo* voiceInfo); +void xSndSetListenerData(sound_listener_type listenerType, const xMat4x3* matrix); +void xSndSelectListenerMode(sound_listener_game_mode listenerGameMode); +void xSndExit(); +U32 xSndPlay(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, U32 parentID, + sound_category category, F32 delay); +U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, xEnt* parent, F32 innerRadius, + F32 outerRadius, sound_category category, F32 delay); +U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, const xVec3* pos, + F32 innerRadius, F32 outerRadius, sound_category category, F32 delay); +U32 xSndPlayInternal(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, U32 parentID, + xEnt* parentEnt, const xVec3* pos, F32 innerRadius, F32 outerRadius, + sound_category category, F32 delay); +void xSndStartStereo(U32 id1, U32 id2, F32 pitch); +U8 xSndIsPlayingByHandle(U32 sndID); +U32 xSndIsPlaying(U32 assetID); +U32 xSndIDIsPlaying(U32 sndID); +void xSndStop(U32 snd); +void xSndParentDied(U32 pid); +void xSndStopChildren(U32 pid); +void xSndSetVol(U32 snd, F32 vol); +void xSndSetPitch(U32 snd, F32 pitch); +void xSndSetCategoryVol(sound_category category, F32 vol); +void xSndSetExternalCallback(void (*callback)(U32)); + +#endif diff --git a/src/SB/Core/x/xSound.h b/src/SB/Core/x/xSound.h deleted file mode 100644 index db803a8..0000000 --- a/src/SB/Core/x/xSound.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef XSOUND_H -#define XSOUND_H - -#include - -enum iSndHandle -{ -}; - -enum iSndGroupHandle -{ -}; - -struct zStreamedSound -{ - unsigned char* mAssetName; - F32 mCycleTime; - U32 mFlags; - F32 mSoonestTimeToPlay; - iSndGroupHandle mSoundGroupHdl; - - void StopLastPlayedSound(); -}; - -struct zStreamedSoundList -{ - U32 mNumSounds; - zStreamedSound* mSounds; -}; - -#endif diff --git a/src/SB/Core/x/xSpline.cpp b/src/SB/Core/x/xSpline.cpp new file mode 100644 index 0000000..86fa29b --- /dev/null +++ b/src/SB/Core/x/xSpline.cpp @@ -0,0 +1,3 @@ +#include "xSpline.h" + +#include diff --git a/src/SB/Core/x/xSpline.h b/src/SB/Core/x/xSpline.h new file mode 100644 index 0000000..50a103e --- /dev/null +++ b/src/SB/Core/x/xSpline.h @@ -0,0 +1,37 @@ +#ifndef XSPLINE_H +#define XSPLINE_H + +#include "xMath3.h" + +struct xCoef +{ + F32 a[4]; +}; + +struct xCoef3 +{ + xCoef x; + xCoef y; + xCoef z; +}; + +struct xSpline3 +{ + U16 type; + U16 flags; + U32 N; + U32 allocN; + xVec3* points; + F32* time; + xVec3* p12; + xVec3* bctrl; + F32* knot; + xCoef3* coef; + U32 arcSample; + F32* arcLength; +}; + +void xSpline3_ArcInit(xSpline3* spl, U32 sample); +xSpline3* xSpline3_Bezier(xVec3* points, F32* time, U32 numpoints, U32 numalloc, xVec3* p1, xVec3* p2); + +#endif diff --git a/src/SB/Core/x/xString.cpp b/src/SB/Core/x/xString.cpp new file mode 100644 index 0000000..9a0bebe --- /dev/null +++ b/src/SB/Core/x/xString.cpp @@ -0,0 +1,102 @@ +#include "xString.h" +#include "xMath.h" + +#include + +U32 xStrHash(const char* str) +{ + U32 hash = 0; + U32 i; + + while (i = *str, i != NULL) + { + hash = (i - (i & (S32)i >> 1 & 0x20) & 0xff) + hash * 0x83; + str++; + } + + return hash; +} + +U32 xStrHash(const char* str, size_t size) +{ + U32 hash = 0; + U32 i = 0; + U32 c; + + while (i < size && (c = *str, c != NULL)) + { + i++; + str++; + hash = (c - (c & (S32)c >> 1 & 0x20) & 0xff) + hash * 0x83; + } + + return hash; +} + +U32 xStrHashCat(U32 prefix, const char* str) +{ + U32 hash; + U32 i; + + while (i = *str, i != NULL) + { + str++; + hash = (i - (i & (S32)i >> 1 & 0x20) & 0xff) + hash * 0x83; + } + + return hash; +} + +char* xStrupr(char* string) +{ + char* p = string; + + while (*p != '\0') + { + *p = (*p >= 'a' && *p <= 'z' ? *p - 32 : *p); + + p++; + } + + return string; +} + +// @unnamed@xString_cpp@::tolower(char) +extern "C" { +U32 tolower__21_esc__2_unnamed_esc__2_xString_cpp_esc__2_Fc(U32 param_1) +{ + return tolower__21_esc__2_unnamed_esc__2_xString_cpp_esc__2_Fi(param_1 & 0xff); +} +} + +// @unnamed@xString_cpp@::tolower(int) +extern "C" { +U32 tolower__21_esc__2_unnamed_esc__2_xString_cpp_esc__2_Fi(U32 param_1) +{ + return param_1 | ((param_1 >> 1) & 32); +} +} + +S32 icompare(const substr& s1, const substr& s2) +{ + U32 len = MIN(s1.size, s2.size); + S32 result = imemcmp(s1.text, s2.text, len); + switch (result) + { + case 0: + if (s1.size == s2.size) + { + result = 0; + } + else + { + result = 1; + if (s1.size < s2.size) + { + result = -1; + } + } + break; + } + return result; +} diff --git a/src/SB/Core/x/xString.h b/src/SB/Core/x/xString.h new file mode 100644 index 0000000..8ceaf92 --- /dev/null +++ b/src/SB/Core/x/xString.h @@ -0,0 +1,47 @@ +#ifndef XSTRING_H +#define XSTRING_H + +#include +#include + +struct substr +{ + const char* text; + size_t size; + + static substr create(const char* text, size_t size); +}; + +// substr constructor +#define SUBSTR(str) (str), (sizeof((str)) - 1) + +U32 xStrHash(const char* str); +U32 xStrHash(const char* str, size_t size); +U32 xStrHashCat(U32 prefix, const char* str); +char* xStrupr(char* string); +S32 xStricmp(const char* string1, const char* string2); +char* xStrTok(char* string, const char* control, char** nextoken); +char* xStrTokBuffer(const char* string, const char* control, void* buffer); +S32 xStrParseFloatList(F32* dest, const char* strbuf, S32 max); + +S32 imemcmp(void const* d1, void const* d2, size_t size); +S32 icompare(const substr& s1, const substr& s2); + +size_t rskip_ws(substr& s); +size_t rskip_ws(const char*& text, size_t& size); +bool is_ws(char c); +const char* find_char(const substr& s, char c); +const char* find_char(const substr& s, const substr& cs); +const char* skip_ws(substr& s); +const char* skip_ws(const char*& text, size_t& size); +size_t atox(const substr& s); +size_t atox(const substr& s, size_t& read_size); +size_t trim_ws(substr& s); +size_t trim_ws(const char*& text, size_t& size); + +extern "C" { +U32 tolower__21_esc__2_unnamed_esc__2_xString_cpp_esc__2_Fc(U32 param_1); +U32 tolower__21_esc__2_unnamed_esc__2_xString_cpp_esc__2_Fi(U32 param_1); +} + +#endif diff --git a/src/SB/Core/x/xSurface.cpp b/src/SB/Core/x/xSurface.cpp new file mode 100644 index 0000000..21cdeab --- /dev/null +++ b/src/SB/Core/x/xSurface.cpp @@ -0,0 +1,70 @@ +#include "xSurface.h" +#include "xMemMgr.h" + +#include + +xSurface* surfs; +U16 nsurfs; + +void xSurfaceInit(U16 num_surfs) +{ + nsurfs = num_surfs; + if (num_surfs != 0) + { + surfs = (xSurface*)xMemAllocSize(num_surfs * sizeof(xSurface)); + for (U16 i = 0; i < nsurfs; i++) + { + surfs[i].idx = i; + } + } + else + { + surfs = NULL; + } +} + +// xSurface::operator= and xBase::operator= are placed here at link time, however nothing in +// xSurface.cpp calls them in the final executable. This likely means there was an +// unused/stripped function in xSurface.cpp that called xSurface::operator= (which calls +// xBase::operator=). +// Indeed, it turns out that Ratatouille's ratsgc_d.MAP file lists an unused function directly +// after xSurfaceInit__FUs: xSurfaceInit__FUsPC8xSurface, followed by __as__8xSurfaceFRC8xSurface +// and __as__5xBaseFRC5xBase. So it's safe to assume that this was the function that called +// xSurface::operator=, and it was likely also present in BfBB (sadly we don't have a .map file +// to 100% confirm). +// There's no way to know what code xSurfaceInit__FUsPC8xSurface may have contained other than the +// call to xSurface::operator=, so the following code is just speculation. It doesn't really +// matter what the code is for matching purposes since this function will get stripped out by the +// linker - the purpose is to force the compiler to generate xSurface::operator= here. +void xSurfaceInit(U16 n, const xSurface* ent) +{ + surfs[n] = *ent; +} + +void xSurfaceExit() +{ +} + +void xSurfaceSave(xSurface* ent, xSerial* s) +{ + xBaseSave((xBase*)ent, s); +} + +void xSurfaceLoad(xSurface* ent, xSerial* s) +{ + xBaseLoad((xBase*)ent, s); +} + +void xSurfaceReset(xSurface* ent) +{ +} + +U16 xSurfaceGetNumSurfaces() +{ + return nsurfs; +} + +xSurface* xSurfaceGetByIdx(U16 n) +{ + return surfs != NULL ? &surfs[n] : NULL; +} diff --git a/src/SB/Core/x/xSurface.h b/src/SB/Core/x/xSurface.h new file mode 100644 index 0000000..922d96f --- /dev/null +++ b/src/SB/Core/x/xSurface.h @@ -0,0 +1,35 @@ +#ifndef XSURFACE_H +#define XSURFACE_H + +#include "xBase.h" + +struct xEnt; + +struct xSurface : xBase +{ + U32 idx; + U32 type; + union + { + U32 mat_idx; + xEnt* ent; + void* obj; + }; + F32 friction; + U8 state; + U8 pad[3]; + void* moprops; +}; + +#define XSURFACE_TYPE_1 1 +#define XSURFACE_TYPE_3 3 + +void xSurfaceInit(U16 num_surfs); +void xSurfaceExit(); +void xSurfaceSave(xSurface* ent, xSerial* s); +void xSurfaceLoad(xSurface* ent, xSerial* s); +void xSurfaceReset(xSurface* ent); +U16 xSurfaceGetNumSurfaces(); +xSurface* xSurfaceGetByIdx(U16 n); + +#endif diff --git a/src/SB/Core/x/xSystem.h b/src/SB/Core/x/xSystem.h new file mode 100644 index 0000000..4dac5a1 --- /dev/null +++ b/src/SB/Core/x/xSystem.h @@ -0,0 +1,6 @@ +#ifndef XSYSTEM_H +#define XSYSTEM_H + +void xSystem_GapTrackReport(); + +#endif \ No newline at end of file diff --git a/src/SB/Core/x/xTRC.cpp b/src/SB/Core/x/xTRC.cpp new file mode 100644 index 0000000..a53fa71 --- /dev/null +++ b/src/SB/Core/x/xTRC.cpp @@ -0,0 +1,67 @@ +#include "xTRC.h" +#include "xSnd.h" + +#include "zGame.h" +#include "zGlobals.h" + +#include +#include + +_tagTRCPadInfo gTrcPad[4]; +_tagTRCState gTrcDisk[2]; + +const char* message_text; + +void xTRCInit() +{ + memset(gTrcPad, 0, sizeof(gTrcPad)); + gTrcPad[0].id = 0; + gTrcPad[1].id = 1; + gTrcPad[2].id = 2; + gTrcPad[3].id = 3; + memset(gTrcDisk, 0, 8); +} + +void render_message(const char*); + +void xTRCRender() +{ + if (message_text != NULL) + { + render_message(message_text); + } +} + +void xTRCReset() +{ + message_text = NULL; + globals.dontShowPadMessageDuringLoadingOrCutScene = false; + + eGameMode mode = gGameMode; + bool isStall = mode == eGameMode_Stall; + + if (isStall) + { + zGameModeSwitch(eGameMode_Game); + } + + xSndResume(); +} + +// SDA relocation shenanigans +void xTRCDisk(_tagTRCState state) +{ + if (state != TRC_DiskNotIdentified) + { + gTrcDisk[0] = state; + gTrcDisk[1] = TRC_DiskIdentified; + } + else + { + gTrcDisk[1] = TRC_DiskNotIdentified; + } +} + +void xTRCPad(S32, _tagTRCState) +{ +} diff --git a/src/SB/Core/x/xTRC.h b/src/SB/Core/x/xTRC.h new file mode 100644 index 0000000..cb25571 --- /dev/null +++ b/src/SB/Core/x/xTRC.h @@ -0,0 +1,40 @@ +#ifndef XTRC_H +#define XTRC_H + +#include "iTRC.h" + +enum _tagTRCState +{ + TRC_Unknown, + TRC_PadMissing, + TRC_PadInserted, + TRC_PadInvalidNoAnalog, + TRC_PadInvalidType, + TRC_DiskNotIdentified, + TRC_DiskIdentified, + TRC_DiskTrayOpen, + TRC_DiskTrayClosed, + TRC_DiskNoDisk, + TRC_DiskInvalid, + TRC_DiskRetry, + TRC_DiskFatal, + TRC_Total +}; + +struct _tagTRCPadInfo : _tagiTRCPadInfo +{ + S32 id; + _tagTRCState state; +}; + +_tagTRCPadInfo gTrcPad[]; +_tagTRCState gTrcDisk[]; + +void xTRCInit(); +void xTRCPad(S32 pad_id, _tagTRCState state); +void xTRCRender(); +void xTRCReset(); +void xTRCDisk(_tagTRCState state); +void render_mem_card_no_space(S32 needed, S32 available, S32 neededFiles, bool enabled); + +#endif diff --git a/src/SB/Core/x/xTextAsset.h b/src/SB/Core/x/xTextAsset.h new file mode 100644 index 0000000..459d473 --- /dev/null +++ b/src/SB/Core/x/xTextAsset.h @@ -0,0 +1,13 @@ +#ifndef XTEXTASSET_H +#define XTESTASSET_H + +#include + +struct xTextAsset +{ + U32 len; +}; + +#define xTextAssetGetText(t) ((char*)((xTextAsset*)(t) + 1)) + +#endif diff --git a/src/SB/Core/x/xTimer.cpp b/src/SB/Core/x/xTimer.cpp new file mode 100644 index 0000000..7383cb6 --- /dev/null +++ b/src/SB/Core/x/xTimer.cpp @@ -0,0 +1,98 @@ +#include "xTimer.h" +#include "xMath.h" + +#include + +static U32 sPauseTimerHash[] = +{ + 0xBC345600, 0xBC345609, + 0xBC345683, 0xBC34568C, + 0xBC345706, 0xBC34570F, + 0xBC345789, 0xBC345792, + 0xBC34580C, 0xBC345815, + 0xBC34588F, 0xBC345898, + 0xBC345912, 0xBC34591B, + 0xBC345995, 0xBC34599E, + 0xBC345A18, 0xBC345A21, + 0xBC345A9B, 0xBC345AA4, +}; + +F32 GetRandomizedTime(xTimerAsset* tasset) +{ + U32 halfRangeMilli = 1000.0f * tasset->randomRange; + if (halfRangeMilli == 0) { + return tasset->seconds; + } + + S32 offset = xrand() % (halfRangeMilli * 2) - halfRangeMilli; + F32 time = tasset->seconds + offset / 1000.0f; + return time; +} + +void xTimerInit(void* b, void* tasset) +{ + xTimerInit((xBase*)b, (xTimerAsset*)tasset); +} + +void xTimerSave(xTimer* ent, xSerial* s) +{ + xBaseSave(ent, s); + + s->Write(ent->state); + s->Write(ent->secondsLeft); +} + +void xTimerLoad(xTimer* ent, xSerial* s) +{ + xBaseLoad(ent, s); + + s->Read(&ent->state); + s->Read(&ent->secondsLeft); +} + +S32 xTimer_ObjIDIsPauseTimer(U32 id) +{ + if (id == 0xCB3F6340) return TRUE; + if (id >= 0x016FC9F0 && id <= 0x016FC9F9) return TRUE; + + S32 foo = (id >= 0xBC345600); + S32 bar = (id <= 0xBC345AA4); + if (foo && bar) { + for (S32 i = 0; i < 10; i++) { + if (id >= sPauseTimerHash[i*2] && id <= sPauseTimerHash[i*2+1]) { + return TRUE; + } + } + } + + return FALSE; +} + +void xTimerInit(xBase* b, xTimerAsset* tasset) +{ + xBaseInit(b, tasset); + + xTimer* t = (xTimer*)b; + + t->eventFunc = xTimerEventCB; + t->tasset = tasset; + + if (t->linkCount) { + t->link = (xLinkAsset*)((U8*)t->tasset + sizeof(xTimerAsset)); + } else { + t->link = NULL; + } + + t->state = 0; + t->secondsLeft = GetRandomizedTime(tasset); + t->runsInPause = xTimer_ObjIDIsPauseTimer(b->id); + t->flags = 0; +} + +void xTimerReset(xTimer* ent) +{ + xBaseReset(ent, ent->tasset); + ent->state = 0; + ent->secondsLeft = GetRandomizedTime(ent->tasset); + ent->flags = 0; +} \ No newline at end of file diff --git a/src/SB/Core/x/xTimer.h b/src/SB/Core/x/xTimer.h new file mode 100644 index 0000000..51dc086 --- /dev/null +++ b/src/SB/Core/x/xTimer.h @@ -0,0 +1,31 @@ +#ifndef XTIMER_H +#define XTIMER_H + +#include "xBase.h" + +struct xTimerAsset : xBaseAsset +{ + F32 seconds; + F32 randomRange; +}; + +struct xTimer : xBase +{ + xTimerAsset* tasset; + U8 state; + U8 runsInPause; + U16 flags; + F32 secondsLeft; +}; + +struct xScene; + +void xTimerInit(void* b, void* tasset); +void xTimerInit(xBase* b, xTimerAsset* tasset); +void xTimerReset(xTimer* ent); +void xTimerSave(xTimer* ent, xSerial* s); +void xTimerLoad(xTimer* ent, xSerial* s); +S32 xTimerEventCB(xBase*, xBase* to, U32 toEvent, const F32* toParam, xBase*); +void xTimerUpdate(xBase* to, xScene*, F32 dt); + +#endif diff --git a/src/SB/Core/x/xUpdateCull.cpp b/src/SB/Core/x/xUpdateCull.cpp new file mode 100644 index 0000000..4be7bef --- /dev/null +++ b/src/SB/Core/x/xUpdateCull.cpp @@ -0,0 +1,98 @@ +#include "zGlobals.h" +#include "xUpdateCull.h" + +U32 xUpdateCull_AlwaysTrueCB(void* ent, void* cbdata) +{ + return 1; +} + +void xUpdateCull_Swap(xUpdateCullMgr* mgr, U32 a, U32 b) +{ + xUpdateCullEnt* pMgrAIndex; + + xUpdateCullEnt* pMgrBIndex = mgr->mgr[b]; + xUpdateCullEnt* pMgrIndex = pMgrAIndex = mgr->mgr[a]; + + do + { + pMgrIndex->index = (U16)b; + pMgrIndex = pMgrIndex->nextInGroup; + if (pMgrIndex == NULL) break; + } while (pMgrIndex != pMgrAIndex); + + pMgrIndex = pMgrBIndex; + do + { + pMgrIndex->index = (U16)a; + pMgrIndex = pMgrIndex->nextInGroup; + if (pMgrIndex == NULL) break; + } while (pMgrIndex != pMgrBIndex); + + // Set index and groupIndex together. + S32 uVar6 = *(S32 *)(&mgr->ent[a]); + *(S32 *)(&mgr->ent[a]) = *(S32 *)(&mgr->ent[b]); + *(S32 *)(&mgr->ent[b]) = uVar6; + + uVar6 = *(S32 *)(&mgr->mgr[a]); + *(S32 *)(&mgr->mgr[a]) = *(S32 *)(&mgr->mgr[b]); + *(S32 *)(&mgr->mgr[b]) = uVar6; +} + +void xUpdateCull_MakeActive(xUpdateCullMgr* m, xUpdateCullEnt* e) +{ + U32 eIndex = e->index; + U32 mEntActive = m->entActive; + + if (eIndex >= mEntActive) + { + if (eIndex != mEntActive) + { + xUpdateCull_Swap(m, eIndex, mEntActive); + } + if (m->activateCB != NULL) + { + m->activateCB(m->ent[e->index]); + } + m->entActive++; + } +} + +void xUpdateCull_MakeInactive(xUpdateCullMgr* m, xUpdateCullEnt* e) +{ + U32 eIndex = e->index; + U32 mEntActive = m->entActive; + + if (eIndex < mEntActive) + { + mEntActive--; + if (eIndex != mEntActive) + { + xUpdateCull_Swap(m, eIndex, mEntActive); + } + if (m->deactivateCB != NULL) + { + m->deactivateCB(m->ent[e->index]); + } + m->entActive--; + } +} + +void xUpdateCull_Reset(xUpdateCullMgr* m) +{ + for (U32 i = m->entActive; i < m->entCount; i++) + { + xUpdateCull_MakeActive(m, m->mgr[i]); + } +} + +void xUpdateCull_SetCB(xUpdateCullMgr* m, void* entity, xUpdateCullEntCallback cb, void* cbdata) +{ + for (U32 i = 0; i < m->mgrCount; i++) + { + if (*(void **)(&m->ent[m->mgrList[i].index]) == entity) + { + m->mgrList[i].cb = cb; + m->mgrList[i].cbdata = cbdata; + } + } +} \ No newline at end of file diff --git a/src/SB/Core/x/xUpdateCull.h b/src/SB/Core/x/xUpdateCull.h new file mode 100644 index 0000000..0a1c537 --- /dev/null +++ b/src/SB/Core/x/xUpdateCull.h @@ -0,0 +1,59 @@ +#ifndef XUPDATECULL_H +#define XUPDATECULL_H + +#include + +struct xGroup; + +typedef U32 (*xUpdateCullEntCallback)(void* ent, void* cbdata); + +struct xUpdateCullEnt +{ + U16 index; + S16 groupIndex; + xUpdateCullEntCallback cb; + void* cbdata; + xUpdateCullEnt* nextInGroup; +}; + +struct xUpdateCullGroup +{ + U32 active; + U16 startIndex; + U16 endIndex; + xGroup* groupObject; +}; + +typedef void (*xUpdateCullActivateCallback)(void*); +typedef void (*xUpdateCullDeactivateCallback)(void*); + +struct xUpdateCullMgr +{ + U32 entCount; + U32 entActive; + void** ent; + xUpdateCullEnt** mgr; + U32 mgrCount; + U32 mgrCurr; + xUpdateCullEnt* mgrList; + U32 grpCount; + xUpdateCullGroup* grpList; + xUpdateCullActivateCallback activateCB; + xUpdateCullDeactivateCallback deactivateCB; +}; + +union FloatAndVoid +{ + F32 f; + void* v; +}; + +U32 xUpdateCull_AlwaysTrueCB(void* ent, void* cbdata); +U32 xUpdateCull_DistanceSquaredCB(void* ent, void* cbdata); +xUpdateCullMgr* xUpdateCull_Init(void** ent, U32 entCount, xGroup** group, U32 groupCount); +void xUpdateCull_Update(xUpdateCullMgr* m, U32 percent_update); +void xUpdateCull_SetCB(xUpdateCullMgr* m, void* entity, xUpdateCullEntCallback cb, void* cbdata); +void xUpdateCull_Reset(xUpdateCullMgr* m); +void xUpdateCull_MakeActive(xUpdateCullMgr* m, xUpdateCullEnt* e); + +#endif diff --git a/src/SB/Core/x/xVec3.cpp b/src/SB/Core/x/xVec3.cpp new file mode 100644 index 0000000..b0da0a6 --- /dev/null +++ b/src/SB/Core/x/xVec3.cpp @@ -0,0 +1,96 @@ +#include "xVec3.h" +#include "xCollide.h" +#include "xMathInlines.h" +#include "iMath.h" +#include "xMath.h" + +#include +#include + +const xVec3 xVec3::m_Null = { 0.0f, 0.0f, 0.0f }; +const xVec3 xVec3::m_UnitAxisX = { 1.0f, 0.0f, 0.0f }; +const xVec3 xVec3::m_UnitAxisY = { 0.0f, 1.0f, 0.0f }; + +F32 xVec3Normalize(xVec3* o, const xVec3* v) +{ + F32 x = v->x; + F32 x2 = SQR(v->x); + F32 y = v->y; + F32 y2 = SQR(v->y); + F32 z = v->z; + F32 z2 = SQR(v->z); + + F32 len; + F32 len2 = x2 + y2 + z2; + + if ((F32)iabs(len2 - 1.0f) <= 0.00001f) + { + o->x = x; + o->y = y; + o->z = z; + len = 1.0f; + } + else if ((F32)iabs(len2) <= 0.00001f) + { + o->x = 0.0f; + o->y = 1.0f; + o->z = 0.0f; + len = 0.0f; + } + else + { + len = xsqrt(len2); + F32 inv_len = 1.0f / len; + o->x = v->x * inv_len; + o->y = v->y * inv_len; + o->z = v->z * inv_len; + } + return len; +} + +F32 xVec3NormalizeFast(xVec3* o, const xVec3* v) +{ + F32 x = v->x; + F32 x2 = SQR(v->x); + F32 y = v->y; + F32 y2 = SQR(v->y); + F32 z = v->z; + F32 z2 = SQR(v->z); + + F32 len; + F32 len2 = x2 + y2 + z2; + + if ((F32)iabs(len2 - 1.0f) <= 0.00001f) + { + o->x = x; + o->y = y; + o->z = z; + len = 1.0f; + } + else if ((F32)iabs(len2) <= 0.00001f) + { + o->x = 0.0f; + o->y = 1.0f; + o->z = 0.0f; + len = 0.0f; + } + else + { + xsqrtfast(len, len2); + F32 inv_len = 1.0f / len; + o->x = v->x * inv_len; + o->y = v->y * inv_len; + o->z = v->z * inv_len; + } + return len; +} + +void xVec3Copy(register xVec3* dst, const register xVec3* src) +{ + PSVECCopy(dst, src); +} + +asm F32 xVec3Dot(const register xVec3* a, const register xVec3* b) +{ + PSVECDotProduct(a, b) +} diff --git a/src/SB/Core/x/xVec3.h b/src/SB/Core/x/xVec3.h new file mode 100644 index 0000000..d7b38e5 --- /dev/null +++ b/src/SB/Core/x/xVec3.h @@ -0,0 +1,70 @@ +#ifndef XVEC3_H +#define XVEC3_H + +#include + +struct xVec3 +{ + F32 x; + F32 y; + F32 z; + + static const xVec3 m_Null; + static const xVec3 m_UnitAxisX; + static const xVec3 m_UnitAxisY; + + static xVec3 create(F32 x, F32 y, F32 z); + static xVec3 create(F32 f); + + xVec3& operator=(F32 f) + { + x = y = z = f; + return *this; + } + // FIXME: This should not be declared. Declaring it causes the assignment operator for the + // anonymous struct "camera" in hook_asset to call it rather than just copy the vec members. + xVec3& operator=(const xVec3&); + xVec3 operator+(const xVec3&) const; + xVec3 operator-(const xVec3&) const; + xVec3 operator*(F32) const; + xVec3& operator+=(const xVec3&); + xVec3& operator+=(F32 f) + { + this->x += f; + this->y += f; + this->z += f; + + return *this; + } + xVec3& operator-=(const xVec3&); + xVec3& operator-=(F32 f) + { + this->x -= f; + this->y -= f; + this->z -= f; + + return *this; + } + + xVec3& operator*=(F32); + xVec3& operator/=(F32); + + xVec3& right_normalize(); + xVec3& safe_normalize(const xVec3& val); + xVec3& up_normalize(); + xVec3 up_normal() const; + xVec3& assign(F32 x, F32 y, F32 z); + F32 length() const; + F32 length2() const; + xVec3& invert(); + F32 dot(const xVec3& c) const; + xVec3& normalize(); + xVec3& assign(F32 val); +}; + +F32 xVec3Normalize(xVec3* o, const xVec3* v); +F32 xVec3NormalizeFast(xVec3* o, const xVec3* v); +void xVec3Copy(xVec3* dst, const xVec3* src); +F32 xVec3Dot(const xVec3* a, const xVec3* b); + +#endif diff --git a/src/SB/Core/x/xVec3Inlines.h b/src/SB/Core/x/xVec3Inlines.h new file mode 100644 index 0000000..a09f848 --- /dev/null +++ b/src/SB/Core/x/xVec3Inlines.h @@ -0,0 +1,37 @@ +#ifndef XVEC3INLINES_H +#define XVEC3INLINES_H + +#include "xVec3.h" + +void xVec3Sub(xVec3* o, const xVec3* a, const xVec3* b); +void xVec3Cross(xVec3* o, const xVec3* a, const xVec3* b); +void xVec3Inv(xVec3* o, const xVec3* v); +void xVec3Copy(xVec3* o, const xVec3* v); +F32 xVec3Length(const xVec3* v); +void xVec3SMul(xVec3* o, const xVec3* v, F32 s); +void xVec3Add(xVec3* o, const xVec3* a, const xVec3* b); +void xVec3Init(xVec3* v, F32 _x, F32 _y, F32 _z); +void xVec3AddTo(xVec3* o, const xVec3* v); +void xVec3Lerp(xVec3* o, const xVec3* a, const xVec3* b, F32 t); +void xVec3ScaleC(xVec3* o, const xVec3* v, F32 x, F32 y, F32 z); +F32 xVec3Dist(const xVec3* a, const xVec3* b); +F32 xVec3Dist2(const xVec3* vecA, const xVec3* vecB); +F32 xVec3Length2(const xVec3* vec); +F32 xVec3LengthFast(F32 x, F32 y, F32 z); +void xVec3AddScaled(xVec3* o, const xVec3* v, F32 s); + +inline void xVec3SMulBy(xVec3* v, F32 s) +{ + v->x *= s; + v->y *= s; + v->z *= s; +} + +inline void xVec3SubFrom(xVec3* o, const xVec3* v) +{ + o->x -= v->x; + o->y -= v->y; + o->z -= v->z; +} + +#endif diff --git a/src/SB/Core/x/xVolume.cpp b/src/SB/Core/x/xVolume.cpp new file mode 100644 index 0000000..06acc9f --- /dev/null +++ b/src/SB/Core/x/xVolume.cpp @@ -0,0 +1,40 @@ +#include + +#include "xBound.h" +#include "xLinkAsset.h" +#include "xVolume.h" + +void xVolume::Init(xVolumeAsset* asset) +{ + xBaseInit(this, asset); + this->asset = asset; + + if (this->linkCount) + { + this->link = (xLinkAsset*)(this->asset + 1); + } + else + { + this->link = NULL; + } +} + +void xVolume::Reset() +{ + xBaseReset(this, this->asset); +} + +void xVolume::Save(xSerial* s) +{ + xBaseSave(this, s); +} + +void xVolume::Load(xSerial* s) +{ + xBaseLoad(this, s); +} + +xBound* xVolume::GetBound() +{ + return &this->asset->bound; +} diff --git a/src/SB/Core/x/xVolume.h b/src/SB/Core/x/xVolume.h new file mode 100644 index 0000000..d278ff4 --- /dev/null +++ b/src/SB/Core/x/xVolume.h @@ -0,0 +1,27 @@ +#ifndef XVOLUME_H +#define XVOLUME_H + +#include "xBase.h" +#include "xBound.h" + +struct xVolumeAsset : xBaseAsset +{ + U32 flags; + xBound bound; + F32 rot; + F32 xpivot; + F32 zpivot; +}; + +struct xVolume : xBase +{ + xVolumeAsset* asset; + + void Init(xVolumeAsset* asset); + void Reset(); + void Save(xSerial* s); + void Load(xSerial* s); + xBound* GetBound(); +}; + +#endif diff --git a/src/SB/Core/x/xbinio.cpp b/src/SB/Core/x/xbinio.cpp new file mode 100644 index 0000000..49b30a4 --- /dev/null +++ b/src/SB/Core/x/xbinio.cpp @@ -0,0 +1,734 @@ +#include "xbinio.h" + +#include "xMath.h" + +#include + +#define LITTLE_ENDIAN 0 +#define BIG_ENDIAN 1 + +#ifdef GAMECUBE +#define ENDIAN BIG_ENDIAN +#else +#define ENDIAN LITTLE_ENDIAN +#endif + +struct st_BINIO_XTRADATA +{ + char* dbl_buf; + S32 dblbuf_size; + S32 dbl_beg; + S32 dbl_end; + S32 dbl_amt; + U32 fpos; + char* asyn_data; + S32 asyn_amt; + S32 asyn_elesize; + S32 asyn_ismot; + en_BIO_ASYNC_ERRCODES asyn_status; + U32 pad[3]; + S32 gcaskey; +}; + +static U32 g_loadlock = 0xFFFFFF00; +static st_FILELOADINFO g_loadinst[8] = {}; +static tag_xFile g_xfload[8] = {}; +static st_BINIO_XTRADATA g_xtraload[8] = {}; +static st_BINIO_XTRADATA* g_async_context = NULL; + +static void LoadDestroy(st_FILELOADINFO* fli); +static S32 SkipBytes(st_FILELOADINFO* fli, S32 fwd); +static S32 ReadSeek(st_FILELOADINFO* fli, S32 pos); +static void SetBuffer(st_FILELOADINFO* fli, char* dblbuffer, S32 bufsize); +static void DiscardBuffer(st_FILELOADINFO* fli); +static S32 ReadRaw(st_FILELOADINFO* fli, void* data, S32 size, S32 count); +static S32 ReadBytes(st_FILELOADINFO* fli, char* data, S32 count); +static S32 ReadMShorts(st_FILELOADINFO* fli, S16* data, S32 count); +static S32 ReadMLongs(st_FILELOADINFO* fli, S32* data, S32 count); +static S32 ReadMFloats(st_FILELOADINFO* fli, F32* data, S32 count); +static S32 ReadMDoubles(st_FILELOADINFO* fli, F64* data, S32 count); +static S32 ReadIShorts(st_FILELOADINFO* fli, S16* data, S32 count); +static S32 ReadILongs(st_FILELOADINFO* fli, S32* data, S32 count); +static S32 ReadIFloats(st_FILELOADINFO* fli, F32* data, S32 count); +static S32 ReadIDoubles(st_FILELOADINFO* fli, F64* data, S32 count); +static S32 AsyncMRead(st_FILELOADINFO* fli, S32 offset, char* data, S32 size, S32 n); +static S32 AsyncIRead(st_FILELOADINFO* fli, S32 offset, char* data, S32 size, S32 n); +static en_BIO_ASYNC_ERRCODES AsyncReadStatus(st_FILELOADINFO* fli); +static void Swap2(char* d, S32 n); +static void Swap4(char* d, S32 n); +static void Swap8(char* d, S32 n); +static tag_xFile* BFD_open(const char* filename, const char* mode, U32 lockid, S32, + void* xtradata); +static void BFD_close(tag_xFile* bffp, void* xtradata); +static S32 BFD_read(void* data, S32 elesize, S32 elecnt, tag_xFile* bffp, void* xtradata); +static S32 BFD_seek(tag_xFile* bffp, S32 offset, S32 whence, void* xtradata); +static S32 BFD_getLength(tag_xFile* bffp, void* xtradata); +static S32 BFD_startSector(const char* filename); +static void BFD_cb_GCP2_readasync(tag_xFile* bffp); +static S32 BFD_AsyncRead(st_FILELOADINFO* fli, S32 pos, void* data, S32 size, S32 n, + S32 endian); +static en_BIO_ASYNC_ERRCODES BFD_AsyncReadStatus(st_FILELOADINFO* fli); + +st_FILELOADINFO* xBinioLoadCreate(const char* filename) +{ + st_FILELOADINFO* fli = NULL; + tag_xFile* tmp_fp; + S32 i; + S32 uselock = -1; + + for (i = 0; i < 8; i++) + { + if (!(g_loadlock & (1 << i))) + { + g_loadlock |= 1 << i; + + uselock = i; + fli = &g_loadinst[i]; + + break; + } + } + + if (fli) + { + memset(fli, 0, sizeof(st_FILELOADINFO)); + + fli->lockid = uselock & ~(uselock >> 31); + fli->xtradata = &g_xtraload[uselock]; + fli->destroy = LoadDestroy; + fli->readBytes = ReadBytes; + fli->readMShorts = ReadMShorts; + fli->readMLongs = ReadMLongs; + fli->readMFloats = ReadMFloats; + fli->readMDoubles = ReadMDoubles; + fli->readIShorts = ReadIShorts; + fli->readILongs = ReadILongs; + fli->readIFloats = ReadIFloats; + fli->readIDoubles = ReadIDoubles; + fli->asyncIRead = AsyncIRead; + fli->asyncMRead = AsyncMRead; + fli->asyncReadStatus = AsyncReadStatus; + fli->skipBytes = SkipBytes; + fli->seekSpot = ReadSeek; + fli->setDoubleBuf = SetBuffer; + fli->discardDblBuf = DiscardBuffer; + fli->error = FIOERR_NONE; + fli->remain = 0; + fli->basesector = 0; + fli->filesize = 0; + fli->position = 0; + fli->basesector = 0; + + tmp_fp = BFD_open(filename, "rb", uselock, 0, fli->xtradata); + + if (tmp_fp) + { + fli->basesector = BFD_startSector(filename); + fli->privdata = tmp_fp; + fli->filesize = BFD_getLength(tmp_fp, fli->xtradata); + fli->remain = fli->filesize; + } + else + { + LoadDestroy(fli); + fli = NULL; + } + } + + return fli; +} + +static void LoadDestroy(st_FILELOADINFO* fli) +{ + tag_xFile* fp = (tag_xFile*)fli->privdata; + + if (fp) + { + BFD_close(fp, fli->xtradata); + } + + U32 lockid = fli->lockid; + + memset(fli, 0, sizeof(st_FILELOADINFO)); + + g_loadlock &= ~(1 << lockid); +} + +static S32 SkipBytes(st_FILELOADINFO* fli, S32 fwd) +{ + tag_xFile* file = (tag_xFile*)fli->privdata; + + if (fli->error != FIOERR_NONE) + { + return 0; + } + + if (fwd == 0) + { + return 1; + } + + if (fwd < 0) + { + fwd = 0; + } + + if (BFD_seek(file, fli->position + fwd, IFILE_SEEK_SET, fli->xtradata) != 0) + { + fli->error = FIOERR_SEEKFAIL; + } + else + { + fli->remain -= fwd; + fli->position += fwd; + } + + if (fli->error != FIOERR_NONE) + { + return 0; + } + + return 1; +} + +static S32 ReadSeek(st_FILELOADINFO* fli, S32 pos) +{ + tag_xFile* file = (tag_xFile*)fli->privdata; + + if (fli->error != FIOERR_NONE) + { + return 0; + } + + pos = MIN(pos, fli->filesize); + + if (BFD_seek(file, pos, IFILE_SEEK_SET, fli->xtradata) != 0) + { + fli->error = FIOERR_SEEKFAIL; + } + else + { + fli->position = pos; + fli->remain = fli->filesize - pos; + } + + if (fli->error != FIOERR_NONE) + { + return 0; + } + + return 1; +} + +static void SetBuffer(st_FILELOADINFO* fli, char* dblbuffer, S32 bufsize) +{ + st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)fli->xtradata; + + if (xtra) + { + xtra->dbl_buf = dblbuffer; + xtra->dblbuf_size = bufsize; + xtra->dbl_beg = 0; + xtra->dbl_end = 0; + xtra->dbl_amt = 0; + } +} + +static void DiscardBuffer(st_FILELOADINFO* fli) +{ + SetBuffer(fli, NULL, 0); +} + +static S32 ReadRaw(st_FILELOADINFO* fli, void* data, S32 size, S32 count) +{ + tag_xFile* file = (tag_xFile*)fli->privdata; + + if (fli->error != FIOERR_NONE) + { + return 0; + } + + S32 amt = (size * count > fli->remain) ? fli->remain / size : count; + + if (amt) + { + S32 n = BFD_read(data, size, amt, file, fli->xtradata); + + if (n != amt) + { + fli->error = FIOERR_READFAIL; + } + + fli->remain -= size * amt; + fli->position += size * amt; + } + + return amt; +} + +static S32 ReadBytes(st_FILELOADINFO* fli, char* data, S32 count) +{ + S32 act = ReadRaw(fli, data, sizeof(char), count); + return act; +} + +static S32 ReadMShorts(st_FILELOADINFO* fli, S16* data, S32 count) +{ + S32 act = ReadRaw(fli, data, sizeof(S16), count); + +#if ENDIAN == LITTLE_ENDIAN + Swap2((char*)data, act); +#endif + + return act; +} + +static S32 ReadMLongs(st_FILELOADINFO* fli, S32* data, S32 count) +{ + S32 act = ReadRaw(fli, data, sizeof(S32), count); + +#if ENDIAN == LITTLE_ENDIAN + Swap4((char*)data, act); +#endif + + return act; +} + +static S32 ReadMFloats(st_FILELOADINFO* fli, F32* data, S32 count) +{ + S32 act = ReadRaw(fli, data, sizeof(F32), count); + +#if ENDIAN == LITTLE_ENDIAN + Swap4((char*)data, act); +#endif + + return act; +} + +static S32 ReadMDoubles(st_FILELOADINFO* fli, F64* data, S32 count) +{ + S32 act = ReadRaw(fli, data, sizeof(F64), count); + +#if ENDIAN == LITTLE_ENDIAN + Swap8((char*)data, act); +#endif + + return act; +} + +static S32 ReadIShorts(st_FILELOADINFO* fli, S16* data, S32 count) +{ + S32 act = ReadRaw(fli, data, sizeof(S16), count); + +#if ENDIAN == BIG_ENDIAN + Swap2((char*)data, act); +#endif + + return act; +} + +static S32 ReadILongs(st_FILELOADINFO* fli, S32* data, S32 count) +{ + S32 act = ReadRaw(fli, data, sizeof(S32), count); + +#if ENDIAN == BIG_ENDIAN + Swap4((char*)data, act); +#endif + + return act; +} + +static S32 ReadIFloats(st_FILELOADINFO* fli, F32* data, S32 count) +{ + S32 act = ReadRaw(fli, data, sizeof(F32), count); + +#if ENDIAN == BIG_ENDIAN + Swap4((char*)data, act); +#endif + + return act; +} + +static S32 ReadIDoubles(st_FILELOADINFO* fli, F64* data, S32 count) +{ + S32 act = ReadRaw(fli, data, sizeof(F64), count); + +#if ENDIAN == BIG_ENDIAN + Swap8((char*)data, act); +#endif + + return act; +} + +static S32 AsyncMRead(st_FILELOADINFO* fli, S32 offset, char* data, S32 size, S32 n) +{ + return BFD_AsyncRead(fli, offset, data, size, n, BIG_ENDIAN); +} + +static S32 AsyncIRead(st_FILELOADINFO* fli, S32 offset, char* data, S32 size, S32 n) +{ + return BFD_AsyncRead(fli, offset, data, size, n, LITTLE_ENDIAN); +} + +static en_BIO_ASYNC_ERRCODES AsyncReadStatus(st_FILELOADINFO* fli) +{ + return BFD_AsyncReadStatus(fli); +} + +static void Swap2(char* d, S32 n) +{ + char t; + + while (n--) + { + t = d[0]; + d[0] = d[1]; + d[1] = t; + + d += 2; + } +} + +static void Swap4(char* d, S32 n) +{ + char t; + + while (n--) + { + t = d[0]; + d[0] = d[3]; + d[3] = t; + + t = d[1]; + d[1] = d[2]; + d[2] = t; + + d += 4; + } +} + +static void Swap8(char* d, S32 n) +{ + char t; + + while (n--) + { + t = d[0]; + d[0] = d[7]; + d[7] = t; + + t = d[1]; + d[1] = d[6]; + d[6] = t; + + t = d[2]; + d[2] = d[5]; + d[5] = t; + + t = d[3]; + d[3] = d[4]; + d[4] = t; + + d += 8; + } +} + +static tag_xFile* BFD_open(const char* filename, const char* mode, U32 lockid, S32, + void* xtradata) +{ + tag_xFile* bffp; + U32 orc; // open return code + st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)xtradata; + S32 xfflg = IFILE_OPEN_READ; + + if (strcmp(mode, "rb") == 0) + { + bffp = &g_xfload[lockid]; + xfflg = IFILE_OPEN_READ; + } + else if (strcmp(mode, "wb") == 0) + { + bffp = NULL; + xfflg = IFILE_OPEN_WRITE; + } + else + { + bffp = NULL; + } + + if (bffp) + { + strncpy(bffp->relname, filename, sizeof(bffp->relname) - 1); + bffp->relname[sizeof(bffp->relname) - 1] = '\0'; + + orc = iFileOpen(filename, xfflg, bffp); + + if (orc != 0) + { + bffp = NULL; + } + else + { + xtra->fpos = 0; + xtra->dbl_buf = NULL; + xtra->dblbuf_size = 0; + xtra->dbl_beg = 0; + xtra->dbl_end = 0; + xtra->dbl_amt = 0; + } + } + + return bffp; +} + +static void BFD_close(tag_xFile* bffp, void* xtradata) +{ + st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)xtradata; + + iFileClose(bffp); + + xtra->fpos = 0; + xtra->dbl_buf = NULL; + xtra->dblbuf_size = 0; + xtra->dbl_beg = 0; + xtra->dbl_end = 0; + xtra->dbl_amt = 0; +} + +static S32 BFD_read(void* data, S32 elesize, S32 elecnt, tag_xFile* bffp, void* xtradata) +{ + st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)xtradata; + char* dest = (char*)data; + S32 readbeg; + S32 refill = 0; + S32 remain; + S32 actual; + U32 holdpos; + U32 numBytes = 0; + U32 safety = 0; + S32 r26 = elesize * elecnt; + + if (r26 == 0) + { + return 0; + } + + if (!xtra->dbl_buf || xtra->dblbuf_size < 1 || r26 > xtra->dblbuf_size) + { + iFileSeek(bffp, xtra->fpos, IFILE_SEEK_SET); + numBytes = iFileRead(bffp, dest, r26); + + xtra->fpos += numBytes; + } + else + { + remain = r26; + + while (true) + { + if (xtra->fpos < xtra->dbl_beg) + { + refill = 1; + + xtra->dbl_beg = xtra->fpos - (xtra->fpos % xtra->dblbuf_size); + xtra->dbl_end = xtra->dbl_beg + xtra->dblbuf_size; + xtra->dbl_amt = 0; + } + else if (xtra->fpos >= xtra->dbl_end) + { + refill = 1; + + xtra->dbl_beg = xtra->fpos - (xtra->fpos % xtra->dblbuf_size); + xtra->dbl_end = xtra->dbl_beg + xtra->dblbuf_size; + xtra->dbl_amt = 0; + } + + if (refill) + { + holdpos = xtra->fpos; + + iFileSeek(bffp, xtra->dbl_beg, IFILE_SEEK_SET); + + xtra->fpos = holdpos; + xtra->dbl_amt = iFileRead(bffp, xtra->dbl_buf, xtra->dblbuf_size); + } + + readbeg = xtra->fpos - xtra->dbl_beg; + + if (xtra->dbl_amt > readbeg) + { + actual = MIN(remain, xtra->dbl_amt - readbeg); + + memcpy(dest + numBytes, xtra->dbl_buf + readbeg, actual); + + numBytes += actual; + remain -= actual; + + xtra->fpos += actual; + } + + if (numBytes == r26 || xtra->dbl_amt < 1 || safety++ > 60000) + { + break; + } + } + } + + return (S32)numBytes / elesize; +} + +static S32 BFD_seek(tag_xFile* bffp, S32 offset, S32 whence, void* xtradata) +{ + st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)xtradata; + S32 pos = iFileSeek(bffp, offset, whence); + + xtra->fpos = offset; + + if (pos == -1) + { + return 1; + } + + return 0; +} + +static S32 BFD_getLength(tag_xFile* bffp, void* xtradata) +{ + return iFileGetSize(bffp); +} + +static S32 BFD_startSector(const char* filename) +{ + tag_xFile file = {}; + U32 addr = 0; + U32 length = 0; + + if (!iFileFind(filename, &file)) + { + iFileGetInfo(&file, &addr, &length); + } + + iFileClose(&file); + + return addr; +} + +static void BFD_cb_GCP2_readasync(tag_xFile* bffp) +{ +} + +static S32 BFD_AsyncRead(st_FILELOADINFO* fli, S32 pos, void* data, S32 size, S32 n, + S32 endian) +{ + tag_xFile* file = (tag_xFile*)fli->privdata; + st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)fli->xtradata; + + if (fli->error != FIOERR_NONE) + { + return 0; + } + + if (g_async_context) + { + return 0; + } + + g_async_context = xtra; + + xtra->asyn_status = BINIO_ASYNC_INPROG; + xtra->asyn_data = (char*)data; + xtra->asyn_elesize = size; + xtra->asyn_amt = n; + xtra->asyn_ismot = 1; + + iFileSeek(file, pos, IFILE_SEEK_SET); + xFileSetUserData(file, fli); + + S32 result = iFileReadAsync(file, data, size * n, BFD_cb_GCP2_readasync, 0); + S32 rc; + + if (result < 0) + { + rc = 0; + } + else + { + xtra->gcaskey = result; + rc = 1; + } + + if (rc == 0) + { + g_async_context = NULL; + xtra->asyn_status = BINIO_ASYNC_NOOP; + } + + return 1; +} + +static en_BIO_ASYNC_ERRCODES BFD_AsyncReadStatus(st_FILELOADINFO* fli) +{ + en_BIO_ASYNC_ERRCODES status; + st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)fli->xtradata; + + if (!g_async_context) + { + status = BINIO_ASYNC_NOOP; + } + else if (xtra != g_async_context) + { + status = BINIO_ASYNC_INPROG; + } + else + { + if (xtra->asyn_status == BINIO_ASYNC_INPROG) + { + XFILE_READSECTOR_STATUS xrdstat; + S32 amtsofar = 0; + + xrdstat = xFileReadAsyncStatus(xtra->gcaskey, &amtsofar); + + switch (xrdstat) + { + case XFILE_RDSTAT_INPROG: + case XFILE_RDSTAT_QUEUED: + { + xtra->asyn_status = BINIO_ASYNC_INPROG; + break; + } + case XFILE_RDSTAT_DONE: + { + xtra->asyn_status = BINIO_ASYNC_DONE; + break; + } + case XFILE_RDSTAT_FAIL: + case XFILE_RDSTAT_EXPIRED: + default: + { + xtra->asyn_status = BINIO_ASYNC_FAIL; + break; + } + } + } + + status = xtra->asyn_status; + + if (status == BINIO_ASYNC_FAIL || status == BINIO_ASYNC_DONE) + { + xtra->asyn_status = BINIO_ASYNC_NOOP; + g_async_context = NULL; + } + } + + return status; +} + +WEAK void xFileSetUserData(tag_xFile* file, void* userdata) +{ + file->user_data = userdata; +} + +WEAK XFILE_READSECTOR_STATUS xFileReadAsyncStatus(S32 key, S32* amtToFar) +{ + return (XFILE_READSECTOR_STATUS)iFileReadAsyncStatus(key, amtToFar); +} diff --git a/src/SB/Core/x/xbinio.h b/src/SB/Core/x/xbinio.h new file mode 100644 index 0000000..53ba1e9 --- /dev/null +++ b/src/SB/Core/x/xbinio.h @@ -0,0 +1,77 @@ +#ifndef XBINIO_H +#define XBINIO_H + +#include "xFile.h" + +enum en_BIO_ASYNC_ERRCODES +{ + BINIO_ASYNC_FAIL = -1, + BINIO_ASYNC_NOOP, + BINIO_ASYNC_INPROG, + BINIO_ASYNC_DONE, + BINIO_ASYNC_FORCEENUMSIZEINT = 0x7fffffff +}; + +enum en_FIOERRCODES +{ + FIOERR_NONE, + FIOERR_READFAIL, + FIOERR_WRITEFAIL, + FIOERR_SEEKFAIL, + FIOERR_USERABORT +}; + +struct st_FILELOADINFO +{ + void (*destroy)(st_FILELOADINFO*); + S32 (*readBytes)(st_FILELOADINFO*, char*, S32); + S32 (*readMShorts)(st_FILELOADINFO*, S16*, S32); + S32 (*readMLongs)(st_FILELOADINFO*, S32*, S32); + S32 (*readMFloats)(st_FILELOADINFO*, F32*, S32); + S32 (*readMDoubles)(st_FILELOADINFO*, F64*, S32); + S32 (*readIShorts)(st_FILELOADINFO*, S16*, S32); + S32 (*readILongs)(st_FILELOADINFO*, S32*, S32); + S32 (*readIFloats)(st_FILELOADINFO*, F32*, S32); + S32 (*readIDoubles)(st_FILELOADINFO*, F64*, S32); + S32 (*skipBytes)(st_FILELOADINFO*, S32); + S32 (*seekSpot)(st_FILELOADINFO*, S32); + void (*setDoubleBuf)(st_FILELOADINFO*, char*, S32); + void (*discardDblBuf)(st_FILELOADINFO*); + S32 (*asyncIRead)(st_FILELOADINFO*, S32, char*, S32, S32); + S32 (*asyncMRead)(st_FILELOADINFO*, S32, char*, S32, S32); + en_BIO_ASYNC_ERRCODES (*asyncReadStatus)(st_FILELOADINFO*); + U32 lockid; + en_FIOERRCODES error; + U32 basesector; + void* privdata; + void* xtradata; + void* asyndata; + S32 filesize; + S32 remain; + S32 position; +}; + +struct st_FILESAVEINFO +{ + void (*destroy)(st_FILESAVEINFO*); + S32 (*writeBytes)(st_FILESAVEINFO*, char*, S32); + S32 (*writeMShorts)(st_FILESAVEINFO*, S16*, S32); + S32 (*writeMLongs)(st_FILESAVEINFO*, S32*, S32); + S32 (*writeMFloats)(st_FILESAVEINFO*, F32*, S32); + S32 (*writeMDoubles)(st_FILESAVEINFO*, F64*, S32); + S32 (*writeIShorts)(st_FILESAVEINFO*, S16*, S32); + S32 (*writeILongs)(st_FILESAVEINFO*, S32*, S32); + S32 (*writeIFloats)(st_FILESAVEINFO*, F32*, S32); + S32 (*writeIDoubles)(st_FILESAVEINFO*, F64*, S32); + S32 (*seekSpot)(st_FILESAVEINFO*, S32); + S32 length; + S32 position; + en_FIOERRCODES error; + U32 lockid; + void* privdata; + void* xtradata; +}; + +st_FILELOADINFO* xBinioLoadCreate(const char* filename); + +#endif diff --git a/src/SB/Core/x/xhipio.cpp b/src/SB/Core/x/xhipio.cpp new file mode 100644 index 0000000..42b22a6 --- /dev/null +++ b/src/SB/Core/x/xhipio.cpp @@ -0,0 +1,511 @@ +#include "xhipio.h" + +#include + +static st_HIPLOADDATA* HIPLCreate(const char* filename, char* dblbuf, S32 bufsize); +static void HIPLDestroy(st_HIPLOADDATA* lddata); +static U32 HIPLBaseSector(st_HIPLOADDATA* lddata); +static S32 HIPLSetBypass(st_HIPLOADDATA* lddata, S32 enable, S32 use_async); +static void HIPLSetSpot(st_HIPLOADDATA* lddata, S32 spot); +static U32 HIPLBlockEnter(st_HIPLOADDATA* lddata); +static void HIPLBlockExit(st_HIPLOADDATA* lddata); +static S32 HIPLBlockRead(st_HIPLOADDATA* lddata, void* data, S32 cnt, S32 size); +static S32 HIPLBypassRead(st_HIPLOADDATA* lddata, void* data, S32 cnt, S32 size); +static S32 HIPLReadAsync(st_HIPLOADDATA* lddata, S32 pos, char* data, S32 cnt, S32 size); +static en_READ_ASYNC_STATUS HIPLPollRead(st_HIPLOADDATA* lddata); +static S32 HIPLReadBytes(st_HIPLOADDATA* lddata, char* data, S32 cnt); +static S32 HIPLReadShorts(st_HIPLOADDATA* lddata, S16* data, S32 cnt); +static S32 HIPLReadLongs(st_HIPLOADDATA* lddata, S32* data, S32 cnt); +static S32 HIPLReadFloats(st_HIPLOADDATA* lddata, F32* data, S32 cnt); +static S32 HIPLReadString(st_HIPLOADDATA* lddata, char* buf); + +static U32 g_loadlock = 0; + +static st_HIPLOADDATA g_hiploadinst[8] = {}; + +// clang-format off +static st_HIPLOADFUNCS g_map_HIPL_funcmap = +{ + HIPLCreate, + HIPLDestroy, + HIPLBaseSector, + HIPLBlockEnter, + HIPLBlockExit, + HIPLReadBytes, + HIPLReadShorts, + HIPLReadLongs, + HIPLReadFloats, + HIPLReadString, + HIPLSetBypass, + HIPLSetSpot, + HIPLPollRead +}; +// clang-format on + +st_HIPLOADFUNCS* get_HIPLFuncs() +{ + return &g_map_HIPL_funcmap; +} + +static st_HIPLOADDATA* HIPLCreate(const char* filename, char* dblbuf, S32 bufsize) +{ + st_HIPLOADDATA* lddata = NULL; + st_FILELOADINFO* fli; + st_HIPLOADBLOCK* tmp_blk; + S32 i; + S32 uselock = -1; + + for (i = 0; i < 8; i++) + { + if (!(g_loadlock & (1 << i))) + { + g_loadlock |= 1 << i; + + uselock = i; + lddata = &g_hiploadinst[i]; + + break; + } + } + + if (lddata) + { + memset(lddata, 0, sizeof(st_HIPLOADDATA)); + + lddata->lockid = uselock; + lddata->top = -1; + lddata->base_sector = 0; + lddata->use_async = 0; + lddata->asyn_stat = HIP_RDSTAT_NONE; + lddata->bypass = 0; + lddata->bypass_recover = -1; + lddata->pos = 0; + lddata->readTop = 0; + + for (i = 0; i < 8; i++) + { + tmp_blk = &lddata->stk[i]; + + tmp_blk->endpos = 0; + tmp_blk->blk_id = 0; + tmp_blk->blk_remain = 0; + tmp_blk->flags = 0; + } + + fli = xBinioLoadCreate(filename); + + if (fli) + { + lddata->fli = fli; + lddata->base_sector = fli->basesector; + + if (dblbuf && bufsize > 0) + { + fli->setDoubleBuf(fli, dblbuf, bufsize); + } + } + else + { + HIPLDestroy(lddata); + lddata = NULL; + } + } + + return lddata; +} + +static void HIPLDestroy(st_HIPLOADDATA* lddata) +{ + S32 lockid; + + if (lddata) + { + if (lddata->fli) + { + lddata->fli->destroy(lddata->fli); + } + + lockid = lddata->lockid; + + memset(lddata, 0, sizeof(st_HIPLOADDATA)); + + g_loadlock &= ~(1 << lockid); + } +} + +static U32 HIPLBaseSector(st_HIPLOADDATA* lddata) +{ + return lddata->base_sector; +} + +static S32 HIPLSetBypass(st_HIPLOADDATA* lddata, S32 enable, S32 use_async) +{ + lddata->fli->discardDblBuf(lddata->fli); + + if (enable && lddata->bypass) + { + return 0; + } + + if (!enable && !lddata->bypass) + { + return 0; + } + + if (enable) + { + lddata->bypass = 1; + lddata->use_async = use_async; + lddata->bypass_recover = lddata->fli->position; + } + else + { + lddata->fli->seekSpot(lddata->fli, lddata->bypass_recover); + lddata->bypass = 0; + lddata->use_async = 0; + lddata->bypass_recover = -1; + } + + return 1; +} + +static void HIPLSetSpot(st_HIPLOADDATA* lddata, S32 spot) +{ + if (lddata->bypass) + { + lddata->pos = spot; + lddata->fli->seekSpot(lddata->fli, spot); + } +} + +static U32 HIPLBlockEnter(st_HIPLOADDATA* lddata) +{ + st_HIPLOADBLOCK* top; + U32 cid = 0; + S32 size = 0; + + if (lddata->bypass) + { + return 0; + } + + if (lddata->top >= 0 && lddata->stk[lddata->top].blk_remain <= 0) + { + return 0; + } + + if (HIPLReadLongs(lddata, (S32*)&cid, -1) == 0) + { + cid = 0; + } + else + { + HIPLReadLongs(lddata, &size, -1); + + if (lddata->top >= 0) + { + lddata->stk[lddata->top].blk_remain -= size; + } + + top = &lddata->stk[++lddata->top]; + + top->blk_id = cid; + top->blk_remain = size; + top->endpos = lddata->pos + top->blk_remain + (top->blk_remain & 1); + top->flags = 0; + } + + return cid; +} + +static void HIPLBlockExit(st_HIPLOADDATA* lddata) +{ + st_HIPLOADBLOCK* top; + + if (!lddata->bypass) + { + top = &lddata->stk[lddata->top--]; + + lddata->fli->skipBytes(lddata->fli, top->endpos - lddata->pos); + lddata->pos = top->endpos; + } +} + +static S32 HIPLBlockRead(st_HIPLOADDATA* lddata, void* data, S32 cnt, S32 size) +{ + st_HIPLOADBLOCK* top; + S32 got = 0; + S32 left = 0; + S32 head = 0; + + if (lddata->bypass) + { + return 0; + } + + if (cnt == 0) + { + return 0; + } + + if (lddata->top < 0) + { + top = NULL; + } + else + { + top = &lddata->stk[lddata->top]; + left = top->blk_remain / size; + } + + if (cnt < 0) + { + cnt = -cnt; + head = 1; + + if (top && cnt > left) + { + cnt = left; + } + } + + if (!head && left < cnt) + { + cnt = left; + } + + if (cnt == 0) + { + got = 0; + } + else if (size == 1) + { + got = lddata->fli->readBytes(lddata->fli, (char*)data, cnt); + } + else if (size == 2) + { + got = lddata->fli->readMShorts(lddata->fli, (S16*)data, cnt); + } + else if (size == 4) + { + got = lddata->fli->readMLongs(lddata->fli, (S32*)data, cnt); + } + + got *= size; + + lddata->pos += got; + + if (top) + { + top->blk_remain -= got; + } + + return got; +} + +static S32 HIPLBypassRead(st_HIPLOADDATA* lddata, void* data, S32 cnt, S32 size) +{ + S32 got = 0; + + if (!lddata->bypass) + { + return 0; + } + + if (lddata->use_async) + { + return HIPLReadAsync(lddata, lddata->pos, (char*)data, cnt, size); + } + + if (cnt == 0) + { + return 0; + } + + if (cnt == 0) + { + got = 0; + } + else if (size == 1) + { + got = lddata->fli->readBytes(lddata->fli, (char*)data, cnt); + } + else if (size == 2) + { + got = lddata->fli->readMShorts(lddata->fli, (S16*)data, cnt); + } + else if (size == 4) + { + got = lddata->fli->readMLongs(lddata->fli, (S32*)data, cnt); + } + + return got * size; +} + +static S32 HIPLReadAsync(st_HIPLOADDATA* lddata, S32 pos, char* data, S32 cnt, S32 size) +{ + S32 rc; + + lddata->asyn_stat = HIP_RDSTAT_NONE; + + rc = lddata->fli->asyncMRead(lddata->fli, pos, data, cnt, size); + + lddata->asyn_stat = HIP_RDSTAT_INPROG; + + return rc; +} + +static en_READ_ASYNC_STATUS HIPLPollRead(st_HIPLOADDATA* lddata) +{ + en_READ_ASYNC_STATUS rdstat = HIP_RDSTAT_INPROG; + en_BIO_ASYNC_ERRCODES pollstat; + + if (!lddata->bypass) + { + return HIP_RDSTAT_NOBYPASS; + } + + if (!lddata->use_async) + { + return HIP_RDSTAT_NOASYNC; + } + + pollstat = lddata->fli->asyncReadStatus(lddata->fli); + + switch (pollstat) + { + case BINIO_ASYNC_INPROG: + { + rdstat = HIP_RDSTAT_INPROG; + break; + } + case BINIO_ASYNC_DONE: + { + rdstat = HIP_RDSTAT_SUCCESS; + lddata->asyn_stat = HIP_RDSTAT_NONE; + break; + } + case BINIO_ASYNC_FAIL: + { + rdstat = HIP_RDSTAT_FAILED; + lddata->asyn_stat = HIP_RDSTAT_NONE; + break; + } + default: + { + lddata->asyn_stat = HIP_RDSTAT_NONE; + break; + } + } + + return rdstat; +} + +static S32 HIPLReadBytes(st_HIPLOADDATA* lddata, char* data, S32 cnt) +{ + if (lddata->bypass) + { + return HIPLBypassRead(lddata, data, cnt, sizeof(char)); + } + else + { + return HIPLBlockRead(lddata, data, cnt, sizeof(char)); + } +} + +static S32 HIPLReadShorts(st_HIPLOADDATA* lddata, S16* data, S32 cnt) +{ + S32 got; + + if (lddata->bypass) + { + got = HIPLBypassRead(lddata, data, cnt, sizeof(S16)); + } + else + { + got = HIPLBlockRead(lddata, data, cnt, sizeof(S16)); + } + + got /= sizeof(S16); + + return got; +} + +static S32 HIPLReadLongs(st_HIPLOADDATA* lddata, S32* data, S32 cnt) +{ + S32 got; + + if (lddata->bypass) + { + got = HIPLBypassRead(lddata, data, cnt, sizeof(S32)); + } + else + { + got = HIPLBlockRead(lddata, data, cnt, sizeof(S32)); + } + + got /= sizeof(S32); + + return got; +} + +static S32 HIPLReadFloats(st_HIPLOADDATA* lddata, F32* data, S32 cnt) +{ + S32 got; + + if (lddata->bypass) + { + got = HIPLBypassRead(lddata, data, cnt, sizeof(F32)); + } + else + { + got = HIPLBlockRead(lddata, data, cnt, sizeof(F32)); + } + + got /= sizeof(F32); + + return got; +} + +static S32 HIPLReadString(st_HIPLOADDATA* lddata, char* buf) +{ + S32 n = 0; + char pad = 0; + + if (lddata->bypass) + { + while (HIPLBypassRead(lddata, &buf[n], 1, sizeof(char))) + { + if (buf[n] == '\0') + { + if (!(n & 1)) + { + HIPLBypassRead(lddata, &pad, 1, sizeof(char)); + } + + break; + } + + n++; + } + } + else + { + while (HIPLBlockRead(lddata, &buf[n], 1, sizeof(char))) + { + if (buf[n] == '\0') + { + if (!(n & 1)) + { + HIPLBlockRead(lddata, &pad, 1, sizeof(char)); + } + + break; + } + + n++; + } + } + + return n; +} diff --git a/src/SB/Core/x/xhipio.h b/src/SB/Core/x/xhipio.h new file mode 100644 index 0000000..9b93ca2 --- /dev/null +++ b/src/SB/Core/x/xhipio.h @@ -0,0 +1,90 @@ +#ifndef XHIPIO_H +#define XHIPIO_H + +#include "xbinio.h" + +enum en_READ_ASYNC_STATUS +{ + HIP_RDSTAT_NONE = -1, + HIP_RDSTAT_INPROG, + HIP_RDSTAT_SUCCESS, + HIP_RDSTAT_FAILED, + HIP_RDSTAT_NOBYPASS, + HIP_RDSTAT_NOASYNC +}; + +struct st_HIPLOADBLOCK +{ + S32 endpos; + U32 blk_id; + S32 blk_remain; + S32 flags; +}; + +struct st_HIPLOADDATA +{ + st_FILELOADINFO* fli; + S32 lockid; + S32 bypass; + S32 bypass_recover; + U32 base_sector; + S32 use_async; + en_READ_ASYNC_STATUS asyn_stat; + S32 pos; + S32 top; + S32 readTop; + st_HIPLOADBLOCK stk[8]; +}; + +struct st_HIPLOADFUNCS +{ + st_HIPLOADDATA* (*create)(const char*, char*, S32); + void (*destroy)(st_HIPLOADDATA*); + U32 (*basesector)(st_HIPLOADDATA*); + U32 (*enter)(st_HIPLOADDATA*); + void (*exit)(st_HIPLOADDATA*); + S32 (*readBytes)(st_HIPLOADDATA*, char*, S32); + S32 (*readShorts)(st_HIPLOADDATA*, S16*, S32); + S32 (*readLongs)(st_HIPLOADDATA*, S32*, S32); + S32 (*readFloats)(st_HIPLOADDATA*, F32*, S32); + S32 (*readString)(st_HIPLOADDATA*, char*); + S32 (*setBypass)(st_HIPLOADDATA*, S32, S32); + void (*setSpot)(st_HIPLOADDATA*, S32); + en_READ_ASYNC_STATUS (*pollRead)(st_HIPLOADDATA*); +}; + +struct st_HIPSAVEBLOCK +{ + S32 pos; + S32 len; + S32 flags; +}; + +struct st_HIPSAVEDATA +{ + st_FILESAVEINFO* fsi; + S32 lockid; + S32 pos; + S32 top; + S32 writeTop; + st_HIPSAVEBLOCK stk[8]; +}; + +struct st_HIPSAVEFUNCS +{ + st_HIPSAVEDATA* (*create)(const char*); + void (*destroy)(st_HIPSAVEDATA*); + void (*open)(st_HIPSAVEDATA*, U32); + void (*close)(st_HIPSAVEDATA*); + void (*writeBytes)(st_HIPSAVEDATA*, char*, S32); + void (*writeShorts)(st_HIPSAVEDATA*, S16*, S32); + void (*writeLongs)(st_HIPSAVEDATA*, S32*, S32); + void (*writeFloats)(st_HIPSAVEDATA*, F32*, S32); + void (*writeString)(st_HIPSAVEDATA*, char*); + S32 (*curSpot)(st_HIPSAVEDATA*); + S32 (*spotLong)(st_HIPSAVEDATA*, S32, U32); +}; + +st_HIPLOADFUNCS* get_HIPLFuncs(); + +#endif diff --git a/src/SB/Core/x/xordarray.cpp b/src/SB/Core/x/xordarray.cpp new file mode 100644 index 0000000..85f8b41 --- /dev/null +++ b/src/SB/Core/x/xordarray.cpp @@ -0,0 +1,183 @@ +#include "xordarray.h" +#include "xMemMgr.h" + +#include + +extern F32 lbl_803CCEE8; // 0.95f +extern F32 lbl_803CCEF0; // 176f + +void XOrdInit(st_XORDEREDARRAY* array, S32 size, S32 tempAlloc) +{ + U32 cnt = 1; + if (size >= 1) + { + cnt = size; + } + if (tempAlloc) + { + array->list = (void**)xMemPushTemp(cnt << 2); + } + else + { + array->list = (void**)xMemAlloc(gActiveHeap, cnt << 2, 0); + } + array->cnt = 0; + array->max = cnt; + array->warnlvl = lbl_803CCEE8 * (cnt ^ 0x80000000); + if (array->warnlvl == array->max) + { + cnt = array->max - 1; + array->warnlvl = cnt & ~((S32)cnt >> 0x1f); + } +} + +void XOrdReset(st_XORDEREDARRAY* array) +{ + array->cnt = 0; +} + +void XOrdDone(st_XORDEREDARRAY* array, S32 wasTempAlloc) +{ + if (array->max != 0 && wasTempAlloc != 0) + { + xMemPopTemp(array->list); + } + array->list = NULL; + array->cnt = 0; + array->max = 0; + array->warnlvl = 0; +} + +void XOrdAppend(st_XORDEREDARRAY* array, void* elt) +{ + if (array->cnt >= array->max) + { + return; + } + array->list[array->cnt++] = elt; +} + +void XOrdInsert(st_XORDEREDARRAY* array, void* elt, XOrdCompareCallback compare) +{ + if (array->cnt < array->max) + { + array->cnt++; + S32 pos = array->cnt - 1; + void* currElement = (void*)(pos * sizeof(void*)); + while (pos > 0) + { + // FIXME: currElement + // S32 score = compare(array->list + currElement - sizeof(void*), elt); + // if (score <= 0) + // { + // array->list[pos] = elt; + // return; + // } + // pos--; + // void* tmp = (void*)(array->list + currElement); + // currElement--; + // *tmp = tmp[-1]; + } + *array->list = elt; + } +} + +void* XOrdRemove(st_XORDEREDARRAY* array, void* elt, S32 index) +{ + if (elt == NULL) + { + if (index < 0) + { + return NULL; + } + if (index >= array->max) + { + return NULL; + } + } + + if ((index >= 0) && (index < array->max)) + { + elt = array->list[index]; + } + else if (elt != NULL) + { + index = -1; + int iVar4 = 0; + for (int i = array->cnt; i > 0; i--) + { + if (array->list[iVar4] == elt) + { + index = iVar4; + break; + } + iVar4++; + } + } + + if (index < 0) + { + return NULL; + } + + array->cnt--; + for (; index < array->cnt; index++) + { + array->list[index] = array->list[index + 1]; + } + + return elt; +} + +S32 XOrdLookup(st_XORDEREDARRAY* array, const void* key, XOrdTestCallback test) +{ + S32 v, index, rightBound, leftBound; + leftBound = 0; + index = array->cnt; + do + { + rightBound = index; + if (rightBound <= leftBound) + { + return -1; + } + index = (leftBound + rightBound) / 2; + v = test(key, array->list[index]); + if (v == 0) + break; + if (0 < v) + { + leftBound = index + 1; + index = rightBound; + } + } while (true); + return index; +} + +void XOrdSort(st_XORDEREDARRAY* array, S32 (*test)(void*, void*)) +{ + void** list = array->list; + S32 num = 1; + // FIXME: cnt?? + // while (num <= cnt) + // { + // num = num * 3 + 1; + // } + for (;;) + { + if (num == 1) + { + return; + } + num = num / 3 + (num >> 0x1f); + num = num - (num >> 0x1f); + S32 numPos = num * sizeof(void*); + void** currItem = list + num; + S32 i = num; + // FIXME: cnt?? + // while (i < cnt) + // { + // // TODO!!! + // } + } +} diff --git a/src/SB/Core/x/xordarray.h b/src/SB/Core/x/xordarray.h new file mode 100644 index 0000000..43ed6a0 --- /dev/null +++ b/src/SB/Core/x/xordarray.h @@ -0,0 +1,26 @@ +#ifndef XORDARRAY_H +#define XORDARRAY_H + +#include + +struct st_XORDEREDARRAY +{ + void** list; + S32 cnt; + S32 max; + S32 warnlvl; +}; + +typedef S32 (*XOrdCompareCallback)(void* vkey, void* vitem); +typedef S32 (*XOrdTestCallback)(const void* vkey, void* vitem); + +void XOrdInit(st_XORDEREDARRAY* array, S32 size, S32 tempAlloc); +void XOrdReset(st_XORDEREDARRAY* array); +void XOrdDone(st_XORDEREDARRAY* array, S32 wasTempAlloc); +void XOrdAppend(st_XORDEREDARRAY* array, void* elt); +void XOrdInsert(st_XORDEREDARRAY* array, void* elt, XOrdCompareCallback compare); +void* XOrdRemove(st_XORDEREDARRAY* array, void* elt, S32 index); +S32 XOrdLookup(st_XORDEREDARRAY* array, const void* key, XOrdTestCallback test); +void XOrdSort(st_XORDEREDARRAY* array, S32 (*test)(void*, void*)); + +#endif diff --git a/src/SB/Core/x/xpkrsvc.cpp b/src/SB/Core/x/xpkrsvc.cpp new file mode 100644 index 0000000..12b7d38 --- /dev/null +++ b/src/SB/Core/x/xpkrsvc.cpp @@ -0,0 +1,1768 @@ +#include "xpkrsvc.h" + +#include +#include +#include + +#include "xhipio.h" +#include "xutil.h" +#include "xMath.h" +#include "xMemMgr.h" + +extern char xpkrsvc_strings[]; + +// Square and JESway: Function relocation issues will resolve themselves when all the functions +// here 100% match, as it is apparently related to the instruction size of each function +static st_PACKER_READ_FUNCS g_pkr_read_funcmap_original = { 1, + PKR_ReadInit, + PKR_ReadDone, + PKR_LoadLayer, + PKR_GetAssetSize, + PKR_LoadAsset, + PKR_AssetByType, + PKR_AssetCount, + PKR_IsAssetReady, + PKR_SetActive, + PKR_AssetName, + PKR_GetBaseSector, + PKR_GetAssetInfo, + PKR_GetAssetInfoByType, + PKR_PkgHasAsset, + PKR_getPackTimestamp, + PKR_Disconnect }; +static st_PACKER_READ_FUNCS g_pkr_read_funcmap = g_pkr_read_funcmap_original; +st_PACKER_READ_DATA g_readdatainst[16] = {}; + +st_HIPLOADFUNCS* g_hiprf; +U32 g_loadlock; +S32 pkr_sector_size; +volatile S32 g_packinit; +volatile S32 g_memalloc_pair; +volatile S32 g_memalloc_runtot; +volatile S32 g_memalloc_runfree; + +st_PACKER_READ_FUNCS* PKRGetReadFuncs(S32 apiver) +{ + switch (apiver) + { + case 1: + return &g_pkr_read_funcmap; + default: + return NULL; + } +} + +S32 PKRStartup() +{ + if (g_packinit++ == 0) + { + g_pkr_read_funcmap = g_pkr_read_funcmap_original; + g_hiprf = get_HIPLFuncs(); + pkr_sector_size = 32; + } + return g_packinit; +} + +S32 PKRShutdown() +{ + g_packinit--; + return g_packinit; +} + +S32 PKRLoadStep(S32) +{ + return PKR_LoadStep_Async(); +} + +st_PACKER_READ_DATA* PKR_ReadInit(void* userdata, char* pkgfile, U32 opts, S32* cltver, + st_PACKER_ASSETTYPE* typelist) +{ + // I'm pretty sure this is just a pointer to an array on the heap + // But it needs to be an array of pointers to generate correct code ??? + char* tocbuf_RAW[1]; + tocbuf_RAW[0] = NULL; + st_PACKER_READ_DATA* pr = NULL; + S32 uselock = -1; + + PKR_alloc_chkidx(); + char* tocbuf_aligned = (char*)PKR_getmem('PTOC', 0x8000, 'PTOC', 0x40, 1, tocbuf_RAW); + + for (S32 i = 0; i < 16; i++) + { + if (!(g_loadlock & 1 << i)) + { + g_loadlock |= 1 << i; + pr = &g_readdatainst[i]; + uselock = i; + break; + } + } + + if (pr != NULL) + { + memset(pr, 0, sizeof(st_PACKER_READ_DATA)); + pr->lockid = uselock; + pr->userdata = userdata; + pr->opts = opts; + pr->types = typelist; + pr->cltver = -1; + strncpy(pr->packfile, pkgfile, 0x80); + + if (tocbuf_aligned == NULL) + { + pr->pkg = g_hiprf->create(pkgfile, NULL, 0); + } + else + { + pr->pkg = g_hiprf->create(pkgfile, tocbuf_aligned, 0x8000); + } + + if (pr->pkg != NULL) + { + pr->base_sector = g_hiprf->basesector(pr->pkg); + PKR_parse_TOC(pr->pkg, pr); + *cltver = pr->cltver; + g_hiprf->setBypass(pr->pkg, 1, 1); + } + else + { + PKR_ReadDone(pr); + pr = NULL; + *cltver = -1; + } + } + else + { + *cltver = -1; + pr = NULL; + } + + PKR_relmem('PTOC', 0x8000, (void*)tocbuf_RAW[0], 'PTOC', 1); + tocbuf_RAW[0] = NULL; + return pr; +} + +void PKR_ReadDone(st_PACKER_READ_DATA* pr) +{ + S32 i; + S32 j; + S32 lockid; + st_PACKER_ATOC_NODE* assnode; + st_PACKER_LTOC_NODE* laynode; + st_XORDEREDARRAY* tmplist; + + if (pr == NULL) + { + return; + } + for (i = pr->laytoc.cnt - 1; i >= 0; i--) + { + st_PACKER_LTOC_NODE* laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; + for (j = laynode->assref.cnt - 1; j >= 0; j--) + { + assnode = (st_PACKER_ATOC_NODE*)laynode->assref.list[j]; + if (assnode->typeref != NULL && assnode->typeref->assetUnloaded != NULL && + !(assnode->loadflag & 0x100000)) + { + assnode->typeref->assetUnloaded(assnode->memloc, assnode->aid); + } + } + } + + for (i = 0; i < pr->laytoc.cnt; i++) + { + laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; + if (laynode->laymem != NULL) + { + PKR_LayerMemRelease(pr, laynode); + laynode->laymem = NULL; + } + } + + PKR_kiilpool_anode(pr); + + for (i = 0; i < pr->laytoc.cnt; i++) + { + laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; + PKR_oldlaynode(laynode); + } + + XOrdDone(&pr->asstoc, false); + XOrdDone(&pr->laytoc, false); + + for (i = 0; i < 129; i++) + { + tmplist = &pr->typelist[i]; + if (tmplist->max != 0) + { + XOrdDone(tmplist, false); + } + } + + if (pr->pkg != NULL) + { + g_hiprf->destroy(pr->pkg); + pr->pkg = NULL; + } + + lockid = pr->lockid; + memset(pr, 0, sizeof(st_PACKER_READ_DATA)); + g_loadlock &= ~(1 << lockid); +} + +S32 PKR_SetActive(st_PACKER_READ_DATA* pr, en_LAYER_TYPE layer) +{ + S32 result; + S32 rc = 1; + S32 i; + S32 j; + st_PACKER_ATOC_NODE* assnode; + st_PACKER_LTOC_NODE* laynode; + + if (pr == NULL) + { + return 0; + } + + for (i = 0; i < pr->laytoc.cnt; i++) + { + laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; + if (layer > PKR_LTYPE_DEFAULT && laynode->laytyp != layer) + { + continue; + } + + for (j = 0; j < laynode->assref.cnt; j++) + { + assnode = (st_PACKER_ATOC_NODE*)laynode->assref.list[j]; + if (assnode->loadflag & 0x10000 || (assnode->loadflag & 0x80000) == 0) + { + continue; + } + + if (assnode->typeref == NULL) + { + assnode->Name(); + xUtil_idtag2string(assnode->asstype, 0); + } + else if (assnode->typeref->assetLoaded != NULL) + { + if (!(assnode->typeref->assetLoaded(pr->userdata, assnode->aid, assnode->memloc, + assnode->d_size))) + { + rc = 0; + } + else + { + assnode->loadflag |= 0x10000; + } + } + } + } + + return rc; +} + +S32 PKR_parse_TOC(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 done = 0; + S32 is_ok = 0; + U32 cid = g_hiprf->enter(pkg); + while (cid != false) + { + switch (cid) + { + case 'HIPA': + done = LOD_r_HIPA(pkg, pr); + break; + case 'PACK': + LOD_r_PACK(pkg, pr); + if (done) + { + if (pr->asscnt > 0) + { + XOrdInit(&pr->asstoc, pr->asscnt, 0); + PKR_makepool_anode(pr, pr->asscnt); + } + if (pr->laycnt > 0) + { + XOrdInit(&pr->laytoc, pr->laycnt, 0); + } + } + break; + case 'DICT': + LOD_r_DICT(pkg, pr); + PKR_bld_typecnt(pr); + is_ok = true; + break; + case 'STRM': + LOD_r_STRM(pkg, pr); + break; + } + + if (!done) + { + break; + } + + g_hiprf->exit(pkg); + + if (is_ok) + { + break; + } + + cid = g_hiprf->enter(pkg); + } + return done; +} + +S32 PKR_LoadStep_Async() +{ + S32 rc; + static st_PACKER_READ_DATA* curpr = NULL; + static st_PACKER_LTOC_NODE* asynlay = NULL; + + if (asynlay == NULL) + { + PKR_findNextLayerToLoad(&curpr, &asynlay); + + if (asynlay != NULL) + { + if (PKR_layerLoadDest(asynlay->laytyp) != PKR_LDDEST_SKIP && asynlay->laysize > 1 && + asynlay->assref.cnt > 0) + { + asynlay->laymem = PKR_LayerMemReserve(curpr, asynlay); + PKR_drv_guardLayer(asynlay); + st_PACKER_ATOC_NODE* tmpass = (st_PACKER_ATOC_NODE*)asynlay->assref.list[0]; + g_hiprf->setSpot(tmpass->ownpkg, tmpass->d_off); + + if (g_hiprf->readBytes(tmpass->ownpkg, asynlay->laymem, asynlay->laysize)) + { + asynlay->flg_ldstat |= 0x1000000; + } + else + { + PKR_LayerMemRelease(curpr, asynlay); + asynlay->flg_ldstat &= 0xfcffffff; + curpr = NULL; + asynlay = NULL; + } + + rc = 1; + } + else + { + rc = 1; + asynlay->flg_ldstat |= 0x2000000; + asynlay = NULL; + } + } + else + { + rc = 0; + curpr = NULL; + asynlay = NULL; + } + } + else + { + S32 moretodo = g_hiprf->pollRead(curpr->pkg); + if (moretodo == 1) + { + moretodo = PKR_drv_guardVerify(asynlay); + } + + if (!moretodo) + { + rc = 1; + } + else if (moretodo == 1) + { + PKR_updateLayerAssets(asynlay); + + if (PKR_layerTypeNeedsXForm(asynlay->laytyp)) + { + PKR_xformLayerAssets(asynlay); + } + + if (PKR_layerLoadDest(asynlay->laytyp) == PKR_LDDEST_RWHANDOFF) + { + PKR_LayerMemRelease(curpr, asynlay); + } + + rc = 1; + asynlay->flg_ldstat |= 0x2000000; + asynlay = NULL; + } + else + { + en_PKR_LAYER_LOAD_DEST loaddest = PKR_layerLoadDest(asynlay->laytyp); + if (asynlay->laymem != NULL && loaddest == PKR_LDDEST_RWHANDOFF) + { + PKR_LayerMemRelease(curpr, asynlay); + } + + rc = 1; + asynlay->flg_ldstat &= 0xfcffffff; + asynlay = NULL; + curpr = NULL; + } + } + + return rc; +} + +char* PKR_LayerMemReserve(st_PACKER_READ_DATA* pr, st_PACKER_LTOC_NODE* layer) +{ + char* mem = NULL; + if (layer->laymem != NULL) + { + return layer->laymem; + } + + switch (PKR_layerLoadDest(layer->laytyp)) + { + case PKR_LDDEST_SKIP: + break; + case PKR_LDDEST_KEEPSTATIC: + mem = (char*)PKR_getmem('LYR\0', layer->laysize, layer->laytyp + 0x8000, 0x40); + break; + case PKR_LDDEST_KEEPMALLOC: + mem = (char*)PKR_getmem('LYR\0', layer->laysize, layer->laytyp + 0x8000, 0x40, 1, + &layer->laytru); + break; + case PKR_LDDEST_RWHANDOFF: + PKR_push_memmark(); + mem = (char*)PKR_getmem('LYR\0', layer->laysize, layer->laytyp + 0x8000, 0x40); + break; + } + + return mem; +} + +void PKR_LayerMemRelease(st_PACKER_READ_DATA* pr, st_PACKER_LTOC_NODE* layer) +{ + switch (PKR_layerLoadDest(layer->laytyp)) + { + case PKR_LDDEST_SKIP: + break; + case PKR_LDDEST_RWHANDOFF: + PKR_relmem('LYR\0', layer->laysize, layer->laymem, layer->laytyp + 0x8000, 0); + PKR_pop_memmark(); + layer->laymem = NULL; + break; + case PKR_LDDEST_KEEPSTATIC: + PKR_relmem('LYR\0', layer->laysize, layer->laymem, layer->laytyp + 0x8000, 0); + break; + case PKR_LDDEST_KEEPMALLOC: + PKR_relmem('LYR\0', layer->laysize, layer->laytru, layer->laytyp + 0x8000, 1); + layer->laymem = NULL; + layer->laytru = NULL; + break; + } +} + +void PKR_drv_guardLayer(st_PACKER_LTOC_NODE*) +{ +} + +S32 PKR_drv_guardVerify(st_PACKER_LTOC_NODE*) +{ + return 1; +} + +en_PKR_LAYER_LOAD_DEST PKR_layerLoadDest(en_LAYER_TYPE layer) +{ + switch (layer) + { + case PKR_LTYPE_SRAM: + case PKR_LTYPE_CUTSCENE: + return PKR_LDDEST_SKIP; + case PKR_LTYPE_TEXTURE: + case PKR_LTYPE_BSP: + case PKR_LTYPE_MODEL: + return PKR_LDDEST_RWHANDOFF; + case PKR_LTYPE_ANIMATION: + case PKR_LTYPE_JSPINFO: + return PKR_LDDEST_KEEPMALLOC; + case PKR_LTYPE_DEFAULT: + case PKR_LTYPE_VRAM: + case PKR_LTYPE_SNDTOC: + case PKR_LTYPE_CUTSCENETOC: + return PKR_LDDEST_KEEPSTATIC; + default: + return PKR_LDDEST_KEEPSTATIC; + } +} + +S32 PKR_layerTypeNeedsXForm(en_LAYER_TYPE layer) +{ + switch (layer) + { + case PKR_LTYPE_TEXTURE: + case PKR_LTYPE_BSP: + case PKR_LTYPE_MODEL: + return true; + case PKR_LTYPE_DEFAULT: + case PKR_LTYPE_ANIMATION: + case PKR_LTYPE_VRAM: + case PKR_LTYPE_SNDTOC: + case PKR_LTYPE_CUTSCENETOC: + case PKR_LTYPE_JSPINFO: + return true; + case PKR_LTYPE_SRAM: + case PKR_LTYPE_CUTSCENE: + return false; + default: + return false; + } +} + +S32 PKR_findNextLayerToLoad(st_PACKER_READ_DATA** work_on_pkg, st_PACKER_LTOC_NODE** next_layer) +{ + st_PACKER_READ_DATA* tmppr; + st_PACKER_LTOC_NODE* tmplay; + + *next_layer = NULL; + if (*work_on_pkg != NULL) + { + tmppr = *work_on_pkg; + for (S32 i = 0; i < tmppr->laytoc.cnt; i++) + { + tmplay = (st_PACKER_LTOC_NODE*)tmppr->laytoc.list[i]; + if (!(tmplay->flg_ldstat & 0x2000000)) + { + *next_layer = tmplay; + *work_on_pkg = tmppr; + break; + } + } + } + + if (*next_layer == NULL) + { + tmppr = g_readdatainst; + for (S32 i = 0; i < 16; i++, tmppr++) + { + if ((g_loadlock & 1 << i) == 0 || tmppr == *work_on_pkg) + { + continue; + } + + for (S32 j = 0; j < tmppr->laytoc.cnt; j++) + { + tmplay = (st_PACKER_LTOC_NODE*)tmppr->laytoc.list[j]; + if (!(tmplay->flg_ldstat & 0x2000000)) + { + *next_layer = tmplay; + *work_on_pkg = tmppr; + break; + } + } + + if (*next_layer != NULL) + { + break; + } + } + } + + return *next_layer != NULL; +} + +void PKR_updateLayerAssets(st_PACKER_LTOC_NODE* laynode) +{ + st_PACKER_ATOC_NODE* tmpass = NULL; + for (S32 i = 0; i < laynode->assref.cnt; i++) + { + tmpass = (st_PACKER_ATOC_NODE*)laynode->assref.list[i]; + if (tmpass->d_off > 0 && tmpass->d_size > 0) + { + break; + } + tmpass = NULL; + } + + if (tmpass != NULL) + { + S32 lay_hip_pos = tmpass->d_off; + for (S32 i = 0; i < laynode->assref.cnt; i++) + { + st_PACKER_ATOC_NODE* tmpass = (st_PACKER_ATOC_NODE*)laynode->assref.list[i]; + if (!(tmpass->loadflag & 0x100000)) + { + if (tmpass->loadflag & 0x200000) + { + tmpass->Name(); + tmpass->memloc = NULL; + } + else + { + tmpass->memloc = laynode->laymem + (tmpass->d_off - lay_hip_pos); + tmpass->loadflag |= 0x80000; + tmpass->Name(); + } + } + } + } +} + +void PKR_xformLayerAssets(st_PACKER_LTOC_NODE* laynode) +{ + S32 i; + S32 will_be_dumped = false; + en_PKR_LAYER_LOAD_DEST loaddest = PKR_layerLoadDest(laynode->laytyp); + + if (loaddest == PKR_LDDEST_RWHANDOFF) + { + will_be_dumped = true; + } + + for (i = 0; i < laynode->assref.cnt; i++) + { + st_PACKER_ATOC_NODE* tmpass = (st_PACKER_ATOC_NODE*)laynode->assref.list[i]; + if ((tmpass->loadflag & 0x100000) == 0) + { + PKR_xform_asset(tmpass, will_be_dumped); + if (will_be_dumped && tmpass->x_size < 1) + { + tmpass->Name(); + tmpass->memloc = NULL; + } + } + } +} + +void PKR_xform_asset(st_PACKER_ATOC_NODE* assnode, S32 dumpable_layer) +{ + if (!(assnode->infoflag & 4)) + { + if (assnode->typeref == NULL) + { + return; + } + + if (assnode->typeref->readXForm != NULL) + { + assnode->Name(); + xUtil_idtag2string(assnode->asstype, 0); + } + else + { + return; + } + } + + st_PACKER_ASSETTYPE* atype = assnode->typeref; + if (atype == NULL) + { + assnode->Name(); + } + else if (atype->readXForm == NULL) + { + assnode->Name(); + } + else + { + if (assnode->d_size == 0) + { + assnode->Name(); + xUtil_idtag2string(assnode->asstype, 0); + assnode->memloc = NULL; + } + + char* xformloc = + (char*)atype->readXForm(assnode->ownpr->userdata, assnode->aid, assnode->memloc, + assnode->d_size, (U32*)&assnode->x_size); + if (!dumpable_layer && assnode->memloc == xformloc && assnode->x_size != 0) + { + assnode->Name(); + } + else if (assnode->d_size == 0 || assnode->x_size == 0) + { + assnode->memloc = NULL; + assnode->loadflag |= 0x200000; + } + else + { + assnode->memloc = xformloc; + } + } +} + +void* PKR_FindAsset(st_PACKER_READ_DATA* pr, U32 aid) +{ + st_PACKER_ATOC_NODE* assnode = NULL; + S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); + + if (idx >= 0) + { + assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; + } + + if (assnode != NULL) + { + if (assnode->memloc == NULL) + { + assnode->Name(); + } + + return assnode->memloc; + } + return NULL; +} + +S32 PKR_LoadLayer(st_PACKER_READ_DATA* pr, en_LAYER_TYPE layer) +{ + return 0; +} + +void* PKR_LoadAsset(st_PACKER_READ_DATA* pr, U32 aid, char*, void*) +{ + return PKR_FindAsset(pr, aid); +} + +U32 PKR_GetAssetSize(st_PACKER_READ_DATA* pr, U32 aid) +{ + st_PACKER_ATOC_NODE* assnode = NULL; + S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); + + if (idx > -1) + { + assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; + } + + if (assnode != NULL) + { + if (assnode->x_size > 0) + { + return assnode->x_size; + } + return assnode->d_size; + } + return 0; +} + +S32 PKR_AssetCount(st_PACKER_READ_DATA* pr, U32 type) +{ + S32 count = 0; + if (type == 0) + { + return pr->asstoc.cnt; + } + else + { + S32 idx = PKR_typeHdlr_idx(pr, type); + if (idx >= 0) + { + st_XORDEREDARRAY* tmplist = &pr->typelist[idx]; + count = tmplist->cnt; + } + } + return count; +} + +void* PKR_AssetByType(st_PACKER_READ_DATA* pr, U32 type, S32 idx, U32* size) +{ + if (size != NULL) + { + *size = 0; + } + + if (idx < 0) + { + idx = 0; + } + + S32 typeidx = PKR_typeHdlr_idx(pr, type); + if (typeidx < 0) + { + return 0; + } + + st_XORDEREDARRAY* tmplist = &pr->typelist[typeidx]; + if (idx >= tmplist->cnt) + { + return 0; + } + + st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)tmplist->list[idx]; + if (size != NULL) + { + *size = assnode->d_size; + } + return assnode->memloc; +} + +// +S32 PKR_IsAssetReady(st_PACKER_READ_DATA* pr, U32 aid) +{ + S32 ready = false; + S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); + if (idx >= 0) + { + st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; + if (assnode->loadflag & 0x80000) + { + ready = true; + } + else + { + ready = false; + } + } + + return ready; +} + +U32 PKR_getPackTimestamp(st_PACKER_READ_DATA* pr) +{ + return pr->time_made; +} + +void PKR_Disconnect(st_PACKER_READ_DATA* pr) +{ + if (pr->pkg != NULL) + { + g_hiprf->destroy(pr->pkg); + pr->pkg = NULL; + } +} + +U32 PKRAssetIDFromInst(void* inst) +{ + return ((st_PACKER_ATOC_NODE*)inst)->aid; +} + +char* PKR_AssetName(st_PACKER_READ_DATA* pr, U32 aid) +{ + char* name = NULL; + + if (aid == 0) + { + return NULL; + } + else + { + S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); + if (idx >= 0) + { + name = ((st_PACKER_ATOC_NODE*)pr->asstoc.list[idx])->Name(); + } + } + + return name; +} + +U32 PKR_GetBaseSector(st_PACKER_READ_DATA* pr) +{ + return pr->base_sector; +} + +S32 PKR_GetAssetInfo(st_PACKER_READ_DATA* pr, U32 aid, st_PKR_ASSET_TOCINFO* tocainfo) +{ + memset(tocainfo, 0, sizeof(st_PKR_ASSET_TOCINFO)); + S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); + if (idx >= 0) + { + st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; + tocainfo->aid = aid; + tocainfo->typeref = assnode->typeref; + tocainfo->sector = pr->base_sector + assnode->d_off / pkr_sector_size; + tocainfo->plus_offset = assnode->d_off % pkr_sector_size; + tocainfo->size = assnode->d_size; + tocainfo->mempos = assnode->memloc; + } + return idx >= 0 ? 1 : 0; +} + +S32 PKR_GetAssetInfoByType(st_PACKER_READ_DATA* pr, U32 type, S32 idx, + st_PKR_ASSET_TOCINFO* tocainfo) +{ + memset(tocainfo, 0, sizeof(st_PKR_ASSET_TOCINFO)); + if (idx < 0) + { + idx = 0; + } + + S32 typeidx = PKR_typeHdlr_idx(pr, type); + if (typeidx < 0) + { + return 0; + } + + st_XORDEREDARRAY* tmplist = &pr->typelist[typeidx]; + if (idx >= tmplist->cnt) + { + return 0; + } + + st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)tmplist->list[idx]; + tocainfo->aid = assnode->aid; + tocainfo->typeref = assnode->typeref; + tocainfo->sector = pr->base_sector + assnode->d_off / pkr_sector_size; + tocainfo->plus_offset = assnode->d_off % pkr_sector_size; + tocainfo->size = assnode->d_size; + tocainfo->mempos = assnode->memloc; + + return 1; +} + +S32 PKR_PkgHasAsset(st_PACKER_READ_DATA* pr, U32 aid) +{ + S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); + if (idx < 0) + { + return 0; + } + + S32 rc = 1; + st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; + if (assnode->loadflag & 0x100000) + { + rc = 0; + } + else if (assnode->loadflag & 0x200000) + { + rc = 0; + } + return rc; +} + +S32 PKR_FRIEND_assetIsGameDup(U32 aid, const st_PACKER_READ_DATA* skippr, S32 oursize, U32 ourtype, + U32 chksum, char*) +{ + S32 is_dup = 0; + if (aid == 0x7ab6743a) + { + return 0; + } + if (aid == 0x98a3f56c) + { + return 0; + } + + for (int i = 0; i < 16; i++) + { + if ((g_loadlock & 1 << i) == 0 || &g_readdatainst[i] == skippr) + { + continue; + } + + S32 idx = XOrdLookup(&g_readdatainst[i].asstoc, (void*)aid, OrdTest_R_AssetID); + if (idx < 0) + { + continue; + } + + st_PACKER_ATOC_NODE* tmp_ass = (st_PACKER_ATOC_NODE*)g_readdatainst[i].asstoc.list[idx]; + if ((tmp_ass->loadflag & 0x80000) == 0 && tmp_ass->asstype != 0x534e4420 && + tmp_ass->asstype != 0x534e4453) + { + continue; + } + + tmp_ass->Name(); + xUtil_idtag2string(tmp_ass->asstype, 0); + + if (ourtype != 0 && ourtype != tmp_ass->asstype) + { + tmp_ass->Name(); + xUtil_idtag2string(tmp_ass->asstype, 0); + xUtil_idtag2string(ourtype, 1); + } + if (oursize >= 0 && oursize != tmp_ass->d_size) + { + tmp_ass->Name(); + xUtil_idtag2string(tmp_ass->asstype, 0); + } + if (chksum != 0 && chksum != tmp_ass->d_chksum) + { + tmp_ass->Name(); + xUtil_idtag2string(tmp_ass->asstype, 0); + } + is_dup = 1; + break; + } + + return is_dup; +} + +S32 PKR_makepool_anode(st_PACKER_READ_DATA* pr, S32 cnt) +{ + if (cnt == 0) + { + return 0; + } + + st_PACKER_ATOC_NODE* assnode = + (st_PACKER_ATOC_NODE*)PKR_getmem('ANOD', cnt * sizeof(st_PACKER_ATOC_NODE), 'FAKE', 0x40); + if (assnode != NULL) + { + pr->pool_anode = assnode; + pr->pool_nextaidx = 0; + } + return assnode != NULL ? cnt * sizeof(st_PACKER_ATOC_NODE) : 0; +} + +void PKR_kiilpool_anode(st_PACKER_READ_DATA* pr) +{ + if (pr->asscnt == 0) + { + return; + } + + PKR_relmem('ANOD', pr->asscnt * sizeof(st_PACKER_ATOC_NODE), pr->pool_anode, 'FAKE', 0); + pr->pool_anode = NULL; + pr->pool_nextaidx = 0; +} + +// +st_PACKER_ATOC_NODE* PKR_newassnode(st_PACKER_READ_DATA* pr, U32 aid) +{ + S32 idx = pr->pool_nextaidx; + st_PACKER_ATOC_NODE* newnode = (st_PACKER_ATOC_NODE*)&pr->pool_anode[idx]; + pr->pool_nextaidx++; + + memset(newnode, 0, sizeof(st_PACKER_ATOC_NODE)); + newnode->aid = aid; + return newnode; +} + +st_PACKER_LTOC_NODE* PKR_newlaynode(en_LAYER_TYPE layer, S32 refcnt) +{ + st_PACKER_LTOC_NODE* newnode = + (st_PACKER_LTOC_NODE*)PKR_getmem('LNOD', sizeof(st_PACKER_LTOC_NODE), layer + 0x8000, 0x40); + memset(newnode, 0, sizeof(st_PACKER_LTOC_NODE)); + + newnode->laytyp = layer; + XOrdInit(&newnode->assref, refcnt <= 1 ? 2 : refcnt, 0); + return newnode; +} + +void PKR_oldlaynode(st_PACKER_LTOC_NODE* laynode) +{ + XOrdDone(&laynode->assref, 0); + PKR_relmem('LNOD', sizeof(st_PACKER_LTOC_NODE), laynode, laynode->laytyp + 0x8000, 0); +} + +S32 OrdComp_R_Asset(void* vkey, void* vitem) +{ + S32 rc; + if (*(U32*)vkey < *(U32*)vitem) + { + rc = -1; + } + else if (*(U32*)vkey > *(U32*)vitem) + { + rc = 1; + } + else + { + rc = 0; + } + return rc; +} + +S32 OrdTest_R_AssetID(const void* vkey, void* vitem) +{ + S32 rc; + if ((U32)vkey < *(U32*)vitem) + { + rc = -1; + } + else if ((U32)vkey > *(U32*)vitem) + { + rc = 1; + } + else + { + rc = 0; + } + return rc; +} + +S32 LOD_r_HIPA(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + pr->pkgver = 'HIPA'; + return 1; +} + +S32 LOD_r_PACK(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + U32 cid = g_hiprf->enter(pkg); + while (cid != 0) + { + switch (cid) + { + case 'PVER': + LOD_r_PVER(pkg, pr); + break; + case 'PFLG': + LOD_r_PFLG(pkg, pr); + break; + case 'PCNT': + LOD_r_PCNT(pkg, pr); + break; + case 'PCRT': + LOD_r_PCRT(pkg, pr); + break; + case 'PMOD': + LOD_r_PMOD(pkg, pr); + break; + case 'PLAT': + LOD_r_PLAT(pkg, pr); + break; + } + g_hiprf->exit(pkg); + cid = g_hiprf->enter(pkg); + } + return 1; +} + +S32 LOD_r_PVER(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 ver = 0; + g_hiprf->readLongs(pkg, &ver, 1); + pr->subver = ver; + + if (ver < 2) + { + PKR_spew_verhist(); + } + + // S32 amt = -1; + ver = -1; + g_hiprf->readLongs(pkg, &ver, 1); + pr->cltver = ver; + + ver = -1; + S32 amt = g_hiprf->readLongs(pkg, &ver, 1); + if (amt != 1) + { + pr->compatver = 1; + } + else + { + pr->compatver = ver; + } + return 1; +} + +S32 LOD_r_PFLG(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 flg = 0; + g_hiprf->readLongs(pkg, &flg, 1); + return 1; +} + +S32 LOD_r_PCNT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 cnt = 0; + g_hiprf->readLongs(pkg, &cnt, 1); + pr->asscnt = cnt; + g_hiprf->readLongs(pkg, &cnt, 1); + pr->laycnt = cnt; + g_hiprf->readLongs(pkg, &cnt, 1); + g_hiprf->readLongs(pkg, &cnt, 1); + g_hiprf->readLongs(pkg, &cnt, 1); + return 1; +} + +S32 LOD_r_PCRT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 time = 0; + char arr[256] = {}; + + g_hiprf->readLongs(pkg, &time, 1); + pr->time_made = time; + + if (pr->subver > 1) + { + g_hiprf->readString(pkg, arr); + } + return 1; +} + +S32 LOD_r_PMOD(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 time_mod = 0; + g_hiprf->readLongs(pkg, &time_mod, 1); + pr->time_mod = time_mod; + return 1; +} + +S32 ValidatePlatform(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr, S32 plattag, char* plat, + char* vid, char* lang, char* title) +{ + char fullname[128] = {}; + sprintf(fullname, "%s %s %s %s", plat, vid, lang, title); + + bool rc = false; + if ((strcmp(plat, "Game Cube") == 0 || strcmp(plat, "Xbox") == 0 || + strcmp(plat, "PlayStation 2") == 0)) + { + rc = true; + } + if (!rc) + { + return 0; + } + + rc = false; + if (strcmp(vid, "NTSC") == 0 || strcmp(vid, "PAL") == 0) + { + rc = true; + } + if (!rc) + { + return 0; + } + + rc = false; + if (strcmp(lang, "US Common") == 0 || strcmp(lang, "United Kingdom") == 0 || + strcmp(lang, "French") == 0 || strcmp(lang, "German") == 0) + { + rc = true; + } + if (!rc) + { + return 0; + } + + rc = false; + if (strcmp(title, "Sponge Bob") == 0 || strcmp(title, "Incredibles") == 0 || + strcmp(title, "Jimmy Newtron") == 0) + { + rc = true; + } + if (!rc) + { + return 0; + } + + rc = !(bool)(strcmp(plat, "Game Cube")); + if (!rc) + { + return 0; + } + + rc = !(strcmp(vid, "NTSC")); + if (!rc) + { + return 0; + } + + rc = !(strcmp(lang, "US Common")); + if (!rc) + { + return 0; + } + + rc = !(strcmp(title, "Sponge Bob")); + if (!rc) + { + return 0; + } + return 1; +} + +S32 LOD_r_PLAT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 result = 1; + S32 plattag = 0; + char platname[32] = {}; + char vidname[32] = {}; + char langname[32] = {}; + char titlename[32] = {}; + + g_hiprf->readLongs(pkg, &plattag, 1); + g_hiprf->readString(pkg, platname); + g_hiprf->readString(pkg, vidname); + g_hiprf->readString(pkg, langname); + if (g_hiprf->readString(pkg, titlename) == 0) + { + strcpy(titlename, ""); + } + if (ValidatePlatform(pkg, pr, plattag, platname, vidname, langname, titlename) == 0) + { + result = 0; + } + return result; +} + +S32 LOD_r_DICT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + U32 cid = g_hiprf->enter(pkg); + while (cid != 0) + { + switch (cid) + { + case 'ATOC': + LOD_r_ATOC(pkg, pr); + XOrdSort(&pr->asstoc, OrdComp_R_Asset); + break; + case 'LTOC': + LOD_r_LTOC(pkg, pr); + break; + } + + g_hiprf->exit(pkg); + cid = g_hiprf->enter(pkg); + } + return 1; +} + +S32 LOD_r_ATOC(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + U32 cid = g_hiprf->enter(pkg); + while (cid != 0) + { + switch (cid) + { + case 'AINF': + LOD_r_AINF(pkg, pr); + break; + case 'AHDR': + LOD_r_AHDR(pkg, pr); + break; + } + g_hiprf->exit(pkg); + cid = g_hiprf->enter(pkg); + } + return 1; +} + +S32 LOD_r_AINF(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 ival = 0; + g_hiprf->readLongs(pkg, &ival, 1); + return 1; +} + +S32 LOD_r_AHDR(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 ival = 0; + + g_hiprf->readLongs(pkg, &ival, 1); + st_PACKER_ATOC_NODE* assnode = PKR_newassnode(pr, ival); + assnode->ownpr = pr; + assnode->ownpkg = pkg; + XOrdAppend(&pr->asstoc, assnode); + + g_hiprf->readLongs(pkg, &ival, 1); + assnode->asstype = ival; + assnode->typeref = PKR_type2typeref(assnode->asstype, pr->types); + + g_hiprf->readLongs(pkg, &ival, 1); + assnode->d_off = ival; + + g_hiprf->readLongs(pkg, &ival, 1); + assnode->d_size = ival; + assnode->readrem = ival; + assnode->readcnt = 0; + if (assnode->d_size < 1) + { + assnode->loadflag |= 0x200000; + } + + g_hiprf->readLongs(pkg, &ival, 1); + assnode->d_pad = ival; + + g_hiprf->readLongs(pkg, &ival, 1); + assnode->infoflag = ival; + + U32 cid = g_hiprf->enter(pkg); + while (cid != 0) + { + switch (cid) + { + case 'ADBG': + LOD_r_ADBG(pkg, pr, assnode); + } + g_hiprf->exit(pkg); + cid = g_hiprf->enter(pkg); + } + + S32 isdup = PKR_FRIEND_assetIsGameDup(assnode->aid, pr, assnode->d_size, assnode->asstype, + assnode->d_chksum, NULL); + if (isdup) + { + assnode->loadflag |= 0x100000; + } + return 1; +} + +S32 LOD_r_ADBG(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr, st_PACKER_ATOC_NODE* assnode) +{ + S32 ival = 0; + char tmpbuf[256] = {}; + + g_hiprf->readLongs(pkg, &ival, 1); + assnode->assalign = ival; + + g_hiprf->readString(pkg, tmpbuf); + tmpbuf[0] = 0; + + g_hiprf->readString(pkg, tmpbuf); + + if (pr->subver > 1) + { + g_hiprf->readLongs(pkg, &ival, 1); + assnode->d_chksum = ival; + } + + return 1; +} + +S32 LOD_r_LTOC(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + U32 cid = g_hiprf->enter(pkg); + while (cid != 0) + { + switch (cid) + { + case 'LINF': + LOD_r_LINF(pkg, pr); + break; + case 'LHDR': + LOD_r_LHDR(pkg, pr); + break; + } + g_hiprf->exit(pkg); + cid = g_hiprf->enter(pkg); + } + return 1; +} + +S32 LOD_r_LINF(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 ival = 0; + g_hiprf->readLongs(pkg, &ival, 1); + return 1; +} + +S32 LOD_r_LHDR(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 i; + S32 ival = 0; + S32 refcnt = 0; + + g_hiprf->readLongs(pkg, &ival, 1); + en_LAYER_TYPE laytyp = (en_LAYER_TYPE)ival; + g_hiprf->readLongs(pkg, &refcnt, 1); + st_PACKER_LTOC_NODE* laynode = PKR_newlaynode(laytyp, refcnt); + XOrdAppend(&pr->laytoc, laynode); + + for (i = 0; i < refcnt; i++) + { + g_hiprf->readLongs(pkg, &ival, 1); + S32 idx = XOrdLookup(&pr->asstoc, (void*)ival, OrdTest_R_AssetID); + st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; + XOrdAppend(&laynode->assref, assnode); + + if (i != refcnt - 1) + { + laynode->laysize += assnode->d_size + assnode->d_pad; + } + else + { + laynode->laysize += assnode->d_size; + } + } + + if (laynode->laysize > 0) + { + laynode->laysize = laynode->laysize + 0x7ff & 0xfffff800; + } + + U32 cid = g_hiprf->enter(pkg); + while (cid != NULL) + { + switch (cid) + { + case 'LDBG': + LOD_r_LDBG(pkg, pr, laynode); + break; + } + g_hiprf->exit(pkg); + cid = g_hiprf->enter(pkg); + } + return 1; +} + +S32 LOD_r_LDBG(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr, st_PACKER_LTOC_NODE* laynode) +{ + S32 ivar = 0; + if (pr->subver > 1) + { + g_hiprf->readLongs(pkg, &ivar, 1); + laynode->chksum = ivar; + } + return 1; +} + +S32 LOD_r_STRM(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + U32 cid = g_hiprf->enter(pkg); + while (cid != 0) + { + switch (cid) + { + case 'DHDR': + LOD_r_DHDR(pkg, pr); + break; + case 'DPAK': + LOD_r_DPAK(pkg, pr); + break; + } + g_hiprf->exit(pkg); + cid = g_hiprf->enter(pkg); + } + return 1; +} + +S32 LOD_r_DHDR(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + S32 ivar = 0; + g_hiprf->readLongs(pkg, &ivar, 1); + return 1; +} + +S32 LOD_r_DPAK(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) +{ + return 1; +} + +void PKR_spew_verhist() +{ +} + +st_PACKER_ASSETTYPE* PKR_type2typeref(U32 asstype, st_PACKER_ASSETTYPE* types) +{ + st_PACKER_ASSETTYPE* da_type = NULL; + if (types != NULL) + { + for (st_PACKER_ASSETTYPE* tmptype = types; tmptype->typetag != 0; tmptype++) + { + if (tmptype->typetag == asstype) + { + da_type = tmptype; + break; + } + } + } + if (da_type == NULL) + { + xUtil_idtag2string(asstype, 0); + } + return da_type; +} + +void PKR_bld_typecnt(st_PACKER_READ_DATA* pr) +{ + st_PACKER_LTOC_NODE* laynode; + st_PACKER_ATOC_NODE* assnode; + S32 j; + S32 i; + S32 typcnt[129] = {}; + st_XORDEREDARRAY* tmplist; + U32 lasttype = 0; + S32 lastidx = 0; + + for (i = 0; i < pr->laytoc.cnt; i++) + { + laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; + for (j = 0; j < laynode->assref.cnt; j++) + { + assnode = (st_PACKER_ATOC_NODE*)laynode->assref.list[j]; + if (!(assnode->loadflag & 0x100000) && !(assnode->loadflag & 0x200000)) + { + S32 idx; + if (lasttype != 0 && assnode->asstype == lasttype) + { + idx = lastidx; + } + else + { + idx = PKR_typeHdlr_idx(pr, assnode->asstype); + lastidx = idx; + lasttype = assnode->asstype; + } + + if (idx < 0) + { + xUtil_idtag2string(assnode->asstype, 0); + assnode->Name(); + typcnt[128]++; + } + else + { + typcnt[idx]++; + } + } + } + } + + for (i = 0; i < 129; i++) + { + if (typcnt[i] >= 1) + { + XOrdInit(&pr->typelist[i], typcnt[i] > 1 ? typcnt[i] : 2, false); + } + } + + for (i = 0; i < pr->laytoc.cnt; i++) + { + st_PACKER_LTOC_NODE* laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; + for (j = 0; j < laynode->assref.cnt; j++) + { + st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)laynode->assref.list[j]; + if (!(assnode->loadflag & 0x100000) && !(assnode->loadflag & 0x200000)) + { + S32 idx; + if (lasttype != 0 && assnode->asstype == lasttype) + { + idx = lastidx; + } + else + { + idx = PKR_typeHdlr_idx(pr, assnode->asstype); + lastidx = idx; + lasttype = assnode->asstype; + } + + st_XORDEREDARRAY* tmplist; + if (idx < 0) + { + tmplist = &pr->typelist[128]; + } + else + { + tmplist = &pr->typelist[idx]; + } + XOrdAppend(tmplist, assnode); + } + } + } +} + +S32 PKR_typeHdlr_idx(st_PACKER_READ_DATA* pr, U32 type) +{ + S32 idx = -1; + int i = 0; + st_PACKER_ASSETTYPE* tmptype = pr->types; + while (tmptype->typetag != 0) + { + if (tmptype->typetag == type) + { + idx = i; + break; + } + i++; + tmptype++; + } + + return idx; +} + +void PKR_alloc_chkidx() +{ +} + +void* PKR_getmem(U32 id, S32 amount, U32 ui, S32 align) +{ + return PKR_getmem(id, amount, ui, align, false, NULL); +} + +void* PKR_getmem(U32 id, S32 amount, U32, S32 align, S32 isTemp, char** memtrue) +{ + if (amount == 0) + { + return NULL; + } + + void* memptr; + + if (isTemp) + { + memptr = xMemPushTemp(amount + align); + + if (memtrue != NULL) + { + *memtrue = (char*)memptr; + } + + if (align != 0) + { + // TODO: wtf is this + memptr = (void*)(-align & (U32)((S32)memptr + align - 1)); + } + } + else + { + memptr = xMemAlloc(gActiveHeap, amount, align); + } + + if (memptr != NULL) + { + memset(memptr, 0, amount); + } + + g_memalloc_pair++; + g_memalloc_runtot += amount; + if (g_memalloc_runtot < 0) + { + g_memalloc_runtot = amount; + } + + if (memptr != NULL) + { + xUtil_idtag2string(id, 0); + } + else + { + xUtil_idtag2string(id, 0); + } + + return memptr; +} + +void PKR_relmem(U32 id, S32 blksize, void* memptr, U32, S32 isTemp) +{ + g_memalloc_pair--; + g_memalloc_runfree += blksize; + if (g_memalloc_runfree < 0) + { + g_memalloc_runfree = blksize; + } + + xUtil_idtag2string(id, 0); + if (memptr != NULL && blksize > 0) + { + if (isTemp) + { + xMemPopTemp(memptr); + } + else + { + xUtil_idtag2string(id, 1); + } + } +} + +void PKR_push_memmark() +{ + xMemPushBase(); +} + +void PKR_pop_memmark() +{ + xMemPopBase(xMemGetBase() - 1); +} + +char* st_PACKER_ATOC_NODE::Name() const +{ + return xpkrsvc_strings + 82; +} diff --git a/src/SB/Core/x/xpkrsvc.h b/src/SB/Core/x/xpkrsvc.h new file mode 100644 index 0000000..7b25e75 --- /dev/null +++ b/src/SB/Core/x/xpkrsvc.h @@ -0,0 +1,224 @@ +#ifndef XPKRSVC_H +#define XPKRSVC_H + +#include +#include + +#include "xhipio.h" +#include "xordarray.h" + +struct st_PACKER_ASSETTYPE +{ + U32 typetag; + U32 tflags; + S32 typalign; + void* (*readXForm)(void*, U32, void*, U32, U32*); + void* (*writeXForm)(void*, U32, void*, void*, U32, U32*); + S32 (*assetLoaded)(void*, U32, void*, S32); + void* (*makeData)(void*, U32, void*, S32*, S32*); + void (*cleanup)(void*, U32, void*); + void (*assetUnloaded)(void*, U32); + void (*writePeek)(void*, U32, void*, char*); +}; + +struct st_PKR_ASSET_TOCINFO +{ + U32 aid; + st_PACKER_ASSETTYPE* typeref; + U32 sector; + U32 plus_offset; + U32 size; + void* mempos; +}; + +enum en_LAYER_TYPE +{ + PKR_LTYPE_DEFAULT, + PKR_LTYPE_TEXTURE, + PKR_LTYPE_BSP, + PKR_LTYPE_MODEL, + PKR_LTYPE_ANIMATION, + PKR_LTYPE_VRAM, + PKR_LTYPE_SRAM, + PKR_LTYPE_SNDTOC, + PKR_LTYPE_CUTSCENE, + PKR_LTYPE_CUTSCENETOC, + PKR_LTYPE_JSPINFO, + PKR_LTYPE_NOMORE, + PKR_LTYPE_ALL = 0xffffffff +}; + +enum en_PKR_LAYER_LOAD_DEST +{ + PKR_LDDEST_SKIP, + PKR_LDDEST_KEEPSTATIC, + PKR_LDDEST_KEEPMALLOC, + PKR_LDDEST_RWHANDOFF, + PKR_LDDEST_NOMORE, + PKR_LDDEST_FORCE = 0x7fffffff +}; + +struct st_PACKER_READ_DATA; +struct st_PACKER_ATOC_NODE +{ + U32 aid; + U32 asstype; + S32 d_off; + S32 d_size; + S32 d_pad; + U32 d_chksum; + S32 assalign; + S32 infoflag; + S32 loadflag; + char* memloc; + S32 x_size; + S32 readcnt; + S32 readrem; + st_PACKER_ASSETTYPE* typeref; + st_HIPLOADDATA* ownpkg; + st_PACKER_READ_DATA* ownpr; + + // looks like this was removed in the GC version + // Evidence: memory allocation; Name function returns a constant + // char basename[32]; + + char* Name() const; +}; + +struct st_PACKER_LTOC_NODE +{ + en_LAYER_TYPE laytyp; + st_XORDEREDARRAY assref; + S32 flg_ldstat; + S32 danglecnt; + U32 chksum; + S32 laysize; + char* laymem; + char* laytru; +}; + +struct st_PACKER_READ_DATA +{ + st_PACKER_ASSETTYPE* types; + void* userdata; + U32 opts; + U32 pkgver; + S32 cltver; + S32 subver; + S32 compatver; + st_HIPLOADDATA* pkg; + U32 base_sector; + S32 lockid; + char packfile[128]; + S32 asscnt; + S32 laycnt; + st_XORDEREDARRAY asstoc; + st_XORDEREDARRAY laytoc; + st_PACKER_ATOC_NODE* pool_anode; + S32 pool_nextaidx; + st_XORDEREDARRAY typelist[129]; + time_t time_made; + time_t time_mod; +}; + +struct st_PACKER_READ_FUNCS +{ + U32 api_ver; + st_PACKER_READ_DATA* (*Init)(void*, char*, U32, S32*, st_PACKER_ASSETTYPE*); + void (*Done)(st_PACKER_READ_DATA*); + S32 (*LoadLayer)(st_PACKER_READ_DATA*, en_LAYER_TYPE); + U32 (*GetAssetSize)(st_PACKER_READ_DATA*, U32); + void* (*LoadAsset)(st_PACKER_READ_DATA*, U32, char*, void*); + void* (*AssetByType)(st_PACKER_READ_DATA*, U32, S32, U32*); + S32 (*AssetCount)(st_PACKER_READ_DATA*, U32); + S32 (*IsAssetReady)(st_PACKER_READ_DATA*, U32); + S32 (*SetActive)(st_PACKER_READ_DATA*, en_LAYER_TYPE); + char* (*AssetName)(st_PACKER_READ_DATA*, U32); + U32 (*GetBaseSector)(st_PACKER_READ_DATA*); + S32 (*GetAssetInfo)(st_PACKER_READ_DATA*, U32, st_PKR_ASSET_TOCINFO*); + S32 (*GetAssetInfoByType)(st_PACKER_READ_DATA*, U32, S32, st_PKR_ASSET_TOCINFO*); + S32 (*PkgHasAsset)(st_PACKER_READ_DATA*, U32); + U32 (*PkgTimeStamp)(st_PACKER_READ_DATA*); + void (*PkgDisconnect)(st_PACKER_READ_DATA*); +}; + +st_PACKER_READ_FUNCS* PKRGetReadFuncs(S32 apiver); +S32 PKRStartup(); +S32 PKRShutdown(); +S32 PKRLoadStep(S32); +st_PACKER_READ_DATA* PKR_ReadInit(void* userdata, char* pkgfile, U32 opts, S32* cltver, + st_PACKER_ASSETTYPE* typelist); +void PKR_ReadDone(st_PACKER_READ_DATA* pr); +S32 PKR_SetActive(st_PACKER_READ_DATA* pr, en_LAYER_TYPE layer); +S32 PKR_parse_TOC(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 PKR_LoadStep_Async(); +char* PKR_LayerMemReserve(st_PACKER_READ_DATA* pr, st_PACKER_LTOC_NODE* layer); +void PKR_LayerMemRelease(st_PACKER_READ_DATA* pr, st_PACKER_LTOC_NODE* layer); +void PKR_drv_guardLayer(st_PACKER_LTOC_NODE*); +S32 PKR_drv_guardVerify(st_PACKER_LTOC_NODE*); +en_PKR_LAYER_LOAD_DEST PKR_layerLoadDest(en_LAYER_TYPE layer); +S32 PKR_layerTypeNeedsXForm(en_LAYER_TYPE layer); +S32 PKR_findNextLayerToLoad(st_PACKER_READ_DATA** work_on_pkg, st_PACKER_LTOC_NODE** next_layer); +void PKR_updateLayerAssets(st_PACKER_LTOC_NODE* laynode); +void PKR_xformLayerAssets(st_PACKER_LTOC_NODE* laynode); +void PKR_xform_asset(st_PACKER_ATOC_NODE* assnode, S32 dumpable_layer); +void* PKR_FindAsset(st_PACKER_READ_DATA* pr, U32 aid); +S32 PKR_LoadLayer(st_PACKER_READ_DATA* pr, en_LAYER_TYPE layer); +void* PKR_LoadAsset(st_PACKER_READ_DATA* pr, U32 aid, char*, void*); +U32 PKR_GetAssetSize(st_PACKER_READ_DATA* pr, U32 aid); +S32 PKR_AssetCount(st_PACKER_READ_DATA* pr, U32 type); +void* PKR_AssetByType(st_PACKER_READ_DATA* pr, U32 type, S32 idx, U32* size); +S32 PKR_IsAssetReady(st_PACKER_READ_DATA* pr, U32 aid); +U32 PKR_getPackTimestamp(st_PACKER_READ_DATA* pr); +void PKR_Disconnect(st_PACKER_READ_DATA* pr); +U32 PKRAssetIDFromInst(void* asset_inst); +char* PKR_AssetName(st_PACKER_READ_DATA* pr, U32 aid); +U32 PKR_GetBaseSector(st_PACKER_READ_DATA* pr); +S32 PKR_GetAssetInfo(st_PACKER_READ_DATA* pr, U32 aid, st_PKR_ASSET_TOCINFO* tocainfo); +S32 PKR_GetAssetInfoByType(st_PACKER_READ_DATA* pr, U32 type, S32 idx, + st_PKR_ASSET_TOCINFO* tocainfo); +S32 PKR_PkgHasAsset(st_PACKER_READ_DATA* pr, U32 aid); +S32 PKR_FRIEND_assetIsGameDup(U32 aid, const st_PACKER_READ_DATA* skippr, S32 oursize, U32 ourtype, + U32 chksum, char*); +S32 PKR_makepool_anode(st_PACKER_READ_DATA* pr, S32 cnt); +void PKR_kiilpool_anode(st_PACKER_READ_DATA* pr); +st_PACKER_ATOC_NODE* PKR_newassnode(st_PACKER_READ_DATA* pr, U32 aid); +st_PACKER_LTOC_NODE* PKR_newlaynode(en_LAYER_TYPE layer, S32 refcnt); +void PKR_oldlaynode(st_PACKER_LTOC_NODE* laytoc); +S32 OrdComp_R_Asset(void* vkey, void* vitem); +S32 OrdTest_R_AssetID(const void* vkey, void* vitem); +S32 LOD_r_HIPA(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_PACK(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_PVER(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_PFLG(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_PCNT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_PCRT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_PMOD(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 ValidatePlatform(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr, S32 plattag, char* plat, + char* vid, char* lang, char* title); +S32 LOD_r_PLAT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_DICT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_ATOC(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_AINF(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_AHDR(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_ADBG(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr, st_PACKER_ATOC_NODE* assnode); +S32 LOD_r_LTOC(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_LINF(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_LHDR(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_LHDR(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_LDBG(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr, st_PACKER_LTOC_NODE* laynode); +S32 LOD_r_STRM(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_DHDR(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +S32 LOD_r_DPAK(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr); +void PKR_spew_verhist(); +st_PACKER_ASSETTYPE* PKR_type2typeref(U32 asstype, st_PACKER_ASSETTYPE* types); +void PKR_bld_typecnt(st_PACKER_READ_DATA* pr); +S32 PKR_typeHdlr_idx(st_PACKER_READ_DATA* pr, U32 type); +void PKR_alloc_chkidx(); +void* PKR_getmem(U32 id, S32 amount, U32, S32 align); +void* PKR_getmem(U32 id, S32 amount, U32, S32 align, S32 isTemp, char** memtrue); +void PKR_relmem(U32 id, S32 blksize, void* memptr, U32, S32 isTemp); +void PKR_push_memmark(); +void PKR_pop_memmark(); + +#endif diff --git a/src/SB/Core/x/xsavegame.cpp b/src/SB/Core/x/xsavegame.cpp new file mode 100644 index 0000000..ea40be0 --- /dev/null +++ b/src/SB/Core/x/xsavegame.cpp @@ -0,0 +1,1480 @@ +#include "xsavegame.h" + +#include +#include +#include + +#include "xutil.h" +#include "xMemMgr.h" +#include "isavegame.h" + +S32 g_xsginit; +st_XSAVEGAME_DATA g_xsgdata = {}; +st_XSAVEGAME_LEADER g_leaders[3] = {}; +static XSGAutoData g_autodata; + +S32 xSGStartup() +{ + if (g_xsginit++ == 0) + { + xUtilStartup(); + iSGStartup(); + memset(&g_xsgdata, 0, sizeof(st_XSAVEGAME_DATA)); + } + xSGAutoSave_Startup(); + return g_xsginit; +} + +S32 xSGShutdown() +{ + g_xsginit--; + if (g_xsginit == 0) + { + iSGShutdown(); + xUtilShutdown(); + } + return g_xsginit; +} + +st_XSAVEGAME_DATA* xSGInit(en_SAVEGAME_MODE mode) +{ + st_XSAVEGAME_DATA* xsgdata = &g_xsgdata; + if (g_xsgdata.stage != 0) + { + return NULL; + } + + xsgdata->mode = mode; + xsgdata->chksum = xUtil_crc_init(); + xsgdata->upd_tally = 1; + xsgdata->file_chksum = 0; + xsgdata->read_chksum = xUtil_crc_init(); + xsgdata->stage |= 1; + xsgdata->isgsess = iSGSessionBegin(xsgdata, xSG_cb_ISGChange, 0); + + if (mode == XSG_MODE_LOAD) + { + xSGAddLoadClient(xsgdata, 'LEDR', xsgdata, xSG_cb_leader_load); + } + else + { + xSGAddSaveClient(xsgdata, 'LEDR', xsgdata, xSG_cb_leader_svinfo, xSG_cb_leader_svproc); + } + + memset(&g_leaders, 0, sizeof(g_leaders)); + return xsgdata; +} + +S32 xSGDone(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + if (!(xsgdata->stage & 1)) + { + result = 0; + } + + if (xsgdata->isgsess != NULL) + { + iSGSessionEnd(xsgdata->isgsess); + } + if (xsgdata->mode == XSG_MODE_SAVE) + { + if (xsgdata->membuf != (char*)0x0) + { + xUtil_idtag2string('XSGS', 0); + xMemPopTemp(xsgdata->membuf); + xsgdata->membuf = (char*)0x0; + xsgdata->memsize = 0; + xsgdata->buf_curpos = (char*)0x0; + } + } + else if (xsgdata->mode == XSG_MODE_LOAD) + { + if (xsgdata->membuf != NULL) + { + xUtil_idtag2string('XSGL', 0); + xMemPopTemp(xsgdata->loadbuf); + xsgdata->loadbuf = NULL; + xsgdata->loadsize = 0; + xsgdata->walkpos = NULL; + xsgdata->walkremain = 0; + } + if (xsgdata->loadbuf != NULL) + { + xMemPopTemp(xsgdata->loadbuf); + xsgdata->loadbuf = NULL; + xsgdata->walkpos = NULL; + xsgdata->walkremain = 0; + } + } + + memset(&g_xsgdata, 0, sizeof(st_XSAVEGAME_DATA)); + memset(&g_leaders, 0, sizeof(g_leaders)); + return result; +} + +S32 xSGCheckForCorruptFiles(st_XSAVEGAME_DATA* xsgdata, char files[][64]) +{ + return iSGCheckForCorruptFiles(xsgdata->isgsess, files); +} + +S32 xSGTgtCount(st_XSAVEGAME_DATA* xsgdata, S32* max) +{ + return iSGTgtCount(xsgdata->isgsess, max); +} + +S32 xSGTgtPhysSlotIdx(st_XSAVEGAME_DATA* xsgdata, S32 tidx) +{ + return iSGTgtPhysSlotIdx(xsgdata->isgsess, tidx); +} + +S32 xSGTgtIsFormat(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32* badEncode) +{ + S32 result = 0; + U32 state = iSGTgtState(xsgdata->isgsess, tidx, NULL); + if (state & 0x4000000) + { + if (badEncode != NULL) + { + *badEncode = 1; + } + } + else if (state & 2) + { + result = 1; + } + + S32 rc = -1; + if (!(state & 0x1000000)) + { + rc = result; + } + return rc; +} + +S32 xSGTgtFormatTgt(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32* canRecover) +{ + return iSGTgtFormat(xsgdata->isgsess, tidx, 0, canRecover); +} + +S32 xSGTgtSelect(st_XSAVEGAME_DATA* xsgdata, S32 tidx) +{ + S32 result = iSGTgtSetActive(xsgdata->isgsess, tidx); + if (result != 0 && xSG_chdir_gamedir(xsgdata) != 0) + { + xSG_grab_leaders(xsgdata); + } + return result; +} + +S32 xSGTgtHasGameDir(st_XSAVEGAME_DATA* xsgdata, S32 tidx) +{ + S32 rc = iSGTgtSetActive(xsgdata->isgsess, tidx); + if (rc != 0) + { + return xSG_chdir_gamedir(xsgdata); + } + return rc; +} + +S32 xSGTgtHaveRoom(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32 fsize, S32 slotidx, + S32* bytesNeeded, S32* availOnDisk, S32* needFile) +{ + char fname[256] = {}; + + if (slotidx < 0) + { + return iSGTgtHaveRoom(xsgdata->isgsess, tidx, fsize, NULL, NULL, bytesNeeded, availOnDisk, + needFile); + } + + strcpy(fname, iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, slotidx)); + return iSGTgtHaveRoom(xsgdata->isgsess, tidx, fsize, NULL, fname, bytesNeeded, availOnDisk, + needFile); +} + +S32 xSGTgtHaveRoomStartup(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32 fsize, S32 slotidx, + S32* bytesNeeded, S32* availOnDisk, S32* needFile) +{ + char fname[256] = {}; + + if (slotidx < 0) + { + return iSGTgtHaveRoomStartup(xsgdata->isgsess, tidx, fsize, NULL, NULL, bytesNeeded, + availOnDisk, needFile); + } + + strcpy(fname, iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, slotidx)); + return iSGTgtHaveRoomStartup(xsgdata->isgsess, tidx, fsize, NULL, fname, bytesNeeded, + availOnDisk, needFile); +} + +U8 xSGCheckMemoryCard(st_XSAVEGAME_DATA* xsgdata, S32 index) +{ + return iSGCheckMemoryCard(xsgdata->isgsess, index); +} + +void xSGGameSet(st_XSAVEGAME_DATA* xsgdata, S32 gidx) +{ + xsgdata->gslot = gidx; +} + +S32 xSGGameIsEmpty(st_XSAVEGAME_DATA* xsgdata, S32 gidx) +{ + return xSGGameSize(xsgdata, gidx) <= 0; +} + +S32 xSGGameSize(st_XSAVEGAME_DATA* xsgdata, S32 gidx) +{ + S32 size = 0; + if (xSG_chdir_gamedir(xsgdata)) + { + char* fname = xSG_cm_slotname(xsgdata, gidx); + size = iSGFileSize(xsgdata->isgsess, fname); + } + return size; +} + +char* xSGGameModDate(st_XSAVEGAME_DATA* xsgdata, S32 gidx) +{ + static char da_date[32] = {}; + da_date[0] = '\0'; + if (xSG_chdir_gamedir(xsgdata)) + { + char* slotname = xSG_cm_slotname(xsgdata, gidx); + char* date = iSGFileModDate(xsgdata->isgsess, slotname); + if (date != NULL) + { + strcpy(da_date, date); + } + else + { + strcpy(da_date, +#if 1 // Need these strings and can't seem get them any other way + 0x409 + "The Mystery Machine\0" + "Mystery Machine\0" + "On Edge in the Hedge!\0" + "Hedges\0" + "It's a Mean Greenhouse, Scooby!\0" + "Greenhouse\0" + "Chills & Spills on Haunted Hill!\0" + "Haunted Hill\0" + "Scared Stiff at Skull Cliff!\0" + "Skull Cliff\0" + "Misbehavin'? Cause a Cave In\0" + "Caves\0" + "A Tight Spot for a Grave Plot!\0" + "Graves\0" + "A One Way Trip to the Crypt!\0" + "Crypts\0" + "Gloom & Doom Down in the Tomb!\0" + "Tombs\0" + "Shock on the Dock!\0" + "Docks\0" + "Fishy Clues for Scooby-Doo?\0" + "Cannery Row\0" + "Fear on the Pier!\0" + "Piers\0" + "Coast for Some Ghosts!\0" + "Shoreline\0" + "Going Down Witch Way?\0" + "Coastal Point\0" + "Lighthouse Fright House!\0" + "Lighthouse\0" + "Wreck on the Deck!\0" + "Danger Rocks\0" + "Aghast by the Mast!\0" + "Masts\0" + "Shiver Your Timbers, Scooby!\0" + "Shipwrecks\0" + "Clamor in the Manor!\0" + "Manor\0" + "Mind Your Manors!\0" + "Stairway\0" + "All Scares Upstairs!\0" + "Upstairs\0" + "Don't Look Down, Scooby-Doo!\0" + "Hallways\0" + "Panic in the Attic!\0" + "Attic\0" + "A Dark and Stormy Knight!\0" + "Rooftops\0" + "Who's Yella' in the Cellar?\0" + "Cellar\0" + "Creepy Crawlies in the Hallways\0" + "Catacombs\0" + "Gusts Abound Underground\0" + "Tunnels\0" + "Little Lab of Horrors\0" + "Secret Lab\0" + "Mastermind Unmasked!\0" + "Mastermind\0" + "Cower in the Tower!\0" + "Tower\0" + "Monster Gallery\0" +#endif + ""); + } + } + return da_date; +} + +char* xSGGameLabel(st_XSAVEGAME_DATA* xsgdata, S32 gidx) +{ + char* da_name = NULL; + if (xSG_chdir_gamedir(xsgdata) && g_leaders[gidx].gameLabel != NULL) + { + da_name = g_leaders[gidx].gameLabel; + } + return da_name; +} + +S32 xSGGameThumbIndex(st_XSAVEGAME_DATA* xsgdata, S32 gidx) +{ + S32 idx_thum = -1; + if (xSG_chdir_gamedir(xsgdata)) + { + st_XSAVEGAME_LEADER* lead = &g_leaders[gidx]; + idx_thum = lead->thumbIconIdx; + } + return idx_thum; +} + +S32 xSGGameProgress(st_XSAVEGAME_DATA* xsgdata, S32 gidx) +{ + S32 progress = -1; + if (xSG_chdir_gamedir(xsgdata)) + { + st_XSAVEGAME_LEADER* lead = &g_leaders[gidx]; + progress = lead->progress; + } + return progress; +} + +S32 xSGAddSaveClient(st_XSAVEGAME_DATA* xsgdata, U32 clttag, void* cltdata, + S32 (*infofunc)(void*, st_XSAVEGAME_DATA*, S32*, S32*), + S32 (*procfunc)(void*, st_XSAVEGAME_DATA*, st_XSAVEGAME_WRITECONTEXT*)) +{ + S32 result = 1; + if (xsgdata->stage & 0x40000000) + { + result = 0; + } + else if (!(xsgdata->stage & 1)) + { + result = 0; + } + + if (xsgdata->stkcnt + 1 >= 128) + { + xUtil_idtag2string(clttag, 0); + result = 0; + } + + st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[xsgdata->stkcnt++]; + clt->idtag = clttag; + clt->cltinfo = infofunc; + clt->cltproc = procfunc; + clt->cltdata = cltdata; + clt->needamt = 0; + clt->realamt = 0; + clt->buf_sizepos = NULL; + + xsgdata->stage |= 4; + if (result == 0) + { + xsgdata->stage |= 0x40000000; + } + return result; +} + +S32 xSGAddLoadClient(st_XSAVEGAME_DATA* xsgdata, U32 clttag, void* cltdata, + S32 (*loadfunc)(void*, st_XSAVEGAME_DATA*, st_XSAVEGAME_READCONTEXT*, + U32, S32)) +{ + S32 result = 1; + if (xsgdata->stage & 0x40000000) + { + result = 0; + } + else if (!(xsgdata->stage & 1)) + { + result = 0; + } + else if (xsgdata->stkcnt + 1 >= 128) + { + xUtil_idtag2string(clttag, 0); + result = 0; + } + + if (clttag != 0 || xsgdata->dfltloadclt.idtag == 0) + { + if (clttag == 0) + { + xsgdata->dfltloadclt.idtag = 1; + xsgdata->dfltloadclt.cltload = loadfunc; + xsgdata->dfltloadclt.cltdata = cltdata; + xsgdata->dfltloadclt.blokact = 0; + xsgdata->dfltloadclt.blokmax = 0; + xsgdata->dfltloadclt.blokpos = NULL; + xsgdata->dfltloadclt.readpos = NULL; + xsgdata->dfltloadclt.readremain = 0; + xsgdata->dfltloadclt.readamt = 0; + } + else + { + st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[xsgdata->stkcnt++]; + clt->idtag = clttag; + clt->cltload = loadfunc; + clt->cltdata = cltdata; + clt->blokact = 0; + clt->blokmax = 0; + clt->blokpos = NULL; + clt->readpos = NULL; + clt->readremain = 0; + clt->readamt = 0; + } + } + + xsgdata->stage |= 2; + if (result == 0) + { + xsgdata->stage |= 0x40000000; + } + return result; +} + +S32 xSGSetup(st_XSAVEGAME_DATA* xsgdata) +{ + return xSGSetup(xsgdata, 0, "nothing", -1, 0, 0); +} + +S32 xSGSetup(st_XSAVEGAME_DATA* xsgdata, S32 gidx, char* label, S32 progress, iTime playtime, + S32 thumbIconIdx) +{ + S32 result = 1; + if (xsgdata->stage & 0x40000000) + { + result = 0; + } + else if (!(xsgdata->stage & 1)) + { + result = 0; + } + + if (xsgdata->mode == XSG_MODE_SAVE) + { + xsgdata->gslot = gidx; + strncpy(xsgdata->label, label, 63); + xsgdata->label[63] = '\0'; + xsgdata->playtime = playtime; + xsgdata->progress = progress; + xsgdata->thumbIconIdx = thumbIconIdx; + if (result != 0 && xSG_sv_flipinfo(xsgdata) == 0) + { + result = 0; + } + if (result != 0 && xSG_sv_prepdest(xsgdata) == 0) + { + result = 0; + } + } + else + { + if (xSG_ld_prepload(xsgdata) == 0) + { + result = 0; + } + } + + xsgdata->stage |= 8; + if (result == 0) + { + xsgdata->stage |= 0x40000000; + } + return result; +} + +S32 xSGProcess(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + if (xsgdata->stage & 0x40000000) + { + result = 0; + } + else if (!(xsgdata->stage & 1)) + { + result = 0; + } + else if (!(xsgdata->stage & 8)) + { + result = 0; + } + + if (result != 0 && xsgdata->mode == XSG_MODE_SAVE) + { + if (xSG_smem_blkopen(xsgdata) == 0) + { + result = 0; + } + + if (result != 0 && xSG_sv_flipproc(xsgdata) == 0) + { + result = 0; + } + if (result != 0 && xSG_sv_bldchksum(xsgdata) == 0) + { + result = 0; + } + if (result != 0 && xSG_smem_blkclose(xsgdata) == 0) + { + result = 0; + } + + if (result != 0) + { + xSG_sv_commit(xsgdata); + } + } + else if (result != 0 && xsgdata->mode == XSG_MODE_LOAD) + { + if (xSG_ld_readgame(xsgdata) == 0) + { + result = 0; + } + } + + xsgdata->stage |= 0x10; + if (result == 0) + { + xsgdata->stage |= 0x40000000; + } + return result; +} + +S32 xSGWrapup(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + S32 rc = 0; + + if (xsgdata->stage & 0x40000000) + { + result = 0; + } + else if (!(xsgdata->stage & 1)) + { + result = 0; + } + else if (!(xsgdata->stage & 0x10)) + { + result = 0; + xsgdata->stage |= 0x40000000; + } + + if (xsgdata->mode != XSG_MODE_LOAD) + { + return result; + } + if (result == 0) + { + return result; + } + + if (result != 0) + { + rc = xSG_ld_readhead(xsgdata); + } + if (rc < 0) + { + xsgdata->stage |= 0x40000000; + return -1; + } + + if (rc == 0) + { + result = 0; + } + if (result != 0) + { + rc = xSG_ld_validate(xsgdata); + } + + if (rc < 0) + { + xsgdata->stage |= 0x40000000; + return -1; + } + + if (rc == 0) + { + result = 0; + } + if (result != 0) + { + rc = xSG_ld_findcltblk(xsgdata); + } + + if (rc == 0) + { + result = 0; + } + if (result != 0) + { + rc = xSG_ld_flipload(xsgdata); + } + + if (rc == 0) + { + result = 0; + } + if (result == 0) + { + xsgdata->stage |= 0x40000000; + } + + return result; +} + +en_XSGASYNC_STATUS xSGAsyncStatus(st_XSAVEGAME_DATA* xsgdata, S32 block, en_XSG_WHYFAIL* whyFail, + char* errmsg) +{ + en_XSGASYNC_STATUS xstat = XSG_ASTAT_NOOP; + en_ASYNC_OPERR whyerr = ISG_OPERR_NONE; + + if (errmsg != NULL) + { + errmsg[0] = '\0'; + } + + en_ASYNC_OPSTAT istat = iSGPollStatus(xsgdata->isgsess, 0, block); + switch (istat) + { + case ISG_OPSTAT_FAILURE: + xstat = XSG_ASTAT_FAILED; + whyerr = iSGOpError(xsgdata->isgsess, errmsg); + break; + case ISG_OPSTAT_INPROG: + xstat = XSG_ASTAT_INPROG; + break; + case ISG_OPSTAT_SUCCESS: + xstat = XSG_ASTAT_SUCCESS; + break; + } + + if (whyFail != NULL && whyerr != ISG_OPERR_NONE) + { + en_XSG_WHYFAIL con = XSG_WHYERR_NONE; + + switch (whyerr) + { + case ISG_OPERR_NONE: + break; + case ISG_OPERR_NOCARD: + con = XSG_WHYERR_NOCARD; + break; + case ISG_OPERR_NOROOM: + case ISG_OPERR_SVNOSPACE: + con = XSG_WHYERR_NOROOM; + break; + case ISG_OPERR_DAMAGE: + con = XSG_WHYERR_DAMAGE; + break; + case ISG_OPERR_SVWRITE: + con = XSG_WHYERR_CARDYANKED; + break; + default: + con = XSG_WHYERR_OTHER; + break; + } + *whyFail = con; + } + return xstat; +} + +S32 xSG_cb_leader_svinfo(void*, st_XSAVEGAME_DATA*, S32* cur_space, S32* max_fullgame) +{ + *cur_space = 0x100; + *max_fullgame = 0x100; + return 1; +} + +S32 xSG_cb_leader_svproc(void* cltdata, st_XSAVEGAME_DATA* original_xsgdata, + st_XSAVEGAME_WRITECONTEXT* wctxt) +{ + st_XSAVEGAME_DATA* xsg = (st_XSAVEGAME_DATA*)cltdata; + st_XSAVEGAME_LEADER leader = {}; + char fundata[] = "--TakeMeToYourLeader--"; + + strncpy(leader.gameLabel, xsg->label, 0x40); + leader.gameLabel[63] = 0; + leader.gametime = xsg->playtime; + leader.progress = xsg->progress; + leader.thumbIconIdx = xsg->thumbIconIdx; + + xSGWriteData(original_xsgdata, wctxt, leader.gameLabel, sizeof(st_XSAVEGAME_LEADER)); + xSGWriteData(original_xsgdata, wctxt, fundata, 0x16); + return 1; +} + +S32 xSG_cb_leader_load(void*, st_XSAVEGAME_DATA* original_xsgdata, + st_XSAVEGAME_READCONTEXT* rctxt, U32, S32) +{ + char fundata[32] = {}; + st_XSAVEGAME_LEADER discard = {}; + xSGReadData(original_xsgdata, rctxt, discard.gameLabel, sizeof(st_XSAVEGAME_LEADER)); + xSGReadData(original_xsgdata, rctxt, fundata, 0x16); + return 1; +} + +S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, char* data, + S32 elesiz, S32 n) +{ + S32 cnt; + S32 is_ok = 1; + + if (xsgdata->stage & 0x40000000) + { + return 0; + } + if (elesiz == 0) + { + return 0; + } + + cnt = n * elesiz; + if (cnt == 0) + { + return cnt; + } + + if (xsgdata->upd_tally != 0 && xsgdata->totamt + cnt > xsgdata->memsize) + { + xsgdata->stage |= 0x40000000; + return 0; + } + + void* mcprc; + mcprc = memcpy(xsgdata->buf_curpos, data, cnt); + if (mcprc == NULL) + { + is_ok = 0; + } + else + { + xsgdata->buf_curpos += cnt; + } + + // I wonder if this was supposed to be a boolean and + if (is_ok & xsgdata->upd_tally) + { + xsgdata->totamt += cnt; + if (wctxt != NULL) + { + st_XSAVEGAME_CLIENT* clt = (st_XSAVEGAME_CLIENT*)wctxt; + clt->realamt += cnt; + } + } + + if (is_ok == 0) + { + xsgdata->stage |= 0x40000000; + return 0; + } + else + { + return cnt / elesiz; + } + + return cnt; +} + +S32 xSGWriteStrLen(const char* str) +{ + S32 len = strlen(str); + len += (len + 1 & 1) + 1; + return len; +} + +S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, char* data, + S32 n) +{ + return xSGWriteData(xsgdata, wctxt, data, sizeof(char), n); +} + +S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, S32* data, + S32 n) +{ + return xSGWriteData(xsgdata, wctxt, (char*)data, sizeof(S32), n); +} + +S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, U32* data, + S32 n) +{ + return xSGWriteData(xsgdata, wctxt, (char*)data, sizeof(U32), n); +} + +S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, F32* data, + S32 n) +{ + return xSGWriteData(xsgdata, wctxt, (char*)data, sizeof(F32), n); +} + +S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, char* buff, + S32 elesiz, S32 n) +{ + S32 cnt; + if (elesiz == 0) + { + return 0; + } + + cnt = n * elesiz; + if (cnt == 0) + { + return cnt; + } + + st_XSAVEGAME_CLIENT* clt = (st_XSAVEGAME_CLIENT*)rctxt; + if (clt != NULL && cnt > clt->readremain) + { + xUtil_idtag2string(clt->idtag, 0); + return 0; + } + + if (clt != NULL) + { + memcpy(buff, clt->readpos, cnt); + } + else + { + memcpy(buff, xsgdata->walkpos, cnt); + } + + xsgdata->walkpos += cnt; + xsgdata->walkremain -= cnt; + + if (clt != NULL) + { + clt->readpos += cnt; + clt->readamt += cnt; + clt->readremain -= cnt; + } + + return cnt / elesiz; +} + +S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, char* buff, S32 n) +{ + return xSGReadData(xsgdata, rctxt, buff, sizeof(char), n); +} + +S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, S32* buff, S32 n) +{ + return xSGReadData(xsgdata, rctxt, (char*)buff, sizeof(S32), n); +} + +S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, U32* buff, + S32 n) +{ + return xSGReadData(xsgdata, rctxt, (char*)buff, sizeof(U32), n); +} + +S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, F32* buff, + S32 n) +{ + return xSGReadData(xsgdata, rctxt, (char*)buff, sizeof(F32), n); +} + +S32 xSG_grab_leaders(st_XSAVEGAME_DATA* xsgdata) +{ + S32 num_found = 0; + char readbuf[116] = {}; + + memset(&g_leaders, 0, sizeof(g_leaders)); + + if (!xSG_chdir_gamedir(xsgdata)) + { + return 0; + } + + for (S32 i = 0; i < 3; i++) + { + if (!xSGGameIsEmpty(xsgdata, i)) + { + char* slotname = xSG_cm_slotname(xsgdata, i); + S32 rc = iSGReadLeader(xsgdata->isgsess, slotname, readbuf, sizeof(readbuf), 0); + if (rc != 0) + { + num_found++; + memcpy(&g_leaders[i], readbuf + 0x1c, sizeof(st_XSAVEGAME_LEADER)); + } + } + } + + return num_found; +} + +S32 xSG_chdir_gamedir(st_XSAVEGAME_DATA* xsgdata) +{ + S32 rc = 1; + char* name = iSGMakeName(ISG_NGTYP_GAMEDIR, NULL, 0); + if (!iSGSelectGameDir(xsgdata->isgsess, name)) + { + rc = 0; + } + return rc; +} + +char* xSG_cm_slotname(st_XSAVEGAME_DATA* xsgdata, S32 gidx) +{ + static char slotname[32] = {}; + slotname[0] = '\0'; + + char* tmp; + if (gidx == 0x9a5) + { + tmp = iSGMakeName(ISG_NGTYP_CONFIG, NULL, 0); + } + else + { + tmp = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, gidx); + } + strcpy(slotname, tmp); + return slotname; +} + +void xSG_areaComposeLabel(char* label, int, char*, int) +{ + char buf[64] = {}; + iSGMakeTimeStamp(buf); + sprintf(label, "%s", buf); +} + +S32 xSG_sv_flipinfo(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + S32 cltamt = 0; + S32 cltmax = 0; + + for (S32 i = 0; i < xsgdata->stkcnt; i++) + { + st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[i]; + cltamt = 0; + cltmax = 0; + + S32 rc = clt->cltinfo(clt->cltdata, xsgdata, &cltamt, &cltmax); + if (rc == 0) + { + xUtil_idtag2string(clt->idtag, 0); + result = 0; + } + else + { + clt->needamt = cltamt; + clt->maxamt = cltmax; + xsgdata->cltneed += cltamt; + xsgdata->cltmax += cltmax; + xsgdata->chdrneed += 0xc; + } + + if (result == 0) + { + xsgdata->stage |= 0x40000000; + break; + } + } + return result; +} + +S32 xSG_sv_prepdest(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + + if (xsgdata->cltneed < 1) + { + result = 0; + } + else + { + xsgdata->memsize = xsgdata->cltmax + xsgdata->chdrneed + 0x10; + xsgdata->membuf = (char*)xMemPushTemp(xsgdata->memsize); + + if (xsgdata->membuf == NULL) + { + result = 0; + } + else + { + xUtil_idtag2string('XSGS', 0); + memset(xsgdata->membuf, 0, xsgdata->memsize); + xsgdata->buf_curpos = xsgdata->membuf; + } + } + return result; +} + +S32 xSG_sv_flipproc(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + S32 rc; + char bfill = 0xbf; + + for (S32 i = 0; i < xsgdata->stkcnt; i++) + { + st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[i]; + + rc = xSG_smem_cltopen(xsgdata, clt); + if (rc != 0) + { + rc = clt->cltproc(clt->cltdata, xsgdata, (st_XSAVEGAME_WRITECONTEXT*)clt); + if (rc == 0) + { + xUtil_idtag2string(clt->idtag, 0); + result = 0; + } + + S32 needfill = clt->maxamt - clt->realamt; + xUtil_idtag2string(clt->idtag, 0); + while (needfill-- > 0) + { + xSGWriteData(xsgdata, NULL, &bfill, 1); + } + } + + if (rc != 0 && xSG_smem_cltclose(xsgdata, clt) == 0) + { + result = 0; + xUtil_idtag2string(clt->idtag, 0); + } + + if (result == 0) + { + break; + } + } + return result; +} + +S32 xSG_sv_bldchksum(st_XSAVEGAME_DATA* xsgdata) +{ + xsgdata->chksum = + xUtil_crc_update(xsgdata->chksum, xsgdata->membuf + 16, xsgdata->memsize - 16); + return 1; +} + +S32 xSG_smem_blkopen(st_XSAVEGAME_DATA* xsgdata) +{ + S32 i = '3333'; + S32 j = 'GDAT'; + S32 k = 1; + + xSGWriteData(xsgdata, 0, &j, 1); + xSGWriteData(xsgdata, 0, &k, 1); + + xsgdata->buf_sizespot = xsgdata->buf_curpos; + xSGWriteData(xsgdata, 0, &i, 1); + xsgdata->buf_cksmspot = xsgdata->buf_curpos; + xSGWriteData(xsgdata, 0, &i, 1); + return 1; +} + +S32 xSG_smem_blkclose(st_XSAVEGAME_DATA* xsgdata) +{ + xsgdata->upd_tally = 0; + + char* last_bufpos = xsgdata->buf_curpos; + xsgdata->buf_curpos = xsgdata->buf_sizespot; + xSGWriteData(xsgdata, NULL, &xsgdata->totamt, 1); + xsgdata->buf_curpos = last_bufpos; + + last_bufpos = xsgdata->buf_curpos; + xsgdata->buf_curpos = xsgdata->buf_cksmspot; + xSGWriteData(xsgdata, NULL, &xsgdata->chksum, 1); + xsgdata->buf_curpos = last_bufpos; + xsgdata->upd_tally = 1; + return 1; +} + +S32 xSG_smem_cltopen(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_CLIENT* clt) +{ + S32 i = '3333'; + S32 j = 0; + + xUtil_idtag2string(clt->idtag, 0); + j = clt->idtag; + xSGWriteData(xsgdata, 0, &j, 1); + clt->buf_maxpos = xsgdata->buf_curpos; + xSGWriteData(xsgdata, 0, &i, 1); + clt->buf_sizepos = xsgdata->buf_curpos; + xSGWriteData(xsgdata, 0, &i, 1); + xUtil_idtag2string(clt->idtag, 0); + return 1; +} + +S32 xSG_smem_cltclose(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_CLIENT* clt) +{ + xUtil_idtag2string(clt->idtag, 0); + xsgdata->upd_tally = 0; + if (clt->needamt < clt->realamt) + { + xUtil_idtag2string(clt->idtag, 0); + } + + char* last_bufpos = xsgdata->buf_curpos; + xsgdata->buf_curpos = clt->buf_maxpos; + xSGWriteData(xsgdata, NULL, &clt->maxamt, 1); + xsgdata->buf_curpos = last_bufpos; + + xsgdata->buf_curpos = clt->buf_sizepos; + xSGWriteData(xsgdata, NULL, &clt->realamt, 1); + xsgdata->buf_curpos = last_bufpos; + xsgdata->upd_tally = 1; + + xUtil_idtag2string(clt->idtag, 0); + return 1; +} + +S32 xSG_sv_commit(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + S32 rc; + char browselabel[64] = {}; + + char* name = iSGMakeName(ISG_NGTYP_GAMEDIR, NULL, 0); + if (!iSGSetupGameDir(xsgdata->isgsess, name, 1)) + { + result = 0; + } + else + { + xSG_areaComposeLabel(browselabel, xsgdata->thumbIconIdx, xsgdata->label, + xsgdata->gslot + 1); + + if (!iSGSaveFile(xsgdata->isgsess, iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, xsgdata->gslot), + xsgdata->membuf, xsgdata->memsize, 1, browselabel)) + { + result = 0; + } + } + + return result; +} + +void xSG_cb_ISGChange(void*, en_CHGCODE what) +{ + XSGAutoData* asg = xSGAutoSave_GetCache(); + switch (what) + { + case ISG_CHG_NONE: + break; + case ISG_CHG_TARGET: + asg->MarkInvalid(); + break; + case ISG_CHG_GAMELIST: + asg->MarkInvalid(); + break; + } +} + +S32 xSG_ld_prepload(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + char* name = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, xsgdata->gslot); + xsgdata->loadsize = iSGFileSize(xsgdata->isgsess, name); + + if (xsgdata->loadsize < 1) + { + result = 0; + } + else + { + xsgdata->loadbuf = (char*)xMemPushTemp(xsgdata->loadsize); + memset(xsgdata->loadbuf, 0, xsgdata->loadsize); + } + return result; +} + +S32 xSG_ld_readgame(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + if (xsgdata->stage & 0x40000000) + { + result = 0; + } + + char* name = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, xsgdata->gslot); + if (!iSGLoadFile(xsgdata->isgsess, name, xsgdata->loadbuf, 1)) + { + result = 0; + } + + if (result == 0) + { + xsgdata->stage |= 0x40000000; + } + + return result; +} + +S32 xSG_ld_readhead(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + S32 ival = 0; + bool not_ok = 0; + + xsgdata->walkpos = xsgdata->loadbuf; + xsgdata->walkremain = xsgdata->loadsize; + xSGReadData(xsgdata, NULL, &ival, 1); + + if (ival != 'GDAT') + { + result = 0; + not_ok = 1; + } + + xSGReadData(xsgdata, NULL, &ival, 1); + if (ival != 1) + { + result = 0; + not_ok = 1; + } + + xSGReadData(xsgdata, NULL, &ival, 1); + xsgdata->readsize = ival; + + xSGReadData(xsgdata, NULL, &ival, 1); + xsgdata->file_chksum = ival; + if (not_ok) + { + return -1; + } + return result; +} + +S32 xSG_ld_validate(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + + xsgdata->loadsize = xsgdata->readsize; + xsgdata->walkpos = xsgdata->loadbuf + 0x10; + xsgdata->walkremain = xsgdata->loadsize - 0x10; + xsgdata->read_chksum = + xUtil_crc_update(xsgdata->read_chksum, xsgdata->walkpos, xsgdata->walkremain); + + if (xsgdata->read_chksum != xsgdata->file_chksum) + { + result = -1; + } + + return result; +} + +S32 xSG_ld_findcltblk(st_XSAVEGAME_DATA* xsgdata) +{ + S32 ival = 0; + U32 tag = 0; + S32 maxamt = 0; + S32 actamt = 0; + st_XSAVEGAME_CLIENT* dfltclt = &xsgdata->dfltloadclt; + + xsgdata->walkpos = xsgdata->loadbuf; + xsgdata->walkremain = xsgdata->loadsize; + xSGReadData(xsgdata, 0, &ival, 1); + xSGReadData(xsgdata, 0, &ival, 1); + xSGReadData(xsgdata, 0, &ival, 1); + xSGReadData(xsgdata, 0, &ival, 1); + + while (xsgdata->walkremain > 0) + { + tag = 0; + S32 found = 0; + maxamt = 0; + actamt = 0; + + xSGReadData(xsgdata, 0, &tag, 1); + xSGReadData(xsgdata, 0, &maxamt, 1); + xSGReadData(xsgdata, 0, &actamt, 1); + xUtil_idtag2string(tag, 0); + + for (S32 i = 0; i < xsgdata->stkcnt; i++) + { + st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[i]; + + if (clt->idtag == tag) + { + found = true; + clt->blokpos = xsgdata->walkpos; + clt->blokact = actamt; + clt->blokmax = maxamt; + clt->readpos = xsgdata->walkpos; + clt->readamt = 0; + clt->readremain = actamt; + break; + } + } + + if (!found) + { + if (dfltclt->idtag != 0) + { + xUtil_idtag2string(tag, 0); + dfltclt->blokpos = xsgdata->walkpos; + dfltclt->blokact = actamt; + dfltclt->blokmax = maxamt; + dfltclt->readpos = xsgdata->walkpos; + dfltclt->readamt = 0; + dfltclt->readremain = actamt; + + S32 rc = + dfltclt->cltload(dfltclt->cltdata, xsgdata, (st_XSAVEGAME_READCONTEXT*)dfltclt, + tag, dfltclt->blokact); + if (rc == 0) + { + xUtil_idtag2string(tag, 0); + } + + rc = dfltclt->readremain; + if (rc > 0) + { + xsgdata->walkpos += rc + (maxamt - actamt); + xsgdata->walkremain -= dfltclt->readremain + (maxamt - actamt); + } + } + else + { + xUtil_idtag2string(tag, 0); + xsgdata->walkpos += maxamt; + xsgdata->walkremain -= maxamt; + } + } + else + { + xsgdata->walkpos += maxamt; + xsgdata->walkremain -= maxamt; + } + } + return 1; +} + +S32 xSG_ld_flipload(st_XSAVEGAME_DATA* xsgdata) +{ + S32 result = 1; + S32 rc; + + for (S32 i = 0; i < xsgdata->stkcnt; i++) + { + st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[i]; + if (clt->cltload != NULL && clt->blokact != 0 && clt->blokpos != NULL) + { + xUtil_idtag2string(clt->idtag, 0); + + rc = clt->cltload(clt->cltdata, xsgdata, (st_XSAVEGAME_READCONTEXT*)clt, clt->idtag, + clt->blokact); + if (rc == 0) + { + xUtil_idtag2string(clt->idtag, 0); + result = 0; + } + } + else + { + xUtil_idtag2string(clt->idtag, 0); + } + + if (result == 0) + { + break; + } + } + + return result; +} + +XSGAutoData* xSGAutoSave_GetCache() +{ + return &g_autodata; +} + +void xSGAutoSave_Startup() +{ + XSGAutoData* asg = xSGAutoSave_GetCache(); + asg->flg_autodata = 0; + asg->lastGame = -1; + asg->lastTarg = -1; + asg->lastPhysicalSlot = -1; + iSGAutoSave_Startup(); +} + +S32 XSGAutoData::IsValid() +{ + if (this->flg_autodata & 1 && !XSGAutoData::HWCheckConnect(this->lastTarg)) + { + this->flg_autodata &= 0x0fffffffe; + } + return this->flg_autodata & 1; +} + +void XSGAutoData::MarkInvalid() +{ + this->flg_autodata &= 0xfffffffe; +} + +S32 XSGAutoData::SetCache(S32 targ, S32 game, S32 physicalSlot) +{ + this->Discard(); + this->isg_monitor = this->HWConnect(targ); + if (this->isg_monitor == NULL) + { + return 0; + } + + this->lastTarg = targ; + this->lastGame = game; + this->lastPhysicalSlot = physicalSlot; + this->flg_autodata |= 1; + return 1; +} + +void XSGAutoData::Discard() +{ + this->flg_autodata = 0; + this->lastTarg = -1; + this->lastGame = -1; + this->lastPhysicalSlot = -1; + if (this->isg_monitor != NULL) + { + this->HWDisconnect(this->isg_monitor); + } + this->isg_monitor = NULL; +} + +st_ISGSESSION* XSGAutoData::HWConnect(S32 targ) +{ + return iSGAutoSave_Connect(targ, xSGAutoSave_GetCache(), ASG_ISG_changed); +} + +void XSGAutoData::HWDisconnect(st_ISGSESSION* isgsess) +{ + iSGAutoSave_Disconnect(isgsess); +} + +S32 XSGAutoData::HWCheckConnect(S32 targ) +{ + return iSGAutoSave_Monitor(this->isg_monitor, this->lastTarg); +} + +void ASG_ISG_changed(void*, en_CHGCODE what) +{ + XSGAutoData* asg = xSGAutoSave_GetCache(); + switch (what) + { + case ISG_CHG_NONE: + break; + case ISG_CHG_TARGET: + asg->MarkInvalid(); + break; + case ISG_CHG_GAMELIST: + asg->MarkInvalid(); + break; + } +} diff --git a/src/SB/Core/x/xsavegame.h b/src/SB/Core/x/xsavegame.h new file mode 100644 index 0000000..a62b609 --- /dev/null +++ b/src/SB/Core/x/xsavegame.h @@ -0,0 +1,217 @@ +#ifndef XSAVEGAME_H +#define XSAVEGAME_H + +#include + +#include "iTime.h" +#include "isavegame.h" + +struct st_XSAVEGAME_READCONTEXT +{ +}; + +struct st_XSAVEGAME_WRITECONTEXT +{ +}; + +enum en_SAVEGAME_MODE +{ + XSG_MODE_LOAD = 0xa, + XSG_MODE_SAVE +}; + +struct st_XSAVEGAME_DATA; + +struct st_XSAVEGAME_CLIENT +{ + U32 idtag; + S32 (*cltinfo)(void*, st_XSAVEGAME_DATA*, S32*, S32*); + S32 (*cltproc)(void*, st_XSAVEGAME_DATA*, st_XSAVEGAME_WRITECONTEXT*); + S32 (*cltload)(void*, st_XSAVEGAME_DATA*, st_XSAVEGAME_READCONTEXT*, U32, S32); + void* cltdata; + S32 needamt; + S32 maxamt; + S32 realamt; + char* buf_sizepos; + char* buf_maxpos; + S32 blokact; + S32 blokmax; + char* blokpos; + char* readpos; + S32 readamt; + S32 readremain; +}; + +struct st_XSAVEGAME_DATA +{ + S32 gfile_idx; + en_SAVEGAME_MODE mode; + U32 stage; + S32 gslot; + char label[64]; + S32 progress; + S32 thumbIconIdx; + iTime playtime; + char* membuf; + S32 memsize; + char* buf_curpos; + char* buf_sizespot; + char* buf_cksmspot; + S32 totamt; + U32 chksum; + U32 upd_tally; + S32 cltneed; + S32 cltmax; + S32 chdrneed; + S32 stkcnt; + st_XSAVEGAME_CLIENT cltstk[128]; + st_XSAVEGAME_CLIENT dfltloadclt; + U32 file_chksum; + U32 read_chksum; + S32 readsize; + char* loadbuf; + S32 loadsize; + char* walkpos; + S32 walkremain; + st_ISGSESSION* isgsess; +}; + +struct XSGAutoData +{ + S32 flg_autodata; + S32 lastTarg; + S32 lastGame; + S32 lastPhysicalSlot; + st_ISGSESSION* isg_monitor; + + S32 IsValid(); + void MarkInvalid(); + S32 SetCache(S32 targ, S32 game, S32 physicalSlot); + void Discard(); + st_ISGSESSION* HWConnect(S32 targ); + void HWDisconnect(st_ISGSESSION* isgsess); + S32 HWCheckConnect(S32 targ); + S32 LastPhysicalSlot(); + S32 LastGame(); + S32 LastTarget(); +}; + +enum en_XSGASYNC_STATUS +{ + XSG_ASTAT_NOOP, + XSG_ASTAT_INPROG, + XSG_ASTAT_SUCCESS, + XSG_ASTAT_FAILED +}; + +struct st_XSAVEGAME_LEADER +{ + char gameLabel[64]; + S32 progress; + iTime gametime; + char thumbIconIdx; +}; + +enum en_XSG_WHYFAIL +{ + XSG_WHYERR_NONE, + XSG_WHYERR_NOCARD, + XSG_WHYERR_NOROOM, + XSG_WHYERR_DAMAGE, + XSG_WHYERR_CARDYANKED, + XSG_WHYERR_OTHER, + XSG_WHYERR_NOMORE +}; + +struct st_XSG_SHORTLABEL +{ + const char* msglong; + const char* msgshort; +}; + +S32 xSGStartup(); +S32 xSGShutdown(); +st_XSAVEGAME_DATA* xSGInit(en_SAVEGAME_MODE mode); +S32 xSGDone(st_XSAVEGAME_DATA* xsgdata); +S32 xSGCheckForCorruptFiles(st_XSAVEGAME_DATA* xsgdata, char files[][64]); +S32 xSGTgtCount(st_XSAVEGAME_DATA* xsgdata, S32* max); +S32 xSGTgtPhysSlotIdx(st_XSAVEGAME_DATA* xsgdata, S32 tidx); +S32 xSGTgtIsFormat(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32* badEncode); +S32 xSGTgtFormatTgt(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32* canRecover); +S32 xSGTgtSelect(st_XSAVEGAME_DATA* xsgdata, S32 tidx); +S32 xSGTgtHasGameDir(st_XSAVEGAME_DATA* xsgdata, S32 tidx); +S32 xSGTgtHaveRoom(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32 fsize, S32 slotidx, + S32* bytesNeeded, S32* availOnDisk, S32* needFile); +S32 xSGTgtHaveRoomStartup(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32 fsize, S32 slotidx, + S32* bytesNeeded, S32* availOnDisk, S32* needFile); +U8 xSGCheckMemoryCard(st_XSAVEGAME_DATA* xsgdata, S32 index); +void xSGGameSet(st_XSAVEGAME_DATA* xsgdata, S32 gidx); +S32 xSGGameIsEmpty(st_XSAVEGAME_DATA* xsgdata, S32 gidx); +S32 xSGGameSize(st_XSAVEGAME_DATA* xsgdata, S32 gidx); +char* xSGGameModDate(st_XSAVEGAME_DATA* xsgdata, S32 gidx); +char* xSGGameLabel(st_XSAVEGAME_DATA* xsgdata, S32 gidx); +S32 xSGGameThumbIndex(st_XSAVEGAME_DATA* xsgdata, S32 gidx); +S32 xSGGameProgress(st_XSAVEGAME_DATA* xsgdata, S32 gidx); +S32 xSGAddSaveClient(st_XSAVEGAME_DATA* xsgdata, U32 clttag, void* cltdata, + S32 (*infofunc)(void*, st_XSAVEGAME_DATA*, S32*, S32*), + S32 (*procfunc)(void*, st_XSAVEGAME_DATA*, st_XSAVEGAME_WRITECONTEXT*)); +S32 xSGAddLoadClient(st_XSAVEGAME_DATA* xsgdata, U32 clttag, void* cltdata, + S32 (*loadfunc)(void*, st_XSAVEGAME_DATA*, st_XSAVEGAME_READCONTEXT*, + U32, S32)); +S32 xSGSetup(st_XSAVEGAME_DATA* xsgdata); +S32 xSGSetup(st_XSAVEGAME_DATA* xsgdata, S32 gidx, char* label, S32 progress, iTime playtime, + S32 thumbIconIdx); +S32 xSGProcess(st_XSAVEGAME_DATA* xsgdata); +S32 xSGWrapup(st_XSAVEGAME_DATA* xsgdata); +en_XSGASYNC_STATUS xSGAsyncStatus(st_XSAVEGAME_DATA* xsgdata, S32 block, en_XSG_WHYFAIL* whyFail, + char* errmsg); +S32 xSG_cb_leader_svinfo(void*, st_XSAVEGAME_DATA*, S32* cur_space, S32* max_fullgame); +S32 xSG_cb_leader_svproc(void* cltdata, st_XSAVEGAME_DATA* original_xsgdata, + st_XSAVEGAME_WRITECONTEXT* wctxt); +S32 xSG_cb_leader_load(void*, st_XSAVEGAME_DATA* original_xsgdata, + st_XSAVEGAME_READCONTEXT* rctxt, U32, S32); +S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, char* data, + S32 elesiz, S32 n); +S32 xSGWriteStrLen(const char* str); +S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, char* data, + S32 n); +S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, S32* data, + S32 n); +S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, U32* data, + S32 n); +S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, F32* data, + S32 n); +S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, char* buff, + S32 elesiz, S32 n); +S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, char* buff, S32 n); +S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, S32* buff, + S32 n); +S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, U32* buff, + S32 n); +S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, F32* buff, + S32 n); +S32 xSG_grab_leaders(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_chdir_gamedir(st_XSAVEGAME_DATA* xsgdata); +char* xSG_cm_slotname(st_XSAVEGAME_DATA* xsgdata, S32 gidx); +void xSG_areaComposeLabel(char* label, int, char*, int); +S32 xSG_sv_flipinfo(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_sv_prepdest(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_sv_flipproc(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_sv_bldchksum(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_smem_blkopen(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_smem_blkclose(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_smem_cltopen(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_CLIENT* clt); +S32 xSG_smem_cltclose(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_CLIENT* clt); +S32 xSG_sv_commit(st_XSAVEGAME_DATA* xsgdata); +void xSG_cb_ISGChange(void*, en_CHGCODE what); +S32 xSG_ld_prepload(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_ld_readgame(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_ld_readhead(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_ld_validate(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_ld_findcltblk(st_XSAVEGAME_DATA* xsgdata); +S32 xSG_ld_flipload(st_XSAVEGAME_DATA* xsgdata); +XSGAutoData* xSGAutoSave_GetCache(); +void xSGAutoSave_Startup(); +void ASG_ISG_changed(void*, en_CHGCODE what); + +#endif diff --git a/src/SB/Core/x/xserializer.cpp b/src/SB/Core/x/xserializer.cpp new file mode 100644 index 0000000..f9fd640 --- /dev/null +++ b/src/SB/Core/x/xserializer.cpp @@ -0,0 +1,3 @@ +#include "xserializer.h" + +#include diff --git a/src/SB/Core/x/xserializer.h b/src/SB/Core/x/xserializer.h new file mode 100644 index 0000000..bf1d598 --- /dev/null +++ b/src/SB/Core/x/xserializer.h @@ -0,0 +1,51 @@ +#ifndef XSERIALIZER_H +#define XSERIALIZER_H + +#include +#include "xsavegame.h" + +struct st_SERIAL_CLIENTINFO +{ + U32 idtag; + S32* membuf; + S32 trueoff; + S32 actsize; +}; + +struct xSerial +{ + U32 idtag; + S32 baseoff; + st_SERIAL_CLIENTINFO* ctxtdata; + S32 warned; + S32 curele; + S32 bitidx; + S32 bittally; + + xSerial(); + ~xSerial(); + + void setClient(U32 idtag); + + S32 Write_b1(S32 bits); + S32 Write_b7(U32 bits); + S32 Write(U8 data); + S32 Write(S16 data); + S32 Write(S32 data); + S32 Write(U32 data); + S32 Write(F32 data); + S32 Read_b1(S32* bits); + S32 Read_b7(U32* bits); + S32 Read(U8* buf); + S32 Read(S16* buf); + S32 Read(S32* buf); + S32 Read(U32* buf); + S32 Read(F32* buf); + void operator delete(void*); +}; + +void xSerialTraverse(S32 (*func)(U32 clientID, xSerial* xser)); +void xSerialWipeMainBuffer(); +S32 xSerial_svgame_register(st_XSAVEGAME_DATA* sgctxt, en_SAVEGAME_MODE mode); + +#endif diff --git a/src/SB/Core/x/xstransvc.cpp b/src/SB/Core/x/xstransvc.cpp new file mode 100644 index 0000000..199917f --- /dev/null +++ b/src/SB/Core/x/xstransvc.cpp @@ -0,0 +1,587 @@ +#include "xstransvc.h" + +#include +#include +#include +#include "xString.h" +#include "xutil.h" +#include "xTRC.h" +#include "iFile.h" + +static st_STRAN_DATA g_xstdata = {}; +static S32 g_straninit; +static st_PACKER_READ_FUNCS* g_pkrf; +static st_PACKER_ASSETTYPE* g_typeHandlers; + +static st_STRAN_SCENE* XST_lock_next(); +static void XST_unlock_all(); +static S32 XST_cnt_locked(); +static S32 XST_PreLoadScene(st_STRAN_SCENE* sdata, const char* path); +static char* XST_translate_sid(U32 sid, char* extension); +static char* XST_translate_sid_path(U32 sid, char* extension); +static st_STRAN_SCENE* XST_find_bySID(U32 sid, S32 findTheHOP); +static void XST_reset_raw(); +static void XST_unlock(st_STRAN_SCENE* sdata); +static void XST_unlock_all(); +static st_STRAN_SCENE* XST_get_rawinst(S32 index); +static S32 XST_cnt_locked(); +static st_STRAN_SCENE* XST_nth_locked(S32 index); + +S32 xSTStartup(st_PACKER_ASSETTYPE* handlers) +{ + if (g_straninit++ == 0) + { + g_typeHandlers = handlers; + XST_reset_raw(); + PKRStartup(); + g_pkrf = PKRGetReadFuncs(1); + } + return g_straninit; +} + +S32 xSTShutdown() +{ + g_straninit--; + if (g_straninit == 0) + { + g_typeHandlers = 0; + XST_unlock_all(); + PKRShutdown(); + } + return g_straninit; +} + +// This doesn't seem exactly how HI would have written this, but it OKs +// TODO: Try to clean this up? +S32 xSTPreLoadScene(U32 sid, void* userdata, S32 flg_hiphop) +{ + S32 result; + S32 i = 0; + st_STRAN_SCENE* sdata; + char* path; + if ((flg_hiphop & 3) == 2) + { + sdata = XST_lock_next(); + sdata->scnid = sid; + sdata->userdata = userdata; + sdata->isHOP = 1; + + path = XST_translate_sid_path(sid, ".HOP"); + if (path != NULL) + { + strcpy(sdata->fnam, path); + i = XST_PreLoadScene(sdata, path); + } + if (i == 0) + { + path = XST_translate_sid(sid, ".HOP"); + if (path != NULL) + { + strcpy(sdata->fnam, path); + i = XST_PreLoadScene(sdata, path); + } + } + if (i == 0) + { + XST_unlock(sdata); + result = 0; + } + else + { + result = i; + } + } + else + { + do + { + sdata = XST_lock_next(); + sdata->scnid = sid; + sdata->userdata = userdata; + sdata->isHOP = 0; + + if (sid != 0x424f4f54 && sid != 0x464f4e54) + { + path = XST_translate_sid_path(sid, ".HIP"); + if (path != NULL) + { + strcpy(sdata->fnam, path); + i = XST_PreLoadScene(sdata, path); + } + } + if (i == 0) + { + path = XST_translate_sid(sid, ".HIP"); + if (path != NULL) + { + strcpy(sdata->fnam, path); + i = XST_PreLoadScene(sdata, path); + } + } + if (i == 0) + { + XST_unlock(sdata); + result = 0; + } + else + { + result = i; + } + } while (i == 0); + } + return result; +} + +S32 xSTQueueSceneAssets(U32 sid, S32 flg_hiphop) +{ + S32 result = 1; + st_STRAN_SCENE* sdata = XST_find_bySID(sid, (flg_hiphop & 3) == 2 ? 1 : 0); + if (sdata == NULL) + { + result = 0; + } + else + { + if (sdata->spkg != NULL) + { + g_pkrf->LoadLayer(sdata->spkg, PKR_LTYPE_ALL); + } + } + return result; +} + +void xSTUnLoadScene(U32 sid, S32 flg_hiphop) +{ + st_STRAN_SCENE* sdata; + if (sid == 0) + { + S32 cnt = XST_cnt_locked(); + + for (int i = 0; i < cnt; i++) + { + sdata = XST_nth_locked(i); + if (sdata->spkg != NULL) + { + g_pkrf->Done(sdata->spkg); + } + sdata->spkg = NULL; + } + XST_unlock_all(); + } + else + { + sdata = XST_find_bySID(sid, (flg_hiphop & 3) == 2 ? 1 : 0); + if (sdata != NULL) + { + if (sdata->spkg != NULL) + { + g_pkrf->Done(sdata->spkg); + } + sdata->spkg = NULL; + } + XST_unlock(sdata); + } +} + +F32 xSTLoadStep(U32) +{ + F32 pct = PKRLoadStep(0) != 0 ? 0.0f : 1.00001f; + + iTRCDisk::CheckDVDAndResetState(); + iFileAsyncService(); + return pct; +} + +void xSTDisconnect(U32 sid, S32 flg_hiphop) +{ + st_STRAN_SCENE* sdata = XST_find_bySID(sid, (flg_hiphop & 3) == 2 ? 1 : 0); + if (sdata != NULL) + { + g_pkrf->PkgDisconnect(sdata->spkg); + } +} + +S32 xSTSwitchScene(U32 sid, void* userdata, S32 (*progmon)(void*, F32)) +{ + st_STRAN_SCENE* sdata; + S32 rc = 0; + + for (S32 i = 1; i >= 0; i--) + { + sdata = XST_find_bySID(sid, i); + if (sdata != NULL) + { + if (progmon != NULL) + { + progmon(userdata, 0.0f); + } + rc = g_pkrf->SetActive(sdata->spkg, PKR_LTYPE_ALL); + if (progmon != NULL) + { + progmon(userdata, 1.0f); + } + } + } + + return rc; +} + +char* xSTAssetName(U32 aid) +{ + char* aname = NULL; + + S32 cnt = XST_cnt_locked(); + for (int i = 0; i < cnt; i++) + { + st_STRAN_SCENE* sdata = XST_nth_locked(i); + if (sdata->spkg != NULL) + { + aname = g_pkrf->AssetName(sdata->spkg, aid); + if (aname != NULL) + { + break; + } + } + } + + return aname; +} + +char* xSTAssetName(void* raw_HIP_asset) +{ + char* aname = NULL; + + S32 cnt = XST_cnt_locked(); + for (int i = 0; i < cnt; i++) + { + st_STRAN_SCENE* sdata = XST_nth_locked(i); + aname = g_pkrf->AssetName(sdata->spkg, PKRAssetIDFromInst(raw_HIP_asset)); + if (aname != NULL) + { + break; + } + } + + return aname; +} + +void* xSTFindAsset(U32 aid, U32* size) +{ + void* memloc = NULL; + if (aid == 0) + { + return memloc; + } + + S32 ready; + S32 scncount = XST_cnt_locked(); + for (S32 i = 0; i < scncount; i++) + { + st_STRAN_SCENE* sdata = XST_nth_locked(i); + if (g_pkrf->PkgHasAsset(sdata->spkg, aid)) + { + memloc = g_pkrf->LoadAsset(sdata->spkg, aid, NULL, NULL); + if (!g_pkrf->IsAssetReady(sdata->spkg, aid)) + { + memloc = NULL; + if (size != NULL) + { + *size = 0; + } + } + else + { + if (size != NULL) + { + *size = g_pkrf->GetAssetSize(sdata->spkg, aid); + } + } + break; + } + } + return memloc; +} + +S32 xSTAssetCountByType(U32 type) +{ + S32 sum = 0; + S32 cnt = XST_cnt_locked(); + for (S32 i = 0; i < cnt; i++) + { + st_STRAN_SCENE* sdata = XST_nth_locked(i); + sum += g_pkrf->AssetCount(sdata->spkg, type); + } + return sum; +} + +void* xSTFindAssetByType(U32 type, S32 idx, U32* size) +{ + void* memptr = NULL; + S32 i; + S32 sum = 0; + S32 cnt = XST_cnt_locked(); + for (i = 0; i < cnt; i++) + { + st_STRAN_SCENE* sdata = XST_nth_locked(i); + S32 scncnt = g_pkrf->AssetCount(sdata->spkg, type); + if (idx >= sum && idx < sum + scncnt) + { + memptr = g_pkrf->AssetByType(sdata->spkg, type, idx - sum, size); + break; + } + + sum += scncnt; + } + return memptr; +} + +S32 xSTGetAssetInfo(U32 aid, st_PKR_ASSET_TOCINFO* tocainfo) +{ + S32 rc = 0; + S32 scncnt = XST_cnt_locked(); + for (S32 i = 0; i < scncnt; i++) + { + st_STRAN_SCENE* sdata = XST_nth_locked(i); + if (g_pkrf->PkgHasAsset(sdata->spkg, aid) != NULL) + { + g_pkrf->GetBaseSector(sdata->spkg); + if (g_pkrf->GetAssetInfo(sdata->spkg, aid, tocainfo)) + { + rc = 1; + break; + } + } + } + return rc; +} + +// Equivalent: scheduling is off with the copy of tocinfo to ainfo +S32 xSTGetAssetInfoByType(U32 type, S32 idx, st_PKR_ASSET_TOCINFO* ainfo) +{ + S32 rc = 0; + S32 sum = 0; + st_PKR_ASSET_TOCINFO tocinfo = { 0, NULL, 0, 0, 0, NULL }; + memset(ainfo, 0, sizeof(st_PKR_ASSET_TOCINFO)); + + S32 found = XST_cnt_locked(); + for (S32 i = 0; i < found; i++) + { + st_STRAN_SCENE* sdata = XST_nth_locked(i); + S32 cnt = g_pkrf->AssetCount(sdata->spkg, type); + if (idx >= sum && idx < sum + cnt) + { + g_pkrf->GetBaseSector(sdata->spkg); + if (g_pkrf->GetAssetInfoByType(sdata->spkg, type, idx - sum, &tocinfo) != 0) + { + ainfo->aid = tocinfo.aid; + ainfo->sector = tocinfo.sector; + ainfo->plus_offset = tocinfo.plus_offset; + ainfo->size = tocinfo.size; + ainfo->mempos = tocinfo.mempos; + rc = 1; + break; + } + } + sum += cnt; + } + + return rc; +} + +S32 xSTGetAssetInfoInHxP(U32 aid, st_PKR_ASSET_TOCINFO* ainfo, U32 j) +{ + S32 rc = 0; + S32 cnt = XST_cnt_locked(); + for (S32 i = 0; i < cnt; i++) + { + st_STRAN_SCENE* sdata = XST_nth_locked(i); + if (j == xStrHash(sdata->fnam) && g_pkrf->PkgHasAsset(sdata->spkg, aid)) + { + g_pkrf->GetBaseSector(sdata->spkg); + if (g_pkrf->GetAssetInfo(sdata->spkg, aid, ainfo)) + { + rc = 1; + break; + } + } + } + return rc; +} + +char* xST_xAssetID_HIPFullPath(U32 aid) +{ + return xST_xAssetID_HIPFullPath(aid, 0); +} + +char* xST_xAssetID_HIPFullPath(U32 aid, U32* sceneID) +{ + char* id = NULL; + S32 cnt = XST_cnt_locked(); + for (int i = 0; i < cnt; i++) + { + st_STRAN_SCENE* sdata = XST_nth_locked(i); + if (g_pkrf->PkgHasAsset(sdata->spkg, aid)) + { + id = sdata->fnam; + if (sceneID != NULL) + { + *sceneID = sdata->scnid; + } + break; + } + } + + return id; +} + +// register crap +static S32 XST_PreLoadScene(st_STRAN_SCENE* sdata, const char* name) +{ + S32 buf = 0; + st_PACKER_READ_DATA* spkg = + g_pkrf->Init(sdata->userdata, (char*)name, 0x2e, &buf, g_typeHandlers); + sdata->spkg = spkg; + if (sdata->spkg != NULL) + { + return buf; + } + return NULL; +} + +static char* XST_translate_sid(U32 sid, char* extension) +{ + static char fname[0x40] = {}; + sprintf(fname, "%s%s", xUtil_idtag2string(sid, 0), extension); + return fname; +} + +static char* XST_translate_sid_path(U32 sid, char* extension) +{ + // NOTE: This buffer extends for 0x44 bytes in the rom + // However, I think that's most likely padding for the jumptable that occurs afterwards + static char fname[0x40] = {}; + char pathSeparator[2] = "/"; + sprintf(fname, "%c%c%s%s%s", *xUtil_idtag2string(sid, 0), *(xUtil_idtag2string(sid, 0) + 1), + pathSeparator, xUtil_idtag2string(sid, 0), extension); + return fname; +} + +static void XST_reset_raw() +{ + memset(&g_xstdata, 0, sizeof(st_STRAN_DATA)); +} + +static st_STRAN_SCENE* XST_lock_next() +{ + st_STRAN_SCENE* sdata = NULL; + S32 uselock = -1; + for (S32 i = 0; i < 16; i++) + { + if (!(g_xstdata.loadlock & 1 << i)) + { + g_xstdata.loadlock |= 1 << i; + sdata = &g_xstdata.hipscn[i]; + memset(sdata, 0, sizeof(st_STRAN_SCENE)); + uselock = i; + break; + } + } + + if (sdata != NULL) + { + sdata->lockid = uselock; + } + + return sdata; +} + +static void XST_unlock(st_STRAN_SCENE* sdata) +{ + if (sdata != NULL) + { + if (g_xstdata.loadlock & 1 << sdata->lockid) + { + // Can't figure out how to get the andc instruction instead of two instructions + // Seems to only generate andc if I remove the memset call. + // NOTE (Square): pulling 1 << sdata->lockid into a temp variable works but + // causes regswaps. + g_xstdata.loadlock &= ~(1 << sdata->lockid); + memset(sdata, 0, sizeof(st_STRAN_SCENE)); + } + } +} + +static void XST_unlock_all() +{ + if (g_xstdata.loadlock) + { + for (S32 i = 0; i < 16; i++) + { + if (g_xstdata.loadlock & 1 << i) + { + XST_unlock(XST_get_rawinst(i)); + } + } + } +} + +static st_STRAN_SCENE* XST_get_rawinst(S32 index) +{ + return &g_xstdata.hipscn[index]; +} + +static S32 XST_cnt_locked() +{ + S32 sum = 0; + for (int i = 0; i < 16; i++) + { + if (g_xstdata.loadlock & 1 << i) + { + sum++; + } + } + return sum; +} + +static st_STRAN_SCENE* XST_nth_locked(S32 index) +{ + st_STRAN_SCENE* sdata = NULL; + S32 cnt = 0; + for (S32 i = 0; i < 16; i++) + { + if (g_xstdata.loadlock & 1 << i) + { + if (cnt == index) + { + sdata = &g_xstdata.hipscn[i]; + break; + } + cnt += 1; + } + } + + return sdata; +} + +static st_STRAN_SCENE* XST_find_bySID(U32 sid, S32 findTheHOP) +{ + st_STRAN_SCENE* da_sdata = NULL; + + for (S32 i = 0; i < 16; i++) + { + st_STRAN_SCENE* sc = &g_xstdata.hipscn[i]; + if (g_xstdata.loadlock & 1 << i && sc->scnid == sid && (findTheHOP || !sc->isHOP)) + { + if (!findTheHOP || sc->isHOP) + { + da_sdata = sc; + break; + } + } + } + return da_sdata; +} + +WEAK void iFileAsyncService() +{ +} diff --git a/src/SB/Core/x/xstransvc.h b/src/SB/Core/x/xstransvc.h new file mode 100644 index 0000000..889a9e8 --- /dev/null +++ b/src/SB/Core/x/xstransvc.h @@ -0,0 +1,41 @@ +#ifndef XSTRANSVC_H +#define XSTRANSVC_H + +#include "xpkrsvc.h" + +struct st_STRAN_SCENE +{ + U32 scnid; + S32 lockid; + st_PACKER_READ_DATA* spkg; + S32 isHOP; + void* userdata; + char fnam[256]; +}; + +struct st_STRAN_DATA +{ + st_STRAN_SCENE hipscn[16]; + U32 loadlock; +}; + +S32 xSTStartup(st_PACKER_ASSETTYPE* handlers); +S32 xSTPreLoadScene(U32 sid, void* userdata, S32 flg_hiphop); +S32 xSTQueueSceneAssets(U32 sid, S32 flg_hiphop); +void xSTUnLoadScene(U32 sid, S32 flg_hiphop); +F32 xSTLoadStep(U32); +void xSTDisconnect(U32 sid, S32 flg_hiphop); +S32 xSTSwitchScene(U32 sid, void* userdata, S32 (*progmon)(void*, F32)); +void* xSTFindAsset(U32 aid, U32* size); +S32 xSTAssetCountByType(U32 type); +void* xSTFindAssetByType(U32 type, S32 idx, U32* size); +char* xSTAssetName(U32 aid); +char* xSTAssetName(void* raw_HIP_asset); +S32 xSTGetAssetInfo(U32 aid, st_PKR_ASSET_TOCINFO* tocainfo); +S32 xSTGetAssetInfoByType(U32 type, S32 idx, st_PKR_ASSET_TOCINFO* ainfo); +char* xST_xAssetID_HIPFullPath(U32 aid); +S32 PKRShutdown(); +char* xST_xAssetID_HIPFullPath(U32 aid, U32* sceneID); +S32 xSTShutdown(); + +#endif diff --git a/src/SB/Core/x/xutil.cpp b/src/SB/Core/x/xutil.cpp new file mode 100644 index 0000000..9a518ff --- /dev/null +++ b/src/SB/Core/x/xutil.cpp @@ -0,0 +1,181 @@ +#include "xutil.h" + +#include "xMath.h" + +#include + +static volatile S32 g_xutilinit; // volatile so xUtilShutdown matches +static S32 g_crc_needinit = 1; +static U32 g_crc32_table[256] = {}; + +S32 xUtilStartup() +{ + if (!g_xutilinit++) + { + xUtil_crc_init(); + } + + return g_xutilinit; +} + +S32 xUtilShutdown() +{ + g_xutilinit--; + return g_xutilinit; +} + +char* xUtil_idtag2string(U32 srctag, S32 bufidx) +{ + U32 tag = srctag; + char* strptr; + char* uc = (char*)&tag; + S32 l; + char t; + static char buf[6][10] = {}; + + if (bufidx < 0 || bufidx >= 7) + { + strptr = buf[0]; + } + else + { + strptr = buf[bufidx]; + } + + // convert tag to big endian + + l = 1; + + if ((S32)((char*)&l)[3] != 0) + { + t = uc[0]; + uc[0] = uc[3]; + uc[3] = t; + + t = uc[1]; + uc[1] = uc[2]; + uc[2] = t; + } + + switch (bufidx) + { + case 4: + case 5: + strptr[0] = isprint(uc[0]) ? uc[0] : '?'; + strptr[1] = isprint(uc[1]) ? uc[1] : '?'; + strptr[2] = isprint(uc[2]) ? uc[2] : '?'; + strptr[3] = isprint(uc[3]) ? uc[3] : '?'; + break; + case 6: + default: + strptr[0] = isprint(uc[3]) ? uc[3] : '?'; + strptr[1] = isprint(uc[2]) ? uc[2] : '?'; + strptr[2] = isprint(uc[1]) ? uc[1] : '?'; + strptr[3] = isprint(uc[0]) ? uc[0] : '?'; + break; + } + + strptr[4] = '\0'; + + if (bufidx == 6) + { + strptr[4] = '/'; + strptr[5] = isprint(uc[0]) ? uc[0] : '?'; + strptr[6] = isprint(uc[1]) ? uc[1] : '?'; + strptr[7] = isprint(uc[2]) ? uc[2] : '?'; + strptr[8] = isprint(uc[3]) ? uc[3] : '?'; + strptr[9] = '\0'; + } + + return strptr; +} + +U32 xUtil_crc_init() +{ + S32 i, j; + U32 crc_accum; + + if (g_crc_needinit) + { + for (i = 0; i < 256; i++) + { + crc_accum = (U32)i << 24; + + for (j = 0; j < 8; j++) + { + if (crc_accum & (1 << 31)) + { + crc_accum = (crc_accum << 1) ^ 0x04C11DB7; + } + else + { + crc_accum = (crc_accum << 1); + } + } + + g_crc32_table[i] = crc_accum; + } + + g_crc_needinit = 0; + } + + return 0xFFFFFFFF; +} + +U32 xUtil_crc_update(U32 crc_accum, char* data, S32 datasize) +{ + S32 i, j; + + if (g_crc_needinit) + { + xUtil_crc_init(); + } + + for (i = 0; i < datasize; i++) + { + j = ((crc_accum >> 24) ^ *data++) & 0xff; + crc_accum = (crc_accum << 8) ^ g_crc32_table[j]; + } + + return crc_accum; +} + +S32 xUtil_yesno(F32 wt_yes) +{ + if (0.0f == wt_yes) + { + return 0; + } + + if (1.0f == wt_yes) + { + return 1; + } + + return (xurand() <= wt_yes); +} + +void xUtil_wtadjust(F32* wts, S32 cnt, F32 arbref) +{ + const volatile F32 ZERO = 0.0f; + + S32 i; + F32 sum = 0.0f, fac; + + for (i = 0; i < cnt; i++) + { + if (wts[i] < ZERO) + { + wts[i] = -wts[i]; + } + + sum += wts[i]; + } + + fac = arbref / sum; + + for (i = 0; i < cnt; i++) + { + wts[i] *= fac; + } +} diff --git a/src/SB/Core/x/xutil.h b/src/SB/Core/x/xutil.h new file mode 100644 index 0000000..2b63111 --- /dev/null +++ b/src/SB/Core/x/xutil.h @@ -0,0 +1,17 @@ +#ifndef XUTIL_H +#define XUTIL_H + +#include + +S32 xUtilStartup(); +S32 xUtilShutdown(); +char* xUtil_idtag2string(U32 srctag, S32 bufidx); +U32 xUtil_crc_init(); +U32 xUtil_crc_update(U32 crc_accum, char* data, S32 datasize); +S32 xUtil_yesno(F32 wt_yes); +void xUtil_wtadjust(F32* wts, S32 cnt, F32 arbref); + +template +T* xUtil_select(T** arg0, S32 arg1, const F32* arg3); + +#endif diff --git a/src/SB/Game/zBase.h b/src/SB/Game/zBase.h new file mode 100644 index 0000000..64f9ab0 --- /dev/null +++ b/src/SB/Game/zBase.h @@ -0,0 +1,81 @@ +#ifndef ZBASE_H +#define ZBASE_H + +enum en_ZBASETYPE +{ + eBaseTypeUnknown, + eBaseTypeTrigger, + eBaseTypeVillain, + eBaseTypePlayer, + eBaseTypePickup, + eBaseTypeEnv, + eBaseTypePlatform, + eBaseTypeCamera, + eBaseTypeDoor, + eBaseTypeSavePoint, + eBaseTypeItem, + eBaseTypeStatic, + eBaseTypeDynamic, + eBaseTypeMovePoint, + eBaseTypeTimer, + eBaseTypeBubble, + eBaseTypePortal, + eBaseTypeGroup, + eBaseTypePendulum, + eBaseTypeSFX, + eBaseTypeFFX, + eBaseTypeVFX, + eBaseTypeCounter, + eBaseTypeHangable, + eBaseTypeButton, + eBaseTypeProjectile, + eBaseTypeSurface, + eBaseTypeDestructObj, + eBaseTypeGust, + eBaseTypeVolume, + eBaseTypeDispatcher, + eBaseTypeCond, + eBaseTypeUI, + eBaseTypeUIFont, + eBaseTypeProjectileType, + eBaseTypeLobMaster, + eBaseTypeFog, + eBaseTypeLight, + eBaseTypeParticleEmitter, + eBaseTypeParticleSystem, + eBaseTypeCutsceneMgr, + eBaseTypeEGenerator, + eBaseTypeScript, + eBaseTypeNPC, + eBaseTypeHud, + eBaseTypeNPCProps, + eBaseTypeParticleEmitterProps, + eBaseTypeBoulder, + eBaseTypeCruiseBubble, + eBaseTypeTeleportBox, + eBaseTypeBusStop, + eBaseTypeTextBox, + eBaseTypeTalkBox, + eBaseTypeTaskBox, + eBaseTypeBoulderGenerator, + eBaseTypeNPCSettings, + eBaseTypeDiscoFloor, + eBaseTypeTaxi, + eBaseTypeHUD_model, + eBaseTypeHUD_font_meter, + eBaseTypeHUD_unit_meter, + eBaseTypeBungeeHook, + eBaseTypeCameraFly, + eBaseTypeTrackPhysics, + eBaseTypeZipLine, + eBaseTypeArena, + eBaseTypeDuplicator, + eBaseTypeLaserBeam, + eBaseTypeTurret, + eBaseTypeCameraTweak, + eBaseTypeSlideProps, + eBaseTypeHUD_text, + eBaseTypeCount +}; + +#endif \ No newline at end of file diff --git a/src/SB/Game/zNMECommon.h b/src/SB/Game/zNMECommon.h new file mode 100644 index 0000000..e69de29 diff --git a/src/SB/Game/zParticleSystemWaterfall.cpp b/src/SB/Game/zParticleSystemWaterfall.cpp index abcf743..48a43a2 100644 --- a/src/SB/Game/zParticleSystemWaterfall.cpp +++ b/src/SB/Game/zParticleSystemWaterfall.cpp @@ -1,109 +1,109 @@ -#include "zParticleSystemWaterfall.h" +// #include "zParticleSystemWaterfall.h" -void zParticleGeneratorWaterfallSplash::deactivate() -{ - zParticleGenerator* pGen; - pGen->deactivate(); - locator.deactivate(); -} +// void zParticleGeneratorWaterfallSplash::deactivate() +// { +// zParticleGenerator* pGen; +// pGen->deactivate(); +// locator.deactivate(); +// } -void zParticleGeneratorWaterfallSplash::activate() -{ - zParticleGenerator* pGen; - pGen->activate(); - locator.activate(*asset, attach_to); // Make const -} +// void zParticleGeneratorWaterfallSplash::activate() +// { +// zParticleGenerator* pGen; +// pGen->activate(); +// locator.activate(*asset, attach_to); // Make const +// } -void zParticleGeneratorWaterfallSplash::reset() -{ - zParticleGenerator::reset(); - emitted = 0; - locator.restart(); - locator.deactivate(); - if (&flags != 0) // This arg needs fixed - { - locator.activate(*asset, attach_to); - } -} +// void zParticleGeneratorWaterfallSplash::reset() +// { +// zParticleGenerator::reset(); +// emitted = 0; +// locator.restart(); +// locator.deactivate(); +// if (&flags != 0) // This arg needs fixed +// { +// locator.activate(*asset, attach_to); +// } +// } -S32 zParticleSystemWaterfallSplash::get_asset_size() const -{ - return 56; // Calls for 0x38 -} +// S32 zParticleSystemWaterfallSplash::get_asset_size() const +// { +// return 56; // Calls for 0x38 +// } -void zParticleSystemWaterfallSplash::scene_enter() -{ - batch_group.create(); -} +// void zParticleSystemWaterfallSplash::scene_enter() +// { +// batch_group.create(); +// } -void zParticleGeneratorWaterfallMist::deactivate() -{ - zParticleGenerator* pGen; - pGen->deactivate(); - locator.deactivate(); -} +// void zParticleGeneratorWaterfallMist::deactivate() +// { +// zParticleGenerator* pGen; +// pGen->deactivate(); +// locator.deactivate(); +// } -void zParticleGeneratorWaterfallMist::activate() -{ - zParticleGenerator* pGen; - pGen->activate(); - locator.activate(*asset, attach_to); // Make const -} +// void zParticleGeneratorWaterfallMist::activate() +// { +// zParticleGenerator* pGen; +// pGen->activate(); +// locator.activate(*asset, attach_to); // Make const +// } -void zParticleGeneratorWaterfallMist::reset() -{ - zParticleGenerator::reset(); - emitted = 0; - locator.restart(); - locator.deactivate(); - if (&flags != 0) // This arg needs fixed - { - locator.activate(*asset, attach_to); - } -} +// void zParticleGeneratorWaterfallMist::reset() +// { +// zParticleGenerator::reset(); +// emitted = 0; +// locator.restart(); +// locator.deactivate(); +// if (&flags != 0) // This arg needs fixed +// { +// locator.activate(*asset, attach_to); +// } +// } -S32 zParticleSystemWaterfallMist::get_asset_size() const -{ - return 52; // Calls for 0x34 -} +// S32 zParticleSystemWaterfallMist::get_asset_size() const +// { +// return 52; // Calls for 0x34 +// } -void zParticleSystemWaterfallMist::scene_enter() -{ - batch_group.create(); -} +// void zParticleSystemWaterfallMist::scene_enter() +// { +// batch_group.create(); +// } -void zParticleGeneratorWaterfall::deactivate() -{ - zParticleGenerator* pGen; - pGen->deactivate(); - locator.deactivate(); -} +// void zParticleGeneratorWaterfall::deactivate() +// { +// zParticleGenerator* pGen; +// pGen->deactivate(); +// locator.deactivate(); +// } -void zParticleGeneratorWaterfall::activate() -{ - zParticleGenerator* pGen; - pGen->activate(); - locator.activate(*asset, attach_to); // Make const -} +// void zParticleGeneratorWaterfall::activate() +// { +// zParticleGenerator* pGen; +// pGen->activate(); +// locator.activate(*asset, attach_to); // Make const +// } -void zParticleGeneratorWaterfall::reset() // 87% -{ - zParticleGenerator::reset(); - emitted = 0; - locator.restart(); - locator.deactivate(); - if (&flags != 0) // This arg needs fixed - { - locator.activate(*asset, attach_to); - } -} +// void zParticleGeneratorWaterfall::reset() // 87% +// { +// zParticleGenerator::reset(); +// emitted = 0; +// locator.restart(); +// locator.deactivate(); +// if (&flags != 0) // This arg needs fixed +// { +// locator.activate(*asset, attach_to); +// } +// } -S32 zParticleSystemWaterfall::get_asset_size() const -{ - return 76; // Calls for 0x4c -} +// S32 zParticleSystemWaterfall::get_asset_size() const +// { +// return 76; // Calls for 0x4c +// } -void zParticleSystemWaterfall::scene_enter() -{ - batch_group.create(); -} +// void zParticleSystemWaterfall::scene_enter() +// { +// batch_group.create(); +// } diff --git a/src/SB/Game/zParticleSystemWaterfall.h b/src/SB/Game/zParticleSystemWaterfall.h index dbb704d..9dcc2d1 100644 --- a/src/SB/Game/zParticleSystemWaterfall.h +++ b/src/SB/Game/zParticleSystemWaterfall.h @@ -1,274 +1,274 @@ -#ifndef ZPARTICLESYSTEMWATERFALL_H -#define ZPARTICLESYSTEMWATERFALL_H - -#include "xNME.h" - -struct _class_0 -{ - F32 yaw; - F32 pitch; - F32 roll; -}; - -struct attach_fixed_data -{ -}; - -struct attach_entity_data -{ - U32 entity; - U8 bone; - U8 pad1; - U8 pad2; - U8 pad3; -}; - -struct attach_entity_tag_data -{ - U32 entity; - xVec3 tag; -}; - -struct attach_data -{ - union - { - attach_fixed_data fixed; - attach_entity_data entity; - attach_entity_tag_data entity_tag; - }; -}; - -struct motion_none_data -{ -}; - -struct motion_spiral_data -{ - U8 flags; - U8 points; - U8 pad1; - U8 pad2; - F32 radius_inner; - F32 radius_outer; - F32 duration; - F32 frequency; -}; - -struct motion_data -{ - union - { - motion_none_data none; - motion_spiral_data spiral; - }; -}; - -struct volume_point_data -{ -}; - -struct volume_sphere_data -{ - F32 radius; -}; - -struct volume_circle_data -{ - F32 radius; - F32 arc_length; -}; - -struct volume_line_data -{ - U8 flags; - U8 pad1; - U8 pad2; - U8 pad3; - F32 radius; - F32 length; -}; - -struct volume_model_data -{ - U8 flags; - U8 exclude; - U8 pad1; - U8 pad2; - F32 expand; -}; - -struct volume_data -{ - union - { - volume_point_data point; - volume_sphere_data sphere; - volume_circle_data circle; - volume_line_data line; - volume_model_data model; - }; -}; - -struct zParticleAsset : xDynAsset -{ - U8 flags; - U8 attach_flags; - U8 motion_flags; - U8 volume_flags; - F32 rate; - U32 texture; - U8 attach_type; - U8 motion_type; - U8 volume_type; - U8 system_type; - xVec3 location; - _class_0 axis; - attach_data attach; - motion_data motion; - volume_data volume; -}; - -struct zParticleGenerator : xBase -{ - zParticleAsset* asset; - S32 flags; - - void activate(); - void deactivate(); - void reset(); - void perturb_dir(xVec3& dir, F32 angle); - xEnt* get_attach_entity(zParticleAsset& asset); - void event_handler(xBase* to, U32 event); -}; - -struct relative_ordering -{ - S32 other; - U8 before_other; -}; - -struct zParticleSystem -{ - S32 type; - S32 need; - zParticleGenerator** generators; - S32 generators_size; - S32 generators_active; - - void destroy_generator(); - void scene_exit(); - void setup(); - void reset(); - void pre_render(); - void render(); - relative_ordering* get_ordering(S32& size); - void scene_enter(); - void update(); -}; - -struct xParticleBatchGroup -{ - U8* elements; - S32 elements_size; - - void create(); -}; - -struct zParticleSystemWaterfall : zParticleSystem -{ - S32 unk; - xParticleBatchGroup batch_group; - - S32 get_asset_size() const; - void update(F32 dt); - void scene_enter(); - zParticleGenerator* create_generator(zParticleAsset& asset); -}; - -struct activity_data -{ -}; - -struct zParticleLocator -{ - activity_data* activity; - - void restart(); - void scene_enter(); - U8 activate(zParticleAsset& asset, xEnt* attach_to); - void deactivate(); -}; - -struct zParticleGeneratorWaterfall : zParticleGenerator -{ - S32 unk; - zParticleSystemWaterfall* system; - xEnt* attach_to; - F32 emitted; //0x24 - zParticleLocator locator; - S32 batch_id; - xVec3 vel_dir; - - void deactivate(); - void activate(); - void reset(); - void create(zParticleSystemWaterfall& system, zParticleAsset& asset); - void update(F32 dt); -}; - -struct zParticleSystemWaterfallMist : zParticleSystem -{ - S32 unk; - xParticleBatchGroup batch_group; - - S32 get_asset_size() const; - void update(F32 dt); - void scene_enter(); - zParticleGenerator* create_generator(zParticleAsset& asset); -}; - -struct zParticleGeneratorWaterfallMist : zParticleGenerator -{ - S32 unk; - zParticleSystemWaterfallMist* system; - xEnt* attach_to; - F32 emitted; - zParticleLocator locator; - S32 batch_id; - - void deactivate(); - void activate(); - void reset(); - void create(zParticleSystemWaterfallMist& system, zParticleAsset& asset); - void update(F32 dt); -}; - -struct zParticleSystemWaterfallSplash : zParticleSystem -{ - S32 unk; - xParticleBatchGroup batch_group; - - S32 get_asset_size() const; - void update(F32 dt); - void scene_enter(); - zParticleGenerator* create_generator(zParticleAsset& asset); -}; - -struct zParticleGeneratorWaterfallSplash : zParticleGenerator -{ - S32 unk; - zParticleSystemWaterfallSplash* system; - xEnt* attach_to; - F32 emitted; - zParticleLocator locator; - S32 batch_id; - - void deactivate(); - void activate(); - void reset(); - void create(zParticleSystemWaterfallSplash& system, zParticleAsset& asset); - void update(F32 dt); -}; - -#endif +// #ifndef ZPARTICLESYSTEMWATERFALL_H +// #define ZPARTICLESYSTEMWATERFALL_H + +// #include "xNME.h" + +// struct _class_0 +// { +// F32 yaw; +// F32 pitch; +// F32 roll; +// }; + +// struct attach_fixed_data +// { +// }; + +// struct attach_entity_data +// { +// U32 entity; +// U8 bone; +// U8 pad1; +// U8 pad2; +// U8 pad3; +// }; + +// struct attach_entity_tag_data +// { +// U32 entity; +// xVec3 tag; +// }; + +// struct attach_data +// { +// union +// { +// attach_fixed_data fixed; +// attach_entity_data entity; +// attach_entity_tag_data entity_tag; +// }; +// }; + +// struct motion_none_data +// { +// }; + +// struct motion_spiral_data +// { +// U8 flags; +// U8 points; +// U8 pad1; +// U8 pad2; +// F32 radius_inner; +// F32 radius_outer; +// F32 duration; +// F32 frequency; +// }; + +// struct motion_data +// { +// union +// { +// motion_none_data none; +// motion_spiral_data spiral; +// }; +// }; + +// struct volume_point_data +// { +// }; + +// struct volume_sphere_data +// { +// F32 radius; +// }; + +// struct volume_circle_data +// { +// F32 radius; +// F32 arc_length; +// }; + +// struct volume_line_data +// { +// U8 flags; +// U8 pad1; +// U8 pad2; +// U8 pad3; +// F32 radius; +// F32 length; +// }; + +// struct volume_model_data +// { +// U8 flags; +// U8 exclude; +// U8 pad1; +// U8 pad2; +// F32 expand; +// }; + +// struct volume_data +// { +// union +// { +// volume_point_data point; +// volume_sphere_data sphere; +// volume_circle_data circle; +// volume_line_data line; +// volume_model_data model; +// }; +// }; + +// struct zParticleAsset : xDynAsset +// { +// U8 flags; +// U8 attach_flags; +// U8 motion_flags; +// U8 volume_flags; +// F32 rate; +// U32 texture; +// U8 attach_type; +// U8 motion_type; +// U8 volume_type; +// U8 system_type; +// xVec3 location; +// _class_0 axis; +// attach_data attach; +// motion_data motion; +// volume_data volume; +// }; + +// struct zParticleGenerator : xBase +// { +// zParticleAsset* asset; +// S32 flags; + +// void activate(); +// void deactivate(); +// void reset(); +// void perturb_dir(xVec3& dir, F32 angle); +// xEnt* get_attach_entity(zParticleAsset& asset); +// void event_handler(xBase* to, U32 event); +// }; + +// struct relative_ordering +// { +// S32 other; +// U8 before_other; +// }; + +// struct zParticleSystem +// { +// S32 type; +// S32 need; +// zParticleGenerator** generators; +// S32 generators_size; +// S32 generators_active; + +// void destroy_generator(); +// void scene_exit(); +// void setup(); +// void reset(); +// void pre_render(); +// void render(); +// relative_ordering* get_ordering(S32& size); +// void scene_enter(); +// void update(); +// }; + +// struct xParticleBatchGroup +// { +// U8* elements; +// S32 elements_size; + +// void create(); +// }; + +// struct zParticleSystemWaterfall : zParticleSystem +// { +// S32 unk; +// xParticleBatchGroup batch_group; + +// S32 get_asset_size() const; +// void update(F32 dt); +// void scene_enter(); +// zParticleGenerator* create_generator(zParticleAsset& asset); +// }; + +// struct activity_data +// { +// }; + +// struct zParticleLocator +// { +// activity_data* activity; + +// void restart(); +// void scene_enter(); +// U8 activate(zParticleAsset& asset, xEnt* attach_to); +// void deactivate(); +// }; + +// struct zParticleGeneratorWaterfall : zParticleGenerator +// { +// S32 unk; +// zParticleSystemWaterfall* system; +// xEnt* attach_to; +// F32 emitted; //0x24 +// zParticleLocator locator; +// S32 batch_id; +// xVec3 vel_dir; + +// void deactivate(); +// void activate(); +// void reset(); +// void create(zParticleSystemWaterfall& system, zParticleAsset& asset); +// void update(F32 dt); +// }; + +// struct zParticleSystemWaterfallMist : zParticleSystem +// { +// S32 unk; +// xParticleBatchGroup batch_group; + +// S32 get_asset_size() const; +// void update(F32 dt); +// void scene_enter(); +// zParticleGenerator* create_generator(zParticleAsset& asset); +// }; + +// struct zParticleGeneratorWaterfallMist : zParticleGenerator +// { +// S32 unk; +// zParticleSystemWaterfallMist* system; +// xEnt* attach_to; +// F32 emitted; +// zParticleLocator locator; +// S32 batch_id; + +// void deactivate(); +// void activate(); +// void reset(); +// void create(zParticleSystemWaterfallMist& system, zParticleAsset& asset); +// void update(F32 dt); +// }; + +// struct zParticleSystemWaterfallSplash : zParticleSystem +// { +// S32 unk; +// xParticleBatchGroup batch_group; + +// S32 get_asset_size() const; +// void update(F32 dt); +// void scene_enter(); +// zParticleGenerator* create_generator(zParticleAsset& asset); +// }; + +// struct zParticleGeneratorWaterfallSplash : zParticleGenerator +// { +// S32 unk; +// zParticleSystemWaterfallSplash* system; +// xEnt* attach_to; +// F32 emitted; +// zParticleLocator locator; +// S32 batch_id; + +// void deactivate(); +// void activate(); +// void reset(); +// void create(zParticleSystemWaterfallSplash& system, zParticleAsset& asset); +// void update(F32 dt); +// }; + +// #endif diff --git a/src/SB/Game/zTalkBox.cpp b/src/SB/Game/zTalkBox.cpp index e69de29..644512e 100644 --- a/src/SB/Game/zTalkBox.cpp +++ b/src/SB/Game/zTalkBox.cpp @@ -0,0 +1,19 @@ +#include "zTalkBox.h" + +#include + +namespace +{ + struct SharedTalkboxState + { + void* padding[2]; // FIXME: variables not verified + ztalkbox* active; + }; + + SharedTalkboxState ztalkbox_shared; +} // namespace + +ztalkbox* ztalkbox::get_active() +{ + return ztalkbox_shared.active; +} diff --git a/src/SB/Game/zTalkBox.h b/src/SB/Game/zTalkBox.h new file mode 100644 index 0000000..fd9c020 --- /dev/null +++ b/src/SB/Game/zTalkBox.h @@ -0,0 +1,96 @@ +#ifndef ZTALKBOX_H +#define ZTALKBOX_H + +#include "zTextBox.h" +//#include "zNPCTypeCommon.h" + +#include "xScene.h" + +struct ztalkbox : xBase +{ + struct asset_type : xDynAsset + { + U32 dialog_box; + U32 prompt_box; + U32 quit_box; + bool trap : 8; + bool pause : 8; + bool allow_quit : 8; + bool trigger_pads : 8; + bool page : 8; + bool show : 8; + bool hide : 8; + bool audio_effect : 8; + U32 teleport; + struct + { + struct + { + bool time : 8; + bool prompt : 8; + bool sound : 8; + bool event : 8; + } type; + F32 delay; + S32 which_event; + } auto_wait; + struct + { + U32 skip; + U32 noskip; + U32 quit; + U32 noquit; + U32 yesno; + } prompt; + }; + + enum answer_enum + { + ANSWER_CONTINUE, + ANSWER_YES, + ANSWER_NO, + ANSWER_3, + }; + + struct callback + { + callback(); + virtual void on_signal(U32); + virtual void on_start(); + virtual void on_stop(); + virtual void on_answer(answer_enum); + }; + + struct + { + bool visible : 1; + } flag; + asset_type* asset; + ztextbox* dialog_box; + ztextbox* prompt_box; + ztextbox* quit_box; + struct + { + const char* skip; + const char* noskip; + const char* quit; + const char* noquit; + const char* yesno; + } prompt; + //zNPCCommon* npc; + + static void init(); + static void load(xBase& data, xDynAsset& asset, size_t); + static void update_all(xScene& s, F32 dt); + static void render_all(); + static void reset_all(); + static void permit(U32 add_flags, U32 remove_flags); + + static ztalkbox* get_active(); + //void start_talk(U32 textID, callback*, zNPCCommon*); // FIXME: params not verified + void stop_talk(); + + void set_text(U32 textID); +}; + +#endif diff --git a/src/SB/Game/zTaskBox.cpp b/src/SB/Game/zTaskBox.cpp index e69de29..1d55916 100644 --- a/src/SB/Game/zTaskBox.cpp +++ b/src/SB/Game/zTaskBox.cpp @@ -0,0 +1,232 @@ +#include "zTaskBox.h" +#include "zTalkBox.h" +#include "zBase.h" + +// CODE PORTED DIRECTLY FROM BFBB + +extern ztaskbox* shared; + +void ztaskbox::load(const asset_type& a) +{ + xBaseInit((xBase*)this, &(xBaseAsset)a); + this->baseType = eBaseTypeEnv; + // FIXME: can't force const to non-const? + // this->asset = &a; + + // FIXME: Define cb_dispatch + // this->eventFunc = cb_dispatch; + if (this->linkCount != 0) + { + this->link = (xLinkAsset*)(&a + 1); + } + bool enabled = a.enable; + this->state = STATE_INVALID; + if (!enabled) + { + this->flag.enabled = false; + this->current = NULL; + } + else + { + this->flag.enabled = true; + this->set_state(STATE_BEGIN); + this->current = this; + } + if (a.persistent) + { + this->baseFlags |= 2; + } +} + +void ztaskbox::read(xSerial& s) +{ + U8 data[4]; + data[0] = (U8)this->state; + s.Read(data); + set_state((ztaskbox::state_enum)data[0]); +} + +void ztaskbox::write(xSerial& s) +{ + s.Write((U8)this->state); +} + +// WIP. +// void ztaskbox::start_talk(zNMECommon* npc) +// { +// ztaskbox* curr = this->current; +// if (curr != NULL) +// { +// if (curr == this) +// { +// if (this->flag.enabled && this->state != STATE_INVALID) +// { +// //TODO!!! +// } +// } +// else +// { +// curr->set_callback(this->cb); +// this->current->start_talk(NULL); +// } +// } +// } + +// void ztaskbox::talk_callback::reset(ztaskbox& task) +// { +// this->task = &task; +// this->answer = ztalkbox::ANSWER_CONTINUE; +// } + +void ztaskbox::stop_talk() +{ + ztaskbox* curr = this->current; + + if (curr == NULL) + { + return; + } + + if (curr != this) + { + curr->stop_talk(); + return; + } + + if (!this->flag.enabled || this->state == STATE_INVALID) + { + return; + } + + if (shared != this) + { + return; + } + + //ztalkbox* other = (ztalkbox*)zSceneFindObject(this->asset->talk_box); + + // if (other) + // { + // other->stop_talk(); + // shared = NULL; + // } +} + +void ztaskbox::enable() +{ + if (!this->flag.enabled) + { + this->flag.enabled = true; + set_state(STATE_BEGIN); + } +} + +void ztaskbox::disable() +{ + if (this->flag.enabled) + { + stop_talk(); + this->flag.enabled = false; + set_state(STATE_INVALID); + } +} + +void ztaskbox::reset() +{ + disable(); + if (this->asset->enable) + { + enable(); + } +} + +void ztaskbox::initiate() +{ + if (this->state == STATE_BEGIN) + { + set_state(STATE_DESCRIPTION); + } +} + +void ztaskbox::succeed() +{ + if (state == STATE_BEGIN || state == STATE_DESCRIPTION || state == STATE_REMINDER) + { + set_state(STATE_SUCCESS); + } +} + +void ztaskbox::fail() +{ + if (state == STATE_BEGIN || state == STATE_DESCRIPTION || state == STATE_REMINDER) + { + set_state(STATE_FAILURE); + } +} + +void ztaskbox::complete() +{ + if (this->flag.enabled) + { + this->state = STATE_INVALID; + this->flag.enabled = false; + //zEntEvent(this, this, eEventTaskBox_OnComplete); + //this->current = (ztaskbox*)zSceneFindObject(this->asset->next_task); + + // Bruh + if (this->current != NULL) + { + return; + } + } +} + +void ztaskbox::set_callback(callback* cb) +{ + this->cb = cb; +} + +// WIP. +void ztaskbox::init() +{ + shared = NULL; + // STUFF. +} + +ztaskbox::talk_callback::talk_callback() +{ +} + +void ztaskbox::load(xBase& data, xDynAsset& asset, size_t num) +{ + ((ztaskbox&)data).load((asset_type&)asset); +} + +bool ztaskbox::exists(state_enum stage) +{ + U32 state = this->asset->stages[stage]; + //return state != STATE_BEGIN && xSTFindAsset(state, NULL); +} + +void ztaskbox::on_talk_start() +{ + if (this->cb != NULL) + { + cb->on_talk_start(); + } +} + +void ztaskbox::talk_callback::on_start() +{ + this->task->on_talk_start(); +} + +void ztaskbox::talk_callback::on_stop() +{ + this->task->on_talk_stop(answer); +} + +void ztaskbox::talk_callback::on_answer(ztalkbox::answer_enum answer) +{ + this->answer = answer; +} diff --git a/src/SB/Game/zTaskBox.h b/src/SB/Game/zTaskBox.h new file mode 100644 index 0000000..5f45d6c --- /dev/null +++ b/src/SB/Game/zTaskBox.h @@ -0,0 +1,88 @@ +#ifndef ZTASKBOX_H +#define ZTASKBOX_H + +#include "xBase.h" +#include "xDynAsset.h" + +//#include "zNPCTypeCommon.h" +#include "zTalkBox.h" + +#include + +struct ztaskbox : xBase +{ + struct flagData + { + U8 enabled : 8; + U32 dummy : 24; + }; + + enum state_enum + { + STATE_BEGIN, + STATE_DESCRIPTION, + STATE_REMINDER, + STATE_SUCCESS, + STATE_FAILURE, + STATE_END, + MAX_STATE, + STATE_INVALID = 0xffffffff + }; + + struct callback + { + virtual void on_talk_start(); + virtual void on_talk_stop(); + }; + + struct talk_callback : ztalkbox::callback + { + ztaskbox* task; + ztalkbox::answer_enum answer; + + talk_callback(); + void reset(ztaskbox& task); + void on_start(); + void on_stop(); + void on_answer(ztalkbox::answer_enum answer); + }; + + struct asset_type : xDynAsset + { + U8 persistent : 8; + U8 loop : 8; + U8 enable : 8; + U8 retry : 8; + U32 talk_box; + U32 next_task; + U32 stages[6]; + }; + + flagData flag; + asset_type* asset; + state_enum state; + callback* cb; + ztaskbox* current; + + void on_talk_start(); + void on_talk_stop(ztalkbox::answer_enum answer); + void set_state(state_enum state); + void set_callback(callback* cb); + void stop_talk(); + //void start_talk(zNPCCommon* npc); + void write(xSerial& s); + void read(xSerial& s); + void load(const asset_type& a); + static void load(xBase& data, xDynAsset& asset, size_t num); + void enable(); + void disable(); + void reset(); + void initiate(); + void succeed(); + void fail(); + void complete(); + static void init(); + bool exists(state_enum stage); +}; + +#endif diff --git a/src/SB/Game/zTextBox.cpp b/src/SB/Game/zTextBox.cpp index e69de29..cd27a79 100644 --- a/src/SB/Game/zTextBox.cpp +++ b/src/SB/Game/zTextBox.cpp @@ -0,0 +1,467 @@ +#include "zTextBox.h" + +#include "zBase.h" + +#include "xEvent.h" +#include "xstransvc.h" +#include "xTextAsset.h" + +#include + +extern F32 _720_1; +extern F32 _721_1; +extern F32 _722_0; +extern F32 _723_0; +extern F32 _761_1; + +static RwIm2DVertex vert_701[6]; // todo: move to render_bk_tex_scale + +iColor_tag convert(const ztextbox::asset_type::color_type& color); + +namespace +{ + ztextbox* head_active; + + typedef void (*render_bk_callback)(const ztextbox& e); + + void render_bk_fill(const ztextbox& e); + void render_bk_tex_scale(const ztextbox& e); + void render_bk_tex_wrap(const ztextbox& e); + + render_bk_callback render_bk_table[] = { render_bk_fill, render_bk_tex_scale, + render_bk_tex_wrap }; + + void parse_tag_blahblah(xtextbox::jot&, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&); + + xtextbox::tag_type new_tags[] = { SUBSTR("blahblah"), parse_tag_blahblah, NULL, NULL }; + U32 new_tags_size = sizeof(new_tags) / sizeof(new_tags[0]); + + void set_vert(RwIm2DVertex& vert, F32 x, F32 y, F32 u, F32 v, iColor_tag c, F32 nsz, F32 rcz); + + void render_bk_fill(const ztextbox& e) + { + const ztextbox::asset_type& a = *e.asset; + + render_fill_rect(e.tb.font.clip, convert(a.backdrop.color)); + } + + void render_bk_tex_scale(const ztextbox& e) + { + // non-matching: float instruction order + + iColor_tag c = convert(e.asset->backdrop.color); + + F32 rcz = _720_1 / RwCameraGetNearClipPlane(RwCameraGetCurrentCamera()); + F32 nsz = RwIm2DGetNearScreenZ(); + + xfont::set_render_state(e.bgtex); + + basic_rect r = e.tb.font.clip; + r.scale(_721_1, _722_0); + + set_vert(vert_701[0], r.x, r.y, _723_0, _720_1, c, nsz, rcz); + set_vert(vert_701[1], r.x, r.y + r.h, _723_0, _720_1, c, nsz, rcz); + set_vert(vert_701[2], r.x + r.w, r.y, _720_1, _723_0, c, nsz, rcz); + + vert_701[3] = vert_701[2]; + vert_701[4] = vert_701[1]; + + set_vert(vert_701[5], r.x + r.w, r.y + r.h, _720_1, _720_1, c, nsz, rcz); + + RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, vert_701, 6); + + xfont::restore_render_state(); + } + + void set_vert(RwIm2DVertex& vert, F32 x, F32 y, F32 u, F32 v, iColor_tag c, F32 nsz, F32 rcz) + { + RwIm2DVertexSetScreenX(&vert, x); + RwIm2DVertexSetScreenY(&vert, y); + RwIm2DVertexSetScreenZ(&vert, nsz); + RwIm2DVertexSetU(&vert, u, rcz); + RwIm2DVertexSetV(&vert, v, rcz); + RwIm2DVertexSetIntRGBA(&vert, c.r, c.g, c.b, c.a); + } + + void render_bk_tex_wrap(const ztextbox& e) + { + } + + void init_textbox(ztextbox& e) + { + static const U32 xjlookup[] = { 0x0, 0x2, 0x1 }; + + ztextbox::asset_type& a = *e.asset; + + e.tb.flags = 0; + e.tb.font.id = a.font; + e.tb.font.width = a.size.width; + e.tb.font.height = a.size.height; + e.tb.font.space = a.space.x; + e.tb.line_space = a.space.y; + e.tb.font.color = convert(a.color); + e.tb.bounds.x = a.bounds.x + a.inset.left; + e.tb.bounds.y = a.bounds.y + a.inset.top; + e.tb.bounds.w = a.bounds.w - a.inset.left - a.inset.right; + e.tb.bounds.h = a.bounds.h - a.inset.top - a.inset.bottom; + e.tb.flags |= (a.xjustify >= 3) ? xjlookup[0] : xjlookup[a.xjustify]; + e.tb.set_text(e.segments, e.segments_size); + + if (a.expand < ztextbox::asset_type::MAX_EX && a.max_height > a.bounds.h) + { + S32 lines; + F32 minh = e.tb.bounds.h; + F32 maxh = a.max_height - a.inset.top - a.inset.bottom; + + e.tb.bounds.h = maxh; + e.tb.bounds.h = e.tb.yextent(maxh, lines, true); + + if (e.tb.bounds.h > minh) + { + F32 hmore = e.tb.bounds.h - minh; + + if (a.expand == ztextbox::asset_type::EX_CENTER) + { + e.tb.bounds.y -= _761_1 * hmore; + } + else if (a.expand == ztextbox::asset_type::EX_UP) + { + e.tb.bounds.y -= hmore; + } + } + else + { + e.tb.bounds.h = minh; + } + } + + e.tb.font.clip.x = e.tb.bounds.x - a.inset.left; + e.tb.font.clip.y = e.tb.bounds.y - a.inset.top; + e.tb.font.clip.w = e.tb.bounds.w + a.inset.left + a.inset.right; + e.tb.font.clip.h = e.tb.bounds.h + a.inset.top + a.inset.bottom; + } + + void parse_tag_blahblah(xtextbox::jot&, const xtextbox&, const xtextbox&, + const xtextbox::split_tag&) + { + } + + S32 cb_dispatch(xBase*, xBase* to, U32 event, const F32* argf, xBase*) + { + ztextbox& e = *(ztextbox*)to; + + switch (event) + { + case eEventReset: + case eEventSceneEnd: + { + e.reset(); + break; + } + case eEventFontBackdropOn: + { + e.flag.show_backdrop = true; + break; + } + case eEventFontBackdropOff: + { + e.flag.show_backdrop = false; + break; + } + case eEventVisible: + { + if (argf && *(U32*)&argf[0]) + { + e.set_text(*(U32*)&argf[0]); + } + + e.activate(); + break; + } + case eEventInvisible: + { + e.deactivate(); + break; + } + case eEventSetText: + { + if (argf) + { + e.set_text(*(U32*)&argf[0]); + } + + break; + } + case eEventAddText: + { + if (argf) + { + e.add_text(*(U32*)&argf[0]); + } + + break; + } + case eEventClearText: + { + e.clear_text(); + break; + } + } + + return 1; + } +} // namespace + +void ztextbox::load(const asset_type& a) +{ + xBaseInit(this, (xBaseAsset*)&a); + + baseType = eBaseTypeTextBox; + asset = (asset_type*)&a; + eventFunc = cb_dispatch; + + if (linkCount) + { + link = (xLinkAsset*)(&a + 1); + } + + tb.context = this; + prev = NULL; + next = NULL; + + memset(&flag, 0, sizeof(flag)); + + bgtex = NULL; + + if (a.backdrop.texture) + { + RwTexture* tex = (RwTexture*)xSTFindAsset(a.backdrop.texture, NULL); + bgtex = RwTextureGetRaster(tex); + } + + reset(); +} + +void ztextbox::update(xScene&, F32) +{ +} + +void ztextbox::reset() +{ + deactivate(); + + segments_size = 0; + flag.dirty = true; + flag.show_backdrop = true; + + set_text(asset->text); +} + +void ztextbox::render() +{ + if (flag.dirty) + { + init_textbox(*this); + flag.dirty = false; + } + + if (flag.show_backdrop) + { + render_backdrop(); + } + + tb.render(true); +} + +void ztextbox::render_backdrop() +{ + if (asset->backdrop.type < sizeof(render_bk_table) / sizeof(render_bk_table[0])) + { + render_bk_table[asset->backdrop.type](*this); + } +} + +void ztextbox::activate() +{ + if (flag.active) + { + return; + } + + flag.active = true; + flag.visible = true; + + prev = NULL; + next = head_active; + + if (head_active) + { + head_active->prev = this; + } + + head_active = this; +} + +void ztextbox::deactivate() +{ + if (!flag.active) + { + return; + } + + flag.active = false; + flag.visible = false; + + if (prev) + { + prev->next = next; + } + + if (next) + { + next->prev = prev; + } + + if (head_active == this) + { + head_active = next; + } +} + +void ztextbox::set_text(const char* s) +{ + clear_text(); + add_text(s); +} + +void ztextbox::set_text(U32 id) +{ + if (!id) + { + return; + } + + xTextAsset* ta = (xTextAsset*)xSTFindAsset(id, NULL); + + if (!ta) + { + clear_text(); + } + else + { + set_text(xTextAssetGetText(ta)); + } +} + +void ztextbox::add_text(const char* s) +{ + if (!s) + { + return; + } + + segments[segments_size] = s; + segments_size++; + + flag.dirty = true; +} + +void ztextbox::add_text(U32 id) +{ + if (!id) + { + return; + } + + xTextAsset* ta = (xTextAsset*)xSTFindAsset(id, NULL); + + if (ta) + { + add_text(xTextAssetGetText(ta)); + } +} + +void ztextbox::clear_text() +{ + segments_size = 0; + flag.dirty = true; +} + +void ztextbox::refresh() +{ + if (flag.dirty) + { + init_textbox(*this); + flag.dirty = false; + } +} + +void ztextbox::get_text(char* buffer, size_t buffer_size) const +{ + const char* const* it = segments; + const char* const* end = it + segments_size; + + while (it != end) + { + const char* s = *it; + U32 len = strlen(s); + + if (len >= buffer_size) + { + memcpy(buffer, s, buffer_size - 1); + buffer += buffer_size - 1; + break; + } + + memcpy(buffer, s, len); + buffer += len; + it++; + } + + *buffer = '\0'; +} + +void ztextbox::init() +{ + xtextbox::register_tags(new_tags, new_tags_size); + + head_active = NULL; +} + +void ztextbox::load(xBase& data, xDynAsset& asset, size_t) +{ + ((ztextbox&)data).load((asset_type&)asset); +} + +void ztextbox::update_all(xScene& s, F32 dt) +{ + ztextbox* it = head_active; + + while (it) + { + it->update(s, dt); + it = it->next; + } +} + +void ztextbox::render_all() +{ + ztextbox* it = head_active; + + while (it) + { + it->render(); + it = it->next; + } +} + +iColor_tag convert(const ztextbox::asset_type::color_type& color) +{ + iColor_tag c; + c.r = color.r; + c.g = color.g; + c.b = color.b; + c.a = color.a; + return c; +} diff --git a/src/SB/Game/zTextBox.h b/src/SB/Game/zTextBox.h new file mode 100644 index 0000000..203cd6e --- /dev/null +++ b/src/SB/Game/zTextBox.h @@ -0,0 +1,103 @@ +#ifndef ZTEXTBOX_H +#define ZTEXTBOX_H + +#include "xDynAsset.h" +#include "xFont.h" +#include "xScene.h" + +#include + +struct ztextbox : xBase +{ + struct asset_type : xDynAsset + { + struct color_type + { + U8 r; + U8 g; + U8 b; + U8 a; + }; + + U32 text; + basic_rect bounds; + U32 font; + struct + { + F32 width; + F32 height; + } size; + struct + { + F32 x; + F32 y; + } space; + color_type color; + struct + { + F32 left; + F32 top; + F32 right; + F32 bottom; + } inset; + enum + { + XJ_LEFT, + XJ_CENTER, + XJ_RIGHT + } xjustify; + enum + { + EX_UP, + EX_CENTER, + EX_DOWN, + MAX_EX + } expand; + F32 max_height; + struct + { + U32 type; + color_type color; + U32 texture; + } backdrop; + }; + + struct + { + bool active : 1; // bit 24 + bool dirty : 1; // bit 25 + bool show_backdrop : 1; // bit 26 + bool visible : 1; // bit 27 + bool hack_invisible : 1; // bit 28 + } flag; + asset_type* asset; + xtextbox tb; + const char* segments[16]; + U32 segments_size; + ztextbox* next; + ztextbox* prev; + RwRaster* bgtex; + + static void init(); + static void load(xBase& data, xDynAsset& asset, size_t); + static void update_all(xScene& s, F32 dt); + static void render_all(); + + void load(const asset_type& a); + void update(xScene&, F32); + void reset(); + void render(); + void render_backdrop(); + void activate(); + void deactivate(); + void set_text(const char* s); + void set_text(U32 id); + void add_text(const char* s); + void add_text(U32 id); + void clear_text(); + void refresh(); + void get_text(char* buffer, size_t buffer_size) const; + bool visible(); +}; + +#endif diff --git a/src/SB/Game/zWadNME.cpp b/src/SB/Game/zWadNME.cpp index 7d8fcdf..ccc25ce 100644 --- a/src/SB/Game/zWadNME.cpp +++ b/src/SB/Game/zWadNME.cpp @@ -1,18 +1,18 @@ -#include "zWadNME.h" +// #include "zWadNME.h" -S32 zNMEGoalDentDamage::Exit(float, void*) -{ - return 0; // TO-DO -} +// S32 zNMEGoalDentDamage::Exit(float, void*) +// { +// return 0; // TO-DO +// } -S32 zNMEGoalDenDamage::Exit(float dt, void* ctxt) //POSSIBLY RIGHT, NEEDS DOUBLE CHECKED -{ - zNMEDennis* npc; - npc->spd_throttle = -1.0f; - return 0; -} +// S32 zNMEGoalDenDamage::Exit(float dt, void* ctxt) //POSSIBLY RIGHT, NEEDS DOUBLE CHECKED +// { +// zNMEDennis* npc; +// npc->spd_throttle = -1.0f; +// return 0; +// } -S32 zNMEDennis::DfltVulnFlags() -{ - return 0xc07b0007; // HACKED TOGETHER FOR TESTING PURPOSES -} +// S32 zNMEDennis::DfltVulnFlags() +// { +// return 0xc07b0007; // HACKED TOGETHER FOR TESTING PURPOSES +// } diff --git a/src/SB/Game/zWadNME.h b/src/SB/Game/zWadNME.h index 1901ae0..e69de29 100644 --- a/src/SB/Game/zWadNME.h +++ b/src/SB/Game/zWadNME.h @@ -1,323 +0,0 @@ -#ifndef ZWADNME_H -#define ZWADNME_H - -#include - -#include "xNME.h" -#include "zBossCam.h" -#include "xPlayer.h" - -struct base : xEnt, xFactoryInst -{ - S16 bound_bone; - U16 sound_id_offset; - U16 global_parameters_size; - U16 local_parameters_size; - U32 type; - xModelAssetParam* global_parameters; - xModelAssetParam* local_parameters; - union - { - xMovePoint* movepoint; - U32 movepoint_asset_id; - }; - xEntNPCAssetIN* npc_asset; - xModelAssetInfo* model_asset; - F32 shadow_strength; - F32 shadow_cache_fudge_factor; - xVec3 bound_offset; -}; - -struct zNMENPCWrapper : base -{ - void (*fun_setup)(xEnt*); - void (*fun_reset)(xEnt*); - S32 colFreq; - U8 flg_colCheck; - U8 flg_penCheck; - U16 flg_unusedCollFlags; - struct - { - S32 aflg_basenme : 8; - S32 flg_upward : 8; - S32 flg_xtrarend : 1; - S32 flg_inUpdate : 1; - S32 flg_newtime : 1; - S32 flg_postproc : 1; - S32 flg_profProc : 1; - S32 flg_hudrend : 1; - S32 flg_moreUnusedSpace : 10; - }; - - void InitFromNPCMgr(xEntAsset* asset); - void Init(xEntAsset* asset); - void PostInit(); - void PostSetup(); - void Load(); - void NewTime(); - void RenderExtra(); - void RenderHud(); - void Move(); - S32 ColFreqReset(); - void init(xEntAsset* asset); - void SelfSetup(); - void setup(); - void Reset(); - void Setup(); - void reset(); - void update_npc(F32 dt); - void Process(); - void update_bound(); - void change_bounds(); - U8 system_event(); - void render_npc(); - void Render(); - void debug_render(); - void render_extra(); - void damage(); - void destroy(); - void Destroy(); - void scene_setup(); - void add_states(); - void add_transitions(); - S32 SysEvent(); - void BUpdate(); - void UpdateWrapper(F32 dt); - void NMEWrap_Init(xEntAsset* asset); - xAnimTable* CreateAnimTable(); - void SelfDestroy(); - void CollideReview(); -}; - -struct zNMECommon : zNMENPCWrapper -{ - zNMEAsset* nmeass; - S32 siz_nmeass; - xPsyche* psy_self; - NMECfgCommon* cfg_common; - NMEShadParms* cfg_shadparm; - S32 flg_vuln; - S32 flg_move; - S32 flg_misc; - S32 flg_able; - F32 spd_throttle; - NMERuntime runtimeData; - zNMEDriver* drv_data; - zNMENavNet* navnet; - union - { - F32 tmr_common[3]; - F32 tmr_invuln; - }; - F32 tmr_scary; - F32 tmr_lastAlert; - zNMECommon* npc_duplodude; - zNMESoundTable* snd_table; - iSndHandle sndID[10]; - zShrapnelAsset* shrapnelAsset; - - void Destroy(); - void Render(); - void SelfDestroy(); - void ProcessInvis(); - void PostProcess(); - S32 IsAlive(); - S32 IsHealthy(); - S32 IsPresent(); - en_nmesimp SimpleStatus(); - F32 HealthRatio(); - void Boo(); - void DuploOwner(zNMECommon* duper); - void SpeakBegin(); - void SpeakEnd(); - void SpeakStart(); - void SpeakStop(); - S32 CanRope(); - void CollideReview(); - zMovePoint* MvptFirstFollow(); - zMovePoint* MvptFirstTarget(); - xEntFrame* Gimme_xEntFrame(); - zNMEDriver* Gimme_DriveData(); - xEntShadow* Gimme_ShadowData(); - zNMENavNet* Gimme_NavNet(); - zNMEArena* Gimme_NMEArena(); - xShadowSimpleCache* Gimme_SimpShadowCache(); - void Reset(); - void PoofOfBubbles(); - S32 LaunchProjectile(en_haztyp haztyp, F32 spd_proj, F32 dst_minRange, xVec3* pos_launch, - F32 tym_predictMax, F32 hyt_offset, F32 rad_min, F32 rad_max); - void GiveReward(); - void DeathFXKick(); - void DieTheGoodDeath(); - F32 ThrottleAdjust(F32 dt, F32 spd_want, F32 accel); - xAnimTable* CreateAnimTable(xAnimTable* table); - xAnimTransition* AnimMakeSmackTran(U32 animID); - S32 AnimStart(U32 animID, S32 forceRestart); - S32 MatMoveToPos(xVec3* pos_tobe, F32 dt, F32 spd, S32 doTurn, F32 spd_turnrate); - F32 MatQRotTowards(F32 dt, xVec3* dir_face, F32 spd_turnrate); - xModelInstance* ModelAtomicFind(S32 index, S32 idx_prev, xModelInstance* mdl_prev); - S32 HaveLOSToPos(xVec3* pos, F32 dist, xScene* xscn, xBase* tgt, xCollis* colCallers); - S32 ReviewCollBounce(xEntCollis* npccol, xVec3* vel, F32 fac_elastic); - S32 ReviewCollSurfs(xEntCollis* npccol, zNMECommon* npc); - void RunCollision(F32 dt); - en_nmesimp Common_SimpStat(); - void ApplyGlowDamp(); - void ShadStufUpdate(); - void FullShadAcquire(); - void ShadowPrep(); - S32 WannaPoolShadow(); - void TellMeVisOnOff(xEnt* ent); - S32 Respawn(xVec3* pos, zMovePoint* mvptFirst, zMovePoint* mvptSpawnRef); - void Damage(en_npcdmg dmgtype, xBase* who, xVec3* vec_hit, S32 amt_dmgCaller, - en_plyrpup pup_fromCaller); - void ConvertHitEvent(NMESysEvent* sysmail); - S32 DfltSysEventMail(NMESysEvent* sysmail); - S32 SysEvent(xBase* from, xBase* to, U32 toEvent, F32* toParam, xBase* toParamWidget, - U32 toParamWidgetID, S32* handled); - S32 NMEMessage(NMEMsg* mail); - S32 TypeHandleMail(); - void CreateConfig(); - void Setup(); - void Common_Init(); - void Process(F32 dt); - void BUpdate(xVec3* pos); - void Init(xEntAsset* entasset); -}; - -struct zNMEBoss : zNMECommon -{ -}; - -struct zNMEDennis; - -struct zNMESBBat : zNMECommon -{ - zNMEDennis* npc_bossman; - void Reset(); - void Process(F32 dt); - void Setup(); - void Init(xEntAsset* asset); - void SelfSetup(); - U32 AnimPick(S32 gid); - xAnimTable* CreateAnimTable(xAnimTable* table); -}; - -struct zNMEDennis : zNMEBoss -{ - S32 pts_health; - NMECfgDennis* cfg_dennis; - F32 tmr_nextLeap; - S32 cnt_attacksTilEvade; - zMovePoint* nav_evade; - zNMESBBat* npc_sbbat; - union - { - en_denstage stageCurr; - S32 stageCurrNum; - }; - union - { - xModelBlur moveBlur; - xModelBlur moveBlurShort; - }; - xModelBlur moveBlurLong; - zStreamedSoundList oneLiners; - DennisLetMeKnow tellMeWhen; - S32 flg_firstTimestep; - zBossCam_Binary cam_boss; - en_dbcmode mod_camCurr; - en_dbcmode mod_camWant; - xGroup* grp_mvpt; - - zMovePoint* PickEvade(zMovePoint* nav_from); - S32 DenMailSys(NMESysEvent* sysmail); - S32 DenMailDamage(NMEDamageInfo* dmgmail); - S32 TypeHandleMail(NMEMsg* mail); - void BossCamSet(en_dbcmode mod_desired, U8 forceCut); - en_vis VisionTarget(); - void RenderHud(); - void PostProcess(); - void NewTime(F32 dt); - void BUpdate(xVec3* pos); - void Process(F32 dt); - S32 IsAlive(); - void Destroy(); - void Reset(); - void Setup(); - void Init(xEntAsset* asset); - xAnimTable* CreateAnimTable(xAnimTable* table); - U32 AnimPick(S32 gid, en_npcgspot gspot); - zMovePoint* MvptFirstFollow(); - void SelfSetup(); - S32 DfltVulnFlags(); - void CreateConfig(); -}; - -struct zNMEDenToo : zNMEBoss -{ - S32 pts_health; - DenTooMeter denTooMeter; - NMECfgDenToo* cfg_dentoo; - F32 tmr_nextLeap; - S32 cnt_attacksTilEvade; - zMovePoint* nav_evade; - union - { - en_dentstage stageCurr; - S32 stageCurrNum; - }; - xModelBlur blur_jumpShort; - xModelBlur blur_jumpLong; - zStreamedSoundList oneLiners; - xGroup* grp_mvpt; - S32 flg_firstTimestep; - zBossCam_Binary cam_boss; - en_dtbcmode mod_camCurr; - en_dtbcmode mod_camWant; - F32 tmr_bobCycle; - - zMovePoint* PickEvade(zMovePoint* nav_from); - S32 DenMailSys(NMESysEvent* sysmail); - S32 DenMailDamage(NMEDamageInfo* dmgmail); - S32 TypeHandleMail(NMEMsg* mail); - void BossCamRepel(); - void BossCamSet(en_dtbcmode mod_desired, U8 forceCut); - void RespondToHittingPlayer(); - en_vis VisionTarget(); - void RenderHud(); - void BUpdate(xVec3* pos); - void PostProcess(); - void Process(F32 dt); - S32 IsAlive(); - void Destroy(); - void Reset(); - void Setup(); - void Init(xEntAsset* asset); - xAnimTable* CreateAnimTable(xAnimTable* table); - U32 AnimPick(S32 gid, en_npcgspot gspot); - zMovePoint* MvptFirstFollow(); - void SelfSetup(); - S32 DfltVulnFlags(); - void CreateConfig(); - S32 WannaPoolShadow(); -}; - -struct zNMEGoalDenDamage : zNMEGoalCommon -{ - S32 GoalHandleMail(NMEMsg* mail); - S32 ChkExistence(zNMEDennis* npc, F32 dt, S32& nextgoal, en_trantype& trantype); - S32 Process(en_trantype* trantype, F32 dt, void* ctxt); - S32 Exit(float, void*); - S32 Enter(); -}; - -struct zNMEGoalDentDamage : zNMEGoalCommon -{ - S32 GoalHandleMail(NMEMsg* mail); - S32 ChkExistence(zNMEDenToo* npc, F32 dt, S32& nextgoal, en_trantype& trantype); - S32 Process(en_trantype* trantype, F32 dt, void* ctxt); - S32 Exit(float, void*); - S32 Enter(); -}; - -#endif From 3f4bfc21dc300aaef49ee7081a2f4252ef5622e9 Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Thu, 24 Apr 2025 14:29:05 -0400 Subject: [PATCH 4/7] Added and Fixed the rest ofthe .h (I believe). Finished iException and got it successfully linked. --- configure.py | 2 +- src/SB/Core/gc/iException.cpp | 8 + src/SB/Core/gc/iException.h | 8 + src/SB/Core/gc/iMath3.h | 2 +- src/SB/Core/x/xEnv.h | 15 + src/SB/Game/zMovePoint.cpp | 142 ++ src/SB/Game/zMovePoint.h | 43 + src/SB/Game/zNMECommon.cpp | 490 +++++ src/SB/Game/zNMECommon.h | 654 ++++++ src/SB/Game/zNPCSndTable.cpp | 62 + src/SB/Game/zNPCSndTable.h | 61 + src/SB/Game/zParEmitter.cpp | 35 + src/SB/Game/zParEmitter.h | 14 + src/SB/Game/zPortal.cpp | 62 + src/SB/Game/zPortal.h | 25 + src/SB/Game/zScene.cpp | 3586 +++++++++++++++++++++++++++++++++ src/SB/Game/zScene.h | 72 + src/SB/Game/zShrapnel.cpp | 3 + src/SB/Game/zShrapnel.h | 223 ++ src/SB/Game/zTalkBox.cpp | 2 + src/SB/Game/zTalkBox.h | 7 +- src/SB/Game/zTaskBox.cpp | 77 +- src/SB/Game/zTaskBox.h | 6 +- 23 files changed, 5558 insertions(+), 41 deletions(-) create mode 100644 src/SB/Game/zMovePoint.cpp create mode 100644 src/SB/Game/zMovePoint.h create mode 100644 src/SB/Game/zNMECommon.cpp create mode 100644 src/SB/Game/zNPCSndTable.cpp create mode 100644 src/SB/Game/zNPCSndTable.h create mode 100644 src/SB/Game/zParEmitter.cpp create mode 100644 src/SB/Game/zParEmitter.h create mode 100644 src/SB/Game/zPortal.cpp create mode 100644 src/SB/Game/zPortal.h create mode 100644 src/SB/Game/zScene.cpp create mode 100644 src/SB/Game/zScene.h create mode 100644 src/SB/Game/zShrapnel.cpp create mode 100644 src/SB/Game/zShrapnel.h diff --git a/configure.py b/configure.py index 5fe4d51..1575602 100644 --- a/configure.py +++ b/configure.py @@ -339,7 +339,7 @@ def MatchingFor(*versions): Object(NonMatching, "SB/Game/zParticleCustom.cpp"), Object(NonMatching, "SB/Core/gc/iWad.cpp"), Object(NonMatching, "SB/Core/gc/iTRC.cpp"), - Object(NonMatching, "SB/Core/gc/iException.cpp"), + Object(Matching, "SB/Core/gc/iException.cpp"), Object(NonMatching, "SB/Core/gc/iScrFX.cpp"), Object(NonMatching, "SB/Core/gc/iARAMTmp.cpp"), diff --git a/src/SB/Core/gc/iException.cpp b/src/SB/Core/gc/iException.cpp index e69de29..7cc017f 100644 --- a/src/SB/Core/gc/iException.cpp +++ b/src/SB/Core/gc/iException.cpp @@ -0,0 +1,8 @@ +#include "iException.h" + +void iExceptionMemCrash(const char* loc, U32 size, const char* arg3) +{ + OSReport("Out of memory crash, Loc=%s Size=%d\n", loc, size); + OSReport("%s\n", arg3); + OSPanic("iException.cpp", 25, ""); +} diff --git a/src/SB/Core/gc/iException.h b/src/SB/Core/gc/iException.h index e69de29..1ef1cd2 100644 --- a/src/SB/Core/gc/iException.h +++ b/src/SB/Core/gc/iException.h @@ -0,0 +1,8 @@ +#ifndef IEXCEPTION_H +#define IEXCEPTION_H + +#include "dolphin.h" +#include "dolphin/os.h" +#include + +#endif diff --git a/src/SB/Core/gc/iMath3.h b/src/SB/Core/gc/iMath3.h index e69caf2..678a787 100644 --- a/src/SB/Core/gc/iMath3.h +++ b/src/SB/Core/gc/iMath3.h @@ -9,7 +9,7 @@ union xiMat4x3Union { - xMat4x3 xm; + //xMat4x3 xm; CURRENTLY BROKEN. DONT KNOW WHY RwMatrix im; }; diff --git a/src/SB/Core/x/xEnv.h b/src/SB/Core/x/xEnv.h index a64c5b1..d72573b 100644 --- a/src/SB/Core/x/xEnv.h +++ b/src/SB/Core/x/xEnv.h @@ -31,6 +31,21 @@ struct xEnvAsset : xBaseAsset F32 loldHeight; }; +struct _zEnv : xBase +{ + xEnvAsset* easset; +}; + +void zEnvInit(void* env, void* easset); +void zEnvInit(_zEnv* env, xEnvAsset* easset); +void zEnvSetup(_zEnv* env); +void zEnvStartingCamera(_zEnv* env); +void zEnvRender(xEnv* env); +void zEnvSave(_zEnv* ent, xSerial* s); +void zEnvLoad(_zEnv* ent, xSerial* s); +void zEnvReset(_zEnv* env); +S32 zEnvEventCB(xBase*, xBase* to, U32 toEvent, const F32* toParam, xBase*); + void xEnvLoadBsp(xEnv* env, const void* data, U32 datasize, S32 dataType); void xEnvFree(xEnv* env); void xEnvSetup(xEnv* env); diff --git a/src/SB/Game/zMovePoint.cpp b/src/SB/Game/zMovePoint.cpp new file mode 100644 index 0000000..bc06743 --- /dev/null +++ b/src/SB/Game/zMovePoint.cpp @@ -0,0 +1,142 @@ +#include "zMovePoint.h" +#include "zNPCSupplement.h" + +#include "xEvent.h" + +#include + +// PORTED DIRECTLY FROM BFBB + +extern zMovePoint* g_mvpt_list; +extern S32 g_mvpt_cnt; +extern F32 lbl_803CDD40; +extern F32 lbl_803CDD44; + +// Random load word at the end of the function for some reason. +zMovePoint* zMovePoint_GetMemPool(S32 cnt) +{ + /*if (cnt != 0) + { + g_mvpt_list = (zMovePoint*)xMemAllocSize(cnt * sizeof(zMovePoint)); + } + else + { + g_mvpt_list = NULL; + } + g_mvpt_cnt = cnt; + return g_mvpt_list;*/ + + g_mvpt_list = cnt ? (zMovePoint*)xMemAllocSize(cnt * sizeof(zMovePoint)) : NULL; + g_mvpt_cnt = cnt; + return g_mvpt_list; +} + +void zMovePointInit(zMovePoint* m, xMovePointAsset* asset) +{ + xMovePointInit((xMovePoint*)m, asset); + m->eventFunc = zMovePointEventCB; + if (m->linkCount) + { + m->link = + (xLinkAsset*)(((U32*)asset + sizeof(xMovePointAsset) / 4) + (U32)asset->numPoints); + } + else + { + m->link = NULL; + } +} + +zMovePoint* zMovePoint_GetInst(S32 n) +{ + return &g_mvpt_list[n]; +} + +void zMovePointSetup(zMovePoint* mvpt, zScene* scn) +{ + xMovePointSetup((xMovePoint*)mvpt, (xScene*)scn); +} + +zMovePoint* zMovePoint_From_xAssetID(U32 aid) +{ + zMovePoint* pnt = g_mvpt_list; + zMovePoint* ret = NULL; + for (S32 i = g_mvpt_cnt; i > 0; i--) + { + if (pnt->asset->id == aid) + { + ret = pnt; + break; + } + pnt++; + } + return ret; +} + +void zMovePointSave(zMovePoint* ent, xSerial* s) +{ + xMovePointSave((xMovePoint*)ent, s); +} + +void zMovePointLoad(zMovePoint* ent, xSerial* s) +{ + xMovePointLoad((xMovePoint*)ent, s); +} + +void zMovePointReset(zMovePoint* m) +{ + xMovePointReset((xMovePoint*)m); +} + +S32 zMovePointEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* b3) +{ + switch (toEvent) + { + case eEventOn: + ((zMovePoint*)to)->on = true; + break; + case eEventOff: + ((zMovePoint*)to)->on = false; + break; + case eEventArrive: + break; + case eEventReset: + zMovePointReset((zMovePoint*)to); + break; + case eEventMakeASplash: + xVec3* pos = ((zMovePoint*)to)->pos; + if (pos != NULL) + { + if (*toParam < lbl_803CDD40) + { + NPCC_MakeASplash(pos, lbl_803CDD44); + } + else + { + NPCC_MakeASplash(pos, *toParam); + } + } + break; + } + return eEventEnable; +} + +F32 zMovePointGetNext(const zMovePoint* current, const zMovePoint* prev, zMovePoint** next, + xVec3* hdng) +{ + return xMovePointGetNext((xMovePoint*)current, (xMovePoint*)prev, (xMovePoint**)next, hdng); +} + +xVec3* zMovePointGetPos(const zMovePoint* m) +{ + return xMovePointGetPos((xMovePoint*)m); +} + +F32 zMovePointGetDelay(const zMovePoint* m) +{ + return xMovePointGetDelay((xMovePoint*)m); +} + +F32 xMovePointGetDelay(const xMovePoint* m) +{ + return m->delay; +} diff --git a/src/SB/Game/zMovePoint.h b/src/SB/Game/zMovePoint.h new file mode 100644 index 0000000..fb58329 --- /dev/null +++ b/src/SB/Game/zMovePoint.h @@ -0,0 +1,43 @@ +#ifndef ZMOVEPOINT_H +#define ZMOVEPOINT_H + +#include "xMovePoint.h" + +#include "zScene.h" + +#include + +struct zMovePoint : xMovePoint +{ + F32 RadiusZone() + { + return asset->zoneRadius; + } + F32 Delay() + { + return asset->delay; + } + xVec3* PosGet() + { + return pos; + } + U32 NumNodes(); + U8 IsOn(); +}; + +zMovePoint* zMovePoint_GetMemPool(S32 cnt); +void zMovePointInit(zMovePoint* m, xMovePointAsset* asset); +zMovePoint* zMovePoint_GetInst(S32 n); +void zMovePointSetup(zMovePoint* mvpt, zScene* scn); +zMovePoint* zMovePoint_From_xAssetID(U32 aid); +void zMovePointSave(zMovePoint* ent, xSerial* s); +void zMovePointLoad(zMovePoint* ent, xSerial* s); +void zMovePointReset(zMovePoint* m); +S32 zMovePointEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* b3); +F32 zMovePointGetNext(const zMovePoint* current, const zMovePoint* prev, zMovePoint** next, + xVec3* hdng); +xVec3* zMovePointGetPos(const zMovePoint* m); +F32 zMovePointGetDelay(const zMovePoint* m); +F32 xMovePointGetDelay(const xMovePoint* m); + +#endif diff --git a/src/SB/Game/zNMECommon.cpp b/src/SB/Game/zNMECommon.cpp new file mode 100644 index 0000000..c11fe9c --- /dev/null +++ b/src/SB/Game/zNMECommon.cpp @@ -0,0 +1,490 @@ +#include "zNPCTypeCommon.h" + +#include +#include + +#include "zEntCruiseBubble.h" +#include "zEntTeleportBox.h" +#include "zGlobals.h" +#include "zNPCTypes.h" +#include "zNPCSndTable.h" +#include "zNPCSupport.h" +#include "zNPCFXCinematic.h" + +#include "iModel.h" +#include "iSnd.h" + +#include "xString.h" +#include "xDebug.h" + +extern char zNPCTypeCommon_strings[]; +extern char* g_strz_lassanim[3]; +extern S32 g_hash_lassanim[3]; +extern volatile S32 g_skipDescent; +extern NPCConfig* g_ncfghead; +extern NPCSndTrax g_sndTrax_General[]; +extern F32 lbl_803CE4C0; +extern S32 g_flg_wonder; +extern S32 g_isConversation; +extern xBase* g_ownerConversation; +extern F32 g_tmr_talkless; + +xFactoryInst* ZNPC_Create_Common(S32 who, RyzMemGrow* grow, void*) +{ + zNPCCommon* com = NULL; + + switch (who) + { + case NPC_TYPE_COMMON: + { + com = new (who, grow) zNPCCommon(who); + break; + } + } + + return com; +} + +void ZNPC_Destroy_Common(xFactoryInst* inst) +{ + delete inst; +} + +void ZNPC_Common_Startup() +{ + S32 i; + + for (i = 0; i < 3; i++) + { + g_hash_lassanim[i] = xStrHash(g_strz_lassanim[i]); + } + + NPCSupport_Startup(); + NPCS_Startup(); + zNPCSettings_MakeDummy(); + zNPCFXStartup(); +} + +void ZNPC_Common_Shutdown() +{ + NPCS_Shutdown(); + NPCSupport_Shutdown(); + zNPCFXShutdown(); +} + +void zNPCCommon_ScenePrepare() +{ + NPCS_SndTimersReset(); + NPCS_SndTablePrepare(g_sndTrax_General); + NPCSupport_ScenePrepare(); + zNPCCommon_WonderReset(); + g_skipDescent = 5; +} + +void zNPCCommon_SceneFinish() +{ + zNPCCommon::ConfigSceneDone(); + NPCSupport_SceneFinish(); + xDebugRemoveTweak(zNPCTypeCommon_strings + 0x42b); +} + +void zNPCCommon_SceneReset() +{ + NPCSupport_SceneReset(); + zNPCPlyrSnd_Reset(); + g_skipDescent = 5; +} + +void zNPCCommon_ScenePostInit() +{ + NPCSupport_ScenePostInit(); +} + +void zNPCCommon_Timestep(F32 dt) +{ + NPCSupport_Timestep(dt); + NPCS_SndTimersUpdate(dt); + zNPCPlyrSnd_Update(dt); + g_skipDescent -= 1; + if (g_skipDescent < 0) + { + g_skipDescent = 0; + } +} + +void zNPCCommon::Destroy() +{ + SelfDestroy(); +} + +void zNPCCommon::Process(xScene* xscn, F32 dt) +{ + if ((flg_misc & 4) != 0) + { + ModelScaleSet(&cfg_npc->scl_model); + } + flags1.flg_upward = flags1.flg_upward & ~0x2; + xNPCBasic::Process(xscn, dt); +} + +void zNPCCommon::ParseProps() +{ + for (S32 i = 0x3f; i < 0x42; i++) + { + switch (i) + { + case 0x3f: + MvptReset(NULL); + break; + default: + break; + } + } +} + +bool zNPCCommon::IsMountableType(en_ZBASETYPE type) +{ + switch (type) + { + case eBaseTypePlatform: + return true; + break; + default: + return false; + break; + } +} + +void zNPCCommon::SelfDestroy() +{ + xBehaveMgr* bmgr = xBehaveMgr_GetSelf(); + if (psy_instinct != NULL) + { + bmgr->UnSubscribe(psy_instinct); + } + psy_instinct = NULL; +} + +S32 zNPCCommon::GetVertPos(en_mdlvert vid, xVec3* pos) +{ + NPCConfig* cfg = cfg_npc; + if (!(cfg->flg_vert & 1 << vid)) + { + return 0; + } + iModelTagEval(model->Data, &cfg->tag_vert[vid], model->Mat, pos); + return 1; +} + +void zNPCCommon::ConfigSceneDone() +{ + g_ncfghead = 0; +} + +void zNPCCommon_WonderReset() +{ + g_isConversation = 0; + g_flg_wonder = 0; +} + +S32 NPCC_NPCIsConversing() +{ + return g_isConversation; +} + +void zNPCCommon::WonderOfTalking(S32 inprogress, xBase* owner) +{ + if (inprogress) + { + g_isConversation = 1; + if (owner) + { + g_ownerConversation = owner; + return; + } + else + { + g_ownerConversation = this; + return; + } + } + + g_isConversation = 0; + g_ownerConversation = NULL; +} + +S32 zNPCCommon::SomethingWonderful() +{ + S32 flg_wonder = g_flg_wonder; + + if (globals.player.Health < 1) + { + // Idk why they wouldn't do flg_wonder |= x here, but this is needed to match + flg_wonder = g_flg_wonder | 0b00000010; + } + + if (globals.player.ControlOff & 0xffffbeff) + { + flg_wonder |= 0b00000100; + } + + if (cruise_bubble::active() && (this->SelfType() & 0xffffff00) == 'NTF\0') + { + flg_wonder |= 0b01000000; + } + + if (globals.cmgr && globals.cmgr->csn) + { + flg_wonder |= 0b00000001; + } + + if (g_isConversation) + { + flg_wonder |= 0b00001000; + } + + if (!NPCC_LampStatus()) + { + flg_wonder |= 0b00100000; + } + + if (zEntTeleportBox_playerIn()) + { + flg_wonder |= 0b10000000; + } + + return flg_wonder; +} + +S32 zNPCCommon::SndIsAnyPlaying() +{ + S32 iVar1 = 0; + + for (S32 i = 0; i < 4; i++) + { + iVar1 = xSndIsPlaying(0, (U32)this + i); + if (iVar1) + { + break; + } + } + + return iVar1; +} + +U32 zNPCCommon::LassoInit() +{ + lassdata = PRIV_GetLassoData(); + if (lassdata != NULL) + { + memset(lassdata, 0, 0x18); + lassdata->stage = LASS_STAT_PENDING; + lassdata->lassoee = this; + } + if (lassdata) + { + return 1; + } + return 0; +} + +zNPCLassoInfo* zNPCCommon::GimmeLassInfo() +{ + return flg_vuln & 0x1000000 ? lassdata : NULL; +} + +void zNPCCommon::LassoNotify(en_LASSO_EVENT event) +{ + zNPCLassoInfo* lass = this->lassdata; + + if (!lass->stage && event) + { + return; + } + + switch (event) + { + case LASS_STAT_DONE: + { + lass->stage = LASS_STAT_PENDING; + break; + } + case LASS_STAT_PENDING: + { + lass->stage = LASS_STAT_DONE; + break; + } + case LASS_STAT_GRABBING: + { + lass->stage = LASS_STAT_GRABBING; + break; + } + case LASS_STAT_NOMORE: + { + lass->stage = LASS_STAT_TOSSING; + return; + } + case LASS_STAT_UNK_5: + { + lass->stage = LASS_STAT_DONE; + break; + } + } +} + +void zNPCCommon::AddDEVGoals(xPsyche*) +{ +} + +U32 zNPCCommon::DBG_Name() +{ + return 0; +} + +void zNPCCommon::DBG_AddTweakers() +{ +} + +void zNPCCommon::SelfSetup() +{ +} + +void zNPCCommon::DBG_RptDataSize() +{ +} + +U32 zNPCCommon::DBG_InstName() +{ + return this->DBG_Name(); +} + +xEntDrive* zNPCCommon::PRIV_GetDriverData() +{ + return NULL; +} +void zNPCCommon::ModelScaleSet(const xVec3* vec) +{ + ModelScaleSet(vec->x, vec->y, vec->z); +} + +xAnimTable* zNPCCommon::AnimGetTable() +{ + return model->Anim->Table; +} + +zNPCLassoInfo* zNPCCommon::PRIV_GetLassoData() +{ + return NULL; +} + +void zNPCCommon::DuploOwner(zNPCCommon* duper) +{ + npc_duplodude = duper; +} + +void zNPCCommon::SpeakBegin() +{ +} + +void zNPCCommon::SpeakEnd() +{ +} + +void zNPCCommon::SpeakStart(U32 param_1, U32 param_2, S32 param_3) +{ +} + +void zNPCCommon::SpeakStop() +{ +} + +F32 zNPCCommon::GenShadCacheRad() +{ + return lbl_803CE4C0; +} + +// xNPCBasic vtable at: 0x2949F4 +// vtable reference is stored immidately _after_ object fields in an xNPCBasic +// instance. That is, sizeof(xNPCBasic) = sizeof(visible fields) + an extra 4 +// bytes for the vtable pointer after those fields. +// vtable[0] = NULL (I think these first two are for RTTI which is disabled) +// vtable[1] = NULL +// vtable[2] = Init(FP9xEntAsset) +// vtable[3] = PostInit(Fv) +// vtable[4] = Setup(Fv) +// vtable[5] = PostSetup(Fv) +// vtable[6] = Reset(Fv) +// vtable[7] = Process(FP6xScenef) +// vtable[8] = BUpdate(FP5xVec3) +// vtable[9] = NewTime(FP6xScenef) +// vtable[10] = Move(FP6xScenefP9xEntFrame) +// vtable[11] = SysEvent(FP5xBaseP5xBaseUiPCfP5xBasePi) +// vtable[12] = Render(Fv) +// vtable[13] = Save(CFP7xSerial) +// vtable[14] = Load(FP7xSerial) +// vtable[15] = CollideReview(Fv) +// vtable[16] = ColChkFlags(CFv) +// vtable[17] = ColPenFlags(CFv) +// vtable[18] = ColChkByFlags(CFv) +// vtable[19] = ColPenByFlags(CFv) +// vtable[20] = PhysicsFlags(CFv) +xNPCBasic::xNPCBasic(S32 value) +{ + myNPCType = value; +} + +void xNPCBasic::Setup() +{ +} + +void xNPCBasic::Move(xScene* xscn, F32 dt, xEntFrame* frm) +{ +} + +S32 xNPCBasic::SysEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam, + xBase* toParamWidget, S32* handled) +{ + return 1; +} + +void xNPCBasic::DBG_PStatOn(en_npcperf stat) +{ +} + +void xNPCBasic::DBG_PStatCont(en_npcperf stat) +{ +} + +void xNPCBasic::PostInit() +{ +} + +void xNPCBasic::Render() +{ + xEntRender(this); +} + +void xPsyche::ImmTranOn() +{ + flg_psyche |= 1; +} + +void xPsyche::ImmTranOff() +{ + flg_psyche &= 0xfffffffe; +} + +S32 xPsyche::ImmTranIsOn() +{ + return flg_psyche & 1; +} + +S32 xPsyche::HasGoal(S32 goal) +{ + return FindGoal(goal) != NULL; +} + +U32 xSndIsPlaying(U32 assetID, U32 parid) +{ + return iSndIsPlaying(assetID, parid) & 0xff; +} diff --git a/src/SB/Game/zNMECommon.h b/src/SB/Game/zNMECommon.h index e69de29..ce42192 100644 --- a/src/SB/Game/zNMECommon.h +++ b/src/SB/Game/zNMECommon.h @@ -0,0 +1,654 @@ +#ifndef ZNPCTYPECOMMON_H +#define ZNPCTYPECOMMON_H + +#include "xNPCBasic.h" +#include "xDynAsset.h" +#include "xListItem.h" +#include "xEntDrive.h" +#include "xBehaveMgr.h" +#include "xEnt.h" +#include "xSFX.h" + +#include "zNPCSndTable.h" +#include "zMovePoint.h" +#include "zShrapnel.h" + +// DIRECTLY PORTED FROM BFBB + +typedef struct NPCMsg; + +enum en_npcparm +{ + NPC_PARM_NONE, + NPC_PARM_MOVERATE, + NPC_PARM_TURNRATE, + NPC_PARM_ACCEL, + NPC_PARM_DRIFT, + NPC_PARM_MASS, + NPC_PARM_TOSSGRAV, + NPC_PARM_TOSSELASTIC, + NPC_PARM_BND_ISBOX, + NPC_PARM_BND_CENTER, + NPC_PARM_BND_EXTENT, + NPC_PARM_HITPOINTS, + NPC_PARM_MODELSCALE, + NPC_PARM_DETECT_RAD, + NPC_PARM_DETECT_HYT, + NPC_PARM_DETECT_OFF, + NPC_PARM_ATTACK_RAD, + NPC_PARM_ATTACK_FOV, + NPC_PARM_SND_RAD, + NPC_PARM_TIMEFIDGET, + NPC_PARM_TIMEATTACK, + NPC_PARM_TIMESTUN, + NPC_PARM_TIMEALERT, + NPC_PARM_VTX_ATTACKBASE, + NPC_PARM_VTX_ATTACK, + NPC_PARM_VTX_ATTACK1, + NPC_PARM_VTX_ATTACK2, + NPC_PARM_VTX_ATTACK3, + NPC_PARM_VTX_ATTACK4, + NPC_PARM_VTX_EYEBALL, + NPC_PARM_VTX_DMGSMOKEA, + NPC_PARM_VTX_DMGSMOKEB, + NPC_PARM_VTX_DMGSMOKEC, + NPC_PARM_VTX_DMGFLAMEA, + NPC_PARM_VTX_DMGFLAMEB, + NPC_PARM_VTX_DMGFLAMEC, + NPC_PARM_VTX_PROPEL, + NPC_PARM_VTX_EXHAUST, + NPC_PARM_VTX_GEN01, + NPC_PARM_VTX_GEN02, + NPC_PARM_VTX_GEN03, + NPC_PARM_VTX_GEN04, + NPC_PARM_VTX_GEN05, + NPC_PARM_ATK_SIZE01, + NPC_PARM_ATK_FRAMES01, + NPC_PARM_ATK_FRAMES01A, + NPC_PARM_ATK_FRAMES01B, + NPC_PARM_ATK_FRAMES02, + NPC_PARM_ATK_FRAMES02A, + NPC_PARM_ATK_FRAMES02B, + NPC_PARM_ATK_FRAMES03, + NPC_PARM_ATK_FRAMES03A, + NPC_PARM_ATK_FRAMES03B, + NPC_PARM_ESTEEM_A, + NPC_PARM_ESTEEM_B, + NPC_PARM_ESTEEM_C, + NPC_PARM_ESTEEM_D, + NPC_PARM_ESTEEM_E, + NPC_PARM_SHADOW_CASTDIST, + NPC_PARM_SHADOW_RADCACHE, + NPC_PARM_SHADOW_RADRASTER, + NPC_PARAM_TEST_COUNT, + NPC_PARM_ENDTAG_INI, + NPC_PARM_FIRSTMVPT, + NPC_PARM_ENDTAG_PROPS, + NPC_PARM_BOGUSSHARE, + NPC_PARM_ENDTAG_SHARE, + NPC_PARM_NOMORE, + NPC_PARM_FORCEINT = 0x7fffffff +}; + +enum en_NPC_GOAL_SPOT +{ + NPC_GSPOT_START = 0x20, + NPC_GSPOT_RESUME, + NPC_GSPOT_FINISH, + NPC_GSPOT_STARTALT, + NPC_GSPOT_ALTA, + NPC_GSPOT_ALTB, + NPC_GSPOT_PATROLPAUSE, + NPC_GSPOT_NOMORE, + NPC_GSPOT_FORCEINT = 0x7fffffff +}; + +enum en_NPC_CARRY_STATE +{ + zNPCCARRY_NONE, + zNPCCARRY_PICKUP, + zNPCCARRY_THROW, + zNPCCARRY_ATTEMPTPICKUP, + zNPCCARRY_FORCEINT = 0x7fffffff +}; + +enum en_NPC_DAMAGE_TYPE +{ + DMGTYP_UNDECIDED, + DMGTYP_ABOVE, + DMGTYP_BELOW, + DMGTYP_SIDE, + DMGTYP_INSTAKILL, + DMGTYP_KILLEVENT, + DMGTYP_HITBYTOSS, + DMGTYP_NPCATTACK, + DMGTYP_ROPE, + DMGTYP_CRUISEBUBBLE, + DMGTYP_PROJECTILE, + DMGTYP_BOULDER, + DMGTYP_BUBBOWL, + DMGTYP_THUNDER_TIKI_EXPLOSION, + DMGTYP_DAMAGE_SURFACE, + DMGTYP_BUNGEED, + DMGTYP_SURFACE, + DMGTYP_NOMORE, + DMGTYP_FORCEINT = 0x7fffffff +}; + +enum en_npcvibe +{ + NPC_VIBE_SOFT, + NPC_VIBE_NORM, + NPC_VIBE_HARD, + NPC_VIBE_BUILD_A, + NPC_VIBE_BUILD_B, + NPC_VIBE_BUILD_C, + NPC_VIBE_NOMORE, + NPC_VIBE_FORCE = 0x7fffffff +}; + +struct xEntNPCAsset +{ + S32 npcFlags; + S32 npcModel; + S32 npcProps; + U32 movepoint; + U32 taskWidgetPrime; + U32 taskWidgetSecond; +}; + +enum en_npcbtyp +{ + NPCP_BASIS_NONE, + NPCP_BASIS_EVILROBOT, + NPCP_BASIS_FRIENDLYROBOT, + NPCP_BASIS_LOVINGCITIZEN, + NPCP_BASIS_GRUMPYCITIZEN, + NPCP_BASIS_NOMORE, + NPCP_BASIS_FORCE = 0x7fffffff +}; + +enum en_dupowavmod +{ + NPCP_DUPOWAVE_CONTINUOUS, + NPCP_DUPOWAVE_DISCREET, + NPCP_DUPOWAVE_NOMORE, + NPCP_DUPOWAVE_FORCE = 0x7fffffff +}; + +struct zNPCSettings : xDynAsset +{ + en_npcbtyp basisType; + S8 allowDetect; + U8 allowPatrol; + U8 allowWander; + U8 reduceCollide; + S8 useNavSplines; + S8 pad[3]; + S8 allowChase; + S8 allowAttack; + S8 assumeLOS; + S8 assumeFOV; + en_dupowavmod duploWaveMode; + F32 duploSpawnDelay; + S32 duploSpawnLifeMax; +}; + +struct NPCConfig : xListItem +{ + U32 modelID; + S32 flg_config; + F32 spd_turnMax; + F32 spd_moveMax; + F32 fac_accelMax; + F32 fac_driftMax; + F32 fac_gravKnock; + F32 fac_elastic; + S32 pts_damage; + S32 useBoxBound; + xVec3 off_bound; + xVec3 dim_bound; + F32 npcMass; + F32 npcMassInv; + F32 rad_detect; + F32 hyt_detect; + F32 off_detect; + F32 rad_attack; + F32 fov_attack; + xVec3 scl_model; + F32 tym_attack; + F32 tym_fidget; + F32 tym_stun; + F32 tym_alert; + F32 dst_castShadow; + F32 rad_shadowCache; + F32 rad_shadowRaster; + F32 rad_dmgSize; + S32 flg_vert; + xModelTag tag_vert[20]; + xVec3 animFrameRange[9]; + S32 cnt_esteem[5]; + F32 rad_sound; + NPCSndTrax* snd_trax; // 0x39C + NPCSndTrax* snd_traxShare; // 0x3A0 + S32 test_count; + U8 talk_filter[4]; + U8 talk_filter_size; +}; + +enum en_LASSO_STATUS +{ + LASS_STAT_DONE, + LASS_STAT_PENDING, + LASS_STAT_GRABBING, + LASS_STAT_TOSSING, + LASS_STAT_NOMORE, + LASS_STAT_UNK_5, // needed to match switch in zNPCCommon::LassoNotify, checks value of 5 + LASS_STAT_FORCEINT = 0x7fffffff +}; + +enum en_mdlvert +{ + NPC_MDLVERT_ATTACKBASE, + NPC_MDLVERT_ATTACK, + NPC_MDLVERT_ATTACK1, + NPC_MDLVERT_ATTACK2, + NPC_MDLVERT_ATTACK3, + NPC_MDLVERT_ATTACK4, + NPC_MDLVERT_LOSEYEBALL, + NPC_MDLVERT_DMGSMOKE_A, + NPC_MDLVERT_DMGSMOKE_B, + NPC_MDLVERT_DMGSMOKE_C, + NPC_MDLVERT_DMGFLAME_A, + NPC_MDLVERT_DMGFLAME_B, + NPC_MDLVERT_DMGFLAME_C, + NPC_MDLVERT_PROPEL, + NPC_MDLVERT_EXHAUST, + NPC_MDLVERT_GEN01, + NPC_MDLVERT_GEN02, + NPC_MDLVERT_GEN03, + NPC_MDLVERT_GEN04, + NPC_MDLVERT_GEN05, + NPC_MDLVERT_NOMORE, + NPC_MDLVERT_FORCEINT = 0x7fffffff +}; + +enum en_LASSO_EVENT +{ + LASS_EVNT_BEGIN, + LASS_EVNT_ENDED, + LASS_EVNT_GRABSTART, + LASS_EVNT_GRABEND, + LASS_EVNT_YANK, + LASS_EVNT_ABORT, + LASS_EVNT_NOMORE, + LASS_EVNT_FORCEINT = 0x7fffffff +}; + +enum en_NPC_MSG_ID +{ + NPC_MID_NONE, + NPC_MID_SYSEVENT, + NPC_MID_RESPAWN, + NPC_MID_DAMAGE, + NPC_MID_EXPLOSION, + NPC_MID_BUNNYHOP, + NPC_MID_DTRON_NPCEMIT, + NPC_MID_DTRON_NPCAVAIL, + NPC_MID_DTRON_ISDEAD, + NPC_MID_CHAT_REQUEST, + NPC_MID_CHAT_DECLINE, + NPC_MID_CHAT_ACCEPT, + NPC_MID_CHAT_DONE, + NPC_MID_CHAT_ABORT, + NPC_MID_TALKSTART, + NPC_MID_TALKON, + NPC_MID_TALKOFF, + NPC_MID_SAWPLYR, + NPC_MID_NEEDMEDIC, + NPC_MID_UNDERATTACK, + NPC_MID_NPCDIED, + NPC_MID_PLYRSPATULA, + NPC_MID_BECOMESCARED, + NPC_MID_NOLONGERSCARED, + NPC_MID_CELEBRATE, + NPC_MID_STUN, + NPC_MID_SCRIPTBEGIN, + NPC_MID_SCRIPTEND, + NPC_MID_SCRIPTHALT, + NPC_MID_DEV_ANIMSPIN, + NPC_MID_DEV_ANIMCYCLE, + NPC_MID_DEV_HEROMODE, + NPC_MID_DEV_DONE, + NPC_MID_NOMORE, + NPC_MID_FORCE = 0x7fffffff +}; + +enum en_NPC_MSG_DATA +{ + NPC_MDAT_BLANK, + NPC_MDAT_SYSEVENT, + NPC_MDAT_BLAST, + NPC_MDAT_CHAT, + NPC_MDAT_SPAWN, + NPC_MDAT_TARGET, + NPC_MDAT_DAMAGE, + NPC_MDAT_STUN, + NPC_MDAT_SCRIPT, + NPC_MDAT_MOUNT, + NPC_MDAT_AREANOTIFY, + NPC_MDAT_NOMORE, + NPC_MDAT_FORCE = 0x7fffffff +}; + +enum en_SM_NOTICES +{ + SM_NOTE_NPCDIED, + SM_NOTE_NPCSTANDBY, + SM_NOTE_NPCALIVE, + SM_NOTE_DUPPAUSE, + SM_NOTE_DUPRESUME, + SM_NOTE_DUPSETDELAY, + SM_NOTE_DUPDEAD, + SM_NOTE_KILLKIDS, + SM_NOTE_NOMORE, + SM_NOTE_FORCE = 0x7fffffff +}; + +struct zNPCLassoInfo +{ + en_LASSO_STATUS stage; + xEnt* lassoee; + xAnimState* holdGuideAnim; + xModelInstance* holdGuideModel; + xAnimState* grabGuideAnim; + xModelInstance* grabGuideModel; +}; + +struct zNPCCommon : xNPCBasic //Size of zNPCCommon: 0x2A0 +{ + xEntAsset* entass; // 0x1BC + xEntNPCAsset* npcass; // 0x1C0 + zNPCSettings* npcsetass; // 0x1C4 + S32 flg_vuln; // 0x1C8 + S32 flg_move; // 0x1CC + S32 flg_misc; // 0x1D0 + S32 flg_able; // 0x1D4 + NPCConfig* cfg_npc; // 0x1D8 + zNPCSettings npcset; // 0x1DC + zMovePoint* nav_past; // 0x208 + zMovePoint* nav_curr; // 0x20C + zMovePoint* nav_dest; // 0x210 + zMovePoint* nav_lead; + xSpline3* spl_mvptspline; + F32 len_mvptspline; + F32 dst_curspline; + xEntDrive* drv_data; + xPsyche* psy_instinct; // 0x228 + zNPCCommon* npc_duplodude; + F32 spd_throttle; //0x230 + S32 flg_xtrarend; + F32 tmr_fidget; //0x238 + F32 tmr_invuln; // 0x23C + zShrapnelAsset* explosion; // 0x240 + xModelAssetParam* parmdata; // 0x244 + U32 pdatsize; //0x248 + zNPCLassoInfo* lassdata; //0x24C + NPCSndQueue snd_queue[4]; //0x250 + + zNPCCommon(S32 myType); + + F32 TurnToFace(F32 dt, const xVec3* dir_want, F32 useTurnRate); + F32 ThrottleApply(F32 dt, const xVec3* dir, S32 force3D); + F32 ThrottleAccel(F32 dt, S32 speedup, F32 pct_max); + F32 ThrottleAdjust(F32 dt, F32 spd_want, F32 accel); + + F32 BoundAsRadius(int useCfg); + void VelStop(); + static void ConfigSceneDone(); + U32 LassoInit(); + zNPCLassoInfo* GimmeLassInfo(); + void AddDEVGoals(xPsyche*); + U32 DBG_Name(); // return type might be wrong + void DBG_AddTweakers(); + void DBG_RptDataSize(); + U32 DBG_InstName(); // return type might be wrong + xAnimTable* AnimGetTable(); + F32 AnimTimeRemain(xAnimState* ast); + F32 AnimTimeCurrent(); + F32 AnimDuration(xAnimState* ast); + bool IsMountableType(en_ZBASETYPE type); + void MvptReset(zMovePoint* nav_goto); + S32 MvptCycle(); + S32 HaveLOSToPos(xVec3*, float, xScene*, xBase*, xCollis*); + void ModelScaleSet(F32 x, F32 y, F32 z); + void ModelScaleSet(F32 unk); + void ModelScaleSet(const xVec3* vec); + xModelInstance* ModelAtomicFind(int index, int idx_prev, xModelInstance* mdl_prev); + xModelInstance* ModelAtomicHide(int index, xModelInstance* mdl); + xModelInstance* ModelAtomicShow(int index, xModelInstance* mdl); + S32 AnimStart(U32 animID, S32 forceRestart); + xAnimState* AnimFindState(U32 animID); + xAnimState* AnimCurState(); + xAnimSingle* AnimCurSingle(); + U32 AnimCurStateID(); + void GiveReward(); + S32 SndPlayFromSFX(xSFX* sfx, U32* sid_played); + S32 SndPlayRandom(en_NPC_SOUND sndtype); + S32 SndChanIsBusy(S32 flg_chan); + S32 LassoUseGuides(S32 idx_grabmdl, S32 idx_holdmdl); + S32 GetVertPos(en_mdlvert vid, xVec3* pos); + void Vibrate(en_npcvibe vibe, F32 duration); + void AddScripting(xPsyche* psy, S32 (*eval_script)(xGoal*, void*, en_trantype*, F32, void*), + S32 (*eval_playanim)(xGoal*, void*, en_trantype*, F32, void*), + S32 (*eval_attack)(xGoal*, void*, en_trantype*, F32, void*), + S32 (*eval_move)(xGoal*, void*, en_trantype*, F32, void*), + S32 (*eval_follow)(xGoal*, void*, en_trantype*, F32, void*), + S32 (*eval_lead)(xGoal*, void*, en_trantype*, F32, void*), + S32 (*eval_wait)(xGoal*, void*, en_trantype*, F32, void*)); + void AddBaseline(xPsyche*, int (*)(xGoal*, void*, en_trantype*, float, void*), + int (*)(xGoal*, void*, en_trantype*, float, void*), + int (*)(xGoal*, void*, en_trantype*, float, void*), + int (*)(xGoal*, void*, en_trantype*, float, void*), + int (*)(xGoal*, void*, en_trantype*, float, void*)); + + // defined from zNPCGoalRobo.cpp + xVec3* Center(); + xVec3* Pos(); + RwMatrix* BoneMat(S32 unk) const; + RwV3d* BonePos(S32 unk) const; + void XZVecToPlayer(xVec3* unk1, F32* unk2); + F32 XZDstSqToPos(const xVec3* unk1, xVec3* unk2, F32* unk3); + void XZVecToPos(xVec3* unk1, const xVec3* unk2, F32* unk3); + void XYZVecToPos(xVec3* dest, xVec3* unk2) + { + xVec3Sub(dest, unk2, Pos()); + } + F32 XYZDstSqToPlayer(xVec3* unk); + F32 XYZDstSqToPos(xVec3* unk1, xVec3* dest) + { + xVec3 dest_vec; + if (dest == NULL) + { + dest = &dest_vec; + } + XYZVecToPos(dest, unk1); + return xVec3Length2(dest); + } + void WonderOfTalking(S32 inprogress, xBase* owner); + // return type is probably wrong + S32 SomethingWonderful(); + S32 SndIsAnyPlaying(); + + // vTable (xNPCBasic) + + virtual void Init(xEntAsset* asset); + virtual void Reset(); + virtual void Setup(); + virtual void Process(xScene* xscn, F32 dt); + virtual void BUpdate(xVec3* pos); + virtual void NewTime(xScene* xscn, F32 dt); + virtual void Move(xScene* xscn, F32 dt, xEntFrame*); + virtual S32 SysEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam, + xBase* toParamWidget, S32* handled); + virtual void CollideReview(); + virtual void Destroy(); + + // vTable (zNPCCommon) + virtual S32 NPCMessage(NPCMsg* mail); + virtual void RenderExtra(); + virtual void RenderExtraPostParticles(); + virtual void ParseINI(); + virtual void ParseLinks(); + virtual void ParseProps(); + virtual void SelfSetup(); + virtual void SelfDestroy(); + virtual S32 IsHealthy(); + virtual S32 IsAlive(); + virtual void Damage(en_NPC_DAMAGE_TYPE damtype, xBase* who, const xVec3* vec_hit); + virtual S32 Respawn(const xVec3* pos, zMovePoint* mvptFirst, zMovePoint* mvptSpawnRef); + virtual void DuploOwner(zNPCCommon* duper); + virtual void DuploNotice(en_SM_NOTICES, void*); + virtual S32 CanRope(); + virtual void LassoNotify(en_LASSO_EVENT event); + virtual S32 SetCarryState(en_NPC_CARRY_STATE); + virtual void Stun(F32 stuntime); + virtual void SpeakBegin(); + virtual void SpeakEnd(); + virtual void SpeakStart(U32 sound, U32 param_2, S32 param_3); + virtual void SpeakStop(); + + virtual U32 AnimPick(S32 animID, en_NPC_GOAL_SPOT gspot, xGoal* goal) + { + return 0; + } + + virtual void GetParm(en_npcparm pid, void* val); + virtual void GetParmDefault(en_npcparm pid, void* val); + virtual F32 GenShadCacheRad(); + virtual xEntDrive* PRIV_GetDriverData(); + virtual zNPCLassoInfo* PRIV_GetLassoData(); + virtual S32 LassoSetup(); + +protected: + // This prevents implicit destructors from being generated in subclasses of zNPCCommon + ~zNPCCommon(); +}; + +struct NPCSysEvent +{ + S32 doLinkEvents; + S32 handled; + xBase* from; + xBase* to; + U32 toEvent; + F32 toParam[4]; + xBase* toParamWidget; +}; + +struct NPCBlastInfo +{ + xVec3 pos_blast; + F32 rad_blast; + F32 spd_expand; +}; + +struct NPCChatInfo +{ + xVec3 pos_chat; + F32 tym_chat; +}; + +struct NPCSpawnInfo +{ + xVec3 pos_spawn; + zMovePoint* nav_firstMovepoint; + zMovePoint* nav_spawnReference; + S32 spawnSuccess; +}; + +struct NPCTargetInfo +{ + xBase* bas_tgt; + xVec3 pos_tgt; +}; + +struct NPCDamageInfo +{ + en_NPC_DAMAGE_TYPE dmg_type; + xBase* dmg_from; + xVec3 vec_dmghit; +}; + +struct NPCStunInfo +{ + F32 tym_stuntime; + en_NPC_CARRY_STATE carrystate; + S32 allowStun; +}; + +struct NPCScriptInfo +{ + U32 aid_playanim; +}; + +struct NPCMountInfo +{ + xEnt* ent_toMount; + xCollis* col_forMount; +}; + +struct NPCAreaInfo +{ + zNPCCommon* npc_origin; + xVec3 pos_origin; +}; + +struct NPCMsg +{ + en_NPC_MSG_ID msgid; + U32 sendto; + U32 from; + en_NPC_MSG_DATA infotype; // 0xC + union + { + NPCSysEvent sysevent; + NPCBlastInfo blastarea; + NPCChatInfo chatter; + NPCSpawnInfo spawning; + NPCTargetInfo target; + NPCDamageInfo dmgdata; // 0x10 + NPCStunInfo stundata; + NPCScriptInfo scriptdata; + NPCMountInfo mountdata; + NPCAreaInfo areadata; + }; + void* attached; // 0x38 + NPCMsg* next; + F32 tmr_delay; // 0x40 +}; + +xFactoryInst* ZNPC_Create_Common(S32 who, RyzMemGrow* grow, void*); +void ZNPC_Destroy_Common(xFactoryInst* inst); +void zNPCCommon_ScenePrepare(); +void zNPCCommon_ScenePostInit(); +void zNPCCommon_SceneFinish(); +void zNPCPlyrSnd_Reset(); +void zNPCPlyrSnd_Update(F32 dt); +void zNPCCommon_SceneReset(); +void ZNPC_Destroy_Common(xFactoryInst* inst); +void zNPCSettings_MakeDummy(); +void ZNPC_Common_Startup(); +void zNPCCommon_WonderReset(); +void ZNPC_Common_Shutdown(); +void NPCC_BuildStandardAnimTran(xAnimTable* table, char** namelist, S32* ourAnims, S32 idx_dflt, + F32 blend); +void zNPCCommon_Timestep(xScene* xscn, F32 dt); + +xAnimTable* ZNPC_AnimTable_Common(); +xAnimTable* ZNPC_AnimTable_LassoGuide(); +S32 NPCC_NPCIsConversing(); +void zNPCCommon_EjectPhlemOnPawz(); +U32 xSndIsPlaying(U32 assetID, U32 parid); + +#endif diff --git a/src/SB/Game/zNPCSndTable.cpp b/src/SB/Game/zNPCSndTable.cpp new file mode 100644 index 0000000..846fd8b --- /dev/null +++ b/src/SB/Game/zNPCSndTable.cpp @@ -0,0 +1,62 @@ +#include "zNPCSndTable.h" +#include "zNPCGoalVillager.h" + +#include "xString.h" + +#include + +static char* g_strz_sndgroup[26]; +static unsigned int g_hash_sndgroup[26]; +static float g_tmrz_sndplay[26]; + +NPCSndProp g_sndProps[]; + +void NPCS_Startup() +{ + for (int i = 0; i < (int)(sizeof(g_strz_sndgroup) / sizeof(char*)); i++) + { + g_hash_sndgroup[i] = xStrHash(g_strz_sndgroup[i]); + } +} + +void NPCS_Shutdown() +{ +} + +int NPCS_SndOkToPlay(en_NPC_SOUND sndtype) +{ + if (sndtype == NPC_STYP_BOGUS) + { + return 1; + } + if (sndtype == NPC_STYP_LISTEND) + { + return 0; + } + return g_tmrz_sndplay[sndtype] < 0.0f; +} + +void NPCS_SndTypePlayed(en_NPC_SOUND sndtype, float delayNext) +{ + float tym = 2.0f; + + switch (sndtype) + { + case NPC_STYP_TIKISTACK: + tym = 0.15f; + break; + case NPC_STYP_TIKIEXPLODE: + tym = 2.0f; + break; + default: + tym = -1.0f; + break; + } + + if (delayNext > 0.0f) + { + tym = delayNext; + } + + g_tmrz_sndplay[sndtype] = tym; +} diff --git a/src/SB/Game/zNPCSndTable.h b/src/SB/Game/zNPCSndTable.h new file mode 100644 index 0000000..717d416 --- /dev/null +++ b/src/SB/Game/zNPCSndTable.h @@ -0,0 +1,61 @@ +#ifndef ZNPCSNDTABLE_H +#define ZNPCSNDTABLE_H + +#include + +enum en_NPC_SOUND +{ + NPC_STYP_BOGUS = -2, + NPC_STYP_LISTEND = 0, + NPC_STYP_ENCOUNTER, + NPC_STYP_CLANKING, + NPC_STYP_EXCLAIM, + NPC_STYP_OUCH, + NPC_STYP_CHEERING, + NPC_STYP_RESPAWN, + NPC_STYP_ALERT, + NPC_STYP_DIZZY, + NPC_STYP_DANCE, + NPC_STYP_LAUGH, + NPC_STYP_ATTACK, + NPC_STYP_PUNCH, + NPC_STYP_WEPLAUNCH, + NPC_STYP_LIGHTNING, + NPC_STYP_WARNBANG, + NPC_STYP_DEATH, + NPC_STYP_DEATHJELLY, + NPC_STYP_BONKED, + NPC_STYP_UNBONKED, + NPC_STYP_TIKISTACK, + NPC_STYP_TIKIEXPLODE, + NPC_STYP_TIKITHUNDER, + NPC_STYP_XSFXTALK, + NPC_STYP_ONELINER, + NPC_STYP_ONELINERTOO, + NPC_STYP_NOMORE, + NPC_STYP_FORCE = 0x7fffffff +}; + +struct NPCSndTrax +{ + en_NPC_SOUND typ_sound; + char* nam_sound; + U32 aid_sound; +}; + +struct NPCSndQueue //0x14 +{ + U32 sndDirect; //0x0 + en_NPC_SOUND sndtype; //0x4 + S32 flg_snd; //0x8 + F32 tmr_delay; //0xC + F32 radius; //0x10 +}; + +void NPCS_Startup(); +void NPCS_SndTimersReset(); +void NPCS_SndTimersUpdate(F32 dt); +void NPCS_SndTablePrepare(NPCSndTrax* trax); +void NPCS_Shutdown(); + +#endif diff --git a/src/SB/Game/zParEmitter.cpp b/src/SB/Game/zParEmitter.cpp new file mode 100644 index 0000000..4142917 --- /dev/null +++ b/src/SB/Game/zParEmitter.cpp @@ -0,0 +1,35 @@ +#include "zParEmitter.h" + +#include +#include "zBase.h" +#include "zGlobals.h" +#include "xString.h" + +zParEmitter* zParEmitterFind(U32 asset_id) +{ + zScene* s = globals.sceneCur; + + if (s == NULL) + { + return NULL; + } + + zParEmitter* pe = (zParEmitter*)s->baseList[eBaseTypeParticleEmitter]; + + for (S32 i = s->baseCount[eBaseTypeParticleEmitter]; i > 0; i--) + { + if (pe->tasset->id == asset_id) + { + return pe; + } + pe++; + } + + return NULL; +} + +zParEmitter* zParEmitterFind(const char* asset_name) +{ + U32 asset_id = xStrHash(asset_name); + return zParEmitterFind(asset_id); +} diff --git a/src/SB/Game/zParEmitter.h b/src/SB/Game/zParEmitter.h new file mode 100644 index 0000000..2dce49f --- /dev/null +++ b/src/SB/Game/zParEmitter.h @@ -0,0 +1,14 @@ +#ifndef ZPAREMITTER_H +#define ZPAREMITTER_H + +#include +#include "xParEmitter.h" + +struct zParEmitter : xParEmitter +{ +}; + +zParEmitter* zParEmitterFind(U32 asset_id); +zParEmitter* zParEmitterFind(const char* asset_name); + +#endif diff --git a/src/SB/Game/zPortal.cpp b/src/SB/Game/zPortal.cpp new file mode 100644 index 0000000..8ac82da --- /dev/null +++ b/src/SB/Game/zPortal.cpp @@ -0,0 +1,62 @@ +#include "xBase.h" +#include "xEvent.h" + +#include "zPortal.h" +#include "zGlobals.h" +#include "zScene.h" + +extern zGlobals globals; + +void zPortalInit(void* portal, void* passet) +{ + zPortalInit((_zPortal*)portal, (xPortalAsset*)passet); +} + +void zPortalInit(_zPortal* portal, xPortalAsset* passet) +{ + xBaseInit((xBase*)portal, (xBaseAsset*)passet); + + portal->passet = passet; + portal->eventFunc = (xBaseEventCB)zPortalEventCB; + + if (portal->linkCount != 0) + { + portal->link = (xLinkAsset*)(portal->passet + 1); + } +} + +void zPortalReset(_zPortal* portal) +{ + xBaseReset((xBase*)portal, (xBaseAsset*)portal->passet); +} + +void zPortalSave(_zPortal* ent, xSerial* s) +{ + xBaseSave((xBase*)ent, s); +} + +void zPortalLoad(_zPortal* ent, xSerial* s) +{ + xBaseLoad((xBase*)ent, s); +} + +S32 zPortalEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* b3) +{ + switch (toEvent) + { + case eEventReset: + { + zPortalReset((_zPortal*)to); + break; + } + case eEventTeleportPlayer: + { + if (globals.player.Health != 0) + { + zSceneSwitch((_zPortal*)to, false); + } + break; + } + } + return eEventEnable; +} diff --git a/src/SB/Game/zPortal.h b/src/SB/Game/zPortal.h new file mode 100644 index 0000000..8fe600e --- /dev/null +++ b/src/SB/Game/zPortal.h @@ -0,0 +1,25 @@ +#ifndef ZPORTAL_H +#define ZPORTAL_H + +#include "xBase.h" + +struct xPortalAsset : xBaseAsset +{ + U32 assetCameraID; + U32 assetMarkerID; + F32 ang; + U32 sceneID; +}; + +struct _zPortal : xBase +{ + xPortalAsset* passet; +}; + +void zPortalInit(void* portal, void* passet); +void zPortalInit(_zPortal* portal, xPortalAsset* passet); +void zPortalSave(_zPortal* ent, xSerial* s); +void zPortalLoad(_zPortal* ent, xSerial* s); +S32 zPortalEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* b3); + +#endif diff --git a/src/SB/Game/zScene.cpp b/src/SB/Game/zScene.cpp new file mode 100644 index 0000000..5a9b789 --- /dev/null +++ b/src/SB/Game/zScene.cpp @@ -0,0 +1,3586 @@ +#include "zScene.h" + +#include "zEntTrigger.h" +#include "zMovePoint.h" +#include "zEntPickup.h" +#include "zEntSimpleObj.h" +#include "zPlatform.h" +#include "zPendulum.h" +#include "zEntHangable.h" +#include "zEntDestructObj.h" +#include "zEntButton.h" +#include "zPortal.h" +#include "zCamMarker.h" +#include "zGust.h" +#include "zVolume.h" +#include "zConditional.h" +#include "zEnv.h" +#include "zUI.h" +#include "zUIFont.h" +#include "zLight.h" +#include "zCutsceneMgr.h" +#include "zEGenerator.h" +#include "zScript.h" +#include "zDiscoFloor.h" +#include "zEntTeleportBox.h" +#include "zBusStop.h" +#include "zTextBox.h" +#include "zTalkBox.h" +#include "zTaskBox.h" +#include "zTaxi.h" +#include "zEntPlayerBungeeState.h" +#include "zCameraFly.h" +#include "zCameraTweak.h" +#include "zNPCMgr.h" +#include "zGlobals.h" +#include "zDispatcher.h" +#include "zThrown.h" +#include "zGrid.h" +#include "zFX.h" +#include "zSurface.h" +#include "zGoo.h" +#include "zParPTank.h" +#include "zAnimList.h" +#include "zParSys.h" +#include "zRenderState.h" +#include "zGame.h" +#include "zNPCGlyph.h" +#include "zNPCHazard.h" +#include "zEntPlayerOOBState.h" +#include "zActionLine.h" +#include "zGameState.h" +#include "zEntCruiseBubble.h" +#include "zHud.h" +#include "zMenu.h" +#include "zNPCTypeBossSandy.h" +#include "zNPCTypeBossPatrick.h" +#include "zCombo.h" +#include "zLOD.h" +#include "zMusic.h" +#include "zNPCTypeTiki.h" +#include "zGameExtras.h" +#include "zCollGeom.h" +#include "zFeet.h" +#include "zParCmd.h" +#include "zAssetTypes.h" + +#include "xNPCBasic.h" +#include "xString.h" +#include "xstransvc.h" +#include "xDynAsset.h" +#include "xParSys.h" +#include "xParEmitter.h" +#include "xEntBoulder.h" +#include "xTimer.h" +#include "xCounter.h" +#include "xSFX.h" +#include "xGroup.h" +#include "xSurface.h" +#include "xFog.h" +#include "xHudModel.h" +#include "xHudFontMeter.h" +#include "xHudUnitMeter.h" +#include "xHudText.h" +#include "iModel.h" +#include "xutil.h" +#include "xModelBucket.h" +#include "xFX.h" +#include "xDecal.h" +#include "xPtankPool.h" +#include "xSystem.h" +#include "xSkyDome.h" +#include "xShadow.h" +#include "xParMgr.h" +#include "xScrFx.h" +#include "xTRC.h" +#include "xCM.h" +#include "xMath.h" +#include "iMath.h" +#include "xMarkerAsset.h" +#include "xPartition.h" +#include "xMathInlines.h" + +#include +#include + +U8 HACK_BASETYPE; +static S32 bytesNeeded; +static S32 availOnDisk; +static S32 neededFiles; +static F32 offsetx; +static F32 offsety; +static U32 enableScreenAdj; +volatile static F32 oldOffsetx; +volatile static F32 oldOffsety; +static S32 sMemDepthSceneStart = -1; +static S32 sMemDepthJustHIPStart = -1; +_zEnv* gCurEnv; +U32 gTransitionSceneID; +F32 gSceneUpdateTime; +static xVec3 sOldPosPlayer; +static xVec3 sOldPosCamera; +static U32 sSuddenMove; + +struct zSceneLevel +{ + const char* desc; + const char* prefix; +}; + +// clang-format off +static zSceneLevel sLevelTable[] = +{ + { "Bikini Bottom", "HB" }, + { "Jellyfish Fields", "JF"} , + { "Downtown Bikini Bottom", "BB" }, + { "Goo Lagoon", "GL" }, + { "Poseidome", "B1" }, + { "Rock Bottom", "RB" }, + { "Mermalair", "BC" }, + { "Sand Mountain", "SM" }, + { "Industrial Park", "B2" }, + { "Kelp Forest", "KF" }, + { "Flying Dutchman's Graveyard", "GY" }, + { "Spongebob's Dream", "DB" }, + { "Chum Bucket Lab", "B3" }, + { "PLAYGROUND", "PG" }, + { "Start", "MN" } +}; +// clang-format on + +struct zSceneObjectInstanceDesc +{ + const char* name; + S32 baseType; + U32 assetType; + U32 sizeRuntime; + U32 (*func)(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); + void (*objectInitFunc)(void* ent, void* asset); + U32 (*querySubObjects)(void*); +}; + +static U32 zSceneInitFunc_DefaultEnt(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); +static U32 zSceneInitFunc_Default(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); +static U32 zSceneInitFunc_MovePoint(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); +static U32 zSceneInitFunc_SBNPC(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); +static U32 zSceneInitFunc_Player(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); +static U32 zSceneInitFunc_Camera(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); +static U32 zSceneInitFunc_Surface(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); +static U32 zSceneInitFunc_Gust(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); +static U32 zSceneInitFunc_Volume(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); +static U32 zSceneInitFunc_LobMaster(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); +static U32 zSceneInitFunc_Dispatcher(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx); + +// clang-format off +static zSceneObjectInstanceDesc sInitTable[] = +{ + { "Trig", eBaseTypeTrigger, 'TRIG', sizeof(zEntTrigger), zSceneInitFunc_DefaultEnt, zEntTriggerInit, NULL }, + { "Move Point", eBaseTypeMovePoint, 'MVPT', sizeof(zMovePoint), zSceneInitFunc_MovePoint, NULL, NULL }, + { "Pickup", eBaseTypePickup, 'PKUP', sizeof(zEntPickup), zSceneInitFunc_DefaultEnt, zEntPickupInit, NULL }, + { "Simple", eBaseTypeStatic, 'SIMP', sizeof(zEntSimpleObj), zSceneInitFunc_DefaultEnt, zEntSimpleObj_Init, NULL }, + { "ParticleSystem", eBaseTypeParticleSystem, 'PARS', sizeof(xParSys), zSceneInitFunc_Default, xParSysInit, NULL }, + { "ParticleEmitter", eBaseTypeParticleEmitter, 'PARE', sizeof(xParEmitter), zSceneInitFunc_Default, xParEmitterInit, NULL }, + { "Track", eBaseTypeTrackPhysics, 'TRCK', sizeof(zEntSimpleObj), zSceneInitFunc_DefaultEnt, zEntTrackPhysics_Init, NULL }, + { "Platform", eBaseTypePlatform, 'PLAT', sizeof(zPlatform), zSceneInitFunc_DefaultEnt, zPlatform_Init, NULL }, + { "Pendulum", eBaseTypePendulum, 'PEND', sizeof(_zPendulum), zSceneInitFunc_DefaultEnt, zPendulum_Init, NULL }, + { "Hanger", eBaseTypeHangable, 'HANG', sizeof(zEntHangable), zSceneInitFunc_DefaultEnt, zEntHangable_Init, NULL }, + { "DestructObj", eBaseTypeDestructObj, 'DSTR', sizeof(zEntDestructObj), zSceneInitFunc_DefaultEnt, zEntDestructObj_Init, NULL }, + { "Boulder", eBaseTypeBoulder, 'BOUL', sizeof(xEntBoulder), zSceneInitFunc_DefaultEnt, xEntBoulder_Init, NULL }, + { "NPC", eBaseTypeNPC, 'VIL ', 0, zSceneInitFunc_SBNPC, NULL, NULL }, + { "Button", eBaseTypeButton, 'BUTN', sizeof(_zEntButton), zSceneInitFunc_DefaultEnt, zEntButton_Init, NULL }, + { "Player", eBaseTypePlayer, 'PLYR', sizeof(zEnt), zSceneInitFunc_Player, NULL, NULL }, + { "Timer", eBaseTypeTimer, 'TIMR', sizeof(xTimer), zSceneInitFunc_Default, xTimerInit, NULL }, + { "Counter", eBaseTypeCounter, 'CNTR', sizeof(_xCounter), zSceneInitFunc_Default, xCounterInit, NULL }, + { "SFX", eBaseTypeSFX, 'SFX ', sizeof(xSFX), zSceneInitFunc_Default, xSFXInit, NULL }, + { "Group", eBaseTypeGroup, 'GRUP', sizeof(xGroup), zSceneInitFunc_Default, xGroupInit, NULL }, + { "Portal", eBaseTypePortal, 'PORT', sizeof(_zPortal), zSceneInitFunc_Default, zPortalInit, NULL }, + { "Camera", eBaseTypeCamera, 'CAM ', sizeof(zCamMarker), zSceneInitFunc_Camera, NULL, NULL }, + { "Surface", eBaseTypeSurface, 'SURF', sizeof(xSurface), zSceneInitFunc_Surface, NULL, NULL }, + { "Gust", eBaseTypeGust, 'GUST', sizeof(zGust), zSceneInitFunc_Gust, NULL, NULL }, + { "Volume", eBaseTypeVolume, 'VOLU', sizeof(zVolume), zSceneInitFunc_Volume, NULL, NULL }, + { "Conditional", eBaseTypeCond, 'COND', sizeof(_zConditional), zSceneInitFunc_Default, zConditionalInit, NULL }, + { "Lob Master", eBaseTypeLobMaster, 'LOBM', 0, zSceneInitFunc_LobMaster, NULL, NULL }, + { "Env", eBaseTypeEnv, 'ENV ', sizeof(_zEnv), zSceneInitFunc_Default, zEnvInit, NULL }, + { "Dispatcher", eBaseTypeDispatcher, 'DPAT', 0, zSceneInitFunc_Dispatcher, NULL, NULL }, + { "UI", eBaseTypeUI, 'UI ', sizeof(_zUI), zSceneInitFunc_DefaultEnt, zUI_Init, NULL }, + { "UI Font", eBaseTypeUIFont, 'UIFT', sizeof(zUIFont), zSceneInitFunc_Default, zUIFont_Init, NULL }, + { "Fog", eBaseTypeFog, 'FOG ', sizeof(_xFog), zSceneInitFunc_Default, xFogInit, NULL }, + { "Light", eBaseTypeLight, 'LITE', sizeof(_zLight), zSceneInitFunc_Default, zLightInit, NULL }, + { "CutSceneMgr", eBaseTypeCutsceneMgr, 'CSNM', sizeof(zCutsceneMgr), zSceneInitFunc_Default, zCutsceneMgrInit, NULL }, + { "EGenerator", eBaseTypeEGenerator, 'EGEN', sizeof(zEGenerator), zSceneInitFunc_DefaultEnt, zEGenerator_Init, NULL }, + { "Script", eBaseTypeScript, 'SCRP', sizeof(_zScript), zSceneInitFunc_Default, zScriptInit, NULL }, + { "Disco Floor", eBaseTypeDiscoFloor, 'DSCO', sizeof(z_disco_floor), zSceneInitFunc_Default, z_disco_floor::init, NULL }, + { NULL } +}; +// clang-format on + +extern U32 _1251; +extern char byte_803D0884; +extern U32 _2014; + +extern U32 _1250; +extern F32 _1373; +extern F32 _1374; +extern F32 _1375; +extern F32 _1493; +extern F32 _1494; +extern F32 _1495; +extern F32 _1496_0; +extern U32 _2013; +extern F32 _2094; +extern F32 _2095_0; +extern F32 _2096_0; +extern F32 _2097_0; +extern F32 _2242; + +static void zSceneObjHashtableInit(S32 count); +static void zSceneObjHashtableExit(); +static S32 zSceneObjHashtableUsage(); +static void zSceneObjHashtableAdd(U32 id, xBase* base); +static xBase* zSceneObjHashtableGet(U32 id); +static xBase* zSceneExitSoundIteratorCB(xBase* b, zScene*, void*); +static void zSceneAutoSave(); + +namespace +{ + struct dynamic_type_data + { + const char* name; + S32 type; + size_t size; + bool is_ent; + void (*load)(xBase& data, xDynAsset& asset, size_t size); + }; + + extern const dynamic_type_data dynamic_types[14]; + + // clang-format off + const dynamic_type_data dynamic_types[] = + { + { "game_object:Teleport", eBaseTypeTeleportBox, sizeof(_zEntTeleportBox), true, zEntTeleportBox_Init }, + { "game_object:BusStop", eBaseTypeBusStop, sizeof(zBusStop), false, zBusStop_Init }, + { "game_object:text_box", eBaseTypeTextBox, sizeof(ztextbox), false, ztextbox::load }, + { "game_object:talk_box", eBaseTypeTalkBox, sizeof(ztalkbox), false, ztalkbox::load }, + { "game_object:task_box", eBaseTypeTaskBox, sizeof(ztaskbox), false, ztaskbox::load }, + { "game_object:BoulderGenerator", eBaseTypeBoulderGenerator, sizeof(xBoulderGenerator), false, xBoulderGenerator_Init }, + { "game_object:Taxi", eBaseTypeTaxi, sizeof(zTaxi), false, zTaxi_Init }, + { "hud:model", eBaseTypeHUD_model, sizeof(xBase) + sizeof(xhud::model_widget), false, xhud::model_widget::load }, + { "hud:meter:font", eBaseTypeHUD_font_meter, sizeof(xBase) + sizeof(xhud::font_meter_widget), false, xhud::font_meter_widget::load }, + { "hud:meter:unit", eBaseTypeHUD_unit_meter, sizeof(xBase) + sizeof(xhud::unit_meter_widget), false, xhud::unit_meter_widget::load }, + { "hud:text", eBaseTypeHUD_text, sizeof(xBase) + sizeof(xhud::text_widget), false, xhud::text_widget::load }, + { "game_object:bungee_hook", eBaseTypeBungeeHook, sizeof(bungee_state::hook_type), false, bungee_state::load }, + { "game_object:Flythrough", eBaseTypeCameraFly, sizeof(zCameraFly), false, zCameraFly_Init }, + { "game_object:Camera_Tweak", eBaseTypeCameraTweak, sizeof(zCameraTweak), false, zCameraTweak_Init } + }; + // clang-format on + + S32 count_dynamic_types(const char* name) + { + U32 type = xStrHash(name); + S32 dynaCount = xSTAssetCountByType('DYNA'); + S32 count = 0; + + for (S32 i = 0; i < dynaCount; i++) + { + U32 size; + xDynAsset* asset = (xDynAsset*)xSTFindAssetByType('DYNA', i, &size); + + if (asset && asset->type == type) + { + count++; + } + } + + return count; + } + + void add_dynamic_types(zScene& s) + { + for (S32 i = 0; i < sizeof(dynamic_types) / sizeof(dynamic_types[0]); i++) + { + S32 count = count_dynamic_types(dynamic_types[i].name); + + s.baseCount[dynamic_types[i].type] = count; + s.num_base += count; + } + } + + U32 init_dynamic_type(zScene& s, U32 index, const dynamic_type_data& d) + { + U32 count, type; + S32 dyn_size, i, cnt; + + s.baseList[d.type] = NULL; + + if (s.baseCount[d.type] == 0) + { + return index; + } + + if (d.size) + { + dyn_size = s.baseCount[d.type] * d.size; + s.baseList[d.type] = (xBase*)xMemAllocSize(dyn_size); + } + + type = xStrHash(d.name); + count = xSTAssetCountByType('DYNA'); + + for (i = 0, cnt = 0; i < (S32)count; i++) + { + U32 asset_size; + xDynAsset* a; + xBase* b; + + a = (xDynAsset*)xSTFindAssetByType('DYNA', i, &asset_size); + + if (a && a->type == type) + { + a->baseType = d.type; + + xSTAssetName(a); + + b = (xBase*)((U8*)s.baseList[d.type] + cnt * d.size); + + zSceneSet(b, index); + + if (d.load) + { + d.load(*b, *a, asset_size); + } + + if (d.is_ent) + { + xSceneAddEnt(&s, s.ents[index]); + } + + zSceneObjHashtableAdd(b->id, b); + + index++; + cnt++; + } + } + + return index; + } + + U32 init_dynamic_types(zScene& s, U32 index) + { + for (S32 i = 0; i < sizeof(dynamic_types) / sizeof(dynamic_types[0]); i++) + { + if (dynamic_types[i].load) + { + index = init_dynamic_type(s, index, dynamic_types[i]); + } + } + + return index; + } +} // namespace + +struct IDBasePair +{ + U32 id; + xBase* base; +}; + +static IDBasePair* scobj_idbps; +static S32 scobj_size = -1; +static S32 nidbps = -1; + +static U32 zSceneInitFunc_DefaultEnt(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + U8* block; + S32 count; + U32 assetSize, offset; + xBase* b; + + block = NULL; + assetSize = 0; + offset = desc->sizeRuntime; + count = s->baseCount[desc->baseType]; + + if (count) + { + block = (U8*)xMemAllocSize(count * offset); + + s->baseList[desc->baseType] = (xBase*)block; + } + + for (S32 i = 0; i < count; i++) + { + void* asset = xSTFindAssetByType(desc->assetType, i, &assetSize); + b = (xBase*)(block + i * offset); + + zSceneSet(b, base_idx); + + if (desc->objectInitFunc) + { + desc->objectInitFunc(b, asset); + } + + xSceneAddEnt(s, s->ents[base_idx]); + zSceneObjHashtableAdd(b->id, b); + + base_idx++; + } + + return base_idx; +} + +static U32 zSceneInitFunc_Default(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + U8* block; + S32 count; + U32 assetSize, offset; + xBase* b; + + block = NULL; + assetSize = 0; + offset = desc->sizeRuntime; + count = s->baseCount[desc->baseType]; + + if (count) + { + block = (U8*)xMemAllocSize(count * offset); + + s->baseList[desc->baseType] = (xBase*)block; + } + + for (S32 i = 0; i < count; i++) + { + void* asset = xSTFindAssetByType(desc->assetType, i, &assetSize); + b = (xBase*)(block + i * offset); + + zSceneSet(b, base_idx); + + if (desc->objectInitFunc) + { + desc->objectInitFunc(b, asset); + } + + zSceneObjHashtableAdd(b->id, b); + + base_idx++; + } + + return base_idx; +} + +static U32 zSceneInitFunc_MovePoint(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + S32 count; + U32 assetSize; + zMovePoint* movpBlock; + + assetSize = 0; + count = s->baseCount[desc->baseType]; + movpBlock = zMovePoint_GetMemPool(count); + + if (movpBlock) + { + s->baseList[desc->baseType] = movpBlock; + + for (S32 idx = 0; idx < count; idx++) + { + xBase* b = zMovePoint_GetInst(idx); + xBaseAsset* basset = (xBaseAsset*)xSTFindAssetByType('MVPT', idx, &assetSize); + + zSceneSet(b, base_idx); + zMovePointInit(zMovePoint_GetInst(idx), (xMovePointAsset*)basset); + zSceneObjHashtableAdd(b->id, b); + + base_idx++; + } + } + + return base_idx; +} + +static U32 zSceneInitFunc_SBNPC(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + S32 count; + + count = s->baseCount[desc->baseType]; + + if (count == 0) + { + return base_idx; + } + + s->baseList[desc->baseType] = NULL; + + for (S32 i = 0; i < count; i++) + { + xEnt* ent; + xEntAsset* assdat; + + assdat = (xEntAsset*)xSTFindAssetByType('VIL ', i, NULL); + ent = zNPCMgr_createNPCInst(i, assdat); + + zSceneSet(ent, base_idx); + xSceneAddEnt(s, s->ents[base_idx]); + zSceneObjHashtableAdd(ent->id, ent); + + base_idx++; + } + + return base_idx; +} + +static U32 zSceneInitFunc_Player(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + S32 count; + zEnt* entBlock; + + count = s->baseCount[desc->baseType]; + + if (count) + { + entBlock = (zEnt*)xMemAllocSize(count * sizeof(zEnt)); + + s->baseList[desc->baseType] = entBlock; + + for (S32 idx = 0; idx < count; idx++) + { + xBase* b = &globals.player.ent; + xEntAsset* asset; + + zSceneSet(b, base_idx); + + if (idx == count - 1) + { + xSceneAddEnt(s, s->ents[base_idx]); + } + + asset = (xEntAsset*)xSTFindAssetByType('PLYR', idx, NULL); + + globals.player.ent.id = asset->id; + + zSceneObjHashtableAdd(asset->id, b); + + base_idx++; + } + } + + return base_idx; +} + +static U32 zSceneInitFunc_Camera(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + S32 count; + zCamMarker* camBlock; + + count = s->baseCount[desc->baseType]; + + if (count) + { + camBlock = (zCamMarker*)xMemAllocSize(count * sizeof(zCamMarker)); + s->baseList[desc->baseType] = camBlock; + + for (S32 idx = 0; idx < count; idx++) + { + xBase* b = &camBlock[idx]; + xCamAsset* assetCam = (xCamAsset*)xSTFindAssetByType('CAM ', idx, NULL); + + zSceneSet(b, base_idx); + zCamMarkerInit(b, assetCam); + zSceneObjHashtableAdd(b->id, b); + + base_idx++; + } + } + + return base_idx; +} + +static U32 zSceneInitFunc_Surface(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + S32 count; + + count = s->baseCount[desc->baseType]; + + if (count) + { + s->baseList[desc->baseType] = xSurfaceGetByIdx(0); + + for (S32 idx = 0; idx < count; idx++) + { + xBase* b = xSurfaceGetByIdx(idx); + + zSceneSet(b, base_idx); + zSceneObjHashtableAdd(b->id, b); + + base_idx++; + } + } + + return base_idx; +} + +static U32 zSceneInitFunc_Gust(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + S32 count; + + count = s->baseCount[desc->baseType]; + + zGustInit(); + + if (count) + { + s->baseList[desc->baseType] = zGustGetGust(0); + + for (S32 idx = 0; idx < count; idx++) + { + xBase* b = zGustGetGust(idx); + + zSceneSet(b, base_idx); + zSceneObjHashtableAdd(b->id, b); + + base_idx++; + } + } + + return base_idx; +} + +static U32 zSceneInitFunc_Volume(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + S32 count; + + count = s->baseCount[desc->baseType]; + + zVolumeInit(); + + if (count) + { + s->baseList[desc->baseType] = zVolumeGetVolume(0); + + for (S32 idx = 0; idx < count; idx++) + { + xBase* b = zVolumeGetVolume(idx); + + zLightSetVolume((zVolume*)b); + + zSceneSet(b, base_idx); + zSceneObjHashtableAdd(b->id, b); + + base_idx++; + } + } + + return base_idx; +} + +static U32 zSceneInitFunc_LobMaster(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + return base_idx; +} + +static U32 zSceneInitFunc_Dispatcher(zScene* s, zSceneObjectInstanceDesc* desc, U32 base_idx) +{ + S32 count; + + count = s->baseCount[desc->baseType]; + + if (count) + { + st_ZDISPATCH_DATA* dpat_pool = zDispatcher_memPool(count); + s->baseList[desc->baseType] = dpat_pool; + + for (S32 idx = 0; idx < count; idx++) + { + xBase* b = zDispatcher_getInst(dpat_pool, idx); + xEntAsset* asset = (xEntAsset*)xSTFindAssetByType('DPAT', idx, NULL); + + zSceneSet(b, base_idx); + zDispatcher_Init((st_ZDISPATCH_DATA*)b, asset); + zSceneObjHashtableAdd(b->id, b); + + base_idx++; + } + } + + return base_idx; +} + +void zSceneSet(xBase* b, U32 index) +{ + globals.sceneCur->base[index] = b; +} + +static void PipeCountStuffCB(RpAtomic*, U32 pipeFlags, U32) +{ + if (pipeFlags) + { + xModelLookupCount++; + } +} + +static void PipeAddStuffCB(RpAtomic* data, U32 pipeFlags, U32) +{ + if (pipeFlags) + { + xModelLookupList[xModelLookupCount].model = data; + xModelLookupList[xModelLookupCount].PipeFlags = pipeFlags; + xModelLookupCount++; + } +} + +static void PipeForAllSceneModels(void (*pipeCB)(RpAtomic* data, U32 pipeFlags, U32 subObjects)) +{ + // non-matching: wrong registers + + S32 i, j, k; + S32 numModels = xSTAssetCountByType('MODL'); + + for (i = 0; i < numModels; i++) + { + RpAtomic* model = (RpAtomic*)xSTFindAssetByType('MODL', i, NULL); + + if (model) + { + st_PKR_ASSET_TOCINFO ainfo; + U32 numSubObjects, remainSubObjBits, currSubObjBits; + RpAtomic* tempmodel; + + xSTGetAssetInfoByType('MODL', i, &ainfo); + + numSubObjects = 0; + tempmodel = model; + + do + { + numSubObjects++; + tempmodel = iModelFile_RWMultiAtomic(tempmodel); + } while (tempmodel); + + remainSubObjBits = (1 << numSubObjects) - 1; + + for (j = 0; j < xModelPipeNumTables; j++) + { + for (k = 0; k < xModelPipeCount[j]; k++) + { + if (ainfo.aid == xModelPipeData[j][k].ModelHashID) + { + currSubObjBits = remainSubObjBits & xModelPipeData[j][k].SubObjectBits; + + if (currSubObjBits) + { + pipeCB(model, xModelPipeData[j][k].PipeFlags, currSubObjBits); + } + + remainSubObjBits &= ~currSubObjBits; + + if (!remainSubObjBits) + { + goto loc_800B1698; + } + } + } + } + + if (remainSubObjBits) + { + pipeCB(model, 0, remainSubObjBits); + } + } + + loc_800B1698: + continue; + } +} + +void zSceneInitEnvironmentalSoundEffect() +{ + switch (globals.sceneCur->sceneID) + { + case 'DB06': + case 'KF04': + case 'GL02': + case 'BB03': + case 'BC01': + case 'BC02': + case 'BC03': + case 'BC04': + case 'BC05': + { + xSndSetEnvironmentalEffect(SND_EFFECT_CAVE); + break; + } + default: + { + xSndSetEnvironmentalEffect(SND_EFFECT_NONE); + break; + } + } +} + +static U32 BaseTypeNeedsUpdate(U8 baseType) +{ + if (baseType == eBaseTypeUnknown || baseType == eBaseTypePlayer || baseType == eBaseTypeEnv || + baseType == eBaseTypeCamera || baseType == eBaseTypeStatic || + baseType == eBaseTypeMovePoint || baseType == eBaseTypeBubble || + baseType == eBaseTypePortal || baseType == eBaseTypeGroup || baseType == eBaseTypeSFX || + baseType == eBaseTypeFFX || baseType == eBaseTypeVFX || baseType == eBaseTypeCounter || + baseType == eBaseTypeProjectile || baseType == eBaseTypeGust || + baseType == eBaseTypeVolume || baseType == eBaseTypeDispatcher || + baseType == eBaseTypeCond || baseType == eBaseTypeUI || + baseType == eBaseTypeProjectileType || baseType == eBaseTypeLobMaster || + baseType == eBaseTypeCutsceneMgr || baseType == eBaseTypeHud || + baseType == eBaseTypeNPCProps || baseType == eBaseTypeParticleEmitterProps || + baseType == eBaseTypeCruiseBubble || baseType == eBaseTypeTextBox || + baseType == eBaseTypeTalkBox || baseType == eBaseTypeTaskBox || + baseType == eBaseTypeBoulderGenerator || baseType == eBaseTypeNPCSettings || + baseType == eBaseTypeTurret) + { + return 0; + } + + return 1; +} + +void add_scene_tweaks(); + +void zSceneInit(U32 theSceneID, S32 reloadInProgress) +{ + F32 pdone; + zScene* s; + U32 i; + + U8 rgba_bkgrd[4]; + *(U32*)rgba_bkgrd = _1250; + + gTransitionSceneID = theSceneID; + gOccludeCount = 0; + + char b[5]; + *(U32*)b = _1251; + b[4] = byte_803D0884; + + sprintf(b, xUtil_idtag2string(theSceneID, 0)); + xStrupr(b); + + theSceneID = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; + + xUtil_idtag2string(theSceneID, 0); + + xFogClearFog(); + xSndSceneInit(); + + if (!reloadInProgress) + { + sMemDepthSceneStart = xMemPushBase(); + } + + zGameScreenTransitionBegin(); + zParPTankInit(); + + pdone = _1373; + + if (globals.useHIPHOP && !reloadInProgress) + { + zGameScreenTransitionUpdate(pdone, "... scene preload ...\n"); + + S32 ver_hop = xSTPreLoadScene(theSceneID, NULL, 0x2); + + if (ver_hop >= 0x000A000F) + { + xSTQueueSceneAssets(theSceneID, 0x2); + + do + { + rgba_bkgrd[0] = 0; + rgba_bkgrd[1] = 0; + rgba_bkgrd[2] = 0; + rgba_bkgrd[3] = 0; + + pdone += _1373; + + zGameScreenTransitionUpdate(pdone, "... scene loading ...\n", rgba_bkgrd); + } while (xSTLoadStep(theSceneID) < _1374); + + xSTDisconnect(theSceneID, 0x2); + } + } + + sMemDepthJustHIPStart = xMemPushBase(); + s = (zScene*)xMemAllocSize(sizeof(zScene)); + + globals.sceneCur = s; + + xSceneInit(s, 200, 2048, 2068, 250); + + s->env = (xEnv*)xMemAllocSize(sizeof(xEnv)); + s->sceneID = theSceneID; + + iTime time; + + time = iTimeGet(); + xUtil_idtag2string(theSceneID, 0); + iTimeDiffSec(time); + + xSTPreLoadScene(theSceneID, NULL, 0x1); + + time = iTimeGet(); + xUtil_idtag2string(theSceneID, 0); + iTimeDiffSec(time); + + xSTQueueSceneAssets(theSceneID, 0x1); + + time = iTimeGet(); + xUtil_idtag2string(theSceneID, 0); + iTimeDiffSec(time); + + pdone += _1373; + + zGameScreenTransitionUpdate(pdone, "... scene asset queue ...\n"); + + time = iTimeGet(); + xUtil_idtag2string(theSceneID, 0); + iTimeDiffSec(time); + + do + { + rgba_bkgrd[0] = 0; + rgba_bkgrd[1] = 0; + rgba_bkgrd[2] = 0; + rgba_bkgrd[3] = 0; + + pdone += _1373; + + zGameScreenTransitionUpdate(pdone, "... scene loading ...\n", rgba_bkgrd); + } while (xSTLoadStep(theSceneID) < _1374); + + xSTDisconnect(theSceneID, 0x1); + + time = iTimeGet(); + xUtil_idtag2string(theSceneID, 0); + iTimeDiffSec(time); + + pdone += _1373; + + zGameScreenTransitionUpdate(pdone, "...initializing scene - sound\n"); + + zEntPlayer_LoadSounds(); + iSndInitSceneLoaded(); + xPadRumbleEnable(globals.currentActivePad, globals.option_vibration); + + xSTSwitchScene(theSceneID, NULL, NULL); + + globals.sceneCur->resolvID = zSceneFindObject; + globals.sceneCur->id2Name = zSceneGetName; + globals.sceneCur->base2Name = zSceneGetName; + + g_xSceneCur = globals.sceneCur; + + xModelPipeNumTables = xSTAssetCountByType('PIPT'); + + for (S32 i = 0; i < xModelPipeNumTables; i++) + { + void* data = xSTFindAssetByType('PIPT', i, NULL); + + xModelPipeCount[i] = *(S32*)data; + xModelPipeData[i] = (xModelPipeInfo*)((S32*)data + 1); + } + + xModelLookupCount = 0; + + PipeForAllSceneModels(PipeCountStuffCB); + + if (xModelLookupCount) + { + xModelLookupList = + (xModelPipeLookup*)xMemAllocSize(xModelLookupCount * sizeof(xModelPipeLookup)); + + xModelLookupCount = 0; + + PipeForAllSceneModels(PipeAddStuffCB); + } + + xModelBucket_PreCountReset(); + PipeForAllSceneModels(xModelBucket_PreCountBucket); + + xModelBucket_PreCountAlloc(256); + PipeForAllSceneModels(xModelBucket_InsertBucket); + + xModelBucket_Init(); + add_scene_tweaks(); + xPTankPoolSceneEnter(); + zParPTankSceneEnter(); + xDecalInit(); + xFXScenePrepare(); + zLasso_scenePrepare(); + zDispatcher_scenePrepare(); + + S32 total_npcs = xSTAssetCountByType('VIL '); + zNPCMgr_scenePrepare(total_npcs); + + zAnimListInit(); + zGooInit(24); + + zGameScreenTransitionUpdate(_1375, "...initializing scene - base types\n"); + + for (i = 0; i < eBaseTypeCount; i++) + { + s->baseCount[i] = 0; + s->baseList[i] = NULL; + } + + zCollGeom_Init(); + zUI_Init(); + zUIFontInit(); + ztextbox::init(); + ztalkbox::init(); + ztaskbox::init(); + + xModelInstStaticAlloc = 1; + s->num_base = 0; + + for (i = 0; sInitTable[i].name; i++) + { + U32 typeCount = xSTAssetCountByType(sInitTable[i].assetType); + + s->baseCount[sInitTable[i].baseType] = typeCount; + s->num_base += typeCount; + + if (sInitTable[i].querySubObjects) + { + for (U32 j = 0; j < typeCount; j++) + { + s->num_base += sInitTable[i].querySubObjects( + xSTFindAssetByType(sInitTable[i].assetType, j, NULL)); + } + } + } + + add_dynamic_types(*s); + + if (s->num_base) + { + s->base = (xBase**)xMemAllocSize(s->num_base * sizeof(xBase*)); + } + else + { + s->base = NULL; + } + + zSceneObjHashtableInit(4096); + xFFXPoolInit(12); + xFFXShakePoolInit(3); + xFFXRotMatchPoolInit(1); + xEntSceneInit(); + xEntMotionDebugInit(s->baseCount[eBaseTypePlatform] + s->baseCount[eBaseTypePendulum] + + s->baseCount[eBaseTypeButton]); + zLightSetVolume(NULL); + xPartitionReset(); + xFXRibbonSceneEnter(); + + U32 base_idx = 0; + + for (i = 0; sInitTable[i].name; i++) + { + HACK_BASETYPE = sInitTable[i].baseType; + + if (sInitTable[i].func) + { + base_idx = sInitTable[i].func(s, &sInitTable[i], base_idx); + } + } + + init_dynamic_types(*s, base_idx); + + s->num_update_base = 0; + + for (i = 0; i < s->num_base; i++) + { + if (BaseTypeNeedsUpdate(s->base[i]->baseType)) + { + s->num_update_base++; + } + } + + s->update_base = (xBase**)xMemAllocSize(s->num_update_base * sizeof(xBase*)); + + base_idx = 0; + + for (i = 0; i < s->num_base; i++) + { + if (BaseTypeNeedsUpdate(s->base[i]->baseType)) + { + s->update_base[base_idx] = s->base[i]; + } + } + + xModelInstStaticAlloc = 0; + + zGameScreenTransitionEnd(); + zSceneObjHashtableUsage(); + zUI_ScenePortalInit(s); + zLightResolveLinks(); + zRenderStateInit(); + xFXStreakInit(); + xFXShineInit(); + xFXFireworksInit("PAREMIT_FIREWORKS_TRAIL", "PAREMIT_FIREWORKS1", "PAREMIT_FIREWORKS2", + "Fireworks_explode", "Fireworks_trail"); + zFeetGetIDs(); + zLightningInit(); + zParCmdFindClipVolumes(); + zEntDestructObj_FindFX(); + zShrapnel_SceneInit(globals.sceneCur); + zCameraTweakGlobal_Reset(); + zActionLineInit(); + xScrFxLetterboxReset(); + xShadowManager_Init(eBaseTypeNPC + 10); + + S32 lkitCount = xSTAssetCountByType('LKIT'); + void* lkitData; + + for (S32 i = 0; i < lkitCount; i++) + { + lkitData = xSTFindAssetByType('LKIT', i, NULL); + + xLightKit_Prepare(lkitData); + } + + xClimateInit(&gClimate); + zSceneInitEnvironmentalSoundEffect(); + + sHackSmoothedUpdate = 1; + + FootstepHackSceneEnter(); + zEntPickup_SceneEnter(); + xFXSceneInit(); + zGame_HackGalleryInit(); + iSndSuspendCD(0); +} + +void add_scene_tweaks() +{ +} + +void zSceneExit(S32 beginReload) +{ + zScene* s = globals.sceneCur; + + zThrown_Reset(); + zEntPickup_FlushGrabbed(); + zGridExit(s); + zSceneForAllBase(zSceneExitSoundIteratorCB, NULL); + xSndStopAll(~SND_CAT_UI); + xSndUpdate(); + iSndWaitForDeadSounds(); + iSndSceneExit(); + xSFXEnvironmentalStreamSceneExit(); + iSndSuspendCD(1); + iFuncProfileDump(); + + RpWorld* world = s->env->geom->world; + + xModel_SceneExit(world); + zFX_SceneExit(world); + zEntEventAll(NULL, 0, eEventRoomEnd, NULL); + zEntEventAll(NULL, 0, eEventSceneEnd, NULL); + + if (globals.sceneCur->pendingPortal) + { + char nextScene[8]; + char curScene[8]; + + strcpy(nextScene, xUtil_idtag2string(globals.sceneCur->pendingPortal->passet->sceneID, 0)); + strcpy(curScene, xUtil_idtag2string(globals.sceneCur->sceneID, 0)); + } + + // non-matching: two instructions are swapped here... + gOccludeCount = 0; + + if (globals.sceneCur->sceneID != 'MNU3') + { + zSceneSave(s, NULL); + } + + zEntPlayerExit(&globals.player.ent); + zSurfaceExit(); + zLightDestroyAll(); + xEntSceneExit(); + xEntMotionDebugExit(); + zSceneObjHashtableExit(); + + if (s->baseCount[eBaseTypeParticleSystem]) + { + zParSys* ps = (zParSys*)s->baseList[eBaseTypeParticleSystem]; + + for (U32 i = 0; i < s->baseCount[eBaseTypeParticleSystem]; i++) + { + if (xBaseIsValid(&ps[i])) + { + xParSysExit(&ps[i]); + } + } + } + + xParEmitterDestroy(); + xModelBucket_Deinit(); + xFXSceneFinish(); + zGooExit(); + zParPTankExit(); + zAnimListExit(); + zNPCMgr_sceneFinish(); + zDispatcher_sceneFinish(); + z_disco_floor::destroy(); + xDecalDestroy(); + zParPTankSceneExit(); + xPTankPoolSceneExit(); + zEntPlayer_UnloadSounds(); + + if (beginReload) + { + xSTUnLoadScene(globals.sceneCur->sceneID, 1); + xMemPopBase(sMemDepthJustHIPStart); + + sMemDepthJustHIPStart = -1; + } + else + { + xSTUnLoadScene(globals.sceneCur->sceneID, 1); + + if (globals.useHIPHOP) + { + xSTUnLoadScene(globals.sceneCur->sceneID, 2); + } + + xMemPopBase(sMemDepthSceneStart); + + sMemDepthSceneStart = -1; + sMemDepthJustHIPStart = -1; + } + + xSystem_GapTrackReport(); + xUtil_idtag2string(globals.sceneCur->sceneID, 0); + + globals.sceneCur = NULL; + + xSceneExit(s); +} + +void zSceneUpdateSFXWidgets() +{ + zScene* s = globals.sceneCur; + xSFXUpdateEnvironmentalStreamSounds((xSFX*)s->baseList[eBaseTypeSFX], + s->baseCount[eBaseTypeSFX]); +} + +static void HackSwapIt(char* buf, S32 size) +{ + // non-matching: r3 and r4 swapped + char* end = size + buf; + end--; + + for (S32 i = 0; i < size / 2; i++) + { + char tmp = *buf; + *buf = *end; + *end = tmp; + + buf++; + end--; + } +} + +void zSceneSwitch(_zPortal* p, S32 forceSameScene) +{ + globals.sceneCur->pendingPortal = p; + + xPortalAsset* passet = globals.sceneCur->pendingPortal->passet; + + gLevelChanged = (zSceneLeavingLevel() != 0); + + if (((char*)&passet->sceneID)[3] < '0' || ((char*)&passet->sceneID)[3] > '9') + { + char* id = (char*)&passet->sceneID; + HackSwapIt(id, 4); + } + + U32 nextSceneID = (((char*)&passet->sceneID)[0] << 24) | (((char*)&passet->sceneID)[1] << 16) | + (((char*)&passet->sceneID)[2] << 8) | ((char*)&passet->sceneID)[3]; + + if (!forceSameScene && nextSceneID == globals.sceneCur->sceneID) + { + U32 PlayerMarkerStartID = passet->assetMarkerID; + U32 PlayerMarkerStartCamID = passet->assetCameraID; + F32 PlayerStartAngle = passet->ang; + + if (zSceneFindObject(PlayerMarkerStartCamID)) + { + globals.player.cp.initCamID = PlayerMarkerStartCamID; + } + + if (PlayerStartAngle >= _1493) + { + xMarkerAsset* marker = (xMarkerAsset*)xSTFindAsset(PlayerMarkerStartID, NULL); + + if (marker) + { + xEnt& player = globals.player.ent; + xVec3& loc = (xVec3&)player.model->Mat->pos; + + xVec3 offset = marker->pos - loc; + + loc = player.frame->mat.pos = marker->pos; + + xCameraMove(&globals.camera, globals.camera.mat.pos + offset); + } + } + else + { + U32 size; + xMarkerAsset* m = (xMarkerAsset*)xSTFindAsset(PlayerMarkerStartID, &size); + + if (m) + { + xVec3Copy(&globals.player.ent.frame->mat.pos, &m->pos); + xVec3Copy((xVec3*)&globals.player.ent.model->Mat->pos, &m->pos); + + xCameraSetTargetMatrix(&globals.camera, xEntGetFrame(&globals.player.ent)); + } + + xEntFrame* frame = globals.player.ent.frame; + + frame->rot.angle = _1494 * PlayerStartAngle / _1495; + frame->rot.axis = xVec3::create(_1496_0, _1374, _1496_0); + + xMat3x3Euler(&frame->mat, frame->rot.angle, _1496_0, _1496_0); + + *(xMat3x3*)globals.player.ent.model->Mat = frame->mat; + + zCameraReset(&globals.camera); + } + + // non-matching: instruction order + + oob_player_teleported = true; + globals.sceneCur->pendingPortal = NULL; + } +} + +void zSceneSave(zScene* ent, xSerial* s) +{ + zEntPickup_FlushGrabbed(); + + U32 i; + xSerial xser; + + s = &xser; + + s->setClient('PLYR'); + s->Write_b1(1); + s->Write(globals.player.MaxHealth); + s->Write(gCurrentPlayer); + s->Write(globals.player.Inv_Shiny); + s->Write(globals.player.Inv_Spatula); + s->Write(globals.player.g.PowerUp[0]); + s->Write(globals.player.g.PowerUp[1]); + + for (i = 0; i < LEVEL_COUNT; i++) + { + s->Write(globals.player.Inv_PatsSock[i]); + s->Write(globals.player.Inv_LevelPickups[i]); + } + + s->Write(globals.player.Inv_PatsSock_Total); + + zCutsceneMgrSave(NULL, s); + oob_state::write_persistent(*s); + + s->setClient('CNTR'); + s->Write_b1(1); + + zUI_ScenePortalSave(s); + + char tempString[32]; + + strcpy(tempString, "HB09 ROBOT COUNTER 01"); + + char c = '1'; + U32 id; + + for (i = 0; i < LEVEL_COUNT; i++) + { + if (c > '9') + { + c = '0'; + tempString[19]++; + } + + tempString[20] = c; + + c++; + + id = xStrHash(tempString); + + s->Write(((_xCounter*)zSceneFindObject(id))->count); + } + + id = xStrHash("REMINDER_SOCK_CNTR"); + + s->Write(((_xCounter*)zSceneFindObject(id))->count); + + zGameExtras_Save(s); + + s->setClient(ent->sceneID); + s->Write_b1(1); + + xSceneSave(ent, s); + + s->Write(offsetx); + s->Write(offsety); + + for (U32 i = 0; i < globals.sceneCur->num_base; i++) + { + xBase* b = globals.sceneCur->base[i]; + + if (b->baseFlags & 0x2) + { + switch (b->baseType) + { + case eBaseTypeTrigger: + { + zEntTriggerSave((zEntTrigger*)b, s); + break; + } + case eBaseTypeNPC: + { + ((xNPCBasic*)b)->Save(s); + break; + } + case eBaseTypePickup: + { + zEntPickup_Save((zEntPickup*)b, s); + break; + } + case eBaseTypeEnv: + { + zEnvSave((_zEnv*)b, s); + break; + } + case eBaseTypeFog: + { + xFogSave((_xFog*)b, s); + break; + } + case eBaseTypeLight: + { + zLightSave((_zLight*)b, s); + break; + } + case eBaseTypePlatform: + { + zPlatform_Save((zPlatform*)b, s); + break; + } + case eBaseTypeCamera: + { + zCamMarkerSave((zCamMarker*)b, s); + break; + } + case eBaseTypeStatic: + { + zEntSimpleObj_Save((zEntSimpleObj*)b, s); + break; + } + case eBaseTypeMovePoint: + { + zMovePointSave((zMovePoint*)b, s); + break; + } + case eBaseTypeTimer: + { + xTimerSave((xTimer*)b, s); + break; + } + case eBaseTypePortal: + { + zPortalSave((_zPortal*)b, s); + break; + } + case eBaseTypeGroup: + { + xGroupSave((xGroup*)b, s); + break; + } + case eBaseTypePendulum: + { + zPendulum_Save((_zPendulum*)b, s); + break; + } + case eBaseTypeSFX: + { + xSFXSave((xSFX*)b, s); + break; + } + case eBaseTypeCounter: + { + xCounterSave((_xCounter*)b, s); + break; + } + case eBaseTypeHangable: + { + zEntHangable_Save((zEntHangable*)b, s); + break; + } + case eBaseTypeButton: + { + zEntButton_Save((_zEntButton*)b, s); + break; + } + case eBaseTypeSurface: + { + zSurfaceSave((xSurface*)b, s); + break; + } + case eBaseTypeDestructObj: + { + zEntDestructObj_Save((zEntDestructObj*)b, s); + break; + } + case eBaseTypeGust: + { + zGustSave((zGust*)b, s); + break; + } + case eBaseTypeScript: + { + zScriptSave((_zScript*)b, s); + break; + } + case eBaseTypeVolume: + { + ((xVolume*)b)->Save(s); + break; + } + case eBaseTypeDispatcher: + { + zDispatcher_Save((st_ZDISPATCH_DATA*)b, s); + break; + } + case eBaseTypeCond: + { + zConditionalSave((_zConditional*)b, s); + break; + } + case eBaseTypeUI: + { + zUI_Save((_zUI*)b, s); + break; + } + case eBaseTypeUIFont: + { + zUIFont_Save((zUIFont*)b, s); + break; + } + case eBaseTypeEGenerator: + { + zEGenerator_Save((zEGenerator*)b, s); + break; + } + case eBaseTypeTeleportBox: + { + zEntTeleportBox_Save((_zEntTeleportBox*)b, s); + break; + } + case eBaseTypeTaskBox: + { + ((ztaskbox*)b)->write(*s); + break; + } + case eBaseTypeTaxi: + { + zTaxi_Save((zTaxi*)b, s); + break; + } + case eBaseTypeCameraFly: + { + zCameraFly_Save((zCameraFly*)b, s); + break; + } + case eBaseTypeCameraTweak: + { + zCameraTweak_Save((zCameraTweak*)b, s); + break; + } + } + } + } +} + +void zSceneLoad(zScene* ent, xSerial* s) +{ + xSerial xser; + S32 sceneExist; + + s = &xser; + + s->setClient('PLYR'); + + sceneExist = 0; + s->Read_b1(&sceneExist); + + if (sceneExist) + { + s->Read(&globals.player.MaxHealth); + + globals.player.Health = globals.player.MaxHealth; + + s->Read((U32*)&gCurrentPlayer); + s->Read(&globals.player.Inv_Shiny); + s->Read(&globals.player.Inv_Spatula); + s->Read(&globals.player.g.PowerUp[0]); + s->Read(&globals.player.g.PowerUp[1]); + + for (S32 i = 0; i < LEVEL_COUNT; i++) + { + s->Read(&globals.player.Inv_PatsSock[i]); + s->Read(&globals.player.Inv_LevelPickups[i]); + } + + s->Read(&globals.player.Inv_PatsSock_Total); + + zCutsceneMgrLoad(NULL, s); + oob_state::read_persistent(*s); + } + + s->setClient('CNTR'); + + sceneExist = 0; + s->Read_b1(&sceneExist); + + if (sceneExist) + { + char tempString[32]; + + zUI_ScenePortalLoad(s); + + strcpy(tempString, "HB09 ROBOT COUNTER 01"); + + char c = '1'; + S32 i; + U32 id; + + for (i = 0; i < LEVEL_COUNT; i++) + { + if (c > '9') + { + c = '0'; + tempString[19]++; + } + + tempString[20] = c; + + c++; + + id = xStrHash(tempString); + + s->Read(&((_xCounter*)zSceneFindObject(id))->count); + } + + id = xStrHash("REMINDER_SOCK_CNTR"); + + s->Read(&((_xCounter*)zSceneFindObject(id))->count); + + zGameExtras_Load(s); + } + + s->setClient(ent->sceneID); + + sceneExist = 0; + s->Read_b1(&sceneExist); + + if (sceneExist) + { + xSceneLoad(ent, s); + + s->Read(&offsetx); + s->Read(&offsety); + + for (U16 i = 0; i < globals.sceneCur->num_base; i++) + { + xBase* b = globals.sceneCur->base[i]; + + if (b->baseFlags & 0x2) + { + switch (b->baseType) + { + case eBaseTypeTrigger: + { + zEntTriggerLoad((zEntTrigger*)b, s); + break; + } + case eBaseTypeNPC: + { + ((xNPCBasic*)b)->Load(s); + break; + } + case eBaseTypePlayer: + { + zEntPlayer_Load((xEnt*)b, s); + break; + } + case eBaseTypePickup: + { + zEntPickup_Load((zEntPickup*)b, s); + break; + } + case eBaseTypeEnv: + { + zEnvLoad((_zEnv*)b, s); + break; + } + case eBaseTypeFog: + { + xFogLoad((_xFog*)b, s); + break; + } + case eBaseTypeLight: + { + zLightLoad((_zLight*)b, s); + break; + } + case eBaseTypePlatform: + { + zPlatform_Load((zPlatform*)b, s); + break; + } + case eBaseTypeCamera: + { + zCamMarkerLoad((zCamMarker*)b, s); + break; + } + case eBaseTypeStatic: + { + zEntSimpleObj_Load((zEntSimpleObj*)b, s); + break; + } + case eBaseTypeMovePoint: + { + zMovePointLoad((zMovePoint*)b, s); + break; + } + case eBaseTypeTimer: + { + xTimerLoad((xTimer*)b, s); + break; + } + case eBaseTypePortal: + { + zPortalLoad((_zPortal*)b, s); + break; + } + case eBaseTypeGroup: + { + xGroupLoad((xGroup*)b, s); + break; + } + case eBaseTypePendulum: + { + zPendulum_Load((_zPendulum*)b, s); + break; + } + case eBaseTypeSFX: + { + xSFXLoad((xSFX*)b, s); + break; + } + case eBaseTypeCounter: + { + xCounterLoad((_xCounter*)b, s); + break; + } + case eBaseTypeHangable: + { + zEntHangable_Load((zEntHangable*)b, s); + break; + } + case eBaseTypeButton: + { + zEntButton_Load((_zEntButton*)b, s); + break; + } + case eBaseTypeSurface: + { + zSurfaceLoad((xSurface*)b, s); + break; + } + case eBaseTypeDestructObj: + { + zEntDestructObj_Load((zEntDestructObj*)b, s); + break; + } + case eBaseTypeGust: + { + zGustLoad((zGust*)b, s); + break; + } + case eBaseTypeScript: + { + zScriptLoad((_zScript*)b, s); + break; + } + case eBaseTypeVolume: + { + ((xVolume*)b)->Load(s); + break; + } + case eBaseTypeDispatcher: + { + zDispatcher_Load((st_ZDISPATCH_DATA*)b, s); + break; + } + case eBaseTypeCond: + { + zConditionalLoad((_zConditional*)b, s); + break; + } + case eBaseTypeUI: + { + zUI_Load((_zUI*)b, s); + break; + } + case eBaseTypeUIFont: + { + zUIFont_Load((zUIFont*)b, s); + break; + } + case eBaseTypeEGenerator: + { + zEGenerator_Load((zEGenerator*)b, s); + break; + } + case eBaseTypeTeleportBox: + { + zEntTeleportBox_Load((_zEntTeleportBox*)b, s); + break; + } + case eBaseTypeTaskBox: + { + ((ztaskbox*)b)->read(*s); + break; + } + case eBaseTypeTaxi: + { + zTaxi_Load((zTaxi*)b, s); + break; + } + case eBaseTypeCameraFly: + { + zCameraFly_Load((zCameraFly*)b, s); + break; + } + case eBaseTypeCameraTweak: + { + zCameraTweak_Load((zCameraTweak*)b, s); + break; + } + } + } + } + } +} + +S32 zSceneSetup_serialTraverseCB(U32 clientID, xSerial* xser); + +void zSceneReset() +{ + zScene* s = globals.sceneCur; + + zEntPlayerPreReset(); + + gOccludeCount = 0; + + xScrFxLetterboxReset(); + zEntPickup_FlushGrabbed(); + zEntPickup_SceneReset(); + zMusicReset(); + zThrown_Reset(); + zShrapnel_Reset(); + zFX_SceneReset(); + xFXSceneReset(); + xShadowManager_Reset(); + ztalkbox::reset_all(); + zCameraTweakGlobal_Reset(); + xPadDestroyRumbleChain(0); + + globals.cmgr = NULL; + + zEntEventAll(NULL, 0, eEventRoomEnd, NULL); + zEntEventAll(NULL, 0, eEventSceneEnd, NULL); + + zSceneSave(s, NULL); + zSceneAutoSave(); + + xSndStopAll(~SND_CAT_UI); + xSndUpdate(); + iSndWaitForDeadSounds(); + + for (U32 i = 0; i < s->num_base; i++) + { + if (s->base[i]) + { + switch (s->base[i]->baseType) + { + case eBaseTypePickup: + case eBaseTypeCamera: + case eBaseTypeDoor: + case eBaseTypeSavePoint: + case eBaseTypeItem: + case eBaseTypeStatic: + case eBaseTypeDynamic: + case eBaseTypeMovePoint: + case eBaseTypeTimer: + case eBaseTypeBubble: + case eBaseTypePortal: + case eBaseTypeGroup: + case eBaseTypeSFX: + case eBaseTypeFFX: + case eBaseTypeVFX: + case eBaseTypeButton: + case eBaseTypeProjectile: + case eBaseTypeSurface: + case eBaseTypeDestructObj: + case eBaseTypeGust: + case eBaseTypeVolume: + case eBaseTypeDispatcher: + case eBaseTypeCond: + case eBaseTypeUI: + case eBaseTypeUIFont: + case eBaseTypeProjectileType: + case eBaseTypeFog: + case eBaseTypeLight: + case eBaseTypeParticleEmitter: + case eBaseTypeParticleSystem: + case eBaseTypeCutsceneMgr: + default: + { + zEntEvent(NULL, 0, s->base[i], eEventReset, NULL, NULL, 1); + break; + } + case eBaseTypeCounter: + { + xCounterReset(s->base[i]); + break; + } + case eBaseTypePlayer: + { + zEntPlayerReset((xEnt*)s->base[i]); + break; + } + case eBaseTypePlatform: + { + zPlatform_Reset((zPlatform*)s->base[i], globals.sceneCur); + break; + } + case eBaseTypePendulum: + { + zPendulum_Reset((_zPendulum*)s->base[i], globals.sceneCur); + break; + } + case eBaseTypeHangable: + { + zEntHangable_Reset((zEntHangable*)s->base[i]); + break; + } + case eBaseTypeLobMaster: + { + zEntEvent(s->base[i], eEventReset); + break; + } + case eBaseTypeEGenerator: + { + zEGenerator_Reset((zEGenerator*)s->base[i], globals.sceneCur); + break; + } + case eBaseTypeEnv: + { + _zEnv* env = (_zEnv*)s->base[i]; + + if (env) + { + if (zSceneFindObject(env->easset->startCameraAssetID)) + { + zCameraReset(&globals.camera); + } + + xClimateInitAsset(&gClimate, env->easset); + } + } + } + } + } + + zNPCMgr_sceneReset(); + zEntPlayer_LoadCheckPoint(); + zSceneLoad(globals.sceneCur, NULL); + zSceneEnableVisited(s); + xSerialTraverse(zSceneSetup_serialTraverseCB); + xSkyDome_Setup(); + xUpdateCull_Reset(globals.updateMgr); + xUpdateCull_Update(globals.updateMgr, 100); + zGridReset(s); + + zEntEventAll(NULL, 0, eEventSceneBegin, NULL); + zEntEventAll(NULL, 0, eEventRoomBegin, NULL); + zEntEventAll(NULL, 0, eEventSceneReset, NULL); + + zNPCTiki_InitStacking(globals.sceneCur); + zNPCTiki_InitFX(globals.sceneCur); + + xUpdateCull_Update(globals.updateMgr, 100); + zLOD_Update(100); + + zGameExtras_SceneReset(); +} + +static void ActivateCB(xBase* base) +{ + base->baseFlags &= (U8)~0x40; +} + +static void DeactivateCB(xBase* base) +{ + base->baseFlags |= 0x40; +} + +// clang-format off +// jumptable for zSceneSetup +static U32 _2098_0[] = +{ +0x800B3418, 0x800B3418, 0x800B3418, +0x800B3418, 0x800B33B0, 0x800B32E0, +0x800B3318, 0x800B3418, 0x800B3418, +0x800B3418, 0x800B3418, 0x800B3378, +0x800B3418, 0x800B3334, 0x800B3418, +0x800B3418, 0x800B3418, 0x800B33DC, +0x800B3340, 0x800B3418, 0x800B3418, +0x800B3418, 0x800B3418, 0x800B3418, +0x800B335C, 0x800B3418, 0x800B33CC, +0x800B340C, 0x800B3418, 0x800B3418, +0x800B3388, 0x800B3418, 0x800B3418, +0x800B3418, 0x800B3418, 0x800B3418, +0x800B3418, 0x800B3418, 0x800B33D4, +0x800B33C4, 0x800B3418, 0x800B3394, +0x800B3418, 0x800B3304, 0x800B3418, +0x800B3418, 0x800B3418, 0x800B3414, +0x800B3418, 0x800B33E4, 0x800B33EC, +0x800B3418, 0x800B3418, 0x800B3418, +0x800B3418, 0x800B3418, 0x800B33F4, +0x800B33FC, 0x800B3418, 0x800B3418, +0x800B3418, 0x800B3418, 0x800B3404, +0x800B3380, 0x800B3418, 0x800B3418, +0x800B3418, 0x800B3418, 0x800B3418, +0x800B3418, 0x800B3418, 0x800B3418 +}; +// clang-format on + +void zSceneSetup() +{ + zScene* s = globals.sceneCur; + + globals.cmgr = NULL; + + xSceneSetup(s); + gUIMgr.Setup(s); + + s->gravity = _2094; + s->drag = _2095_0; + s->flags = 0x5; + + zNPCMgr_scenePostInit(); + + if (s->baseCount[eBaseTypeGust]) + { + zGustSetup(); + } + + if (s->baseCount[eBaseTypeVolume]) + { + zVolumeSetup(); + } + + { + U32 dontcaresize; + xCutscene_Init(xSTFindAssetByType('CTOC', 0, &dontcaresize)); + } + + zLOD_Setup(); + + gCurEnv = NULL; + + for (U32 i = 0; i < s->num_base; i++) + { + if (s->base[i]) + { + switch (s->base[i]->baseType) + { + case eBaseTypeEnv: + { + gCurEnv = (_zEnv*)s->base[i]; + + zEnvSetup(gCurEnv); + xClimateInitAsset(&gClimate, gCurEnv->easset); + + break; + } + case eBaseTypeNPC: + { + ((xNPCBasic*)s->base[i])->Setup(); + break; + } + case eBaseTypePlatform: + { + zPlatform_Reset((zPlatform*)s->base[i], s); + zPlatform_Setup((zPlatform*)s->base[i], s); + break; + } + case eBaseTypeMovePoint: + { + zMovePointSetup((zMovePoint*)s->base[i], s); + break; + } + case eBaseTypePendulum: + { + zPendulum_Reset((_zPendulum*)s->base[i], s); + zPendulum_Setup((_zPendulum*)s->base[i], s); + break; + } + case eBaseTypeButton: + { + zEntButton_Reset((_zEntButton*)s->base[i], s); + zEntButton_Setup((_zEntButton*)s->base[i], s); + break; + } + case eBaseTypeStatic: + { + zEntSimpleObj_Setup((zEntSimpleObj*)s->base[i]); + break; + } + case eBaseTypeTrackPhysics: + { + zEntSimpleObj_Setup((zEntSimpleObj*)s->base[i]); + break; + } + case eBaseTypeDispatcher: + { + zDispatcher_InitDep((st_ZDISPATCH_DATA*)s->base[i], s); + break; + } + case eBaseTypeEGenerator: + { + zEGenerator_Setup((zEGenerator*)s->base[i], s); + zEGenerator_Reset((zEGenerator*)s->base[i], s); + break; + } + case eBaseTypePickup: + { + zEntPickup_Setup((zEntPickup*)s->base[i]); + zEntPickup_Reset((zEntPickup*)s->base[i]); + break; + } + case eBaseTypeParticleSystem: + { + xParSysSetup((xParSys*)s->base[i]); + break; + } + case eBaseTypeSurface: + { + zSurfaceSetup((xSurface*)s->base[i]); + break; + } + case eBaseTypeParticleEmitter: + { + xParEmitterSetup((xParEmitter*)s->base[i]); + break; + } + case eBaseTypeGroup: + { + xGroupSetup((xGroup*)s->base[i]); + break; + } + case eBaseTypeTeleportBox: + { + zEntTeleportBox_Setup((_zEntTeleportBox*)s->base[i]); + break; + } + case eBaseTypeBusStop: + { + zBusStop_Setup((zBusStop*)s->base[i]); + break; + } + case eBaseTypeDiscoFloor: + { + ((z_disco_floor*)s->base[i])->setup(); + break; + } + case eBaseTypeTaxi: + { + zTaxi_Setup((zTaxi*)s->base[i]); + break; + } + case eBaseTypeCameraFly: + { + zCameraFly_Setup((zCameraFly*)s->base[i]); + break; + } + case eBaseTypeDestructObj: + { + zEntDestructObj_Setup((zEntDestructObj*)s->base[i]); + break; + } + case eBaseTypeBoulder: + { + xEntBoulder_Setup((xEntBoulder*)s->base[i]); + break; + } + case eBaseTypeUnknown: + case eBaseTypeZipLine: + case eBaseTypeHUD_text: + { + break; + } + } + } + } + + zEntPickup_Setup(); + zEntTeleportBox_InitAll(); + zEntHangable_SetupFX(); + zThrown_Setup(globals.sceneCur); + + for (U32 i = 0; i < s->num_base; i++) + { + if (s->base[i] && s->base[i]->baseType == eBaseTypeMovePoint) + { + xMovePointSplineSetup((xMovePoint*)s->base[i]); + } + } + + xFXSceneSetup(); + zSceneEnableVisited(s); + xSerialTraverse(zSceneSetup_serialTraverseCB); + xQuickCullInit(xEntGetAllEntsBox()); + zGridInit(s); + zNPCBSandy_AddBoundEntsToGrid(s); + zNPCBPatrick_AddBoundEntsToGrid(s); + zNPCTiki_InitStacking(globals.sceneCur); + zNPCTiki_InitFX(globals.sceneCur); + + enableScreenAdj = 0; + + for (U32 i = 0; i < s->num_base; i++) + { + if (s->base[i] && s->base[i]->baseType == eBaseTypeNPC) + { + xEnt* ent = (xEnt*)s->base[i]; + zLODTable* lod = zLOD_Get(ent); + + if (lod) + { + RpAtomic* tryshad = NULL; + + if (lod->lodBucket[2]) + { + tryshad = lod->lodBucket[2][0]->Data; + } + else if (lod->lodBucket[1]) + { + tryshad = lod->lodBucket[1][0]->Data; + } + else if (lod->lodBucket[0]) + { + tryshad = lod->lodBucket[0][0]->Data; + } + + if (tryshad && RpClumpGetNumAtomics(RpAtomicGetClump(tryshad)) == 1) + { + ent->entShadow->shadowModel = tryshad; + } + } + } + } + + { + int max_drivensort_tiers = 256; + U32 driven_swapped; + U32 i, j; + + do + { + driven_swapped = 0; + + for (i = 0; i < s->num_update_base; i++) + { + if (s->update_base[i]->baseFlags & 0x20) + { + xEnt* bdriven = (xEnt*)s->update_base[i]; + + if (bdriven->driver) + { + for (j = (i + 1) * 2; j < s->num_update_base; j++) + { + if (bdriven->driver == s->update_base[j]) + { + driven_swapped = 1; + + xBase* btmp = s->update_base[i]; + + s->update_base[i] = s->update_base[j]; + s->update_base[j] = btmp; + } + } + } + } + } + } while (--max_drivensort_tiers && driven_swapped); + } + + { + S32 i; + U32 f; + + xEnvAsset* easset = globals.sceneCur->zen->easset; + + if (easset->bspLightKit) + { + globals.sceneCur->env->lightKit = (xLightKit*)xSTFindAsset(easset->bspLightKit, NULL); + } + + if (easset->objectLightKit) + { + xLightKit* objLightKit = (xLightKit*)xSTFindAsset(easset->objectLightKit, NULL); + + if (objLightKit) + { + zScene* zsc = globals.sceneCur; + + for (i = 0; i < s->num_base; i++) + { + if (s->base[i]->baseFlags & 0x20) + { + xEnt* tgtent = (xEnt*)s->base[i]; + + if (tgtent->model) + { + f = tgtent->model->PipeFlags & (0x40 | 0x80); + + if (f != 0x40) + { + tgtent->lightKit = objLightKit; + } + } + } + } + } + } + + S32 lkitCount = xSTAssetCountByType('LKIT'); + + for (i = 0; i < lkitCount; i++) + { + xLightKit* lkit = (xLightKit*)xSTFindAssetByType('LKIT', i, NULL); + + if (lkit->groupID) + { + xGroup* group = (xGroup*)zSceneFindObject(lkit->groupID); + + if (group) + { + U32 j, nitam; + + nitam = xGroupGetCount(group); + + for (j = 0; j < nitam; j++) + { + xBase* itamz = xGroupGetItemPtr(group, j); + + if (itamz && (itamz->baseFlags & 0x20)) + { + xEnt* entitam = (xEnt*)itamz; + + if (entitam->model) + { + f = entitam->model->PipeFlags & (0x40 | 0x80); + + if (f != 0x40) + { + entitam->lightKit = lkit; + } + } + } + } + } + } + } + } + + zEntSimpleObj_MgrInit((zEntSimpleObj**)s->act_ents + s->baseCount[eBaseTypeTrigger] + + s->baseCount[eBaseTypePickup], + s->baseCount[eBaseTypeStatic]); + + xEnt** entList = + s->act_ents + s->baseCount[eBaseTypeTrigger] + s->baseCount[eBaseTypePickup]; // r28 + U32 entCount = s->baseCount[eBaseTypeStatic] + s->baseCount[eBaseTypePlatform] + + s->baseCount[eBaseTypePendulum] + s->baseCount[eBaseTypeHangable] + + s->baseCount[eBaseTypeDestructObj] + s->baseCount[eBaseTypeBoulder] + + s->baseCount[eBaseTypeNPC] + s->baseCount[eBaseTypeButton]; // r27 + + U32 i, j, k; + U32 numPrimeMovers = 0; // r24 + U32 numDriven = 0; // r25 + + for (i = 0; i < s->num_ents; i++) + { + if (s->ents[i]->baseFlags & 0x20) + { + s->ents[i]->isCulled = 0; + } + } + + for (i = 0; i < s->num_ents; i++) + { + if (s->ents[i]->baseFlags & 0x20) + { + if (s->ents[i]->driver) + { + if (!s->ents[i]->isCulled) + { + numDriven++; + s->ents[i]->isCulled = 2; + } + + xEnt* ent = s->ents[i]; + + while (ent->driver) + { + ent = ent->driver; + } + + if (!ent->isCulled) + { + numPrimeMovers++; + ent->isCulled = 1; + } + } + } + } + + U32 numGroups = 0; + + for (i = 0; i < s->num_base; i++) + { + if (s->base[i]->baseType == eBaseTypeGroup) + { + xGroup* grp = (xGroup*)s->base[i]; + + for (j = 0; j < grp->linkCount; j++) + { + // bug: grp->link needs to be changed to grp->link[j] + // currently the 1st link is checked over and over + // and any links after that are not checked + + if (grp->link->srcEvent == eEventSceneBegin && + grp->link->dstEvent == eEventGroupUpdateTogether) + { + numGroups++; + + U32 gcnt = xGroupGetCount(grp); + + for (k = 0; k < gcnt; k++) + { + xBase* gbase = xGroupGetItemPtr(grp, k); + + if (gbase && (gbase->baseFlags & 0x20)) + { + xEnt* gent = (xEnt*)gbase; + + if (gent->isCulled) + { + if (gent->isCulled == 1) + { + numDriven--; + } + + if (gent->isCulled != 1) + { + numPrimeMovers--; + } + + gent->isCulled = 0; + } + } + } + } + } + } + } + + xGroup* driveGroupList = NULL; + + if (numDriven) + { + U32 allocsize = numDriven * sizeof(xGroup) + numDriven * sizeof(xGroupAsset) + + (numDriven + numPrimeMovers) * sizeof(xBase*); + + driveGroupList = (xGroup*)RwMalloc(allocsize); + + memset(driveGroupList, 0, allocsize); + + xGroupAsset* grpAssetList = (xGroupAsset*)(driveGroupList + numDriven); + xBase** grpBaseList = (xBase**)(grpAssetList + numDriven); + + for (i = 0; i < numDriven; i++) + { + driveGroupList[i].baseType = eBaseTypeGroup; + driveGroupList[i].asset = &grpAssetList[i]; + driveGroupList[i].flg_group |= 0x1; + } + + for (i = 0, j = 0; i < s->num_base; i++) + { + if (s->base[i]->baseFlags & 0x20) + { + xEnt* ent = (xEnt*)s->base[i]; + + if (ent->isCulled == 1) + { + xGroupAsset* gasset = driveGroupList[j].asset; + + driveGroupList[j].item = grpBaseList; + *grpBaseList++ = ent; + gasset->itemCount++; + + for (k = 0; k < s->num_base; k++) + { + if (s->base[k]->baseFlags & 0x20) + { + xEnt* other = (xEnt*)s->base[k]; + + if (other->isCulled == 2) + { + xEnt* r12 = other; + + while (r12->driver) + { + r12 = r12->driver; + } + + if (ent == r12) + { + *grpBaseList++ = other; + gasset->itemCount++; + } + } + } + } + + if (gasset->itemCount > 1) + { + numPrimeMovers++; + } + + j++; + } + } + } + } + + xGroup** tempGrpList = NULL; + + if (numGroups) + { + tempGrpList = (xGroup**)RwMalloc(numGroups * sizeof(xGroup*)); + + xGroup** tempGrpCurr = tempGrpList; + + for (i = 0; i < s->num_base; i++) + { + if (s->base[i]->baseType == eBaseTypeGroup) + { + xGroup* grp = (xGroup*)s->base[i]; + + for (j = 0; j < grp->linkCount; j++) + { + // same bug as above + // grp->link should be changed to grp->link[j] + + if (grp->link->srcEvent == eEventSceneBegin && + grp->link->dstEvent == eEventGroupUpdateTogether) + { + *tempGrpCurr++ = grp; + } + } + } + } + + for (i = 0; i < numDriven; i++) + { + if (driveGroupList[i].asset->itemCount > 1) + { + *tempGrpCurr++ = &driveGroupList[i]; + } + } + } + + globals.updateMgr = xUpdateCull_Init((void**)entList, entCount, tempGrpList, numGroups); + globals.updateMgr->activateCB = (xUpdateCullActivateCallback)ActivateCB; + globals.updateMgr->deactivateCB = (xUpdateCullDeactivateCallback)DeactivateCB; + + FloatAndVoid defaultDist; + defaultDist.f = _2096_0; + + FloatAndVoid lodDist; + lodDist.f = _1496_0; + + for (i = 0; i < entCount; i++) + { + zLODTable* lod = zLOD_Get(entList[i]); + + if (lod) + { + if (lod->noRenderDist == _1496_0) + { + lod = NULL; + } + else + { + lodDist.f = SQR(_2097_0 + xsqrt(lod->noRenderDist)); + } + } + + xUpdateCull_SetCB(globals.updateMgr, entList[i], xUpdateCull_DistanceSquaredCB, + (lod) ? lodDist.v : defaultDist.v); + } + + if (tempGrpList) + { + RwFree(tempGrpList); + } + + if (driveGroupList) + { + RwFree(driveGroupList); + } + + for (i = 0; i < s->num_base; i++) + { + if (s->base[i]->baseFlags & 0x20) + { + ((xEnt*)s->base[i])->isCulled = 0; + } + } + + zNPCMgr_scenePostSetup(); + z_disco_floor::post_setup(); + zEntPickup_RewardPostSetup(); + + iColor_tag black; + *(U32*)&black = _2013; + + iColor_tag clear; + *(U32*)&clear = _2014; + + xScrFxFade(&black, &clear, _1374, NULL, 0); +} + +S32 zSceneSetup_serialTraverseCB(U32 clientID, xSerial* xser) +{ + char uiName[16]; + S32 val = 0; + xBase* b; + + xser->Read_b1(&val); + + if (val == 0) + { + return 1; + } + + sprintf(uiName, "%s", xUtil_idtag2string(clientID, 0)); + + uiName[1] = ' '; + + strcat(uiName, " VISITED"); + + b = zSceneFindObject(xStrHash(uiName)); + + if (b) + { + b->baseFlags |= 0x1; + } + + return 1; +} + +void zSceneUpdate(F32 dt) +{ + U32 i; + S32 isPaused; + zScene* s; + xBase** b; + + if (_1496_0 == dt) + { + return; + } + + isPaused = zGameIsPaused(); + gSceneUpdateTime = dt; + + if (!isPaused) + { + zEntPickup_SceneUpdate(dt); + zEntButton_SceneUpdate(dt); + } + + xEntSetTimePassed(dt); + + if (globals.cmgr) + { + zCutsceneMgrUpdate(globals.cmgr, globals.sceneCur, dt); + } + + s = globals.sceneCur; + b = s->update_base; + + gUIMgr.PreUpdate(s, dt); + + if (s->baseCount[eBaseTypeUIFont]) + { + zUIFont* ui = (zUIFont*)s->baseList[eBaseTypeUIFont]; + + for (i = 0; i < s->baseCount[eBaseTypeUIFont]; i++) + { + zUIFont_PreUpdate(&ui[i], s, dt); + } + } + + if (!isPaused) + { + zNPCMgr_sceneTimestep(s, dt); + } + else if (s->sceneID == 'B101') + { + zNPCBSandy_GameIsPaused(s); + } + else if (s->sceneID == 'B201') + { + zNPCBPatrick_GameIsPaused(s); + } + + ztextbox::update_all(*s, dt); + ztalkbox::update_all(*s, dt); + + gUIMgr.Update(s, dt); + + if (xVec3Dist(&sOldPosPlayer, (xVec3*)&globals.player.ent.model->Mat->pos) > _2242 || + xVec3Dist(&sOldPosCamera, &globals.camera.mat.pos) > _2242) + { + sSuddenMove = 1; + } + else + { + sSuddenMove = 0; + } + + sOldPosPlayer = *(xVec3*)&globals.player.ent.model->Mat->pos; + sOldPosCamera = globals.camera.mat.pos; + + xUpdateCull_Update(globals.updateMgr, sSuddenMove ? 100 : 5); + + for (i = 0; i < s->num_update_base; i++) + { + if (!(b[i]->baseFlags & 0x40)) + { + switch (b[i]->baseType) + { + case eBaseTypeUIFont: + { + if (((xEnt*)b[i])->update) + { + ((xEnt*)b[i])->update((xEnt*)b[i], s, dt); + } + break; + } + case eBaseTypeZipLine: + { + if (((xEnt*)b[i])->update && !isPaused) + { + ((xEnt*)b[i])->update((xEnt*)b[i], s, dt); + } + break; + } + case eBaseTypeTrigger: + case eBaseTypePickup: + case eBaseTypePlatform: + case eBaseTypeDoor: + case eBaseTypeSavePoint: + case eBaseTypeItem: + case eBaseTypeDynamic: + case eBaseTypePendulum: + case eBaseTypeHangable: + case eBaseTypeButton: + case eBaseTypeDestructObj: + case eBaseTypeEGenerator: + case eBaseTypeNPC: + case eBaseTypeBoulder: + case eBaseTypeTeleportBox: + { + if (((xEnt*)b[i])->update && !isPaused) + { + ((xEnt*)b[i])->update((xEnt*)b[i], s, dt); + } + break; + } + case eBaseTypeTimer: + { + if (!isPaused || ((xTimer*)b[i])->runsInPause) + { + xTimerUpdate(b[i], s, dt); + } + break; + } + case eBaseTypeScript: + { + if (!isPaused) + { + zScriptUpdate(b[i], s, dt); + } + break; + } + case eBaseTypeFog: + { + if (!isPaused) + { + xFogUpdate(b[i], s, dt); + } + break; + } + case eBaseTypeParticleEmitter: + { + if (!isPaused) + { + xParEmitterUpdate(b[i], s, dt); + } + break; + } + case eBaseTypeParticleSystem: + { + if (!isPaused && !zGameIsPaused()) + { + xParSysUpdate(b[i], s, dt); + } + break; + } + case eBaseTypeLight: + { + if (!isPaused) + { + zLightUpdate(b[i], s, dt); + } + break; + } + case eBaseTypeSurface: + { + if (!isPaused || ((xSurface*)b[i])->type == XSURFACE_TYPE_3) + { + zSurfaceUpdate(b[i], s, dt); + } + break; + } + case eBaseTypeBusStop: + { + if (!isPaused) + { + zBusStop_Update(b[i], s, dt); + } + break; + } + case eBaseTypeDiscoFloor: + { + if (!isPaused) + { + ((z_disco_floor*)b[i])->update(*s, dt); + } + + break; + } + case eBaseTypeTaxi: + { + if (!isPaused) + { + zTaxi_Update(b[i], s, dt); + } + break; + } + case eBaseTypeCameraFly: + { + if (!isPaused) + { + zCameraFly_Update(b[i], s, dt); + } + break; + } + } + } + } + + if (!isPaused) + { + zEntSimpleObj_MgrCustomUpdate(s, dt); + } + + if (isPaused) + { + zUI_ScenePortalUpdate(); + } + else + { + zUI_ScenePortalSetToCurrentLevel(s); + } + + zNPCCommon_EjectPhlemOnPawz(); + + if (!isPaused) + { + zActionLineUpdate(dt); + xFXStreakUpdate(dt); + xFXShineUpdate(dt); + xFXFireworksUpdate(dt); + zLightningUpdate(dt); + zGustUpdateFX(dt); + xClimateUpdate(&gClimate, dt); + zShrapnel_Update(dt); + zCombo_Update(dt); + zFXUpdate(dt); + zLOD_Update(sSuddenMove ? 100 : 5); + zParPTankUpdate(dt); + xDecalUpdate(dt); + xCMupdate(dt); + + if (s->pendingPortal) + { + zGameStateSwitch(eGameState_SceneSwitch); + } + } + else + { + zCombo_HideImmediately(); + } +} + +static void zSceneRenderPreFX() +{ + zScene* s = globals.sceneCur; + + globals.currWorld = s->env->geom->world; + + xLightKit_Enable(NULL, globals.currWorld); + + zRenderState(SDRS_SkyBack); + xSkyDome_Render(); + + zRenderState(SDRS_Environment); + zLightAddLocalEnv(); + zEnvRender(s->env); + zLightRemoveLocalEnv(); + + zRenderState(SDRS_OpaqueModels); + z_disco_floor::render_all(); + + U32 shadowHackCase = 0; + + xEnt** entptr = &s->act_ents[s->num_act_ents - 1]; + xEnt** entlast = &s->act_ents[s->baseCount[eBaseTypeTrigger] + s->baseCount[eBaseTypePickup] + + s->baseCount[eBaseTypeStatic]]; + + xModelBucket_Begin(); + zEntSimpleObj_MgrUpdateRender(globals.currWorld, sTimeElapsed); + zEntSimpleObj_MgrCustomRender(); + + while (entptr >= entlast) + { + xEnt* ent = *entptr; + + if (ent->collType != XENT_COLLTYPE_TRIG) + { + if (ent->collType == XENT_COLLTYPE_PLYR) + { + shadowHackCase = 1; + } + else if (ent->render) + { + xLightKit_Enable(ent->lightKit, globals.currWorld); + ent->render(ent); + } + } + + entptr--; + } + + zShrapnel_Render(); + zEntPickup_Render((zEntPickup*)s->baseList[eBaseTypePickup], s->baseCount[eBaseTypePickup]); + xModelBucket_RenderOpaque(); + zNPCCommon_Glyphs_RenderAll(1); + zNPCCommon_Hazards_RenderAll(1); + xLightKit_Enable(NULL, globals.currWorld); + zEntPickup_RenderList((zEntPickup*)s->baseList[eBaseTypePickup], s->baseCount[eBaseTypePickup]); + + if (shadowHackCase == 1 && globals.player.Transparent <= 0 && !oob_state::render()) + { + xLightKit_Enable(globals.player.ent.lightKit, globals.currWorld); + + globals.player.ent.render(&globals.player.ent); + + xLightKit_Enable(NULL, globals.currWorld); + } + + if (globals.cmgr && globals.cmgr->csn->Ready) + { + xLightKit* objLightKit = NULL; + + if (globals.sceneCur->zen->easset->objectLightKit) + { + objLightKit = + (xLightKit*)xSTFindAsset(globals.sceneCur->zen->easset->objectLightKit, NULL); + } + + if (objLightKit) + { + xLightKit_Enable(objLightKit, globals.currWorld); + } + + xCutscene_Render(globals.cmgr->csn, NULL, NULL, NULL); + + if (objLightKit) + { + xLightKit_Enable(NULL, globals.currWorld); + } + } + + zEntPlayer_ShadowModelEnable(); + xShadowManager_Render(); + zEntPlayer_ShadowModelDisable(); + xShadowSimple_Render(); + + zRenderState(SDRS_AlphaModels); + xModelBucket_RenderAlpha(); + z_disco_floor::effects_render_all(); + xFXRingRender(); + + zRenderState(SDRS_Lightning); + zLightningRender(); + zActionLineRender(); + + zRenderState(SDRS_Streak); + xFXStreakRender(); + xFXShineRender(); + xFXRibbonRender(); + xFXAuraRender(); + + zRenderState(SDRS_Particles); + + zParSys* psys = (zParSys*)s->baseList[eBaseTypeParticleSystem]; + + for (S32 i = s->baseCount[eBaseTypeParticleSystem] - 1; i >= 0; i--, psys++) + { + xParSysRender(psys); + } + + xLightKit_Enable(NULL, globals.currWorld); + + zRenderState(SDRS_NPCVisual); + zNPCMgr_scenePostRender(); + zNPCCommon_Glyphs_RenderAll(0); + zNPCCommon_Hazards_RenderAll(0); + + zRenderState(SDRS_AlphaModels); + xParMgrRender(); + zParPTankRender(); + xPTankPoolRender(); + zNPCMgr_scenePostParticleRender(); + xDecalRender(); +} + +static void zSceneRenderPostFX() +{ + zRenderState(SDRS_Glare); + + xScrFXGlareRender(&globals.camera); + xScrFXFullScreenGlareRender(); + + if (zGameModeGet() == eGameMode_Intro && + (zGameStateGet() == eIntroState_Sony || zGameStateGet() == eIntroState_Publisher)) + { + render_mem_card_no_space(bytesNeeded, availOnDisk, neededFiles, + zGameStateGet() == eIntroState_Sony); + } + + cruise_bubble::render_screen(); + oob_state::fx_render(); + + zRenderState(SDRS_Font); + ztextbox::render_all(); + ztalkbox::render_all(); + + zRenderState(SDRS_Font); + xDrawEnd(); + xDrawBegin(); + + RwCameraEndUpdate(globals.camera.lo_cam); + RwCameraClear(globals.camera.lo_cam, NULL, rwCAMERACLEARZ); + RwCameraBeginUpdate(globals.camera.lo_cam); + + zUIRenderAll(); + + eGameMode mode = zGameModeGet(); + + if (mode != eGameMode_Game && mode != eGameMode_Stall) + { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); + zSceneSpawnRandomBubbles(); + + if (mode == eGameMode_Pause || mode == eGameMode_Save) + { + zParPTankUpdate(sTimeElapsed); + } + + zParPTankRender(); + } + + switch (mode) + { + case eGameMode_Load: + case eGameMode_WorldMap: + case eGameMode_ConceptArtGallery: + { + break; + } + default: + { + zRenderState(SDRS_HUD); + zhud::render(); + } + } + + xParMgrRender(); + + if (!zGameIsPaused()) + { + xCMrender(); + } + + if (zGameModeGet() == eGameMode_Intro && + (zGameStateGet() == eIntroState_Sony || zGameStateGet() == eIntroState_Publisher)) + { + render_mem_card_no_space(bytesNeeded, availOnDisk, neededFiles, + zGameStateGet() == eIntroState_Sony); + } + + xTRCRender(); + + if (zGameModeGet() == eGameMode_Intro && zGameStateGet() == eIntroState_License) + { + xScrFxDrawScreenSizeRectangle(); + } +} + +void zSceneRender() +{ + zSceneRenderPreFX(); + xScrFxRender(globals.camera.lo_cam); + zSceneRenderPostFX(); +} + +static void zSceneObjHashtableInit(S32 count) +{ + scobj_idbps = (IDBasePair*)xMemAllocSize(count * sizeof(IDBasePair)); + + memset(scobj_idbps, 0, count * sizeof(IDBasePair)); + + scobj_size = count; + nidbps = 0; +} + +static void zSceneObjHashtableExit() +{ + scobj_idbps = NULL; + scobj_size = -1; + nidbps = -1; +} + +static S32 zSceneObjHashtableUsage() +{ + return nidbps; +} + +static void zSceneObjHashtableAdd(U32 id, xBase* base) +{ + S32 k, chkd; + + chkd = id & (scobj_size - 1); + + for (k = 0; k < scobj_size; k++) + { + IDBasePair* idbp = &scobj_idbps[chkd]; + + if (idbp->id == 0) + { + idbp->id = id; + idbp->base = base; + nidbps++; + break; + } + + chkd++; + + if (chkd == scobj_size) + { + chkd = 0; + } + } +} + +static xBase* zSceneObjHashtableGet(U32 id) +{ + S32 k, chkd; + + chkd = id & (scobj_size - 1); + + for (k = 0; k < scobj_size; k++) + { + IDBasePair* idbp = &scobj_idbps[chkd]; + + if (idbp->id == id) + { + return idbp->base; + } + + if (idbp->id == 0) + { + return NULL; + } + + chkd++; + + if (chkd == scobj_size) + { + chkd = 0; + } + } + + return NULL; +} + +xBase* zSceneFindObject(U32 gameID) +{ + return zSceneObjHashtableGet(gameID); +} + +xBase* zSceneGetObject(S32 type, S32 idx) +{ + zScene* s = globals.sceneCur; + + if (s) + { + for (U32 i = 0; i < s->num_base; i++) + { + if (s->base[i] && type == s->base[i]->baseType) + { + if (idx == 0) + { + return s->base[i]; + } + else + { + idx--; + } + } + } + } + + return NULL; +} + +const char* zSceneGetName(U32 gameID) +{ + xBase* b = zSceneFindObject(gameID); + + if (b) + { + return zSceneGetName(b); + } + + return ""; +} + +const char* zSceneGetName(xBase* b) +{ + if (b) + { + const char* n = xSTAssetName(b->id); + + if (n) + { + return n; + } + } + + return ""; +} + +void zSceneForAllBase(xBase* (*func)(xBase*, zScene*, void*), void* data) +{ + zScene* s = globals.sceneCur; + + if (s) + { + for (U16 i = 0; i < s->num_base; i++) + { + if (!func(s->base[i], s, data)) + { + break; + } + } + } +} + +void zSceneForAllBase(xBase* (*func)(xBase*, zScene*, void*), S32 baseType, void* data) +{ + zScene* s = globals.sceneCur; + + if (s) + { + for (U16 i = 0; i < s->num_base; i++) + { + if (baseType == s->base[i]->baseType) + { + if (!func(s->base[i], s, data)) + { + break; + } + } + } + } +} + +static xBase* zSceneExitSoundIteratorCB(xBase* b, zScene*, void*) +{ + xSndParentDied((U32)b); + return b; +} + +void zSceneMemLvlChkCB() +{ +} + +U32 zSceneLeavingLevel() +{ + // non-matching: instruction order + + char curScene[4] = ""; + char nextScene[4] = ""; + + strncpy(curScene, xStrupr(xUtil_idtag2string(globals.sceneCur->sceneID, 0)), 4); + strncpy(nextScene, + xStrupr(xUtil_idtag2string(globals.sceneCur->pendingPortal->passet->sceneID, 0)), 4); + + return (curScene[0] != nextScene[3]); +} + +const char* zSceneGetLevelName(U32 sceneID) +{ + char c1 = (sceneID >> 24) & 0xFF; + char c2 = (sceneID >> 16) & 0xFF; + + for (S32 i = 0; i < sizeof(sLevelTable) / sizeof(sLevelTable[0]); i++) + { + if (c1 == sLevelTable[i].prefix[0] && c2 == sLevelTable[i].prefix[1]) + { + return sLevelTable[i].desc; + } + } + + return "Level Not Found"; +} + +U32 zSceneGetLevelIndex() +{ + return zSceneGetLevelIndex(globals.sceneCur->sceneID); +} + +U32 zSceneGetLevelIndex(U32 sceneID) +{ + char c1 = (sceneID >> 24) & 0xFF; + char c2 = (sceneID >> 16) & 0xFF; + + for (S32 i = 0; i < sizeof(sLevelTable) / sizeof(sLevelTable[0]); i++) + { + if (c1 == sLevelTable[i].prefix[0] && c2 == sLevelTable[i].prefix[1]) + { + return i; + } + } + + return 0; +} + +const char* zSceneGetLevelPrefix(U32 index) +{ + if (index >= sizeof(sLevelTable) / sizeof(sLevelTable[0])) + { + return NULL; + } + + return sLevelTable[index].prefix; +} + +const char* zSceneGetAreaname(U32) +{ + return "Temp"; +} + +U32 zSceneCalcProgress() +{ + return globals.player.Inv_Spatula; +} + +void zScene_UpdateFlyToInterface(F32 dt) +{ + zScene* s = globals.sceneCur; + + zEntPickup_UpdateFlyToInterface((zEntPickup*)s->baseList[eBaseTypePickup], + s->baseCount[eBaseTypePickup], dt); +} + +void zSceneCardCheckStartup_set(S32 needed, S32 available, S32 files) +{ + bytesNeeded = needed; + availOnDisk = available; + neededFiles = files; +} + +void zSceneEnableVisited(zScene* s) +{ + U32 uiNameID; + char uiName[64]; + char* sceneName; + + sceneName = xUtil_idtag2string(s->sceneID, 0); + + strcpy(uiName, sceneName); + + uiName[1] = ' '; + + strcat(uiName, " VISITED"); + + uiNameID = xStrHash(uiName); + + for (U32 i = 0; i < s->num_base; i++) + { + if (s->base[i] && s->base[i]->baseType == eBaseTypeUI && uiNameID == s->base[i]->id) + { + s->base[i]->baseFlags |= 0x1; + } + } +} + +void zSceneEnableScreenAdj(U32 enable) +{ + enableScreenAdj = enable; +} + +void zSceneSetOldScreenAdj() +{ + oldOffsetx = offsetx; + oldOffsety = offsety; +} + +U32 zScene_ScreenAdjustMode() +{ + return enableScreenAdj; +} + +xVec3 scale = { 0.2f, -0.7f, 1.5f }; + +void zSceneSpawnRandomBubbles() +{ + RwCamera* currentCamera = RwCameraGetCurrentCamera(); + + if (!currentCamera || zMenuIsFirstBoot()) + { + return; + } + + RwMatrix* mat = RwFrameGetMatrix(RwCameraGetFrame(currentCamera)); + F32 floatRand = xurand(); + + if (floatRand > 0.985f) + { + xVec3 pos, var_48; + F32 r; + + pos.x = mat->pos.x; + pos.y = mat->pos.y; + pos.z = mat->pos.z; + + r = xurand(); + r *= (((S32)(10000 * floatRand) % 2) ? 1 : -1); + + xVec3ScaleC(&var_48, (xVec3*)&mat->right, r, r, r); + xVec3Add(&pos, &pos, &var_48); + xVec3ScaleC(&var_48, (xVec3*)&mat->up, scale.y, scale.y, scale.y); + xVec3Add(&pos, &pos, &var_48); + xVec3ScaleC(&var_48, (xVec3*)&mat->at, scale.z, scale.z, scale.z); + xVec3Add(&pos, &pos, &var_48); + + zFX_SpawnBubbleMenuTrail(&pos, 1, NULL, NULL); + } +} + +static void zSceneAutoSave() +{ +} + +void xSystem_GapTrackReport() +{ +} + +void xDecalDestroy() +{ +} + +void xDecalRender() +{ +} + +U32 xBaseIsValid(xBase* xb) +{ + return xb->baseFlags & 0x4; +} + +void xModelBucket_RenderAlpha() +{ + xModelBucket_RenderAlphaBegin(); + xModelBucket_RenderAlphaLayer(31); + xModelBucket_RenderAlphaEnd(); +} + +void xNPCBasic::Save(xSerial*) const +{ +} + +void xNPCBasic::Load(xSerial*) +{ +} + +void xQuickCullInit(const xBox* box) +{ + xQuickCullInit(&xqc_def_ctrl, box); +} diff --git a/src/SB/Game/zScene.h b/src/SB/Game/zScene.h new file mode 100644 index 0000000..f325a95 --- /dev/null +++ b/src/SB/Game/zScene.h @@ -0,0 +1,72 @@ +#ifndef ZSCENE_H +#define ZSCENE_H + +#include "xScene.h" +#include "xClimate.h" + +#include "zPortal.h" +#include "xEnt.h" +#include "xEnv.h" +#include "zBase.h" + +struct zEnt; + +struct zScene : xScene +{ + _zPortal* pendingPortal; + union + { + U32 num_ents; + U32 num_base; + }; + union + { + xBase** base; + zEnt** ents; + }; + U32 num_update_base; + xBase** update_base; + U32 baseCount[eBaseTypeCount]; + xBase* baseList[eBaseTypeCount]; + _zEnv* zen; +}; + +extern _tagClimate gClimate; +extern _zEnv* gCurEnv; +extern U32 gTransitionSceneID; +extern F32 gSceneUpdateTime; + +void zSceneSet(xBase* b, U32 index); +void zSceneInitEnvironmentalSoundEffect(); +void zSceneInit(U32 theSceneID, S32 reloadInProgress); +void zSceneExit(S32 beginReload); +void zSceneUpdateSFXWidgets(); +void zSceneSwitch(_zPortal* p, S32 forceSameScene); +void zSceneSave(zScene* ent, xSerial* s); +void zSceneLoad(zScene* ent, xSerial* s); +void zSceneSetup(); +void zSceneUpdate(F32 dt); +void zSceneRender(); +xBase* zSceneFindObject(U32 gameID); +xBase* zSceneGetObject(S32 type, S32 idx); +const char* zSceneGetName(U32 gameID); +const char* zSceneGetName(xBase* b); +void zSceneForAllBase(xBase* (*func)(xBase*, zScene*, void*), void* data); +void zSceneForAllBase(xBase* (*func)(xBase*, zScene*, void*), S32 baseType, void* data); +void zSceneMemLvlChkCB(); +U32 zSceneLeavingLevel(); +const char* zSceneGetLevelName(U32 sceneID); +U32 zSceneGetLevelIndex(); +U32 zSceneGetLevelIndex(U32 sceneID); +const char* zSceneGetLevelPrefix(U32 index); +const char* zSceneGetAreaname(U32); +U32 zSceneCalcProgress(); +void zScene_UpdateFlyToInterface(F32 dt); +void zSceneCardCheckStartup_set(S32 needed, S32 available, S32 files); +void zSceneEnableVisited(zScene* s); +void zSceneEnableScreenAdj(U32 enable); +void zSceneSetOldScreenAdj(); +U32 zScene_ScreenAdjustMode(); +void zSceneSpawnRandomBubbles(); + +#endif diff --git a/src/SB/Game/zShrapnel.cpp b/src/SB/Game/zShrapnel.cpp new file mode 100644 index 0000000..305fd9a --- /dev/null +++ b/src/SB/Game/zShrapnel.cpp @@ -0,0 +1,3 @@ +#include "zShrapnel.h" + +#include diff --git a/src/SB/Game/zShrapnel.h b/src/SB/Game/zShrapnel.h new file mode 100644 index 0000000..ccc0de2 --- /dev/null +++ b/src/SB/Game/zShrapnel.h @@ -0,0 +1,223 @@ +#ifndef ZSHRAPNEL_H +#define ZSHRAPNEL_H + +#include "xModel.h" +#include "xCurveAsset.h" +#include "xCollide.h" + +#include "zParEmitter.h" +//#include "zLightning.h" + +#include +#include + +typedef struct zFrag; +typedef struct zShrapnelAsset; + +enum zFragLocType +{ + eFragLocBone, + eFragLocBoneUpdated, + eFragLocBoneLocal, + eFragLocBoneLocalUpdated, + eFragLocTag, + eFragLocTagUpdated, + eFragLocCount, + eFragLocForceSize = 0x7fffffff +}; + +struct zFragBone +{ + S32 index; + xVec3 offset; +}; + +struct zFragLocInfo +{ + union + { + zFragBone bone; + xModelTag tag; + }; +}; + +struct zFragLocation +{ + zFragLocType type; + zFragLocInfo info; +}; + +enum zFragType +{ + eFragInactive, + eFragGroup, + eFragShrapnel, + eFragParticle, + eFragProjectile, + eFragLightning, + eFragSound, + eFragShockwave, + eFragCount, + eFragForceSize = 0x7fffffff +}; + +struct zFragAsset +{ + zFragType type; + U32 id; + U32 parentID[2]; + F32 lifetime; + F32 delay; +}; + +struct zFragGroup +{ + zFrag* list[21]; +}; + +struct zFragParticleAsset : zFragAsset +{ + zFragLocation source; + zFragLocation vel; + xParEmitterCustomSettings emit; + U32 parEmitterID; + zParEmitter* parEmitter; +}; + +struct zFragParticle +{ + zFragParticleAsset* fasset; +}; + +struct zFragProjectileAsset : zFragAsset +{ + U32 modelInfoID; + RpAtomic* modelFile; + zFragLocation launch; + zFragLocation vel; + F32 bounce; + S32 maxBounces; + U32 flags; + U32 childID; + zShrapnelAsset* child; + F32 minScale; + F32 maxScale; + U32 scaleCurveID; + xCurveAsset* scaleCurve; + F32 gravity; +}; + +struct zFragProjectile +{ + zFragProjectileAsset* fasset; + xModelInstance* model; + xParabola path; + F32 angVel; + F32 t; + F32 tColl; + S32 numBounces; + F32 scale; + F32 parentScale; + F32 alpha; + xVec3 N; + xVec3 axis; +}; + +struct zFragLightningAsset : zFragAsset +{ + zFragLocation start; + zFragLocation end; + U32 startParentID; + U32 endParentID; +}; + +struct zFragLightning +{ + zFragLightningAsset* fasset; + xModelInstance* startParent; + xModelInstance* endParent; + //zLightning* lightning; +}; + +struct zFragSoundAsset : zFragAsset +{ + U32 assetID; + zFragLocation source; + F32 volume; + F32 innerRadius; + F32 outerRadius; +}; + +struct zFragSound +{ + zFragSoundAsset* fasset; + xVec3 location; + U32 soundID; +}; + +struct zFragShockwaveAsset : zFragAsset +{ + U32 modelInfoID; + F32 birthRadius; + F32 deathRadius; + F32 birthVelocity; + F32 deathVelocity; + F32 birthSpin; + F32 deathSpin; + F32 birthColor[4]; + F32 deathColor[4]; +}; + +struct zFragShockwave +{ + zFragShockwaveAsset* fasset; + F32 currSize; + F32 currVelocity; + F32 deltVelocity; + F32 currSpin; + F32 deltSpin; + F32 currColor[4]; + F32 deltColor[4]; +}; + +struct zFragInfo +{ + union + { + zFragGroup group; + zFragParticle particle; + zFragProjectile projectile; + zFragLightning lightning; + zFragSound sound; + zFragShockwave shockwave; + }; +}; + +struct zFrag +{ + zFragType type; + zFragInfo info; + F32 delay; + F32 alivetime; + F32 lifetime; + void (*update)(zFrag*, F32); + xModelInstance* parent[2]; + zFrag* prev; + zFrag* next; +}; + +struct zShrapnelAsset +{ + S32 fassetCount; + U32 shrapnelID; + void (*initCB)(zShrapnelAsset*, xModelInstance*, xVec3*, void (*)(zFrag*, zFragAsset*)); +}; + +struct zScene; + +void zShrapnel_SceneInit(zScene*); +void zShrapnel_Update(F32 dt); +void zShrapnel_Reset(); +void zShrapnel_Render(); + +#endif diff --git a/src/SB/Game/zTalkBox.cpp b/src/SB/Game/zTalkBox.cpp index 644512e..d7546f1 100644 --- a/src/SB/Game/zTalkBox.cpp +++ b/src/SB/Game/zTalkBox.cpp @@ -2,6 +2,8 @@ #include +// DIRECTLY PORTED FROM BFBB + namespace { struct SharedTalkboxState diff --git a/src/SB/Game/zTalkBox.h b/src/SB/Game/zTalkBox.h index fd9c020..0d335d7 100644 --- a/src/SB/Game/zTalkBox.h +++ b/src/SB/Game/zTalkBox.h @@ -5,6 +5,9 @@ //#include "zNPCTypeCommon.h" #include "xScene.h" +#include "zNMECommon.h" + +// DIRECTLY PORTED FROM BFBB struct ztalkbox : xBase { @@ -77,7 +80,7 @@ struct ztalkbox : xBase const char* noquit; const char* yesno; } prompt; - //zNPCCommon* npc; + zNPCCommon* npc; static void init(); static void load(xBase& data, xDynAsset& asset, size_t); @@ -87,7 +90,7 @@ struct ztalkbox : xBase static void permit(U32 add_flags, U32 remove_flags); static ztalkbox* get_active(); - //void start_talk(U32 textID, callback*, zNPCCommon*); // FIXME: params not verified + void start_talk(U32 textID, callback*, zNPCCommon*); // FIXME: params not verified void stop_talk(); void set_text(U32 textID); diff --git a/src/SB/Game/zTaskBox.cpp b/src/SB/Game/zTaskBox.cpp index 1d55916..d9b5841 100644 --- a/src/SB/Game/zTaskBox.cpp +++ b/src/SB/Game/zTaskBox.cpp @@ -1,6 +1,13 @@ #include "zTaskBox.h" -#include "zTalkBox.h" + +#include "xEvent.h" +#include "xstransvc.h" + #include "zBase.h" +#include "zScene.h" +#include "zTalkBox.h" + +#include // CODE PORTED DIRECTLY FROM BFBB @@ -52,31 +59,31 @@ void ztaskbox::write(xSerial& s) } // WIP. -// void ztaskbox::start_talk(zNMECommon* npc) -// { -// ztaskbox* curr = this->current; -// if (curr != NULL) -// { -// if (curr == this) -// { -// if (this->flag.enabled && this->state != STATE_INVALID) -// { -// //TODO!!! -// } -// } -// else -// { -// curr->set_callback(this->cb); -// this->current->start_talk(NULL); -// } -// } -// } - -// void ztaskbox::talk_callback::reset(ztaskbox& task) -// { -// this->task = &task; -// this->answer = ztalkbox::ANSWER_CONTINUE; -// } +void ztaskbox::start_talk(zNPCCommon* npc) +{ + ztaskbox* curr = this->current; + if (curr != NULL) + { + if (curr == this) + { + if (this->flag.enabled && this->state != STATE_INVALID) + { + //TODO!!! + } + } + else + { + curr->set_callback(this->cb); + this->current->start_talk(NULL); + } + } +} + +void ztaskbox::talk_callback::reset(ztaskbox& task) +{ + this->task = &task; + this->answer = ztalkbox::ANSWER_CONTINUE; +} void ztaskbox::stop_talk() { @@ -103,13 +110,13 @@ void ztaskbox::stop_talk() return; } - //ztalkbox* other = (ztalkbox*)zSceneFindObject(this->asset->talk_box); + ztalkbox* other = (ztalkbox*)zSceneFindObject(this->asset->talk_box); - // if (other) - // { - // other->stop_talk(); - // shared = NULL; - // } + if (other) + { + other->stop_talk(); + shared = NULL; + } } void ztaskbox::enable() @@ -170,8 +177,8 @@ void ztaskbox::complete() { this->state = STATE_INVALID; this->flag.enabled = false; - //zEntEvent(this, this, eEventTaskBox_OnComplete); - //this->current = (ztaskbox*)zSceneFindObject(this->asset->next_task); + zEntEvent(this, this, eEventTaskBox_OnComplete); + this->current = (ztaskbox*)zSceneFindObject(this->asset->next_task); // Bruh if (this->current != NULL) @@ -205,7 +212,7 @@ void ztaskbox::load(xBase& data, xDynAsset& asset, size_t num) bool ztaskbox::exists(state_enum stage) { U32 state = this->asset->stages[stage]; - //return state != STATE_BEGIN && xSTFindAsset(state, NULL); + return state != STATE_BEGIN && xSTFindAsset(state, NULL); } void ztaskbox::on_talk_start() diff --git a/src/SB/Game/zTaskBox.h b/src/SB/Game/zTaskBox.h index 5f45d6c..a1e5005 100644 --- a/src/SB/Game/zTaskBox.h +++ b/src/SB/Game/zTaskBox.h @@ -4,11 +4,13 @@ #include "xBase.h" #include "xDynAsset.h" -//#include "zNPCTypeCommon.h" +#include "zNMECommon.h" #include "zTalkBox.h" #include +// DIRECTLY PORTED FROM BFBB + struct ztaskbox : xBase { struct flagData @@ -69,7 +71,7 @@ struct ztaskbox : xBase void set_state(state_enum state); void set_callback(callback* cb); void stop_talk(); - //void start_talk(zNPCCommon* npc); + void start_talk(zNPCCommon* npc); void write(xSerial& s); void read(xSerial& s); void load(const asset_type& a); From 95f2f62cbac4f85e3ce7d3d265f45832b79bd12a Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Thu, 24 Apr 2025 14:42:30 -0400 Subject: [PATCH 5/7] fixed the error in xBehaviour --- src/SB/Core/x/xBehaviour.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/SB/Core/x/xBehaviour.h b/src/SB/Core/x/xBehaviour.h index a258860..09fe4c8 100644 --- a/src/SB/Core/x/xBehaviour.h +++ b/src/SB/Core/x/xBehaviour.h @@ -156,11 +156,6 @@ struct xGoal : xListItem, xFactoryInst xGoalPreCalcCallback fun_precalc; xGoalChkRuleCallback fun_chkRule; - xPsyche* psyche; //0x18 - en_GOALSTATE stat; - S32 flg_able; //0x20 - S32 (*fun_process)(xGoal*, void*, en_trantype*, F32, void*); - void* cbdata; xGoal(S32 goalID) From f66e3bfb9c3265b3993217352a54602c87418622 Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Thu, 24 Apr 2025 14:47:25 -0400 Subject: [PATCH 6/7] fix pt2 --- src/SB/Core/x/xBehaviour.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/SB/Core/x/xBehaviour.h b/src/SB/Core/x/xBehaviour.h index 09fe4c8..0d23c90 100644 --- a/src/SB/Core/x/xBehaviour.h +++ b/src/SB/Core/x/xBehaviour.h @@ -219,15 +219,6 @@ struct xGoal : xListItem, xFactoryInst virtual S32 SysEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* toParamWidget, S32* handled) - - S32 flg_npcgauto : 8; - S32 flg_npcgable : 16; - S32 bul_entered : 1; - S32 bul_resumed : 1; - S32 bul_unused : 6; - } flags; - struct - { return 1; } From 24898b8423c8ba042f45d54d0150056bfa622f5d Mon Sep 17 00:00:00 2001 From: Colin Miller Date: Fri, 25 Apr 2025 00:45:56 -0400 Subject: [PATCH 7/7] Cleaned up the .cpp files. Ported tons of code to the core/gc/iWad file. Most code iosnt exactly right, but should be easily fixable --- .../MSL/MSL_C/MSL_Common/Include/stdlib.h | 2 +- src/SB/Core/gc/iAnim.cpp | 234 - src/SB/Core/gc/iAnimSKB.cpp | 132 - src/SB/Core/gc/iCollide.cpp | 7 - src/SB/Core/gc/iCollideFast.cpp | 6 - src/SB/Core/gc/iCutscene.cpp | 358 -- src/SB/Core/gc/iDraw.cpp | 41 - src/SB/Core/gc/iEnv.cpp | 216 - src/SB/Core/gc/iFMV.cpp | 422 -- src/SB/Core/gc/iFX.cpp | 3 - src/SB/Core/gc/iFile.cpp | 351 -- src/SB/Core/gc/iFile.h | 4 +- src/SB/Core/gc/iLight.cpp | 156 - src/SB/Core/gc/iMath.cpp | 39 - src/SB/Core/gc/iMath3.cpp | 751 --- src/SB/Core/gc/iMemMgr.cpp | 55 - src/SB/Core/gc/iMix.cpp | 3 - src/SB/Core/gc/iModel.cpp | 7 - src/SB/Core/gc/iMorph.cpp | 3 - src/SB/Core/gc/iPad.cpp | 168 - src/SB/Core/gc/iParMgr.cpp | 11 - src/SB/Core/gc/iScrFX.cpp | 117 - src/SB/Core/gc/iSnd.cpp | 165 - src/SB/Core/gc/iSystem.cpp | 235 - src/SB/Core/gc/iTime.cpp | 57 - src/SB/Core/gc/iWad.cpp | 4082 +++++++++++++++++ src/SB/Core/gc/iWad.h | 45 + src/SB/Core/gc/isavegame.cpp | 2048 --------- src/SB/Core/gc/ngcrad3d.c | 1 - src/SB/Core/gc/ngcrad3d.cpp | 3 - src/SB/Core/x/iCamera.cpp | 341 -- src/SB/Core/x/xAnim.cpp | 2185 --------- src/SB/Core/x/xBase.cpp | 71 - src/SB/Core/x/xBehaveGoalSimple.cpp | 85 - src/SB/Core/x/xBehaveMgr.cpp | 210 - src/SB/Core/x/xBehaviour.cpp | 120 - src/SB/Core/x/xBound.cpp | 495 -- src/SB/Core/x/xCM.cpp | 115 - src/SB/Core/x/xCamera.cpp | 1344 ------ src/SB/Core/x/xClimate.cpp | 199 - src/SB/Core/x/xClumpColl.cpp | 92 - src/SB/Core/x/xCollide.cpp | 242 - src/SB/Core/x/xCollideFast.cpp | 36 - src/SB/Core/x/xColor.cpp | 16 - src/SB/Core/x/xCounter.cpp | 160 - src/SB/Core/x/xCurveAsset.cpp | 38 - src/SB/Core/x/xCutscene.cpp | 185 - src/SB/Core/x/xDebug.cpp | 56 - src/SB/Core/x/xDecal.cpp | 11 - src/SB/Core/x/xEntBoulder.cpp | 63 - src/SB/Core/x/xEntDrive.cpp | 422 -- src/SB/Core/x/xEntMotion.cpp | 224 - src/SB/Core/x/xEnv.cpp | 38 - src/SB/Core/x/xEvent.cpp | 138 - src/SB/Core/x/xFFX.cpp | 166 - src/SB/Core/x/xFX.cpp | 549 --- src/SB/Core/x/xFXHighDynamicRange.h | 0 src/SB/Core/x/xFactory.cpp | 247 - src/SB/Core/x/xFog.cpp | 82 - src/SB/Core/x/xFont.cpp | 3705 --------------- src/SB/Core/x/xGrid.cpp | 214 - src/SB/Core/x/xGroup.cpp | 215 - src/SB/Core/x/xHud.cpp | 469 -- src/SB/Core/x/xHudFontMeter.cpp | 3 - src/SB/Core/x/xHudMeter.cpp | 3 - src/SB/Core/x/xHudModel.cpp | 77 - src/SB/Core/x/xHudText.cpp | 143 - src/SB/Core/x/xHudUnitMeter.cpp | 3 - src/SB/Core/x/xIni.cpp | 202 - src/SB/Core/x/xJSP.cpp | 62 - src/SB/Core/x/xJaw.cpp | 88 - src/SB/Core/x/xLaserBolt.cpp | 69 - src/SB/Core/x/xLightKit.cpp | 149 - src/SB/Core/x/xMath.cpp | 159 - src/SB/Core/x/xMath2.cpp | 4 - src/SB/Core/x/xMath3.cpp | 766 ---- src/SB/Core/x/xMemMgr.cpp | 395 -- src/SB/Core/x/xModel.cpp | 229 - src/SB/Core/x/xModelBucket.cpp | 109 - src/SB/Core/x/xMorph.cpp | 122 - src/SB/Core/x/xMovePoint.cpp | 180 - src/SB/Core/x/xNPCBasic.cpp | 366 -- src/SB/Core/x/xPad.cpp | 122 - src/SB/Core/x/xPar.cpp | 97 - src/SB/Core/x/xParCmd.cpp | 800 ---- src/SB/Core/x/xParEmitter.cpp | 3 - src/SB/Core/x/xParEmitterType.cpp | 3 - src/SB/Core/x/xParGroup.cpp | 303 -- src/SB/Core/x/xParMgr.cpp | 49 - src/SB/Core/x/xParSys.cpp | 3 - src/SB/Core/x/xPartition.cpp | 42 - src/SB/Core/x/xPtankPool.cpp | 3 - src/SB/Core/x/xQuickCull.cpp | 41 - src/SB/Core/x/xRMemData.cpp | 72 - src/SB/Core/x/xRenderState.cpp | 31 - src/SB/Core/x/xSFX.cpp | 103 - src/SB/Core/x/xScene.cpp | 433 -- src/SB/Core/x/xScrFx.cpp | 11 - src/SB/Core/x/xShadow.cpp | 272 -- src/SB/Core/x/xShadowSimple.cpp | 3 - src/SB/Core/x/xSkyDome.cpp | 101 - src/SB/Core/x/xSnd.cpp | 444 -- src/SB/Core/x/xSnd.h | 1 + src/SB/Core/x/xSpline.cpp | 3 - src/SB/Core/x/xString.cpp | 102 - src/SB/Core/x/xSurface.cpp | 70 - src/SB/Core/x/xTRC.cpp | 67 - src/SB/Core/x/xTRC.h | 2 +- src/SB/Core/x/xTimer.cpp | 98 - src/SB/Core/x/xUpdateCull.cpp | 98 - src/SB/Core/x/xVec3.cpp | 96 - src/SB/Core/x/xVolume.cpp | 40 - src/SB/Core/x/xbinio.cpp | 734 --- src/SB/Core/x/xhipio.cpp | 511 --- src/SB/Core/x/xordarray.cpp | 183 - src/SB/Core/x/xpkrsvc.cpp | 1768 ------- src/SB/Core/x/xsavegame.cpp | 1480 ------ src/SB/Core/x/xserializer.cpp | 3 - src/SB/Core/x/xstransvc.cpp | 587 --- src/SB/Core/x/xutil.cpp | 181 - src/SB/Game/zActionLine.h | 17 + src/SB/Game/zAssetTypes.h | 48 + src/SB/Game/zCamMarker.h | 20 + src/SB/Game/zCamera.h | 122 + src/SB/Game/zCameraFly.h | 29 + src/SB/Game/zCameraTweak.h | 30 + src/SB/Game/zCollGeom.h | 21 + src/SB/Game/zCombo.h | 15 + src/SB/Game/zConditional.h | 32 + src/SB/Game/zCutsceneMgr.h | 47 + src/SB/Game/zDiscoFloor.h | 97 + src/SB/Game/zDispatcher.h | 83 + src/SB/Game/zEGenerator.h | 46 + src/SB/Game/zEnt.cpp | 935 ++++ src/SB/Game/zEnt.h | 63 + src/SB/Game/zEntButton.h | 48 + src/SB/Game/zEntCruiseBubble.h | 655 +++ src/SB/Game/zEntDestructObj.h | 78 + src/SB/Game/zEntHangable.h | 42 + src/SB/Game/zEntPickup.h | 89 + src/SB/Game/zEntPlayer.h | 439 ++ src/SB/Game/zEntPlayerAnimationTables.h | 4 + src/SB/Game/zEntPlayerBungeeState.h | 74 + src/SB/Game/zEntPlayerOOBState.h | 190 + src/SB/Game/zEntSimpleObj.h | 57 + src/SB/Game/zEntTeleportBox.h | 50 + src/SB/Game/zEntTrigger.h | 37 + src/SB/Game/zEnv.h | 22 + src/SB/Game/zEvent.h | 11 + src/SB/Game/zFX.h | 102 + src/SB/Game/zFeet.h | 8 + src/SB/Game/zGame.h | 119 + src/SB/Game/zGameExtras.h | 89 + src/SB/Game/zGameState.h | 108 + src/SB/Game/zGlobals.h | 327 ++ src/SB/Game/zGoo.h | 18 + src/SB/Game/zGrid.h | 18 + src/SB/Game/zGust.h | 44 + src/SB/Game/zHud.h | 17 + src/SB/Game/zLOD.h | 29 + src/SB/Game/zLasso.h | 59 + src/SB/Game/zLight.h | 65 + src/SB/Game/zLightEffect.h | 29 + src/SB/Game/zLightning.h | 116 + src/SB/Game/zMain.h | 4 + src/SB/Game/zMenu.h | 18 + src/SB/Game/zMusic.cpp | 495 ++ src/SB/Game/zMusic.h | 50 + src/SB/Game/zParCmd.h | 8 + src/SB/Game/zParPTank.h | 34 + src/SB/Game/zParSys.h | 10 + src/SB/Game/zPendulum.h | 30 + src/SB/Game/zPickupTable.h | 23 + src/SB/Game/zPlatform.h | 183 + src/SB/Game/zRenderState.h | 38 + src/SB/Game/zRumble.h | 41 + src/SB/Game/zSaveLoad.h | 105 + 177 files changed, 9720 insertions(+), 30212 deletions(-) delete mode 100644 src/SB/Core/gc/iAnim.cpp delete mode 100644 src/SB/Core/gc/iAnimSKB.cpp delete mode 100644 src/SB/Core/gc/iCollide.cpp delete mode 100644 src/SB/Core/gc/iCollideFast.cpp delete mode 100644 src/SB/Core/gc/iCutscene.cpp delete mode 100644 src/SB/Core/gc/iDraw.cpp delete mode 100644 src/SB/Core/gc/iEnv.cpp delete mode 100644 src/SB/Core/gc/iFMV.cpp delete mode 100644 src/SB/Core/gc/iFX.cpp delete mode 100644 src/SB/Core/gc/iFile.cpp delete mode 100644 src/SB/Core/gc/iLight.cpp delete mode 100644 src/SB/Core/gc/iMath.cpp delete mode 100644 src/SB/Core/gc/iMath3.cpp delete mode 100644 src/SB/Core/gc/iMemMgr.cpp delete mode 100644 src/SB/Core/gc/iMix.cpp delete mode 100644 src/SB/Core/gc/iModel.cpp delete mode 100644 src/SB/Core/gc/iMorph.cpp delete mode 100644 src/SB/Core/gc/iPad.cpp delete mode 100644 src/SB/Core/gc/iParMgr.cpp delete mode 100644 src/SB/Core/gc/iSnd.cpp delete mode 100644 src/SB/Core/gc/iSystem.cpp delete mode 100644 src/SB/Core/gc/iTime.cpp create mode 100644 src/SB/Core/gc/iWad.h delete mode 100644 src/SB/Core/gc/isavegame.cpp delete mode 100644 src/SB/Core/gc/ngcrad3d.c delete mode 100644 src/SB/Core/gc/ngcrad3d.cpp delete mode 100644 src/SB/Core/x/iCamera.cpp delete mode 100644 src/SB/Core/x/xAnim.cpp delete mode 100644 src/SB/Core/x/xBase.cpp delete mode 100644 src/SB/Core/x/xBehaveGoalSimple.cpp delete mode 100644 src/SB/Core/x/xBehaveMgr.cpp delete mode 100644 src/SB/Core/x/xBehaviour.cpp delete mode 100644 src/SB/Core/x/xBound.cpp delete mode 100644 src/SB/Core/x/xCM.cpp delete mode 100644 src/SB/Core/x/xClimate.cpp delete mode 100644 src/SB/Core/x/xClumpColl.cpp delete mode 100644 src/SB/Core/x/xCollide.cpp delete mode 100644 src/SB/Core/x/xCollideFast.cpp delete mode 100644 src/SB/Core/x/xColor.cpp delete mode 100644 src/SB/Core/x/xCounter.cpp delete mode 100644 src/SB/Core/x/xCurveAsset.cpp delete mode 100644 src/SB/Core/x/xCutscene.cpp delete mode 100644 src/SB/Core/x/xDebug.cpp delete mode 100644 src/SB/Core/x/xDecal.cpp delete mode 100644 src/SB/Core/x/xEntBoulder.cpp delete mode 100644 src/SB/Core/x/xEntDrive.cpp delete mode 100644 src/SB/Core/x/xEntMotion.cpp delete mode 100644 src/SB/Core/x/xEnv.cpp delete mode 100644 src/SB/Core/x/xEvent.cpp delete mode 100644 src/SB/Core/x/xFFX.cpp delete mode 100644 src/SB/Core/x/xFX.cpp create mode 100644 src/SB/Core/x/xFXHighDynamicRange.h delete mode 100644 src/SB/Core/x/xFactory.cpp delete mode 100644 src/SB/Core/x/xFog.cpp delete mode 100644 src/SB/Core/x/xFont.cpp delete mode 100644 src/SB/Core/x/xGrid.cpp delete mode 100644 src/SB/Core/x/xGroup.cpp delete mode 100644 src/SB/Core/x/xHud.cpp delete mode 100644 src/SB/Core/x/xHudFontMeter.cpp delete mode 100644 src/SB/Core/x/xHudMeter.cpp delete mode 100644 src/SB/Core/x/xHudModel.cpp delete mode 100644 src/SB/Core/x/xHudText.cpp delete mode 100644 src/SB/Core/x/xHudUnitMeter.cpp delete mode 100644 src/SB/Core/x/xIni.cpp delete mode 100644 src/SB/Core/x/xJSP.cpp delete mode 100644 src/SB/Core/x/xJaw.cpp delete mode 100644 src/SB/Core/x/xLaserBolt.cpp delete mode 100644 src/SB/Core/x/xLightKit.cpp delete mode 100644 src/SB/Core/x/xMath.cpp delete mode 100644 src/SB/Core/x/xMath2.cpp delete mode 100644 src/SB/Core/x/xMath3.cpp delete mode 100644 src/SB/Core/x/xMemMgr.cpp delete mode 100644 src/SB/Core/x/xModel.cpp delete mode 100644 src/SB/Core/x/xModelBucket.cpp delete mode 100644 src/SB/Core/x/xMorph.cpp delete mode 100644 src/SB/Core/x/xMovePoint.cpp delete mode 100644 src/SB/Core/x/xNPCBasic.cpp delete mode 100644 src/SB/Core/x/xPad.cpp delete mode 100644 src/SB/Core/x/xPar.cpp delete mode 100644 src/SB/Core/x/xParCmd.cpp delete mode 100644 src/SB/Core/x/xParEmitter.cpp delete mode 100644 src/SB/Core/x/xParEmitterType.cpp delete mode 100644 src/SB/Core/x/xParGroup.cpp delete mode 100644 src/SB/Core/x/xParMgr.cpp delete mode 100644 src/SB/Core/x/xParSys.cpp delete mode 100644 src/SB/Core/x/xPartition.cpp delete mode 100644 src/SB/Core/x/xPtankPool.cpp delete mode 100644 src/SB/Core/x/xQuickCull.cpp delete mode 100644 src/SB/Core/x/xRMemData.cpp delete mode 100644 src/SB/Core/x/xRenderState.cpp delete mode 100644 src/SB/Core/x/xSFX.cpp delete mode 100644 src/SB/Core/x/xScene.cpp delete mode 100644 src/SB/Core/x/xScrFx.cpp delete mode 100644 src/SB/Core/x/xShadow.cpp delete mode 100644 src/SB/Core/x/xShadowSimple.cpp delete mode 100644 src/SB/Core/x/xSkyDome.cpp delete mode 100644 src/SB/Core/x/xSnd.cpp delete mode 100644 src/SB/Core/x/xSpline.cpp delete mode 100644 src/SB/Core/x/xString.cpp delete mode 100644 src/SB/Core/x/xSurface.cpp delete mode 100644 src/SB/Core/x/xTRC.cpp delete mode 100644 src/SB/Core/x/xTimer.cpp delete mode 100644 src/SB/Core/x/xUpdateCull.cpp delete mode 100644 src/SB/Core/x/xVec3.cpp delete mode 100644 src/SB/Core/x/xVolume.cpp delete mode 100644 src/SB/Core/x/xbinio.cpp delete mode 100644 src/SB/Core/x/xhipio.cpp delete mode 100644 src/SB/Core/x/xordarray.cpp delete mode 100644 src/SB/Core/x/xpkrsvc.cpp delete mode 100644 src/SB/Core/x/xsavegame.cpp delete mode 100644 src/SB/Core/x/xserializer.cpp delete mode 100644 src/SB/Core/x/xstransvc.cpp delete mode 100644 src/SB/Core/x/xutil.cpp create mode 100644 src/SB/Game/zActionLine.h create mode 100644 src/SB/Game/zAssetTypes.h create mode 100644 src/SB/Game/zCamMarker.h create mode 100644 src/SB/Game/zCamera.h create mode 100644 src/SB/Game/zCameraFly.h create mode 100644 src/SB/Game/zCameraTweak.h create mode 100644 src/SB/Game/zCollGeom.h create mode 100644 src/SB/Game/zCombo.h create mode 100644 src/SB/Game/zConditional.h create mode 100644 src/SB/Game/zCutsceneMgr.h create mode 100644 src/SB/Game/zDiscoFloor.h create mode 100644 src/SB/Game/zDispatcher.h create mode 100644 src/SB/Game/zEGenerator.h create mode 100644 src/SB/Game/zEnt.cpp create mode 100644 src/SB/Game/zEnt.h create mode 100644 src/SB/Game/zEntButton.h create mode 100644 src/SB/Game/zEntCruiseBubble.h create mode 100644 src/SB/Game/zEntDestructObj.h create mode 100644 src/SB/Game/zEntHangable.h create mode 100644 src/SB/Game/zEntPickup.h create mode 100644 src/SB/Game/zEntPlayer.h create mode 100644 src/SB/Game/zEntPlayerAnimationTables.h create mode 100644 src/SB/Game/zEntPlayerBungeeState.h create mode 100644 src/SB/Game/zEntPlayerOOBState.h create mode 100644 src/SB/Game/zEntSimpleObj.h create mode 100644 src/SB/Game/zEntTeleportBox.h create mode 100644 src/SB/Game/zEntTrigger.h create mode 100644 src/SB/Game/zEnv.h create mode 100644 src/SB/Game/zEvent.h create mode 100644 src/SB/Game/zFX.h create mode 100644 src/SB/Game/zFeet.h create mode 100644 src/SB/Game/zGame.h create mode 100644 src/SB/Game/zGameExtras.h create mode 100644 src/SB/Game/zGameState.h create mode 100644 src/SB/Game/zGlobals.h create mode 100644 src/SB/Game/zGoo.h create mode 100644 src/SB/Game/zGrid.h create mode 100644 src/SB/Game/zGust.h create mode 100644 src/SB/Game/zHud.h create mode 100644 src/SB/Game/zLOD.h create mode 100644 src/SB/Game/zLasso.h create mode 100644 src/SB/Game/zLight.h create mode 100644 src/SB/Game/zLightEffect.h create mode 100644 src/SB/Game/zLightning.h create mode 100644 src/SB/Game/zMain.h create mode 100644 src/SB/Game/zMenu.h create mode 100644 src/SB/Game/zMusic.cpp create mode 100644 src/SB/Game/zMusic.h create mode 100644 src/SB/Game/zParCmd.h create mode 100644 src/SB/Game/zParPTank.h create mode 100644 src/SB/Game/zParSys.h create mode 100644 src/SB/Game/zPendulum.h create mode 100644 src/SB/Game/zPickupTable.h create mode 100644 src/SB/Game/zPlatform.h create mode 100644 src/SB/Game/zRenderState.h create mode 100644 src/SB/Game/zRumble.h create mode 100644 src/SB/Game/zSaveLoad.h diff --git a/include/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/stdlib.h b/include/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/stdlib.h index ffd0d5c..c5dfcbd 100644 --- a/include/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/stdlib.h +++ b/include/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/stdlib.h @@ -18,4 +18,4 @@ long abs(long n); } #endif -#endif \ No newline at end of file +#endif diff --git a/src/SB/Core/gc/iAnim.cpp b/src/SB/Core/gc/iAnim.cpp deleted file mode 100644 index 87e56de..0000000 --- a/src/SB/Core/gc/iAnim.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#include "iAnim.h" - -#include "iAnimSKB.h" -#include "xMath.h" - -#include -#include - -static U8 scratchBuffer[9120]; - -U8* giAnimScratch = scratchBuffer; - -void iAnimInit() -{ - return; -} - -void iAnimEval(void* RawData, F32 time, U32 flags, xVec3* tran, xQuat* quat) -{ - iAnimEvalSKB((iAnimSKBHeader*)RawData, time, flags, tran, quat); -} - -F32 iAnimDuration(void* RawData) -{ - return iAnimDurationSKB((iAnimSKBHeader*)RawData); -} - -U32 iAnimBoneCount(void* RawData) -{ - if (*(U32*)RawData == '1BKS') - { - return ((iAnimSKBHeader*)RawData)->BoneCount; - } - - return 0; -} - -// non-matching: incorrect instruction order and regalloc -void iAnimBlend(F32 BlendFactor, F32 BlendRecip, U16* BlendTimeOffset, - F32* BoneTable, U32 BoneCount, xVec3* Tran1, xQuat* Quat1, xVec3* Tran2, - xQuat* Quat2, xVec3* TranDest, xQuat* QuatDest) -{ - U32 i; - U32 invert = 0; - RtQuat* q2; - RtQuat ident = { 0.0f, 0.0f, 0.0f, 1.0f }; - xVec3* t2; - - if (!Quat2) - { - q2 = &ident; - invert = 1; - t2 = (xVec3*)&ident.imag; - } - else - { - q2 = (RtQuat*)Quat2; - t2 = Tran2; - } - - if (BlendFactor < 0.0f) - { - BlendFactor = -BlendFactor; - invert ^= 1; - } - - if (!BoneTable && !BlendTimeOffset) - { - F32 lerp = BlendFactor * BlendRecip; - - if (lerp < 0.0f) - { - lerp = 0.0f; - } - else if (lerp > 1.0f) - { - lerp = 1.0f; - } - - if (invert) - { - lerp = 1.0f - lerp; - } - - if (Quat1) - { - // non-matching: 0.0f constant is loaded outside of loop - - for (i = 0; i < BoneCount; i++) - { - RtQuatSlerpCache qcache; - - RtQuatSetupSlerpCache((RtQuat*)Quat1, q2, &qcache); - RtQuatSlerp((RtQuat*)QuatDest, (RtQuat*)Quat1, q2, lerp, &qcache); - - Quat1++; - - if (Quat2) - { - q2++; - } - - QuatDest++; - } - } - - if (Tran1) - { - if (Quat2) - { - for (i = 0; i < BoneCount; i++, TranDest++, t2++, Tran1++) - { - TranDest->x = lerp * (t2->x - Tran1->x) + Tran1->x; - TranDest->y = lerp * (t2->y - Tran1->y) + Tran1->y; - TranDest->z = lerp * (t2->z - Tran1->z) + Tran1->z; - } - } - else - { - for (i = 0; i < BoneCount; i++, TranDest++, Tran1++) - { - TranDest->x = lerp * (t2->x - Tran1->x) + Tran1->x; - TranDest->y = lerp * (t2->y - Tran1->y) + Tran1->y; - TranDest->z = lerp * (t2->z - Tran1->z) + Tran1->z; - } - } - } - } - else - { - F32 baselerp; - - if (!BlendTimeOffset) - { - baselerp = BlendFactor * BlendRecip; - - if (baselerp < 0.0f) - { - baselerp = 0.0f; - } - else if (baselerp > 1.0f) - { - baselerp = 1.0f; - } - - if (invert) - { - baselerp = 1.0f - baselerp; - } - } - - for (i = 0; i < BoneCount; i++) - { - F32 lerp; - - if (BlendTimeOffset) - { - baselerp = -(1 / 1024.0f * BlendTimeOffset[i * 2] - BlendFactor); - - if (BlendTimeOffset[i * 2 + 1] != 0) - { - baselerp *= 1 / 1024.0f * BlendTimeOffset[i * 2 + 1]; - - if (baselerp < 0.0f) - { - baselerp = 0.0f; - } - else if (baselerp > 1.0f) - { - baselerp = 1.0f; - } - } - else - { - if (baselerp < 0.0f) - { - baselerp = 0.0f; - } - else - { - baselerp = 1.0f; - } - } - - if (invert) - { - baselerp = 1.0f - baselerp; - } - } - - if (BoneTable) - { - lerp = baselerp * BoneTable[i]; - } - else - { - lerp = baselerp; - } - - if (Quat1) - { - RtQuatSlerpCache qcache; - - RtQuatSetupSlerpCache((RtQuat*)Quat1, q2, &qcache); - RtQuatSlerp((RtQuat*)QuatDest, (RtQuat*)Quat1, q2, lerp, &qcache); - - Quat1++; - - if (Quat2) - { - q2++; - } - - QuatDest++; - } - - if (Tran1) - { - TranDest->x = lerp * (t2->x - Tran1->x) + Tran1->x; - TranDest->y = lerp * (t2->y - Tran1->y) + Tran1->y; - TranDest->z = lerp * (t2->z - Tran1->z) + Tran1->z; - - Tran1++; - - if (Quat2) - { - t2++; - } - - TranDest++; - } - } - } -} diff --git a/src/SB/Core/gc/iAnimSKB.cpp b/src/SB/Core/gc/iAnimSKB.cpp deleted file mode 100644 index 8dace6e..0000000 --- a/src/SB/Core/gc/iAnimSKB.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "iAnimSKB.h" - -#include -#include - -#include - -void iAnimEvalSKB(iAnimSKBHeader* data, F32 time, U32 flags, xVec3* tran, xQuat* quat) -{ - U32 i, tidx, bcount, tcount; - iAnimSKBKey* keys; - F32* times; - U16* offsets; - S32 asdf; // unused - F32 scalex, scaley, scalez; - - tcount = data->TimeCount; - bcount = data->BoneCount; - - keys = (iAnimSKBKey*)(data + 1); - times = (F32*)(keys + data->KeyCount); - offsets = (U16*)(times + tcount); - - if (time < 0.0f) - { - time = 0.0f; - } - - if (time > times[tcount - 1]) - { - time = times[tcount - 1]; - } - - tidx = (tcount - 1) % 4; - - while (times[tidx] < time) - { - tidx += 4; - } - - while (tidx && time <= times[tidx]) - { - tidx--; - } - - offsets += tidx * bcount; - - if (flags & 0x1) - { - bcount = 1; - } - - if (flags & 0x2) - { - bcount--; - offsets++; - } - - if (tcount == 1) - { - // non-matching: float constants are loaded outside of loop - - scalex = data->Scale[0]; - scaley = data->Scale[1]; - scalez = data->Scale[2]; - - for (i = 0; i < bcount; i++, quat++, tran++) - { - iAnimSKBKey* k = &keys[i]; - - quat->v.x = k->Quat[0] * (1.0f / SHRT_MAX); - quat->v.y = k->Quat[1] * (1.0f / SHRT_MAX); - quat->v.z = k->Quat[2] * (1.0f / SHRT_MAX); - quat->s = k->Quat[3] * (1.0f / SHRT_MAX); - - tran->x = k->Tran[0] * scalex; - tran->y = k->Tran[1] * scaley; - tran->z = k->Tran[2] * scalez; - } - } - else - { - // non-matching: float constants are loaded outside of loop - - scalex = data->Scale[0]; - scaley = data->Scale[1]; - scalez = data->Scale[2]; - - for (i = 0; i < bcount; i++, quat++, tran++) - { - // no idea if this part even functionally matches. - // come back to this when not lazy - - RtQuatSlerpCache qcache; - RtQuat q1, q2; - RwReal time1, time2, lerp; - iAnimSKBKey* k = &keys[*offsets]; - U32 costheta, theta; // unused - - offsets++; - - time1 = time - times[k->TimeIndex]; - time2 = times[k[1].TimeIndex] - times[k[0].TimeIndex]; - lerp = time1 / time2; - - q1.imag.x = k[0].Quat[0] * (1.0f / SHRT_MAX); - q1.imag.y = k[0].Quat[1] * (1.0f / SHRT_MAX); - q1.imag.z = k[0].Quat[2] * (1.0f / SHRT_MAX); - q1.real = k[0].Quat[3] * (1.0f / SHRT_MAX); - - q2.imag.x = k[1].Quat[0] * (1.0f / SHRT_MAX); - q2.imag.y = k[1].Quat[1] * (1.0f / SHRT_MAX); - q2.imag.z = k[1].Quat[2] * (1.0f / SHRT_MAX); - q2.real = k[1].Quat[3] * (1.0f / SHRT_MAX); - - RtQuatSetupSlerpCache(&q1, &q2, &qcache); - RtQuatSlerp((RtQuat*)quat, &q1, &q2, lerp, &qcache); - - tran->x = - lerp * (scalex * k[1].Tran[0] - scalex * k[0].Tran[0]) + scalex * k[0].Tran[0]; - tran->y = - lerp * (scaley * k[1].Tran[1] - scaley * k[0].Tran[1]) + scaley * k[1].Tran[1]; - tran->z = - lerp * (scalez * k[1].Tran[2] - scalez * k[0].Tran[2]) + scalez * k[1].Tran[2]; - } - } -} - -F32 iAnimDurationSKB(iAnimSKBHeader* data) -{ - return ((F32*)((iAnimSKBKey*)(data + 1) + data->KeyCount))[data->TimeCount - 1]; -} diff --git a/src/SB/Core/gc/iCollide.cpp b/src/SB/Core/gc/iCollide.cpp deleted file mode 100644 index 2272a46..0000000 --- a/src/SB/Core/gc/iCollide.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "iCollide.h" - -#include - -void iCollideInit(xScene*) -{ -} diff --git a/src/SB/Core/gc/iCollideFast.cpp b/src/SB/Core/gc/iCollideFast.cpp deleted file mode 100644 index 945d8ca..0000000 --- a/src/SB/Core/gc/iCollideFast.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "iCollideFast.h" - -void iCollideFastInit(xScene* sc) -{ - return; -} \ No newline at end of file diff --git a/src/SB/Core/gc/iCutscene.cpp b/src/SB/Core/gc/iCutscene.cpp deleted file mode 100644 index 973bf9f..0000000 --- a/src/SB/Core/gc/iCutscene.cpp +++ /dev/null @@ -1,358 +0,0 @@ -#include "iCutscene.h" - -#include "xpkrsvc.h" -#include "xstransvc.h" -#include "xMath.h" - -#include "iModel.h" - -#include -#include - -U32 read_sizzze = 0; - -void iCSSoundSetup(xCutscene* csn) -{ - xCutsceneData* data; - U32 dataIndex; - U32 numData; - - data = (xCutsceneData*)(csn->Play + 1); - numData = csn->Play->NumData; - - for (dataIndex = 0; dataIndex < numData; dataIndex++) - { - if (data->DataType == XCUTSCENEDATA_TYPE_SOUND) - { - if (csn->SndNumChannel >= 2) - { - break; - } - - csn->SndAssetID[csn->SndNumChannel] = data->AssetID; - csn->SndNumChannel++; - } - - data = (xCutsceneData*)((U8*)data + ALIGN(data->ChunkSize, 16) + sizeof(xCutsceneData)); - } -} - -void* iCSSoundGetData(xSndVoiceInfo* vp, U32* size) -{ - U32 channelIndex; - U32 dataIndex; - xCutscene* csn; - void* retdata; - xCutsceneData* data; - U32 numChannel; - U32 numData; - S32 sndChannelIndex; - U32 r4; - U32 sndChannelReq; - - csn = xCutscene_CurrentCutscene(); - - numChannel = csn->SndNumChannel; - retdata = NULL; - sndChannelIndex = -1; - - for (channelIndex = 0; channelIndex < numChannel; channelIndex++) - { - if (csn->SndAssetID[channelIndex] == vp->assetID) - { - sndChannelIndex = channelIndex; - sndChannelReq = csn->SndChannelReq[channelIndex]; - } - } - - if (sndChannelIndex == -1) - { - return NULL; - } - - if (!csn->Waiting && csn->Stream->ChunkIndex == sndChannelReq) - { - numData = csn->Stream->NumData; - data = (xCutsceneData*)(csn->Stream + 1); - } - else - { - numData = csn->Play->NumData; - data = (xCutsceneData*)(csn->Play + 1); - - if (csn->SndChannelReq[sndChannelIndex] != csn->Play->ChunkIndex) - { - csn->SndChannelReq[sndChannelIndex] = csn->Play->ChunkIndex; - } - } - - r4 = 0; - - for (dataIndex = 0; dataIndex < numData; dataIndex++) - { - if (data->DataType == XCUTSCENEDATA_TYPE_SOUND) - { - if (!retdata) - { - retdata = (void*)(data + 1); - *size = data->ChunkSize; - } - - if (sndChannelIndex == r4) - { - retdata = (void*)(data + 1); - *size = data->ChunkSize; - - break; - } - else - { - r4++; - } - } - - data = (xCutsceneData*)((U8*)data + ALIGN(data->ChunkSize, 16) + sizeof(xCutsceneData)); - } - - if (!retdata) - { - return NULL; - } - - while ((U32)retdata & 0x1F) - { - retdata = (void*)((U8*)retdata + 16); - *size -= 16; - } - - csn->SndChannelReq[sndChannelIndex]++; - - return retdata; -} - -static void iCSAsyncReadCB(tag_xFile* file) -{ - S32 bytes; - xCutscene* csn; - - if (file) - { - if (iFileReadAsyncStatus(file->ps.asynckey, &bytes) == IFILE_RDSTAT_DONE) - { - iFileSeek(file, bytes, IFILE_SEEK_CUR); - } - - csn = xCutscene_CurrentCutscene(); - csn->Waiting = 0; - } -} - -U32 iCSFileOpen(xCutscene* csn) -{ - U32 headerskip; - st_PKR_ASSET_TOCINFO ainfo; - const char* filename; - - headerskip = ALIGN(csn->Info->HeaderSize, 2048); - - if (!xSTGetAssetInfo(csn->Info->AssetID, &ainfo)) - { - return 0; - } - - filename = xST_xAssetID_HIPFullPath(csn->Info->AssetID); - - if (iFileOpen(filename, 0x1, &csn->File) == 0) - { - iFileSeek(&csn->File, headerskip + (ainfo.sector - csn->File.ps.fileInfo.startAddr << 5), - IFILE_SEEK_SET); - - csn->File.ps.asynckey = -1; - } - else - { - return 0; - } - - return 1; -} - -void iCSFileAsyncRead(xCutscene* csn, void* dest, U32 size) -{ - U32* buf = (U32*)dest; - U32 i; - - read_sizzze = size; - csn->Waiting = 1; - - for (i = 0; i < size / 4; i++) - { - buf[i] = 0xDEADBEEF; - } - - iFileReadAsync(&csn->File, dest, size, iCSAsyncReadCB, 0); -} - -void iCSFileAsyncSkip(xCutscene* csn, U32 amount) -{ - csn->Waiting = 1; - - iFileSeek(&csn->File, amount, IFILE_SEEK_CUR); -} - -void iCSFileClose(xCutscene* csn) -{ - iFileReadStop(); - - csn->Opened = 0; -} - -S32 iCSLoadStep(xCutscene* csn) -{ - S32 bytes; - XFILE_READSECTOR_STATUS cdstat; - U32 skipAccum; - U32 tmpSize; - void* foundModel; - U32 i; - - if (csn->Waiting) - { - cdstat = xFileReadAsyncStatus(csn->File.ps.asynckey, &bytes); - - if (cdstat == XFILE_RDSTAT_INPROG || cdstat == XFILE_RDSTAT_QUEUED) - { - return 0; - } - } - - if (csn->DataLoading >= 0) - { - skipAccum = 0; - - while (csn->DataLoading < (S32)csn->Info->NumData) - { - if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_6) - { - foundModel = NULL; - } - else - { - foundModel = xSTFindAsset(csn->Data[csn->DataLoading].AssetID, &tmpSize); - } - - if (foundModel || csn->Data[csn->DataLoading].ChunkSize == 0) - { - csn->Data[csn->DataLoading].DataPtr = foundModel; - - skipAccum += ALIGN(csn->Data[csn->DataLoading].ChunkSize, 2048); - - csn->DataLoading++; - } - else - { - if (skipAccum) - { - iCSFileAsyncSkip(csn, skipAccum); - - skipAccum = 0; - } - - if (csn->GotData) - { - if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_6) - { - csn->Data[csn->DataLoading].DataPtr = - RwMalloc(csn->Data[csn->DataLoading].ChunkSize); - - memcpy(csn->Data[csn->DataLoading].DataPtr, csn->AlignBuf, - csn->Data[csn->DataLoading].ChunkSize); - } - else - { - csn->Data[csn->DataLoading].DataPtr = - iModelFileNew(csn->AlignBuf, csn->Data[csn->DataLoading].ChunkSize); - } - - csn->Data[csn->DataLoading].DataType |= 0x80000000; - csn->DataLoading++; - csn->GotData = 0; - } - else - { - iCSFileAsyncRead(csn, csn->AlignBuf, - ALIGN(csn->Data[csn->DataLoading].ChunkSize, 2048)); - - csn->GotData = 1; - return 0; - } - } - } - - if (skipAccum) - { - iCSFileAsyncSkip(csn, skipAccum); - } - - csn->DataLoading = -1; - } - - if (csn->DataLoading == -1) - { - if (csn->GotData) - { - iCSSoundSetup(csn); - - if (csn->SndNumChannel != 0) - { - xSndPauseAll(1, 1); - xSndUpdate(); - - if (csn->SndNumChannel == 2) - { - // Stereo - - csn->SndHandle[0] = xSndPlay(csn->SndAssetID[0], 0.9f, -99999.0f, 255, 0x200, 0, - SND_CAT_CUTSCENE, 0.0f); - csn->SndHandle[1] = xSndPlay(csn->SndAssetID[1], 0.9f, -99999.0f, 255, 0x200, 0, - SND_CAT_CUTSCENE, 0.0f); - } - else - { - // Mono - - csn->SndHandle[0] = xSndPlay(csn->SndAssetID[0], 0.9f, -99999.0f, 255, 0x200, 0, - SND_CAT_CUTSCENE, 0.0f); - csn->SndHandle[1] = 0; - } - } - - csn->GotData = 0; - csn->DataLoading = -2; - } - else - { - iCSFileAsyncRead(csn, csn->Play, csn->TimeChunkOffs[1] - csn->TimeChunkOffs[0]); - - csn->GotData = 1; - return 0; - } - } - - if (csn->DataLoading == -2) - { - if (csn->Info->NumTime > 1) - { - iCSFileAsyncRead(csn, csn->Stream, csn->TimeChunkOffs[2] - csn->TimeChunkOffs[1]); - } - - csn->DataLoading = -3; - } - - for (i = 0; i < csn->SndNumChannel; i++) - { - } - - csn->Ready = 1; - return 1; -} diff --git a/src/SB/Core/gc/iDraw.cpp b/src/SB/Core/gc/iDraw.cpp deleted file mode 100644 index cffc6a8..0000000 --- a/src/SB/Core/gc/iDraw.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "iDraw.h" - -#include -#include - -void iDrawSetFBMSK(U32 abgr) -{ - size_t tmp, hi; - - hi = abgr >> 24; - - if (hi == 0) - { - GXSetAlphaUpdate(GX_TRUE); - } - else if (hi == 255) - { - GXSetAlphaUpdate(GX_FALSE); - } - - tmp = abgr & 0x00FFFFFF; - - if (tmp == 0) - { - GXSetColorUpdate(GX_TRUE); - } - else - { - GXSetColorUpdate(GX_FALSE); - } -} - -void iDrawBegin() -{ - return; -} - -void iDrawEnd() -{ - return; -} diff --git a/src/SB/Core/gc/iEnv.cpp b/src/SB/Core/gc/iEnv.cpp deleted file mode 100644 index f377f2e..0000000 --- a/src/SB/Core/gc/iEnv.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#include "iEnv.h" - -#include "iModel.h" - -#include "iCamera.h" -#include "xMemMgr.h" - -static S32 sBeginDrawFX; -static RpWorld* sPipeWorld; -static RwCamera* sPipeCamera; -static iEnv* lastEnv; - -static RpAtomic* SetPipelineCB(RpAtomic* atomic, void* data) -{ - if (RwCameraBeginUpdate(sPipeCamera)) - { - RpAtomicInstance(atomic); - RwCameraEndUpdate(sPipeCamera); - } - - if (data) - { - RpAtomicSetPipeline(atomic, (RxPipeline*)data); - } - - return atomic; -} - -static void iEnvSetBSP(iEnv* env, S32 envDataType, RpWorld* bsp) -{ - if (envDataType == 0) - { - env->world = bsp; - } - else if (envDataType == 1) - { - env->collision = bsp; - } - else if (envDataType == 2) - { - env->fx = bsp; - } - else if (envDataType == 3) - { - env->camera = bsp; - } -} - -void iEnvLoad(iEnv* env, const void* data, U32, S32 dataType) -{ - RpWorld* bsp = (RpWorld*)data; - xJSPHeader* jsp = (xJSPHeader*)data; - - if (jsp->idtag[0] == 'J' && jsp->idtag[1] == 'S' && jsp->idtag[2] == 'P' && - jsp->idtag[3] == '\0') - { - if (dataType == 0) - { - RwBBox tmpbbox = { 1000.0f, 1000.0f, 1000.0f, -1000.0f, -1000.0f, -1000.0f }; - - env->world = RpWorldCreate(&tmpbbox); - - sPipeCamera = iCameraCreate(640, 480, 0); - sPipeWorld = env->world; - - // non-matching: sPipeCamera and sPipeWorld loads are skipped - - RpWorldAddCamera(sPipeWorld, sPipeCamera); - - env->jsp = jsp; - - RpClumpForAllAtomics(env->jsp->clump, SetPipelineCB, NULL); - xClumpColl_InstancePointers(env->jsp->colltree, env->jsp->clump); - - RpWorldRemoveCamera(sPipeWorld, sPipeCamera); - - iCameraDestroy(sPipeCamera); - - sPipeWorld = NULL; - sPipeCamera = NULL; - } - } - else - { - if (dataType == 0) - { - env->jsp = NULL; - } - - iEnvSetBSP(env, dataType, bsp); - } - - if (dataType == 0) - { - env->memlvl = xMemGetBase(); - } -} - -void iEnvFree(iEnv* env) -{ - _rwFrameSyncDirty(); - - RpWorldDestroy(env->world); - env->world = NULL; - - if (env->fx) - { - RpWorldDestroy(env->fx); - env->fx = NULL; - } - - if (env->collision) - { - RpWorldDestroy(env->collision); - env->collision = NULL; - } -} - -void iEnvDefaultLighting(iEnv*) -{ -} - -void iEnvLightingBasics(iEnv*, xEnvAsset*) -{ -} - -// This is named JspPS2_ClumpRender on PS2 -static void Jsp_ClumpRender(RpClump* clump, xJSPNodeInfo* nodeInfo) -{ - S32 backcullon = 1; - S32 zbufferon = 1; - RwLLLink* cur = rwLinkListGetFirstLLLink(&clump->atomicList); - RwLLLink* end = rwLinkListGetTerminator(&clump->atomicList); - - while (cur != end) - { - RpAtomic* apAtom = rwLLLinkGetData(cur, RpAtomic, inClumpLink); - - if (RpAtomicGetFlags(apAtom) & rpATOMICRENDER) - { - RwFrame* frame = RpAtomicGetFrame(apAtom); - - if (!iModelCull(apAtom, &frame->ltm)) - { - if (backcullon) - { - if (nodeInfo->nodeFlags & 0x4) - { - backcullon = 0; - RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); - } - } - else - { - if (!(nodeInfo->nodeFlags & 0x4)) - { - backcullon = 1; - RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLBACK); - } - } - - if (zbufferon) - { - if (nodeInfo->nodeFlags & 0x2) - { - zbufferon = 0; - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - } - } - else - { - if (!(nodeInfo->nodeFlags & 0x2)) - { - zbufferon = 1; - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); - } - } - - RpAtomicRender(apAtom); - } - } - - cur = rwLLLinkGetNext(cur); - nodeInfo++; - } -} - -void iEnvRender(iEnv* env) -{ - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - - if (env->jsp) - { - Jsp_ClumpRender(env->jsp->clump, env->jsp->jspNodeList); - } - else - { - RpWorldRender(env->world); - } - - lastEnv = env; -} - -void iEnvEndRenderFX(iEnv*) -{ - iEnv* env = lastEnv; - - if (env->fx && globalCamera && sBeginDrawFX) - { - RpWorldRemoveCamera(env->fx, globalCamera); - RpWorldAddCamera(env->world, globalCamera); - - sBeginDrawFX = 0; - } -} diff --git a/src/SB/Core/gc/iFMV.cpp b/src/SB/Core/gc/iFMV.cpp deleted file mode 100644 index 2d34852..0000000 --- a/src/SB/Core/gc/iFMV.cpp +++ /dev/null @@ -1,422 +0,0 @@ -#include "iFMV.h" - -#include "iCamera.h" -#include "iFile.h" -#include "iPad.h" -#include "iSystem.h" -#include "iTRC.h" - -#include "xFile.h" -#include "xPar.h" - -#include "zGlobals.h" - -#include -#include - -// FIXME: These should be in a RW header somewhere -extern GXRenderModeObj* _RwDlRenderMode; -extern "C" { -void RwGameCubeGetXFBs(void*, void*); -} - -// .bss -static U32 Bink_surface_type[5]; - -// .sbss -static S32 frame_num; -U32 fuckingSurfaceType; -static HBINK Bink; -static HRAD3DIMAGE Image; -static S32 Paused; -static void* pixels; -static volatile F32 vol; -S32 ip; -s32 oof; -void* iFMV::mXFBs[2]; -void* iFMV::mCurrentFrameBuffer; -GXRenderModeObj* iFMV::mRenderMode; - -// .sdata -static float Width_scale = 1.0f; -static float Height_scale = 1.0f; -U8 iFMV::mFirstFrame = 1; - -void* iFMVmalloc(size_t size) -{ - return RwMalloc(size); -} - -void iFMVfree(void* mem) -{ - RwFree(mem); -} - -static void PlayFMV(char* filename, size_t buttons, F32 time); -U32 iFMVPlay(char* filename, U32 buttons, F32 time, bool skippable, bool lockController) -{ - if (filename == NULL) - { - return 1; - } - - frame_num = 0; - while (frame_num >= 0) - { - PlayFMV(filename, buttons, time); - } - return 0; -} - -static void Setup_surface_array() -{ - Bink_surface_type[0] = BINKSURFACE32; - Bink_surface_type[1] = BINKSURFACE32A; - Bink_surface_type[2] = BINKSURFACE565; - Bink_surface_type[3] = BINKSURFACE4444; - Bink_surface_type[4] = BINKSURFACEYUY2; -} - -// WIP. -void Decompress_frame(HBINK bnk, HRAD3DIMAGE rad_image, long flags) -{ - struct Result - { - S32 unk_0; - S32 unk_4; - U32 unk_8; - U32 unk_c; - }; - Result result; - result.unk_4 = BinkDoFrame(bnk); - if (Lock_RAD_3D_image(rad_image, &pixels, &result.unk_c, &result.unk_8) != 0) - { - S32 mask = flags * -1; - mask = mask | flags; - mask = mask >> 0x1f; - mask = mask & 0x80000000; - mask |= Bink_surface_type[result.unk_8]; - result.unk_0 = BinkCopyToBuffer(bnk, pixels, result.unk_c, bnk->unk_4, NULL, NULL, mask); - Unlock_RAD_3D_image(rad_image); - } -} - -static void DrawFrame(float arg0, float arg1, float arg2, float arg3) -{ - GXRenderModeObj* rm = _RwDlRenderMode; - Mtx idt; - Mtx44 mtx; - - GXSetViewport(0.0f, 0.0f, rm->fbWidth, rm->efbHeight, 0.0f, 1.0f); - GXSetScissor(0, 0, rm->fbWidth, rm->efbHeight); - GXSetDispCopySrc(0, 0, rm->fbWidth, rm->efbHeight); - GXSetDispCopyDst(rm->fbWidth, rm->xfbHeight); - GXSetDispCopyYScale((float)rm->xfbHeight / rm->efbHeight); - GXSetCopyFilter(rm->aa, rm->sample_pattern, GX_TRUE, rm->vfilter); - - if (rm->aa) - { - GXSetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); - } - else - { - GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); - } - - GXSetDispCopyGamma(GX_GM_1_0); - C_MTXOrtho(mtx, 0.0f, 480.0f, 0.0f, 640.0f, 0.0f, 10000.0f); - GXSetProjection(mtx, GX_ORTHOGRAPHIC); - PSMTXIdentity(idt); - GXLoadPosMtxImm(idt, 0); - - GXClearVtxDesc(); - GXSetVtxDesc(GX_VA_POS, GX_DIRECT); - GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); - GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_NRM_NBT, GX_S16, 0); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_NRM_NBT, GX_RGBA8, 0); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_NRM_NBT, GX_RGBA6, 0); - - GXSetNumTexGens(1); - GXSetNumChans(1); - GXSetNumTevStages(1); - GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); - GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); - GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); - - if (rm->field_rendering) - { - u32 field = VIGetNextField(); - GXSetViewportJitter(0.0f, 0.0f, rm->fbWidth, rm->efbHeight, 0.0f, 1.0f, field); - } - else - { - GXSetViewport(0.0f, 0.0f, rm->fbWidth, rm->efbHeight, 0.0f, 1.0f); - } - - GXInvalidateVtxCache(); - GXInvalidateTexAll(); - Blit_RAD_3D_image(Image, arg0, arg1, arg2, arg3, 1.0f); -} - -static void xDrawLine2D_LocaliFMVVersion(float, float, float, float); -static void Show_frame() -{ - RwRGBA color = { 0 }; - RwCamera* cam = iCameraCreate(640, 480, FALSE); - RwCameraClear(cam, &color, rwCAMERACLEARIMAGE); - - RwCameraBeginUpdate(cam); - Width_scale = 640 / Bink->unk_0; - Height_scale = 480 / Bink->unk_4; - xDrawLine2D_LocaliFMVVersion(0.0f, 0.0f, 0.0f, 0.0f); - DrawFrame(0.0f, 0.0f, Width_scale, Height_scale); - RwCameraEndUpdate(cam); - RwCameraShowRaster(cam, NULL, 0); - - iCameraDestroy(cam); -} - -static void* arammalloc(size_t size) -{ - return (void*)ARAlloc(size); -} - -// Something weird is going on here... -static void aramfree(void* mem) -{ - u32 vol; - ARFree(&vol); -} - -static void PlayFMV(char* fname, u32 buttons, F32 time) -{ - GXCullMode cull_mode; - GXGetCullMode(&cull_mode); - iFMV::InitDisplay(_RwDlRenderMode); - iPadStopRumble(globals.pad0); - RADSetAudioMemory(arammalloc, aramfree); - RADSetMemory(iFMVmalloc, iFMVfree); - Setup_surface_array(); - - for (char* c = fname; *c != NULL; c++) - { - if (*c == '\\') - { - *c = '/'; - } - } - - tag_xFile file; - DVDFileInfo* pfinfo = &file.ps.fileInfo; - do - { - if (iTRCDisk::IsDiskIDed()) - { - Bink = BinkOpen(fname, NULL); - if (Bink == NULL) - { - BinkGetError(); - } - } - if (iTRCDisk::CheckDVDAndResetState() != 0) - { - break; - } - if (Bink == NULL) - { - iFileOpen(fname, 0, &file); - DVDSeekAsyncPrio(pfinfo, 0, NULL, 2); - if (iTRCDisk::CheckDVDAndResetState()) - { - DVDCancel(&pfinfo->cb); - break; - } - else - { - DVDCancel(&pfinfo->cb); - } - } - } while (Bink == NULL); - - if (Bink != NULL) - { - if (Bink->unk_f0 != 0) - { - for (ip = 0; ip <= Bink->unk_f0; ++ip) - { - vol = gSnd.categoryVolFader[SND_CAT_CUTSCENE]; - vol = vol * vol; - vol = vol * 32768.0f; - BinkSetVolume(Bink, ip, vol); - } - } - - Image = Open_RAD_3D_image(NULL, Bink->unk_0, Bink->unk_4, fuckingSurfaceType); - if (Image != NULL) - { - if (frame_num != 0) - { - BinkGoto(Bink, frame_num, 0); - } - oof = 0; - - do - { - if (iTRCDisk::CheckDVDAndResetState()) - { - goto superbreak; - } - if (BinkWait(Bink) == 0) - { - Decompress_frame(Bink, Image, 1); - Show_frame(); - BinkNextFrame(Bink); - } - else if (Paused) - { - Show_frame(); - } - xPadUpdate(globals.currentActivePad, 0.0f); - - F32 t = (float)Bink->unk_c / (Bink->unk_14 / Bink->unk_18); - if (buttons && t >= time && globals.pad0->pressed & buttons) - { - frame_num = -1; - goto superbreak; - } - } while (Bink->unk_c < Bink->unk_8 - 1); - frame_num = -1; - } - superbreak: - if (frame_num != -1) - { - frame_num = Bink->unk_c; - } - Close_RAD_3D_image(Image); - Image = NULL; - BinkClose(Bink); - Bink = NULL; - } - - GXSetCullMode(cull_mode); - iVSync(); - xPadUpdate(globals.currentActivePad, 0.0f); -} - -void iFMV::InitDisplay(GXRenderModeObj* InRenderMode) -{ - GXColor clr = { 0 }; - Mtx44 mtx; - Mtx idt; - mRenderMode = InRenderMode; - void** xfb = &mXFBs[1]; - RwGameCubeGetXFBs(&mXFBs[0], &mXFBs[1]); - mCurrentFrameBuffer = *xfb; - - InitGX(); - InitVI(); - - GXSetCopyClear(clr, GX_MAX_Z24); - C_MTXOrtho(mtx, 0.0f, mRenderMode->efbHeight, 0.0f, mRenderMode->fbWidth, 0.0f, -100.0f); - GXSetProjection(mtx, GX_ORTHOGRAPHIC); - PSMTXIdentity(idt); - GXLoadPosMtxImm(idt, 0); - GXSetCurrentMtx(0); - - GXSetZMode(GX_TRUE, GX_ALWAYS, GX_TRUE); - GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR); - - GXClearVtxDesc(); - GXSetVtxDesc(GX_VA_POS, GX_DIRECT); - GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); - GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_NRM_NBT, GX_S16, 0); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_NRM_NBT, GX_RGBA8, 0); - GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_NRM_NBT, GX_RGBA6, 0); - - GXSetNumTexGens(1); - GXSetNumChans(1); - GXSetNumTevStages(1); - GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); - GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); - GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); - mFirstFrame = 1; -} - -void iFMV::InitGX() -{ - GXSetViewport(0, 0, mRenderMode->fbWidth, mRenderMode->efbHeight, 0.0f, 1.0f); - GXSetScissor(0, 0, mRenderMode->fbWidth, mRenderMode->efbHeight); - f32 yScaleFactor = GXGetYScaleFactor(mRenderMode->efbHeight, mRenderMode->xfbHeight); - u16 r = GXSetDispCopyYScale(yScaleFactor); - - GXSetDispCopySrc(0, 0, mRenderMode->fbWidth, mRenderMode->efbHeight); - GXSetDispCopyDst(mRenderMode->fbWidth, r); - GXSetCopyFilter(mRenderMode->aa, mRenderMode->sample_pattern, GX_TRUE, mRenderMode->vfilter); - - if (mRenderMode->aa) - { - GXSetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); - } - else - { - GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); - } - - GXCopyDisp(mCurrentFrameBuffer, GX_TRUE); - GXSetDispCopyGamma(GX_GM_1_0); - GXSetCullMode(GX_CULL_NONE); -} - -void iFMV::InitVI() -{ - VISetNextFrameBuffer(iFMV::mXFBs[0]); - mCurrentFrameBuffer = mXFBs[1]; - VIFlush(); - VIWaitForRetrace(); - if (mRenderMode->viTVmode & 1) - { - VIWaitForRetrace(); - } -} - -void iFMV::Suspend() -{ -} - -void iFMV::Resume() -{ -} - -static void xDrawLine2D_LocaliFMVVersion(F32 arg0, F32 arg1, F32 arg2, F32 arg3) -{ - RwRGBA color = { -1, -1, -1, -1 }; - - F32 nearz = RwIm2DGetNearScreenZ(); - void* texraster_state; - RwRenderStateGet(rwRENDERSTATETEXTURERASTER, &texraster_state); - void* vtx_alpha_state; - RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vtx_alpha_state); - RwIm2DVertex verts[2]; - - // RwIm2DVertexSetRealRGBA - - RwIm2DVertexSetScreenX(&verts[0], arg0); - RwIm2DVertexSetScreenY(&verts[0], arg1); - RwIm2DVertexSetScreenZ(&verts[0], nearz); - RwIm2DVertexSetIntRGBA(&verts[0], color.red, color.green, color.blue, color.alpha); - - RwIm2DVertexSetScreenX(&verts[1], arg2); - RwIm2DVertexSetScreenY(&verts[1], arg3); - RwIm2DVertexSetScreenZ(&verts[1], nearz); - RwIm2DVertexSetIntRGBA(&verts[1], color.red, color.green, color.blue, color.alpha); - - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, NULL); - - // { arg2, arg3, nearz, -1 }; - RwIm2DRenderLine(verts, 2, 0, 1); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, texraster_state); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, vtx_alpha_state); -} diff --git a/src/SB/Core/gc/iFX.cpp b/src/SB/Core/gc/iFX.cpp deleted file mode 100644 index 64e1f70..0000000 --- a/src/SB/Core/gc/iFX.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "iFX.h" - -#include diff --git a/src/SB/Core/gc/iFile.cpp b/src/SB/Core/gc/iFile.cpp deleted file mode 100644 index c774766..0000000 --- a/src/SB/Core/gc/iFile.cpp +++ /dev/null @@ -1,351 +0,0 @@ -#include "iFile.h" - -#include "iTRC.h" - -#include "xFile.h" -#include "xMath.h" -#include "xTRC.h" - -#include - -struct file_queue_entry -{ - tag_xFile* file; - void* buf; - U32 size; - U32 offset; - IFILE_READSECTOR_STATUS stat; - void (*callback)(tag_xFile* file); - U32 asynckey; -}; - -extern file_queue_entry file_queue[4]; - -static U32 tbuffer[1024 + 8]; -static U32* buffer32; -volatile U32 iFileSyncAsyncReadActive; - -void iFileInit() -{ - buffer32 = (U32*)OSRoundUp32B(tbuffer); -} - -void iFileExit() -{ -} - -U32* iFileLoad(char* name, U32* buffer, U32* size) -{ - char path[128]; - tag_xFile file; - S32 fileSize, alignedSize; - - iFileFullPath(name, path); - iFileOpen(name, IFILE_OPEN_ABSPATH, &file); - - fileSize = iFileGetSize(&file); - - if (!buffer) - { - buffer = (U32*)OSAlloc(OSRoundUp32B(fileSize)); - } - - alignedSize = OSRoundUp32B(fileSize); - - iFileRead(&file, buffer, alignedSize); - - if (size) - { - *size = alignedSize; - } - - iFileClose(&file); - - return buffer; -} - -U32 iFileOpen(const char* name, S32 flags, tag_xFile* file) -{ - tag_iFile* ps = &file->ps; - - if (flags & IFILE_OPEN_ABSPATH) - { - strcpy(ps->path, name); - } - else - { - iFileFullPath(name, ps->path); - } - - ps->entrynum = DVDConvertPathToEntrynum(ps->path); - - if (ps->entrynum == -1) - { - return 1; - } - - if (!DVDFastOpen(ps->entrynum, &ps->fileInfo)) - { - ps->entrynum = -1; - return 1; - } - - ps->unkC4 = 0; - ps->flags = 0x1; - - iFileSeek(file, 0, IFILE_SEEK_SET); - - return 0; -} - -S32 iFileSeek(tag_xFile* file, S32 offset, S32 whence) -{ - tag_iFile* ps = &file->ps; - S32 position, new_pos; - - switch (whence) - { - case IFILE_SEEK_SET: - { - new_pos = offset; - break; - } - case IFILE_SEEK_CUR: - { - if (DVDGetCommandBlockStatus(&ps->fileInfo.cb) == DVD_STATE_BUSY) - { - return -1; - } - - new_pos = offset + ps->offset; - break; - } - case IFILE_SEEK_END: - { - new_pos = ps->fileInfo.length - offset; - - if (new_pos < 0) - { - new_pos = 0; - } - - break; - } - default: - { - new_pos = offset; - break; - } - } - - ps->offset = new_pos; - - return ps->offset; -} - -static void ifilereadCB(tag_xFile* file) -{ - iFileSyncAsyncReadActive = 0; -} - -U32 iFileRead(tag_xFile* file, void* buf, U32 size) -{ - tag_iFile* ps = &file->ps; - - iFileSeek(file, ps->offset, IFILE_SEEK_SET); - - iFileSyncAsyncReadActive = 1; - - iFileReadAsync(file, buf, size, ifilereadCB, 0); - - while (iFileSyncAsyncReadActive) - { - iTRCDisk::CheckDVDAndResetState(); - } - - return size; -} - -static void async_cb(s32 result, DVDFileInfo* fileInfo) -{ - file_queue_entry* entry = &file_queue[(S32)fileInfo->cb.userData]; - s32 r7 = DVD_RESULT_FATAL_ERROR; - - switch (result) - { - case DVD_RESULT_FATAL_ERROR: - { - xTRCDisk(TRC_DiskFatal); - return; - } - case DVD_RESULT_GOOD: - case DVD_RESULT_IGNORED: - { - if (result >= DVD_RESULT_GOOD) - { - r7 = result; - } - - break; - } - } - - if (r7 < DVD_RESULT_GOOD) - { - entry->stat = IFILE_RDSTAT_FAIL; - - if (entry->callback) - { - entry->callback(entry->file); - } - } - else if (r7 + entry->offset >= entry->size || - r7 + entry->offset + entry->file->ps.offset >= entry->file->ps.fileInfo.length) - { - entry->stat = IFILE_RDSTAT_DONE; - entry->offset = entry->size; - - if (entry->callback) - { - entry->callback(entry->file); - } - - entry->file->ps.asynckey = -1; - } - else - { - entry->offset += r7; - entry->stat = IFILE_RDSTAT_INPROG; - - s32 length; - if ((entry->size - entry->offset < 0x8000)) - { - length = ALIGN(entry->size - entry->offset, 4); - } - else - { - length = 0x10000 - 0x8000; - } - - if (length + entry->offset + entry->file->ps.offset > entry->file->ps.fileInfo.length) - { - // length = OSRoundUp32B(entry->file->ps.fileInfo.length - entry->file->ps.offset - - // entry->offset); - length = entry->file->ps.fileInfo.length; - length -= entry->file->ps.offset; - length -= entry->offset; - length = length + 32 - 1; - length = length & ~(32 - 1); - } - - void* addr = (void*)((U32)entry->buf + entry->offset); - DVDReadAsync(&entry->file->ps.fileInfo, addr, length, - entry->file->ps.offset + entry->offset, async_cb); - } -} - -S32 iFileReadAsync(tag_xFile* file, void* buf, U32 aSize, void (*callback)(tag_xFile*), - S32 priority) -{ - static S32 fopcount = 1; - tag_iFile* ps = &file->ps; - S32 i; - - for (i = 0; i < 4; i++) - { - if (file_queue[i].stat != IFILE_RDSTAT_QUEUED && file_queue[i].stat != IFILE_RDSTAT_INPROG) - { - S32 id = fopcount++ << 2; - S32 asynckey = id + i; - - file_queue[i].file = file; - file_queue[i].buf = buf; - file_queue[i].size = aSize; - file_queue[i].offset = 0; - file_queue[i].stat = IFILE_RDSTAT_QUEUED; - file_queue[i].callback = callback; - file_queue[i].asynckey = asynckey; - - aSize = (aSize < 32) ? ALIGN(aSize, 4) : 32; - - ps->fileInfo.cb.userData = (void*)i; - - DVDReadAsync(&ps->fileInfo, buf, aSize, ps->offset, async_cb); - - ps->asynckey = asynckey; - - return id + i; - } - } - - return -1; -} - -IFILE_READSECTOR_STATUS iFileReadAsyncStatus(S32 key, S32* amtToFar) -{ - if (key != file_queue[key & 0x3].asynckey) - { - return IFILE_RDSTAT_EXPIRED; - } - - if (amtToFar) - { - *amtToFar = file_queue[key & 0x3].offset; - } - - return file_queue[key & 0x3].stat; -} - -U32 iFileClose(tag_xFile* file) -{ - tag_iFile* ps = &file->ps; - S32 ret; - - ret = DVDClose(&file->ps.fileInfo); - ret = DVDClose(&file->ps.fileInfo); - - if (!ret) - { - return 1; - } - - ps->flags = 0; - return 0; -} - -U32 iFileGetSize(tag_xFile* file) -{ - return file->ps.fileInfo.length; -} - -void iFileReadStop() -{ - DVDCancelAllAsync(NULL); -} - -void iFileFullPath(const char* relname, char* fullname) -{ - strcpy(fullname, relname); -} - -void iFileSetPath(char* path) -{ -} - -U32 iFileFind(const char* name, tag_xFile* file) -{ - return iFileOpen(name, 0, file); -} - -void iFileGetInfo(tag_xFile* file, U32* addr, U32* length) -{ - if (addr) - { - *addr = file->ps.fileInfo.startAddr; - } - - if (length) - { - *length = file->ps.fileInfo.length; - } -} diff --git a/src/SB/Core/gc/iFile.h b/src/SB/Core/gc/iFile.h index 3958f7f..9a3250b 100644 --- a/src/SB/Core/gc/iFile.h +++ b/src/SB/Core/gc/iFile.h @@ -57,14 +57,14 @@ U32 iFileOpen(const char* name, S32 flags, tag_xFile* file); S32 iFileSeek(tag_xFile* file, S32 offset, S32 whence); U32 iFileRead(tag_xFile* file, void* buf, U32 size); S32 iFileReadAsync(tag_xFile* file, void* buf, U32 aSize, void (*callback)(tag_xFile*), - S32 priority); + S32 priority); IFILE_READSECTOR_STATUS iFileReadAsyncStatus(S32 key, S32* amtToFar); U32 iFileClose(tag_xFile* file); U32 iFileGetSize(tag_xFile* file); void iFileReadStop(); void iFileFullPath(const char* relname, char* fullname); void iFileSetPath(char* path); -U32 iFileFind(const char* name, tag_xFile* file); +U32 iFileFind(const char* name, int, tag_xFile* file); void iFileGetInfo(tag_xFile* file, U32* addr, U32* length); void iFileAsyncService(); diff --git a/src/SB/Core/gc/iLight.cpp b/src/SB/Core/gc/iLight.cpp deleted file mode 100644 index 92a8c18..0000000 --- a/src/SB/Core/gc/iLight.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include "iLight.h" - -RpWorld* gLightWorld; - -void iLightInit(RpWorld* world) -{ - gLightWorld = world; -} - -iLight* iLightCreate(iLight* light, U32 type) -{ - RwFrame* frame; - - switch (type) - { - case ILIGHT_TYPE_POINT: - light->hw = RpLightCreate(rpLIGHTPOINT); - break; - case ILIGHT_TYPE_SPOT: - light->hw = RpLightCreate(rpLIGHTSPOT); - break; - case ILIGHT_TYPE_SPOTSOFT: - light->hw = RpLightCreate(rpLIGHTSPOTSOFT); - break; - default: - return NULL; - } - - if (!light->hw) - { - return NULL; - } - - frame = RwFrameCreate(); - - if (!frame) - { - RpLightDestroy(light->hw); - return NULL; - } - - RpLightSetFlags(light->hw, rpLIGHTLIGHTATOMICS); - RpLightSetFrame(light->hw, frame); - - RwFrameUpdateObjects(frame); - - light->type = type; - light->sph.center.x = 0.0f; - light->sph.center.y = 0.0f; - light->sph.center.z = 0.0f; - light->sph.r = 0.0f; - light->color.r = 1.0f; - light->color.g = 1.0f; - light->color.b = 1.0f; - light->color.a = 1.0f; - light->dir.x = 0.0f; - light->dir.y = 0.0f; - light->dir.z = 1.0f; - light->coneangle = 0.0f; - - return light; -} - -void iLightModify(iLight* light, U32 flags) -{ - if (flags & 0x5) - { - RwFrame* frame = RpLightGetFrame(light->hw); - RwMatrix temp; - - *(xVec3*)RwMatrixGetRight(&temp) = g_O3; - *(xVec3*)RwMatrixGetUp(&temp) = g_O3; - *(xVec3*)RwMatrixGetAt(&temp) = light->dir; - *(xVec3*)RwMatrixGetPos(&temp) = light->sph.center; - - RwFrameTransform(frame, &temp, rwCOMBINEREPLACE); - } - - if (flags & 0x2) - { - RpLightSetRadius(light->hw, light->sph.r); - } - - if (flags & 0x8) - { - RpLightSetColor(light->hw, (RwRGBAReal*)&light->color); - } - - if (flags & 0x10) - { - if (light->type == ILIGHT_TYPE_SPOT || light->type == ILIGHT_TYPE_SPOTSOFT) - { - RpLightSetConeAngle(light->hw, light->coneangle); - } - } -} - -void iLightSetColor(iLight* light, _xFColor* col) -{ - RpLightSetColor(light->hw, (RwRGBAReal*)col); -} - -void iLightSetPos(iLight* light, xVec3* pos) -{ - RwFrame* f = RpLightGetFrame(light->hw); - RwMatrix* m = RwFrameGetMatrix(f); - - RwMatrixGetPos(m)->x = pos->x; - RwMatrixGetPos(m)->y = pos->y; - RwMatrixGetPos(m)->z = pos->z; - - RwMatrixUpdate(m); - - RwFrameUpdateObjects(f); -} - -void iLightDestroy(iLight* light) -{ - RwFrame* frame; - - light->type = ILIGHT_TYPE_NONE; - - _rwFrameSyncDirty(); - - frame = RpLightGetFrame(light->hw); - - if (frame) - { - RwFrameDestroy(frame); - } - - RpLightDestroy(light->hw); -} - -void iLightEnv(iLight* light, S32 env) -{ - RwUInt32 flags = 0; - - switch (env) - { - case ILIGHT_ENV_NONE: - flags = 0; - break; - case ILIGHT_ENV_ATOMIC: - flags = rpLIGHTLIGHTWORLD; - break; - case ILIGHT_ENV_WORLD: - flags = rpLIGHTLIGHTATOMICS; - break; - case ILIGHT_ENV_ATOMICWORLD: - flags = rpLIGHTLIGHTATOMICS | rpLIGHTLIGHTWORLD; - break; - } - - RpLightSetFlags(light->hw, flags); -} diff --git a/src/SB/Core/gc/iMath.cpp b/src/SB/Core/gc/iMath.cpp deleted file mode 100644 index 35f6ff6..0000000 --- a/src/SB/Core/gc/iMath.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "iMath.h" - -#include - -F32 isin(F32 x) -{ - return std::sinf(x); -} - -#ifndef INLINE -float std::sinf(float x) -{ - return (float)sin((double)x); -} -#endif - -F32 icos(F32 x) -{ - return std::cosf(x); -} - -#ifndef INLINE -float std::cosf(float x) -{ - return (float)cos((double)x); -} -#endif - -F32 itan(F32 x) -{ - return std::tanf(x); -} - -#ifndef INLINE -float std::tanf(float x) -{ - return (float)tan((double)x); -} -#endif diff --git a/src/SB/Core/gc/iMath3.cpp b/src/SB/Core/gc/iMath3.cpp deleted file mode 100644 index 0539117..0000000 --- a/src/SB/Core/gc/iMath3.cpp +++ /dev/null @@ -1,751 +0,0 @@ -#include "iMath3.h" - -#include "xMath.h" -#include "xMath2.h" -#include "xMathInlines.h" - -#include - -extern F32 _555_1; // 0.5f -extern F32 _557_1; // 0.0f -extern F32 _558_3; // 1.0f -extern F32 _560_2; // 0.00001f -extern F32 _607; // 2.0f -extern F32 _608_0; // -1.0f -extern F32 _1060; // -9.9999997e37f -extern F32 _1061; // 9.9999997e37f -extern F32 _1062; // -0.5f - -void iMath3Init() -{ -} - -void iSphereIsectVec(const xSphere* s, const xVec3* v, xIsect* isx) -{ - xVec3Sub(&isx->norm, v, &s->center); - - isx->dist = xVec3Length(&isx->norm); - isx->penned = isx->dist - s->r; -} - -void iSphereIsectRay(const xSphere* s, const xRay3* r, xIsect* isx) -{ - F32 t_in, t_out; - U32 num; - - if (!(r->flags & 0x400)) - { - ((xRay3*)r)->min_t = _557_1; // wait, that's illegal - } - - if (!(r->flags & 0x800)) - { - ((xRay3*)r)->max_t = _558_3; - } - - xVec3Sub(&isx->norm, &r->origin, &s->center); - - num = xMathSolveQuadratic(xVec3Dot(&r->dir, &r->dir), _607 * xVec3Dot(&isx->norm, &r->dir), - xVec3Dot(&isx->norm, &isx->norm) - s->r * s->r, &t_in, &t_out); - - if (num == 0) - { - isx->penned = _558_3; - isx->contained = _558_3; - } - else if (num == 1) - { - if (t_in < r->min_t || t_in > r->max_t) - { - isx->dist = t_in; - isx->penned = _558_3; - isx->contained = _558_3; - } - else - { - isx->dist = t_in; - isx->penned = _608_0; - isx->contained = _558_3; - } - } - else if (t_in < r->min_t) - { - if (t_out < r->min_t) - { - isx->dist = t_out; - isx->penned = _558_3; - isx->contained = _558_3; - } - else - { - isx->dist = t_out; - isx->penned = _608_0; - isx->contained = _608_0; - } - } - else - { - if (t_in <= r->max_t) - { - isx->dist = t_in; - isx->penned = _608_0; - isx->contained = _558_3; - } - else - { - isx->dist = t_in; - isx->penned = _558_3; - isx->contained = _558_3; - } - } -} - -void iSphereIsectSphere(const xSphere* s, const xSphere* p, xIsect* isx) -{ - xVec3Sub(&isx->norm, &p->center, &s->center); - - isx->dist = xVec3Length(&isx->norm); - isx->penned = isx->dist - p->r - s->r; - isx->contained = isx->dist - s->r; -} - -void iSphereInitBoundVec(xSphere* s, const xVec3* v) -{ - xVec3Copy(&s->center, v); - - s->r = _560_2; -} - -void iSphereBoundVec(xSphere* o, const xSphere* s, const xVec3* v) -{ - F32 scale; - xSphere temp; - xSphere* tp; - U32 usetemp; - xIsect isx; - - usetemp = (o == s); - - iSphereIsectVec(s, v, &isx); - - if (isx.penned <= _557_1) - { - if (!usetemp) - { - memcpy(o, s, sizeof(xSphere)); - } - } - else - { - if (usetemp) - { - tp = &temp; - } - else - { - tp = o; - } - - xVec3Copy(&tp->center, &isx.norm); - - scale = (isx.dist - s->r) / (_607 * isx.dist); - - xVec3SMul(&tp->center, &tp->center, scale); - xVec3Add(&tp->center, &tp->center, &s->center); - - tp->r = _555_1 * (isx.dist + s->r); - - if (usetemp) - { - memcpy(o, tp, sizeof(xSphere)); - } - } -} - -void iCylinderIsectVec(const xCylinder* c, const xVec3* v, xIsect* isx) -{ - F32 b = c->center.y + c->h; - - if (v->y >= c->center.y - c->h && v->y <= b && - xVec2Dist(c->center.x, c->center.z, v->x, v->z) <= c->r) - { - isx->penned = _608_0; - } - else - { - isx->penned = _558_3; - } -} - -void iBoxVecDist(const xBox* box, const xVec3* v, xIsect* isx) -{ - if (v->x < box->lower.x) - { - if (v->y < box->lower.y) - { - if (v->z < box->lower.z) - { - isx->norm.x = box->lower.x - v->x; - isx->norm.y = box->lower.y - v->y; - isx->norm.z = box->lower.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x00000000; - isx->flags |= 0x80000000; - } - else if (v->z <= box->upper.z) - { - isx->norm.x = box->lower.x - v->x; - isx->norm.y = box->lower.y - v->y; - isx->norm.z = _557_1; - isx->flags = isx->flags & ~0x1F000000 | 0x01000000; - isx->flags |= 0x40000000; - } - else - { - isx->norm.x = box->lower.x - v->x; - isx->norm.y = box->lower.y - v->y; - isx->norm.z = box->upper.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x02000000; - isx->flags |= 0x80000000; - } - } - else if (v->y <= box->upper.y) - { - if (v->z < box->lower.z) - { - isx->norm.x = box->lower.x - v->x; - isx->norm.y = _557_1; - isx->norm.z = box->lower.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x03000000; - isx->flags |= 0x40000000; - } - else if (v->z <= box->upper.z) - { - isx->norm.x = box->lower.x - v->x; - isx->norm.y = _557_1; - isx->norm.z = _557_1; - isx->flags = isx->flags & ~0x1F000000 | 0x04000000; - isx->flags |= 0x20000000; - } - else - { - isx->norm.x = box->lower.x - v->x; - isx->norm.y = _557_1; - isx->norm.z = box->upper.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x05000000; - isx->flags |= 0x40000000; - } - } - else - { - if (v->z < box->lower.z) - { - isx->norm.x = box->lower.x - v->x; - isx->norm.y = box->upper.y - v->y; - isx->norm.z = box->lower.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x06000000; - isx->flags |= 0x80000000; - } - else if (v->z <= box->upper.z) - { - isx->norm.x = box->lower.x - v->x; - isx->norm.y = box->upper.y - v->y; - isx->norm.z = _557_1; - isx->flags = isx->flags & ~0x1F000000 | 0x07000000; - isx->flags |= 0x40000000; - } - else - { - isx->norm.x = box->lower.x - v->x; - isx->norm.y = box->upper.y - v->y; - isx->norm.z = box->upper.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x08000000; - isx->flags |= 0x80000000; - } - } - } - else if (v->x <= box->upper.x) - { - if (v->y < box->lower.y) - { - if (v->z < box->lower.z) - { - isx->norm.x = _557_1; - isx->norm.y = box->lower.y - v->y; - isx->norm.z = box->lower.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x09000000; - isx->flags |= 0x40000000; - } - else if (v->z <= box->upper.z) - { - isx->norm.x = _557_1; - isx->norm.y = box->lower.y - v->y; - isx->norm.z = _557_1; - isx->flags = isx->flags & ~0x1F000000 | 0x0A000000; - isx->flags |= 0x20000000; - } - else - { - isx->norm.x = _557_1; - isx->norm.y = box->lower.y - v->y; - isx->norm.z = box->upper.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x0B000000; - isx->flags |= 0x40000000; - } - } - else if (v->y <= box->upper.y) - { - if (v->z < box->lower.z) - { - isx->norm.x = _557_1; - isx->norm.y = _557_1; - isx->norm.z = box->lower.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x0C000000; - isx->flags |= 0x20000000; - } - else if (v->z <= box->upper.z) - { - } - else - { - isx->norm.x = _557_1; - isx->norm.y = _557_1; - isx->norm.z = box->upper.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x0E000000; - isx->flags |= 0x20000000; - } - } - else - { - if (v->z < box->lower.z) - { - isx->norm.x = _557_1; - isx->norm.y = box->upper.y - v->y; - isx->norm.z = box->lower.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x0F000000; - isx->flags |= 0x40000000; - } - else if (v->z <= box->upper.z) - { - isx->norm.x = _557_1; - isx->norm.y = box->upper.y - v->y; - isx->norm.z = _557_1; - isx->flags = isx->flags & ~0x1F000000 | 0x10000000; - isx->flags |= 0x20000000; - } - else - { - isx->norm.x = _557_1; - isx->norm.y = box->upper.y - v->y; - isx->norm.z = box->upper.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x11000000; - isx->flags |= 0x40000000; - } - } - } - else - { - if (v->y < box->lower.y) - { - if (v->z < box->lower.z) - { - isx->norm.x = box->upper.x - v->x; - isx->norm.y = box->lower.y - v->y; - isx->norm.z = box->lower.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x12000000; - isx->flags |= 0x80000000; - } - else if (v->z <= box->upper.z) - { - isx->norm.x = box->upper.x - v->x; - isx->norm.y = box->lower.y - v->y; - isx->norm.z = _557_1; - isx->flags = isx->flags & ~0x1F000000 | 0x13000000; - isx->flags |= 0x40000000; - } - else - { - isx->norm.x = box->upper.x - v->x; - isx->norm.y = box->lower.y - v->y; - isx->norm.z = box->upper.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x14000000; - isx->flags |= 0x80000000; - } - } - else if (v->y <= box->upper.y) - { - if (v->z < box->lower.z) - { - isx->norm.x = box->upper.x - v->x; - isx->norm.y = _557_1; - isx->norm.z = box->lower.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x15000000; - isx->flags |= 0x40000000; - } - else if (v->z <= box->upper.z) - { - isx->norm.x = box->upper.x - v->x; - isx->norm.y = _557_1; - isx->norm.z = _557_1; - isx->flags = isx->flags & ~0x1F000000 | 0x16000000; - isx->flags |= 0x20000000; - } - else - { - isx->norm.x = box->upper.x - v->x; - isx->norm.y = _557_1; - isx->norm.z = box->upper.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x17000000; - isx->flags |= 0x40000000; - } - } - else - { - if (v->z < box->lower.z) - { - isx->norm.x = box->upper.x - v->x; - isx->norm.y = box->upper.y - v->y; - isx->norm.z = box->lower.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x18000000; - isx->flags |= 0x80000000; - } - else if (v->z <= box->upper.z) - { - isx->norm.x = box->upper.x - v->x; - isx->norm.y = box->upper.y - v->y; - isx->norm.z = _557_1; - isx->flags = isx->flags & ~0x1F000000 | 0x19000000; - isx->flags |= 0x40000000; - } - else - { - isx->norm.x = box->upper.x - v->x; - isx->norm.y = box->upper.y - v->y; - isx->norm.z = box->upper.z - v->z; - isx->flags = isx->flags & ~0x1F000000 | 0x1A000000; - isx->flags |= 0x80000000; - } - } - } - - isx->dist = xVec3Length(&isx->norm); -} - -void iBoxIsectVec(const xBox* b, const xVec3* v, xIsect* isx) -{ - if (v->x >= b->lower.x && v->x <= b->upper.x && v->y >= b->lower.y && v->y <= b->upper.y && - v->z >= b->lower.z && v->z <= b->upper.z) - { - isx->penned = _608_0; - } - else - { - isx->penned = _558_3; - } -} - -static U32 ClipPlane(F32 denom, F32 numer, F32* t_in, F32* t_out) -{ - if (denom > _557_1) - { - if (numer > denom * (*t_out)) - { - return 0; - } - - if (numer > denom * (*t_in)) - { - *t_in = numer / denom; - } - - return 1; - } - else if (denom < _557_1) - { - if (numer > denom * (*t_in)) - { - return 0; - } - - if (numer > denom * (*t_out)) - { - *t_out = numer / denom; - } - - return 1; - } - - return (numer <= _557_1); -} - -static U32 ClipBox(const xVec3* r3, const xVec3* r4, const xVec3* r5, F32* t_in, F32* t_out) -{ - return (ClipPlane(r5->x, -r4->x - r3->x, t_in, t_out) && - ClipPlane(-r5->x, r4->x - r3->x, t_in, t_out) && - ClipPlane(r5->y, -r4->y - r3->y, t_in, t_out) && - ClipPlane(-r5->y, r4->y - r3->y, t_in, t_out) && - ClipPlane(r5->z, -r4->z - r3->z, t_in, t_out) && - ClipPlane(-r5->z, r4->z - r3->z, t_in, t_out)); -} - -void iBoxIsectRay(const xBox* b, const xRay3* r, xIsect* isx) -{ - xVec3 var_14, var_20; - F32 t_in, t_out; - - if (!(r->flags & 0x400)) - { - ((xRay3*)r)->min_t = _557_1; // wait, that's illegal - } - - if (!(r->flags & 0x800)) - { - ((xRay3*)r)->max_t = _558_3; - } - - // non-matching: incorrect instruction order - - t_in = _1060; - t_out = _1061; - - var_14.x = b->upper.x - b->lower.x; - var_14.y = b->upper.y - b->lower.y; - var_14.z = b->upper.z - b->lower.z; - - var_20.x = b->lower.x + b->upper.x; - var_20.y = b->lower.y + b->upper.y; - - var_14.x *= _555_1; - var_14.y *= _555_1; - var_14.z *= _555_1; - - var_20.z = b->lower.z + b->upper.z; - - var_20.x *= _1062; - var_20.y *= _1062; - var_20.z *= _1062; - - var_20.x += r->origin.x; - var_20.y += r->origin.y; - var_20.z += r->origin.z; - - if (ClipBox(&var_14, &var_20, &r->dir, &t_in, &t_out)) - { - if (t_in < r->min_t) - { - if (t_out < r->min_t) - { - isx->dist = t_out; - isx->penned = _558_3; - isx->contained = _558_3; - } - else - { - isx->dist = t_out; - isx->penned = _608_0; - isx->contained = _608_0; - } - } - else - { - if (t_in <= r->max_t) - { - isx->dist = t_in; - isx->penned = _608_0; - isx->contained = _558_3; - } - else - { - isx->dist = t_in; - isx->penned = _558_3; - isx->contained = _558_3; - } - } - } - else - { - isx->penned = _558_3; - isx->contained = _558_3; - } -} - -void iBoxIsectSphere(const xBox* box, const xSphere* p, xIsect* isx) -{ - U32 xcode, ycode, zcode; - - // non-matching: (p->center.x + p->r) computed inside if statement - - if (p->center.x - p->r < box->lower.x) - { - if (p->center.x + p->r < box->lower.x) - { - xcode = 2; - } - else if (p->center.x + p->r > box->upper.x) - { - xcode = 0; - } - else - { - xcode = 1; - } - } - else - { - if (p->center.x - p->r > box->upper.x) - { - xcode = 5; - } - else if (p->center.x + p->r > box->upper.x) - { - xcode = 4; - } - else - { - xcode = 3; - } - } - - // non-matching: missing division instructions - - if (xcode / 3 == 2) - { - isx->penned = _558_3; - return; - } - - // non-matching: (p->center.y + p->r) computed inside if statement - - if (p->center.y - p->r < box->lower.y) - { - if (p->center.y + p->r < box->lower.y) - { - ycode = 2; - } - else if (p->center.y + p->r > box->upper.y) - { - ycode = 0; - } - else - { - ycode = 1; - } - } - else - { - if (p->center.y - p->r > box->upper.y) - { - ycode = 5; - } - else if (p->center.y + p->r > box->upper.y) - { - ycode = 4; - } - else - { - ycode = 3; - } - } - - // non-matching: missing division instructions - - if (ycode / 3 == 2) - { - isx->penned = _558_3; - return; - } - - // non-matching: (p->center.z + p->r) computed inside if statement - - if (p->center.z - p->r < box->lower.z) - { - if (p->center.z + p->r < box->lower.z) - { - zcode = 2; - } - else if (p->center.z + p->r > box->upper.z) - { - zcode = 0; - } - else - { - zcode = 1; - } - } - else - { - if (p->center.z - p->r > box->upper.z) - { - zcode = 5; - } - else if (p->center.z + p->r > box->upper.z) - { - zcode = 4; - } - else - { - zcode = 3; - } - } - - // non-matching: missing division instructions - - if (zcode / 3 == 2) - { - isx->penned = _558_3; - return; - } - - iBoxIsectVec(box, &p->center, isx); - - if (isx->penned < _557_1) - { - xVec3 var_28; - - xVec3Add(&var_28, &box->lower, &box->upper); - xVec3SMulBy(&var_28, _555_1); - xVec3Sub(&isx->norm, &p->center, &var_28); - - isx->dist = xVec3Length(&isx->norm); - isx->contained = _608_0; - } - else - { - isx->flags = xcode | (ycode << 4) | (zcode << 8); - - iBoxVecDist(box, &p->center, isx); - - isx->penned = isx->dist - p->r; - isx->contained = _558_3; - } -} - -void iBoxInitBoundVec(xBox* b, const xVec3* v) -{ - xVec3Copy(&b->lower, v); - xVec3Copy(&b->upper, v); -} - -void iBoxBoundVec(xBox* o, const xBox* b, const xVec3* v) -{ - xVec3Init(&o->lower, MIN(v->x, b->lower.x), MIN(v->y, b->lower.y), MIN(v->z, b->lower.z)); - xVec3Init(&o->upper, MAX(v->x, b->upper.x), MAX(v->y, b->upper.y), MAX(v->z, b->upper.z)); -} - -F32 xVec2Dist(F32 x1, F32 y1, F32 x2, F32 y2) -{ - F32 x = x1 - x2; - F32 y = y1 - y2; - - return xsqrt(SQR(x) + SQR(y)); -} - -F32 xVec2Dot(const xVec2* a, const xVec2* b) -{ - return a->x * b->x + a->y * b->y; -} - -void xVec2Init(xVec2* v, F32 _x, F32 _y) -{ - v->x = _x; - v->y = _y; -} diff --git a/src/SB/Core/gc/iMemMgr.cpp b/src/SB/Core/gc/iMemMgr.cpp deleted file mode 100644 index 91665e9..0000000 --- a/src/SB/Core/gc/iMemMgr.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "iMemMgr.h" -#include "iSystem.h" -#include "xMemMgr.h" - -#include -#include -#include - -extern xMemInfo_tag gMemInfo; -extern OSHeapHandle he; -extern OSHeapHandle hs; -extern volatile OSHeapHandle the_heap; -extern unsigned char _stack_addr[]; -extern U32 HeapSize; -extern U32 mem_top_alloc; -extern U32 mem_base_alloc; - -// Starts going wrong after the if and else statement, everything else before looks fine. -void iMemInit() -{ - OSHeapHandle hi = (OSHeapHandle)OSGetArenaHi(); - he = hi & 0xffffffe0; - hs = (OSHeapHandle)OSGetArenaLo() + 0x1f & 0xffffffe0; - the_heap = OSCreateHeap(OSInitAlloc((void*)hs, (void*)(hi & 0xffffffe0), 1), (void*)he); - OSHeapHandle currHeap = the_heap; - if (currHeap >= 0) - { - OSSetCurrentHeap(currHeap); - } - else - { - exit(-5); - } - gMemInfo.system.addr = 0; - gMemInfo.system.size = 0x100000; - gMemInfo.system.flags = 0x20; - gMemInfo.stack.addr = (U32)&_stack_addr; - gMemInfo.stack.size = 0xffff8000; - gMemInfo.stack.flags = gMemInfo.DRAM.flags = 0x820; - HeapSize = 0x384000; - gMemInfo.DRAM.addr = (U32)OSAllocFromHeap(__OSCurrHeap, 0x384000); - gMemInfo.DRAM.size = HeapSize; - gMemInfo.DRAM.flags = 0x820; - gMemInfo.SRAM.addr = 0; - gMemInfo.SRAM.size = 0x200000; - gMemInfo.SRAM.flags = 0x660; - mem_top_alloc = gMemInfo.DRAM.addr + HeapSize; - mem_base_alloc = gMemInfo.DRAM.addr; -} - -void iMemExit() -{ - free((void*)gMemInfo.DRAM.addr); - gMemInfo.DRAM.addr = 0; -} diff --git a/src/SB/Core/gc/iMix.cpp b/src/SB/Core/gc/iMix.cpp deleted file mode 100644 index 28a8da4..0000000 --- a/src/SB/Core/gc/iMix.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "iMix.h" - -#include diff --git a/src/SB/Core/gc/iModel.cpp b/src/SB/Core/gc/iModel.cpp deleted file mode 100644 index dd3e9b6..0000000 --- a/src/SB/Core/gc/iModel.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "iModel.h" - -#include - -void iModelCacheAtomic(RpAtomic*) -{ -} diff --git a/src/SB/Core/gc/iMorph.cpp b/src/SB/Core/gc/iMorph.cpp deleted file mode 100644 index 5af9baf..0000000 --- a/src/SB/Core/gc/iMorph.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "iMorph.h" - -#include diff --git a/src/SB/Core/gc/iPad.cpp b/src/SB/Core/gc/iPad.cpp deleted file mode 100644 index 6a04b9c..0000000 --- a/src/SB/Core/gc/iPad.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include - -#include "xTRC.h" -#include "zGlobals.h" - -extern xGlobals* xglobals; -extern zGlobals globals; - -PADStatus sPadData[PAD_MAX_CONTROLLERS]; - -S32 iPadInit() -{ - PADInit(); - return 1; -} - -_tagxPad* iPadEnable(_tagxPad* pad, S16 port) -{ - pad->port = port; - pad->slot = 0; - pad->state = ePad_Enabled; - gTrcPad[pad->port].state = TRC_PadInserted; - pad->flags |= 3; - pad->flags |= 4; - return pad; -} - -S32 iPadConvStick(F32 value) -{ - F32 clampedValue; - if (value > 40.0f) - { - clampedValue = 40.0f; - } - else if (value < -40.0f) - { - clampedValue = -40.0f; - } - else - { - clampedValue = value; - } - - F32 convertedValue = 3.2f * clampedValue; - - if (convertedValue > 127.0f) - { - convertedValue = 127.0f; - } - else if (convertedValue < -127.0f) - { - convertedValue = -127.0f; - } - - return convertedValue; -} - -S32 iPadUpdate(_tagxPad* pad, U32* on) -{ - U16 buttons; - U32 temp_on; - - if (pad->port == 0) - { - PADRead(sPadData); - PADClamp(sPadData); - } - - PADStatus* padData = (PADStatus*)&sPadData; - switch (padData[pad->port].err) - { - case PAD_ERR_NO_CONTROLLER: - xTRCPad(pad->port, TRC_PadMissing); - PADReset(0x80000000 >> pad->port); - goto defaultError; - - case PAD_ERR_NOT_READY: - case PAD_ERR_TRANSFER: - return 0; - - default: - defaultError: - return 0; - - case PAD_ERR_NONE: - temp_on = iPadConvFromGCN(padData[pad->port].button, 1, 0x80); - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 2, 0x20); - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 4, 0x40); - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 8, 0x10); - buttons = sPadData[pad->port].button; - - if (buttons & 0x10) - { - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x20, 0x2000); - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x40, 0x200); - if (sPadData[pad->port].triggerLeft >= 0x18) - { - temp_on |= 0x200; - } - if (sPadData[pad->port].triggerRight >= 0x18) - { - temp_on |= 0x2000; - } - temp_on |= 0x100000; - } - else - { - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x20, 0x1000); - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x40, 0x100); - if (sPadData[pad->port].triggerLeft >= 0x18) - { - temp_on |= 0x100; - } - if (sPadData[pad->port].triggerRight >= 0x18) - { - temp_on |= 0x1000; - } - } - - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x100, 0x10000); - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x200, 0x80000); - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x800, 0x40000); - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x400, 0x20000); - temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x1000, 0x1); - (*on) = temp_on; - - pad->analog1.x = iPadConvStick(sPadData[pad->port].stickX); - pad->analog1.y = -iPadConvStick(sPadData[pad->port].stickY); // Scheduling memes. - pad->analog2.x = iPadConvStick(sPadData[pad->port].substickX); - pad->analog2.y = -iPadConvStick(sPadData[pad->port].substickY); // Same as above. - if (gTrcPad[pad->port].state != TRC_PadInserted) - { - xTRCPad(pad->port, TRC_PadInserted); - } - } - return 1; -} - -S32 iPadConvFromGCN(U32 a, U32 b, U32 c) -{ - // TODO: this can probably be simplified, - // basically a copy of ghidra's output - return c & (S32)(-(a & b) | a & b) >> 0x1f; -} - -void iPadRumbleFx(_tagxPad* p, _tagxRumble* r, F32 time_passed) -{ -} - -void iPadStopRumble() -{ - PADControlMotor(mPad[globals.currentActivePad].port, 0); // Scheduling memes. -} - -void iPadStopRumble(_tagxPad* pad) -{ - PADControlMotor(pad->port, 0); -} - -void iPadStartRumble(_tagxPad* pad, _tagxRumble* rumble) -{ - PADControlMotor(pad->port, 1); -} - -void iPadKill() -{ -} diff --git a/src/SB/Core/gc/iParMgr.cpp b/src/SB/Core/gc/iParMgr.cpp deleted file mode 100644 index b8e280c..0000000 --- a/src/SB/Core/gc/iParMgr.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "iParMgr.h" - -#include - -void iParMgrUpdate(F32) -{ -} - -void iParMgrRender() -{ -} diff --git a/src/SB/Core/gc/iScrFX.cpp b/src/SB/Core/gc/iScrFX.cpp index 004f6af..e69de29 100644 --- a/src/SB/Core/gc/iScrFX.cpp +++ b/src/SB/Core/gc/iScrFX.cpp @@ -1,117 +0,0 @@ -// ported from bfbb repo -#include "iScrFX.h" - -#include - -extern RwRaster *g_rast_gctapdance; -extern S32 g_alreadyTriedAlloc; -extern _iMotionBlurData sMBD; -extern U32 sMotionBlurEnabled; -extern F32 lbl_803CE168; // 0.0f -extern F32 lbl_803CE174; // 1.0f -extern F32 lbl_803CE178; // 0.5f -extern F32 lbl_803CE17C; // 254f - -void iScrFxInit() {} - -void iScrFxBegin() { - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERNEAREST); - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)rwFOGTYPENAFOGTYPE); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, NULL); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, NULL); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)true); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); -} - -void iScrFxEnd() { - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)rwFOGTYPENAFOGTYPE); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)true); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)true); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)false); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); -} - -void iCameraMotionBlurActivate(U32 activate) { sMotionBlurEnabled = activate; } - -// The instructions regarding the setting of sMotionBlurEnabled and -// sMBD.motionBlurAlpha are in the wrong order. -void iCameraSetBlurriness(F32 amount) { - if (amount <= lbl_803CE168) { - sMotionBlurEnabled = 0; - } else { - if (amount > lbl_803CE174) { - amount = lbl_803CE174; - } - sMotionBlurEnabled = 1; - sMBD.motionBlurAlpha = (S32)(lbl_803CE17C * amount + lbl_803CE178); - } -} - -// Instructions in the wrong order. -void iScrFxCameraCreated(RwCamera *pCamera) { - sMBD.motionBlurAlpha = 0x90; - sMBD.motionBlurFrontBuffer = NULL; - sMBD.index[0] = 0; - sMBD.index[1] = 1; - sMBD.index[2] = 2; - sMBD.index[3] = 0; - sMBD.index[4] = 2; - sMBD.index[5] = 3; - iScrFxMotionBlurOpen(pCamera); -} - -void iScrFxCameraEndScene(RwCamera *pCamera) { - if ((sMotionBlurEnabled != 0) && (sMBD.motionBlurAlpha != 0)) { - iScrFxMotionBlurRender(pCamera, sMBD.motionBlurAlpha & 0xff); - } -} - -void iScrFxPostCameraEnd(RwCamera *pCamera) { GCMB_SiphonFrameBuffer(pCamera); } - -RwRaster *FBMBlur_DebugIntervention(RwCamera *camera, RwRaster *ras) { - return ras; -} - -S32 iScrFxMotionBlurOpen(RwCamera *camera) { return 0; } - -S32 iScrFxCameraDestroyed(RwCamera *pCamera) { - GCMB_KillFrameBufferCopy(); - if (sMBD.motionBlurFrontBuffer != NULL) { - RwRasterDestroy(sMBD.motionBlurFrontBuffer); - sMBD.motionBlurFrontBuffer = NULL; - return 1; - } - return 0; -} - -// WIP. -void iScrFxMotionBlurRender(RwCamera *camera, U32 col) { - if (sMBD.motionBlurFrontBuffer != NULL) { - RwRGBA col; - col.alpha = 0xf8; - iCameraOverlayRender(camera, (RwRaster *)sMBD.motionBlurFrontBuffer, col); - } -} - -void GCMB_MakeFrameBufferCopy(const RwCamera *camera) {} - -void GCMB_KillFrameBufferCopy() { - if (g_rast_gctapdance != NULL) { - RwRasterDestroy(g_rast_gctapdance); - } - g_rast_gctapdance = NULL; - g_alreadyTriedAlloc = 0; -} - -void GCMB_SiphonFrameBuffer(const RwCamera *camera) { - if ((g_rast_gctapdance == NULL) && (g_alreadyTriedAlloc == 0)) { - GCMB_MakeFrameBufferCopy(camera); - } - if (g_rast_gctapdance != NULL) { - RwGameCubeCameraTextureFlush(g_rast_gctapdance, 0); - } -} diff --git a/src/SB/Core/gc/iSnd.cpp b/src/SB/Core/gc/iSnd.cpp deleted file mode 100644 index 7ac9e89..0000000 --- a/src/SB/Core/gc/iSnd.cpp +++ /dev/null @@ -1,165 +0,0 @@ -#include "iSnd.h" - -#include -#include - -#include "intrin.h" - -#include "iMix.h" -#include "xCutscene.h" -#include "xSnd.h" -#include "xMath.h" - -extern vinfo voices[58]; -extern char soundInited; -extern S32 SoundFlags; -extern F32 _1262; -extern F32 _1263; -extern volatile S32 fc; - -void arq_callback(long) -{ - if (!soundInited) - { - return; - } - SoundFlags = 0; -} - -void iSndExit() -{ - soundInited = 0; - AXQuit(); -} - -//not sure where this type is from. -void iSndSetEnvironmentalEffect(isound_effect) -{ - return; -} - -void iSndInitSceneLoaded() -{ -} - -U32 iVolFromX(F32 param1) -{ - float f = MAX(param1, 1e-20f); - - S32 i = 43.43f * xlog(f); - S32 comp = MIN(i, 0); - - if (comp < -0x388) - { - return -0x388; - } - else - { - return MIN(i, 0); - } -} - -void iSndVolUpdate(xSndVoiceInfo* info, vinfo* vinfo) -{ - MIXUnMute(vinfo->voice); - xSndInternalUpdateVoicePos(info); - if ((info->flags & 8) != 0) - { - iSndCalcVol3d(info, vinfo); - } - else - { - iSndCalcVol(info, vinfo); - } -} - -void iSndUpdateSounds() -{ - if (!soundInited) - { - return; - } - - for (int i = 0; i < 58; i++) - { - if (voices[i].voice != NULL) - { - iSndVolUpdate(&gSnd.voice[i + 6], &voices[i]); - } - } -} - -void iSndStartStereo(U32 id1, U32 id2, F32 pitch) -{ -} - -void iSndStereo(U32 i) -{ - if (i == 0) - { - OSSetSoundMode(0); - gSnd.stereo = 0; - } - else - { - OSSetSoundMode(1); - gSnd.stereo = 1; - } -} - -void iSndWaitForDeadSounds() -{ - fc = 0; - int i = 0; - // Can't get 0x8c to get stored in r31 - while ((i = fc) < 0x8c) //for (int i = 0; (i = fc) < 0x8c; ) - { - i = fc; - while (fc < i + 0xe) - ; - iSndUpdate(); - } -} - -void iSndSuspendCD(U32) -{ -} - -void iSndMessWithEA(sDSPADPCM* param1) -{ - if (param1 != NULL) - { - param1->buffer[5] = SampleToNybbleAddress(param1->buffer[0] - 1); - } -} - -U32 SampleToNybbleAddress(U32 sample) -{ - U32 a = __mulhwu(0x24924925, sample); - U32 b = (sample - a) >> 1; - - a = b + a; - b = (a >> 3); - a = (a << 1) & 0xfffffff0; - a = a + (sample - (b * 0xe)) + 2; - - return a; -} - -void sndloadcb(tag_xFile* tag) -{ - SoundFlags = 0; -} - -void iSndSetExternalCallback(void (*func_ptr)(U32)) -{ -} - -void iSndMyAXFree(_AXVPB** param1) -{ - if (param1 != NULL && *param1 != NULL) - { - AXFreeVoice(*param1); - *param1 = NULL; - } -} diff --git a/src/SB/Core/gc/iSystem.cpp b/src/SB/Core/gc/iSystem.cpp deleted file mode 100644 index d226793..0000000 --- a/src/SB/Core/gc/iSystem.cpp +++ /dev/null @@ -1,235 +0,0 @@ -#include "iSystem.h" - -#include - -#include - -#include "xDebug.h" -#include "xMath.h" -#include "xSnd.h" -#include "xPad.h" -#include "xMemMgr.h" - -#include "iSystem.h" -#include "iFile.h" -#include "iTime.h" -#include "iTRC.h" - -extern U32 mem_base_alloc; -extern U32 add; -extern U32 size; -extern S32 gEmergencyMemLevel; -extern OSHeapHandle the_heap; -extern void* bad_val; -extern void* MemoryFunctions[4]; -extern U16 last_error; -extern OSContext* last_context; - -// Taken from iSystem.s -// Defining these here makes the stringBase0 offsets match in the later functions. -char* str1 = "Level %d, Warning $03d: %s\n"; -char* str2 = "FPE: Invalid operation: "; -char* str3 = "SNaN\n"; -char* str4 = "Infinity - Infinity\n"; -char* str5 = "Infinity / Infinity\n"; -char* str6 = "0 / 0\n"; -char* str7 = "Infinity * 0\n"; -char* str8 = "Invalid compare\n"; -char* str9 = "Software request\n"; -char* str10 = "Invalid square root\n"; -char* str11 = "Invalid integer convert\n"; -char* str12 = "FPE: Overflow\n"; -char* str13 = "FPE: Underflow\n"; -char* str14 = "FPE: Zero division\n"; -char* str15 = "FPE: Inexact result\n"; -char* str16 = "iSystem.cpp"; -char* str17 = "Unable to initialize memory system.\n"; -char* str18 = "(With apologies to Jim Morrison) This the end, my only friend, The End."; -char* str19 = "%s.rw3"; - -void** psGetMemoryFunctions() -{ - return MemoryFunctions; -} - -void iVSync() -{ - VIWaitForRetrace(); -} - -U16 my_dsc(U16 dsc) -{ - return dsc; -} - -void MemoryProtectionErrorHandler(U16 last, OSContext* ctx, U64 unk1, U64 unk2) -{ - last_error = last; - last_context = ctx; - if (ctx->fpscr) - { - null_func(); - } -} - -// FIXME: Define a bunch of functions :) -void TRCInit() -{ - iTRCDisk::Init(); - // iTRCDisk::SetPadStopRumblingFunction(iPadStopRumble); - // iTRCDisk::SetSndSuspendFunction(iSndSuspend); - // iTRCDisk::SetSndResumeFunction(iSndResume); - // iTRCDisk::SetSndKillFunction(iSndDIEDIEDIE); - // iTRCDisk::SetMovieSuspendFunction(iFMV::Suspend); - // iTRCDisk::SetMovieResumeFunction(iFMV::Resume); - // ResetButton::SetSndKillFunction(iSndDIEDIEDIE); -} - -S32 RenderWareExit() -{ - RwEngineStop(); - RwEngineClose(); - return RwEngineTerm(); -} - -void iSystemExit() -{ - xDebugExit(); - xMathExit(); - RenderWareExit(); - xSndExit(); - xPadKill(); - iFileExit(); - iTimeExit(); - xMemExit(); - OSPanic("iSystem.cpp", 0x21d, - "(With apologies to Jim Morrison) This the end, my only friend, The End."); -} - -void null_func() -{ - mem_base_alloc += 4; -} - -extern "C" { -void mem_null(U32 param_1, U32 param_2) -{ - add = param_1; - size = param_2; -} - -void* malloc(U32 __size) -{ - if ((S32)__size <= 0) - { - return NULL; - } - - void* result = OSAllocFromHeap(the_heap, __size); - - if (result == NULL) - { - null_func(); - } - - return result; -} - -void free(void* __ptr) -{ - if (__ptr != NULL) - { - OSFreeToHeap(the_heap, __ptr); - } -} -} - -void _rwDolphinHeapFree(void* __ptr) -{ - if (__ptr == bad_val) - { - mem_null(0, 0); - } - if (__ptr != NULL) - { - if (*(S32*)((S32)__ptr - 4) == 0xDEADBEEF) - { - free((void*)((S32)__ptr - 32)); - } - else - { - null_func(); - if (gEmergencyMemLevel != 0) - { - xMemPopBase(gEmergencyMemLevel); - gEmergencyMemLevel = 0; - } - } - } -} - -S32 iGetMinute() -{ - OSTime ticks = OSGetTime(); - OSCalendarTime td; - OSTicksToCalendarTime(ticks, &td); - return td.min; -} - -S32 iGetHour() -{ - OSTime ticks = OSGetTime(); - OSCalendarTime td; - OSTicksToCalendarTime(ticks, &td); - return td.hour; -} - -S32 iGetDay() -{ - OSTime ticks = OSGetTime(); - OSCalendarTime td; - OSTicksToCalendarTime(ticks, &td); - return td.mday; -} - -S32 iGetMonth() -{ - OSTime ticks = OSGetTime(); - OSCalendarTime td; - OSTicksToCalendarTime(ticks, &td); - return td.mon + 1; -} - -// Template for future use. TODO -char* iGetCurrFormattedDate(char* input) -{ - return NULL; -} - -// WIP. -char* iGetCurrFormattedTime(char* input) -{ - OSTime ticks = OSGetTime(); - OSCalendarTime td; - OSTicksToCalendarTime(ticks, &td); - bool pm = false; - // STUFF. - char* ret = input; - // STUFF. - if (pm) - { - ret[8] = 'P'; - ret[9] = '.'; - ret[10] = 'M'; - ret[11] = '.'; - } - else - { - ret[8] = 'A'; - ret[9] = '.'; - ret[10] = 'M'; - ret[11] = '.'; - } - ret[12] = '\0'; - return ret + (0xd - (S32)input); -} diff --git a/src/SB/Core/gc/iTime.cpp b/src/SB/Core/gc/iTime.cpp deleted file mode 100644 index 0035caf..0000000 --- a/src/SB/Core/gc/iTime.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "iTime.h" -#include "iSystem.h" - -#include -#include - -static iTime sStartupTime; -static F32 sGameTime; - -void iTimeInit() -{ - sStartupTime = OSGetTime(); -} - -void iTimeExit() -{ -} - -iTime iTimeGet() -{ - return OSGetTime() - sStartupTime; -} - -F32 iTimeDiffSec(iTime time) -{ - return (F32)time / (GET_BUS_FREQUENCY() / 4); -} - -F32 iTimeDiffSec(iTime t0, iTime t1) -{ - return iTimeDiffSec(t1 - t0); -} - -void iTimeGameAdvance(F32 elapsed) -{ - sGameTime += elapsed; -} - -void iTimeSetGame(F32 time) -{ - sGameTime = time; -} - -void iProfileClear(U32 sceneID) -{ - // Redacted. :} -} - -void iFuncProfileDump() -{ - // Redacted. :} -} - -void iFuncProfileParse(char* elfPath, S32 profile) -{ - // Redacted. :} -} diff --git a/src/SB/Core/gc/iWad.cpp b/src/SB/Core/gc/iWad.cpp index e69de29..c721e73 100644 --- a/src/SB/Core/gc/iWad.cpp +++ b/src/SB/Core/gc/iWad.cpp @@ -0,0 +1,4082 @@ +#include "iWad.h" + +static iTime sStartupTime; +static F32 sGameTime; +extern U32 add; +extern U32 size; +extern OSHeapHandle the_heap; +extern U16 last_error; +extern OSContext* last_context; +static st_ISGSESSION g_isgdata_MAIN = { 0 }; + +// iTime + +void iFuncProfileFuncs(int, int, float) +{ +} + +void iFuncProfileDump() +{ +} + +void iProfileClear(U32 sceneID) +{ +} + +void iTimeSetGame(F32 time) +{ + sGameTime = time; +} + +void iTimeGameAdvance(F32 elapsed) +{ + sGameTime += elapsed; +} + +F32 iTimeGetGame() +{ + return sGameTime; +} + +F32 iTimeDiffSec(iTime t0, iTime t1) +{ + return iTimeDiffSec(t1 - t0); +} + +F32 iTimeDiffSec(iTime time) +{ + return (F32)time / (GET_BUS_FREQUENCY() / 4); +} + +iTime iTimeGet() +{ + return OSGetTime() - sStartupTime; +} + +// WIP. +char* iGetCurrFormattedTime(char* input) +{ + OSTime ticks = OSGetTime(); + OSCalendarTime td; + OSTicksToCalendarTime(ticks, &td); + bool pm = false; + // STUFF. + char* ret = input; + // STUFF. + if (pm) + { + ret[8] = 'P'; + ret[9] = '.'; + ret[10] = 'M'; + ret[11] = '.'; + } + else + { + ret[8] = 'A'; + ret[9] = '.'; + ret[10] = 'M'; + ret[11] = '.'; + } + ret[12] = '\0'; + return ret + (0xd - (S32)input); +} + +// Template for future use. TODO +char* iGetCurrFormattedDate(char* input) +{ + return NULL; +} + +S32 iGetMonth() +{ + OSTime ticks = OSGetTime(); + OSCalendarTime td; + OSTicksToCalendarTime(ticks, &td); + return td.mon + 1; +} + +S32 iGetDay() +{ + OSTime ticks = OSGetTime(); + OSCalendarTime td; + OSTicksToCalendarTime(ticks, &td); + return td.mday; +} + +S32 iGetHour() +{ + OSTime ticks = OSGetTime(); + OSCalendarTime td; + OSTicksToCalendarTime(ticks, &td); + return td.hour; +} + +S32 iGetMinute() +{ + OSTime ticks = OSGetTime(); + OSCalendarTime td; + OSTicksToCalendarTime(ticks, &td); + return td.min; +} + +extern "C" { + +void* malloc(U32 __size) +{ + if ((S32)__size <= 0) + { + return NULL; + } + + void* result = OSAllocFromHeap(the_heap, __size); + + if (result == NULL) + { + null_func(); + } + + return result; +} + +void free(void* __ptr) +{ + if (__ptr != NULL) + { + OSFreeToHeap(the_heap, __ptr); + } +} +} + +S32 RenderWareExit() +{ + RwEngineStop(); + RwEngineClose(); + return RwEngineTerm(); +} + +void iSystemExitRWFailSafe() +{ + RwEngineStop(); + RwEngineClose(); +} + +void iSystemExit() // TO-DO - Need to update function calls +{ + xDebugExit(); + xMathExit(); + RwEngineStop(); + RwEngineClose(); + RwEngineTerm(); + xSndMgrExit(); + xPadKill(); + xMemExit(); + OSPanic("GGVE", 0x1e7, + "(With apologies to Jim Morrison) This the end, my only friend, The End."); +} + +void MemoryProtectionErrorHandler(U16 last, OSContext* ctx, U64 unk1, U64 unk2) +{ + last_error = last; + last_context = ctx; +} + +U16 my_dsc(U16 dsc) +{ + return dsc; +} + +void iVSync() +{ + VIWaitForRetrace(); +} + +// iSnd + +void iSndSuspendCD(U32) +{ +} + +void iSndSetExternalCallback(void* func_ptr) +{ +} + +// void iSndStartStereo(iSndHandle id1, iSndHandle id2) +// { +// } + +// void iSndExit() +// { +// FSOUND_Close(); +// } + +// iSaveGame + +// Not 100% on what this does or if it's correctly defined for all cases. Seems to be used for allocation alignment +#define ALIGN_THING(x, n) (n + x - 1 & -x) + +// name is a total guess for now +struct st_ISG_TPL_TEX +{ + struct UnkIn + { + U32 unk_0; + U32 unk_4; + void* unk_8; + U32 unk_c; + U32 unk_10[4]; + U8 unk_20; + U8 unk_21; + U8 unk_22; + U8 unk_23; + }; + struct UnkOut + { + U8 unk_0; + U8 unk_1; + U8 unk_2; + U8 unk_3; + U32 unk_4; + void* unk_8; + }; + + UnkIn* unk_0; + UnkOut* unk_4; +}; + +// WIP. Looks like some sort of header for a file with embedded texture information. +struct st_ISG_TPL_TEXPALETTE +{ + U32 magic; + U32 count; + st_ISG_TPL_TEX* unk_8; +}; + +struct IconData +{ + char game_name[0x20]; + char buf0[0x20]; + char buf1[0x1800]; + char buf2[8][0x800]; + char pad[0x200]; + char footer[0x200]; +}; + +static volatile S32 g_isginit; +static S32 g_legalSectSize[] = { 0x2000, 0, -1 }; +static st_ISG_TPL_TEXPALETTE* g_rawicon; +static st_ISG_TPL_TEXPALETTE* g_rawbanr; +static U32 g_iconsize; +static U32 g_banrsize; +static U8 isMounted; + +S32 iSGAutoSave_Monitor(st_ISGSESSION* isg, S32 idx_target) +{ + if (isg == NULL) + { + return 0; + } + + U32 ret = iSGTgtState(isg, idx_target, NULL); + if (ret == 0 || (ret & 1) == 0) + { + globals.autoSaveFeature = 0; + return 0; + } + return 1; +} + +void iSGAutoSave_Startup() +{ +} + +U8 iSGCheckMemoryCard(st_ISGSESSION* isgdata, S32 index) +{ + s32 memSize; + s32 sectorSize; + + switch (CARDProbeEx(index, &memSize, §orSize)) + { + case CARD_RESULT_READY: + return 1; + } + return 0; +} + +static S32 iSG_curKosher(CARDStat* stat, CARDFileInfo* info) // FIX +{ + S32 rc = 1; + + if ((stat->iconAddr < 1 || stat->iconAddr > 0x7fffffff) && + (stat->commentAddr < 1 || stat->commentAddr > 0x7fffffff)) + { + rc = 0; + } + else + { + char stuff[0x200] = { 0 }; + sprintf(stuff, "SPONGEBOB:WHENROBOTSATTACK::RyanNeilDan"); + void* alloc = xMemPushTemp(0x5e00 + 0x1f); + // align buf address to 32 bytes + char* buf = (char*)((U32)alloc + 0x1f & ~0x1f); + + S32 result; + do + { + result = CARDRead(info, buf, 0x5e00, 0); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + if (memcmp(buf + 0x5a40, stuff, strlen(stuff) - 1)) + { + rc = 0; + } + + if (memcmp(buf, "Battle for Bikini Bottom", strlen("Battle for Bikini Bottom") - 1)) + { + rc = 0; + } + } + + xMemPopTemp(alloc); + } + + return rc; +} + +static S32 iSG_mc_fdel(st_ISG_MEMCARD_DATA* mcdata, const char* fname) +{ + if (mcdata->chan < 0 || mcdata->chan > 1) + { + return 0; + } + + if (isMounted == 0) + { + return 0; + } + + s32 result; + do + { + result = CARDDelete(mcdata->chan, fname); + } while (result == CARD_RESULT_BUSY); + + S32 ret; + if (result == CARD_RESULT_NOFILE) + { + ret = 1; + } + else if (result == CARD_RESULT_READY) + { + ret = 1; + } + else + { + ret = 0; + switch (result) + { + case CARD_RESULT_IOERROR: + mcdata->unk_12c = 1; + break; + case CARD_RESULT_NOPERM: + case CARD_RESULT_FATAL_ERROR: + case CARD_RESULT_WRONGDEVICE: + break; + } + } + return ret; +} + +static S32 iSG_mc_fclose(st_ISG_MEMCARD_DATA* mcdata, CARDStat* stat) +{ + S32 ret = 0; + s32 result; + do + { + result = CARDClose(&mcdata->finfo); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + + if (stat != NULL) + { + memcpy(stat, &mcdata->fstat, sizeof(CARDStat)); + } + + memset(&mcdata->finfo, 0, sizeof(CARDFileInfo)); + memset(&mcdata->fstat, 0, sizeof(CARDStat)); + + return ret; +} + +static S32 iSG_mc_fclose(st_ISG_MEMCARD_DATA* mcdata) +{ + return iSG_mc_fclose(mcdata, NULL); +} + +static S32 iSG_mc_fopen(st_ISG_MEMCARD_DATA* mcdata, const char* fname, S32 fsize, + en_ISG_IOMODE mode, en_ASYNC_OPERR* operr) +{ + S32 ret = 0; + CARDFileInfo* finfo = &mcdata->finfo; + CARDStat* stat = &mcdata->fstat; + if (operr != NULL) + { + *operr = ISG_OPERR_NONE; + } + + if (mode == ISG_IOMODE_READ) + { + s32 result; + do + { + result = CARDOpen(mcdata->chan, (char*)fname, finfo); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + } + else + { + S32 res = iSG_mc_fdel(mcdata, fname); + if (mcdata->unk_12c == 0 && res > 0) + { + s32 result; + do + { + result = CARDCreate(mcdata->chan, (char*)fname, fsize, finfo); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + mcdata->unk_98 = 0; + } + else if (operr != NULL) + { + switch (result) + { + case CARD_RESULT_WRONGDEVICE: + case CARD_RESULT_NOCARD: + *operr = ISG_OPERR_NOCARD; + break; + case CARD_RESULT_IOERROR: + case CARD_RESULT_BROKEN: + mcdata->unk_12c = 1; + *operr = ISG_OPERR_DAMAGE; + break; + case CARD_RESULT_NOENT: + case CARD_RESULT_INSSPACE: + *operr = ISG_OPERR_NOROOM; + break; + default: + *operr = ISG_OPERR_OTHER; + break; + case CARD_RESULT_READY: + case CARD_RESULT_BUSY: + case CARD_RESULT_EXIST: + case CARD_RESULT_NOPERM: + break; + } + } + } + } + + if (ret != 0) + { + s32 result; + do + { + result = CARDGetStatus(mcdata->chan, finfo->fileNo, stat); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + } + + if (ret != 0) + { + if (memcmp(stat->gameName, "GQPE", 4) != 0 || memcmp(stat->company, "78", 2) != 0) + { + iSG_mc_fclose(mcdata); + ret = 0; + } + } + + return ret; +} + +static S32 iSG_fileKosher(st_ISG_MEMCARD_DATA* mcdata, const char* param2, int param3, int* param4) +{ + S32 rc = 0; + en_ASYNC_OPERR operr = ISG_OPERR_NONE; + + if (param4) + { + *param4 = 0; + } + + if (iSG_mc_fopen(mcdata, param2, -1, ISG_IOMODE_READ, &operr) == 0) + { + return -1; + } + + S32 ret = iSG_curKosher(&mcdata->fstat, &mcdata->finfo); + iSG_mc_fclose(mcdata); + + if (ret == 0) + { + rc = 0; + if (param3 && iSG_mc_fdel(mcdata, param2) && param4) + { + *param4 = 1; + } + } + else + { + rc = 1; + } + return rc; +} + +S32 iSGCheckForCorruptFiles(st_ISGSESSION* isgdata, char files[][64]) +{ + if (isgdata->slot < 0) + { + return 0; + } + + S32 i; + char* name; + st_ISG_MEMCARD_DATA* mcdata = &isgdata->mcdata[isgdata->slot]; + S32 ret = 0; + memset(files, NULL, 0xc0); + + for (i = 0; i < ISG_NUM_FILES; ++i) + { + name = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, i); + if (iSG_fileKosher(mcdata, name, 0, NULL) == 0) + { + strcpy(files[ret], name); + ret++; + } + } + return ret; +} + +S32 iSGCheckForWrongDevice() +{ + char* workarea = (char*)RwMalloc(0x10000 - 0x6000); + + S32 ret = -1; + for (S32 i = 0; i < ISG_NUM_SLOTS; ++i) + { + s32 result = CARDMount(i, workarea, NULL); + + switch (result) + { + case CARD_RESULT_READY: + case CARD_RESULT_BROKEN: + case CARD_RESULT_ENCODING: + CARDUnmount(i); + break; + case CARD_RESULT_WRONGDEVICE: + ret = i; + i = ISG_NUM_SLOTS; + break; + } + } + + RwFree(workarea); + + return ret; +} + +static void iSG_cb_asyndone(s32, s32) +{ +} + +static S32 iSG_mcqa_fwrite(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len) +{ + S32 ret = 0; + S32 x = 1000; + CARDStat* fstat = &mcdata->fstat; + s32 result; + do + { + result = CARDGetResultCode(mcdata->chan); + } while (result == CARD_RESULT_BUSY); + + if (result != CARD_RESULT_READY) + { + return 0; + } + + CARDGetXferredBytes(mcdata->chan); + s32 asynresult; + do + { + asynresult = CARDWriteAsync(&mcdata->finfo, buf, len, mcdata->unk_98, iSG_cb_asyndone); + } while (asynresult == CARD_RESULT_BUSY); + + if (asynresult != CARD_RESULT_READY) + { + return 0; + } + + result = CARD_RESULT_BUSY; + do + { + if (x++ > 500) + { + result = CARDGetResultCode(mcdata->chan); + xSndUpdate(); + CARDGetXferredBytes(mcdata->chan); + x = 0; + } + iTRCDisk::CheckDVDAndResetState(); + } while (result == CARD_RESULT_BUSY); + + if (asynresult == CARD_RESULT_READY) + { + mcdata->unk_98 += len; + + do + { + result = CARDGetStatus(mcdata->chan, mcdata->finfo.fileNo, fstat); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + } + return ret; +} + +static S32 iSG_mcqa_fread(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len, S32 offset) +{ + S32 x = 1000; + s32 result = CARDGetResultCode(mcdata->chan); + do + { + result = CARDGetResultCode(mcdata->chan); + } while (result == CARD_RESULT_BUSY); + + if (result != CARD_RESULT_READY) + { + return 0; + } + + CARDGetXferredBytes(mcdata->chan); + do + { + result = CARDReadAsync(&mcdata->finfo, buf, len, offset, iSG_cb_asyndone); + } while (result == CARD_RESULT_BUSY); + + if (result != CARD_RESULT_READY) + { + return 0; + } + + result = CARD_RESULT_BUSY; + do + { + if (x++ > 500) + { + xSndUpdate(); + CARDGetXferredBytes(mcdata->chan); + result = CARDGetResultCode(mcdata->chan); + x = 0; + } + iTRCDisk::CheckDVDAndResetState(); + } while (result == CARD_RESULT_BUSY); + return result != 0 ? 0 : 1; +} + +static S32 iSG_mc_format(st_ISG_MEMCARD_DATA* mcdata, S32, S32* canRecover) +{ + if (mcdata->unk_12c != 0) + { + if (canRecover != NULL) + { + *canRecover = 0; + } + return 0; + } + + if (canRecover != NULL) + { + *canRecover = 1; + } + + s32 result; + do + { + result = CARDFormat(mcdata->chan); + } while (result == CARD_RESULT_BUSY); + + S32 ret; + if (result == CARD_RESULT_READY) + { + ret = 1; + } + else + { + ret = 0; + + switch (result) + { + case CARD_RESULT_IOERROR: + mcdata->unk_12c = 1; + if (canRecover != NULL) + { + *canRecover = 0; + } + break; + case CARD_RESULT_NOCARD: + if (canRecover != NULL) + { + *canRecover = -1; + } + ret = -1; + break; + case CARD_RESULT_FATAL_ERROR: + case CARD_RESULT_WRONGDEVICE: + case CARD_RESULT_NOFILE: + break; + } + } + return ret; +} + +static void iSG_cb_unmount(s32 chan, s32 result) +{ + st_ISGSESSION* session = &g_isgdata_MAIN; + if (chan != session->slot) + { + return; + } + session->slot = -1; + if (session->chgfunc != NULL) + { + session->chgfunc(session->cltdata, ISG_CHG_TARGET); + } + memset(&session->mcdata[chan], 0, sizeof(st_ISG_MEMCARD_DATA)); +} + +static S32 iSG_tpl_unpack(st_ISG_TPL_TEXPALETTE* tpl) +{ + if (tpl->magic != 0x20af30) + { + return 0; + } + + tpl->unk_8 = (st_ISG_TPL_TEX*)((U32)tpl + (U32)tpl->unk_8); + for (S32 i = 0; i < tpl->count; ++i) + { + st_ISG_TPL_TEX* x = &tpl->unk_8[i]; + if (x->unk_0 != NULL) + { + x->unk_0 = (st_ISG_TPL_TEX::UnkIn*)((U32)tpl + (U32)x->unk_0); + if (x->unk_0->unk_23 == 0) + { + x->unk_0->unk_8 = (void*)((U32)tpl + (U32)x->unk_0->unk_8); + x->unk_0->unk_23 = 1; + } + } + if (x->unk_4 != NULL) + { + x->unk_4 = (st_ISG_TPL_TEX::UnkOut*)((U32)tpl + (U32)x->unk_4); + if (x->unk_4->unk_2 == 0) + { + x->unk_4->unk_8 = tpl; + x->unk_4->unk_2 = 1; + } + } + } + return 1; +} + +static st_ISG_TPL_TEX* iSG_tpl_TEXGet(st_ISG_TPL_TEXPALETTE* tpl, U32 n) +{ + return &tpl->unk_8[n]; +} + +static char* iSG_bfr_icondata(char* param1, CARDStat* stat, char* param3, int param4) +{ + IconData data = { 0 }; + static st_ISG_TPL_TEXPALETTE* ico_pal; + static st_ISG_TPL_TEX* ico_desc; + static U32 i = 0; + + sprintf(data.footer, "SPONGEBOB:WHENROBOTSATTACK::RyanNeilDan"); + strncpy(data.game_name, "Battle for Bikini Bottom", sizeof(data.game_name)); + data.game_name[0x1f] = NULL; + + if (param3) + { + strncpy(data.buf0, param3, sizeof(data.buf0)); + } + data.buf0[0x1f] = NULL; + + ico_pal = g_rawbanr; + ico_desc = iSG_tpl_TEXGet(ico_pal, 0); + memcpy(data.buf1, ico_desc->unk_0->unk_8, sizeof(data.buf1)); + + ico_pal = g_rawicon; + for (i = 0; i < 8; i++) + { + ico_desc = iSG_tpl_TEXGet(ico_pal, i); + memcpy(data.buf2[i], ico_desc->unk_0->unk_8, sizeof(data.buf2[i])); + } + + memcpy(param1, &data, sizeof(data)); + + S32 t = ALIGN_THING(param4, 0x200); + return param1 + (t + (sizeof(IconData) - 1) & -t); +} + +static S32 iSG_bnr_unpack(st_ISG_TPL_TEXPALETTE* tpl) +{ + return iSG_tpl_unpack(tpl); +} + +static S32 iSG_load_icondata() +{ + g_rawicon = (st_ISG_TPL_TEXPALETTE*)iFileLoad("/SBGCIcon.tpl", NULL, &g_iconsize); + g_rawbanr = (st_ISG_TPL_TEXPALETTE*)iFileLoad("/SBGCBanner.tpl", NULL, &g_banrsize); + iSG_tpl_unpack(g_rawicon); + iSG_bnr_unpack(g_rawbanr); + + return g_rawicon && (S32)g_iconsize && g_rawbanr && (S32)g_banrsize ? 1 : 0; +} + +static S32 iSG_get_finfo(st_ISG_MEMCARD_DATA* mcdata, const char* dpath) +{ + S32 rc = 0; + en_ASYNC_OPERR operr = ISG_OPERR_NONE; + + if (iSG_mc_fopen(mcdata, dpath, -1, ISG_IOMODE_READ, &operr)) + { + rc = 1; + memcpy(&mcdata->unk_b0, &mcdata->fstat, sizeof(CARDStat)); + memcpy(&mcdata->unk_9c, &mcdata->finfo, sizeof(CARDFileInfo)); + iSG_mc_fclose(mcdata); + } + + return rc; +} + +static S32 iSG_cubeicon_size(S32 slot, S32 param2) +{ + if ((U32)slot > 1) + { + return -1; + } + + S32 t = ALIGN_THING(param2, 0x200); + + // FIXME: Macro not quite right + // return ALIGN_THING(t, sizeof(IconData)); + return -t & sizeof(IconData) + t - 1; +} + +static S32 iSG_isSpaceForFile(st_ISG_MEMCARD_DATA* mcdata, S32 param2, const char* param3, + S32* param4, S32* param5, S32* param6) +{ + S32 rc = 0; + S32 result = 0; + s32 byteNotUsed = 0; + s32 filesNotUsed = 0; + S32 len; + + if (mcdata->unk_0 == 0) + { + return 0; + } + len = iSG_cubeicon_size(mcdata->chan, mcdata->sectorSize); + len = len + param2; + len = ALIGN_THING(mcdata->sectorSize, len); + + do + { + result = CARDFreeBlocks(mcdata->chan, &byteNotUsed, &filesNotUsed); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + if (param5) + { + *param5 = byteNotUsed / mcdata->sectorSize; + } + if (param4) + { + *param4 = len / mcdata->sectorSize; + } + } + else + { + return 0; + } + + if (param6) + { + *param6 = 1; + } + + if (iSG_get_finfo(mcdata, param3)) + { + if (param6) + { + *param6 = *param6 - 1 & ~(*param6 - 1 >> 0x1f); // FIXME: Fakematch + } + if (len <= mcdata->unk_b0.length + byteNotUsed) + { + rc = 1; + } + } + else + { + if (len <= byteNotUsed && filesNotUsed > 0) + { + rc = 1; + } + } + + return rc; +} + +static S32 iSG_mc_isGCcard(st_ISG_MEMCARD_DATA* mcdata, int* param2, int* param3) +{ + S32 result = 0; + S32 rc = 0; + + s32 xferBytes = 0; + u16 encoding = 0; + s32 memSize = 0; + s32 sectorSize = 0; + + if (param2) + { + *param2 = 0; + } + + if (param3) + { + *param3 = 0; + } + + if (mcdata->unk_0 == 0) + { + return 0; + } + if (mcdata->unk_12c) + { + return 0; + } + + do + { + result = CARDProbeEx(mcdata->chan, &memSize, §orSize); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + rc = 1; + } + + if (rc != 0) + { + do + { + result = CARDCheckEx(mcdata->chan, &xferBytes); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + rc = 1; + } + else if (result == CARD_RESULT_BROKEN) + { + rc = 2; + } + else + { + if (result == CARD_RESULT_ENCODING) + { + rc = 3; + if (param2) + { + *param2 = 1; + } + } + else + { + rc = 0; + if (result == CARD_RESULT_ENCODING && param2) + { + *param2 = 1; + } + if (result == CARD_RESULT_IOERROR && param3) + { + *param3 = 1; + } + } + } + } + + if (rc == 1) + { + do + { + result = CARDGetEncoding(mcdata->chan, &encoding); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY && encoding && param2) + { + *param2 = 1; + } + } + + return rc; +} + +// Looks equivalent. Can't get variable initializtions to match. +S32 iSG_mcidx2slot(S32 param1, S32* out_slot, S32* param3) +{ + s32 cardReady[ISG_NUM_SLOTS] = {}; + S32 ret = 0; + S32 idk = 0; + s32 memSize = 0; + s32 sectorSize = 0; + *out_slot = -1; + + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + s32 result; + do + { + result = CARDProbeEx(i, &memSize, §orSize); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + cardReady[i] = TRUE; + } + } + + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + if (cardReady[i]) + { + if (idk == param1) + { + *out_slot = i; + ret = 1; + break; + } + idk++; + } + } + + if (param3) + { + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + param3[i] = cardReady[i]; + } + } + + return ret; +} + +static S32 iSG_mc_fread(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len, S32 offset) +{ + return iSG_mcqa_fread(mcdata, buf, len, offset); +} + +S32 iSGReadLeader(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 numbytes, S32 async) +{ + S32 bufsize; + S32 iconsize; + S32 allocsize; + char* readbuf; + + S32 readret = 0; + st_ISG_MEMCARD_DATA* data; + void* alloc = NULL; + + en_ASYNC_OPERR operr = ISG_OPERR_NONE; + if (isgdata->slot < 0) + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + isgdata->unk_268 = ISG_OPERR_NOCARD; + return 0; + } + data = &isgdata->mcdata[isgdata->slot]; + + if (data->unk_12c != 0) + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + isgdata->unk_268 = ISG_OPERR_DAMAGE; + return 0; + } + + iTRCDisk::CheckDVDAndResetState(); + iconsize = iSG_cubeicon_size(data->chan, data->sectorSize); + S32 sectorsize200 = ALIGN_THING(data->sectorSize, 0x200); + if ((S32)databuf % 32 != 0 || numbytes - (numbytes / sectorsize200) * sectorsize200 != 0) + { + S32 tmpsize = (numbytes + 0x1ff & ~0x1ff); + allocsize = tmpsize + 0x1f; + alloc = xMemPushTemp(allocsize); + memset(alloc, 0, allocsize); + bufsize = tmpsize; + readbuf = (char*)((U32)alloc + 0x1f & ~0x1f); + } + else + { + readbuf = databuf; + bufsize = numbytes; + } + + iTRCDisk::CheckDVDAndResetState(); + + if (iSG_mc_fopen(data, fname, -1, ISG_IOMODE_READ, &operr) != 0) + { + readret = (bool)iSG_mc_fread(data, (char*)readbuf, bufsize, iconsize); + iSG_mc_fclose(data); + } + + if (readret != 0 && alloc != NULL) + { + memcpy(databuf, readbuf, numbytes); + } + if (alloc != NULL) + { + xMemPopTemp(alloc); + } + + isgdata->unk_268 = ISG_OPERR_NONE; + if (readret != 0) + { + isgdata->unk_26c = ISG_OPSTAT_SUCCESS; + } + else + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + if (data->unk_12c != 0) + { + isgdata->unk_268 = ISG_OPERR_DAMAGE; + } + else + { + isgdata->unk_268 = ISG_OPERR_OTHER; + } + } + return readret; +} + +static void iSG_upd_icostat(CARDStat*, CARDStat* stat) +{ + CARDSetCommentAddress(stat, 0); + CARDSetBannerFormat(stat, CARD_STAT_BANNER_RGB5A3); + CARDSetIconAddress(stat, 0x40); + CARDSetIconAnim(stat, CARD_STAT_ANIM_LOOP); + + for (S32 i = 0; i < CARD_ICON_MAX; ++i) + { + CARDSetIconFormat(stat, i, CARD_STAT_BANNER_RGB5A3); + CARDSetIconSpeed(stat, i, CARD_STAT_SPEED_MIDDLE); + } +} + +static void iSG_timestamp(CARDStat*) +{ +} + +static S32 iSG_mc_fwrite(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len) +{ + return iSG_mcqa_fwrite(mcdata, buf, len); +} + +S32 iSGSaveFile(st_ISGSESSION* isgdata, const char* fname, char* data, S32 n, S32 async, char* arg5) +// Only 25%, adding cus it may be useful for the actual function +{ + void* alloc; + S32 allocsize; + char* icondata; + S32 iconsize; + + S32 writeret = 0; + en_ASYNC_OPERR operr = ISG_OPERR_NONE; + CARDStat statA = { 0 }; + CARDStat statB = { 0 }; + + ResetButton::DisableReset(); + if (isgdata->slot < 0) + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + isgdata->unk_268 = ISG_OPERR_NOCARD; + return 0; + } + + st_ISG_MEMCARD_DATA* mcdata = &isgdata->mcdata[isgdata->slot]; + if (mcdata->unk_12c != 0) + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + isgdata->unk_268 = ISG_OPERR_DAMAGE; + return 0; + } + + iTRCDisk::CheckDVDAndResetState(); + iconsize = iSG_cubeicon_size(isgdata->slot, mcdata->sectorSize); + S32 sectorsize200 = ALIGN_THING(mcdata->sectorSize, 0x200); + iconsize += ALIGN_THING(sectorsize200, n); + + allocsize = iconsize + 0x1f; + alloc = xMemPushTemp(allocsize); + memset(alloc, 0, allocsize); + icondata = (char*)((U32)alloc + 0x1f & 0xFFFFFFE0); + + memcpy(iSG_bfr_icondata(icondata, &statA, arg5, mcdata->sectorSize), data, n); + iTRCDisk::CheckDVDAndResetState(); + + if (iSG_mc_fopen(mcdata, fname, iconsize, ISG_IOMODE_WRITE, &operr) != 0) + { + if (iSG_mc_fwrite(mcdata, icondata, iconsize) != 0) + { + writeret = 1; + } + else + { + writeret = 0; + operr = ISG_OPERR_SVWRITE; + } + + if (writeret != 0) + { + iSG_upd_icostat(&statA, &mcdata->fstat); + iSG_timestamp(&mcdata->fstat); + s32 result; + do + { + result = CARDSetStatus(mcdata->chan, mcdata->finfo.fileNo, &mcdata->fstat); + } while (result == CARD_RESULT_BUSY); + + if (result != CARD_RESULT_READY) + { + writeret = 0; + } + } + + if (writeret != 0) + { + s32 result; + do + { + result = CARDSetAttributes(mcdata->chan, mcdata->finfo.fileNo, CARD_ATTR_PUBLIC); + } while (result == CARD_RESULT_BUSY); + } + + iSG_mc_fclose(mcdata, &statB); + } + xMemPopTemp(alloc); + + if (writeret == 0 && mcdata->unk_12c == 0) + { + iSG_mc_fdel(mcdata, fname); + } + + ResetButton::EnableReset(); + iTRCDisk::CheckDVDAndResetState(); + + isgdata->unk_268 = ISG_OPERR_NONE; + if (writeret != 0) + { + isgdata->unk_26c = ISG_OPSTAT_SUCCESS; + } + else + { + isgdata->unk_26c = ISG_OPSTAT_FAILURE; + if (operr != ISG_OPERR_NONE) + { + isgdata->unk_268 = operr; + } + else + { + isgdata->unk_268 = ISG_OPERR_UNKNOWN; + } + } + return writeret; +} + +S32 iSGSetupGameDir(st_ISGSESSION* isgdata, const char* dname, S32 force_iconfix) +{ + return 1; +} + +static S32 iSG_mc_isformatted(st_ISG_MEMCARD_DATA* mcdata) +{ + S32 result = 0; + S32 rc = 0; + s32 xferBytes = 0; + + if (mcdata->unk_0 == 0) + { + rc = 0; + } + else if (mcdata->unk_12c) + { + rc = 0; + } + else + { + do + { + result = CARDCheckEx(mcdata->chan, &xferBytes); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + rc = 1; + } + else if (result == CARD_RESULT_BROKEN) + { + rc = 0; + } + else + { + rc = 0; + } + } + + return rc; +} + +S32 iSGSelectGameDir(st_ISGSESSION* isgdata, const char* dname) +{ + if (isgdata->slot < 0) + { + return 0; + } + st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; + + if (data->unk_0 == 0) + { + return 0; + } + + if (iSG_mc_isGCcard(data, NULL, NULL) == 0) + { + return 0; + } + + if (iSG_mc_isformatted(data) == 0) + { + return 0; + } + + S32 count = 0; + for (S32 idx = 0; idx < ISG_NUM_FILES; ++idx) + { + const char* n = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, idx); + if (iSG_get_finfo(data, n) != 0) + { + count++; + } + } + + return count != 0; +} + +void iSGMakeTimeStamp(char* str) +{ + OSCalendarTime calendar_time = { 0 }; + OSTime time = OSGetTime(); + OSTicksToCalendarTime(time, &calendar_time); + sprintf(str, "%02d/%02d/%04d %02d:%02d:%02d", calendar_time.mon + 1, calendar_time.mday, + calendar_time.year, calendar_time.hour, calendar_time.min, calendar_time.sec); +} + +static S32 iSG_get_fmoddate(st_ISG_MEMCARD_DATA* mcdata, const char* fname, int* sec, int* min, + int* hr, int* mon, int* day, int* yr) +{ + S32 rc = 1; + OSCalendarTime time = { 0 }; + + if (iSG_get_finfo(mcdata, fname) == 0) + { + rc = 0; + } + else + { + OSTime t = mcdata->unk_b0.time; + t = OSSecondsToTicks(t); + OSTicksToCalendarTime(t, &time); + + if (sec) + { + *sec = time.sec; + } + if (min) + { + *min = time.min; + } + if (hr) + { + *hr = time.hour; + } + if (mon) + { + *mon = time.mon + 1; + } + if (day) + { + *day = time.mday; + } + if (mon) + { + *mon = time.mon + 1; + } + if (day) + { + *day = time.mday; + } + if (yr) + { + *yr = time.year; + } + } + + return rc; +} + +char* iSGFileModDate(st_ISGSESSION* isgdata, const char* fname, S32* sec, S32* min, S32* hr, + S32* mon, S32* day, S32* yr) +{ + static char datestr[0x40] = { 0 }; + int sec_str = 0; + int min_str = 0; + int hr_str = 0; + int mon_str = 0; + int day_str = 0; + int yr_str = 0; + if (iSG_get_fmoddate(&isgdata->mcdata[isgdata->slot], fname, &sec_str, &min_str, &hr_str, + &mon_str, &day_str, &yr_str) != 0) + { + sprintf(datestr, "%02d/%02d/%04d %02d:%02d:%02d", mon_str, day_str, yr_str, hr_str, min_str, + sec_str); + + if (sec != NULL) + { + *sec = sec_str; + } + if (min != NULL) + { + *min = min_str; + } + if (hr != NULL) + { + *hr = hr_str; + } + if (mon != NULL) + { + *mon = mon_str; + } + if (day != NULL) + { + *day = day_str; + } + if (yr != NULL) + { + *yr = yr_str; + } + } + else + { + sprintf(datestr, ""); + } + return datestr; +} + +char* iSGFileModDate(st_ISGSESSION* isgdata, const char* fname) +{ + return iSGFileModDate(isgdata, fname, NULL, NULL, NULL, NULL, NULL, NULL); +} + +static S32 iSG_get_fsize(st_ISG_MEMCARD_DATA* mcdata, const char* param2) +{ + S32 rc = -1; + + if (iSG_get_finfo(mcdata, param2)) + { + rc = mcdata->unk_b0.length; + } + + if (rc < 0) + { + rc = -1; + } + + return rc; +} + +S32 iSGFileSize(st_ISGSESSION* isgdata, const char* fname) +{ + S32 ret = 0; + if (isgdata->slot < 0) + { + return -1; + } + st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; + iTRCDisk::CheckDVDAndResetState(); + ret = iSG_get_fsize(data, fname); + if (ret >= 0) + { + ret -= iSG_cubeicon_size(data->chan, data->sectorSize); + if (ret < 0) + { + ret = -1; + } + } + return ret; +} + +S32 iSGTgtHaveRoomStartup(st_ISGSESSION* isgdata, S32 tidx, S32 fsize, const char* dpath, + const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile) +{ + st_ISG_MEMCARD_DATA* data; + S32 i; + S32 count; + S32 opened; + S32 is_space; + if (isgdata->slot < 0) + { + return 0; + } + data = &isgdata->mcdata[isgdata->slot]; + if (data->unk_0 == NULL) + { + return 0; + } + count = 0; + if (fname == NULL) + { + for (i = 0; i < ISG_NUM_FILES; ++i) + { + iTRCDisk::CheckDVDAndResetState(); + fname = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, i); + if (iSG_get_finfo(data, fname) != 0) + { + count++; + } + } + } + + is_space = iSG_isSpaceForFile(data, fsize, fname, bytesNeeded, availOnDisk, needFile); + if (count > 0 && *bytesNeeded > *availOnDisk) + { + if (needFile != NULL && *bytesNeeded > *availOnDisk) + { + *needFile = 0; + return 0; + } + return 1; + } + + CARDFileInfo fileInfo; + opened = 0; + for (i = 0; i < CARD_MAX_FILE && isgdata->slot >= 0 && isgdata->slot < ISG_NUM_SLOTS; ++i) + { + if (CARDFastOpen(isgdata->slot, i, &fileInfo) == 0) + { + opened++; + CARDClose(&fileInfo); + } + } + + if (opened >= CARD_MAX_FILE) + { + if (count > 0) + { + if (needFile != NULL) + { + *needFile = 0; + } + return 0; + } + *needFile = -1; + return 0; + } + + if (*bytesNeeded > *availOnDisk) + { + return 0; + } + return (count >= 3) ? 0 : is_space; +} + +S32 iSGTgtHaveRoom(st_ISGSESSION* isgdata, S32 tidx, S32 fsize, const char* dpath, + const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile) +{ + st_ISG_MEMCARD_DATA* data; + S32 i; + S32 count; + S32 opened; + S32 is_space; + if (isgdata->slot < 0) + { + return 0; + } + data = &isgdata->mcdata[isgdata->slot]; + if (data->unk_0 == NULL) + { + return 0; + } + count = 0; + if (fname == NULL) + { + for (i = 0; i < ISG_NUM_FILES; ++i) + { + iTRCDisk::CheckDVDAndResetState(); + fname = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, i); + if (iSG_get_finfo(data, fname) != 0) + { + count++; + } + } + } + + is_space = iSG_isSpaceForFile(data, fsize, fname, bytesNeeded, availOnDisk, needFile); + if (count > 0 && *bytesNeeded > *availOnDisk) + { + if (needFile != NULL && *bytesNeeded > *availOnDisk) + { + *needFile = 0; + return 0; + } + return 1; + } + + CARDFileInfo fileInfo; + opened = 0; + for (i = 0; i < CARD_MAX_FILE && isgdata->slot >= 0 && isgdata->slot < ISG_NUM_SLOTS; ++i) + { + if (CARDFastOpen(isgdata->slot, i, &fileInfo) == 0) + { + opened++; + CARDClose(&fileInfo); + } + } + + if (opened >= CARD_MAX_FILE) + { + if (count > 0) + { + if (needFile != NULL) + { + *needFile = 0; + } + return 1; + } + return 0; + } + + return (*bytesNeeded > *availOnDisk) ? 0 : is_space; +} + +static S32 iSG_mc_exists(S32 slot) +{ + S32 ret = 0; + s32 memSize = 0; + s32 sectorSize = 0; + + if (slot < -1) + { + return 0; + } + + S32 result; + do + { + result = CARDProbeEx(slot, &memSize, §orSize); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + ret = 1; + } + + return ret; +} + +U32 iSGTgtState(st_ISGSESSION* isgdata, S32 tgtidx, const char* dpath) +{ + S32 isSectSizeValid = 0; + S32 state = 0; + + S32 rc = 0; + + S32 slot = 0; + S32 x = 0; + S32 y = 0; + iTRCDisk::CheckDVDAndResetState(); + + iSG_mcidx2slot(tgtidx, &slot, NULL); + if (slot != isgdata->slot) + { + iSGTgtSetActive(isgdata, tgtidx); + } + + if (isgdata->slot < 0) + { + return 0x1000000; + } + + st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; + if (data->unk_0 == NULL) + { + return 0; + } + + if (iSG_mc_exists(isgdata->slot)) + { + state |= 1; + } + else + { + return 0; + } + + if (data->unk_12c != 0) + { + return state | 0x1000000; + } + + rc = iSG_mc_isGCcard(data, &x, &y); + if (x != 0) + { + state |= 0x4000000; + } + + if (y != 0) + { + state |= 0x2000000; + } + + if (rc == 0) + { + return state; + } + + if (g_legalSectSize[0] > 0) + { + for (S32 i = 0; g_legalSectSize[i] > 0; i++) + { + if (data->sectorSize == g_legalSectSize[i]) + { + isSectSizeValid = 1; + break; + } + } + if (isSectSizeValid == 0) + { + state |= 0x8000004; + return state & ~4; + } + } + + if (iSG_mc_isformatted(data) == 0) + { + return state | 4; + } + else + { + return state | 0xe; + } + + return state; +} + +S32 iSGTgtFormat(st_ISGSESSION* isgdata, S32 tgtidx, S32 async, S32* canRecover) +{ + S32 slot = 0; + S32 rc = 0; + iTRCDisk::CheckDVDAndResetState(); + if (iSG_mc_exists(isgdata->slot) == 0) + { + return 0; + } + + iSG_mcidx2slot(tgtidx, &slot, NULL); + // FIXME: r3 and r0 are swapped here for some reason ... + if (slot != isgdata->slot) + { + return 0; + } + + st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; + if (data->unk_0 == NULL) + { + return 0; + } + + if (iSG_mc_isGCcard(data, NULL, NULL) == 0) + { + return 0; + } + + rc = iSG_mc_format(data, 0, canRecover); + if (rc == -1) + { + return -1; + } + return rc == 0 ? 0 : 1; +} + +S32 iSGTgtPhysSlotIdx(st_ISGSESSION* isgdata, S32 tidx) +{ + S32 idx = -1; + if (iSG_mcidx2slot(tidx, &idx, NULL)) + { + return idx; + } + return -1; +} + +S32 iSGTgtCount(st_ISGSESSION* isgdata, S32* max) +{ + s32 memSize = 0; + s32 sectorSize = 0; + S32 ret = 0; + + if (max != NULL) + { + *max = 2; + } + + for (S32 i = 0; i < ISG_NUM_SLOTS; ++i) + { + iTRCDisk::CheckDVDAndResetState(); + s32 result; + do + { + result = CARDProbeEx(i, &memSize, §orSize); + } while (result == CARD_RESULT_BUSY); + if (result == CARD_RESULT_READY) + { + ret++; + } + } + + return ret; +} + +static S32 iSG_mc_unmount(S32 slot) +{ + S32 rc = 0; + S32 result; + + do + { + result = CARDUnmount(slot); + } while (result == CARD_RESULT_BUSY); + + if (result == CARD_RESULT_READY) + { + rc = 1; + } + else if (result == CARD_RESULT_NOCARD) + { + rc = 1; + } + + return rc; +} + +void iSGSessionEnd(st_ISGSESSION* isgdata) +{ + iTRCDisk::CheckDVDAndResetState(); + for (S32 i = 0; i < ISG_NUM_SLOTS; i++) + { + if (isgdata->mcdata[i].unk_0) + { + iSG_mc_unmount(i); + isgdata->mcdata[i].unk_0 = 0; + } + } + + memset(isgdata, 0, sizeof(st_ISGSESSION)); +} + +static S32 iSG_chk_icondata() +{ + return 1; +} + +st_ISGSESSION* iSGSessionBegin(void* cltdata, void (*chgfunc)(void*, en_CHGCODE), S32 monitor) +{ + iTRCDisk::CheckDVDAndResetState(); + memset(&g_isgdata_MAIN, 0, sizeof(st_ISGSESSION)); + + g_isgdata_MAIN.slot = -1; + g_isgdata_MAIN.chgfunc = chgfunc; + g_isgdata_MAIN.cltdata = cltdata; + + iSG_chk_icondata(); + return &g_isgdata_MAIN; +} + +char* iSGMakeName(en_NAMEGEN_TYPE type, const char* base, S32 idx) +{ + static volatile S32 rotate = 0; // fakematch?? + static char rotatebuf[8][32] = { 0 }; + + const char* fmt_sd = "%s%02d"; + char* use_buf = rotatebuf[rotate++]; + if (rotate == 8) + { + rotate = 0; + } + + *use_buf = NULL; + switch (type) + { + case ISG_NGTYP_GAMEFILE: + + if (base != NULL) + { + sprintf(use_buf, fmt_sd, base, idx); + } + else + { + sprintf(use_buf, fmt_sd, "SpongeBob", idx); + } + break; + case ISG_NGTYP_GAMEDIR: + case ISG_NGTYP_CONFIG: + case ISG_NGTYP_ICONTHUM: + break; + } + + return use_buf; +} + +static void iSG_discard_icondata() +{ + OSFreeToHeap(__OSCurrHeap, g_rawicon); + OSFreeToHeap(__OSCurrHeap, g_rawbanr); + g_rawicon = NULL; + g_iconsize = 0; + g_rawbanr = NULL; + g_banrsize = 0; +} + +S32 iSGShutdown() +{ + iSG_discard_icondata(); + return 1; +} + +static S32 iSG_start_your_engines() +{ + CARDInit(); + return 1; +} + +S32 iSGStartup() +{ + if (g_isginit++ != 0) + { + return g_isginit; + } + + iSG_start_your_engines(); + iSG_load_icondata(); + return g_isginit; +} + +// iPar + +void iParMgrRender() +{ +} + +void iParMgrUpdate(float) +{ +} + +// iPad + +PADStatus sPadData[PAD_MAX_CONTROLLERS]; + +void iPadKill() +{ +} + +void iPadStopRumble() +{ + PADControlMotor(mPad[globals.currentActivePad].port, 0); // Scheduling memes. +} + +void iPadStopRumble(_tagxPad* pad) +{ + PADControlMotor(pad->port, 0); +} + +S32 iPadUpdate(_tagxPad* pad, U32* on) +{ + U16 buttons; + U32 temp_on; + + if (pad->port == 0) + { + PADRead(sPadData); + PADClamp(sPadData); + } + + PADStatus* padData = (PADStatus*)&sPadData; + switch (padData[pad->port].err) + { + case PAD_ERR_NO_CONTROLLER: + xTRCPad(pad->port, TRC_PadMissing); + PADReset(0x80000000 >> pad->port); + goto defaultError; + + case PAD_ERR_NOT_READY: + case PAD_ERR_TRANSFER: + return 0; + + default: + defaultError: + return 0; + + case PAD_ERR_NONE: + temp_on = iPadConvFromGCN(padData[pad->port].button, 1, 0x80); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 2, 0x20); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 4, 0x40); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 8, 0x10); + buttons = sPadData[pad->port].button; + + if (buttons & 0x10) + { + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x20, 0x2000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x40, 0x200); + if (sPadData[pad->port].triggerLeft >= 0x18) + { + temp_on |= 0x200; + } + if (sPadData[pad->port].triggerRight >= 0x18) + { + temp_on |= 0x2000; + } + temp_on |= 0x100000; + } + else + { + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x20, 0x1000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x40, 0x100); + if (sPadData[pad->port].triggerLeft >= 0x18) + { + temp_on |= 0x100; + } + if (sPadData[pad->port].triggerRight >= 0x18) + { + temp_on |= 0x1000; + } + } + + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x100, 0x10000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x200, 0x80000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x800, 0x40000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x400, 0x20000); + temp_on |= iPadConvFromGCN(sPadData[pad->port].button, 0x1000, 0x1); + (*on) = temp_on; + + pad->analog1.x = iPadConvStick(sPadData[pad->port].stickX); + pad->analog1.y = -iPadConvStick(sPadData[pad->port].stickY); // Scheduling memes. + pad->analog2.x = iPadConvStick(sPadData[pad->port].substickX); + pad->analog2.y = -iPadConvStick(sPadData[pad->port].substickY); // Same as above. + if (gTrcPad[pad->port].state != TRC_PadInserted) + { + xTRCPad(pad->port, TRC_PadInserted); + } + } + return 1; +} + +_tagxPad* iPadEnable(_tagxPad* pad, S16 port) +{ + pad->port = port; + pad->slot = 0; + pad->state = ePad_Enabled; + gTrcPad[pad->port].state = TRC_PadInserted; + pad->flags |= 3; + pad->flags |= 4; + return pad; +} + +S32 iPadInit() +{ + PADInit(); + return 1; +} + +// iMorph + +// iModel + +// iMemMgr + +extern xMemInfo_tag gMemInfo; +extern OSHeapHandle he; +extern OSHeapHandle hs; +extern unsigned char _stack_addr[]; +extern U32 HeapSize; +extern U32 mem_top_alloc; +extern U32 mem_base_alloc; + +void iMemExit() +{ + free((void*)gMemInfo.DRAM.addr); + gMemInfo.DRAM.addr = 0; +} + +// I dont have a name for these yet + +void iBoxBoundVec(xBox* o, const xBox* b, const xVec3* v) +{ + xVec3Init(&o->lower, MIN(v->x, b->lower.x), MIN(v->y, b->lower.y), MIN(v->z, b->lower.z)); + xVec3Init(&o->upper, MAX(v->x, b->upper.x), MAX(v->y, b->upper.y), MAX(v->z, b->upper.z)); +} + +void iBoxInitBoundVec(xBox* b, const xVec3* v) +{ + xVec3Copy(&b->lower, v); + xVec3Copy(&b->upper, v); +} + +void iBoxIsectVec(const xBox* b, const xVec3* v, xIsect* isx) +{ + if (v->x >= b->lower.x && v->x <= b->upper.x && v->y >= b->lower.y && v->y <= b->upper.y && + v->z >= b->lower.z && v->z <= b->upper.z) + { + isx->penned = -1.0f; + } + else + { + isx->penned = 1.0f; + } +} + +void iBoxVecDist(const xBox* box, const xVec3* v, xIsect* isx) +{ + if (v->x < box->lower.x) + { + if (v->y < box->lower.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x00000000; + isx->flags |= 0x80000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = 0.0f; + isx->flags = isx->flags & ~0x1F000000 | 0x01000000; + isx->flags |= 0x40000000; + } + else + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x02000000; + isx->flags |= 0x80000000; + } + } + else if (v->y <= box->upper.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = 0.0f; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x03000000; + isx->flags |= 0x40000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = 0.0f; + isx->norm.z = 0.0f; + isx->flags = isx->flags & ~0x1F000000 | 0x04000000; + isx->flags |= 0x20000000; + } + else + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = 0.0f; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x05000000; + isx->flags |= 0x40000000; + } + } + else + { + if (v->z < box->lower.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x06000000; + isx->flags |= 0x80000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = 0.0f; + isx->flags = isx->flags & ~0x1F000000 | 0x07000000; + isx->flags |= 0x40000000; + } + else + { + isx->norm.x = box->lower.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x08000000; + isx->flags |= 0x80000000; + } + } + } + else if (v->x <= box->upper.x) + { + if (v->y < box->lower.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = 0.0f; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x09000000; + isx->flags |= 0x40000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = 0.0f; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = 0.0f; + isx->flags = isx->flags & ~0x1F000000 | 0x0A000000; + isx->flags |= 0x20000000; + } + else + { + isx->norm.x = 0.0f; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x0B000000; + isx->flags |= 0x40000000; + } + } + else if (v->y <= box->upper.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = 0.0f; + isx->norm.y = 0.0f; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x0C000000; + isx->flags |= 0x20000000; + } + else if (v->z <= box->upper.z) + { + } + else + { + isx->norm.x = 0.0f; + isx->norm.y = 0.0f; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x0E000000; + isx->flags |= 0x20000000; + } + } + else + { + if (v->z < box->lower.z) + { + isx->norm.x = 0.0f; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x0F000000; + isx->flags |= 0x40000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = 0.0f; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = 0.0f; + isx->flags = isx->flags & ~0x1F000000 | 0x10000000; + isx->flags |= 0x20000000; + } + else + { + isx->norm.x = 0.0f; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x11000000; + isx->flags |= 0x40000000; + } + } + } + else + { + if (v->y < box->lower.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x12000000; + isx->flags |= 0x80000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = 0.0f; + isx->flags = isx->flags & ~0x1F000000 | 0x13000000; + isx->flags |= 0x40000000; + } + else + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->lower.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x14000000; + isx->flags |= 0x80000000; + } + } + else if (v->y <= box->upper.y) + { + if (v->z < box->lower.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = 0.0f; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x15000000; + isx->flags |= 0x40000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = 0.0f; + isx->norm.z = 0.0f; + isx->flags = isx->flags & ~0x1F000000 | 0x16000000; + isx->flags |= 0x20000000; + } + else + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = 0.0f; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x17000000; + isx->flags |= 0x40000000; + } + } + else + { + if (v->z < box->lower.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->lower.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x18000000; + isx->flags |= 0x80000000; + } + else if (v->z <= box->upper.z) + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = 0.0f; + isx->flags = isx->flags & ~0x1F000000 | 0x19000000; + isx->flags |= 0x40000000; + } + else + { + isx->norm.x = box->upper.x - v->x; + isx->norm.y = box->upper.y - v->y; + isx->norm.z = box->upper.z - v->z; + isx->flags = isx->flags & ~0x1F000000 | 0x1A000000; + isx->flags |= 0x80000000; + } + } + } + + isx->dist = xVec3Length(&isx->norm); +} + +void iSphereBoundVec(xSphere* o, const xSphere* s, const xVec3* v) +{ + F32 scale; + xSphere temp; + xSphere* tp; + U32 usetemp; + xIsect isx; + + usetemp = (o == s); + + iSphereIsectVec(s, v, &isx); + + if (isx.penned <= 0.0f) + { + if (!usetemp) + { + memcpy(o, s, sizeof(xSphere)); + } + } + else + { + if (usetemp) + { + tp = &temp; + } + else + { + tp = o; + } + + xVec3Copy(&tp->center, &isx.norm); + + scale = (isx.dist - s->r) / (2.0f * isx.dist); + + xVec3SMul(&tp->center, &tp->center, scale); + xVec3Add(&tp->center, &tp->center, &s->center); + + tp->r = 0.5f * (isx.dist + s->r); + + if (usetemp) + { + memcpy(o, tp, sizeof(xSphere)); + } + } +} + +void iSphereInitBoundVec(xSphere* s, const xVec3* v) +{ + xVec3Copy(&s->center, v); + + s->r = 0.00001f; +} + +void iMath3Init() +{ +} + +// Sin, Cos, Tan + +F32 itan(F32 x) +{ + return std::tanf(x); +} + +F32 icos(F32 x) +{ + return std::cosf(x); +} + +F32 isin(F32 x) +{ + return std::sinf(x); +} + +// iLight + +void iLightEnv(iLight* light, S32 env) +{ + RwUInt32 flags = 0; + + switch (env) + { + case ILIGHT_ENV_NONE: + flags = 0; + break; + case ILIGHT_ENV_ATOMIC: + flags = rpLIGHTLIGHTWORLD; + break; + case ILIGHT_ENV_WORLD: + flags = rpLIGHTLIGHTATOMICS; + break; + case ILIGHT_ENV_ATOMICWORLD: + flags = rpLIGHTLIGHTATOMICS | rpLIGHTLIGHTWORLD; + break; + } + + RpLightSetFlags(light->hw, flags); +} + +void iLightDestroy(iLight* light) +{ + RwFrame* frame; + + light->type = ILIGHT_TYPE_NONE; + + _rwFrameSyncDirty(); + + frame = RpLightGetFrame(light->hw); + + if (frame) + { + RwFrameDestroy(frame); + } + + RpLightDestroy(light->hw); +} + +void iLightSetPos(iLight* light, xVec3* pos) +{ + RwFrame* f = RpLightGetFrame(light->hw); + RwMatrix* m = RwFrameGetMatrix(f); + + RwMatrixGetPos(m)->x = pos->x; + RwMatrixGetPos(m)->y = pos->y; + RwMatrixGetPos(m)->z = pos->z; + + RwMatrixUpdate(m); + + RwFrameUpdateObjects(f); +} + +void iLightSetColor(iLight* light, _xFColor* col) +{ + RpLightSetColor(light->hw, (RwRGBAReal*)col); +} + +void iLightModify(iLight* light, U32 flags) // Remove xVec ops +{ + if (flags & 0x5) + { + RwFrame* frame = RpLightGetFrame(light->hw); + RwMatrix temp; + + *(xVec3*)RwMatrixGetRight(&temp) = g_O3; + *(xVec3*)RwMatrixGetUp(&temp) = g_O3; + *(xVec3*)RwMatrixGetAt(&temp) = light->dir; + *(xVec3*)RwMatrixGetPos(&temp) = light->sph.center; + + RwFrameTransform(frame, &temp, rwCOMBINEREPLACE); + } + + if (flags & 0x2) + { + RpLightSetRadius(light->hw, light->sph.r); + } + + if (flags & 0x8) + { + RpLightSetColor(light->hw, (RwRGBAReal*)&light->color); + } + + if (flags & 0x10) + { + if (light->type == ILIGHT_TYPE_SPOT || light->type == ILIGHT_TYPE_SPOTSOFT) + { + RpLightSetConeAngle(light->hw, light->coneangle); + } + } +} + +iLight* iLightCreate(iLight* light, U32 type) +{ + RwFrame* frame; + + switch (type) + { + case ILIGHT_TYPE_POINT: + light->hw = RpLightCreate(rpLIGHTPOINT); + break; + case ILIGHT_TYPE_SPOT: + light->hw = RpLightCreate(rpLIGHTSPOT); + break; + case ILIGHT_TYPE_SPOTSOFT: + light->hw = RpLightCreate(rpLIGHTSPOTSOFT); + break; + default: + return NULL; + } + + if (!light->hw) + { + return NULL; + } + + frame = RwFrameCreate(); + + if (!frame) + { + RpLightDestroy(light->hw); + return NULL; + } + + RpLightSetFlags(light->hw, rpLIGHTLIGHTATOMICS); + RpLightSetFrame(light->hw, frame); + + RwFrameUpdateObjects(frame); + + light->type = type; + light->sph.center.x = 0.0f; + light->sph.center.y = 0.0f; + light->sph.center.z = 0.0f; + light->sph.r = 0.0f; + light->color.r = 1.0f; + light->color.g = 1.0f; + light->color.b = 1.0f; + light->color.a = 1.0f; + light->dir.x = 0.0f; + light->dir.y = 0.0f; + light->dir.z = 1.0f; + light->coneangle = 0.0f; + + return light; +} + +void iLightInit(RpWorld* world) +{ + gLightWorld = world; +} + +// Don't know what to call this + +// iFxUVCreatepipe +//_iGCURenderCallback + +// iFMV + +// FIXME: These should be in a RW header somewhere +extern GXRenderModeObj* _RwDlRenderMode; +extern "C" { +void RwGameCubeGetXFBs(void*, void*); +} + +//.bss +static U32 Bink_surface_type[5]; + +//.sbss +static S32 frame_num; +U32 fuckingSurfaceType; //??? +static HBINK Bink; +static HRAD3DIMAGE Image; +static S32 Paused; +static void* pixels; +static volatile F32 vol; +S32 ip; +s32 oof; +void* iFMV::mXFBs[2]; +void* iFMV::mCurrentFrameBuffer; +GXRenderModeObj* iFMV::mRenderMode; + +// .sdata +static float Width_scale = 1.0f; +static float Height_scale = 1.0f; +U8 iFMV::mFirstFrame = 1; + +static void* arammalloc(size_t size) +{ + return (void*)ARAlloc(size); +} + +// Something weird is going on here... +static void aramfree(void* mem) +{ + u32 vol; + ARFree(&vol); +} + +static void DrawFrame(float arg0, float arg1, float arg2, float arg3) +{ + GXRenderModeObj* rm = _RwDlRenderMode; + Mtx idt; + Mtx44 mtx; + + GXSetViewport(0.0f, 0.0f, rm->fbWidth, rm->efbHeight, 0.0f, 1.0f); + GXSetScissor(0, 0, rm->fbWidth, rm->efbHeight); + GXSetDispCopySrc(0, 0, rm->fbWidth, rm->efbHeight); + GXSetDispCopyDst(rm->fbWidth, rm->xfbHeight); + GXSetDispCopyYScale((float)rm->xfbHeight / rm->efbHeight); + GXSetCopyFilter(rm->aa, rm->sample_pattern, GX_TRUE, rm->vfilter); + + if (rm->aa) + { + GXSetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); + } + else + { + GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + } + + GXSetDispCopyGamma(GX_GM_1_0); + C_MTXOrtho(mtx, 0.0f, 480.0f, 0.0f, 640.0f, 0.0f, 10000.0f); + GXSetProjection(mtx, GX_ORTHOGRAPHIC); + PSMTXIdentity(idt); + GXLoadPosMtxImm(idt, 0); + + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_NRM_NBT, GX_S16, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_NRM_NBT, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_NRM_NBT, GX_RGBA6, 0); + + GXSetNumTexGens(1); + GXSetNumChans(1); + GXSetNumTevStages(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); + GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + + if (rm->field_rendering) + { + u32 field = VIGetNextField(); + GXSetViewportJitter(0.0f, 0.0f, rm->fbWidth, rm->efbHeight, 0.0f, 1.0f, field); + } + else + { + GXSetViewport(0.0f, 0.0f, rm->fbWidth, rm->efbHeight, 0.0f, 1.0f); + } + + GXInvalidateVtxCache(); + GXInvalidateTexAll(); + Blit_RAD_3D_image(Image, arg0, arg1, arg2, arg3, 1.0f); +} + +static void xDrawLine2D_LocaliFMVVersion(F32 arg0, F32 arg1, F32 arg2, F32 arg3) +{ + RwRGBA color = { -1, -1, -1, -1 }; + + F32 nearz = RwIm2DGetNearScreenZ(); + void* texraster_state; + RwRenderStateGet(rwRENDERSTATETEXTURERASTER, &texraster_state); + void* vtx_alpha_state; + RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vtx_alpha_state); + RwIm2DVertex verts[2]; + + // RwIm2DVertexSetRealRGBA + + RwIm2DVertexSetScreenX(&verts[0], arg0); + RwIm2DVertexSetScreenY(&verts[0], arg1); + RwIm2DVertexSetScreenZ(&verts[0], nearz); + RwIm2DVertexSetIntRGBA(&verts[0], color.red, color.green, color.blue, color.alpha); + + RwIm2DVertexSetScreenX(&verts[1], arg2); + RwIm2DVertexSetScreenY(&verts[1], arg3); + RwIm2DVertexSetScreenZ(&verts[1], nearz); + RwIm2DVertexSetIntRGBA(&verts[1], color.red, color.green, color.blue, color.alpha); + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, NULL); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, NULL); + + // { arg2, arg3, nearz, -1 }; + RwIm2DRenderLine(verts, 2, 0, 1); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, texraster_state); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, vtx_alpha_state); +} + +static void Show_frame() +{ + RwRGBA color = { 0 }; + RwCamera* cam = iCameraCreate(640, 480, FALSE); + RwCameraClear(cam, &color, rwCAMERACLEARIMAGE); + + RwCameraBeginUpdate(cam); + Width_scale = 640 / Bink->unk_0; + Height_scale = 480 / Bink->unk_4; + xDrawLine2D_LocaliFMVVersion(0.0f, 0.0f, 0.0f, 0.0f); + DrawFrame(0.0f, 0.0f, Width_scale, Height_scale); + RwCameraEndUpdate(cam); + RwCameraShowRaster(cam, NULL, 0); + + iCameraDestroy(cam); +} + +static void PlayFMV(char* fname, u32 buttons, F32 time) +{ + GXCullMode cull_mode; + GXGetCullMode(&cull_mode); + iFMV::InitDisplay(_RwDlRenderMode); + iPadStopRumble(globals.pad0); + RADSetAudioMemory(arammalloc, aramfree); + RADSetMemory(iFMVmalloc, iFMVfree); + Setup_surface_array(); + + for (char* c = fname; *c != NULL; c++) + { + if (*c == '\\') + { + *c = '/'; + } + } + + tag_xFile file; + DVDFileInfo* pfinfo = &file.ps.fileInfo; + do + { + if (iTRCDisk::IsDiskIDed()) + { + Bink = BinkOpen(fname, NULL); + if (Bink == NULL) + { + BinkGetError(); + } + } + if (iTRCDisk::CheckDVDAndResetState() != 0) + { + break; + } + if (Bink == NULL) + { + iFileOpen(fname, 0, &file); + DVDSeekAsyncPrio(pfinfo, 0, NULL, 2); + if (iTRCDisk::CheckDVDAndResetState()) + { + DVDCancel(&pfinfo->cb); + break; + } + else + { + DVDCancel(&pfinfo->cb); + } + } + } while (Bink == NULL); + + if (Bink != NULL) + { + if (Bink->unk_f0 != 0) + { + for (ip = 0; ip <= Bink->unk_f0; ++ip) + { + vol = gSnd.categoryVolFader[SND_CAT_CUTSCENE]; + vol = vol * vol; + vol = vol * 32768.0f; + BinkSetVolume(Bink, ip, vol); + } + } + + Image = Open_RAD_3D_image(NULL, Bink->unk_0, Bink->unk_4, fuckingSurfaceType); + if (Image != NULL) + { + if (frame_num != 0) + { + BinkGoto(Bink, frame_num, 0); + } + oof = 0; + + do + { + if (iTRCDisk::CheckDVDAndResetState()) + { + goto superbreak; + } + if (BinkWait(Bink) == 0) + { + Decompress_frame(Bink, Image, 1); + Show_frame(); + BinkNextFrame(Bink); + } + else if (Paused) + { + Show_frame(); + } + xPadUpdate(globals.currentActivePad, 0.0f); + + F32 t = (float)Bink->unk_c / (Bink->unk_14 / Bink->unk_18); + if (buttons && t >= time && globals.pad0->pressed & buttons) + { + frame_num = -1; + goto superbreak; + } + } while (Bink->unk_c < Bink->unk_8 - 1); + frame_num = -1; + } + superbreak: + if (frame_num != -1) + { + frame_num = Bink->unk_c; + } + Close_RAD_3D_image(Image); + Image = NULL; + BinkClose(Bink); + Bink = NULL; + } + + GXSetCullMode(cull_mode); + iVSync(); + xPadUpdate(globals.currentActivePad, 0.0f); +} + +U32 iFMVPlay(char* filename, U32 buttons, F32 time, bool skippable, bool lockController) +{ + if (filename == NULL) + { + return 1; + } + + frame_num = 0; + while (frame_num >= 0) + { + PlayFMV(filename, buttons, time); + } + return 0; +} + +void _MovieFree(void* mem) +{ + RwFree(mem); +} + +void* _MovieAlloc(U32 size) +{ + return RwMalloc(size); +} + +// iFile + +struct file_queue_entry +{ + tag_xFile* file; + void* buf; + U32 size; + U32 offset; + IFILE_READSECTOR_STATUS stat; + void (*callback)(tag_xFile* file); + U32 asynckey; +}; + +extern file_queue_entry file_queue[4]; + +static U32 tbuffer[1024 + 8]; +static U32* buffer32; +volatile U32 iFileSyncAsyncReadActive; + +void iFileGetInfo(tag_xFile* file, U32* addr, U32* length) +{ + if (addr) + { + *addr = file->ps.fileInfo.startAddr; + } + + if (length) + { + *length = file->ps.fileInfo.length; + } +} + +U32 iFileFind(const char* name, S32 x, tag_xFile* file) +{ + return iFileOpen(name, 0, file); +} + +void iFileSetPath(const char* path) +{ +} + +U32 iFileGetSize(tag_xFile* file) +{ + return file->ps.fileInfo.length; +} + +U32 iFileClose(tag_xFile* file) +{ + tag_iFile* ps = &file->ps; + S32 ret; + + ret = DVDClose(&file->ps.fileInfo); + ret = DVDClose(&file->ps.fileInfo); + + if (!ret) + { + return 1; + } + + ps->flags = 0; + return 0; +} + +static void async_cb(s32 result, DVDFileInfo* fileInfo) +{ + file_queue_entry* entry = &file_queue[(S32)fileInfo->cb.userData]; + s32 r7 = DVD_RESULT_FATAL_ERROR; + + switch (result) + { + case DVD_RESULT_FATAL_ERROR: + { + xTRCDisk(TRC_DiskFatal); + return; + } + case DVD_RESULT_GOOD: + case DVD_RESULT_IGNORED: + { + if (result >= DVD_RESULT_GOOD) + { + r7 = result; + } + + break; + } + } + + if (r7 < DVD_RESULT_GOOD) + { + entry->stat = IFILE_RDSTAT_FAIL; + + if (entry->callback) + { + entry->callback(entry->file); + } + } + else if (r7 + entry->offset >= entry->size || + r7 + entry->offset + entry->file->ps.offset >= entry->file->ps.fileInfo.length) + { + entry->stat = IFILE_RDSTAT_DONE; + entry->offset = entry->size; + + if (entry->callback) + { + entry->callback(entry->file); + } + + entry->file->ps.asynckey = -1; + } + else + { + entry->offset += r7; + entry->stat = IFILE_RDSTAT_INPROG; + + s32 length; + if ((entry->size - entry->offset < 0x8000)) + { + length = ALIGN(entry->size - entry->offset, 4); + } + else + { + length = 0x10000 - 0x8000; + } + + if (length + entry->offset + entry->file->ps.offset > entry->file->ps.fileInfo.length) + { + // length = OSRoundUp32B(entry->file->ps.fileInfo.length - entry->file->ps.offset - + // entry->offset); + length = entry->file->ps.fileInfo.length; + length -= entry->file->ps.offset; + length -= entry->offset; + length = length + 32 - 1; + length = length & ~(32 - 1); + } + + void* addr = (void*)((U32)entry->buf + entry->offset); + DVDReadAsync(&entry->file->ps.fileInfo, addr, length, + entry->file->ps.offset + entry->offset, async_cb); + } +} + +S32 iFileReadAsync(tag_xFile* file, void* buf, U32 aSize, void (*callback)(tag_xFile*), + S32 priority) +{ + static S32 fopcount = 1; + tag_iFile* ps = &file->ps; + S32 i; + + for (i = 0; i < 4; i++) + { + if (file_queue[i].stat != IFILE_RDSTAT_QUEUED && file_queue[i].stat != IFILE_RDSTAT_INPROG) + { + S32 id = fopcount++ << 2; + S32 asynckey = id + i; + + file_queue[i].file = file; + file_queue[i].buf = buf; + file_queue[i].size = aSize; + file_queue[i].offset = 0; + file_queue[i].stat = IFILE_RDSTAT_QUEUED; + file_queue[i].callback = callback; + file_queue[i].asynckey = asynckey; + + aSize = (aSize < 32) ? ALIGN(aSize, 4) : 32; + + ps->fileInfo.cb.userData = (void*)i; + + DVDReadAsync(&ps->fileInfo, buf, aSize, ps->offset, async_cb); + + ps->asynckey = asynckey; + + return id + i; + } + } + + return -1; +} + +IFILE_READSECTOR_STATUS iFileReadAsyncStatus(S32 key, S32* amtToFar) +{ + if (key != file_queue[key & 0x3].asynckey) + { + return IFILE_RDSTAT_EXPIRED; + } + + if (amtToFar) + { + *amtToFar = file_queue[key & 0x3].offset; + } + + return file_queue[key & 0x3].stat; +} + +static void ifilereadCB(tag_xFile* file) +{ + iFileSyncAsyncReadActive = 0; +} + +U32 iFileRead(tag_xFile* file, void* buf, U32 size) +{ + tag_iFile* ps = &file->ps; + + iFileSeek(file, ps->offset, IFILE_SEEK_SET); + + iFileSyncAsyncReadActive = 1; + + iFileReadAsync(file, buf, size, ifilereadCB, 0); + + while (iFileSyncAsyncReadActive) + { + iTRCDisk::CheckDVDAndResetState(); + } + + return size; +} + +U32 iFileOpen(const char* name, S32 flags, tag_xFile* file) +{ + tag_iFile* ps = &file->ps; + + if (flags & IFILE_OPEN_ABSPATH) + { + strcpy(ps->path, name); + } + else + { + iFileFullPath(name, ps->path); + } + + ps->entrynum = DVDConvertPathToEntrynum(ps->path); + + if (ps->entrynum == -1) + { + return 1; + } + + if (!DVDFastOpen(ps->entrynum, &ps->fileInfo)) + { + ps->entrynum = -1; + return 1; + } + + ps->unkC4 = 0; + ps->flags = 0x1; + + iFileSeek(file, 0, IFILE_SEEK_SET); + + return 0; +} + +U32* iFileLoad(const char* name, U32* buffer, U32* size) +{ + char path[128]; + tag_xFile file; + S32 fileSize, alignedSize; + + iFileFullPath(name, path); + iFileOpen(name, IFILE_OPEN_ABSPATH, &file); + + fileSize = iFileGetSize(&file); + + if (!buffer) + { + buffer = (U32*)OSAlloc(OSRoundUp32B(fileSize)); + } + + alignedSize = OSRoundUp32B(fileSize); + + iFileRead(&file, buffer, alignedSize); + + if (size) + { + *size = alignedSize; + } + + iFileClose(&file); + + return buffer; +} + +// iEnv + +static S32 sBeginDrawFX; +static RpWorld* sPipeWorld; +static RwCamera* sPipeCamera; +static iEnv* lastEnv; + +// This is named JspPS2_ClumpRender on PS2 +static void Jsp_ClumpRender(RpClump* clump, xJSPNodeInfo* nodeInfo) +{ + S32 backcullon = 1; + S32 zbufferon = 1; + RwLLLink* cur = rwLinkListGetFirstLLLink(&clump->atomicList); + RwLLLink* end = rwLinkListGetTerminator(&clump->atomicList); + + while (cur != end) + { + RpAtomic* apAtom = rwLLLinkGetData(cur, RpAtomic, inClumpLink); + + if (RpAtomicGetFlags(apAtom) & rpATOMICRENDER) + { + RwFrame* frame = RpAtomicGetFrame(apAtom); + + if (!iModelCull(apAtom, &frame->ltm)) + { + if (backcullon) + { + if (nodeInfo->nodeFlags & 0x4) + { + backcullon = 0; + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE); + } + } + else + { + if (!(nodeInfo->nodeFlags & 0x4)) + { + backcullon = 1; + RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLBACK); + } + } + + if (zbufferon) + { + if (nodeInfo->nodeFlags & 0x2) + { + zbufferon = 0; + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); + } + } + else + { + if (!(nodeInfo->nodeFlags & 0x2)) + { + zbufferon = 1; + RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); + } + } + + RpAtomicRender(apAtom); + } + } + + cur = rwLLLinkGetNext(cur); + nodeInfo++; + } +} + +void iEnvEndRenderFX(iEnv*) +{ + iEnv* env = lastEnv; + + if (env->fx && globalCamera && sBeginDrawFX) + { + RpWorldRemoveCamera(env->fx, globalCamera); + RpWorldAddCamera(env->world, globalCamera); + + sBeginDrawFX = 0; + } +} + +void iEnvRender(iEnv* env, bool) +{ + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); + + if (env->jsp) + { + Jsp_ClumpRender(env->jsp->clump, env->jsp->jspNodeList); + } + else + { + RpWorldRender(env->world); + } + + lastEnv = env; +} + +void iEnvLightingBasics(iEnv*, xEnvAsset*) +{ +} + +void iEnvDefaultLighting(iEnv*) +{ +} + +void iEnvFree(iEnv* env) +{ + _rwFrameSyncDirty(); + + RpWorldDestroy(env->world); + env->world = NULL; + + if (env->fx) + { + RpWorldDestroy(env->fx); + env->fx = NULL; + } + + if (env->collision) + { + RpWorldDestroy(env->collision); + env->collision = NULL; + } +} + +static RpAtomic* SetPipelineCB(RpAtomic* atomic, void* data) +{ + if (RwCameraBeginUpdate(sPipeCamera)) + { + RpAtomicInstance(atomic); + RwCameraEndUpdate(sPipeCamera); + } + + if (data) + { + RpAtomicSetPipeline(atomic, (RxPipeline*)data); + } + + return atomic; +} + +// iXF / iDraw + +void iDrawEnd() +{ + return; +} + +void iDrawBegin() +{ + return; +} + +void iDrawSetFBMSK(U32 abgr) +{ + size_t tmp, hi; + + hi = abgr >> 24; + + if (hi == 0) + { + GXSetAlphaUpdate(GX_TRUE); + } + else if (hi == 255) + { + GXSetAlphaUpdate(GX_FALSE); + } + + tmp = abgr & 0x00FFFFFF; + + if (tmp == 0) + { + GXSetColorUpdate(GX_TRUE); + } + else + { + GXSetColorUpdate(GX_FALSE); + } +} + +// iCS + +U32 read_sizzze = 0; + +S32 iCSLoadStep(xCutscene* csn) +{ + S32 bytes; + XFILE_READSECTOR_STATUS cdstat; + U32 skipAccum; + U32 tmpSize; + void* foundModel; + U32 i; + + if (csn->Waiting) + { + cdstat = xFileReadAsyncStatus(csn->File.ps.asynckey, &bytes); + + if (cdstat == XFILE_RDSTAT_INPROG || cdstat == XFILE_RDSTAT_QUEUED) + { + return 0; + } + } + + if (csn->DataLoading >= 0) + { + skipAccum = 0; + + while (csn->DataLoading < (S32)csn->Info->NumData) + { + if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_6) + { + foundModel = NULL; + } + else + { + foundModel = xSTFindAsset(csn->Data[csn->DataLoading].AssetID, &tmpSize); + } + + if (foundModel || csn->Data[csn->DataLoading].ChunkSize == 0) + { + csn->Data[csn->DataLoading].DataPtr = foundModel; + + skipAccum += ALIGN(csn->Data[csn->DataLoading].ChunkSize, 2048); + + csn->DataLoading++; + } + else + { + if (skipAccum) + { + iCSFileAsyncSkip(csn, skipAccum); + + skipAccum = 0; + } + + if (csn->GotData) + { + if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_6) + { + csn->Data[csn->DataLoading].DataPtr = + RwMalloc(csn->Data[csn->DataLoading].ChunkSize); + + memcpy(csn->Data[csn->DataLoading].DataPtr, csn->AlignBuf, + csn->Data[csn->DataLoading].ChunkSize); + } + else + { + csn->Data[csn->DataLoading].DataPtr = + iModelFileNew(csn->AlignBuf, csn->Data[csn->DataLoading].ChunkSize); + } + + csn->Data[csn->DataLoading].DataType |= 0x80000000; + csn->DataLoading++; + csn->GotData = 0; + } + else + { + iCSFileAsyncRead(csn, csn->AlignBuf, + ALIGN(csn->Data[csn->DataLoading].ChunkSize, 2048)); + + csn->GotData = 1; + return 0; + } + } + } + + if (skipAccum) + { + iCSFileAsyncSkip(csn, skipAccum); + } + + csn->DataLoading = -1; + } + + if (csn->DataLoading == -1) + { + if (csn->GotData) + { + iCSSoundSetup(csn); + + if (csn->SndNumChannel != 0) + { + xSndPauseAll(1, 1); + xSndUpdate(); + + if (csn->SndNumChannel == 2) + { + // Stereo + + csn->SndHandle[0] = xSndPlay(csn->SndAssetID[0], 0.9f, -99999.0f, 255, 0x200, 0, + SND_CAT_CUTSCENE, 0.0f); + csn->SndHandle[1] = xSndPlay(csn->SndAssetID[1], 0.9f, -99999.0f, 255, 0x200, 0, + SND_CAT_CUTSCENE, 0.0f); + } + else + { + // Mono + + csn->SndHandle[0] = xSndPlay(csn->SndAssetID[0], 0.9f, -99999.0f, 255, 0x200, 0, + SND_CAT_CUTSCENE, 0.0f); + csn->SndHandle[1] = 0; + } + } + + csn->GotData = 0; + csn->DataLoading = -2; + } + else + { + iCSFileAsyncRead(csn, csn->Play, csn->TimeChunkOffs[1] - csn->TimeChunkOffs[0]); + + csn->GotData = 1; + return 0; + } + } + + if (csn->DataLoading == -2) + { + if (csn->Info->NumTime > 1) + { + iCSFileAsyncRead(csn, csn->Stream, csn->TimeChunkOffs[2] - csn->TimeChunkOffs[1]); + } + + csn->DataLoading = -3; + } + + for (i = 0; i < csn->SndNumChannel; i++) + { + } + + csn->Ready = 1; + return 1; +} + +void iCSFileClose(xCutscene* csn) +{ + iFileReadStop(); + + csn->Opened = 0; +} + +static void iCSAsyncReadCB(tag_xFile* file) +{ + S32 bytes; + xCutscene* csn; + + if (file) + { + if (iFileReadAsyncStatus(file->ps.asynckey, &bytes) == IFILE_RDSTAT_DONE) + { + iFileSeek(file, bytes, IFILE_SEEK_CUR); + } + + csn = xCutscene_CurrentCutscene(); + csn->Waiting = 0; + } +} + +void iCSFileAsyncRead(xCutscene* csn, void* dest, U32 size) +{ + U32* buf = (U32*)dest; + U32 i; + + read_sizzze = size; + csn->Waiting = 1; + + for (i = 0; i < size / 4; i++) + { + buf[i] = 0xDEADBEEF; + } + + iFileReadAsync(&csn->File, dest, size, iCSAsyncReadCB, 0); +} + +void* iCSSoundGetData(xSndVoiceInfo* vp, U32* size) +{ + U32 channelIndex; + U32 dataIndex; + xCutscene* csn; + void* retdata; + xCutsceneData* data; + U32 numChannel; + U32 numData; + S32 sndChannelIndex; + U32 r4; + U32 sndChannelReq; + + csn = xCutscene_CurrentCutscene(); + + numChannel = csn->SndNumChannel; + retdata = NULL; + sndChannelIndex = -1; + + for (channelIndex = 0; channelIndex < numChannel; channelIndex++) + { + if (csn->SndAssetID[channelIndex] == vp->assetID) + { + sndChannelIndex = channelIndex; + sndChannelReq = csn->SndChannelReq[channelIndex]; + } + } + + if (sndChannelIndex == -1) + { + return NULL; + } + + if (!csn->Waiting && csn->Stream->ChunkIndex == sndChannelReq) + { + numData = csn->Stream->NumData; + data = (xCutsceneData*)(csn->Stream + 1); + } + else + { + numData = csn->Play->NumData; + data = (xCutsceneData*)(csn->Play + 1); + + if (csn->SndChannelReq[sndChannelIndex] != csn->Play->ChunkIndex) + { + csn->SndChannelReq[sndChannelIndex] = csn->Play->ChunkIndex; + } + } + + r4 = 0; + + for (dataIndex = 0; dataIndex < numData; dataIndex++) + { + if (data->DataType == XCUTSCENEDATA_TYPE_SOUND) + { + if (!retdata) + { + retdata = (void*)(data + 1); + *size = data->ChunkSize; + } + + if (sndChannelIndex == r4) + { + retdata = (void*)(data + 1); + *size = data->ChunkSize; + + break; + } + else + { + r4++; + } + } + + data = (xCutsceneData*)((U8*)data + ALIGN(data->ChunkSize, 16) + sizeof(xCutsceneData)); + } + + if (!retdata) + { + return NULL; + } + + while ((U32)retdata & 0x1F) + { + retdata = (void*)((U8*)retdata + 16); + *size -= 16; + } + + csn->SndChannelReq[sndChannelIndex]++; + + return retdata; +} + +void iCSSoundSetup(xCutscene* csn) +{ + xCutsceneData* data; + U32 dataIndex; + U32 numData; + + data = (xCutsceneData*)(csn->Play + 1); + numData = csn->Play->NumData; + + for (dataIndex = 0; dataIndex < numData; dataIndex++) + { + if (data->DataType == XCUTSCENEDATA_TYPE_SOUND) + { + if (csn->SndNumChannel >= 2) + { + break; + } + + csn->SndAssetID[csn->SndNumChannel] = data->AssetID; + csn->SndNumChannel++; + } + + data = (xCutsceneData*)((U8*)data + ALIGN(data->ChunkSize, 16) + sizeof(xCutsceneData)); + } +} + +// iAsync + +// Easy file, will work on soon + +// iAnimSKB + +void iAnimEvalSKB(iAnimSKBHeader* data, F32 time, U32 flags, xVec3* tran, xQuat* quat) +{ + U32 i, tidx, bcount, tcount; + iAnimSKBKey* keys; + F32* times; + U16* offsets; + S32 asdf; // unused + F32 scalex, scaley, scalez; + + tcount = data->TimeCount; + bcount = data->BoneCount; + + keys = (iAnimSKBKey*)(data + 1); + times = (F32*)(keys + data->KeyCount); + offsets = (U16*)(times + tcount); + + if (time < 0.0f) + { + time = 0.0f; + } + + if (time > times[tcount - 1]) + { + time = times[tcount - 1]; + } + + tidx = (tcount - 1) % 4; + + while (times[tidx] < time) + { + tidx += 4; + } + + while (tidx && time <= times[tidx]) + { + tidx--; + } + + offsets += tidx * bcount; + + if (flags & 0x1) + { + bcount = 1; + } + + if (flags & 0x2) + { + bcount--; + offsets++; + } + + if (tcount == 1) + { + // non-matching: float constants are loaded outside of loop + + scalex = data->Scale[0]; + scaley = data->Scale[1]; + scalez = data->Scale[2]; + + for (i = 0; i < bcount; i++, quat++, tran++) + { + iAnimSKBKey* k = &keys[i]; + + quat->v.x = k->Quat[0] * (1.0f / SHRT_MAX); + quat->v.y = k->Quat[1] * (1.0f / SHRT_MAX); + quat->v.z = k->Quat[2] * (1.0f / SHRT_MAX); + quat->s = k->Quat[3] * (1.0f / SHRT_MAX); + + tran->x = k->Tran[0] * scalex; + tran->y = k->Tran[1] * scaley; + tran->z = k->Tran[2] * scalez; + } + } + else + { + // non-matching: float constants are loaded outside of loop + + scalex = data->Scale[0]; + scaley = data->Scale[1]; + scalez = data->Scale[2]; + + for (i = 0; i < bcount; i++, quat++, tran++) + { + // no idea if this part even functionally matches. + // come back to this when not lazy + + RtQuatSlerpCache qcache; + RtQuat q1, q2; + RwReal time1, time2, lerp; + iAnimSKBKey* k = &keys[*offsets]; + U32 costheta, theta; // unused + + offsets++; + + time1 = time - times[k->TimeIndex]; + time2 = times[k[1].TimeIndex] - times[k[0].TimeIndex]; + lerp = time1 / time2; + + q1.imag.x = k[0].Quat[0] * (1.0f / SHRT_MAX); + q1.imag.y = k[0].Quat[1] * (1.0f / SHRT_MAX); + q1.imag.z = k[0].Quat[2] * (1.0f / SHRT_MAX); + q1.real = k[0].Quat[3] * (1.0f / SHRT_MAX); + + q2.imag.x = k[1].Quat[0] * (1.0f / SHRT_MAX); + q2.imag.y = k[1].Quat[1] * (1.0f / SHRT_MAX); + q2.imag.z = k[1].Quat[2] * (1.0f / SHRT_MAX); + q2.real = k[1].Quat[3] * (1.0f / SHRT_MAX); + + RtQuatSetupSlerpCache(&q1, &q2, &qcache); + RtQuatSlerp((RtQuat*)quat, &q1, &q2, lerp, &qcache); + + tran->x = + lerp * (scalex * k[1].Tran[0] - scalex * k[0].Tran[0]) + scalex * k[0].Tran[0]; + tran->y = + lerp * (scaley * k[1].Tran[1] - scaley * k[0].Tran[1]) + scaley * k[1].Tran[1]; + tran->z = + lerp * (scalez * k[1].Tran[2] - scalez * k[0].Tran[2]) + scalez * k[1].Tran[2]; + } + } +} + +// iAnimBlend + +// non-matching: incorrect instruction order and regalloc +void iAnimBlend(F32 BlendFactor, F32 BlendRecip, U16* BlendTimeOffset, F32* BoneTable, + U32 BoneCount, xVec3* Tran1, xQuat* Quat1, xVec3* Tran2, xQuat* Quat2, + xVec3* TranDest, xQuat* QuatDest) +{ + U32 i; + U32 invert = 0; + RtQuat* q2; + RtQuat ident = { 0.0f, 0.0f, 0.0f, 1.0f }; + xVec3* t2; + + if (!Quat2) + { + q2 = &ident; + invert = 1; + t2 = (xVec3*)&ident.imag; + } + else + { + q2 = (RtQuat*)Quat2; + t2 = Tran2; + } + + if (BlendFactor < 0.0f) + { + BlendFactor = -BlendFactor; + invert ^= 1; + } + + if (!BoneTable && !BlendTimeOffset) + { + F32 lerp = BlendFactor * BlendRecip; + + if (lerp < 0.0f) + { + lerp = 0.0f; + } + else if (lerp > 1.0f) + { + lerp = 1.0f; + } + + if (invert) + { + lerp = 1.0f - lerp; + } + + if (Quat1) + { + // non-matching: 0.0f constant is loaded outside of loop + + for (i = 0; i < BoneCount; i++) + { + RtQuatSlerpCache qcache; + + RtQuatSetupSlerpCache((RtQuat*)Quat1, q2, &qcache); + RtQuatSlerp((RtQuat*)QuatDest, (RtQuat*)Quat1, q2, lerp, &qcache); + + Quat1++; + + if (Quat2) + { + q2++; + } + + QuatDest++; + } + } + + if (Tran1) + { + if (Quat2) + { + for (i = 0; i < BoneCount; i++, TranDest++, t2++, Tran1++) + { + TranDest->x = lerp * (t2->x - Tran1->x) + Tran1->x; + TranDest->y = lerp * (t2->y - Tran1->y) + Tran1->y; + TranDest->z = lerp * (t2->z - Tran1->z) + Tran1->z; + } + } + else + { + for (i = 0; i < BoneCount; i++, TranDest++, Tran1++) + { + TranDest->x = lerp * (t2->x - Tran1->x) + Tran1->x; + TranDest->y = lerp * (t2->y - Tran1->y) + Tran1->y; + TranDest->z = lerp * (t2->z - Tran1->z) + Tran1->z; + } + } + } + } + else + { + F32 baselerp; + + if (!BlendTimeOffset) + { + baselerp = BlendFactor * BlendRecip; + + if (baselerp < 0.0f) + { + baselerp = 0.0f; + } + else if (baselerp > 1.0f) + { + baselerp = 1.0f; + } + + if (invert) + { + baselerp = 1.0f - baselerp; + } + } + + for (i = 0; i < BoneCount; i++) + { + F32 lerp; + + if (BlendTimeOffset) + { + baselerp = -(1 / 1024.0f * BlendTimeOffset[i * 2] - BlendFactor); + + if (BlendTimeOffset[i * 2 + 1] != 0) + { + baselerp *= 1 / 1024.0f * BlendTimeOffset[i * 2 + 1]; + + if (baselerp < 0.0f) + { + baselerp = 0.0f; + } + else if (baselerp > 1.0f) + { + baselerp = 1.0f; + } + } + else + { + if (baselerp < 0.0f) + { + baselerp = 0.0f; + } + else + { + baselerp = 1.0f; + } + } + + if (invert) + { + baselerp = 1.0f - baselerp; + } + } + + if (BoneTable) + { + lerp = baselerp * BoneTable[i]; + } + else + { + lerp = baselerp; + } + + if (Quat1) + { + RtQuatSlerpCache qcache; + + RtQuatSetupSlerpCache((RtQuat*)Quat1, q2, &qcache); + RtQuatSlerp((RtQuat*)QuatDest, (RtQuat*)Quat1, q2, lerp, &qcache); + + Quat1++; + + if (Quat2) + { + q2++; + } + + QuatDest++; + } + + if (Tran1) + { + TranDest->x = lerp * (t2->x - Tran1->x) + Tran1->x; + TranDest->y = lerp * (t2->y - Tran1->y) + Tran1->y; + TranDest->z = lerp * (t2->z - Tran1->z) + Tran1->z; + + Tran1++; + + if (Quat2) + { + t2++; + } + + TranDest++; + } + } + } +} + +U32 iAnimBoneCount(void* RawData) +{ + if (*(U32*)RawData == '1BKS') + { + return ((iAnimSKBHeader*)RawData)->BoneCount; + } + + return 0; +} + +F32 iAnimDuration(void* RawData) +{ + return iAnimDurationSKB((iAnimSKBHeader*)RawData); +} + +void iAnimEval(void* RawData, F32 time, U32 flags, xVec3* tran, xQuat* quat) +{ + iAnimEvalSKB((iAnimSKBHeader*)RawData, time, flags, tran, quat); +} + +void iAnimInit() +{ + return; +} diff --git a/src/SB/Core/gc/iWad.h b/src/SB/Core/gc/iWad.h new file mode 100644 index 0000000..ddcc2fe --- /dev/null +++ b/src/SB/Core/gc/iWad.h @@ -0,0 +1,45 @@ +#ifndef IWAD_H +#define IWAD_H + +#include "../src/sb/game/zGlobals.h" + +#include "iAnim.h" +#include "iAnimSKB.h" +#include "iCollide.h" +#include "iCollideFast.h" +#include "iColor.h" +#include "iCutscene.h" +#include "iDraw.h" +#include "iEnv.h" +#include "iFile.h" +#include "iFMV.h" +#include "iFX.h" +#include "iLight.h" +#include "iMath.h" +#include "iMath3.h" +#include "iMemMgr.h" +#include "iMix.h" +#include "iModel.h" +#include "iMorph.h" +#include "iPad.h" +#include "iParMgr.h" +#include "isavegame.h" +#include "iScrFX.h" +#include "iSnd.h" +#include "iSystem.h" +#include "iTime.h" +#include "iTRC.h" +#include "ngcrad3d.h" +#include "xDebug.h" +#include "xPad.h" +#include "xTRC.h" +#include "stdlib.h" +#include "../include/dolphin/dvd.h" +#include "xstransvc.h" +#include +#include +#include + +void iFuncProfileFuncs(int, int, float); + +#endif diff --git a/src/SB/Core/gc/isavegame.cpp b/src/SB/Core/gc/isavegame.cpp deleted file mode 100644 index cfdab72..0000000 --- a/src/SB/Core/gc/isavegame.cpp +++ /dev/null @@ -1,2048 +0,0 @@ -#include "isavegame.h" - -#include "zGlobals.h" - -#include "xMemMgr.h" -#include "xSnd.h" - -#include "iFile.h" -#include "iSystem.h" -#include "iTRC.h" - -#include -#include -#include -#include - -// Not 100% on what this does or if it's correctly defined for all cases. Seems to be used for allocation alignment -#define ALIGN_THING(x, n) (n + x - 1 & -x) - -// name is a total guess for now -struct st_ISG_TPL_TEX -{ - struct UnkIn - { - U32 unk_0; - U32 unk_4; - void* unk_8; - U32 unk_c; - U32 unk_10[4]; - U8 unk_20; - U8 unk_21; - U8 unk_22; - U8 unk_23; - }; - struct UnkOut - { - U8 unk_0; - U8 unk_1; - U8 unk_2; - U8 unk_3; - U32 unk_4; - void* unk_8; - }; - - UnkIn* unk_0; - UnkOut* unk_4; -}; -// WIP. Looks like some sort of header for a file with embedded texture information. -struct st_ISG_TPL_TEXPALETTE -{ - U32 magic; - U32 count; - st_ISG_TPL_TEX* unk_8; -}; - -// .bss -static char cardwork[2][0xa000]; - -// .sbss -static volatile S32 g_isginit; -static st_ISG_TPL_TEXPALETTE* g_rawicon; -static st_ISG_TPL_TEXPALETTE* g_rawbanr; -static U32 g_iconsize; -static U32 g_banrsize; -static U8 isMounted; - -// .data -static st_ISGSESSION g_isgdata_MAIN = { 0 }; -static S32 g_legalSectSize[] = { 0x2000, 0, -1 }; - -static S32 iSG_start_your_engines(); -static S32 iSG_chk_icondata(); -static S32 iSG_load_icondata(); -static void iSG_discard_icondata(); -static S32 iSG_mc_unmount(S32 slot); - -S32 iSGStartup() -{ - if (g_isginit++ != 0) - { - return g_isginit; - } - - iSG_start_your_engines(); - iSG_load_icondata(); - return g_isginit; -} - -S32 iSGShutdown() -{ - iSG_discard_icondata(); - return 1; -} - -char* iSGMakeName(en_NAMEGEN_TYPE type, const char* base, S32 idx) -{ - static volatile S32 rotate = 0; // fakematch?? - static char rotatebuf[8][32] = { 0 }; - - const char* fmt_sd = "%s%02d"; - char* use_buf = rotatebuf[rotate++]; - if (rotate == 8) - { - rotate = 0; - } - - *use_buf = NULL; - switch (type) - { - case ISG_NGTYP_GAMEFILE: - - if (base != NULL) - { - sprintf(use_buf, fmt_sd, base, idx); - } - else - { - sprintf(use_buf, fmt_sd, "SpongeBob", idx); - } - break; - case ISG_NGTYP_GAMEDIR: - case ISG_NGTYP_CONFIG: - case ISG_NGTYP_ICONTHUM: - break; - } - - return use_buf; -} - -static const char* __deadstripped() -{ - return "Slot %c\0" - "Memory Card Slot %c\0" - "Nintendo GameCube Memory Card in Slot %c\0" - "Nintendo GameCube%s Memory Card in Slot %c\0" - "^\0" - "Nintendo GameCube%s Memory Card\0" - "is damaged and cannot be used\0" - "unsupprted sector size\0" - "is formatted for another market\0" - "encountered unexpected error (%d)"; -} - -st_ISGSESSION* iSGSessionBegin(void* cltdata, void (*chgfunc)(void*, en_CHGCODE), S32 monitor) -{ - iTRCDisk::CheckDVDAndResetState(); - memset(&g_isgdata_MAIN, 0, sizeof(st_ISGSESSION)); - - g_isgdata_MAIN.slot = -1; - g_isgdata_MAIN.chgfunc = chgfunc; - g_isgdata_MAIN.cltdata = cltdata; - - iSG_chk_icondata(); - return &g_isgdata_MAIN; -} - -void iSGSessionEnd(st_ISGSESSION* isgdata) -{ - iTRCDisk::CheckDVDAndResetState(); - for (S32 i = 0; i < ISG_NUM_SLOTS; i++) - { - if (isgdata->mcdata[i].unk_0) - { - iSG_mc_unmount(i); - isgdata->mcdata[i].unk_0 = 0; - } - } - - memset(isgdata, 0, sizeof(st_ISGSESSION)); -} - -S32 iSGTgtCount(st_ISGSESSION* isgdata, S32* max) -{ - s32 memSize = 0; - s32 sectorSize = 0; - S32 ret = 0; - - if (max != NULL) - { - *max = 2; - } - - for (S32 i = 0; i < ISG_NUM_SLOTS; ++i) - { - iTRCDisk::CheckDVDAndResetState(); - s32 result; - do - { - result = CARDProbeEx(i, &memSize, §orSize); - } while (result == CARD_RESULT_BUSY); - if (result == CARD_RESULT_READY) - { - ret++; - } - } - - return ret; -} - -S32 iSGTgtPhysSlotIdx(st_ISGSESSION* isgdata, S32 tidx) -{ - S32 idx = -1; - if (iSG_mcidx2slot(tidx, &idx, NULL)) - { - return idx; - } - return -1; -} - -static S32 iSG_mc_exists(S32 slot); -static S32 iSG_mc_isGCcard(st_ISG_MEMCARD_DATA* mcdata, int* param2, int* param3); -static S32 iSG_mc_format(st_ISG_MEMCARD_DATA*, S32, S32* canRecover); -S32 iSGTgtFormat(st_ISGSESSION* isgdata, S32 tgtidx, S32 async, S32* canRecover) -{ - S32 slot = 0; - S32 rc = 0; - iTRCDisk::CheckDVDAndResetState(); - if (iSG_mc_exists(isgdata->slot) == 0) - { - return 0; - } - - iSG_mcidx2slot(tgtidx, &slot, NULL); - // FIXME: r3 and r0 are swapped here for some reason ... - if (slot != isgdata->slot) - { - return 0; - } - - st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; - if (data->unk_0 == NULL) - { - return 0; - } - - if (iSG_mc_isGCcard(data, NULL, NULL) == 0) - { - return 0; - } - - rc = iSG_mc_format(data, 0, canRecover); - if (rc == -1) - { - return -1; - } - return rc == 0 ? 0 : 1; -} - -static S32 iSG_mc_isformatted(st_ISG_MEMCARD_DATA* mcdata); -U32 iSGTgtState(st_ISGSESSION* isgdata, S32 tgtidx, const char* dpath) -{ - S32 isSectSizeValid = 0; - S32 state = 0; - - S32 rc = 0; - - S32 slot = 0; - S32 x = 0; - S32 y = 0; - iTRCDisk::CheckDVDAndResetState(); - - iSG_mcidx2slot(tgtidx, &slot, NULL); - if (slot != isgdata->slot) - { - iSGTgtSetActive(isgdata, tgtidx); - } - - if (isgdata->slot < 0) - { - return 0x1000000; - } - - st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; - if (data->unk_0 == NULL) - { - return 0; - } - - if (iSG_mc_exists(isgdata->slot)) - { - state |= 1; - } - else - { - return 0; - } - - if (data->unk_12c != 0) - { - return state | 0x1000000; - } - - rc = iSG_mc_isGCcard(data, &x, &y); - if (x != 0) - { - state |= 0x4000000; - } - - if (y != 0) - { - state |= 0x2000000; - } - - if (rc == 0) - { - return state; - } - - if (g_legalSectSize[0] > 0) - { - for (S32 i = 0; g_legalSectSize[i] > 0; i++) - { - if (data->sectorSize == g_legalSectSize[i]) - { - isSectSizeValid = 1; - break; - } - } - if (isSectSizeValid == 0) - { - state |= 0x8000004; - return state & ~4; - } - } - - if (iSG_mc_isformatted(data) == 0) - { - return state | 4; - } - else - { - return state | 0xe; - } - - return state; -} - -static S32 iSG_mc_settgt(st_ISG_MEMCARD_DATA* mcdata, S32 slot); -S32 iSGTgtSetActive(st_ISGSESSION* isgdata, S32 tgtidx) -{ - S32 ret = 0; - S32 slot = 0; - iSG_mcidx2slot(tgtidx, &slot, NULL); - st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[slot]; - iTRCDisk::CheckDVDAndResetState(); - if (data->unk_0) - { - ret = 1; - } - else - { - if (iSG_mc_settgt(data, slot) != 0) - { - ret = 1; - isgdata->slot = slot; - } - } - return ret; -} - -static S32 iSG_get_finfo(st_ISG_MEMCARD_DATA* mcdata, const char* dpath); -static S32 iSG_isSpaceForFile(st_ISG_MEMCARD_DATA* mcdata, S32 param2, const char* param3, - S32* param4, S32* param5, S32* param6); -S32 iSGTgtHaveRoom(st_ISGSESSION* isgdata, S32 tidx, S32 fsize, const char* dpath, - const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile) -{ - st_ISG_MEMCARD_DATA* data; - S32 i; - S32 count; - S32 opened; - S32 is_space; - if (isgdata->slot < 0) - { - return 0; - } - data = &isgdata->mcdata[isgdata->slot]; - if (data->unk_0 == NULL) - { - return 0; - } - count = 0; - if (fname == NULL) - { - for (i = 0; i < ISG_NUM_FILES; ++i) - { - iTRCDisk::CheckDVDAndResetState(); - fname = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, i); - if (iSG_get_finfo(data, fname) != 0) - { - count++; - } - } - } - - is_space = iSG_isSpaceForFile(data, fsize, fname, bytesNeeded, availOnDisk, needFile); - if (count > 0 && *bytesNeeded > *availOnDisk) - { - if (needFile != NULL && *bytesNeeded > *availOnDisk) - { - *needFile = 0; - return 0; - } - return 1; - } - - CARDFileInfo fileInfo; - opened = 0; - for (i = 0; i < CARD_MAX_FILE && isgdata->slot >= 0 && isgdata->slot < ISG_NUM_SLOTS; ++i) - { - if (CARDFastOpen(isgdata->slot, i, &fileInfo) == 0) - { - opened++; - CARDClose(&fileInfo); - } - } - - if (opened >= CARD_MAX_FILE) - { - if (count > 0) - { - if (needFile != NULL) - { - *needFile = 0; - } - return 1; - } - return 0; - } - - return (*bytesNeeded > *availOnDisk) ? 0 : is_space; -} - -S32 iSGTgtHaveRoomStartup(st_ISGSESSION* isgdata, S32 tidx, S32 fsize, const char* dpath, - const char* fname, S32* bytesNeeded, S32* availOnDisk, S32* needFile) -{ - st_ISG_MEMCARD_DATA* data; - S32 i; - S32 count; - S32 opened; - S32 is_space; - if (isgdata->slot < 0) - { - return 0; - } - data = &isgdata->mcdata[isgdata->slot]; - if (data->unk_0 == NULL) - { - return 0; - } - count = 0; - if (fname == NULL) - { - for (i = 0; i < ISG_NUM_FILES; ++i) - { - iTRCDisk::CheckDVDAndResetState(); - fname = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, i); - if (iSG_get_finfo(data, fname) != 0) - { - count++; - } - } - } - - is_space = iSG_isSpaceForFile(data, fsize, fname, bytesNeeded, availOnDisk, needFile); - if (count > 0 && *bytesNeeded > *availOnDisk) - { - if (needFile != NULL && *bytesNeeded > *availOnDisk) - { - *needFile = 0; - return 0; - } - return 1; - } - - CARDFileInfo fileInfo; - opened = 0; - for (i = 0; i < CARD_MAX_FILE && isgdata->slot >= 0 && isgdata->slot < ISG_NUM_SLOTS; ++i) - { - if (CARDFastOpen(isgdata->slot, i, &fileInfo) == 0) - { - opened++; - CARDClose(&fileInfo); - } - } - - if (opened >= CARD_MAX_FILE) - { - if (count > 0) - { - if (needFile != NULL) - { - *needFile = 0; - } - return 0; - } - *needFile = -1; - return 0; - } - - if (*bytesNeeded > *availOnDisk) - { - return 0; - } - return (count >= 3) ? 0 : is_space; -} - -static S32 iSG_get_fsize(st_ISG_MEMCARD_DATA* mcdata, const char* param2); -static S32 iSG_cubeicon_size(S32 slot, S32 param2); -S32 iSGFileSize(st_ISGSESSION* isgdata, const char* fname) -{ - S32 ret = 0; - if (isgdata->slot < 0) - { - return -1; - } - st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; - iTRCDisk::CheckDVDAndResetState(); - ret = iSG_get_fsize(data, fname); - if (ret >= 0) - { - ret -= iSG_cubeicon_size(data->chan, data->sectorSize); - if (ret < 0) - { - ret = -1; - } - } - return ret; -} - -char* iSGFileModDate(st_ISGSESSION* isgdata, const char* fname) -{ - return iSGFileModDate(isgdata, fname, NULL, NULL, NULL, NULL, NULL, NULL); -} - -static S32 iSG_get_fmoddate(st_ISG_MEMCARD_DATA* mcdata, const char* fname, int* sec, int* min, - int* hr, int* mon, int* day, int* yr); -char* iSGFileModDate(st_ISGSESSION* isgdata, const char* fname, S32* sec, S32* min, S32* hr, - S32* mon, S32* day, S32* yr) -{ - static char datestr[0x40] = { 0 }; - int sec_str = 0; - int min_str = 0; - int hr_str = 0; - int mon_str = 0; - int day_str = 0; - int yr_str = 0; - if (iSG_get_fmoddate(&isgdata->mcdata[isgdata->slot], fname, &sec_str, &min_str, &hr_str, - &mon_str, &day_str, &yr_str) != 0) - { - sprintf(datestr, "%02d/%02d/%04d %02d:%02d:%02d", mon_str, day_str, yr_str, hr_str, min_str, - sec_str); - - if (sec != NULL) - { - *sec = sec_str; - } - if (min != NULL) - { - *min = min_str; - } - if (hr != NULL) - { - *hr = hr_str; - } - if (mon != NULL) - { - *mon = mon_str; - } - if (day != NULL) - { - *day = day_str; - } - if (yr != NULL) - { - *yr = yr_str; - } - } - else - { - sprintf(datestr, ""); - } - return datestr; -} - -void iSGMakeTimeStamp(char* str) -{ - OSCalendarTime calendar_time = { 0 }; - OSTime time = OSGetTime(); - OSTicksToCalendarTime(time, &calendar_time); - sprintf(str, "%02d/%02d/%04d %02d:%02d:%02d", calendar_time.mon + 1, calendar_time.mday, - calendar_time.year, calendar_time.hour, calendar_time.min, calendar_time.sec); -} - -S32 iSGSelectGameDir(st_ISGSESSION* isgdata, const char* dname) -{ - if (isgdata->slot < 0) - { - return 0; - } - st_ISG_MEMCARD_DATA* data = &isgdata->mcdata[isgdata->slot]; - - if (data->unk_0 == 0) - { - return 0; - } - - if (iSG_mc_isGCcard(data, NULL, NULL) == 0) - { - return 0; - } - - if (iSG_mc_isformatted(data) == 0) - { - return 0; - } - - S32 count = 0; - for (S32 idx = 0; idx < ISG_NUM_FILES; ++idx) - { - const char* n = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, idx); - if (iSG_get_finfo(data, n) != 0) - { - count++; - } - } - - return count != 0; -} - -S32 iSGSetupGameDir(st_ISGSESSION* isgdata, const char* dname, S32 force_iconfix) -{ - return 1; -} - -static char* iSG_bfr_icondata(char* param1, CARDStat* stat, char* param3, int param4); -static S32 iSG_mc_fopen(st_ISG_MEMCARD_DATA*, const char*, S32, en_ISG_IOMODE, en_ASYNC_OPERR*); -static S32 iSG_mc_fclose(st_ISG_MEMCARD_DATA*); -static S32 iSG_mc_fclose(st_ISG_MEMCARD_DATA*, CARDStat*); -static S32 iSG_mc_fdel(st_ISG_MEMCARD_DATA* mcdata, const char* fname); -static S32 iSG_mc_fwrite(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 bufsize); -static void iSG_upd_icostat(CARDStat*, CARDStat*); -static void iSG_timestamp(CARDStat*); -S32 iSGSaveFile(st_ISGSESSION* isgdata, const char* fname, char* data, S32 n, S32 async, char* arg5) -{ - void* alloc; - S32 allocsize; - char* icondata; - S32 iconsize; - - S32 writeret = 0; - en_ASYNC_OPERR operr = ISG_OPERR_NONE; - CARDStat statA = { 0 }; - CARDStat statB = { 0 }; - - ResetButton::DisableReset(); - if (isgdata->slot < 0) - { - isgdata->unk_26c = ISG_OPSTAT_FAILURE; - isgdata->unk_268 = ISG_OPERR_NOCARD; - return 0; - } - - st_ISG_MEMCARD_DATA* mcdata = &isgdata->mcdata[isgdata->slot]; - if (mcdata->unk_12c != 0) - { - isgdata->unk_26c = ISG_OPSTAT_FAILURE; - isgdata->unk_268 = ISG_OPERR_DAMAGE; - return 0; - } - - iTRCDisk::CheckDVDAndResetState(); - iconsize = iSG_cubeicon_size(isgdata->slot, mcdata->sectorSize); - S32 sectorsize200 = ALIGN_THING(mcdata->sectorSize, 0x200); - iconsize += ALIGN_THING(sectorsize200, n); - - allocsize = iconsize + 0x1f; - alloc = xMemPushTemp(allocsize); - memset(alloc, 0, allocsize); - icondata = (char*)((U32)alloc + 0x1f & 0xFFFFFFE0); - - memcpy(iSG_bfr_icondata(icondata, &statA, arg5, mcdata->sectorSize), data, n); - iTRCDisk::CheckDVDAndResetState(); - - if (iSG_mc_fopen(mcdata, fname, iconsize, ISG_IOMODE_WRITE, &operr) != 0) - { - if (iSG_mc_fwrite(mcdata, icondata, iconsize) != 0) - { - writeret = 1; - } - else - { - writeret = 0; - operr = ISG_OPERR_SVWRITE; - } - - if (writeret != 0) - { - iSG_upd_icostat(&statA, &mcdata->fstat); - iSG_timestamp(&mcdata->fstat); - s32 result; - do - { - result = CARDSetStatus(mcdata->chan, mcdata->finfo.fileNo, &mcdata->fstat); - } while (result == CARD_RESULT_BUSY); - - if (result != CARD_RESULT_READY) - { - writeret = 0; - } - } - - if (writeret != 0) - { - s32 result; - do - { - result = CARDSetAttributes(mcdata->chan, mcdata->finfo.fileNo, CARD_ATTR_PUBLIC); - } while (result == CARD_RESULT_BUSY); - } - - iSG_mc_fclose(mcdata, &statB); - } - xMemPopTemp(alloc); - - if (writeret == 0 && mcdata->unk_12c == 0) - { - iSG_mc_fdel(mcdata, fname); - } - - ResetButton::EnableReset(); - iTRCDisk::CheckDVDAndResetState(); - - isgdata->unk_268 = ISG_OPERR_NONE; - if (writeret != 0) - { - isgdata->unk_26c = ISG_OPSTAT_SUCCESS; - } - else - { - isgdata->unk_26c = ISG_OPSTAT_FAILURE; - if (operr != ISG_OPERR_NONE) - { - isgdata->unk_268 = operr; - } - else - { - isgdata->unk_268 = ISG_OPERR_UNKNOWN; - } - } - return writeret; -} - -S32 iSGLoadFile(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 async) -{ - S32 numBytes = iSGFileSize(isgdata, fname); - return iSGReadLeader(isgdata, fname, databuf, numBytes, async); -} - -static S32 iSG_mc_fread(st_ISG_MEMCARD_DATA* mcdata, char*, S32, S32); -S32 iSGReadLeader(st_ISGSESSION* isgdata, const char* fname, char* databuf, S32 numbytes, S32 async) -{ - S32 bufsize; - S32 iconsize; - S32 allocsize; - char* readbuf; - - S32 readret = 0; - st_ISG_MEMCARD_DATA* data; - void* alloc = NULL; - - en_ASYNC_OPERR operr = ISG_OPERR_NONE; - if (isgdata->slot < 0) - { - isgdata->unk_26c = ISG_OPSTAT_FAILURE; - isgdata->unk_268 = ISG_OPERR_NOCARD; - return 0; - } - data = &isgdata->mcdata[isgdata->slot]; - - if (data->unk_12c != 0) - { - isgdata->unk_26c = ISG_OPSTAT_FAILURE; - isgdata->unk_268 = ISG_OPERR_DAMAGE; - return 0; - } - - iTRCDisk::CheckDVDAndResetState(); - iconsize = iSG_cubeicon_size(data->chan, data->sectorSize); - S32 sectorsize200 = ALIGN_THING(data->sectorSize, 0x200); - if ((S32)databuf % 32 != 0 || numbytes - (numbytes / sectorsize200) * sectorsize200 != 0) - { - S32 tmpsize = (numbytes + 0x1ff & ~0x1ff); - allocsize = tmpsize + 0x1f; - alloc = xMemPushTemp(allocsize); - memset(alloc, 0, allocsize); - bufsize = tmpsize; - readbuf = (char*)((U32)alloc + 0x1f & ~0x1f); - } - else - { - readbuf = databuf; - bufsize = numbytes; - } - - iTRCDisk::CheckDVDAndResetState(); - - if (iSG_mc_fopen(data, fname, -1, ISG_IOMODE_READ, &operr) != 0) - { - readret = (bool)iSG_mc_fread(data, (char*)readbuf, bufsize, iconsize); - iSG_mc_fclose(data); - } - - if (readret != 0 && alloc != NULL) - { - memcpy(databuf, readbuf, numbytes); - } - if (alloc != NULL) - { - xMemPopTemp(alloc); - } - - isgdata->unk_268 = ISG_OPERR_NONE; - if (readret != 0) - { - isgdata->unk_26c = ISG_OPSTAT_SUCCESS; - } - else - { - isgdata->unk_26c = ISG_OPSTAT_FAILURE; - if (data->unk_12c != 0) - { - isgdata->unk_268 = ISG_OPERR_DAMAGE; - } - else - { - isgdata->unk_268 = ISG_OPERR_OTHER; - } - } - return readret; -} - -en_ASYNC_OPSTAT iSGPollStatus(st_ISGSESSION* isgdata, en_ASYNC_OPCODE* curop, S32 block) -{ - return isgdata->unk_26c; -} - -en_ASYNC_OPERR iSGOpError(st_ISGSESSION* isgdata, char* errmsg) -{ - static char* errmsgs[0x16] = { - "No current error", - "No operation in async queue", - "Too many async ops queued simultaneously", - "Init Failed", - "Unable to access Save Game Directory", - "Access Error - no card ?!? (eg yanked out)", - "Access Error - no room on card (file handles free bytes, etc)", - "Access Error - card is damaged or something bad", - "Access Error - file being loaded appears to be corrupt (I-Level)", - "Access Error - general problem", - "Save Error - Not enough free space to save file", - "Save Error - during initalization (async queue)", - "Save Error - during write", - "Save Error - opening file", - "Load Error - during initalization (async queue)", - "Load Error - during read", - "Load Error - opening file", - "Target problem (general error)", - "Target Error - media removed or changed", - "Target Error - Not ready for I/O (unformatted?)", - "Operation encountered unknown error", - NULL - }; - - en_ASYNC_OPERR err; - if (errmsg == NULL) - { - return isgdata->unk_268; - } - - if (isgdata->unk_268 < ISG_OPERR_NOMORE) - { - strncpy(errmsg, errmsgs[isgdata->unk_268], 0x80); - } - else - { - strncpy(errmsg, errmsgs[ISG_OPERR_UNKNOWN], 0x80); - } - errmsg[0x7f] = NULL; - return isgdata->unk_268; -} - -static S32 iSG_start_your_engines() -{ - CARDInit(); - return 1; -} - -// Looks equivalent. Can't get variable initializtions to match. -S32 iSG_mcidx2slot(S32 param1, S32* out_slot, S32* param3) -{ - s32 cardReady[ISG_NUM_SLOTS] = {}; - S32 ret = 0; - S32 idk = 0; - s32 memSize = 0; - s32 sectorSize = 0; - *out_slot = -1; - - for (S32 i = 0; i < ISG_NUM_SLOTS; i++) - { - s32 result; - do - { - result = CARDProbeEx(i, &memSize, §orSize); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - cardReady[i] = TRUE; - } - } - - for (S32 i = 0; i < ISG_NUM_SLOTS; i++) - { - if (cardReady[i]) - { - if (idk == param1) - { - *out_slot = i; - ret = 1; - break; - } - idk++; - } - } - - if (param3) - { - for (S32 i = 0; i < ISG_NUM_SLOTS; i++) - { - param3[i] = cardReady[i]; - } - } - - return ret; -} - -static S32 iSG_mc_exists(S32 slot) -{ - S32 ret = 0; - s32 memSize = 0; - s32 sectorSize = 0; - - if (slot < -1) - { - return 0; - } - - S32 result; - do - { - result = CARDProbeEx(slot, &memSize, §orSize); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - ret = 1; - } - - return ret; -} - -static S32 iSG_mc_tryRepair(st_ISG_MEMCARD_DATA* mcdata) -{ - S32 result = 0; - S32 rc = 0; - s32 xferBytes = 0; - - if (mcdata->unk_0 == 0) - { - rc = 0; - } - - else if (mcdata->unk_12c) - { - rc = 0; - } - else - { - do - { - result = CARDCheckEx(mcdata->chan, &xferBytes); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - rc = 1; - } - else if (result == CARD_RESULT_ENCODING) - { - rc = 1; - } - else - { - if (result != CARD_RESULT_BROKEN) - { - mcdata->unk_12c = 1; - } - rc = 0; - } - } - return rc; -} - -static S32 iSG_mc_isformatted(st_ISG_MEMCARD_DATA* mcdata) -{ - S32 result = 0; - S32 rc = 0; - s32 xferBytes = 0; - - if (mcdata->unk_0 == 0) - { - rc = 0; - } - else if (mcdata->unk_12c) - { - rc = 0; - } - else - { - do - { - result = CARDCheckEx(mcdata->chan, &xferBytes); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - rc = 1; - } - else if (result == CARD_RESULT_BROKEN) - { - rc = 0; - } - else - { - rc = 0; - } - } - - return rc; -} - -static S32 iSG_mc_isGCcard(st_ISG_MEMCARD_DATA* mcdata, int* param2, int* param3) -{ - S32 result = 0; - S32 rc = 0; - - s32 xferBytes = 0; - u16 encoding = 0; - s32 memSize = 0; - s32 sectorSize = 0; - - if (param2) - { - *param2 = 0; - } - - if (param3) - { - *param3 = 0; - } - - if (mcdata->unk_0 == 0) - { - return 0; - } - if (mcdata->unk_12c) - { - return 0; - } - - do - { - result = CARDProbeEx(mcdata->chan, &memSize, §orSize); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - rc = 1; - } - - if (rc != 0) - { - do - { - result = CARDCheckEx(mcdata->chan, &xferBytes); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - rc = 1; - } - else if (result == CARD_RESULT_BROKEN) - { - rc = 2; - } - else - { - if (result == CARD_RESULT_ENCODING) - { - rc = 3; - if (param2) - { - *param2 = 1; - } - } - else - { - rc = 0; - if (result == CARD_RESULT_ENCODING && param2) - { - *param2 = 1; - } - if (result == CARD_RESULT_IOERROR && param3) - { - *param3 = 1; - } - } - } - } - - if (rc == 1) - { - do - { - result = CARDGetEncoding(mcdata->chan, &encoding); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY && encoding && param2) - { - *param2 = 1; - } - } - - return rc; -} - -static S32 iSG_cubeicon_size(S32 param1, S32 param2); -static S32 iSG_get_finfo(st_ISG_MEMCARD_DATA*, const char*); -// PS2 signature: -// static signed int iSG_isSpaceForFile(class st_ISG_MEMCARD_DATA* mcdata, S32 mcidx, S32 fsize, -// char* dpath, char* fname, S32* bytesNeeded, S32* availOnDisk) -static S32 iSG_isSpaceForFile(st_ISG_MEMCARD_DATA* mcdata, S32 param2, const char* param3, - S32* param4, S32* param5, S32* param6) -{ - S32 rc = 0; - S32 result = 0; - s32 byteNotUsed = 0; - s32 filesNotUsed = 0; - S32 len; - - if (mcdata->unk_0 == 0) - { - return 0; - } - len = iSG_cubeicon_size(mcdata->chan, mcdata->sectorSize); - len = len + param2; - len = ALIGN_THING(mcdata->sectorSize, len); - - do - { - result = CARDFreeBlocks(mcdata->chan, &byteNotUsed, &filesNotUsed); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - if (param5) - { - *param5 = byteNotUsed / mcdata->sectorSize; - } - if (param4) - { - *param4 = len / mcdata->sectorSize; - } - } - else - { - return 0; - } - - if (param6) - { - *param6 = 1; - } - - if (iSG_get_finfo(mcdata, param3)) - { - if (param6) - { - *param6 = *param6 - 1 & ~(*param6 - 1 >> 0x1f); // FIXME: Fakematch - } - if (len <= mcdata->unk_b0.length + byteNotUsed) - { - rc = 1; - } - } - else - { - if (len <= byteNotUsed && filesNotUsed > 0) - { - rc = 1; - } - } - - return rc; -} - -static S32 iSG_mc_mount(S32 slot); -static S32 iSG_mc_settgt(st_ISG_MEMCARD_DATA* mcdata, S32 slot) -{ - if (iSG_mc_mount(slot)) - { - mcdata->unk_0 = 1; - mcdata->chan = slot; - - iSG_mc_tryRepair(mcdata); - CARDGetSectorSize(slot, (u32*)&mcdata->sectorSize); - } - else - { - mcdata->unk_0 = 0; - } - - return mcdata->unk_0 != 0 ? 1 : 0; -} - -static S32 iSG_get_finfo(st_ISG_MEMCARD_DATA* mcdata, const char* dpath) -{ - S32 rc = 0; - en_ASYNC_OPERR operr = ISG_OPERR_NONE; - - if (iSG_mc_fopen(mcdata, dpath, -1, ISG_IOMODE_READ, &operr)) - { - rc = 1; - memcpy(&mcdata->unk_b0, &mcdata->fstat, sizeof(CARDStat)); - memcpy(&mcdata->unk_9c, &mcdata->finfo, sizeof(CARDFileInfo)); - iSG_mc_fclose(mcdata); - } - - return rc; -} - -static S32 iSG_curKosher(CARDStat* stat, CARDFileInfo* info) -{ - S32 rc = 1; - - if ((stat->iconAddr < 1 || stat->iconAddr > 0x7fffffff) && - (stat->commentAddr < 1 || stat->commentAddr > 0x7fffffff)) - { - rc = 0; - } - else - { - char stuff[0x200] = { 0 }; - sprintf(stuff, "SPONGEBOB:WHENROBOTSATTACK::RyanNeilDan"); - void* alloc = xMemPushTemp(0x5e00 + 0x1f); - // align buf address to 32 bytes - char* buf = (char*)((U32)alloc + 0x1f & ~0x1f); - - S32 result; - do - { - result = CARDRead(info, buf, 0x5e00, 0); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - if (memcmp(buf + 0x5a40, stuff, strlen(stuff) - 1)) - { - rc = 0; - } - - if (memcmp(buf, "Battle for Bikini Bottom", strlen("Battle for Bikini Bottom") - 1)) - { - rc = 0; - } - } - - xMemPopTemp(alloc); - } - - return rc; -} -static S32 iSG_fileKosher(st_ISG_MEMCARD_DATA* mcdata, const char* param2, int param3, int* param4) -{ - S32 rc = 0; - en_ASYNC_OPERR operr = ISG_OPERR_NONE; - - if (param4) - { - *param4 = 0; - } - - if (iSG_mc_fopen(mcdata, param2, -1, ISG_IOMODE_READ, &operr) == 0) - { - return -1; - } - - S32 ret = iSG_curKosher(&mcdata->fstat, &mcdata->finfo); - iSG_mc_fclose(mcdata); - - if (ret == 0) - { - rc = 0; - if (param3 && iSG_mc_fdel(mcdata, param2) && param4) - { - *param4 = 1; - } - } - else - { - rc = 1; - } - return rc; -} - -static S32 iSG_get_fsize(st_ISG_MEMCARD_DATA* mcdata, const char* param2) -{ - S32 rc = -1; - - if (iSG_get_finfo(mcdata, param2)) - { - rc = mcdata->unk_b0.length; - } - - if (rc < 0) - { - rc = -1; - } - - return rc; -} - -static S32 iSG_get_fmoddate(st_ISG_MEMCARD_DATA* mcdata, const char* fname, int* sec, int* min, - int* hr, int* mon, int* day, int* yr) -{ - S32 rc = 1; - OSCalendarTime time = { 0 }; - - if (iSG_get_finfo(mcdata, fname) == 0) - { - rc = 0; - } - else - { - OSTime t = mcdata->unk_b0.time; - t = OSSecondsToTicks(t); - OSTicksToCalendarTime(t, &time); - - if (sec) - { - *sec = time.sec; - } - if (min) - { - *min = time.min; - } - if (hr) - { - *hr = time.hour; - } - if (mon) - { - *mon = time.mon + 1; - } - if (day) - { - *day = time.mday; - } - if (mon) - { - *mon = time.mon + 1; - } - if (day) - { - *day = time.mday; - } - if (yr) - { - *yr = time.year; - } - } - - return rc; -} - -static void iSG_timestamp(CARDStat*) -{ -} - -struct IconData -{ - char game_name[0x20]; - char buf0[0x20]; - char buf1[0x1800]; - char buf2[8][0x800]; - char pad[0x200]; - char footer[0x200]; -}; -static S32 iSG_cubeicon_size(S32 slot, S32 param2) -{ - if ((U32)slot > 1) - { - return -1; - } - - S32 t = ALIGN_THING(param2, 0x200); - - // FIXME: Macro not quite right - // return ALIGN_THING(t, sizeof(IconData)); - return -t & sizeof(IconData) + t - 1; -} - -static S32 iSG_chk_icondata() -{ - return 1; -} - -static S32 iSG_tpl_unpack(st_ISG_TPL_TEXPALETTE*); -static S32 iSG_bnr_unpack(st_ISG_TPL_TEXPALETTE*); -static S32 iSG_load_icondata() -{ - g_rawicon = (st_ISG_TPL_TEXPALETTE*)iFileLoad("/SBGCIcon.tpl", NULL, &g_iconsize); - g_rawbanr = (st_ISG_TPL_TEXPALETTE*)iFileLoad("/SBGCBanner.tpl", NULL, &g_banrsize); - iSG_tpl_unpack(g_rawicon); - iSG_bnr_unpack(g_rawbanr); - - return g_rawicon && (S32)g_iconsize && g_rawbanr && (S32)g_banrsize ? 1 : 0; -} - -static void iSG_discard_icondata() -{ - OSFreeToHeap(__OSCurrHeap, g_rawicon); - OSFreeToHeap(__OSCurrHeap, g_rawbanr); - g_rawicon = NULL; - g_iconsize = 0; - g_rawbanr = NULL; - g_banrsize = 0; -} - -static st_ISG_TPL_TEX* iSG_tpl_TEXGet(st_ISG_TPL_TEXPALETTE*, unsigned int); -static char* iSG_bfr_icondata(char* param1, CARDStat* stat, char* param3, int param4) -{ - IconData data = { 0 }; - static st_ISG_TPL_TEXPALETTE* ico_pal; - static st_ISG_TPL_TEX* ico_desc; - static U32 i = 0; - - sprintf(data.footer, "SPONGEBOB:WHENROBOTSATTACK::RyanNeilDan"); - strncpy(data.game_name, "Battle for Bikini Bottom", sizeof(data.game_name)); - data.game_name[0x1f] = NULL; - - if (param3) - { - strncpy(data.buf0, param3, sizeof(data.buf0)); - } - data.buf0[0x1f] = NULL; - - ico_pal = g_rawbanr; - ico_desc = iSG_tpl_TEXGet(ico_pal, 0); - memcpy(data.buf1, ico_desc->unk_0->unk_8, sizeof(data.buf1)); - - ico_pal = g_rawicon; - for (i = 0; i < 8; i++) - { - ico_desc = iSG_tpl_TEXGet(ico_pal, i); - memcpy(data.buf2[i], ico_desc->unk_0->unk_8, sizeof(data.buf2[i])); - } - - memcpy(param1, &data, sizeof(data)); - - S32 t = ALIGN_THING(param4, 0x200); - return param1 + (t + (sizeof(IconData) - 1) & -t); -} - -static void iSG_upd_icostat(CARDStat*, CARDStat* stat) -{ - CARDSetCommentAddress(stat, 0); - CARDSetBannerFormat(stat, CARD_STAT_BANNER_RGB5A3); - CARDSetIconAddress(stat, 0x40); - CARDSetIconAnim(stat, CARD_STAT_ANIM_LOOP); - - for (S32 i = 0; i < CARD_ICON_MAX; ++i) - { - CARDSetIconFormat(stat, i, CARD_STAT_BANNER_RGB5A3); - CARDSetIconSpeed(stat, i, CARD_STAT_SPEED_MIDDLE); - } -} - -static S32 iSG_tpl_unpack(st_ISG_TPL_TEXPALETTE* tpl) -{ - if (tpl->magic != 0x20af30) - { - return 0; - } - - tpl->unk_8 = (st_ISG_TPL_TEX*)((U32)tpl + (U32)tpl->unk_8); - for (S32 i = 0; i < tpl->count; ++i) - { - st_ISG_TPL_TEX* x = &tpl->unk_8[i]; - if (x->unk_0 != NULL) - { - x->unk_0 = (st_ISG_TPL_TEX::UnkIn*)((U32)tpl + (U32)x->unk_0); - if (x->unk_0->unk_23 == 0) - { - x->unk_0->unk_8 = (void*)((U32)tpl + (U32)x->unk_0->unk_8); - x->unk_0->unk_23 = 1; - } - } - if (x->unk_4 != NULL) - { - x->unk_4 = (st_ISG_TPL_TEX::UnkOut*)((U32)tpl + (U32)x->unk_4); - if (x->unk_4->unk_2 == 0) - { - x->unk_4->unk_8 = tpl; - x->unk_4->unk_2 = 1; - } - } - } - return 1; -} - -static S32 iSG_bnr_unpack(st_ISG_TPL_TEXPALETTE* tpl) -{ - return iSG_tpl_unpack(tpl); -} - -static st_ISG_TPL_TEX* iSG_tpl_TEXGet(st_ISG_TPL_TEXPALETTE* tpl, U32 n) -{ - return &tpl->unk_8[n]; -} - -static void iSG_cb_unmount(s32 chan, s32 result); -static S32 iSG_mc_mount(S32 slot) -{ - s32 ret = 0; - // ?? for some reason this variable is in the stack frame - volatile s32 result = 0; - do - { - result = CARDMount(slot, cardwork[slot], iSG_cb_unmount); - isMounted = 1; - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - ret = 1; - } - else if (result == CARD_RESULT_BROKEN || result == CARD_RESULT_ENCODING) - { - ret = 1; - } - return ret; -} - -static S32 iSG_mc_unmount(S32 slot) -{ - S32 rc = 0; - S32 result; - - do - { - result = CARDUnmount(slot); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - rc = 1; - } - else if (result == CARD_RESULT_NOCARD) - { - rc = 1; - } - - return rc; -} - -static void iSG_cb_unmount(s32 chan, s32 result) -{ - st_ISGSESSION* session = &g_isgdata_MAIN; - if (chan != session->slot) - { - return; - } - session->slot = -1; - if (session->chgfunc != NULL) - { - session->chgfunc(session->cltdata, ISG_CHG_TARGET); - } - memset(&session->mcdata[chan], 0, sizeof(st_ISG_MEMCARD_DATA)); -} - -static S32 iSG_mc_format(st_ISG_MEMCARD_DATA* mcdata, S32, S32* canRecover) -{ - if (mcdata->unk_12c != 0) - { - if (canRecover != NULL) - { - *canRecover = 0; - } - return 0; - } - - if (canRecover != NULL) - { - *canRecover = 1; - } - - s32 result; - do - { - result = CARDFormat(mcdata->chan); - } while (result == CARD_RESULT_BUSY); - - S32 ret; - if (result == CARD_RESULT_READY) - { - ret = 1; - } - else - { - ret = 0; - - switch (result) - { - case CARD_RESULT_IOERROR: - mcdata->unk_12c = 1; - if (canRecover != NULL) - { - *canRecover = 0; - } - break; - case CARD_RESULT_NOCARD: - if (canRecover != NULL) - { - *canRecover = -1; - } - ret = -1; - break; - case CARD_RESULT_FATAL_ERROR: - case CARD_RESULT_WRONGDEVICE: - case CARD_RESULT_NOFILE: - break; - } - } - return ret; -} - -static S32 iSG_mc_fopen(st_ISG_MEMCARD_DATA* mcdata, const char* fname, S32 fsize, - en_ISG_IOMODE mode, en_ASYNC_OPERR* operr) -{ - S32 ret = 0; - CARDFileInfo* finfo = &mcdata->finfo; - CARDStat* stat = &mcdata->fstat; - if (operr != NULL) - { - *operr = ISG_OPERR_NONE; - } - - if (mode == ISG_IOMODE_READ) - { - s32 result; - do - { - result = CARDOpen(mcdata->chan, (char*)fname, finfo); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - ret = 1; - } - } - else - { - S32 res = iSG_mc_fdel(mcdata, fname); - if (mcdata->unk_12c == 0 && res > 0) - { - s32 result; - do - { - result = CARDCreate(mcdata->chan, (char*)fname, fsize, finfo); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - ret = 1; - mcdata->unk_98 = 0; - } - else if (operr != NULL) - { - switch (result) - { - case CARD_RESULT_WRONGDEVICE: - case CARD_RESULT_NOCARD: - *operr = ISG_OPERR_NOCARD; - break; - case CARD_RESULT_IOERROR: - case CARD_RESULT_BROKEN: - mcdata->unk_12c = 1; - *operr = ISG_OPERR_DAMAGE; - break; - case CARD_RESULT_NOENT: - case CARD_RESULT_INSSPACE: - *operr = ISG_OPERR_NOROOM; - break; - default: - *operr = ISG_OPERR_OTHER; - break; - case CARD_RESULT_READY: - case CARD_RESULT_BUSY: - case CARD_RESULT_EXIST: - case CARD_RESULT_NOPERM: - break; - } - } - } - } - - if (ret != 0) - { - s32 result; - do - { - result = CARDGetStatus(mcdata->chan, finfo->fileNo, stat); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - ret = 1; - } - } - - if (ret != 0) - { - if (memcmp(stat->gameName, "GQPE", 4) != 0 || memcmp(stat->company, "78", 2) != 0) - { - iSG_mc_fclose(mcdata); - ret = 0; - } - } - - return ret; -} - -static S32 iSG_mc_fclose(st_ISG_MEMCARD_DATA* mcdata) -{ - return iSG_mc_fclose(mcdata, NULL); -} - -static S32 iSG_mc_fclose(st_ISG_MEMCARD_DATA* mcdata, CARDStat* stat) -{ - S32 ret = 0; - s32 result; - do - { - result = CARDClose(&mcdata->finfo); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - ret = 1; - } - - if (stat != NULL) - { - memcpy(stat, &mcdata->fstat, sizeof(CARDStat)); - } - - memset(&mcdata->finfo, 0, sizeof(CARDFileInfo)); - memset(&mcdata->fstat, 0, sizeof(CARDStat)); - - return ret; -} - -static S32 iSG_mc_fdel(st_ISG_MEMCARD_DATA* mcdata, const char* fname) -{ - if (mcdata->chan < 0 || mcdata->chan > 1) - { - return 0; - } - - if (isMounted == 0) - { - return 0; - } - - s32 result; - do - { - result = CARDDelete(mcdata->chan, fname); - } while (result == CARD_RESULT_BUSY); - - S32 ret; - if (result == CARD_RESULT_NOFILE) - { - ret = 1; - } - else if (result == CARD_RESULT_READY) - { - ret = 1; - } - else - { - ret = 0; - switch (result) - { - case CARD_RESULT_IOERROR: - mcdata->unk_12c = 1; - break; - case CARD_RESULT_NOPERM: - case CARD_RESULT_FATAL_ERROR: - case CARD_RESULT_WRONGDEVICE: - break; - } - } - return ret; -} - -static void iSG_cb_asyndone(s32, s32) -{ -} - -static S32 iSG_mcqa_fread(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len, S32 offset); -static S32 iSG_mc_fread(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len, S32 offset) -{ - return iSG_mcqa_fread(mcdata, buf, len, offset); -} - -static void iSG_cb_asyndone(s32, s32); -static S32 iSG_mcqa_fread(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len, S32 offset) -{ - S32 x = 1000; - s32 result = CARDGetResultCode(mcdata->chan); - do - { - result = CARDGetResultCode(mcdata->chan); - } while (result == CARD_RESULT_BUSY); - - if (result != CARD_RESULT_READY) - { - return 0; - } - - CARDGetXferredBytes(mcdata->chan); - do - { - result = CARDReadAsync(&mcdata->finfo, buf, len, offset, iSG_cb_asyndone); - } while (result == CARD_RESULT_BUSY); - - if (result != CARD_RESULT_READY) - { - return 0; - } - - result = CARD_RESULT_BUSY; - do - { - if (x++ > 500) - { - xSndUpdate(); - CARDGetXferredBytes(mcdata->chan); - result = CARDGetResultCode(mcdata->chan); - x = 0; - } - iTRCDisk::CheckDVDAndResetState(); - } while (result == CARD_RESULT_BUSY); - return result != 0 ? 0 : 1; -} - -static S32 iSG_mcqa_fwrite(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len); -static S32 iSG_mc_fwrite(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len) -{ - return iSG_mcqa_fwrite(mcdata, buf, len); -} - -static S32 iSG_mcqa_fwrite(st_ISG_MEMCARD_DATA* mcdata, char* buf, S32 len) -{ - S32 ret = 0; - S32 x = 1000; - CARDStat* fstat = &mcdata->fstat; - s32 result; - do - { - result = CARDGetResultCode(mcdata->chan); - } while (result == CARD_RESULT_BUSY); - - if (result != CARD_RESULT_READY) - { - return 0; - } - - CARDGetXferredBytes(mcdata->chan); - s32 asynresult; - do - { - asynresult = CARDWriteAsync(&mcdata->finfo, buf, len, mcdata->unk_98, iSG_cb_asyndone); - } while (asynresult == CARD_RESULT_BUSY); - - if (asynresult != CARD_RESULT_READY) - { - return 0; - } - - result = CARD_RESULT_BUSY; - do - { - if (x++ > 500) - { - result = CARDGetResultCode(mcdata->chan); - xSndUpdate(); - CARDGetXferredBytes(mcdata->chan); - x = 0; - } - iTRCDisk::CheckDVDAndResetState(); - } while (result == CARD_RESULT_BUSY); - - if (asynresult == CARD_RESULT_READY) - { - mcdata->unk_98 += len; - - do - { - result = CARDGetStatus(mcdata->chan, mcdata->finfo.fileNo, fstat); - } while (result == CARD_RESULT_BUSY); - - if (result == CARD_RESULT_READY) - { - ret = 1; - } - } - return ret; -} - -S32 iSGCheckForWrongDevice() -{ - char* workarea = (char*)RwMalloc(0x10000 - 0x6000); - - S32 ret = -1; - for (S32 i = 0; i < ISG_NUM_SLOTS; ++i) - { - s32 result = CARDMount(i, workarea, NULL); - - switch (result) - { - case CARD_RESULT_READY: - case CARD_RESULT_BROKEN: - case CARD_RESULT_ENCODING: - CARDUnmount(i); - break; - case CARD_RESULT_WRONGDEVICE: - ret = i; - i = ISG_NUM_SLOTS; - break; - } - } - - RwFree(workarea); - - return ret; -} - -S32 iSGCheckForCorruptFiles(st_ISGSESSION* isgdata, char files[][64]) -{ - if (isgdata->slot < 0) - { - return 0; - } - - S32 i; - char* name; - st_ISG_MEMCARD_DATA* mcdata = &isgdata->mcdata[isgdata->slot]; - S32 ret = 0; - memset(files, NULL, 0xc0); - - for (i = 0; i < ISG_NUM_FILES; ++i) - { - name = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, i); - if (iSG_fileKosher(mcdata, name, 0, NULL) == 0) - { - strcpy(files[ret], name); - ret++; - } - } - return ret; -} - -U8 iSGCheckMemoryCard(st_ISGSESSION* isgdata, S32 index) -{ - s32 memSize; - s32 sectorSize; - - switch (CARDProbeEx(index, &memSize, §orSize)) - { - case CARD_RESULT_READY: - return 1; - } - return 0; -} - -void iSGAutoSave_Startup() -{ -} - -st_ISGSESSION* iSGAutoSave_Connect(S32 idx_target, void* cltdata, void (*chg)(void*, en_CHGCODE)) -{ - st_ISGSESSION* isgdata = iSGSessionBegin(cltdata, chg, 1); - if (isgdata == NULL) - { - return isgdata; - } - - if (iSGTgtSetActive(isgdata, idx_target) == 0) - { - iSGSessionEnd(isgdata); - isgdata = NULL; - } - return isgdata; -} - -void iSGAutoSave_Disconnect(st_ISGSESSION* isg) -{ - iSGSessionEnd(isg); -} - -S32 iSGAutoSave_Monitor(st_ISGSESSION* isg, S32 idx_target) -{ - if (isg == NULL) - { - return 0; - } - - U32 ret = iSGTgtState(isg, idx_target, NULL); - if (ret == 0 || (ret & 1) == 0) - { - globals.autoSaveFeature = 0; - return 0; - } - return 1; -} diff --git a/src/SB/Core/gc/ngcrad3d.c b/src/SB/Core/gc/ngcrad3d.c deleted file mode 100644 index f69b348..0000000 --- a/src/SB/Core/gc/ngcrad3d.c +++ /dev/null @@ -1 +0,0 @@ -#include "ngcrad3d.h" diff --git a/src/SB/Core/gc/ngcrad3d.cpp b/src/SB/Core/gc/ngcrad3d.cpp deleted file mode 100644 index ab9c71b..0000000 --- a/src/SB/Core/gc/ngcrad3d.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "ngcrad3d.h" - -#include diff --git a/src/SB/Core/x/iCamera.cpp b/src/SB/Core/x/iCamera.cpp deleted file mode 100644 index e1e99ba..0000000 --- a/src/SB/Core/x/iCamera.cpp +++ /dev/null @@ -1,341 +0,0 @@ -#include "iCamera.h" - -#include "xShadow.h" - -#include "iScrFX.h" -#include "iMath.h" - -#include "zGlobals.h" - -#include - -extern F32 sCameraNearClip; -extern F32 sCameraFarClip; -extern RwCamera* sMainGameCamera; - -extern F32 _640_0; -extern F32 _706_0; -extern F32 _707_1; -extern F32 _708_3; -extern F32 _709_1; -extern F32 _741_3; -extern F32 _742_1; -extern F32 _743_1; -extern F64 _769_1; -extern F64 _826_0; - -RwCamera* iCameraCreate(S32 width, S32 height, S32 mainGameCamera) -{ - RwV2d vw; - RwCamera* camera; - - camera = RwCameraCreate(); - - RwCameraSetFrame(camera, RwFrameCreate()); - RwCameraSetRaster(camera, RwRasterCreate(width, height, 0, rwRASTERTYPECAMERA)); - RwCameraSetZRaster(camera, RwRasterCreate(width, height, 0, rwRASTERTYPEZBUFFER)); - RwCameraSetFarClipPlane(camera, sCameraFarClip); - RwCameraSetNearClipPlane(camera, sCameraNearClip); - - vw.x = _640_0; - vw.y = _640_0; - - RwCameraSetViewWindow(camera, &vw); - - if (mainGameCamera) - { - iScrFxCameraCreated(camera); - sMainGameCamera = camera; - } - - return camera; -} - -void iCameraDestroy(RwCamera* camera) -{ - RpWorld* pWorld; - RwRaster* raster; - RwFrame* frame; - - _rwFrameSyncDirty(); - - pWorld = RwCameraGetWorld(camera); - - if (pWorld) - { - RpWorldRemoveCamera(pWorld, camera); - } - - if (camera == sMainGameCamera) - { - iScrFxCameraDestroyed(camera); - sMainGameCamera = NULL; - } - - if (camera) - { - frame = RwCameraGetFrame(camera); - - if (frame) - { - RwCameraSetFrame(camera, NULL); - RwFrameDestroy(frame); - } - - raster = RwCameraGetRaster(camera); - - if (raster) - { - RwRasterDestroy(raster); - RwCameraSetRaster(camera, NULL); - } - - raster = RwCameraGetZRaster(camera); - - if (raster) - { - RwRasterDestroy(raster); - RwCameraSetZRaster(camera, NULL); - } - - RwCameraDestroy(camera); - } -} - -void iCameraBegin(RwCamera* cam, S32 clear) -{ - if (clear) - { - if (xglobals->fog.type != rwFOGTYPENAFOGTYPE) - { - RwCameraClear(cam, &xglobals->fog.bgcolor, rwCAMERACLEARIMAGE | rwCAMERACLEARZ); - } - else - { - RwCameraClear(cam, NULL, rwCAMERACLEARZ); - } - } - - RwCameraSetNearClipPlane(cam, sCameraNearClip); - RwCameraBeginUpdate(cam); -} - -void iCameraEnd(RwCamera* cam) -{ - iScrFxCameraEndScene(cam); - RwCameraEndUpdate(cam); - iScrFxPostCameraEnd(cam); -} - -void iCameraShowRaster(RwCamera* cam) -{ - RwCameraShowRaster(cam, NULL, 0); -} - -void iCameraFrustumPlanes(RwCamera* cam, xVec4* frustplane) -{ - RwFrustumPlane* rwPlane; - - rwPlane = &cam->frustumPlanes[2]; - frustplane[0].x = rwPlane->plane.normal.x; - frustplane[1].x = rwPlane->plane.normal.y; - frustplane[2].x = rwPlane->plane.normal.z; - frustplane[3].x = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[4]; - frustplane[0].y = rwPlane->plane.normal.x; - frustplane[1].y = rwPlane->plane.normal.y; - frustplane[2].y = rwPlane->plane.normal.z; - frustplane[3].y = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[5]; - frustplane[0].z = rwPlane->plane.normal.x; - frustplane[1].z = rwPlane->plane.normal.y; - frustplane[2].z = rwPlane->plane.normal.z; - frustplane[3].z = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[3]; - frustplane[0].w = rwPlane->plane.normal.x; - frustplane[1].w = rwPlane->plane.normal.y; - frustplane[2].w = rwPlane->plane.normal.z; - frustplane[3].w = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[1]; - frustplane[4].x = rwPlane->plane.normal.x; - frustplane[5].x = rwPlane->plane.normal.y; - frustplane[6].x = rwPlane->plane.normal.z; - frustplane[7].x = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[0]; - frustplane[4].y = rwPlane->plane.normal.x; - frustplane[5].y = rwPlane->plane.normal.y; - frustplane[6].y = rwPlane->plane.normal.z; - frustplane[7].y = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[2]; - frustplane[4].z = rwPlane->plane.normal.x; - frustplane[5].z = rwPlane->plane.normal.y; - frustplane[6].z = rwPlane->plane.normal.z; - frustplane[7].z = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[4]; - frustplane[4].w = rwPlane->plane.normal.x; - frustplane[5].w = rwPlane->plane.normal.y; - frustplane[6].w = rwPlane->plane.normal.z; - frustplane[7].w = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[2]; - frustplane[8].x = rwPlane->plane.normal.x; - frustplane[9].x = rwPlane->plane.normal.y; - frustplane[10].x = rwPlane->plane.normal.z; - frustplane[11].x = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[4]; - frustplane[8].y = rwPlane->plane.normal.x; - frustplane[9].y = rwPlane->plane.normal.y; - frustplane[10].y = rwPlane->plane.normal.z; - frustplane[11].y = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[5]; - frustplane[8].z = rwPlane->plane.normal.x; - frustplane[9].z = rwPlane->plane.normal.y; - frustplane[10].z = rwPlane->plane.normal.z; - frustplane[11].z = rwPlane->plane.distance; - - rwPlane = &cam->frustumPlanes[3]; - frustplane[8].w = rwPlane->plane.normal.x; - frustplane[9].w = rwPlane->plane.normal.y; - frustplane[10].w = rwPlane->plane.normal.z; - frustplane[11].w = rwPlane->plane.distance; -} - -void iCameraUpdatePos(RwCamera* cam, xMat4x3* pos) -{ - RwFrame* f; - RwMatrix* m; - - f = RwCameraGetFrame(cam); - m = RwFrameGetMatrix(f); - - xMat4x3Copy((xMat4x3*)m, pos); - - m = RwFrameGetLTM(f); - - xMat4x3Copy((xMat4x3*)m, pos); - - RwFrameOrthoNormalize(f); - RwFrameUpdateObjects(f); -} - -void iCameraSetFOV(RwCamera* cam, F32 fov) -{ - RwV2d vw; - - vw.x = itan(_706_0 * (_707_1 * fov) / _708_3); - - // non-matching: frsp instruction is here for some reason - vw.y = _709_1 * vw.x; - - RwCameraSetViewWindow(cam, &vw); -} - -void iCameraAssignEnv(RwCamera* camera, iEnv* env_geom) -{ - globalCamera = camera; - - RpWorldAddCamera(env_geom->world, camera); - xShadowSetWorld(env_geom->world); -} - -void iCamGetViewMatrix(RwCamera* camera, xMat4x3* view_matrix) -{ - RwMatrix* rw_view; - - memset(view_matrix, 0, sizeof(xMat4x3)); - - rw_view = RwCameraGetViewMatrix(camera); - - view_matrix->right.x = rw_view->right.x; - view_matrix->right.y = rw_view->right.y; - view_matrix->right.z = rw_view->right.z; - view_matrix->up.x = rw_view->up.x; - view_matrix->up.y = rw_view->up.y; - view_matrix->up.z = rw_view->up.z; - view_matrix->at.x = rw_view->at.x; - view_matrix->at.y = rw_view->at.y; - view_matrix->at.z = rw_view->at.z; - view_matrix->pos.x = rw_view->pos.x; - view_matrix->pos.y = rw_view->pos.y; - view_matrix->pos.z = rw_view->pos.z; -} - -void iCameraSetNearFarClip(F32 nearPlane, F32 farPlane) -{ - if (nearPlane <= *(const F32*)&_742_1) - { - nearPlane = _741_3; - } - - sCameraNearClip = nearPlane; - - // non-matching: _742_1 is loaded too early - - if (farPlane <= *(const F32*)&_742_1) - { - farPlane = _743_1; - } - - sCameraFarClip = farPlane; -} - -void iCameraSetFogParams(iFogParams* fp, F32 time) -{ - if (!fp || fp->type == rwFOGTYPENAFOGTYPE) - { - xglobals->fog.type = rwFOGTYPENAFOGTYPE; - xglobals->fogA.type = rwFOGTYPENAFOGTYPE; - } - else if (_742_1 == time || fp->type != xglobals->fogA.type) - { - xglobals->fog = *fp; - xglobals->fogA = *fp; - xglobals->fog_t0 = 0; - } - else - { - xglobals->fogA = xglobals->fog; - xglobals->fogB = *fp; - - // todo - } -} - -void iCameraSetFogRenderStates() -{ - RwCamera* pCamera; - iFogParams* pFogParams; - U32 bite_me; - - pCamera = RwCameraGetCurrentCamera(); - pFogParams = &xglobals->fog; - - if (pFogParams->type == rwFOGTYPENAFOGTYPE) - { - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); - - RwCameraSetFarClipPlane(pCamera, sCameraFarClip); - } - else - { - bite_me = (pFogParams->fogcolor.alpha << 24) | (pFogParams->fogcolor.red << 16) | - (pFogParams->fogcolor.green << 8) | pFogParams->fogcolor.blue; - - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)pFogParams->type); - RwRenderStateSet(rwRENDERSTATEFOGCOLOR, (void*)bite_me); - RwRenderStateSet(rwRENDERSTATEFOGDENSITY, (void*)&pFogParams->density); - - RwCameraSetFogDistance(pCamera, pFogParams->start); - RwCameraSetFarClipPlane(pCamera, pFogParams->stop); - } -} diff --git a/src/SB/Core/x/xAnim.cpp b/src/SB/Core/x/xAnim.cpp deleted file mode 100644 index 18a2f2c..0000000 --- a/src/SB/Core/x/xAnim.cpp +++ /dev/null @@ -1,2185 +0,0 @@ -#include "xAnim.h" - -#include "iAnim.h" -#include "iModel.h" - -#include "xMemMgr.h" -#include "xMath.h" -#include "xModel.h" -#include "xMorph.h" -#include "xString.h" - -#include -#include -#include -#include - -#include -#include - -static xMemPool sxAnimTempTranPool; - -U32 gxAnimUseGrowAlloc = 0; - -static bool _xSingleCompare(char a, char b) -{ - switch (b) - { - case '?': - case '*': - case '+': - { - return true; - } - case '#': - { - return (a >= '0' && a <= '9'); - } - } - - return (a == b); -} - -static bool _xSingleCompare(char ch, const char* str) -{ - while (*str != '\0') - { - if (_xSingleCompare(ch, *str)) - { - return true; - } - - str++; - } - - return false; -} - -static bool _xCharIn(char ch, const char* str) -{ - while (*str != '\0') - { - if (ch == *str) - { - return true; - } - - str++; - } - - return false; -} - -static U8 _xCheckAnimNameInner(const char* name, const char* pattern, S32 patternSize, char* extra, - S32* nameOut, S32* extraOut) -{ - const char* startExtra = NULL; - char* initialExtra = extra; - S32 patternCurrent = 0; - S32 nameCurrent = 0; - while (patternCurrent < patternSize) - { - U32 check = pattern[patternCurrent]; - switch (check) - { - case '+': - case '?': - patternCurrent++; - if (nameCurrent == 0) - { - return 0; - } - nameCurrent++; - if (check != '?') - { - // Holy shit I hate this please tell me there's a better way - case '*': - check = patternCurrent + 1; - char nextPattern[128] = { 0 }; - nextPattern[0] = pattern[check]; - while (nextPattern[0] == '{' || nextPattern[0] == '}' || nextPattern[0] == '<' || - nextPattern[0] == '>') - { - check++; - nextPattern[0] = pattern[check]; - } - - if (nextPattern[0] == '(') - { - S32 nextPatternCount = 0; - U8 first = 1; - S32 parenCount = 0; - - while (pattern[check] != NULL && parenCount > -1) - { - if (pattern[check] == '(') - { - parenCount++; - } - else if (pattern[check] == ')') - { - parenCount--; - } - else if (parenCount == 0) - { - const char* IGNORE_PATTERNS = "{}()<>"; - if (pattern[check] == '|') - { - first = 1; - } - else if (first && _xCharIn(pattern[check], IGNORE_PATTERNS) == 0) - { - first = 0; - nextPattern[nextPatternCount++] = pattern[check]; - } - } - check++; - } - nextPattern[nextPatternCount] = NULL; - } - - while (name[nameCurrent] != NULL && - _xSingleCompare(name[nameCurrent], nextPattern) == 0) - { - nameCurrent++; - } - patternCurrent++; - } - break; - case '#': - if (name[nameCurrent] < '0' || name[nameCurrent] > '9') - { - return 0; - } - nameCurrent++; - - for (const char* x = &name[nameCurrent]; *x >= '0' && *x <= '9'; x++) - { - nameCurrent++; - } - patternCurrent++; - break; - case '{': - startExtra = &name[nameCurrent]; - patternCurrent++; - break; - case '}': - S32 length = &name[nameCurrent] - startExtra; - if (extra != NULL) - { - memcpy(extra, startExtra, length); - extra[length] = NULL; - extra = extra + length; - *++extra = '\x01'; - } - startExtra = NULL; - patternCurrent++; - break; - case '(': - patternCurrent++; - U8 done = 0; - const char* current = &pattern[patternCurrent]; - while (*current != ')' && *current != NULL) - { - const char* startPattern = current; - while (*startPattern != NULL && *startPattern != ')' && *startPattern != '|') - { - if (*startPattern == '(') - { - S32 pc = 1; - while (*startPattern != NULL && pc > 0) - { - if (*startPattern == ')') - { - pc--; - } - else if (*startPattern == '(') - { - pc++; - } - startPattern++; - } - if (*startPattern != NULL) - { - startPattern++; - } - } - else - { - startPattern++; - } - } - - if (startPattern != current) - { - S32 nameOut; - S32 extraOut; - - // NOTE (Square): There is no DWARF for an extra variable here and this programming pattern seems - // extremely wack. I think this "variable" is completely compiler generated for some reason - U8 wtfman = 0; - if (!done && - _xCheckAnimNameInner(&name[nameCurrent], current, startPattern - current, - extra, &nameOut, &extraOut)) - { - wtfman = 1; - } - - if (wtfman != 0) - { - done = 1; - nameCurrent += nameOut; - extra = extra + extraOut; - } - else if (extra != NULL) - { - *extra = '\x01'; - } - } - - current = startPattern; - if (*startPattern == '|') - { - current++; - } - } - if (*current != NULL) - { - current++; - } - patternCurrent += current - pattern; - if (!done) - { - return 0; - } - break; - case '<': - { - patternCurrent++; - const char* current = &pattern[patternCurrent]; - const char* positiveEnd = current; - while (*positiveEnd != NULL && *positiveEnd != ';' && *positiveEnd != '>') - { - positiveEnd++; - } - - const char* negative = NULL; - const char* negativeEnd = NULL; - - if (*positiveEnd == ';') - { - negativeEnd = positiveEnd + 1; - negative = negativeEnd; - while (*negativeEnd != NULL && *negativeEnd != '>') - { - negativeEnd++; - }; - positiveEnd = negativeEnd; - } - S32 nameOut; - S32 extraOut; - U8 matched = _xCheckAnimNameInner(&name[nameCurrent], current, positiveEnd - current, - extra, &nameOut, &extraOut); - if (matched != 0) - { - if (negative != NULL && - _xCheckAnimNameInner(&name[nameCurrent], negative, negativeEnd - negative, NULL, - NULL, NULL) != 0) - { - if (extra != NULL) - { - *extra = '\x01'; - } - matched = 0; - } - else - { - nameCurrent = nameCurrent + nameOut; - extra += extraOut; - } - } - - if (*positiveEnd != NULL) - { - positiveEnd++; - } - patternCurrent += &positiveEnd[patternCurrent] - &pattern[patternCurrent]; - if (matched == 0) - { - return 0; - } - break; - } - case NULL: - return 0; - case ')': - default: - if (name[nameCurrent] != pattern[patternCurrent]) - { - return 0; - } - nameCurrent++; - patternCurrent++; - break; - } - } - - if (nameOut != NULL) - { - *nameOut = nameCurrent; - } - if (extraOut != NULL) - { - *extraOut = extra - initialExtra; - } - return 1; -} - -static bool _xCheckAnimName(const char* name, const char* pattern, char* extra) -{ - S32 patternSize, nameOut; - U8 rc; - - *extra = 1; - patternSize = strlen(pattern); - - rc = _xCheckAnimNameInner(name, pattern, patternSize, extra, &nameOut, NULL); - - return (rc && name[nameOut] == '\0'); -} - -void xAnimInit() -{ - iAnimInit(); - memset(&sxAnimTempTranPool, 0, sizeof(xMemPool)); -} - -void xAnimTempTransitionInit(U32 count) -{ - xMemPoolSetup(&sxAnimTempTranPool, xMemAllocSize(count * sizeof(xAnimTransition)), 0, 0, NULL, - sizeof(xAnimTransition), count, count / 2); -} - -// TODO: move to xMathInlines.h -static F32 xatan2(F32 y, F32 x) -{ - return xAngleClampFast(std::atan2f(y, x)); -} - -#ifndef INLINE -float std::atan2f(float y, float x) -{ - return (float)atan2((double)y, (double)x); -} -#endif - -float CalcRecipBlendMax(U16* arg0) -{ - float max = 0.0f; - while (arg0[0] != 0xFFFF) - { - float f3; - if (arg0[1] == 0) - { - f3 = 0.0f; - } - else - { - f3 = 1.0f / (0.0009765625f * arg0[1]); - } - - f3 = 0.001f * arg0[0] + f3; - if (f3 > max) - { - max = f3; - } - arg0 += 2; - } - - if (max == 0.0f) - { - return 0.0f; - } - return 1.0f / max; -} - -static U32 StateHasTransition(xAnimState* state, xAnimTransition* tran) -{ - xAnimTransitionList* curr = state->List; - - while (curr) - { - if (curr->T == tran) - { - return TRUE; - } - - curr = curr->Next; - } - - return FALSE; -} - -static U32 DefaultHasTransition(xAnimState* state, xAnimTransition* tran, U32* r5) -{ - U32 r7 = 1; - xAnimTransitionList* curr = state->Default; - - while (curr) - { - if (curr->T == tran) - { - return TRUE; - } - - if (curr->T->Conditional == tran->Conditional && curr->T->UserFlags == tran->UserFlags) - { - r7 = 0; - } - - curr = curr->Next; - } - - *r5 += r7; - return FALSE; -} - -static U32 DefaultOverride(xAnimState* state, xAnimTransition* tran) -{ - xAnimTransitionList* list = state->Default; - - while (list) - { - if (list->T->Conditional == tran->Conditional && list->T->UserFlags == tran->UserFlags) - { - list->T = tran; - return TRUE; - } - - list = list->Next; - } - - return FALSE; -} - -static void TransitionTimeInit(xAnimSingle* single, xAnimTransition* tran) -{ - if (tran->Flags & 0x20) - { - if ((tran->Dest->Data->FileFlags ^ single->State->Data->FileFlags) & 0x1000) - { - single->Time = tran->Dest->Data->Duration - single->Time; - } - } - else - { - single->Time = ((tran->Dest->Flags & 0x100) && tran->DestTime == 0.0f) ? - single->State->Data->Duration * xurand() : - tran->DestTime; - } - single->LastTime = single->Time; -} - -xAnimFile* xAnimFileNewBilinear(void** rawData, const char* name, U32 flags, xAnimFile** linkedList, - U32 numX, U32 numY) -{ - xAnimFile* afile; - if (gxAnimUseGrowAlloc) - { - afile = (xAnimFile*)xMemGrowAlloc(gActiveHeap, numX * numY * 4 + sizeof(xAnimFile)); - } - else - { - afile = (xAnimFile*)xMemAlloc(gActiveHeap, numX * numY * 4 + sizeof(xAnimFile), 0); - } - - if (numX > 1 || numY > 1) - { - flags |= 0x4000; - } - - if (**(U32**)rawData == 'QSPM') - { - flags |= 0x8000; - } - - if (linkedList != NULL) - { - afile->Next = *linkedList; - *linkedList = afile; - } - else - { - afile->Next = NULL; - } - - afile->RawData = (void**)&afile[1]; - for (S32 i = 0; i < (S32)numX * (S32)numY; ++i) - { - afile->RawData[i] = rawData[i]; - } - - afile->Name = name; - afile->ID = xStrHash(name); - afile->FileFlags = flags; - - F32 dur; - if (afile->FileFlags & 0x2000) - { - if (afile->FileFlags & 0x8000) - { - dur = xMorphSeqDuration(*(xMorphSeqFile**)afile->RawData); - } - else - { - dur = iAnimDuration(*afile->RawData); - } - dur = dur * 2.0f; - } - else if (afile->FileFlags & 0x8000) - { - dur = xMorphSeqDuration(*(xMorphSeqFile**)afile->RawData); - } - else - { - dur = iAnimDuration(*afile->RawData); - } - afile->Duration = dur; - afile->TimeOffset = 0.0f; - - afile->BoneCount = flags & 0x8000 ? 0 : iAnimBoneCount(*rawData); - - afile->NumAnims[0] = numX; - afile->NumAnims[1] = numY; - - return afile; -} - -xAnimFile* xAnimFileNew(void* rawData, const char* name, U32 flags, xAnimFile** linkedList) -{ - return xAnimFileNewBilinear(&rawData, name, flags, linkedList, 1, 1); -} - -void xAnimFileSetTime(xAnimFile* data, float duration, float timeOffset) -{ - F32 rawDuration; - if (data->FileFlags & 0x8000) - { - rawDuration = xMorphSeqDuration(*(xMorphSeqFile**)data->RawData); - } - else - { - rawDuration = iAnimDuration(*data->RawData); - } - - if (timeOffset > rawDuration - 0.1f) - { - timeOffset = rawDuration - 0.1f; - } - - data->TimeOffset = timeOffset; - if (duration > rawDuration - timeOffset) - { - duration = rawDuration - timeOffset; - } - - data->Duration = (data->FileFlags & 0x2000) ? 2.0f * duration : duration; -} - -void xAnimFileEval(xAnimFile* data, F32 time, F32* bilinear, U32 flags, xVec3* tran, xQuat* quat, - F32* arg6) -{ - S32 i; - U32 numBones; - F32 bilerp[2]; - U32 biindex[2]; - U32 biplus[2]; - xQuat* q0; - xVec3* t0; - xQuat* q1; - xVec3* t1; - - time = xAnimFileRawTime(data, CLAMP(time, 0.0f, data->Duration)); - if (data->FileFlags & 0x8000) - { - return; - } - - if (flags & 0x1) - { - numBones = 1; - } - else - { - numBones = data->BoneCount; - } - - if (flags & 0x2) - { - numBones--; - } - - if (numBones == 0) - { - return; - } - - if (bilinear != NULL && data->FileFlags & 0x4000) - { - for (i = 0; i < 2; ++i) - { - F32 f30 = CLAMP(bilinear[i], 0.0f, data->NumAnims[i] - 1); - f32 t = std::floorf(f30); - bilerp[i] = f30 - t; - biindex[i] = t; - biplus[i] = MIN(biindex[i] + 1, data->NumAnims[i]); - } - - q0 = (xQuat*)(giAnimScratch + 0x1560); - t0 = (xVec3*)((U8*)q0 + 0x410); - if (bilerp[0] && bilerp[1]) - { - q1 = (xQuat*)(giAnimScratch + 0x1c80); - t1 = (xVec3*)((U8*)q1 + 0x410); - - iAnimEval(data->RawData[biindex[0] + biindex[1] * data->NumAnims[0]], time, flags, tran, - quat); - iAnimEval(data->RawData[biplus[0] + biindex[1] * data->NumAnims[0]], time, flags, t0, - q0); - iAnimBlend(bilerp[0], 1.0f, NULL, NULL, numBones, tran, quat, t0, q0, tran, quat); - - iAnimEval(data->RawData[biindex[0] + biplus[1] * data->NumAnims[0]], time, flags, t0, - q0); - iAnimEval(data->RawData[biplus[0] + biplus[1] * data->NumAnims[0]], time, flags, t1, - q1); - iAnimBlend(bilerp[0], 1.0f, NULL, NULL, numBones, t0, q0, t1, q1, t0, q0); - iAnimBlend(bilerp[1], 1.0f, NULL, NULL, numBones, tran, quat, t0, q0, tran, quat); - } - else if (bilerp[0]) - { - iAnimEval(data->RawData[biindex[0] + biindex[1] * data->NumAnims[0]], time, flags, tran, - quat); - iAnimEval(data->RawData[biplus[0] + biindex[1] * data->NumAnims[0]], time, flags, t0, - q0); - iAnimBlend(bilerp[0], 1.0f, NULL, NULL, numBones, tran, quat, t0, q0, tran, quat); - } - else if (bilerp[1]) - { - iAnimEval(data->RawData[biindex[0] + biindex[1] * data->NumAnims[0]], time, flags, tran, - quat); - iAnimEval(data->RawData[biindex[0] + biplus[1] * data->NumAnims[0]], time, flags, t0, - q0); - iAnimBlend(bilerp[0], 1.0f, NULL, NULL, numBones, tran, quat, t0, q0, tran, quat); - } - else - { - iAnimEval(data->RawData[biindex[0] + biindex[1] * data->NumAnims[0]], time, flags, tran, - quat); - } - } - else - { - iAnimEval(data->RawData[0], time, flags, tran, quat); - } -} - -#ifndef INLINE -float std::floorf(float x) -{ - return (float)floor((double)x); -} -#endif - -xAnimEffect* xAnimStateNewEffect(xAnimState* state, U32 flags, F32 startTime, F32 endTime, - xAnimEffectCallback callback, U32 userDataSize) -{ - xAnimEffect* curr; - xAnimEffect** prev; - xAnimEffect* effect; - - effect = - (gxAnimUseGrowAlloc ? (xAnimEffect*)xMemGrowAllocSize(userDataSize + sizeof(xAnimEffect)) : - (xAnimEffect*)xMemAllocSize(userDataSize + sizeof(xAnimEffect))); - - effect->Flags = flags; - effect->StartTime = startTime; - effect->EndTime = endTime; - effect->Callback = callback; - - prev = &state->Effects; - curr = state->Effects; - - while (curr && startTime > curr->StartTime) - { - prev = &curr->Next; - curr = curr->Next; - } - - effect->Next = curr; - *prev = effect; - - return effect; -} - -xAnimTable* xAnimTableNew(const char* name, xAnimTable** linkedList, U32 userFlags) -{ - xAnimTable* table; - - table = (xAnimTable*)xMemAllocSize(sizeof(xAnimTable)); - - if (linkedList) - { - table->Next = *linkedList; - *linkedList = table; - } - else - { - table->Next = NULL; - } - - table->Name = name; - table->TransitionList = NULL; - table->StateList = NULL; - table->AnimIndex = NULL; - table->MorphIndex = NULL; - table->UserFlags = userFlags; - - return table; -} - -void xAnimDefaultBeforeEnter(xAnimPlay* play, xAnimState* state) -{ - U32 entry; - - if (state->MultiFile) - { - entry = rand() % state->MultiFile->Count; - - state->Data = state->MultiFile->Files[entry].File; - } -} - -xAnimState* xAnimTableNewState(xAnimTable* table, const char* name, U32 flags, U32 userFlags, - F32 speed, F32* boneBlend, F32* timeSnap, F32 fadeRecip, - U16* fadeOffset, void* callbackData, - xAnimStateBeforeEnterCallback beforeEnter, - xAnimStateCallback stateCallback, - xAnimStateBeforeAnimMatricesCallback beforeAnimMatrices) -{ - xAnimState* state; - - state = (gxAnimUseGrowAlloc ? (xAnimState*)xMemGrowAllocSize(sizeof(xAnimState)) : - (xAnimState*)xMemAllocSize(sizeof(xAnimState))); - - if (!table->StateList) - { - state->Next = NULL; - table->StateList = state; - } - else - { - state->Next = table->StateList->Next; - table->StateList->Next = state; - } - - state->Name = name; - state->ID = xStrHash(name); - state->Flags = flags; - state->UserFlags = userFlags; - state->Speed = speed; - state->Data = NULL; - state->Effects = NULL; - state->Default = NULL; - state->List = NULL; - state->BoneBlend = boneBlend; - state->TimeSnap = timeSnap; - state->FadeRecip = (fadeOffset ? CalcRecipBlendMax(fadeOffset) : fadeRecip); - state->FadeOffset = fadeOffset; - state->MultiFile = NULL; - state->CallbackData = callbackData; - state->BeforeEnter = beforeEnter; - state->StateCallback = stateCallback; - state->BeforeAnimMatrices = beforeAnimMatrices; - - return state; -} - -static void _xAnimTableAddTransitionHelper(xAnimState* state, xAnimTransition* tran, - U32& stateCount, U32& allocCount, xAnimState** stateList) -{ - if (tran->Flags & 0x10) - { - if (!DefaultHasTransition(state, tran, &stateCount)) - { - stateList[allocCount] = state; - allocCount++; - } - } - else - { - if (!StateHasTransition(state, tran)) - { - stateList[allocCount] = state; - allocCount++; - stateCount++; - } - } -} - -// WIP -void _xAnimTableAddTransition(xAnimTable* table, xAnimTransition* tran, const char* source, - const char* dest) -{ - // unsigned char * buffer; // r29+0x110 - // class xAnimState * * stateList; // r29+0x100 - // unsigned int i; // r4 - // unsigned int stateCount; // r30 - // unsigned int allocCount; // r21 - // char * stateName; // r29+0xFC - // class xAnimTransitionList * tlist; // r29+0xE0 - // class xAnimTransition * substTransitionList[32]; // r29+0x230 - // unsigned int substTransitionCount; // r29+0xD0 - // unsigned char hasSubst; // r29+0xC0 - // signed int i; // r5 - // unsigned char isComplex; // r8 - // char * COMPLEX_PATTERNS; // r7 - // char * search; // r6 - // class xAnimState * state; // r23 - // char extra[128]; // r29+0x1B0 - // char tempName[128]; // r29+0x130 - // char * tempIterator; // r19 - // char * extraIterator; // r18 - // unsigned char allowMissingState; // r29+0xB0 - // signed int i; // r17 - // unsigned int extraIteratorLength; // r16 - // class xAnimTransition * duplicatedTransition; // r17 - // class xAnimTransitionList * curr; // r7 - - U8* buffer = (U8*)giAnimScratch; - xAnimState** stateList = (xAnimState**)(giAnimScratch + 0x400); - S32 i; - U32 stateCount = 0; - U32 allocCount = 0; - - xAnimTransitionList* tlist; - xAnimTransition* substTransitionList[32]; - - char extra[128]; - char tempName[128]; - - U8 bVar2 = false; - U8 bVar1 = false; - S32 iVar12 = 0; - - if (dest != NULL) - { - for (S32 i = 0; dest[i] != NULL; ++i) - { - if (dest[i] == '@' || dest[i] == '~') - { - bVar2 = true; - break; - } - } - } - - for (char* x = xStrTokBuffer(source, " ,\t\n\r", table); x != NULL; - x = xStrTokBuffer(source, " ,\t\n\r", table)) - { - bVar1 = dest != NULL; - if (!bVar1) - { - for (char* it = x; *it != NULL; ++it) - { - if (_xCharIn(*it, "#+*?{}()<>|;") != 0) - { - bVar1 = true; - break; - } - } - } - - if (bVar1) - { - for (xAnimState* state = table->StateList; state != NULL; state = state->Next) - { - if (_xCheckAnimName(state->Name, x, tempName)) - { - if (bVar2) - { - for (const char* tempIterator = dest; *tempIterator != NULL; ++tempIterator) - { - if (*dest == '@' || *dest == '~') - { - bVar1 = *dest == '~'; - U32 l = strlen(tempName); - strcpy(extra, tempName); - } - else - { - *extra = *dest; - } - } - *extra = NULL; - xAnimState* sp = xAnimTableGetState(table, extra); - if (bVar1 && sp == NULL) - { - continue; - } - - xAnimTransition* duplicatedTransition = tran; - if (iVar12 != 0) - { - if (gxAnimUseGrowAlloc) - { - duplicatedTransition = (xAnimTransition*)xMemGrowAlloc( - gActiveHeap, sizeof(xAnimTransition)); - } - else - { - duplicatedTransition = (xAnimTransition*)xMemAlloc( - gActiveHeap, sizeof(xAnimTransition), 0); - } - memcpy(duplicatedTransition, tran, sizeof(xAnimTransition)); - } - duplicatedTransition->Dest = sp; - iVar12++; - substTransitionList[iVar12] = duplicatedTransition; - } - if (tran->Dest != state) - { - _xAnimTableAddTransitionHelper(state, tran, stateCount, allocCount, - stateList); - } - } - } - } - else - { - xAnimState* ssp = xAnimTableGetState(table, x); - if (ssp != NULL && tran->Dest != ssp) - { - _xAnimTableAddTransitionHelper(ssp, tran, stateCount, allocCount, stateList); - } - } - } - - xAnimTransitionList* curr; - if (stateCount != 0) - { - if (gxAnimUseGrowAlloc) - { - curr = (xAnimTransitionList*)xMemGrowAlloc(gActiveHeap, - stateCount * sizeof(xAnimTransitionList)); - } - else - { - curr = (xAnimTransitionList*)xMemAlloc(gActiveHeap, - stateCount * sizeof(xAnimTransitionList), 0); - } - } - if (tran->Flags & 0x10) - { - for (S32 i = 0; i < allocCount; ++i) - { - if (DefaultOverride(stateList[i], tran) == 0) - { - if (tran->Conditional == NULL && stateList[i]->Default != NULL) - { - curr->Next = NULL; - curr->T = bVar2 ? substTransitionList[i] : tran; - } - } - else - { - curr->T = bVar2 ? substTransitionList[i] : tran; - stateList[i]->Default = curr; - } - } - } - else - { - if (bVar2) - { - for (S32 i = 0; i < allocCount; ++i) - { - curr->T = substTransitionList[i]; - curr->Next = stateList[i]->List->Next; - } - } - else - { - for (S32 i = 0; i < allocCount; ++i) - { - curr->T = tran; - curr->Next = stateList[i]->List->Next; - } - } - } -} - -void xAnimTableAddTransition(xAnimTable* table, xAnimTransition* tran, const char* source) -{ - _xAnimTableAddTransition(table, tran, source, NULL); -} - -xAnimTransition* xAnimTableNewTransition(xAnimTable* table, const char* source, const char* dest, - xAnimTransitionConditionalCallback conditional, - xAnimTransitionCallback callback, U32 flags, U32 userFlags, - F32 srcTime, F32 destTime, U16 priority, U16 queuePriority, - F32 blendRecip, U16* blendOffset) -{ - xAnimTransition* tran; - if (gxAnimUseGrowAlloc) - { - tran = (xAnimTransition*)xMemGrowAllocSize(sizeof(xAnimTransition)); - } - else - { - tran = (xAnimTransition*)xMemAllocSize(sizeof(xAnimTransition)); - } - - if (blendRecip != 0.0f) - { - blendRecip = 1.0f / blendRecip; - } - - tran->Next = table->TransitionList; - table->TransitionList = tran; - - U8 isComplex = FALSE; - if (dest == NULL || *dest == NULL) - { - tran->Dest = NULL; - } - else - { - for (S32 i = 0; dest[i] != NULL; ++i) - { - if (dest[i] == '@' || dest[i] == '~') - { - isComplex = true; - break; - } - } - tran->Dest = isComplex ? NULL : xAnimTableGetState(table, dest); - } - - tran->Conditional = conditional; - tran->Callback = callback; - tran->Flags = flags; - tran->UserFlags = userFlags; - tran->SrcTime = srcTime; - tran->DestTime = destTime; - tran->Priority = priority; - tran->QueuePriority = queuePriority; - - tran->BlendRecip = blendOffset != NULL ? CalcRecipBlendMax(blendOffset) : blendRecip; - tran->BlendOffset = blendOffset; - - _xAnimTableAddTransition(table, tran, source, isComplex ? dest : NULL); - - return tran; -} - -void xAnimTableAddFile(xAnimTable* table, xAnimFile* file, const char* states) -{ - U8* buffer = (U8*)giAnimScratch; - char* stateName = xStrTokBuffer(states, " ,\t\n\r", buffer); - while (stateName != NULL) - { - xAnimTableAddFileID(table, file, xStrHash(stateName), 0, 0); - stateName = xStrTokBuffer(NULL, " ,\t\n\r", buffer); - } -} - -xAnimState* xAnimTableGetStateID(xAnimTable* table, U32 ID); - -xAnimState* xAnimTableAddFileID(xAnimTable* table, xAnimFile* file, U32 stateID, U32 subStateID, - U32 subStateCount) -{ - xAnimState* state; - - state = xAnimTableGetStateID(table, stateID); - - if (state) - { - if (subStateID) - { - if (!state->MultiFile) - { - state->MultiFile = - (gxAnimUseGrowAlloc ? (xAnimMultiFile*)xMemGrowAllocSize( - subStateCount * sizeof(xAnimMultiFileEntry) + - sizeof(xAnimMultiFileBase)) : - (xAnimMultiFile*)xMemAllocSize( - subStateCount * sizeof(xAnimMultiFileEntry) + - sizeof(xAnimMultiFileBase))); - - state->MultiFile->Count = 0; - } - - U32 count = state->MultiFile->Count; - - state->MultiFile->Files[count].ID = subStateID; - state->MultiFile->Files[count].File = file; - - state->MultiFile->Count++; - } - - state->Data = file; - - if (file->FileFlags & 0x8000) - { - table->MorphIndex |= (1 << (state->Flags & 0xF)); - } - else - { - table->AnimIndex |= (1 << (state->Flags & 0xF)); - } - } - - return state; -} - -xAnimState* xAnimTableGetStateID(xAnimTable* table, U32 ID) -{ - xAnimState* curr; - - curr = table->StateList; - - while (curr) - { - if (curr->ID == ID) - { - return curr; - } - - curr = curr->Next; - } - - return NULL; -} - -xAnimState* xAnimTableGetState(xAnimTable* table, const char* name) -{ - return xAnimTableGetStateID(table, xStrHash(name)); -} - -static void EffectActiveInsert(xAnimSingle* single, xAnimActiveEffect* active) -{ - U32 index = 0; - U32 count = single->ActiveCount; - xAnimActiveEffect* curr = &single->ActiveList[0]; - - while (index < count && curr->Effect) - { - curr++; - index++; - } - - *curr = *active; - - if (index < count - 1) - { - (curr + 1)->Effect = NULL; - } -} - -static void EffectActiveRemove(xAnimActiveEffect* active, U32 index, U32 count) -{ - count--; - - if (index == count || !(active + 1)->Effect) - { - active->Effect = NULL; - } - else - { - xAnimActiveEffect* curr = active; - - while (index < count && (curr + 1)->Effect) - { - curr++; - index++; - } - - *active = *curr; - curr->Effect = NULL; - } -} - -static U32 EffectPlaying(xAnimSingle* single, xAnimEffect* effect) -{ - U32 index = 0; - - while (index < single->ActiveCount && single->ActiveList[index].Effect) - { - if (single->ActiveList[index].Effect == effect) - { - return TRUE; - } - - index++; - } - - return FALSE; -} - -static void EffectSingleStart(xAnimSingle* single) -{ - xAnimEffect* effect = single->State->Effects; - xAnimActiveEffect tempActive; - F32 time = single->Time; - U32 flags; - - while (effect && effect->StartTime < time) - { - flags = effect->Flags; - - if (flags & 0x1) - { - if (flags & 0x4) - { - tempActive.Effect = effect; - tempActive.Handle = effect->Callback(1, &tempActive, single, single->Play->Object); - - flags = effect->Flags; - - if (flags & 0x2) - { - if (effect->EndTime <= time) - { - effect->Callback(3, &tempActive, single, single->Play->Object); - } - else - { - EffectActiveInsert(single, &tempActive); - } - } - else if (flags & 0x20) - { - EffectActiveInsert(single, &tempActive); - } - } - else if ((flags & 0x2) && !(flags & 0x10) && effect->EndTime > time) - { - tempActive.Effect = effect; - tempActive.Handle = effect->Callback(1, &tempActive, single, single->Play->Object); - - EffectActiveInsert(single, &tempActive); - } - } - - effect = effect->Next; - } - - single->Effect = effect; -} - -static void EffectSingleDuration(xAnimSingle* single) -{ - F32 time = single->Time; - xAnimActiveEffect* alist = single->ActiveList; - U32 index = 0; - U32 count = single->ActiveCount; - - while (index < count && alist->Effect) - { - if (!(alist->Effect->Flags & 0x20) && alist->Effect->EndTime <= time) - { - alist->Effect->Callback(3, alist, single, single->Play->Object); - - EffectActiveRemove(alist, index, count); - } - else - { - alist->Effect->Callback(2, alist, single, single->Play->Object); - - alist++; - index++; - } - } -} - -static void EffectSingleRun(xAnimSingle* single) -{ - xAnimEffect* effect = single->Effect; - xAnimActiveEffect tempActive; - F32 time = single->Time; - U32 flags; - - while (effect && effect->StartTime <= time) - { - flags = effect->Flags; - - if ((flags & 0x1) && (!(flags & 0x20) || !EffectPlaying(single, effect))) - { - tempActive.Effect = effect; - tempActive.Handle = effect->Callback(1, &tempActive, single, single->Play->Object); - - if (flags & 0x2) - { - if (effect->EndTime <= time) - { - effect->Callback(3, &tempActive, single, single->Play->Object); - } - else - { - EffectActiveInsert(single, &tempActive); - } - } - else if (flags & 0x20) - { - EffectActiveInsert(single, &tempActive); - } - } - - effect = effect->Next; - } - - single->Effect = effect; -} - -static void EffectSingleLoop(xAnimSingle* single) -{ - EffectSingleRun(single); - xAnimActiveEffect* alist = single->ActiveList; - U32 index = 0; - U32 count = single->ActiveCount; - while (index < count && alist[index].Effect != NULL) - { - if (!(alist[index].Effect->Flags & 0x20)) - { - alist[index].Effect->Callback(3, &alist[index], single, single->Play->Object); - - EffectActiveRemove(&alist[index], index, count); - } - else - { - index++; - } - } - - xAnimEffect* effect = single->State->Effects; - while (effect != NULL && effect->StartTime < 0.0f) - { - effect = effect->Next; - } - single->Effect = effect; -} - -static void EffectSingleStop(xAnimSingle* single) -{ - if (single->State == NULL || single->LastTime == -1.0f) - { - return; - } - - for (U32 i = 0; single->ActiveCount > i && single->ActiveList[i].Effect != NULL; ++i) - { - if (single->ActiveList[i].Effect->Flags & 0x2) - { - single->ActiveList[i].Effect->Callback(3, &single->ActiveList[i], single, - single->Play->Object); - } - } - - single->ActiveList->Effect = NULL; - for (xAnimEffect* effect = single->Effect; effect != NULL; effect = effect->Next) - { - xAnimActiveEffect tempActive; - if ((effect->Flags & 0x9) == 0x9) - { - tempActive.Effect = effect; - tempActive.Handle = effect->Callback(1, &tempActive, single, single->Play->Object); - - if (effect->Flags & 0x2) - { - effect->Callback(3, &tempActive, single, single->Play->Object); - } - } - } - - single->Effect = NULL; -} - -static void StopUpdate(xAnimSingle* single) -{ - if (single->Time > single->State->Data->Duration) - { - single->Time = single->State->Data->Duration; - single->CurrentSpeed = 0.0f; - } -} - -static void LoopUpdate(xAnimSingle* single) -{ - F32 time = single->Time; - F32 duration = single->State->Data->Duration; - - if (time > duration) - { - single->Time = duration; - - EffectSingleLoop(single); - - single->Time = time - duration; - } -} - -void xAnimPlaySetState(xAnimSingle* single, xAnimState* state, F32 startTime) -{ - EffectSingleStop(single); - if (single->Blend) - { - EffectSingleStop(single->Blend); - single->Blend->State = NULL; - } - - single->State = state; - if (state == NULL) - { - return; - } - - single->Time = - (state->Flags & 0x100 && startTime == 0.0f) ? state->Data->Duration * xurand() : startTime; - single->CurrentSpeed = state->Speed; - single->BilinearLerp[0] = 0.0f; - single->BilinearLerp[1] = 0.0f; - single->Effect = NULL; - memset(single->ActiveList, 0, single->ActiveCount * sizeof(xAnimActiveEffect)); - single->LastTime = -1.0f; - single->Sync = NULL; - - if (single->Tran != NULL && single->Tran->Flags & 0x2) - { - xMemPoolFree(&sxAnimTempTranPool, single->Tran); - } - - single->Tran = NULL; - single->BlendFactor = 0.0f; -} - -static void SingleUpdate(xAnimSingle* single, F32 timeDelta) -{ - U32 foundBlendstop = 0; - U32 firstStep = 1; - xAnimTransition* foundTransition = NULL; - xAnimSingle* bl = NULL; - F32 tranDelta = 0.0f; - F32 blendDelta = 0.0f; - F32 singleTime; - if (single->State == NULL) - { - return; - } - - void* object = single->Play->Object; - if (single->LastTime == -1.0f) - { - EffectSingleStart(single); - } - - single->LastTime = single->Time; - singleTime = timeDelta * single->CurrentSpeed + single->Time; - - if (single->Blend != NULL && single->Blend->State != NULL) - { - bl = single->Blend; - if (bl->LastTime == -1.0f) - { - EffectSingleStart(bl); - } - bl->LastTime = bl->Time; - } - - F32 duration = single->State->Data->Duration; - if (single->Sync != NULL) - { - // FIXME: assignment in the loop seems unlikely but assigning at the - // declaration swaps instructions. - F32 timeCmp; - if ((timeCmp = single->Sync->SrcTime) != 0.0f) - { - if (timeCmp > duration) - { - timeCmp = duration; - } - if (single->LastTime <= timeCmp && singleTime >= timeCmp) - { - foundTransition = single->Sync; - tranDelta = (singleTime - timeCmp) / single->CurrentSpeed; - timeDelta = timeDelta - tranDelta; - if (timeDelta < 0.0f) - { - timeDelta = 0.0f; - } - } - else - { - timeCmp += duration; - if (single->LastTime <= timeCmp && singleTime >= timeCmp) - { - foundTransition = single->Sync; - tranDelta = (singleTime - timeCmp) / single->CurrentSpeed; - timeDelta = timeDelta - tranDelta; - if (timeDelta < 0.0f) - { - timeDelta = 0.0f; - } - } - } - } - else if (bl == NULL) - { - foundTransition = single->Sync; - tranDelta = timeDelta; - timeDelta = 0.0f; - } - } - else - { - if ((single->State->Flags & 0x30) == 0x20) - { - F32 timeCmp = single->State->Default->T->SrcTime; - - if (timeCmp == 0.0f || timeCmp > duration) - { - timeCmp = duration; - } - - if (singleTime >= timeCmp && - ((single->State->Default->T->Flags & 0x4) == 0 || bl == NULL)) - { - xAnimTransitionList* curr = single->State->Default; - while (curr != NULL && curr->T->Conditional != NULL && - curr->T->Conditional(curr->T, single, object) == 0) - { - curr = curr->Next; - } - - if (curr == NULL) - { - fprintf(stderr, "State \"%s\" no default conditionals true!\n", - single->State->Name); - curr = single->State->Default; - } - - foundTransition = curr->T; - if (single->LastTime < timeCmp) - { - tranDelta = (singleTime - timeCmp) / single->CurrentSpeed; - timeDelta = timeDelta - tranDelta; - if (timeDelta < 0.0f) - { - timeDelta = 0.0f; - } - } - else - { - tranDelta = timeDelta; - timeDelta = 0.0f; - } - } - } - } - - if (single->BlendFactor != 0.0f) - { - F32 recip; - if (single->Tran != NULL) - { - recip = single->Tran->BlendRecip; - } - else - { - recip = single->State->FadeRecip; - } - - if (recip * (single->BlendFactor + timeDelta) > 1.0f) - { - foundBlendstop = 1; - blendDelta = (single->BlendFactor + timeDelta) - (1.0f / recip); - timeDelta = timeDelta - blendDelta; - if (timeDelta < 0.0f) - { - timeDelta = 0.0f; - } - if (blendDelta < 0.0f) - { - blendDelta = 0.01f; - } - } - } - - do - { - if (!firstStep) - { - if (foundBlendstop) - { - single->BlendFactor = 0.0f; - if (bl != NULL) - { - EffectSingleStop(bl); - bl->State = NULL; - bl = NULL; - - if (single->Tran != NULL && single->Tran->Flags & 0x2) - { - xMemPoolFree(&sxAnimTempTranPool, single->Tran); - } - single->Tran = NULL; - } - else - { - if (single->Tran != NULL) - { - if (single->Tran != NULL && single->Tran->Flags & 0x2) - { - xMemPoolFree(&sxAnimTempTranPool, single->Tran); - } - single->Tran = NULL; - } - else - { - EffectSingleStop(single); - single->State = NULL; - return; - } - } - timeDelta = blendDelta; - foundBlendstop = FALSE; - } - else - { - if (bl != NULL) - { - EffectSingleStop(bl); - bl->State = NULL; - bl = NULL; - single->BlendFactor = 0.0f; - } - if (foundTransition->BlendRecip == 0.0f || single->Blend == NULL) - { - EffectSingleStop(single); - if (single->Tran != NULL && single->Tran->Flags & 0x2) - { - xMemPoolFree(&sxAnimTempTranPool, single->Tran); - } - single->Tran = NULL; - } - else - { - bl = single->Blend; - bl->State = single->State; - bl->Time = single->Time; - bl->CurrentSpeed = single->CurrentSpeed; - bl->BilinearLerp[0] = single->BilinearLerp[0]; - bl->BilinearLerp[1] = single->BilinearLerp[1]; - bl->Effect = single->Effect; - bl->LastTime = single->LastTime; - memcpy(bl->ActiveList, single->ActiveList, - single->ActiveCount * sizeof(xAnimTransitionList)); - single->ActiveList->Effect = NULL; - - if (single->Tran != NULL && single->Tran->Flags & 0x2) - { - xMemPoolFree(&sxAnimTempTranPool, single->Tran); - } - single->Tran = foundTransition; - single->BlendFactor = 0.0000001f; - } - - TransitionTimeInit(single, foundTransition); - single->State = foundTransition->Dest; - single->CurrentSpeed = single->State->Speed; - single->BilinearLerp[0] = 0.0f; - single->BilinearLerp[1] = 0.0f; - single->Sync = NULL; - EffectSingleStart(single); - - if (foundTransition->Dest->BeforeEnter != NULL) - { - foundTransition->Dest->BeforeEnter(single->Play, foundTransition->Dest); - } - if (foundTransition->Callback != NULL) - { - foundTransition->Callback(foundTransition, single, single->Play->Object); - } - timeDelta = tranDelta; - foundTransition = NULL; - } - } - - single->Time = timeDelta * single->CurrentSpeed + single->Time; - if (single->BlendFactor != 0.0f) - { - single->BlendFactor += timeDelta; - } - if ((single->State->Flags & 0x30) == 0x10) - { - LoopUpdate(single); - } - else - { - StopUpdate(single); - } - EffectSingleRun(single); - - if (bl != NULL) - { - if ((bl->State->Flags & 0x30) == 0x10) - { - LoopUpdate(bl); - } - else - { - StopUpdate(bl); - } - EffectSingleRun(bl); - } - - firstStep = FALSE; - } while (foundBlendstop || foundTransition != NULL); - - if (single->Tran == NULL && single->BlendFactor == 0.0f) - { - if ((single->State->Flags & 0x30) == 0x30) - { - if (single->State->Flags & 0x200) - { - if (single->Time >= duration) - { - single->BlendFactor = 0.0000001f; - } - } - else if (single->State->FadeRecip * (duration - single->Time) < 1.0f) - { - single->BlendFactor = 0.0000001f; - } - } - } - EffectSingleDuration(single); - if (bl != NULL) - { - EffectSingleDuration(bl); - } -} - -static void SingleEval(xAnimSingle* single, xVec3* tran, xQuat* quat) -{ - if (single->Play->BoneCount > 1) - { - xAnimFileEval(single->State->Data, single->Time, single->BilinearLerp, 0x2, tran + 1, - quat + 1, NULL); - - if (single->Blend && single->Blend->State) - { - xQuat* qbuf = (xQuat*)(giAnimScratch + 0xE40); - xVec3* vbuf = (xVec3*)(qbuf + 0x41); - - xAnimFileEval(single->Blend->State->Data, single->Blend->Time, - single->Blend->BilinearLerp, 0x2, vbuf, qbuf, NULL); - - iAnimBlend(single->BlendFactor, single->Tran->BlendRecip, single->Tran->BlendOffset, - NULL, single->Play->BoneCount - 1, vbuf, qbuf, tran + 1, quat + 1, tran + 1, - quat + 1); - } - } -} - -void xAnimPlaySetup(xAnimPlay* play, void* object, xAnimTable* table, xModelInstance* modelInst) -{ - play->BoneCount = modelInst->BoneCount; - play->Object = object; - play->Table = table; - play->ModelInst = modelInst; - - modelInst->Anim = play; - modelInst->Flags |= 0x104; - - if (table->MorphIndex != 0) - { - modelInst->Flags |= 0x80; - } - - for (S32 i = 0; i < play->NumSingle; ++i) - { - play->Single[i].SingleFlags = (1 << i & table->MorphIndex) ? 0x8000 : 0x1; - play->Single[i].State = NULL; - play->Single[i].Tran = NULL; - if (play->Single[i].Blend != NULL) - { - play->Single[i].Blend->State = NULL; - } - } - xAnimPlaySetState(play->Single, table->StateList, 0.0f); -} - -void xAnimPlayChooseTransition(xAnimPlay* play) -{ - U32 i; - void* object = play->Object; - xAnimTransition** list = (xAnimTransition**)giAnimScratch; - xAnimTransition** found; - xAnimTransitionList* curr; - - memset(list, 0, play->NumSingle * sizeof(xAnimTransition*)); - - for (i = 0; i < play->NumSingle; i++) - { - if (play->Single[i].State) - { - curr = play->Single[i].State->List; - - if (curr && curr->T->Conditional) - { - while (curr) - { - if (curr->T->Conditional(curr->T, &play->Single[i], object)) - { - found = &list[curr->T->Dest->Flags & 0xF]; - - if (!*found || curr->T->Priority > (*found)->Priority) - { - *found = curr->T; - } - } - - curr = curr->Next; - } - } - } - } - - for (i = 0; i < play->NumSingle; i++) - { - if (list[i] && - (!play->Single[i].Sync || list[i]->Priority > play->Single[i].Sync->QueuePriority)) - { - xAnimPlayStartTransition(play, list[i]); - } - } -} - -void xAnimPlayStartTransition(xAnimPlay* play, xAnimTransition* transition) -{ - xAnimSingle* single = &play->Single[transition->Dest->Flags & 0xf]; - xAnimSingle* bl = single->Blend; - - if (transition->SrcTime != 0.0f || (transition->Flags & 0x4 && bl != NULL && bl->State)) - { - single->Sync = transition; - return; - } - - if (bl != NULL && bl->State != NULL) - { - EffectSingleStop(bl); - bl->State = NULL; - single->BlendFactor = 0.0f; - } - - if (transition->BlendRecip == 0.0f || single->Blend == NULL) - { - EffectSingleStop(single); - if (single->Tran != NULL && single->Tran->Flags & 0x2) - { - xMemPoolFree(&sxAnimTempTranPool, single->Tran); - } - single->Tran = NULL; - } - else - { - if (single->State != NULL) - { - bl->State = single->State; - bl->Time = single->Time; - bl->CurrentSpeed = single->CurrentSpeed; - bl->BilinearLerp[0] = single->BilinearLerp[0]; - bl->BilinearLerp[1] = single->BilinearLerp[1]; - bl->Effect = single->Effect; - - bl->LastTime = single->LastTime; - - memcpy(bl->ActiveList, single->ActiveList, - single->ActiveCount * sizeof(xAnimActiveEffect)); - single->ActiveList[0].Effect = NULL; - } - - if (single->Tran != NULL && single->Tran->Flags & 0x2) - { - xMemPoolFree(&sxAnimTempTranPool, single->Tran); - } - single->Tran = transition; - single->BlendFactor = 0.0000001f; - } - - TransitionTimeInit(single, transition); - single->State = transition->Dest; - single->CurrentSpeed = single->State->Speed; - single->BilinearLerp[0] = 0.0f; - single->BilinearLerp[1] = 0.0f; - single->Sync = NULL; - EffectSingleStart(single); - - if (transition->Dest->BeforeEnter != NULL) - { - transition->Dest->BeforeEnter(play, transition->Dest); - } - - if (transition->Callback != NULL) - { - transition->Callback(transition, single, single->Play->Object); - } -} - -void xAnimPlayUpdate(xAnimPlay* play, F32 timeDelta) -{ - U32 i; - xAnimSingle* single; - - for (i = 0; i < play->NumSingle; i++) - { - single = &play->Single[i]; - - SingleUpdate(single, timeDelta); - - if (single->State->StateCallback) - { - single->State->StateCallback(single->State, single, play->Object); - } - } -} - -void xAnimPlayEval(xAnimPlay* play) -{ - U32 i; - U32 bone; - xQuat* quatresult = (xQuat*)giAnimScratch; - xVec3* tranresult = (xVec3*)((U8*)quatresult + 0x410); - - if (play->BoneCount > 1) - { - xQuat* quatblend = (xQuat*)((U8*)quatresult + 0x720); - xVec3* tranblend = (xVec3*)((U8*)quatblend + 0x410); - SingleEval(play->Single, tranresult, (xQuat*)giAnimScratch); - for (i = 1; i < play->NumSingle; ++i) - { - xAnimSingle* si = &play->Single[i]; - if (si->State == NULL || si->SingleFlags & 0x8000) - { - continue; - } - F32 blendF = 1.0f; - F32 blendR = 1.0f; - U16* blendO = NULL; - SingleEval(si, tranblend, quatblend); - - if ((si->Blend == NULL || si->Blend->State == NULL) && si->BlendFactor) - { - if (si->Tran != NULL) - { - blendF = si->BlendFactor; - blendR = si->Tran->BlendRecip; - blendO = si->Tran->BlendOffset; - } - else - { - blendF = -si->BlendFactor; - blendR = si->State->FadeRecip; - blendO = si->State->FadeOffset; - } - } - - if ((si->SingleFlags & 0x3) == 2) - { - iAnimBlend(blendF, blendR, blendO, si->State->BoneBlend, play->BoneCount - 1, - tranblend + 1, quatblend + 1, NULL, NULL, tranblend + 1, quatblend + 1); - - for (bone = 1; bone < play->BoneCount; ++bone) - { - tranresult[bone].x += tranblend[bone].x; - tranresult[bone].y += tranblend[bone].y; - tranresult[bone].z += tranblend[bone].z; - xQuatMul(&quatresult[bone], &quatresult[bone], &quatblend[bone]); - } - } - else - { - iAnimBlend(blendF, blendR, blendO, si->State->BoneBlend, play->BoneCount - 1, - tranresult + 1, quatresult + 1, tranblend + 1, quatblend + 1, - tranresult + 1, quatresult + 1); - } - } - } - memset(tranresult, 0, sizeof(xVec3)); - memset(quatresult, 0, sizeof(xQuat)); - if (play->Single->State->BeforeAnimMatrices != NULL) - { - play->Single->State->BeforeAnimMatrices(play, quatresult, tranresult, play->BoneCount); - } - - if (play->BeforeAnimMatrices != NULL) - { - play->BeforeAnimMatrices(play, quatresult, tranresult, play->BoneCount); - } - iModelAnimMatrices(play->ModelInst->Data, quatresult, tranresult, &play->ModelInst->Mat[1]); -} - -void xAnimPoolCB(xMemPool* pool, void* data) -{ - S32 i; - xAnimPlay* clone = (xAnimPlay*)data; - xAnimPlay* play = (xAnimPlay*)pool->Buffer; - xAnimSingle* clonesingle = (xAnimSingle*)(clone + 1); - xAnimSingle* currsingle; - xAnimActiveEffect* curract; - - clone->NumSingle = play->NumSingle; - clone->Single = clonesingle; - - clonesingle += play->NumSingle; - - for (i = 0; i < play->NumSingle; i++) - { - clone->Single[i].Play = clone; - - if (play->Single[i].Blend) - { - clone->Single[i].Blend = clonesingle; - - clonesingle->Blend = NULL; - clonesingle->Play = clone; - - clonesingle++; - } - else - { - clone->Single[i].Blend = NULL; - } - } - - curract = (xAnimActiveEffect*)clonesingle; - - for (i = 0; i < clone->NumSingle; i++) - { - clonesingle = &clone->Single[i]; - currsingle = &play->Single[i]; - - while (clonesingle) - { - clonesingle->ActiveCount = currsingle->ActiveCount; - - if (currsingle->ActiveCount) - { - clonesingle->ActiveList = curract; - - curract += currsingle->ActiveCount; - } - else - { - clonesingle->ActiveList = NULL; - } - - currsingle = currsingle->Blend; - clonesingle = clonesingle->Blend; - } - } - - clone->Pool = pool; -} - -#define ADD_4_BITS(x) (((x) & 1) + (((x) >> 1) & 1) + (((x) >> 2) & 1) + (((x) >> 3) & 1)) -void xAnimPoolInit(xMemPool* pool, U32 count, U32 singles, U32 blendFlags, U32 effectMax) -{ - effectMax += effectMax & 1; - - U32 size = - (effectMax * sizeof(xAnimActiveEffect) + sizeof(xAnimSingle)) * - (ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0x0)) + - ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0x4)) + - ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0x8)) + - ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0xC)) + singles) + - sizeof(xAnimPlay); - - U32 i; - void* buffer = xMemAllocSize(count * size); - - xAnimPlay* play = (xAnimPlay*)buffer; - play->NumSingle = singles; - - xAnimSingle* currsingle; - play->Single = currsingle = (xAnimSingle*)((U32)play + sizeof(xAnimPlay)); - currsingle += singles; - - for (i = 0; i < singles; ++i) - { - if (blendFlags & (1 << i)) - { - play->Single[i].Blend = currsingle; - currsingle->Blend = NULL; - currsingle++; - } - else - { - play->Single[i].Blend = NULL; - } - } - - xAnimActiveEffect* curract = (xAnimActiveEffect*)currsingle; - for (i = 0; i < play->NumSingle; ++i) - { - currsingle = &play->Single[i]; - while (currsingle) - { - currsingle->ActiveCount = effectMax; - if (effectMax != 0) - { - currsingle->ActiveList = curract; - curract += effectMax; - } - else - { - currsingle->ActiveList = NULL; - } - - currsingle = currsingle->Blend; - } - } - - play->Pool = pool; - xMemPoolSetup(pool, buffer, 0, 1, xAnimPoolCB, size, count, count / 2); -} - -xAnimPlay* xAnimPoolAlloc(xMemPool* pool, void* object, xAnimTable* table, - xModelInstance* modelInst) -{ - xAnimPlay* play; - - play = (xAnimPlay*)xMemPoolAlloc(pool); - - xAnimPlaySetup(play, object, table, modelInst); - - return play; -} - -void xAnimPoolFree(xAnimPlay* play) -{ - U32 i; - - for (i = 0; i < play->NumSingle; i++) - { - EffectSingleStop(&play->Single[i]); - - if (play->Single[i].Blend) - { - EffectSingleStop(play->Single[i].Blend); - } - } - - xMemPoolFree(play->Pool, play); -} diff --git a/src/SB/Core/x/xBase.cpp b/src/SB/Core/x/xBase.cpp deleted file mode 100644 index 59f9531..0000000 --- a/src/SB/Core/x/xBase.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "xBase.h" - -void xBaseInit(xBase* xb, xBaseAsset* asset) -{ - xb->id = asset->id; - xb->baseType = asset->baseType; - xb->baseFlags = asset->baseFlags; - xb->linkCount = asset->linkCount; - xb->link = NULL; - - xBaseValidate(xb); -} - -void xBaseSetup(xBase* xb) -{ - return; -} - -void xBaseSave(xBase* ent, xSerial* s) -{ - if (xBaseIsEnabled(ent)) - { - s->Write_b1(1); - } - else - { - s->Write_b1(0); - } -} - -void xBaseLoad(xBase* ent, xSerial* s) -{ - S32 b = 0; - s->Read_b1(&b); - - if (b) - { - xBaseEnable(ent); - } - else - { - xBaseDisable(ent); - } -} - -void xBaseReset(xBase* xb, xBaseAsset* asset) -{ - xb->baseFlags = (xb->baseFlags & 0x10) | (asset->baseFlags & ~0x10); - - xBaseValidate(xb); -} - -void xBaseValidate(xBase* xb) -{ - xb->baseFlags |= 0x4; -} - -bool xBaseIsEnabled(const xBase* xb) -{ - return (xb->baseFlags & 0x1); -} - -void xBaseDisable(xBase* xb) -{ - xb->baseFlags &= ~0x1; -} - -void xBaseEnable(xBase* xb) -{ - xb->baseFlags |= 0x1; -} diff --git a/src/SB/Core/x/xBehaveGoalSimple.cpp b/src/SB/Core/x/xBehaveGoalSimple.cpp deleted file mode 100644 index 972c528..0000000 --- a/src/SB/Core/x/xBehaveGoalSimple.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "xBehaveGoalSimple.h" - -void xGoalSimple_RegisterTypes(xFactory* fac) -{ - fac->RegItemType('GSM\x00', GOALCreate_Generic, GOALDestroy_Generic); - fac->RegItemType('GSM\x01', GOALCreate_Generic, GOALDestroy_Generic); -} - -xFactoryInst* GOALCreate_Generic(S32 who, RyzMemGrow* growCtxt, void*) -{ - xGoal* goal = NULL; - - switch (who) - { - case 'GSM\x00': - { - goal = new (who, growCtxt) xGoalGeneric(who); - break; - } - case 'GSM\x01': - { - goal = new (who, growCtxt) xGoalEmpty(who); - break; - } - } - - return goal; -} - -void GOALDestroy_Generic(xFactoryInst* item) -{ - delete item; -} - -S32 xGoalGeneric::Enter(F32 dt, void* updCtxt) -{ - if (this->fun_enter) - { - return this->fun_enter(this, this->usrData, dt, updCtxt); - } - - return xGoal::Enter(dt, updCtxt); -} - -S32 xGoalGeneric::Exit(F32 dt, void* updCtxt) -{ - if (this->fun_exit) - { - return this->fun_exit(this, this->usrData, dt, updCtxt); - } - - return xGoal::Exit(dt, updCtxt); -} - -S32 xGoalGeneric::Suspend(F32 dt, void* updCtxt) -{ - if (this->fun_suspend) - { - return this->fun_suspend(this, this->usrData, dt, updCtxt); - } - - return xGoal::Suspend(dt, updCtxt); -} - -S32 xGoalGeneric::Resume(F32 dt, void* updCtxt) -{ - if (this->fun_resume) - { - return this->fun_resume(this, this->usrData, dt, updCtxt); - } - - return xGoal::Resume(dt, updCtxt); -} - -S32 xGoalGeneric::SysEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam, - xBase* toParamWidget, S32* handled) -{ - if (this->fun_sysevent) - { - return this->fun_sysevent(this, this->usrData, from, to, toEvent, toParam, toParamWidget, - handled); - } - - return xGoal::SysEvent(from, to, toEvent, toParam, toParamWidget, handled); -} diff --git a/src/SB/Core/x/xBehaveMgr.cpp b/src/SB/Core/x/xBehaveMgr.cpp deleted file mode 100644 index 653488f..0000000 --- a/src/SB/Core/x/xBehaveMgr.cpp +++ /dev/null @@ -1,210 +0,0 @@ -#include "xBehaveMgr.h" - -#include - -#include "xBehaveGoalSimple.h" -#include "xutil.h" - -extern S32 g_modinit_xBehaveMgr; -extern xBehaveMgr* g_behavmgr; - -void xBehaveMgr_Startup() -{ - if (g_modinit_xBehaveMgr++ == 0) - { - g_behavmgr = new ('BMGR', NULL) xBehaveMgr(); - g_behavmgr->Startup(0xfa, 0xfa); - } -} - -void xBehaveMgr_Shutdown() -{ - g_modinit_xBehaveMgr--; - if (g_modinit_xBehaveMgr == 0) - { - if (g_behavmgr != NULL) - { - delete g_behavmgr; - } - g_behavmgr = NULL; - } -} - -xBehaveMgr* xBehaveMgr_GetSelf() -{ - return g_behavmgr; -} - -xFactory* xBehaveMgr_GoalFactory() -{ - return g_behavmgr->GetFactory(); -} - -void xBehaveMgr_ScenePrepare() -{ - g_behavmgr->ScenePrepare(); -} - -void xBehaveMgr_SceneFinish() -{ - g_behavmgr->SceneFinish(); -} - -void xBehaveMgr_SceneReset() -{ - g_behavmgr->SceneReset(); -} - -void xBehaveMgr::RegBuiltIn() -{ - xGoalSimple_RegisterTypes(this->goalFactory); -} - -xPsyche* xBehaveMgr::Subscribe(xBase* owner, S32 i) -{ - xPsyche* psyche = &this->psypool[this->psylist.cnt]; - XOrdAppend(&this->psylist, psyche); - psyche->FreshWipe(); - psyche->SetOwner(owner, NULL); - return psyche; -} - -void xBehaveMgr::UnSubscribe(xPsyche* psy) -{ - psy->KillBrain(this->goalFactory); - XOrdRemove(&this->psylist, psy, -1); -} - -void xBehaveMgr::ScenePrepare() -{ -} - -void xBehaveMgr::SceneFinish() -{ - XOrdReset(&this->psylist); -} - -void xBehaveMgr::SceneReset() -{ - for (S32 i = 0; i < this->psylist.cnt; i++) - { - xPsyche* psyche = (xPsyche*)this->psylist.list[i]; - psyche->Amnesia(0); - } -} - -void xPsyche::BrainBegin() -{ - xFactory* factory = xBehaveMgr_GoalFactory(); - this->psystat = PSY_STAT_GROW; - factory->GrowDataEnable(&this->fakebase, false); -} - -void xPsyche::BrainExtend() -{ - xFactory* factory = xBehaveMgr_GoalFactory(); - this->psystat = PSY_STAT_EXTEND; - factory->GrowDataEnable(&this->fakebase, true); -} - -void xPsyche::BrainEnd() -{ - xBehaveMgr_GoalFactory()->GrowDataDisable(); - this->psystat = PSY_STAT_THINK; -} - -xGoal* xPsyche::AddGoal(S32 gid, void* createData) -{ - xGoal* goal = (xGoal*)xBehaveMgr_GoalFactory()->CreateItem(gid, createData, NULL); - - if (goal != NULL) - { - if (this->goallist != NULL) - { - this->goallist->Insert(goal); - } - else - { - this->goallist = goal; - } - goal->SetPsyche(this); - } - else - { - xUtil_idtag2string(gid, NULL); - } - return goal; -} - -extern F32 _750; -void xPsyche::FreshWipe() -{ - this->goalstak[0] = NULL; - this->goalstak[1] = NULL; - this->goalstak[2] = NULL; - this->goalstak[3] = NULL; - this->goalstak[4] = NULL; - this->staktop = -1; - this->gid_safegoal = 0; - this->pendgoal = 0; - this->pendtype = PEND_TRAN_NONE; - this->tmr_stack[0][0] = _750; - this->tmr_stack[0][1] = _750; - this->tmr_stack[0][2] = _750; - this->tmr_stack[0][3] = _750; - this->tmr_stack[0][4] = _750; - this->clt_owner = NULL; - this->userContext = NULL; - this->fun_remap = NULL; - this->cb_notice = NULL; - this->psystat = PSY_STAT_BLANK; - this->flg_psyche |= 1; -} - -void xPsyche::SetOwner(xBase* clt_owner, void* userContext) -{ - this->clt_owner = clt_owner; - this->userContext = userContext; - if (clt_owner == NULL) - { - return; - } - - this->fakebase.id = clt_owner->id; - this->fakebase.baseType = clt_owner->baseType + 0x80; - this->fakebase.linkCount = 0; - this->fakebase.baseFlags = 0; - this->fakebase.link = NULL; - this->fakebase.eventFunc = NULL; -} - -void xPsyche::KillBrain(xFactory* factory) -{ - this->Lobotomy(factory); - this->fun_remap = NULL; -} - -void xPsyche::Lobotomy(xFactory* factory) -{ - while (this->goallist != NULL) - { - xGoal* goal = this->goallist->RemHead(&this->goallist); - factory->DestroyItem(goal); - } -} - -void xPsyche::Amnesia(S32 i) -{ - xGoal* g = this->goallist; - while (g != NULL) - { - xGoal* thisg = g; - g = g->Next(); - // this->goallist = this->goallist->Next(); - - if (i == 0 && this->GIDInStack(thisg->GetID()) != NULL) - { - continue; - } - } -} diff --git a/src/SB/Core/x/xBehaviour.cpp b/src/SB/Core/x/xBehaviour.cpp deleted file mode 100644 index a6e4e7e..0000000 --- a/src/SB/Core/x/xBehaviour.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "xBehaviour.h" - -WEAK void xGoal::SetPsyche(xPsyche* psyche) -{ - this->psyche = psyche; -} - -WEAK const char* xGoal::Name() -{ - return NULL; -} - -WEAK void xGoal::SetState(en_GOALSTATE state) -{ - this->stat = state; -} - -WEAK en_GOALSTATE xGoal::GetState() const -{ - return this->stat; -} - -WEAK xGoal* xListItem::Next() -{ - return this->next; -} - -WEAK void xListItem::Insert(xGoal* list) -{ - xGoal* node = (xGoal*)this; - - node->prev = list; - node->next = list->next; - - if (list->next) - { - list->next->prev = node; - } - - list->next = node; -} - -WEAK xGoal* xListItem::RemHead(xGoal** listhead) -{ - if (*listhead == NULL) - { - return NULL; - } - - xGoal* oldhead = (*listhead)->Head(); - - if (!oldhead) - { - *listhead = NULL; - } - else - { - *listhead = oldhead->Next(); - oldhead->Remove(); - } - - return oldhead; -} - -WEAK xGoal* xListItem::Head() -{ - xGoal* node = (xGoal*)this; - - if (!node) - { - return node; - } - - while (node->prev) - { - node = node->prev; - } - - return node; -} - -WEAK xBase* xGoal::GetOwner() const -{ - return this->psyche->GetClient(); -} - -void xGoal::Clear() -{ - this->stat = GOAL_STAT_UNKNOWN; -} - -S32 xGoal::PreCalc(F32 dt, void* updCtxt) -{ - if (this->fun_precalc) - { - return this->fun_precalc(this, this->cbdata, dt, updCtxt); - } - - return 0; -} - -S32 xGoal::EvalRules(en_trantype* trantype, F32 dt, void* updCtxt) -{ - if (this->fun_chkRule) - { - return this->fun_chkRule(this, this->cbdata, trantype, dt, updCtxt); - } - - return 0; -} - -S32 xGoal::Process(en_trantype* trantype, float dt, void* ctxt, xScene* scene) -{ - if (this->fun_process) - { - return this->fun_process(this, this->cbdata, trantype, dt, ctxt); - } - - return 0; -} diff --git a/src/SB/Core/x/xBound.cpp b/src/SB/Core/x/xBound.cpp deleted file mode 100644 index 132111b..0000000 --- a/src/SB/Core/x/xBound.cpp +++ /dev/null @@ -1,495 +0,0 @@ -#include "xBound.h" - -#include "xMath.h" -#include "xMathInlines.h" -#include "xDraw.h" - -#include "iMath.h" - -extern F32 _571; -extern F32 _640; -extern F32 _641; -extern F32 _642; -extern F32 _643; -extern F32 _644; - -void xBoundUpdate(xBound* b) -{ - if (b->type == XBOUND_TYPE_BOX) - { - xVec3Add(&b->box.center, &b->box.box.lower, &b->box.box.upper); - xVec3SMul(&b->box.center, &b->box.center, _571); - } - else if (b->type == XBOUND_TYPE_OBB) - { - xVec3Add(&b->box.center, &b->box.box.lower, &b->box.box.upper); - xVec3SMul(&b->box.center, &b->box.center, _571); - xMat4x3Toworld(&b->box.center, b->mat, &b->box.center); - } - - if (b->type != XBOUND_TYPE_NA) - { - xQuickCullForBound(&b->qcd, b); - } -} - -void xBoundGetBox(xBox& box, const xBound& bound) -{ - switch (bound.type) - { - case XBOUND_TYPE_SPHERE: - { - const xSphere& o = bound.sph; - - box.upper.assign(o.center.x + o.r, o.center.y + o.r, o.center.z + o.r); - box.lower.assign(o.center.x - o.r, o.center.y - o.r, o.center.z - o.r); - - break; - } - case XBOUND_TYPE_BOX: - { - box = bound.box.box; - - break; - } - case XBOUND_TYPE_OBB: - { - xBoxInitBoundOBB(&box, &bound.box.box, bound.mat); - - break; - } - } -} - -void xBoundGetSphere(xSphere& o, const xBound& bound) -{ - switch (bound.type) - { - case XBOUND_TYPE_SPHERE: - { - o = bound.sph; - - break; - } - case XBOUND_TYPE_BOX: - { - o.center = bound.box.center; - o.r = (bound.box.box.upper - bound.box.center).length(); - - break; - } - case XBOUND_TYPE_OBB: - { - const xMat4x3& mat = *bound.mat; - xVec3 v = (bound.box.box.upper - bound.box.box.lower) * _571; - - o.r = xsqrt(SQR(v.x) * mat.right.length2() + SQR(v.y) * mat.up.length2() + - SQR(v.z) * mat.at.length2()); - o.center = bound.box.center; - - break; - } - } -} - -F32 xsqrt(F32 x) -{ - const F32 half = _571; - const F32 three = _640; - - if (x <= _641 || isinf(x)) - { - return x; - } - - // non-matching: frsp instruction - - F32 guess = __frsqrte(x); - guess = half * guess * (three - guess * guess * x); - - if (guess > _644) - { - return _642 / guess; - } - - return _643; -} - -U32 xBoundSphereHitsOBB(const xSphere* s, const xBox* b, const xMat4x3* m, xCollis* coll) -{ - return xSphereHitsOBB_nu(s, b, m, coll); -} - -void xBoundHitsBound(const xBound* a, const xBound* b, xCollis* c) -{ - if (!xQuickCullIsects(&a->qcd, &b->qcd)) - { - c->flags &= ~0x1; - } - else - { - // non-matching: jumptable - - switch (a->type | (b->type << 3)) - { - case (XBOUND_TYPE_SPHERE | (XBOUND_TYPE_SPHERE << 3)): - { - xSphereHitsSphere(&a->sph, &b->sph, c); - break; - } - case (XBOUND_TYPE_SPHERE | (XBOUND_TYPE_OBB << 3)): - { - xBoundSphereHitsOBB(&a->sph, &b->box.box, b->mat, c); - break; - } - case (XBOUND_TYPE_SPHERE | (XBOUND_TYPE_BOX << 3)): - { - xSphereHitsBox(&a->sph, &b->box.box, c); - break; - } - case (XBOUND_TYPE_BOX | (XBOUND_TYPE_SPHERE << 3)): - { - xBoxHitsSphere(&a->box.box, &b->sph, c); - break; - } - case (XBOUND_TYPE_BOX | (XBOUND_TYPE_OBB << 3)): - { - xBoxHitsObb(&a->box.box, &b->box.box, b->mat, c); - break; - } - case (XBOUND_TYPE_OBB | (XBOUND_TYPE_OBB << 3)): - { - break; - } - } - } -} - -static void xBoundOBBIsectRay(const xBox* b, const xMat4x3* m, const xRay3* r, xIsect* isect) -{ - xRay3 xfr; - xBox sbox; - xVec3 scale; - xMat4x3 mnormal; - - { - F32 len2 = SQR(m->right.x) + SQR(m->right.y) + SQR(m->right.z); - - if ((F32)iabs(len2 - _642) <= _644) - { - // non-matching: incorrect instruction + order - - scale.x = *(const F32*)&_642; - - mnormal.right.x = m->right.x; - mnormal.right.y = m->right.y; - mnormal.right.z = m->right.z; - } - else if ((F32)iabs(len2) <= _644) - { - // non-matching: incorrect order - - scale.x = _641; - - mnormal.right.x = _641; - mnormal.right.y = _642; - mnormal.right.z = _641; - } - else - { - scale.x = xsqrt(len2); - - F32 len_inv = _642 / scale.x; - - mnormal.right.x = m->right.x * len_inv; - mnormal.right.y = m->right.y * len_inv; - mnormal.right.z = m->right.z * len_inv; - } - } - - { - F32 len2 = SQR(m->up.x) + SQR(m->up.y) + SQR(m->up.z); - - if ((F32)iabs(len2 - _642) <= _644) - { - // non-matching: incorrect instruction + order - - scale.y = *(const F32*)&_642; - - mnormal.up.x = m->up.x; - mnormal.up.y = m->up.y; - mnormal.up.z = m->up.z; - } - else if ((F32)iabs(len2) <= _644) - { - // non-matching: incorrect order - - scale.y = _641; - - mnormal.up.x = _641; - mnormal.up.y = _642; - mnormal.up.z = _641; - } - else - { - scale.y = xsqrt(len2); - - F32 len_inv = _642 / scale.y; - - mnormal.up.x = m->up.x * len_inv; - mnormal.up.y = m->up.y * len_inv; - mnormal.up.z = m->up.z * len_inv; - } - } - - { - F32 len2 = SQR(m->at.x) + SQR(m->at.y) + SQR(m->at.z); - - if ((F32)iabs(len2 - _642) <= _644) - { - // non-matching: incorrect instruction + order - - scale.z = *(const F32*)&_642; - - mnormal.at.x = m->at.x; - mnormal.at.y = m->at.y; - mnormal.at.z = m->at.z; - } - else if ((F32)iabs(len2) <= _644) - { - // non-matching: incorrect order - - scale.z = _641; - - mnormal.at.x = _641; - mnormal.at.y = _642; - mnormal.at.z = _641; - } - else - { - scale.z = xsqrt(len2); - - F32 len_inv = _642 / scale.z; - - mnormal.at.x = m->at.x * len_inv; - mnormal.at.y = m->at.y * len_inv; - mnormal.at.z = m->at.z * len_inv; - } - } - - mnormal.pos = m->pos; - - sbox.upper.x = b->upper.x * scale.x; - sbox.upper.y = b->upper.y * scale.y; - sbox.upper.z = b->upper.z * scale.z; - sbox.lower.x = b->lower.x * scale.x; - sbox.lower.y = b->lower.y * scale.y; - sbox.lower.z = b->lower.z * scale.z; - - xMat4x3Tolocal(&xfr.origin, &mnormal, &r->origin); - xMat3x3Tolocal(&xfr.dir, &mnormal, &r->dir); - - xfr.min_t = r->min_t; - xfr.max_t = r->max_t; - xfr.flags = r->flags; - - iBoxIsectRay(&sbox, &xfr, isect); -} - -void xRayHitsBound(const xRay3* r, const xBound* b, xCollis* c) -{ - xIsect isect; - - if (b->type == XBOUND_TYPE_SPHERE) - { - iSphereIsectRay(&b->sph, r, &isect); - } - else if (b->type == XBOUND_TYPE_OBB) - { - xBoundOBBIsectRay(&b->box.box, b->mat, r, &isect); - } - else if (b->type == XBOUND_TYPE_BOX) - { - iBoxIsectRay(&b->box.box, r, &isect); - } - - if (isect.penned <= _641) - { - c->flags |= 0x1; - c->dist = isect.dist; - } - else - { - c->flags &= ~0x1; - } -} - -void xSphereHitsBound(const xSphere* o, const xBound* b, xCollis* c) -{ - switch (b->type) - { - case XBOUND_TYPE_SPHERE: - { - xSphereHitsSphere(o, &b->sph, c); - break; - } - case XBOUND_TYPE_OBB: - { - xBoundSphereHitsOBB(o, &b->box.box, b->mat, c); - break; - } - case XBOUND_TYPE_BOX: - { - xSphereHitsBox(o, &b->box.box, c); - break; - } - } -} - -void xVecHitsBound(const xVec3* v, const xBound* b, xCollis* c) -{ - xIsect isect; - - if (b->type == XBOUND_TYPE_SPHERE) - { - iSphereIsectVec(&b->sph, v, &isect); - } - else if (b->type == XBOUND_TYPE_OBB) - { - xVec3 lv; - - xMat4x3Tolocal(&lv, b->mat, v); - iBoxIsectVec(&b->box.box, &lv, &isect); - } - else if (b->type == XBOUND_TYPE_BOX) - { - iBoxIsectVec(&b->box.box, v, &isect); - } - - if (isect.penned <= _641) - { - c->flags |= 0x1; - } - else - { - c->flags &= ~0x1; - } -} - -void xBoundDraw(const xBound* b) -{ - if (b->type == XBOUND_TYPE_SPHERE) - { - xDrawSphere2(&b->sph, 12); - } - else if (b->type == XBOUND_TYPE_OBB) - { - xDrawOBB(&b->box.box, b->mat); - } - else if (b->type == XBOUND_TYPE_BOX) - { - xDrawBox(&b->box.box); - } -} - -void xQuickCullForBound(xQCData* q, const xBound* b) -{ - xQuickCullForBound(&xqc_def_ctrl, q, b); -} - -void xMat4x3Toworld(xVec3* o, const xMat4x3* m, const xVec3* v) -{ - xMat3x3RMulVec(o, m, v); - - o->x += m->pos.x; - o->y += m->pos.y; - o->z += m->pos.z; -} - -void xMat4x3Tolocal(xVec3* o, const xMat4x3* m, const xVec3* v) -{ - o->x = v->x - m->pos.x; - o->y = v->y - m->pos.y; - o->z = v->z - m->pos.z; - - xMat3x3Tolocal(o, m, o); -} - -void xVec3SMul(xVec3* o, const xVec3* v, F32 s) -{ - o->x = v->x * s; - o->y = v->y * s; - o->z = v->z * s; -} - -void xVec3Add(xVec3* o, const xVec3* a, const xVec3* b) -{ - o->x = a->x + b->x; - o->y = a->y + b->y; - o->z = a->z + b->z; -} - -xVec3& xVec3::assign(F32 x, F32 y, F32 z) -{ - this->x = x; - this->y = y; - this->z = z; - - return *this; -} - -F32 xVec3::length2() const -{ - return this->x * this->x + this->y * this->y + this->z * this->z; -} - -xVec3 xVec3::operator*(F32 f) const -{ - xVec3 temp = *this; - temp *= f; - - return temp; -} - -xVec3& xVec3::operator*=(F32 f) -{ - this->x *= f; - this->y *= f; - this->z *= f; - - return *this; -} - -F32 xVec3::length() const -{ - return xsqrt(this->length2()); -} - -xVec3 xVec3::operator-(const xVec3& v) const -{ - xVec3 temp = *this; - temp -= v; - - return temp; -} - -xVec3& xVec3::operator-=(const xVec3& v) -{ - this->x -= v.x; - this->y -= v.y; - this->z -= v.z; - - return *this; -} - -void xDrawBox(const xBox*) -{ -} - -void xDrawOBB(const xBox*, const xMat4x3*) -{ -} - -void xDrawSphere2(const xSphere*, U32) -{ -} diff --git a/src/SB/Core/x/xCM.cpp b/src/SB/Core/x/xCM.cpp deleted file mode 100644 index c4a8984..0000000 --- a/src/SB/Core/x/xCM.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "xCM.h" -#include "xEvent.h" - -#include - -volatile static F32 credits_time; -static xCreditsData* credits_data; -static U32 credits_parentID; - -F32 dtscale; - -static void xCMprep(xCreditsData* data) -{ - /* - data seems to point to this general structure: - 0x00 - xCMheader - 0x18 - xCMcredits - 0x50 - xCMpreset* presets_array[xCMcredits.num_presets] - - xCMhunk* hunk_array[?] - */ - - char* dp; // In the DWARF. Don't know what this is used for. - xCMheader* hdr = (xCMheader*)data; - - if (hdr->magic != 0xBEEEEEEF) - { - return; - } - - xCMcredits* cp = (xCMcredits *)(&hdr[1]); - while ((int)cp - (int)data < hdr->total_size) - { - xCMpreset* pp = (xCMpreset*)(&cp[1]); - xCMhunk* hp = (xCMhunk*)(&pp[cp->num_presets]); - - for ( ; (int)hp - (int)cp < cp->credits_size; hp = (xCMhunk*)((int)hp + hp->hunk_size)) - { - switch (pp[hp->preset].align) - { - case 0: - case 1: - case 2: - case 3: - - if (hdr->state == 0) - { - if (hp->text1 != NULL) - { - hp->text1 -= (int)data; - } - if (hp->text2 != NULL) - { - hp->text2 -= (int)data; - } - } - else - { - if (hp->text1 != NULL) - { - hp->text1 += (int)data; - } - if (hp->text2 != NULL) - { - hp->text2 += (int)data; - } - } - break; - } - } - cp = (xCMcredits*)hp; - } - - hdr->state = hdr->state == 0 ? 1 : 0; -} - -void xCMupdate(F32 time) -{ - if (credits_data != 0) - { - credits_time += (time * dtscale); - if (credits_time >= *(F32*)((int)&credits_data->dummy + 0x10)) - { - xCMstop(); - } - } -} - -void xCMrender() -{ - xCMrender(credits_time, credits_data); -} - -void xCMstart(xCreditsData* data, F32 time, xBase* parent) -{ - if ((credits_data = data) != NULL) - { - credits_time = 0.0f; - - if (parent != NULL) - { - credits_parentID = parent->id; - } - } -} - -// Equivalent: scheduling -void xCMstop() -{ - credits_time = 10000.0f; - credits_data = NULL; - if (credits_parentID != 0) - { - zEntEvent(credits_parentID, 0x212); - } -} diff --git a/src/SB/Core/x/xCamera.cpp b/src/SB/Core/x/xCamera.cpp index 2400691..e69de29 100644 --- a/src/SB/Core/x/xCamera.cpp +++ b/src/SB/Core/x/xCamera.cpp @@ -1,1344 +0,0 @@ -#include "xCamera.h" - -#include "xstransvc.h" -#include "xMath.h" -#include "xMathInlines.h" -#include "xScene.h" -#include "xCollideFast.h" -#include "xScrFx.h" - -#include "iMath.h" - -#include -#include - -struct cameraFXShake -{ - F32 magnitude; - xVec3 dir; - F32 cycleTime; - F32 cycleMax; - F32 dampen; - F32 dampenRate; - F32 rotate_magnitude; - F32 radius; - xVec3* epicenterP; - xVec3 epicenter; - xVec3* player; -}; - -struct cameraFXZoom -{ - F32 holdTime; - F32 vel; - F32 accel; - F32 distance; - U32 mode; - F32 velCur; - F32 distanceCur; - F32 holdTimeCur; -}; - -#define CAMERAFX_ZOOM_MODE_0 0 -#define CAMERAFX_ZOOM_MODE_1 1 -#define CAMERAFX_ZOOM_MODE_2 2 -#define CAMERAFX_ZOOM_MODE_3 3 - -struct cameraFX -{ - S32 type; - S32 flags; - F32 elapsedTime; - F32 maxTime; - union - { - cameraFXShake shake; - cameraFXZoom zoom; - }; -}; - -#define CAMERAFX_TYPE_SHAKE 2 - -struct cameraFXTableEntry -{ - S32 type; - void (*func)(cameraFX*, F32, xMat4x3*, xMat4x3*); - void (*funcKill)(cameraFX*); -}; - -extern F32 _764; -extern F32 _765; -extern F32 _766; -extern F32 _785; -extern F32 _786; -extern F32 _787; -extern F32 _788; -extern F32 _789; -extern F32 _790; -extern F32 _830; -extern F32 _831; -extern F32 _873; -extern F32 _874; -extern F32 _880; -extern F32 _888; -extern F32 _895; -extern F32 _1234; -extern F32 _1235; -extern F32 _1236; -extern F32 _1237; -extern F32 _1238; -extern F32 _1239; -extern F32 _1240; -extern F32 _1241; -extern F32 _1242; -extern F32 _1283; -extern F64 _1286; -extern F32 _1404; -extern F32 _1405; -extern F32 _1534; -extern F32 _1584; -extern F32 _1585; -extern F32 _1586; -extern F32 _1757; -extern F32 _1758; -extern F32 _1766; -extern F32 _1772; - -extern S32 sCamCollis; -extern volatile S32 xcam_collis_owner_disable; -extern S32 xcam_do_collis; -extern F32 xcam_collis_radius; -extern F32 xcam_collis_stiffness; -extern RpAtomic* sInvisWallHack; -extern xMat4x3 sCameraFXMatOld; -extern cameraFX sCameraFX[10]; -extern cameraFXTableEntry sCameraFXTable[3]; - -static void xCameraFXInit(); -void add_camera_tweaks(); - -void xCameraInit(xCamera* cam, U32 width, U32 height) -{ - xCameraFXInit(); - - cam->lo_cam = iCameraCreate(width, height, 1); - - xCameraSetFOV(cam, _764); - - cam->bound.sph.center.x = _765; - cam->bound.sph.center.y = _765; - cam->bound.sph.center.z = _765; - cam->bound.sph.r = _766; - cam->tgt_mat = NULL; - cam->tgt_omat = NULL; - cam->tgt_bound = NULL; - cam->sc = NULL; - cam->tran_accum.x = _765; - cam->tran_accum.y = _765; - cam->tran_accum.z = _765; - - add_camera_tweaks(); -} - -void add_camera_tweaks() -{ -} - -void xCameraExit(xCamera* cam) -{ - if (cam->lo_cam) - { - iCameraDestroy(cam->lo_cam); - cam->lo_cam = NULL; - } -} - -void xCameraReset(xCamera* cam, F32 d, F32 h, F32 pitch) -{ - sInvisWallHack = (RpAtomic*)xSTFindAsset(0xB8895D14, NULL); - - xMat4x3Identity(&cam->mat); - - cam->omat = cam->mat; - cam->focus.x = _765; - cam->focus.y = _765; - cam->focus.z = _785; - cam->tran_accum.x = _765; - cam->tran_accum.y = _765; - cam->tran_accum.z = _765; - cam->flags = 0; - - F32 goal_p = _786; - - if (cam->tgt_mat) - { - goal_p += xatan2(cam->tgt_mat->at.x, cam->tgt_mat->at.z); - } - - xCameraMove(cam, 0x2E, d, h, goal_p, _765, _787, _787); - - cam->pitch_goal = pitch; - cam->pitch_cur = pitch; - cam->roll_cur = _765; - - xMat3x3Euler(&cam->mat, cam->yaw_cur, cam->pitch_cur, cam->roll_cur); - - cam->omat = cam->mat; - cam->yaw_ct = _788; - cam->yaw_cd = _788; - cam->yaw_ccv = _789; - cam->yaw_csv = _788; - cam->pitch_ct = _788; - cam->pitch_cd = _788; - cam->pitch_ccv = _790; - cam->pitch_csv = _788; - cam->roll_ct = _788; - cam->roll_cd = _788; - cam->roll_ccv = _790; - cam->roll_csv = _788; - cam->flags |= 0x80; - - xcam_do_collis = 1; - xcam_collis_owner_disable = 0; -} - -static void xCam_buildbasis(xCamera* cam) -{ - if (cam->tgt_mat) - { - F32 d2d; - F32 dx__ = cam->mat.pos.x - cam->tgt_mat->pos.x; - F32 dz__ = cam->mat.pos.z - cam->tgt_mat->pos.z; - - F32 dist2 = SQR(dx__) + SQR(dz__); - F32 dist_inv; - - if ((F32)iabs(dist2 - _788) <= _830) - { - cam->mbasis.at.x = dx__; - cam->mbasis.at.z = dz__; - - d2d = _788; - } - else if ((F32)iabs(dist2) <= _830) - { - cam->mbasis.at.x = _765; - cam->mbasis.at.z = _765; - - d2d = _765; - } - else - { - d2d = xsqrt(dist2); - dist_inv = _788 / d2d; - - cam->mbasis.at.x = dx__ * dist_inv; - cam->mbasis.at.z = dz__ * dist_inv; - } - - if (d2d < _830) - { - cam->mbasis.at.x = cam->mat.at.x; - cam->mbasis.at.z = cam->mat.at.z; - - dist2 = xsqrt(SQR(cam->mbasis.at.x) + SQR(cam->mbasis.at.z)); - - if (dist2 > _831) - { - // non-matching: wrong registers - dist_inv = _788 / dist2; - - cam->mbasis.at.x *= dist_inv; - cam->mbasis.at.z *= dist_inv; - } - else - { - cam->mbasis.at.x = isin(cam->pcur); - cam->mbasis.at.z = icos(cam->pcur); - } - } - - cam->mbasis.at.y = _765; - cam->mbasis.up.x = _765; - cam->mbasis.up.y = _788; - cam->mbasis.up.z = _765; - cam->mbasis.right.x = cam->mbasis.at.z; - cam->mbasis.right.y = _765; - cam->mbasis.right.z = -cam->mbasis.at.x; - } -} - -static void xCam_cyltoworld(xVec3* v, const xMat4x3* tgt_mat, F32 d, F32 h, F32 p, U32 flags) -{ - if (flags & 0x10) - { - v->y = h; - } - else - { - v->y = h + tgt_mat->pos.y; - } - - if (flags & 0x20) - { - v->x = d * isin(p) + tgt_mat->pos.x; - v->z = d * icos(p) + tgt_mat->pos.z; - } - else - { - p += xatan2(tgt_mat->at.x, tgt_mat->at.z); - - v->x = d * isin(p) + tgt_mat->pos.x; - v->z = d * icos(p) + tgt_mat->pos.z; - } -} - -static void xCam_worldtocyl(F32& d, F32& h, F32& p, const xMat4x3* tgt_mat, const xVec3* v, - U32 flags) -{ - F32 lx, lz; - - F32 dx__ = v->x - tgt_mat->pos.x; - F32 dz__ = v->z - tgt_mat->pos.z; - - F32 dist2 = SQR(dx__) + SQR(dz__); - F32 dist_inv; - - if ((F32)iabs(dist2 - _788) <= _830) - { - lx = dx__; - lz = dz__; - d = _788; - } - else if ((F32)iabs(dist2) <= _830) - { - d = lz = lx = _765; - } - else - { - d = xsqrt(dist2); - - dist_inv = _788 / d; - - lx = dx__ * dist_inv; - lz = dz__ * dist_inv; - } - - if (flags & 0x10) - { - h = v->y; - } - else - { - h = v->y - tgt_mat->pos.y; - } - - p = xatan2(lx, lz); - - if (!(flags & 0x20)) - { - F32 tgt_p = p - xatan2(tgt_mat->at.x, tgt_mat->at.z); - - p = xDangleClamp(tgt_p); - } -} - -static void xCam_CorrectD(xCamera* r3, F32 f1, F32 f2, F32 f3) -{ - // non-matching: incorrect float register - - F32 tmp1, tmp2, tmp3; - - tmp1 = _873 * (_874 * f1 - f2 * f3); - tmp1 -= f2; - tmp1 *= f3; - - tmp2 = r3->mbasis.at.x * tmp1; - tmp3 = r3->mbasis.at.z * tmp1; - - r3->mat.pos.x += tmp2; - r3->mat.pos.z += tmp3; -} - -static void xCam_CorrectH(xCamera* r3, F32 f1, F32 f2, F32 f3) -{ - F32 tmp; - - f2 = _880 * f2; - - tmp = _873 * -(f2 * f3 - f1); - tmp -= f2; - tmp *= f3; - - r3->mat.pos.y += tmp; -} - -static void xCam_CorrectP(xCamera* r3, F32 f1, F32 f2, F32 f3) -{ - F32 tmp1, tmp2, tmp3; - - f2 = _880 * f2; - - tmp1 = _888 * (_874 * f1 - f2 * f3); - tmp1 -= f2; - tmp1 *= f3; - - tmp2 = r3->mbasis.right.x * tmp1; - tmp3 = r3->mbasis.right.z * tmp1; - - r3->mat.pos.x += tmp2; - r3->mat.pos.z += tmp3; -} - -static void xCam_DampP(xCamera* r3, F32 f1, F32 f2) -{ - F32 tmp1, tmp2; - - f1 = _895 * f1; - f2 = f1 * f2 * f2; - - tmp1 = r3->mbasis.right.x * f2; - tmp2 = r3->mbasis.right.z * f2; - - r3->mat.pos.x += tmp1; - r3->mat.pos.z += tmp2; -} -static void xCam_CorrectYaw(xCamera* r3, F32 f1, F32 f2, F32 f3) -{ - // non-matching: incorrect float registers, slightly out-of-order fmsubs instruction - - F32 tmp1, tmp2; - - tmp1 = _788 / r3->yaw_ct; - - tmp2 = _874 * r3->yaw_cd * f1 - f2 * f3; - tmp2 = tmp1 * tmp2; - tmp2 -= f2; - tmp2 *= r3->yaw_csv * f3; - - r3->yaw_cur += tmp2; -} -static void xCam_CorrectPitch(xCamera* r3, F32 f1, F32 f2, F32 f3) -{ - // non-matching: same reasons as xCam_CorrectYaw - - F32 tmp1, tmp2; - - tmp1 = _788 / r3->pitch_ct; - - tmp2 = _874 * r3->pitch_cd * f1 - f2 * f3; - tmp2 = tmp1 * tmp2; - tmp2 -= f2; - tmp2 *= r3->pitch_csv * f3; - - r3->pitch_cur += tmp2; -} - -static void xCam_CorrectRoll(xCamera* r3, F32 f1, F32 f2, F32 f3) -{ - // non-matching: same reasons as xCam_CorrectYaw - - F32 tmp1, tmp2; - - tmp1 = _788 / r3->roll_ct; - - tmp2 = _874 * r3->roll_cd * f1 - f2 * f3; - tmp2 = tmp1 * tmp2; - tmp2 -= f2; - tmp2 *= r3->roll_csv * f3; - - r3->roll_cur += tmp2; -} - -void SweptSphereHitsCameraEnt(xScene*, xRay3* ray, xQCData* qcd, xEnt* ent, void* data) -{ - xSweptSphere* sws = (xSweptSphere*)data; - - if (ent->camcollModel && ent->chkby & 0x10 && xQuickCullIsects(qcd, &ent->bound.qcd)) - { - if (!xEntIsVisible(ent)) - { - if (ent->model->Data != sInvisWallHack) - { - return; - } - - if (ent->collLev != 5) - { - if (ent->bound.type == XBOUND_TYPE_BOX) - { - xSweptSphereToBox(sws, &ent->bound.box.box, NULL); - return; - } - else if (ent->bound.type == XBOUND_TYPE_OBB) - { - xSweptSphereToBox(sws, &ent->bound.box.box, ent->bound.mat); - return; - } - else - { - return; - } - } - } - - U32 result = 0; - - switch (ent->bound.type) - { - case XBOUND_TYPE_SPHERE: - { - F32 oldrad = ent->bound.sph.r; - - ent->bound.sph.r += sws->radius; - - result = xRayHitsSphereFast(ray, &ent->bound.sph); - - ent->bound.sph.r = oldrad; - - break; - } - case XBOUND_TYPE_BOX: - { - xBox tmpbox; - tmpbox.upper.x = ent->bound.box.box.upper.x + sws->radius; - tmpbox.upper.y = ent->bound.box.box.upper.y + sws->radius; - tmpbox.upper.z = ent->bound.box.box.upper.z + sws->radius; - tmpbox.lower.x = ent->bound.box.box.lower.x - sws->radius; - tmpbox.lower.y = ent->bound.box.box.lower.y - sws->radius; - tmpbox.lower.z = ent->bound.box.box.lower.z - sws->radius; - - result = xRayHitsBoxFast(ray, &tmpbox); - - break; - } - case XBOUND_TYPE_OBB: - { - xBox tmpbox; - xRay3 lr; - xMat3x3 mn; - - F32 f31 = xVec3Length(&ent->bound.mat->right); - - xMat3x3Normalize(&mn, ent->bound.mat); - xMat4x3Tolocal(&lr.origin, ent->bound.mat, &ray->origin); - xMat3x3Tolocal(&lr.dir, &mn, &ray->dir); - - lr.max_t = ray->max_t / f31; - lr.min_t = ray->min_t / f31; - lr.flags = ray->flags; - - tmpbox.upper.x = ent->bound.box.box.upper.x + sws->radius / f31; - tmpbox.upper.y = ent->bound.box.box.upper.y + sws->radius / f31; - tmpbox.upper.z = ent->bound.box.box.upper.z + sws->radius / f31; - tmpbox.lower.x = ent->bound.box.box.lower.x - sws->radius / f31; - tmpbox.lower.y = ent->bound.box.box.lower.y - sws->radius / f31; - tmpbox.lower.z = ent->bound.box.box.lower.z - sws->radius / f31; - - result = xRayHitsBoxFast(&lr, &tmpbox); - - break; - } - } - - if (result) - { - xModelInstance* collmod = ent->camcollModel; - - xSweptSphereToModel(sws, collmod->Data, collmod->Mat); - } - } -} - -static void _xCameraUpdate(xCamera* cam, F32 dt) -{ - // lol nope -} - -void xCameraUpdate(xCamera* cam, F32 dt) -{ - S32 i; - S32 num_updates; - F32 sdt; - - num_updates = std::ceilf(_1283 * dt); - - sdt = dt / num_updates; - - for (i = 0; i < num_updates; i++) - { - sCamCollis = (i == num_updates - 1); - - _xCameraUpdate(cam, sdt); - } -} - -#ifndef INLINE -float std::ceilf(float x) -{ - return (float)ceil((double)x); -} -#endif - -void xCameraBegin(xCamera* cam, S32 clear) -{ - iCameraBegin(cam->lo_cam, clear); - iCameraFrustumPlanes(cam->lo_cam, cam->frustplane); - iCameraUpdateFog(cam->lo_cam, 0); -} - -void xCameraFXBegin(xCamera* cam) -{ - xMat4x3Identity(&sCameraFXMatOld); - xMat4x3Copy(&sCameraFXMatOld, &cam->mat); -} - -static void xCameraFXInit() -{ - memset(sCameraFX, 0, sizeof(sCameraFX)); - - sCameraFX[0].flags = 0; - sCameraFX[1].flags = 0; - sCameraFX[2].flags = 0; - sCameraFX[3].flags = 0; - sCameraFX[4].flags = 0; - sCameraFX[5].flags = 0; - sCameraFX[6].flags = 0; - sCameraFX[7].flags = 0; - sCameraFX[8].flags = 0; - sCameraFX[9].flags = 0; -} - -cameraFX* xCameraFXAlloc() -{ - S32 i; - cameraFX* f; - - for (i = 0; i < sizeof(sCameraFX) / sizeof(cameraFX); i++) - { - f = &sCameraFX[i]; - - if (f->flags == 0) - { - // non-matching: _765 is only loaded once - - f->flags = 0x1; - f->elapsedTime = _765; - f->maxTime = _765; - - return f; - } - } - - return NULL; -} - -void xCameraFXZoomUpdate(cameraFX* f, F32 dt, const xMat4x3*, xMat4x3* m) -{ - switch (f->zoom.mode) - { - case CAMERAFX_ZOOM_MODE_0: - { - f->zoom.velCur += f->zoom.accel * dt; - f->zoom.distanceCur += f->zoom.velCur * dt; - - if (f->zoom.distanceCur >= f->zoom.distance) - { - f->zoom.distanceCur = f->zoom.distance; - f->zoom.mode = CAMERAFX_ZOOM_MODE_2; - f->zoom.holdTimeCur = _765; - } - - xMat4x3MoveLocalAt(m, f->zoom.distanceCur); - - break; - } - case CAMERAFX_ZOOM_MODE_2: - { - f->zoom.holdTimeCur += dt; - - if (f->zoom.holdTimeCur > f->zoom.holdTime) - { - f->zoom.mode = CAMERAFX_ZOOM_MODE_1; - f->zoom.distanceCur = f->zoom.distance; - f->zoom.velCur = f->zoom.vel; - } - - xMat4x3MoveLocalAt(m, f->zoom.distance); - - break; - } - case CAMERAFX_ZOOM_MODE_1: - { - f->zoom.velCur += f->zoom.accel * dt; - f->zoom.distanceCur -= f->zoom.velCur * dt; - - if (f->zoom.distanceCur <= 0.0f) - { - f->zoom.distanceCur = 0.0f; - f->zoom.mode = CAMERAFX_ZOOM_MODE_3; - f->flags |= 0x2; - } - - xMat4x3MoveLocalAt(m, f->zoom.distanceCur); - - break; - } - case CAMERAFX_ZOOM_MODE_3: - { - break; - } - } -} - -void xCameraFXShake(F32 maxTime, F32 magnitude, F32 cycleMax, F32 rotate_magnitude, F32 radius, - xVec3* epicenter, xVec3* player) -{ - cameraFX* f = xCameraFXAlloc(); - - if (f) - { - f->type = CAMERAFX_TYPE_SHAKE; - f->maxTime = maxTime; - f->shake.magnitude = magnitude; - f->shake.dir.x = _788; - f->shake.dir.y = _788; - f->shake.cycleMax = cycleMax; - f->shake.cycleTime = _765; - f->shake.dampen = _765; - f->shake.dampenRate = _788 / maxTime; - f->shake.rotate_magnitude = rotate_magnitude; - f->shake.radius = radius; - f->shake.epicenterP = epicenter; - - if (f->shake.epicenterP) - { - f->shake.epicenter = *f->shake.epicenterP; - } - - f->shake.player = player; - } -} - -void xCameraFXShakeUpdate(cameraFX* f, F32 dt, const xMat4x3*, xMat4x3* m) -{ - F32 x, y, scale, noise; - xVec3 var_4C, e; - - f->shake.cycleTime += dt; - - while (f->shake.cycleTime > f->shake.cycleMax) - { - f->shake.dir.x = -f->shake.dir.x; - f->shake.dir.y = -f->shake.dir.y; - f->shake.cycleTime -= f->shake.cycleMax; - } - - scale = f->shake.dampenRate * (f->maxTime - f->elapsedTime); - noise = _1404 * (xurand() - _766); - - if (f->shake.radius > _765 && f->shake.player) - { - xVec3Sub(&var_4C, f->shake.player, &f->shake.epicenter); - - F32 f1 = var_4C.length(); - - if (f1 > f->shake.radius) - { - scale = _765; - } - else - { - scale *= icos(f1 / f->shake.radius * _786 * _766); - } - } - - x = (f->shake.magnitude + noise) * f->shake.dir.x * scale / f->shake.cycleMax * - f->shake.cycleTime * isin(f->shake.cycleTime / f->shake.cycleMax * _786); - - noise = _1404 * (xurand() - _766); - - y = (f->shake.magnitude + noise) * f->shake.dir.y * scale / f->shake.cycleMax * - f->shake.cycleTime * isin(f->shake.cycleTime / f->shake.cycleMax * _786); - - xMat4x3MoveLocalRight(m, x); - xMat4x3MoveLocalUp(m, y); - - xMat3x3GetEuler(m, &e); - - e.z += - f->shake.cycleTime / f->shake.cycleMax * _1405 * _1404 * scale * f->shake.rotate_magnitude; - - xMat3x3Euler(m, &e); -} - -void xCameraFXUpdate(xCamera* cam, F32 dt) -{ - S32 i; - cameraFX* f; - cameraFXTableEntry* t; - - for (i = 0; i < 10; i++) - { - f = &sCameraFX[i]; - - if (f->flags & 0x1) - { - f->elapsedTime += dt; - - // non-matching: _765 is loaded too early - - if ((f->maxTime > _765 && f->elapsedTime > f->maxTime) || f->flags & 0x2) - { - f->flags = 0; - - t = &sCameraFXTable[f->type]; - - if (t->funcKill) - { - t->funcKill(f); - } - } - else - { - t = &sCameraFXTable[f->type]; - - if (t->func) - { - t->func(f, dt, &sCameraFXMatOld, &cam->mat); - } - } - } - } - - iCameraUpdatePos(cam->lo_cam, &cam->mat); -} - -void xCameraFXEnd(xCamera* cam) -{ - xMat4x3Copy(&cam->mat, &sCameraFXMatOld); - iCameraUpdatePos(cam->lo_cam, &sCameraFXMatOld); -} - -void xCameraEnd(xCamera* cam, F32 seconds, S32 update_scrn_fx) -{ - if (update_scrn_fx) - { - xScrFxUpdate(cam->lo_cam, seconds); - } - - iCameraEnd(cam->lo_cam); -} - -void xCameraShowRaster(xCamera* cam) -{ - iCameraShowRaster(cam->lo_cam); -} - -void xCameraSetScene(xCamera* cam, xScene* sc) -{ - cam->sc = sc; - - iCameraAssignEnv(cam->lo_cam, sc->env->geom); -} - -void xCameraSetTargetMatrix(xCamera* cam, xMat4x3* mat) -{ - cam->tgt_mat = mat; -} - -void xCameraSetTargetOMatrix(xCamera* cam, xMat4x3* mat) -{ - cam->tgt_omat = mat; -} - -void xCameraDoCollisions(S32 do_collis, S32 owner) -{ - xcam_collis_owner_disable &= ~(1 << owner); - xcam_collis_owner_disable |= !do_collis << owner; - - xcam_do_collis = (xcam_collis_owner_disable == 0); -} - -void xCameraMove(xCamera* cam, U32 flags, F32 dgoal, F32 hgoal, F32 pgoal, F32 tm, F32 tm_acc, - F32 tm_dec) -{ - cam->flags = (cam->flags & ~0x3E) | (flags & 0x3E); - cam->dgoal = dgoal; - cam->hgoal = hgoal; - cam->pgoal = pgoal; - - if (tm <= _765) - { - if (cam->tgt_mat) - { - cam->dcur = dgoal; - cam->hcur = hgoal; - cam->pcur = pgoal; - - xCam_cyltoworld(&cam->mat.pos, cam->tgt_mat, dgoal, hgoal, pgoal, cam->flags); - - cam->omat.pos = cam->mat.pos; - cam->yaw_cur = cam->yaw_goal = cam->pcur + ((cam->pcur >= _786) ? _1534 : _786); - } - } - else - { - cam->flags |= 0x1; - cam->tm_acc = tm - tm_acc; - cam->tm_dec = tm_dec; - cam->tmr = tm; - - F32 s = _788 / (tm - _766 * (tm_acc - tm_dec)); - - cam->depv = s * (dgoal - cam->dcur); - cam->hepv = s * (hgoal - cam->hcur); - cam->pepv = xDangleClamp(pgoal - cam->pcur) * s * _766 * (dgoal + cam->dcur); - } -} - -void xCameraMove(xCamera* cam, const xVec3& loc) -{ - cam->omat.pos = cam->mat.pos = loc; - cam->flags &= ~0x3E; - cam->tm_acc = cam->tm_dec = cam->tmr = _765; -} - -void xCameraMove(xCamera* cam, const xVec3& loc, F32 maxSpeed) -{ - xVec3 var_28; - F32 f1; - - xVec3Sub(&var_28, &loc, &cam->mat.pos); - - f1 = xVec3Length(&var_28); - - if (f1 > maxSpeed) - { - xVec3SMul(&var_28, &var_28, maxSpeed / f1); - xVec3Add(&cam->mat.pos, &cam->mat.pos, &var_28); - } - else - { - cam->mat.pos = loc; - } - - cam->omat.pos = cam->mat.pos; - cam->flags &= ~0x3E; - cam->tm_acc = cam->tm_dec = cam->tmr = _765; -} - -void xCameraFOV(xCamera* cam, F32 fov, F32 maxSpeed, F32 dt) -{ - F32 speed = maxSpeed * dt; - F32 currentFOV = xCameraGetFOV(cam); - - if (currentFOV != fov) - { - if (speed != _765) - { - F32 len = fov - currentFOV; - - if ((F32)iabs(len) > speed) - { - len *= speed / len; - xCameraSetFOV(cam, currentFOV + len); - } - else - { - xCameraSetFOV(cam, fov); - } - } - else - { - xCameraSetFOV(cam, fov); - } - } -} - -void xCameraLook(xCamera* cam, U32 flags, const xQuat* orn_goal, F32 tm, F32 tm_acc, F32 tm_dec) -{ - F32 s; // unused - - cam->flags = (cam->flags & ~0xF80) | (flags & 0xF80); - cam->orn_goal = *orn_goal; - - if (tm <= _765) - { - if (cam->tgt_mat) - { - xQuatToMat(orn_goal, &cam->mat); - - *(xMat3x3*)&cam->omat = *(xMat3x3*)&cam->mat; - } - } - else - { - cam->flags |= 0x40; - cam->ltm_acc = tm - tm_acc; - cam->ltm_dec = tm_dec; - cam->ltmr = tm; - - xQuatDiff(&cam->orn_diff, &cam->orn_cur, orn_goal); - - cam->orn_epv = _788 / (tm - _766 * (tm_acc - tm_dec)) * xQuatGetAngle(&cam->orn_diff); - } -} - -void xCameraLookYPR(xCamera* cam, U32 flags, F32 yaw, F32 pitch, F32 roll, F32 tm, F32 tm_acc, - F32 tm_dec) -{ - cam->flags = (cam->flags & ~0xF80) | (flags & 0xF80) | 0x80; - cam->yaw_goal = yaw; - cam->pitch_goal = pitch; - cam->roll_goal = roll; - - if (tm <= _765) - { - if (cam->tgt_mat) - { - cam->yaw_cur = yaw; - cam->pitch_cur = pitch; - cam->roll_cur = roll; - - xMat3x3Euler(&cam->mat, yaw, pitch, roll); - - *(xMat3x3*)&cam->omat = *(xMat3x3*)&cam->mat; - } - } - else - { - cam->flags |= 0x40; - cam->ltm_acc = tm - tm_acc; - cam->ltm_dec = tm_dec; - cam->ltmr = tm; - - F32 s = _788 / (tm - _766 * (tm_acc - tm_dec)); - - cam->yaw_epv = s * xDangleClamp(yaw - cam->yaw_cur); - cam->pitch_epv = s * xDangleClamp(pitch - cam->pitch_cur); - cam->roll_epv = s * xDangleClamp(roll - cam->roll_cur); - } -} - -void xCameraRotate(xCamera* cam, const xMat3x3& m, F32 time, F32 accel, F32 decl) -{ - xVec3 eu; - - cam->flags = cam->flags & ~0xF80 | 0x80; - - xMat3x3GetEuler(&m, &eu); - - cam->yaw_goal = eu.x; - cam->pitch_goal = eu.y; - cam->roll_goal = eu.z; - - if (_765 == time) - { - cam->yaw_cur = eu.x; - cam->pitch_cur = eu.y; - cam->roll_cur = eu.z; - } - - *(xMat3x3*)&cam->mat = m; - - if (_765 == time) - { - *(xMat3x3*)&cam->omat = m; - } - - if (_765 == time) - { - cam->ltm_acc = cam->ltm_dec = cam->ltmr = _765; - } - else - { - cam->ltm_acc = accel; - cam->ltm_dec = decl; - cam->ltmr = time; - } - - cam->yaw_epv = cam->pitch_epv = cam->roll_epv = _765; -} - -void xCameraRotate(xCamera* cam, const xVec3& v, F32 roll, F32 time, F32 accel, F32 decl) -{ - cam->yaw_goal = xatan2(v.x, v.z); - cam->pitch_goal = -xasin(v.y); - cam->roll_goal = roll; - - if (_765 == time) - { - cam->yaw_cur = cam->yaw_goal; - cam->pitch_cur = cam->pitch_goal; - cam->roll_cur = cam->roll_goal; - } - - cam->flags = cam->flags & ~0xF80 | 0x80; - - xMat3x3Euler(&cam->mat, cam->yaw_goal, cam->pitch_goal, cam->roll_goal); - - if (_765 == time) - { - *(xMat3x3*)&cam->omat = *(xMat3x3*)&cam->mat; - } - - if (_765 == time) - { - cam->ltm_acc = cam->ltm_dec = cam->ltmr = _765; - } - else - { - cam->ltm_acc = accel; - cam->ltm_dec = decl; - cam->ltmr = time; - } - - cam->yaw_epv = cam->pitch_epv = cam->roll_epv = _765; -} - -F32 xasin(F32 x) -{ - return std::asinf(x); -} - -#ifndef INLINE -float std::asinf(float x) -{ - return (float)asin((double)x); -} -#endif - -static void bound_sphere_xz(xVec3& r3, xVec3& r4, const xVec3& r5, F32 f1, const xVec3& r6, F32 f2) -{ - // non-matching: incorrect registers and out-of-order instructions - F32 _f31 = f1 / f2; - F32 _f3 = _f31 / xsqrt(SQR(f2) - SQR(f1)); - F32 _f5 = f1 * _f31; - F32 _f7 = _f3 * r6.z; - F32 _f8 = _f5 * r6.x; - F32 _f6 = _f3 * r6.x; - F32 _f5_2 = _f5 * r6.z; - - r3.x = r5.x + _f7 + _f8; - r3.y = r5.y; - r3.z = r5.z - _f6 + _f5_2; - - r4.x = r5.x - _f7 + _f8; - r4.y = r5.y; - r4.z = r5.z + _f6 + _f5_2; -} - -void xBinaryCamera::init() -{ - this->camera = NULL; - this->s2 = NULL; - this->s1 = NULL; -} - -void xBinaryCamera::start(xCamera& camera) -{ - this->camera = &camera; - - xQuatFromMat(&this->cam_dir, &camera.mat); - - this->stick_offset = _765; -} - -void xBinaryCamera::stop() -{ - this->camera = NULL; -} - -void xBinaryCamera::update(F32 dt) -{ -} - -void xCameraSetFOV(xCamera* cam, F32 fov) -{ - cam->fov = fov; - - iCameraSetFOV(cam->lo_cam, fov); -} - -F32 xCameraGetFOV(const xCamera* cam) -{ - return cam->fov; -} - -void xBinaryCamera::render_debug() -{ -} - -void xMat4x3Identity(xMat4x3* m) -{ - xMat4x3Copy(m, &g_I3); -} - -void xMat4x3Copy(xMat4x3* o, const xMat4x3* m) -{ - memcpy(o, m, sizeof(xMat4x3)); -} - -void xQuatConj(xQuat* o, const xQuat* q) -{ - o->s = q->s; - - xVec3Inv(&o->v, &q->v); -} - -void xMat3x3LookAt(xMat3x3* m, const xVec3* pos, const xVec3* at) -{ - xVec3 v; - - xVec3Sub(&v, at, pos); - xMat3x3LookVec(m, &v); -} - -F32 xQuatGetAngle(const xQuat* q) -{ - if (q->s > _1584) - { - return _765; - } - else if (q->s < _1586) - { - return _1585; - } - else - { - return _874 * xacos(q->s); - } -} - -U32 xEntIsVisible(const xEnt* ent) -{ - return (ent->flags & 0x81) == 0x1; -} - -F32 xVec3Length(const xVec3* v) -{ - return xsqrt(SQR(v->x) + SQR(v->y) + SQR(v->z)); -} - -void xVec3Sub(xVec3* o, const xVec3* a, const xVec3* b) -{ - o->x = a->x - b->x; - o->y = a->y - b->y; - o->z = a->z - b->z; -} - -void xVec3Inv(xVec3* o, const xVec3* v) -{ - o->x = -v->x; - o->y = -v->y; - o->z = -v->z; -} - -F32 xacos(F32 x) -{ - return std::acosf(x); -} - -#ifndef INLINE -float std::acosf(float x) -{ - return (float)acos((double)x); -} -#endif - -void xVec3AddTo(xVec3* o, const xVec3* v) -{ - o->x += v->x; - o->y += v->y; - o->z += v->z; -} - -xVec3& xVec3::invert() -{ - this->x = -this->x; - this->y = -this->y; - this->z = -this->z; - - return *this; -} - -F32 xexp(F32 x) -{ - return std::expf(x); -} - -#ifndef INLINE -float std::expf(float x) -{ - return (float)exp((double)x); -} -#endif - -F32 xrmod(F32 ang) -{ - F32 frac = _1766 * ang; - - if (frac < _765) - { - return (frac - std::ceilf(frac) + _788) * _1585; - } - else if (frac >= _788) - { - return (frac - std::floorf(frac)) * _1585; - } - - return ang; -} - -xVec3& xVec3::operator/=(F32 f) -{ - F32 f2 = _788; - - this->x *= f2 / f; - this->y *= f2 / f; - this->z *= f2 / f; - - return *this; -} - -xVec3& xVec3::right_normalize() -{ - return this->safe_normalize(xVec3::m_UnitAxisX); -} - -xVec3& xVec3::safe_normalize(const xVec3& val) -{ - F32 len = this->length2(); - - if (len < _1772) - { - return (*this = val); - } - else - { - return (*this *= _788 / xsqrt(len)); - } -} - -template <> F32 range_limit(F32 v, F32 minv, F32 maxv) -{ - if (v <= minv) - { - return minv; - } - - if (v >= maxv) - { - return maxv; - } - - return v; -} - -xVec2& xVec2::operator=(F32 f) -{ - this->x = this->y = f; - - return *this; -} diff --git a/src/SB/Core/x/xClimate.cpp b/src/SB/Core/x/xClimate.cpp deleted file mode 100644 index 4b42249..0000000 --- a/src/SB/Core/x/xClimate.cpp +++ /dev/null @@ -1,199 +0,0 @@ -#include "xClimate.h" - -#include -#include -#include "xMath.h" -#include "xMath3.h" -#include "xString.h" -#include "xVec3.h" -#include "zGlobals.h" -#include "zParEmitter.h" -#include "zParPTank.h" - -_tagClimate* sClimate; - -const float snow_life = 3.0f; -const xVec3 snow_vel = { 0.0f, -2.0f, 0.0f }; -const xVec3 snow_dvel = { 0.1f, 0.1f, 0.1f }; - -void xClimateVecFromAngle(F32 angleDegrees, xVec3* vec) -{ - xMat3x3 Mat; - - xMat3x3Identity(&Mat); - xMat3x3Euler(&Mat, (PI * angleDegrees) / ONEEIGHTY, 0.0f, 0.0f); - xVec3Init(vec, 0.0f, 0.0f, 1.0f); - xMat3x3LMulVec(vec, &Mat, vec); -} - -void xClimateInit(_tagClimate* climate) -{ - climate->rain.strength = 0.0f; - - climate->rain.rain_emitter = zParEmitterFind(xStrHash("PAREMIT_RAIN")); - climate->rain.rain_emitter->emit_flags &= 0xfe; - - climate->rain.snow_emitter = zParEmitterFind(xStrHash("PAREMIT_SNOW")); - climate->rain.snow_emitter->emit_flags &= 0xfe; -} - -// Equivalent -// float ops are being optimized more aggressively -void xClimateInitAsset(_tagClimate* climate, xEnvAsset* asset) -{ - sClimate = climate; - climate->wind.strength = 0.0f; - xClimateVecFromAngle(climate->wind.angle, &climate->wind.dir); - - if (asset->climateFlags == 0) - { - climate->wind.strength = 0.0f; - climate->rain.strength = 0.0f; - return; - } - if (asset->climateFlags & 1) - { - climate->rain.rain = 1.0f; - climate->rain.strength = 0.5f * (asset->climateStrengthMax - asset->climateStrengthMin); - climate->rain.strength += asset->climateStrengthMin; - } - else if (asset->climateFlags & 2) - { - climate->rain.rain = 0.0f; - climate->rain.strength = 0.5f * (asset->climateStrengthMax - asset->climateStrengthMin); - climate->rain.strength += asset->climateStrengthMin; - } -} - -void xClimateSetSnow(F32 stre) -{ - sClimate->rain.rain = 0; - sClimate->rain.strength = stre; -} - -void xClimateSetRain(F32 stre) -{ - sClimate->rain.rain = 1; - sClimate->rain.strength = stre; -} - -// Equivalent -// Float literal is being loaded three separate times in the original code. -void GetPosBigDogWhattupFool(xVec3* vec) -{ - xCamera* camera = &xglobals->camera; - vec->x = 10.0f * camera->mat.at.x + camera->mat.pos.x; - vec->y = 10.0f * camera->mat.at.y + camera->mat.pos.y; - vec->z = 10.0f * camera->mat.at.z + camera->mat.pos.z; -} - -// NOTE (Square): I think it's equivalent but it's very hard to tell. Our compiler is optimizing the float ops -// much more aggresively and it's throwing the regalloc off. -void UpdateRain(_tagClimate* climate, float seconds) -{ - _tagRain* r = &climate->rain; - xParEmitterCustomSettings info; - memset(&info, 0, sizeof(xParEmitterCustomSettings)); - info.custom_flags = 0x100; - - if (r->rain != 0) - { - S32 total_rain_drops = 25.0f * r->strength; - for (S32 i = 0; i < total_rain_drops; i++) - { - GetPosBigDogWhattupFool(&info.pos); - info.pos.x += 25.0f * xurand() - 12.5f; - info.pos.y += 8.0f; - info.pos.z += 25.0f * xurand() - 12.5f; - xParEmitterEmitCustom(r->rain_emitter, seconds, &info); - } - return; - } - - xVec3 fool; - S32 total_snow_flakes = 25.0f * r->strength; - info.custom_flags |= 0x202; - GetPosBigDogWhattupFool(&fool); - if (gPTankDisable) - { - for (S32 i = 0; i < total_snow_flakes; i++) - { - info.pos = fool; - info.pos.x += 45.0f * xurand() - 22.5f; - info.pos.z += 25.0f * xurand() - 22.5f; - - F32 xx = info.pos.x - fool.x; - F32 zz = info.pos.z - fool.z; - F32 perc = 1.0f - xx * zz / 506.25f; - info.pos.y += 4.0f * perc + 4.0f; - - info.vel.x = snow_dvel.x * xurand() + snow_vel.x; - info.vel.y = snow_dvel.y * xurand() + snow_vel.y; - info.vel.z = snow_dvel.z * xurand() + snow_vel.z; - - info.life.val[0] = snow_life * perc + snow_life; - xParEmitterEmitCustom(r->snow_emitter, seconds, &info); - } - return; - } - - S32 num = (F32)total_snow_flakes * 0.1f; - if (num > 0) - { - xVec3* pos = (xVec3*)xMemPushTemp(num * 2 * sizeof(xVec3)); - xVec3* vel = pos + num; - if (pos != NULL) - { - for (S32 i = 0; i < num; i++) - { - *pos = fool; - pos->x += 45.0f * xurand() - 22.5f; - pos->z += 45.0f * xurand() - 22.5f; - - F32 zz = pos->z - fool.z; - F32 xx = pos->x - fool.x; - float perc = (1.0f - (xx * xx + zz * zz) / 506.25f); - - pos->y += 4.0f * perc + 4.0f; - - vel->x = snow_dvel.x * xurand() + snow_vel.x; - vel->y = snow_dvel.y * xurand() + snow_vel.y; - vel->z = snow_dvel.z * xurand() + snow_vel.z; - - pos++; - vel++; - } - - zParPTankSpawnSnow(pos, vel, num); - xMemPopTemp(pos); - } - } -} - -void UpdateWind(_tagClimate* climate, F32 seconds) -{ - return; -} - -void xClimateUpdate(_tagClimate* climate, F32 seconds) -{ - UpdateRain(climate, seconds); - UpdateWind(climate, seconds); -} - -void xVec3Init(xVec3* vec, F32 x, F32 y, F32 z) -{ - vec->x = x; - vec->y = y; - vec->z = z; -} - -void xMat3x3Identity(xMat3x3* matrix) -{ - xMat3x3Copy(matrix, &g_I3); -} - -void xMat3x3Copy(xMat3x3* m1, const xMat3x3* m2) -{ - memcpy(m1, m2, sizeof(xMat3x3)); -} diff --git a/src/SB/Core/x/xClumpColl.cpp b/src/SB/Core/x/xClumpColl.cpp deleted file mode 100644 index 046bb97..0000000 --- a/src/SB/Core/x/xClumpColl.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "xClumpColl.h" - -#include - -xClumpCollBSPTree* xClumpColl_StaticBufferInit(void* data, U32 param_2) -{ - U32* header; // unused - - U32 numBranchNodes = *(U32*)((int)data + 4); - U32 numTriangles = *(U32*)((int)data + 8); - - xClumpCollBSPTree* tree = (xClumpCollBSPTree*)RwMalloc(16); - if (numBranchNodes != 0) - { - tree->branchNodes = (xClumpCollBSPBranchNode*)((int)data + 12); - tree->triangles = (xClumpCollBSPTriangle*)(tree->branchNodes + numBranchNodes); - } - else - { - tree->branchNodes = NULL; - tree->triangles = (xClumpCollBSPTriangle*)((int)data + 12); - } - tree->numBranchNodes = numBranchNodes; - tree->numTriangles = numTriangles; - return tree; -} - -void xClumpColl_InstancePointers(xClumpCollBSPTree* tree, RpClump* clump) -{ - S32 i; - S32 numAtom; - TempAtomicList* atomicList; - TempAtomicList* iterList; - TempAtomicList* alist; - S32 vertIndex; - S32 numMeshes; - S32 meshIndex; - RpMesh* mesh; -} - -//WIP -xClumpCollBSPTree* xClumpColl_ForAllBoxLeafNodeIntersections(xClumpCollBSPTree* tree, RwBBox* box, - S32 (*callBack)(xClumpCollBSPTriangle*, - void*), - void* data) -{ - S32 nStack; - nodeInfo nodeStack[33]; - xClumpCollBSPBranchNode* branch; - - U32 uVar1; - int iVar2; - int iVar3 = 0; - U32 local_124 = 0; - U32 local_128 = 1 - ((-(int)tree->branchNodes | (int)tree->branchNodes) >> 31); - while (true) - { - while (true) - { - if (iVar3 < 0) - { - return tree; - } - if (local_128 == 1) - break; - branch = tree->branchNodes + local_124; - uVar1 = branch->leftInfo; - if ((float)branch->leftValue <= *(float*)((int)&(box->inf).x + (uVar1 & 0xc))) - { - local_128 = branch->rightInfo & 3; - local_124 = branch->rightInfo >> 0xc; - } - else - { - local_128 = uVar1 & 3; - local_124 = uVar1 >> 0xc; - if ((float)branch->rightValue <= *(float*)((int)&(box->sup).x + (uVar1 & 0xc))) - { - iVar3 = iVar3 + 1; - *(int*)&nodeStack[iVar3 * 2] = branch->rightInfo & 3; - *(int*)&nodeStack[iVar3 * 2 + 1] = branch->rightInfo >> 0xc; - } - } - } - iVar2 = ((*callBack)(tree->triangles + local_124, data)); - if (iVar2 == 0) - break; - *(U32*)&nodeStack[iVar3 * 2] = local_128; - iVar3--; - } - return 0; -} diff --git a/src/SB/Core/x/xCollide.cpp b/src/SB/Core/x/xCollide.cpp deleted file mode 100644 index 61690de..0000000 --- a/src/SB/Core/x/xCollide.cpp +++ /dev/null @@ -1,242 +0,0 @@ -#include "xCollide.h" -#include "zSurface.h" -#include "iCollide.h" -#include "iMath3.h" - -#include - -// extern F32 lbl_803CCAA8; // 0.0 - -_xCollsIdx xCollideGetCollsIdx(const xCollis* coll, const xVec3* tohit, const xMat3x3* mat) -{ - if (tohit->y * tohit->y > tohit->x * tohit->x + tohit->z * tohit->z) - { - if (tohit->y < 0.0f) - { - if ((coll->flags & 0x20000) == 0) - { - if (coll->optr != NULL && coll->mptr->Surf != NULL ? - zSurfaceGetStandOn(coll->mptr->Surf) : - 1) - { - return k_XCOLLS_IDX_FLOOR; - } - } - } - else - { - return k_XCOLLS_IDX_CEIL; - } - } - F32 local_x = mat->right.x * tohit->x + mat->right.z * tohit->z; - F32 local_z = mat->at.x * tohit->x + mat->at.z * tohit->z; - if (local_x > 0.0f) - { - if (local_z > 0.0f) - { - if (local_x > local_z) - { - return k_XCOLLS_IDX_LEFT; - } - else - { - return k_XCOLLS_IDX_FRONT; - } - } - else - { - if (local_x > -local_z) - { - return k_XCOLLS_IDX_LEFT; - } - else - { - return k_XCOLLS_IDX_REAR; - } - } - } - else - { - if (local_z > 0.0f) - { - if (local_x < -local_z) - { - return k_XCOLLS_IDX_RIGHT; - } - else - { - return k_XCOLLS_IDX_FRONT; - } - } - else - { - if (local_x < local_z) - { - return k_XCOLLS_IDX_RIGHT; - } - else - { - return k_XCOLLS_IDX_REAR; - } - } - } -} - -void xCollideInit(xScene* sc) -{ - iCollideInit(sc); -} - -U32 xBoxHitsSphere(const xBox* a, const xSphere* b, xCollis* coll) -{ - U32 uVar1; - - xIsect isx; - - iBoxIsectSphere(a, b, &isx); - - if (!(isx.penned <= 0.0f)) - { - uVar1 = 0; - coll->flags &= 0xfffffffe; - } - else - { - if (isx.contained <= 0.0f) - { - coll->flags |= 0x10; - } - coll->dist = isx.dist; - if (coll->flags & 0x0400) - { - xVec3Copy(&coll->tohit, &isx.norm); - } - if ((coll->flags & 0x800) != 0) - { - if (isx.dist == 0.0f) - { - xVec3Copy(&coll->depen, &g_O3); - } - else - { - xVec3SMul(&coll->depen, &isx.norm, isx.penned / isx.dist); - } - } - if ((coll->flags & 0x1200) != 0) - { - xVec3Normalize(&coll->hdng, &isx.norm); - } - if ((coll->flags & 0x200) != 0) - { - xVec3Inv(&coll->norm, &coll->hdng); - } - uVar1 = 1; - coll->flags |= 1; - } - return uVar1; -} - -U32 xSphereHitsBox(const xSphere* a, const xBox* b, xCollis* coll) -{ - U32 uVar1; - - xIsect isx; - - iBoxIsectSphere(b, a, &isx); - - if (!(isx.penned <= 0.0f)) - { - uVar1 = 0; - coll->flags &= 0xfffffffe; - } - else - { - if (isx.contained <= 0.0f) - { - coll->flags |= 0x10; - } - coll->dist = isx.dist; - if (coll->flags & 0x0400) - { - xVec3Copy(&coll->tohit, &isx.norm); - } - if ((coll->flags & 0x800) != 0) - { - if (isx.dist == 0.0f) - { - xVec3Copy(&coll->depen, &g_O3); - } - else - { - xVec3SMul(&coll->depen, &isx.norm, isx.penned / isx.dist); - } - } - if ((coll->flags & 0x1200) != 0) - { - xVec3Normalize(&coll->hdng, &isx.norm); - } - if ((coll->flags & 0x200) != 0) - { - xVec3Inv(&coll->norm, &coll->hdng); - } - uVar1 = 1; - coll->flags |= 1; - } - return uVar1; -} - -U32 xSphereHitsSphere(const xSphere* a, const xSphere* b, xCollis* coll) -{ - U32 uVar1; - - xIsect isx; - - iSphereIsectSphere(b, a, &isx); - - if (!(isx.penned <= 0.0f)) - { - uVar1 = 0; - coll->flags &= 0xfffffffe; - } - else - { - if (isx.contained <= 0.0f) - { - coll->flags |= 0x10; - } - coll->dist = a->r + isx.penned; - if ((coll->flags & 0x1600) != 0) - { - if (isx.dist == 0.0f) - { - xVec3Copy(&coll->tohit, &g_O3); - } - else - { - xVec3SMul(&coll->tohit, &isx.norm, -coll->dist / isx.dist); - } - } - if ((coll->flags & 0x800) != 0) - { - if (isx.dist == 0.0f) - { - xVec3Copy(&coll->depen, &g_O3); - } - else - { - xVec3SMul(&coll->depen, &isx.norm, -isx.penned / isx.dist); - } - } - if ((coll->flags & 0x1200) != 0) - { - xVec3Normalize(&coll->hdng, &coll->tohit); - } - if ((coll->flags & 0x200) != 0) - { - xVec3Inv(&coll->norm, &coll->hdng); - } - uVar1 = 1; - coll->flags |= 1; - } - return uVar1; -} diff --git a/src/SB/Core/x/xCollideFast.cpp b/src/SB/Core/x/xCollideFast.cpp deleted file mode 100644 index 32b6f97..0000000 --- a/src/SB/Core/x/xCollideFast.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "xCollideFast.h" -#include "iCollideFast.h" -#include "xMath.h" - -#include - -void xCollideFastInit(xScene* sc) -{ - iCollideFastInit(sc); -} - -U32 xRayHitsSphereFast(const xRay3* r, const xSphere* s) -{ - xVec3 length; - xVec3Sub(&length, &r->origin, &s->center); - F32 dVar3 = xVec3Dot(&length, &length) - SQR(s->r); - if (dVar3 <= 0.0f) - { - return 1; - } - - if (r->flags & (1 << 11) && dVar3 > r->max_t * (2.0f * s->r + r->max_t)) - { - return 0; - } - - F32 dot = xVec3Dot(&length, &r->dir); - return (dot >= 0.0f) ? 0 : (SQR(dot) >= dVar3); -} - -U32 xRayHitsBoxFast(const xRay3* r, const xBox* b) -{ - xIsect isect; - iBoxIsectRay(b, r, &isect); - return isect.penned <= 0.0f || isect.contained <= 0.0f; -} diff --git a/src/SB/Core/x/xColor.cpp b/src/SB/Core/x/xColor.cpp deleted file mode 100644 index 42f72b5..0000000 --- a/src/SB/Core/x/xColor.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "xColor.h" - -const iColor_tag g_RED = { 255, 0, 0, 255 }; -const iColor_tag g_GREEN = { 0, 255, 0, 255 }; -const iColor_tag g_BLUE = { 0, 0, 255, 255 }; -const iColor_tag g_CYAN = { 0, 255, 255, 255 }; -const iColor_tag g_YELLOW = { 255, 255, 0, 255 }; -const iColor_tag g_WHITE = { 255, 255, 255, 255 }; -const iColor_tag g_GRAY50 = { 128, 128, 128, 255 }; -const iColor_tag g_NEON_RED = { 255, 32, 0, 255 }; -const iColor_tag g_NEON_GREEN = { 32, 255, 0, 255 }; -const iColor_tag g_NEON_BLUE = { 32, 32, 255, 255 }; -const iColor_tag g_PIMP_GOLD = { 215, 220, 19, 255 }; -const iColor_tag g_ORANGE = { 255, 165, 0, 255 }; -const iColor_tag g_LAVENDER = { 200, 105, 229, 255 }; -const iColor_tag g_PINK = { 255, 128, 255, 255 }; diff --git a/src/SB/Core/x/xCounter.cpp b/src/SB/Core/x/xCounter.cpp deleted file mode 100644 index 69b7997..0000000 --- a/src/SB/Core/x/xCounter.cpp +++ /dev/null @@ -1,160 +0,0 @@ -#include "xCounter.h" - -#include "xDebug.h" -#include "xEvent.h" - -namespace -{ - void add_tweaks(_xCounter&) - { - return; - } -} // namespace - -void xCounterInit() -{ - xDebugRemoveTweak("Widgets|Counters"); -} - -void xCounterInit(void* b, void* asset) -{ - xCounterInit((xBase*)b, (xCounterAsset*)asset); -} - -void xCounterInit(xBase* b, xCounterAsset* asset) -{ - _xCounter* t = (_xCounter*)b; - - xBaseInit(t, asset); - - t->eventFunc = xCounterEventCB; - t->asset = asset; - - if (t->linkCount) - { - t->link = (xLinkAsset*)(t->asset + 1); - } - else - { - t->link = 0; - } - - t->state = 0; - t->count = asset->count; - t->counterFlags = 0; - - add_tweaks(*t); -} - -void xCounterReset(xBase* b) -{ - _xCounter* t = (_xCounter*)b; - - xBaseInit(t, t->asset); - - if (t->linkCount) - { - t->link = (xLinkAsset*)(t->asset + 1); - } - else - { - t->link = 0; - } - - t->count = t->asset->count; - t->state = 0; -} - -void xCounterSave(_xCounter* ent, xSerial* s) -{ - xBaseSave(ent, s); - - s->Write(ent->state); - s->Write(ent->count); -} - -void xCounterLoad(_xCounter* ent, xSerial* s) -{ - xBaseLoad(ent, s); - - s->Read(&ent->state); - s->Read(&ent->count); -} - -int xCounterEventCB(xBase*, xBase* to, U32 toEvent, const F32*, xBase*) -{ - _xCounter* t = (_xCounter*)to; - - switch (toEvent) - { - case eEventDecrement: - { - if (t->state != 1 && (!(t->counterFlags & 0x1) || t->count != 2)) - { - t->count--; - - if (t->count == 0) - { - zEntEvent(t, t, eEventExpired); - } - else if (t->count > 0 && t->count <= 20) - { - zEntEvent(t, t, t->count + (eEventCount1 - 1)); - } - } - break; - } - case eEventIncrement: - { - if (t->state != 1) - { - t->count++; - - if (t->count == 0) - { - zEntEvent(t, t, eEventExpired); - } - else if (t->count > 0 && t->count <= 20) - { - zEntEvent(t, t, t->count + (eEventCount1 - 1)); - } - } - break; - } - case eEventReset: - { - t->state = 0; - t->count = t->asset->count; - break; - } - case eEventExpired: - { - if (!(t->counterFlags & 0x1) || t->count != 2) - { - t->count = 0; - t->state = 1; - } - break; - } - default: - { - if (t->state != 1 && toEvent >= eEventCount1 && toEvent <= eEventCount20) - { - S16 newCount = toEvent - (eEventCount1 - 1); - - if (!(t->counterFlags & 0x1) || t->count != 2) - { - t->count = newCount; - } - } - } - } - - return 1; -} - -// TODO: move to xDebug.cpp -inline void xDebugRemoveTweak(const char*) -{ - return; -} diff --git a/src/SB/Core/x/xCurveAsset.cpp b/src/SB/Core/x/xCurveAsset.cpp deleted file mode 100644 index d7df991..0000000 --- a/src/SB/Core/x/xCurveAsset.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "xCurveAsset.h" - -#include "xMath.h" - -#include - -F32 xCurveAssetEvaluate(const xCurveAsset* curve_asset, F32 t) -{ - F32 max_t = curve_asset->delta * (curve_asset->numPoints - 1); - - if (curve_asset->clamp == xCC_CONSTANT) - { - F32 curve_length = MIN(t, max_t); - - t = MAX(curve_length, 0.0f); - } - else - { - S32 curve_shift = t / max_t; - - if (t < 0.0f) - { - curve_shift--; - } - - t -= curve_shift * max_t; - - if (curve_asset->clamp == xCC_OSCILLATE && abs(curve_shift % 2) == 1) - { - t = max_t - t; - } - } - - U32 last_point = t / curve_asset->delta; - F32 u = (t - (last_point * curve_asset->delta)) / curve_asset->delta; - - return (1.0f - u) * curve_asset->points[last_point] + u * curve_asset->points[last_point + 1]; -} diff --git a/src/SB/Core/x/xCutscene.cpp b/src/SB/Core/x/xCutscene.cpp deleted file mode 100644 index 02bd422..0000000 --- a/src/SB/Core/x/xCutscene.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include "xCutscene.h" -#include "xSnd.h" -#include "xAnim.h" -#include "xDebug.h" -#include "xModelBucket.h" -#include "xSnd.h" - -#include "iCutscene.h" -#include "iModel.h" - -#include -#include - -extern xCutscene sActiveCutscene; -extern xCutsceneInfo* sCutTocInfo; -extern U32 sCutTocCount; -extern void* RwEngineInstance; -extern xModelInstance sCutsceneFakeModel[8]; - -extern F32 _672; // 1.0 - -extern F32 lbl_803CCB3C; // 0.0 -extern F32 lbl_803CCB40; // 0.033333335 - -// Non-matching: scheduling -void xCutscene_Init(void* toc) -{ - memset(&sActiveCutscene, 0, 0x198); - sCutTocCount = 0; - sCutTocInfo = 0; - if (toc != NULL) - { - sCutTocCount = *(S32*)toc; - sCutTocInfo = (xCutsceneInfo*)((S32*)toc + 1); - } - for (int i = 0; i < 8; i++) - { - *(volatile int*)&sCutsceneFakeModel[i].Mat = - (volatile int)xMemAlloc(gActiveHeap, sizeof(RwMatrixTag) * 65, 0); - *(volatile int*)&sCutsceneFakeModel[i].Bucket = - (volatile int)xMemAlloc(gActiveHeap, sizeof(xModelBucket*) * 2, 0); - *(volatile int*)sCutsceneFakeModel[i].Bucket = - (volatile int)xMemAlloc(gActiveHeap, sizeof(xModelBucket), 0); - *(volatile int*)&sCutsceneFakeModel[i].Bucket[1] = - (volatile int)*sCutsceneFakeModel[i].Bucket; - *(volatile int*)&sCutsceneFakeModel[i].PipeFlags = (volatile int)0x6530; - *(volatile float*)&sCutsceneFakeModel[i].RedMultiplier = (volatile float)1.0f; - *(volatile float*)&sCutsceneFakeModel[i].GreenMultiplier = (volatile float)1.0f; - *(volatile float*)&sCutsceneFakeModel[i].BlueMultiplier = (volatile float)1.0f; - *(volatile float*)&sCutsceneFakeModel[i].Alpha = (volatile float)1.0f; - } -} - -// Damn RwEngineInstance ruining this (as well as the members being accessed incorrectly by Ghidra) -xCutscene* xCutscene_Create(U32 id) -{ - xCutscene* csn; - xCutsceneInfo* cnfo; - U32 maxload; - - xSndPauseAll(1, 1); - memset(&sActiveCutscene, 0, 0x198); - sActiveCutscene.PlaybackSpeed = _672; - - for (int i = 0; i < sCutTocCount; i++) - { - cnfo = &sCutTocInfo[i]; - if (sCutTocInfo[i].AssetID == id) - { - break; - } - } - maxload = cnfo->MaxBufEven + cnfo->MaxBufOdd; - if (cnfo->MaxModel > maxload) - { - maxload = cnfo->MaxModel; - } - // sActiveCutscene.RawBuf = RwFree(maxload + 0x3c); - sActiveCutscene.AlignBuf = sActiveCutscene.RawBuf; - while ((int)sActiveCutscene.AlignBuf & 0x3f != 0) - { - sActiveCutscene.AlignBuf = (void*)((int)sActiveCutscene.AlignBuf + 4); - } - sActiveCutscene.TimeChunkOffs = (U32*)(cnfo[1].SoundLeft + cnfo->NumData * 0x10 + -0x30); - sActiveCutscene.Info = cnfo; - sActiveCutscene.Data = (xCutsceneData*)(cnfo + 1); - sActiveCutscene.Visibility = sActiveCutscene.TimeChunkOffs + cnfo->NumTime + 1; - sActiveCutscene.BreakList = - (xCutsceneBreak*)(sActiveCutscene.TimeChunkOffs + cnfo->NumTime + 1 + cnfo->VisSize); - sActiveCutscene.Play = (xCutsceneTime*)sActiveCutscene.AlignBuf; - sActiveCutscene.Stream = (xCutsceneTime*)((int)sActiveCutscene.AlignBuf + cnfo->MaxBufEven); - return &sActiveCutscene; -} - -S32 xCutscene_Destroy(xCutscene* csn) -{ - csn->Ready = 0; - xSndSetExternalCallback(0); - if (csn->SndStarted != 0) - { - xSndStop(csn->SndHandle[0]); - if (csn->SndNumChannel == 2) - { - xSndStop(csn->SndHandle[1]); - } - xSndUpdate(); - csn->SndStarted = 0; - } - xSndPauseAll(0, 0); - xSndUpdate(); - if (csn->Opened != 0) - { - iCSFileClose(csn); - } - for (int i = 0; i < csn->Info->NumData; i++) - { - // if ((((U32*)csn->Data->DataType + i) & 0x80000000) && - // ((RpAtomic*)((U32*)((U32*)csn->Data->DataType + i) + 3) != NULL)) - // { - // if ((((U32*)csn->Data->DataType + i) & 0xfffffff) == 6) - // { - // RwFree(); - // } - // else - // { - // iModelUnload((RpAtomic*)((U32*)((U32*)csn->Data->DataType + i) + 3)); - // } - // (U32)((U32*)csn->Data->DataType + i) = (((U32*)csn->Data->DataType + i) & 0xfffffff); - // } - } - RwFree(csn->RawBuf); - memset(csn, 0, sizeof(xCutscene)); - return 1; -} - -S32 xCutscene_LoadStart(xCutscene* csn) -{ - U32 cnt; - - cnt = iCSFileOpen(csn); - - if (cnt <= 0) - { - return 0; - } - - csn->Opened = 1; - return 1; -} - -F32 xCutsceneConvertBreak(float param_1, xCutsceneBreak* param_2, U32 param_3, int param_4) -{ - int i = 0; - if (param_3 == 0) - { - return param_1; - } - while (true) - { - if (param_4 != param_2[i].Index) - { - break; - } - if (param_2[i].Time - param_1 <= lbl_803CCB3C) - { - break; - } - if (lbl_803CCB40 <= param_2[i].Time - param_1) - { - break; - } - i++; - param_3--; - if (param_3 == 0) - { - return param_1; - } - } - return param_2[i].Time - lbl_803CCB40; -} - -xCutscene* xCutscene_CurrentCutscene() -{ - return &sActiveCutscene; -} diff --git a/src/SB/Core/x/xDebug.cpp b/src/SB/Core/x/xDebug.cpp deleted file mode 100644 index 1d0a099..0000000 --- a/src/SB/Core/x/xDebug.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "xDebug.h" -#include "xFont.h" - -#include "iColor.h" - -#include - -U32 gFrameCount; - -// Remaining weak definitions will match once referenced e.g. iColor_tag::operator= - -void xprintf(const char* msg, ...) -{ - // Redacted. :} -} - -S32 xDebugModeAdd(const char* mode, void(*debugFunc)()) -{ - // Redacted. :} - return -1; -} - -void xDebugInit() -{ - // Redacted. :} -} - -void xDebugUpdate() -{ - // Redacted. :} -} - -void xDebugExit() -{ - // Redacted. :} -} - -void xDebugTimestampScreen() -{ - // Redacted. :} -} - -void xtextbox::render(bool cache) const -{ - render(temp_layout(cache), 0, -1); -} - -F32 NSCREENY(F32 scale) -{ - return (1.0f / 480) * scale; -} - -F32 NSCREENX(F32 scale) -{ - return (1.0f / 640) * scale; -} \ No newline at end of file diff --git a/src/SB/Core/x/xDecal.cpp b/src/SB/Core/x/xDecal.cpp deleted file mode 100644 index b459468..0000000 --- a/src/SB/Core/x/xDecal.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "xDecal.h" - -#include - -//Doesn't OK if you use it from header, so assuming it's global. -extern U32 active_emitters_size; - -void xDecalInit() -{ - active_emitters_size = 0; -} diff --git a/src/SB/Core/x/xEntBoulder.cpp b/src/SB/Core/x/xEntBoulder.cpp deleted file mode 100644 index e585d94..0000000 --- a/src/SB/Core/x/xEntBoulder.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "xMath3.h" -#include "xVec3.h" -#include "xEntBoulder.h" - -#include - -void xEntBoulder_FitToModel(xEntBoulder* ent) -{ - xVec3Copy(&ent->bound.cyl.center, (xVec3*)(&ent->model->Data->boundingSphere.center)); - ent->bound.cyl.r = ent->model->Data->boundingSphere.radius; - xVec3Copy(&ent->localCenter, &ent->bound.cyl.center); - xVec3AddTo(&ent->bound.cyl.center, (xVec3*)&ent->model->Mat->pos); -} - -void xEntBoulder_Init(void* ent, void* asset) -{ - xEntBoulder_Init((xEntBoulder*)ent, (xEntAsset*)asset); -} - -void xEntBoulder_AddInstantForce(xEntBoulder* ent, xVec3* force) -{ - if (ent->update != 0) - { - xVec3* frcptr = &ent->instForce; - xVec3AddTo(frcptr, force); - } -} - -void xEntBoulder_AddForce(xEntBoulder* ent, xVec3* force) -{ - if (ent->update != 0) - { - xVec3* frcptr = &ent->force; - xVec3AddTo(frcptr, force); - } -} - -void xEntBoulder_BUpdate() -{ - //For some reason this seems to be a completely empty function -} - -void xEntBoulder_BUpdate(xEnt*, xVec3*) -{ -} - -void xEntBoulder_Setup(xEntBoulder* ent) -{ - ent->asset->redMult = 0.0f; - ent->asset->greenMult = 0.0f; - ent->asset->blueMult = 0.0f; - - if (ent->model != NULL) - { - ent->asset->seeThru = ent->model->Alpha; - } - else - { - ent->asset->seeThru = 1.0f; - } - - xEntSetup(ent); -} diff --git a/src/SB/Core/x/xEntDrive.cpp b/src/SB/Core/x/xEntDrive.cpp deleted file mode 100644 index 03ca310..0000000 --- a/src/SB/Core/x/xEntDrive.cpp +++ /dev/null @@ -1,422 +0,0 @@ -#include "xEntDrive.h" - -#include "xMath.h" - -#include - -void xEntDriveInit(xEntDrive* drv, xEnt* driven) -{ - if (drv == NULL) - { - return; - } - - drv->flags = 0; - drv->driven = driven; - drv->driver = NULL; - drv->s = 0.0f; - drv->tm = 0.0f; - drv->tmr = 0.0f; - drv->odriver = NULL; - drv->os = 0.0f; - drv->otm = 0.0f; - drv->otmr = 0.0f; -} - -void xEntDriveMount(xEntDrive* drv, xEnt* driver, F32 mt, const xCollis* coll) -{ - if (drv->driven == NULL || drv->driven->frame == NULL || driver == NULL || - driver->frame == NULL) - { - xEntDriveInit(drv, drv->driven); - return; - } - drv->dloc = 0.0f; - if (driver == drv->odriver && drv->os) - { - drv->driver = driver; - driver->driving_count++; - if (mt < 0.0f) - { - drv->s = 1.0f; - drv->tmr = 0.0f; - } - else - { - drv->s = drv->os; - drv->tmr = mt * (1.0f - drv->s); - } - - drv->tm = mt; - drv->odriver = NULL; - drv->os = 0.0f; - drv->otm = 0.0f; - drv->otmr = 0.0f; - } - else - { - drv->driver = driver; - driver->driving_count++; - if (mt < 0.0f) - { - drv->s = 1.0f; - drv->tmr = 0.0f; - } - else - { - drv->s = 0.0f; - drv->tmr = mt; - } - drv->tm = mt; - } - - xVec3 euler; - xMat3x3 a_descaled; - if (drv->flags & 1) - { - { - F32 len2 = SQR(drv->driver->frame->mat.right.x) + SQR(drv->driver->frame->mat.right.y) + - SQR(drv->driver->frame->mat.right.z); - if (xabs(len2 - 1) <= 0.00001f) - { - a_descaled.right.x = drv->driver->frame->mat.right.x; - a_descaled.right.y = drv->driver->frame->mat.right.y; - a_descaled.right.z = drv->driver->frame->mat.right.z; - } - else if (xabs(len2) <= 0.00001f) - { - a_descaled.right.x = 0.0f; - a_descaled.right.y = 1.0f; - a_descaled.right.z = 0.0f; - } - else - { - F32 len_inv = 1.0f / xsqrt(len2); - a_descaled.right.x = drv->driver->frame->mat.right.x * len_inv; - a_descaled.right.y = drv->driver->frame->mat.right.y * len_inv; - a_descaled.right.z = drv->driver->frame->mat.right.z * len_inv; - } - } - - { - F32 len2 = SQR(drv->driver->frame->mat.up.x) + SQR(drv->driver->frame->mat.up.y) + - SQR(drv->driver->frame->mat.up.z); - if (xabs(len2 - 1.0f) <= 0.00001f) - { - a_descaled.up.x = drv->driver->frame->mat.up.x; - a_descaled.up.y = drv->driver->frame->mat.up.y; - a_descaled.up.z = drv->driver->frame->mat.up.z; - } - else if (xabs(len2) <= 0.00001f) - { - a_descaled.up.x = 0.0f; - a_descaled.up.y = 1.0f; - a_descaled.up.z = 0.0f; - } - else - { - F32 len_inv = 1.0f / xsqrt(len2); - a_descaled.up.x = drv->driver->frame->mat.up.x * len_inv; - a_descaled.up.y = drv->driver->frame->mat.up.y * len_inv; - a_descaled.up.z = drv->driver->frame->mat.up.z * len_inv; - } - } - - { - F32 len2 = SQR(drv->driver->frame->mat.at.x) + SQR(drv->driver->frame->mat.at.y) + - SQR(drv->driver->frame->mat.at.z); - if (xabs(len2 - 1.0f) <= 0.00001f) - { - a_descaled.at.x = drv->driver->frame->mat.at.x; - a_descaled.at.y = drv->driver->frame->mat.at.y; - a_descaled.at.z = drv->driver->frame->mat.at.z; - } - else if (xabs(len2) <= 0.00001f) - { - a_descaled.at.x = 0.0f; - a_descaled.at.y = 1.0f; - a_descaled.at.z = 0.0f; - } - else - { - F32 len_inv = 1.0f / xsqrt(len2); - a_descaled.at.x = drv->driver->frame->mat.at.x * len_inv; - a_descaled.at.y = drv->driver->frame->mat.at.y * len_inv; - a_descaled.at.z = drv->driver->frame->mat.at.z * len_inv; - } - } - xMat3x3GetEuler(&a_descaled, &euler); - drv->yaw = euler.x; - } - - if (coll != NULL && coll->flags & 0x2000) - { - drv->flags |= 0x2; - - *(xCollis::tri_data*)&drv->tri = coll->tri; - drv->tri.loc = xCollisTriHit(drv->tri, *driver->model); - xMat4x3Tolocal(&drv->tri.loc, &drv->driver->frame->mat, &drv->tri.loc); - drv->tri.coll = coll; - } - - xVec3Copy(&drv->q, &drv->driven->frame->mat.pos); - xMat4x3Tolocal(&drv->p, &drv->driver->frame->mat, &drv->q); -} - -void xEntDriveDismount(xEntDrive* drv, F32 dmt) -{ - if (drv == NULL) - { - return; - } - - if (drv->driver == NULL) - { - return; - } - - if (drv->driven == NULL || drv->driven->frame == NULL || drv->driver->frame == NULL) - { - xEntDriveInit(drv, drv->driven); - return; - } - drv->odriver = drv->driver; - drv->os = drv->s; - drv->otm = dmt; - drv->otmr = dmt * drv->os; - if (drv->driver != NULL) - { - drv->driver->driving_count--; - } - - drv->driver = NULL; - drv->s = 0.0f; - drv->tm = 0.0f; - drv->tmr = 0.0f; - drv->flags &= ~2; - xVec3Copy(&drv->q, &drv->driven->frame->mat.pos); - xMat4x3Tolocal(&drv->op, &drv->odriver->frame->mat, &drv->q); -} - -void xEntDriveUpdate(xEntDrive* drv, xScene* s, F32 dt, const xCollis* coll) -{ - if ((drv != NULL && (drv->odriver != NULL || drv->driver != NULL))) - { - if (drv->driven == NULL || drv->driven->frame == NULL || - (drv->odriver != NULL && drv->odriver->frame == NULL)) - { - xEntDriveInit(drv, drv->driven); - return; - } - - if (drv->otmr > 0.0f) - { - drv->otmr -= dt; - if (drv->otmr <= 0.0f) - { - drv->os = 0.0f; - drv->otmr = 0.0f; - } - else - { - drv->os = drv->otmr / drv->otm; - } - } - - if (drv->tmr > 0.0f) - { - drv->tmr -= dt; - if (drv->tmr <= 0.0f) - { - drv->s = 1.0f; - drv->tmr = 0.0f; - } - else - { - drv->s = 1.0f - drv->tmr / drv->tm; - } - } - - if (!drv->os && !drv->s) - { - return; - } - - xVec3 euler; - xMat3x3 rot; - xMat3x3 a_descaled; - if (drv->s && drv->flags & 1) - { - if (drv->driver == NULL || drv->driver->frame == NULL) - { - xEntDriveInit(drv, drv->driven); - return; - } - - { - F32 len2 = SQR(drv->driver->frame->mat.right.x) + - SQR(drv->driver->frame->mat.right.y) + - SQR(drv->driver->frame->mat.right.z); - if (xabs(len2 - 1) <= 0.00001f) - { - a_descaled.right.x = drv->driver->frame->mat.right.x; - a_descaled.right.y = drv->driver->frame->mat.right.y; - a_descaled.right.z = drv->driver->frame->mat.right.z; - } - else if (xabs(len2) <= 0.00001f) - { - a_descaled.right.x = 0.0f; - a_descaled.right.y = 1.0f; - a_descaled.right.z = 0.0f; - } - else - { - F32 len_inv = 1.0f / xsqrt(len2); - a_descaled.right.x = drv->driver->frame->mat.right.x * len_inv; - a_descaled.right.y = drv->driver->frame->mat.right.y * len_inv; - a_descaled.right.z = drv->driver->frame->mat.right.z * len_inv; - } - } - - { - F32 len2 = SQR(drv->driver->frame->mat.up.x) + SQR(drv->driver->frame->mat.up.y) + - SQR(drv->driver->frame->mat.up.z); - if (xabs(len2 - 1.0f) <= 0.00001f) - { - a_descaled.up.x = drv->driver->frame->mat.up.x; - a_descaled.up.y = drv->driver->frame->mat.up.y; - a_descaled.up.z = drv->driver->frame->mat.up.z; - } - else if (xabs(len2) <= 0.00001f) - { - a_descaled.up.x = 0.0f; - a_descaled.up.y = 1.0f; - a_descaled.up.z = 0.0f; - } - else - { - F32 len_inv = 1.0f / xsqrt(len2); - a_descaled.up.x = drv->driver->frame->mat.up.x * len_inv; - a_descaled.up.y = drv->driver->frame->mat.up.y * len_inv; - a_descaled.up.z = drv->driver->frame->mat.up.z * len_inv; - } - } - - { - F32 len2 = SQR(drv->driver->frame->mat.at.x) + SQR(drv->driver->frame->mat.at.y) + - SQR(drv->driver->frame->mat.at.z); - if (xabs(len2 - 1.0f) <= 0.00001f) - { - a_descaled.at.x = drv->driver->frame->mat.at.x; - a_descaled.at.y = drv->driver->frame->mat.at.y; - a_descaled.at.z = drv->driver->frame->mat.at.z; - } - else if (xabs(len2) <= 0.00001f) - { - a_descaled.at.x = 0.0f; - a_descaled.at.y = 1.0f; - a_descaled.at.z = 0.0f; - } - else - { - F32 len_inv = 1.0f / xsqrt(len2); - a_descaled.at.x = drv->driver->frame->mat.at.x * len_inv; - a_descaled.at.y = drv->driver->frame->mat.at.y * len_inv; - a_descaled.at.z = drv->driver->frame->mat.at.z * len_inv; - } - } - xMat3x3GetEuler(&a_descaled, &euler); - xMat3x3RotY(&rot, drv->s * (euler.x - drv->yaw)); - xMat3x3Mul(&drv->driven->frame->mat, &drv->driven->frame->mat, &rot); - drv->yaw = euler.x; - } - - drv->dloc = 0.0f; - xVec3 newq; - if (drv->os) - { - if (drv->odriver == NULL || drv->odriver->frame == NULL) - { - xEntDriveInit(drv, drv->driven); - return; - } - - xMat4x3Toworld(&newq, &drv->odriver->frame->mat, &drv->op); - xVec3Sub(&drv->driven->frame->dpos, &newq, &drv->q); - xVec3SMulBy(&drv->driven->frame->dpos, drv->os); - xVec3AddTo(&drv->driven->frame->mat.pos, &drv->driven->frame->dpos); - drv->dloc += drv->driven->frame->dpos; - } - - if (drv->s) - { - if (drv->driver == NULL || drv->driver->frame == NULL) - { - xEntDriveInit(drv, drv->driven); - return; - } - - if (drv->flags & 0x2) - { - xModelInstance& m = *drv->driver->model; - if (xModelAnimCollDirty(m)) - { - xModelAnimCollRefresh(m); - } - xVec3 world_loc; - xMat4x3Toworld(&world_loc, &drv->driver->frame->mat, &drv->tri.loc); - - xVec3 new_loc; - new_loc = xCollisTriHit(drv->tri, m); - drv->driven->frame->dpos = new_loc - world_loc; - - if (drv->tri.index != drv->tri.coll->tri.index || - !(xabs(drv->tri.r - drv->tri.coll->tri.r) <= 0.1f) || - !(xabs(drv->tri.d - drv->tri.coll->tri.d) <= 0.1f)) - { - *(xCollis::tri_data*)&drv->tri = drv->tri.coll->tri; - } - - xMat4x3 oldmat = *(xMat4x3*)m.Mat; - *(xMat4x3*)m.Mat = drv->driver->frame->mat; - - drv->tri.loc = xCollisTriHit(drv->tri, m); - xMat4x3Tolocal(&drv->tri.loc, &drv->driver->frame->mat, &drv->tri.loc); - *(xMat4x3*)m.Mat = oldmat; - } - else - { - xMat4x3Toworld(&newq, &drv->driver->frame->mat, &drv->p); - xVec3Sub(&drv->driven->frame->dpos, &newq, &drv->q); - } - - drv->driven->frame->dpos *= drv->s; - drv->dloc += drv->driven->frame->dpos; - drv->driven->frame->mat.pos += drv->driven->frame->dpos; - if (drv->driven->model != NULL) - { - *(xVec3*)&drv->driven->model->Mat->pos = drv->driven->frame->mat.pos; - } - } - - xVec3Copy(&drv->q, &drv->driven->frame->mat.pos); - if (drv->os) - { - if (drv->odriver == NULL || drv->odriver->frame == NULL) - { - xEntDriveInit(drv, drv->driven); - return; - } - xMat4x3Tolocal(&drv->op, &drv->odriver->frame->mat, &drv->q); - } - if (drv->s) - { - if (drv->driver == NULL || drv->driver->frame == NULL) - { - xEntDriveInit(drv, drv->driven); - return; - } - xMat4x3Tolocal(&drv->p, &drv->driver->frame->mat, &drv->q); - } - } -} diff --git a/src/SB/Core/x/xEntMotion.cpp b/src/SB/Core/x/xEntMotion.cpp deleted file mode 100644 index 8b51220..0000000 --- a/src/SB/Core/x/xEntMotion.cpp +++ /dev/null @@ -1,224 +0,0 @@ -#include "xDebug.h" -#include "xEntMotion.h" -#include "xMath.h" - -#include - -// Artificial -enum en_MOTIONTYPE -{ - MOTION_TYPE_EXRT, - MOTION_TYPE_ORBT, - MOTION_TYPE_SPLN, - MOTION_TYPE_MVPT, - MOTION_TYPE_MECH, - MOTION_TYPE_PEND -}; - -void xEntMotionInit(xEntMotion* a, xEnt* b, xEntMotionAsset* c) -{ - a->asset = c; - a->type = c->type; - a->flags = c->flags; - - if (a->type == MOTION_TYPE_EXRT) - { - xVec3Copy(&a->er.a, &c->er.ret_pos); - xVec3Add(&a->er.b, &c->er.ret_pos, &c->er.ext_dpos); - - a->er.et = c->er.ext_tm; - a->er.wet = c->er.ext_wait_tm; - a->er.rt = c->er.ret_tm; - a->er.wrt = c->er.ret_wait_tm; - - if (a->er.p <= 0) - { - a->er.p = 10.0f; - } - - a->er.brt = a->er.et + a->er.wet; - a->er.ert = a->er.brt + a->er.rt; - a->er.p = a->er.ert + a->er.wrt; - } - else if (a->type == MOTION_TYPE_ORBT) - { - xVec3Copy((xVec3*)(&a->er.b), &c->er.ret_pos); - - a->orb.a = c->orb.w; - a->orb.b = c->orb.h; - - if (c->orb.period <= 0.0f) - { - c->orb.period = 10.0f; - } - - a->orb.p = c->orb.period; - a->orb.w = (2 * PI) / c->orb.period; - } - else if (a->type == MOTION_TYPE_MVPT) - { - // literally nothing - } - else if (a->type == MOTION_TYPE_PEND) - { - if (c->pen.period <= 1e-5f) - { - c->pen.period = 0; - } - - a->pen.w = (2 * PI) / c->pen.period; - } - else if (a->type == MOTION_TYPE_MECH) - { - if (c->mp.speed < 1e-5f) - { - c->mp.speed = 0; - } - - if (c->mech.sld_acc_tm + c->mech.sld_dec_tm > c->mech.sld_tm) - { - c->mech.sld_dec_tm = c->mech.sld_acc_tm = c->mech.sld_tm * 0.5f; - } - - if (c->mech.rot_tm < 3.0f) - { - c->mech.rot_tm = 1.0f; - } - - if (c->mech.type == 2) - { - if (c->mech.rot_tm != c->mech.sld_tm) - { - c->mech.rot_tm = c->mech.sld_tm; - } - } - if (c->mech.rot_acc_tm + c->mech.rot_dec_tm > c->mech.rot_tm) - { - c->mech.rot_dec_tm = c->mech.rot_acc_tm = c->mech.rot_tm * 0.5f; - } - } - - a->owner = b; - a->target = NULL; - - xEntMotionDebugAdd(a); -} - -void xEntMechForward(xEntMotion* motion) -{ - xEntMotionMechData* mech = &(motion->asset->mech); - xEntMotionAsset* mkasst = motion->asset; - - xEntMotionRun(motion); - - if ((motion->mech.state != 0) && (motion->mech.state != 1) && (motion->mech.state != 2)) - { - if (motion->mech.state == 3) - { - motion->mech.ss = -motion->mech.ss; - motion->mech.sr = -motion->mech.sr; - motion->tmr = mkasst->mech.sld_tm - motion->tmr; - motion->mech.state = 0; - } - else if (motion->mech.state == 4) - { - motion->mech.ss = -motion->mech.ss; - motion->mech.sr = -motion->mech.sr; - motion->tmr = mkasst->mech.rot_tm - motion->tmr; - motion->mech.state = 1; - } - else if ((motion->mech.state != 5) && (motion->mech.state != 6) && - (motion->mech.state == 7)) - { - motion->mech.ss = -motion->mech.ss; - motion->mech.sr = -motion->mech.sr; - motion->tmr = 0.0f; - - if ((mech->type == 0) || (mech->type == 2) || (mech->type == 4)) - { - motion->mech.state = 0; - } - else - { - motion->mech.state = 1; - } - } - } -} - -void xEntMechReverse(xEntMotion* motion) -{ - xEntMotionMechData* mech = &(motion->asset->mech); - xEntMotionAsset* mkasst = motion->asset; - - xEntMotionRun(motion); - - if (motion->mech.state == 0) - { - motion->mech.ss = -motion->mech.ss; - motion->mech.sr = -motion->mech.sr; - motion->tmr = mkasst->mech.sld_tm - motion->tmr; - motion->mech.state = 3; - } - else if (motion->mech.state == 1) - { - motion->mech.ss = -motion->mech.ss; - motion->mech.sr = -motion->mech.sr; - motion->tmr = mkasst->mech.rot_tm - motion->tmr; - motion->mech.state = 4; - } - else if ((motion->mech.state != 2) && (motion->mech.state != 3) && (motion->mech.state != 4) && - (motion->mech.state != 5) && (motion->mech.state == 6)) - { - motion->mech.ss = -motion->mech.ss; - motion->mech.sr = -motion->mech.sr; - motion->tmr = 0.0f; - - if ((mech->type == 0) || (mech->type == 2) || (mech->type == 4)) - { - motion->mech.state = 3; - } - else - { - motion->mech.state = 4; - } - } -} - -static xEntMotion** dbg_xems; -static U16 dbg_num; -static U16 dbg_num_allocd; -static S16 dbg_idx; - -void xEntMotionDebugCB(); - -// Non-matching: scheduling -void xEntMotionDebugInit(U16 num_xems) -{ - if (num_xems != 0) - { - xDebugModeAdd("DBG_XENTMOTION", xEntMotionDebugCB); - dbg_num = 0; - dbg_xems = (xEntMotion**)xMemAlloc(gActiveHeap, num_xems << 2, 0); - dbg_num_allocd = num_xems; - dbg_idx = 0; - } -} - -// This scheduling is absolutely shambolic -void xEntMotionDebugAdd(xEntMotion* motion) -{ - if (dbg_num < dbg_num_allocd) - { - dbg_num++; - dbg_xems[dbg_num] = motion; - } -} - -void xEntMotionDebugExit() -{ - dbg_num = 0; - dbg_xems = NULL; - dbg_num_allocd = 0; - dbg_idx = -1; -} diff --git a/src/SB/Core/x/xEnv.cpp b/src/SB/Core/x/xEnv.cpp deleted file mode 100644 index 6899de6..0000000 --- a/src/SB/Core/x/xEnv.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "xEnv.h" - -xEnv* gCurXEnv; - -void xEnvLoadBsp(xEnv* env, const void* data, U32 datasize, S32 dataType) -{ - if (dataType == 0) - { - env->geom = &env->ienv; - } - - iEnvLoad(env->geom, data, datasize, dataType); - gCurXEnv = env; -} - -void xEnvSetup(xEnv* env) -{ - iEnvDefaultLighting(env->geom); - env->lightKit = NULL; - gCurXEnv = env; -} - -void xEnvFree(xEnv* env) -{ - if (env->geom != NULL) - { - iEnvFree(env->geom); - env->geom = NULL; - } -} - -void xEnvRender(xEnv* env) -{ - if (env->geom != NULL) - { - iEnvRender(env->geom); - } -} diff --git a/src/SB/Core/x/xEvent.cpp b/src/SB/Core/x/xEvent.cpp deleted file mode 100644 index e1b07c7..0000000 --- a/src/SB/Core/x/xEvent.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include - -#include "xEvent.h" -#include "xString.h" -#include "xstransvc.h" - -#include "zScene.h" - -char zEventLogBuf[256][20]; - -void zEntEvent(char* to, U32 toEvent) -{ - U32 id = xStrHash(to); - xBase* sendTo = zSceneFindObject(id); - - if (sendTo) - { - zEntEvent(sendTo, toEvent); - } -} - -void zEntEvent(U32 toID, U32 toEvent) -{ - xBase* sendTo = zSceneFindObject(toID); - - if (sendTo) - { - zEntEvent(sendTo, toEvent); - } -} - -void zEntEvent(U32 toID, U32 toEvent, F32 toParam0, F32 toParam1, F32 toParam2, - F32 toParam3) -{ - xBase* sendTo; - F32 toParam[4]; - - toParam[0] = toParam0; - toParam[1] = toParam1; - toParam[2] = toParam2; - toParam[3] = toParam3; - - sendTo = zSceneFindObject(toID); - - if (sendTo) - { - zEntEvent(sendTo, toEvent, toParam); - } -} - -void zEntEvent(xBase* to, U32 toEvent) -{ - zEntEvent(NULL, 0, to, toEvent, NULL, NULL, 0); -} - -void zEntEvent(xBase* to, U32 toEvent, F32 toParam0, F32 toParam1, F32 toParam2, - F32 toParam3) -{ - F32 toParam[4]; - - toParam[0] = toParam0; - toParam[1] = toParam1; - toParam[2] = toParam2; - toParam[3] = toParam3; - - zEntEvent(to, toEvent, toParam, NULL); -} - -void zEntEvent(xBase* to, U32 toEvent, const F32* toParam) -{ - zEntEvent(NULL, 0, to, toEvent, toParam, NULL, 0); -} - -void zEntEvent(xBase* to, U32 toEvent, const F32* toParam, xBase* toParamWidget) -{ - zEntEvent(NULL, 0, to, toEvent, toParam, toParamWidget, 0); -} - -void zEntEvent(xBase* from, xBase* to, U32 toEvent) -{ - zEntEvent(from, 0, to, toEvent, NULL, NULL, 0); -} - -void zEntEvent(xBase* from, xBase* to, U32 toEvent, const F32* toParam) -{ - zEntEvent(from, 0, to, toEvent, toParam, NULL, 0); -} - -void zEntEvent(xBase* from, U32 fromEvent, xBase* to, U32 toEvent, const F32* toParam, - xBase* toParamWidget, S32 forceEvent) -{ - if (toEvent == eEventDisable) - { - xBaseDisable(to); - } - else if (toEvent == eEventEnable) - { - xBaseEnable(to); - } - - if (to->eventFunc && (xBaseIsEnabled(to) || forceEvent)) - { - to->eventFunc(from, to, toEvent, toParam, toParamWidget); - } - - if (xBaseIsEnabled(to) && to->linkCount) - { - xLinkAsset* idx = to->link; - - for (S32 i = 0; i < to->linkCount; i++, idx++) - { - if (toEvent == idx->srcEvent) - { - if (!idx->chkAssetID || (from && idx->chkAssetID == from->id)) - { - xBase* sendTo = zSceneFindObject(idx->dstAssetID); - - if (sendTo) - { - xBase* b = NULL; - - if (idx->paramWidgetAssetID) - { - b = zSceneFindObject(idx->paramWidgetAssetID); - - if (!b) - { - b = (xBase*)xSTFindAsset(idx->paramWidgetAssetID, NULL); - } - } - - zEntEvent(to, toEvent, sendTo, idx->dstEvent, idx->param, b, 0); - } - } - } - } - } -} diff --git a/src/SB/Core/x/xFFX.cpp b/src/SB/Core/x/xFFX.cpp deleted file mode 100644 index 8ac6465..0000000 --- a/src/SB/Core/x/xFFX.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include "xFFX.h" -#include "xEnt.h" -#include "xMemMgr.h" - -#include - -extern xFFX* alist; -extern xFFXShakeState* shake_alist; -extern U32 rot_match_psize; -extern xFFXRotMatchState* rot_match_pool; -extern xFFXRotMatchState* rot_match_alist; - -// Structure same as the bottom function, get that one, you get this one. -//void xFFXPoolInit(U32 num_ffx); - -xFFX* xFFXAlloc() -{ - xFFX* alist2; - alist2 = alist; - if (alist == NULL) - { - return NULL; - } - alist = alist->next; - return alist2; -} - -void xFFXFree(xFFX* ffx) -{ - ffx->next = alist; - alist = ffx; -} - -void xFFXTurnOn(xFFX* f) -{ - f->flags |= 1; -} - -void xFFXTurnOff(xFFX* f) -{ - f->flags &= 0xfffffffe; -} - -S16 xFFXAddEffect(xEnt* ent, xFFX* f) -{ - U8 numFFX; - f->next = (xFFX*)ent->ffx; - f->flags = f->flags | 1; - *(xFFX**)&ent->ffx = f; - numFFX = ent->num_ffx; - ent->num_ffx = numFFX + 1; - return numFFX; -} - -S16 xFFXAddEffect(xEnt* ent, void (*dof)(xEnt*, xScene*, F32, void*), void* fd) -{ - xFFX* f = (xFFX*)xFFXAlloc(); - S16 effectID; - if (f == NULL) - { - effectID = -1; - } - else - { - f->doEffect = dof; - f->fdata = fd; - effectID = xFFXAddEffect(ent, f); - } - return effectID; -} - -// WIP. -U32 xFFXRemoveEffectByFData(xEnt* ent, void* fdata) -{ - xFFX* ffx; - xFFX** found; - - found = (xFFX**)&ent->ffx; - while (true) - { - ffx = *found; - if (ffx == NULL) - { - return 0; - } - if (fdata == ffx->fdata) - break; - found = &ffx->next; - } - ffx = ffx->next; - ent->num_ffx--; - xFFXFree(*found); - *found = ffx; - return 1; -} - -void xFFXApplyOne(xFFX* ffx, xEnt* ent, xScene* sc, F32 dt) -{ - if (ffx->next != NULL) - { - xFFXApplyOne(ffx->next, ent, sc, dt); - } - if ((ffx->flags & 1) != 0) - { - ffx->doEffect(ent, sc, dt, ffx->fdata); - } -} - -void xFFXApply(xEnt* ent, xScene* sc, F32 dt) -{ - if ((xFFX*)ent->ffx != NULL) - { - xFFXApplyOne((xFFX*)ent->ffx, ent, sc, dt); - } -} - -// The structure of this is identical to the pool init below. Figure out that one, you get this one as well. -//void xFFXShakePoolInit(U32 num); - -xFFXShakeState* xFFXShakeAlloc() -{ - xFFXShakeState* alist2; - alist2 = shake_alist; - if (shake_alist == NULL) - { - return NULL; - } - shake_alist = shake_alist->next; - return alist2; -} - -void xFFXShakeFree(xFFXShakeState* s) -{ - s->next = shake_alist; - shake_alist = s; -} - -// Some instructions are in the wrong order. -void xFFXRotMatchPoolInit(U32 num) -{ - rot_match_psize = num; - rot_match_pool = (xFFXRotMatchState*)xMemAllocSize(num * sizeof(xFFXRotMatchState)); - U32 i = 1; - rot_match_pool->next = NULL; - S32 ind = sizeof(xFFXRotMatchState); - while (i < rot_match_psize) - { - S32 nextAddr = ind - 1; - i++; - *(xFFXRotMatchState**)((S32)&rot_match_pool->next + ind) = rot_match_pool + nextAddr; - ind += sizeof(xFFXRotMatchState); - } - rot_match_alist = rot_match_pool + (rot_match_psize - 1); -} - -xFFXRotMatchState* xFFXRotMatchAlloc() -{ - xFFXRotMatchState* alist2; - alist2 = rot_match_alist; - if (rot_match_alist == NULL) - { - return NULL; - } - rot_match_alist = rot_match_alist->next; - return alist2; -} diff --git a/src/SB/Core/x/xFX.cpp b/src/SB/Core/x/xFX.cpp deleted file mode 100644 index 92c74bc..0000000 --- a/src/SB/Core/x/xFX.cpp +++ /dev/null @@ -1,549 +0,0 @@ -#include "xFX.h" - -#include "xstransvc.h" - -#include "iMath.h" -#include "zParEmitter.h" -#include "zSurface.h" -#include "zFX.h" -#include "zGlobals.h" - -#include -#include - -/* boot.HIP texture IDs */ -#define ID_gloss_edge 0xB8C2351E -#define ID_rainbowfilm_smooth32 0x741B0566 - -extern const char _stringBase0_7[]; - -extern F32 _957_0; -extern F32 _958; -extern F32 _995; -extern F32 _1132; -extern F32 _1171; - -RpAtomicCallBackRender gAtomicRenderCallBack = NULL; -F32 EnvMapShininess = 1.0f; -RpLight* MainLight = NULL; - -static U32 num_fx_atomics = 0; - -static U32 xfx_initted = 0; - -static void LightResetFrame(RpLight* light); - -void xFXInit() -{ - if (!xfx_initted) - { - xfx_initted = 1; - - RpLight* light = RpLightCreate(rpLIGHTDIRECTIONAL); - - if (light) - { - RwFrame* frame = RwFrameCreate(); - - if (frame) - { - RpLightSetFrame(light, frame); - LightResetFrame(light); - - MainLight = light; - } - else - { - RpLightDestroy(light); - } - } - - xFXanimUVCreate(); - xFXAuraInit(); - } -} - -static U32 Im3DBufferPos = 0; -static RwTexture* g_txtr_drawRing = NULL; - -static void DrawRingSetup() -{ - g_txtr_drawRing = (RwTexture*)xSTFindAsset(ID_rainbowfilm_smooth32, NULL); -} - -static void DrawRingSceneExit() -{ - g_txtr_drawRing = NULL; -} - -static void DrawRing(xFXRing* m) -{ - // todo: uses int-to-float conversion -} - -xFXRing* xFXRingCreate(const xVec3* pos, const xFXRing* params) -{ - xFXRing* ring = &ringlist[0]; - - if (!pos || !params) - { - return NULL; - } - - for (S32 i = 0; i < RING_COUNT; i++, ring++) - { - if (ring->time <= _957_0) - { - // non-matching: _958 is only loaded once - - memcpy(ring, params, sizeof(xFXRing)); - - ring->time = _995; - ring->pos = *pos; - ring->ring_radius_delta *= _958 / ring->lifetime; - ring->ring_height_delta *= _958 / ring->lifetime; - ring->ring_tilt_delta *= _958 / ring->lifetime; - - return ring; - } - } - - return NULL; -} - -static void xFXRingUpdate(F32 dt) -{ - xFXRing* ring = &ringlist[0]; - - if ((F32)iabs(dt) < _995) - { - return; - } - - for (S32 i = 0; i < RING_COUNT; i++, ring++) - { - if (ring->time <= _957_0) - { - continue; - } - - F32 lifetime = ring->lifetime; - - if (lifetime < dt) - { - lifetime = dt; - } - - ring->time += dt; - - F32 t = ring->time / lifetime; - - // non-matching: float scheduling - - if (t > _958) - { - ring->time = _957_0; - - if (ring->parent) - { - *ring->parent = NULL; - } - - ring->parent = NULL; - } - } -} - -void xFXRingRender() -{ - S32 i; - xFXRing* ring = &ringlist[0]; - - for (i = 0; i < RING_COUNT; i++, ring++) - { - if (ring->time > _957_0) - { - DrawRing(ring); - } - } -} - -static RpMaterial* MaterialSetEnvMap(RpMaterial* material, void* data); -static RpMaterial* MaterialSetBumpMap(RpMaterial* material, void* data); -static RpMaterial* MaterialSetBumpEnvMap(RpMaterial* material, RwTexture* env, F32 shininess, - RwTexture* bump, F32 bumpiness); - -void xFX_SceneEnter(RpWorld* world) -{ - S32 i; - S32 num = RpWorldGetNumMaterials(world); - - for (i = 0; i < num; i++) - { - xSurface* sp = zSurfaceGetSurface(i); - zSurfaceProps* pp = (zSurfaceProps*)sp->moprops; - - if (pp && pp->asset) - { - zSurfMatFX* fxp = &pp->asset->matfx; - - if (fxp->flags) - { - if (fxp->flags == 0x10) - { - fxp->flags |= 0x1; - } - - RpMaterial* mp = RpWorldGetMaterial(world, i); - - if (RpMaterialGetTexture(mp)) - { - gFXSurfaceFlags = fxp->flags; - - if (fxp->flags & 0x1) - { - RwTexture* env = (RwTexture*)xSTFindAsset(fxp->envmapID, NULL); - - if (!env) - { - continue; - } - - MaterialSetEnvMap(mp, env); - RpMatFXMaterialSetEnvMapCoefficient(mp, _1132 * fxp->shininess); - } - - if (fxp->flags & 0x2) - { - RwTexture* bump = (RwTexture*)xSTFindAsset(fxp->bumpmapID, NULL); - - if (!bump) - { - continue; - } - - MaterialSetBumpMap(mp, bump); - RpMatFXMaterialSetBumpMapCoefficient(mp, fxp->bumpiness); - } - - if (fxp->flags & 0x4) - { - RwTexture* env = (RwTexture*)xSTFindAsset(fxp->envmapID, NULL); - RwTexture* bump = (RwTexture*)xSTFindAsset(fxp->bumpmapID, NULL); - - if (!env || !bump) - { - continue; - } - - MaterialSetBumpEnvMap(mp, env, fxp->shininess, bump, fxp->bumpiness); - } - } - } - } - } - - zScene* sc = globals.sceneCur; - - for (i = 0; i < sc->num_act_ents; i++) - { - xEnt* ent = sc->act_ents[i]; - - if (!gAtomicRenderCallBack && ent->model) - { - RpAtomicCallBackRender tmp = RpAtomicGetRenderCallBack(ent->model->Data); - - RpAtomicSetRenderCallBack(ent->model->Data, NULL); - - gAtomicRenderCallBack = RpAtomicGetRenderCallBack(ent->model->Data); - - RpAtomicSetRenderCallBack(ent->model->Data, tmp); - } - - if (ent->model) - { - // non-matching: strings are getting cached for some reason - - U32 bubble; - - bubble = (ent->id == xStrHash(_stringBase0_7)); - bubble |= (ent->id == xStrHash(_stringBase0_7 + 13)); - bubble |= (ent->id == xStrHash(_stringBase0_7 + 28)); - bubble |= (ent->id == xStrHash(_stringBase0_7 + 42)); - bubble |= (ent->id == xStrHash(_stringBase0_7 + 62)); - bubble |= (ent->id == xStrHash(_stringBase0_7 + 75)); - - if (bubble) - { - xSTAssetName(ent->id); - - RpAtomicSetRenderCallBack(ent->model->Data, xFXBubbleRender); - } - } - } - - num_fx_atomics = 0; -} - -void xFX_SceneExit(RpWorld*) -{ -} - -void xFXUpdate(F32 dt) -{ - xFXRingUpdate(dt); - xFXRibbonUpdate(dt); - xFXAuraUpdate(dt); -} - -static const RwV3d _1168 = { 1, 0, 0 }; -static const RwV3d _1169 = { 0, 1, 0 }; - -static void LightResetFrame(RpLight* light) -{ - // non-matching: lwzu instruction - - RwV3d v1 = { 1, 0, 0 }; - RwV3d v2 = { 0, 1, 0 }; - - RwFrame* frame = RpLightGetFrame(light); - - RwFrameRotate(frame, &v1, _1171, rwCOMBINEREPLACE); - RwFrameRotate(frame, &v2, _1171, rwCOMBINEPOSTCONCAT); -} - -static RpMaterial* MaterialDisableMatFX(RpMaterial* material, void*) -{ - RpMatFXMaterialSetEffects(material, rpMATFXEFFECTNULL); - return material; -} - -RpAtomic* AtomicDisableMatFX(RpAtomic* atomic) -{ - RpMatFXAtomicEnableEffects(atomic); - - RpGeometry* geometry = RpAtomicGetGeometry(atomic); - - if (geometry) - { - RpGeometryForAllMaterials(geometry, MaterialDisableMatFX, NULL); - } - - return atomic; -} - -static RpAtomic* PreAllocMatFX_cb(RpAtomic* atomic, void*) -{ - AtomicDisableMatFX(atomic); - return atomic; -} - -void xFXPreAllocMatFX(RpClump* clump) -{ - RpClumpForAllAtomics(clump, PreAllocMatFX_cb, NULL); -} - -RpMaterial* MaterialSetShininess(RpMaterial* material, void*) -{ - RpMatFXMaterialFlags flags = RpMatFXMaterialGetEffects(material); - - if (flags == rpMATFXEFFECTENVMAP || flags == rpMATFXEFFECTBUMPENVMAP) - { - RpMatFXMaterialSetEnvMapCoefficient(material, EnvMapShininess); - } - - return material; -} - -static RpAtomic* AtomicSetShininess(RpAtomic* atomic, void* data) -{ - RpGeometry* geometry = RpAtomicGetGeometry(atomic); - - if (geometry) - { - RpGeometryForAllMaterials(geometry, MaterialSetShininess, data); - } - - return atomic; -} - -struct xFXBubbleParams -{ - U32 pass1 : 1; - U32 pass2 : 1; - U32 pass3 : 1; - U32 padding : 5; - U8 pass1_alpha; - U8 pass2_alpha; - U8 pass3_alpha; - U32 pass1_fbmsk; - U32 fresnel_map; - F32 fresnel_map_coeff; - U32 env_map; - F32 env_map_coeff; -}; - -static xFXBubbleParams defaultBFX = { - // pass1, pass2, pass3, padding - 1, 1, 1, 0, - // pass1_alpha, pass2_alpha, pass3_alpha, pass1_fbsk - 0, 0, 192, 0xFFFFFFFF, - // fresnel_map, fresnel_map_coeff - ID_gloss_edge, 0.75f, - // env_map, env_map_coeff - ID_rainbowfilm_smooth32, 0.5f -}; - -static U32 bfx_curr = 0; -static xFXBubbleParams* BFX = &defaultBFX; - -static U32 sFresnelMap = 0; -static U32 sEnvMap = 0; -static S32 sTweaked = 0; - -static RxPipeline* xFXanimUVPipeline = NULL; -F32 xFXanimUVRotMat0[2] = { 1.0f, 0.0f }; -F32 xFXanimUVRotMat1[2] = { 0.0f, 1.0f }; -F32 xFXanimUVTrans[2] = { 0.0f, 0.0f }; -F32 xFXanimUVScale[2] = { 1.0f, 1.0f }; -F32 xFXanimUV2PRotMat0[2] = { 1.0f, 0.0f }; -F32 xFXanimUV2PRotMat1[2] = { 0.0f, 1.0f }; -F32 xFXanimUV2PTrans[2] = { 0.0f, 0.0f }; -F32 xFXanimUV2PScale[2] = { 1.0f, 1.0f }; -RwTexture* xFXanimUV2PTexture = NULL; - -namespace -{ -#define ALPHA_COUNT 300 - - U8 alpha_count0[ALPHA_COUNT]; - U8 alpha_count1[ALPHA_COUNT]; -} // namespace - -// clip_triangle jumptable -static U32 _1933[] = { 0x80028610, 0x80028640, 0x80028640, 0x80028640, 0x80028640, 0x80028640, - 0x80028640, 0x80028620, 0x80028640, 0x80028640, 0x80028640, 0x80028640, - 0x80028640, 0x80028640, 0x80028630, 0x80028640, 0x80028640, 0x80028640, - 0x80028640, 0x80028640, 0x80028640, 0x80028630, 0x80028640, 0x80028640, - 0x80028640, 0x80028640, 0x80028640, 0x80028640, 0x80028620, 0x80028640, - 0x80028640, 0x80028640, 0x80028640, 0x80028640, 0x80028640, 0x80028610 }; - -static const U8 segments_1637[43] = { 0, 1, 3, 0, 1, 2, 4, 0, 3, 4, 3, 0, 0, 0, 0, - 0, 1, 2, 4, 0, 2, 1, 2, 0, 4, 2, 1, 0, 0, 0, - 0, 0, 3, 4, 3, 0, 4, 2, 1, 0, 3, 1, 0 }; - -struct _tagFirework -{ - S32 state; - F32 timer; - xVec3 vel; - xVec3 pos; - F32 fuel; -}; - -#define FIREWORK_COUNT 10 - -static _tagFirework sFirework[FIREWORK_COUNT]; -static zParEmitter* sFireworkTrailEmit = NULL; -static zParEmitter* sFirework1Emit = NULL; -static zParEmitter* sFirework2Emit = NULL; -static U32 sFireworkSoundID = 0; -static U32 sFireworkLaunchSoundID = 0; - -static RwIm3DVertex sStripVert_2188[4]; - -static RwIm3DVertex blah_2485[4]; - -namespace -{ -#define RIBBON_COUNT 64 - - xFXRibbon* active_ribbons[RIBBON_COUNT]; - U32 active_ribbons_size = 0; - bool ribbons_dirty = false; -} // namespace - -struct _xFXAuraAngle -{ - F32 angle; - F32 cc; - F32 ss; -}; - -struct _xFXAura -{ - xVec3 pos; - iColor_tag color; - F32 size; - void* parent; - U32 frame; - F32 dangle[2]; -}; - -#define AURA_COUNT 32 - -static F32 sAuraPulse[2]; -static F32 sAuraPulseAng[2]; -static _xFXAuraAngle sAuraAngle[2]; -static RwTexture* gAuraTex = NULL; -static _xFXAura sAura[AURA_COUNT]; - -__declspec(section ".rodata") static const char _stringBase0_7[] = "bubble buddy\0" - "bubble missile\0" - "bubble helmet\0" - "bubble bowling ball\0" - "bubble shoeL\0" - "bubble shoeR\0" - "spec3\0" - "default_env_map.RW3\0" - "gloss_edge\0" - "update frame\n\0" - "fx_streak1\0" - "BLENDZERO\0" - "BLENDONE\0" - "BLENDSRCCOLOR\0" - "BLENDINVSRCCOLOR\0" - "BLENDSRCALPHA\0" - "BLENDINVSRCALPHA\0" - "BLENDDESTALPHA\0" - "BLENDINVDESTALPHA\0" - "BLENDDESTCOLOR\0" - "BLENDINVDESTCOLOR\0" - "BLENDSRCALPHASAT\0" - "FX|Ribbon"; - -void xFXStartup() -{ -} - -void xFXShutdown() -{ -} - -void xFXSceneInit() -{ -} - -void xFXSceneReset() -{ -} - -void xFXScenePrepare() -{ -} - -void xFXRibbon::update_curve_tweaks() -{ -} - -void xFXRibbon::debug_init(const char*, const char*) -{ -} - -void xFXRibbon::debug_update_curve() -{ -} - -void xFXRibbon::debug_update(F32) -{ -} diff --git a/src/SB/Core/x/xFXHighDynamicRange.h b/src/SB/Core/x/xFXHighDynamicRange.h new file mode 100644 index 0000000..e69de29 diff --git a/src/SB/Core/x/xFactory.cpp b/src/SB/Core/x/xFactory.cpp deleted file mode 100644 index a98ec73..0000000 --- a/src/SB/Core/x/xFactory.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#include "xFactory.h" -#include "xMemMgr.h" - -#include -#include - -xFactory::xFactory(S32 maxTypes) -{ - U32 amt = maxTypes * sizeof(XGOFTypeInfo); - this->infopool = (XGOFTypeInfo*)xMemAllocSize(amt); - memset(this->infopool, 0, amt); - XOrdInit(&this->infolist, maxTypes, 0); -} - -xFactory::~xFactory() -{ - this->infopool = NULL; - XOrdDone(&this->infolist, 0); -} - -static S32 OrdTest_infotype(const void* vkey, void* vitem); -static S32 OrdComp_infotype(void* vkey, void* vitem); - -S32 xFactory::RegItemType(XGOFTypeInfo* info) -{ - S32 rc = 0; - XGOFTypeInfo* tptr = info; - XGOFTypeInfo* nextrec; - - while (tptr->tid) - { - rc = 1; - - if (!tptr->creator) - { - rc = 0; - break; - } - - if (!tptr->destroyer) - { - rc = 0; - break; - } - - if (infolist.cnt >= infolist.max) - { - rc = -2; - break; - } - - S32 idx = XOrdLookup(&infolist, tptr, OrdTest_infotype); - - if (idx >= 0) - { - rc = -1; - break; - } - - nextrec = &infopool[infolist.cnt]; - nextrec->tid = tptr->tid; - nextrec->creator = tptr->creator; - nextrec->destroyer = tptr->destroyer; - - XOrdInsert(&infolist, nextrec, OrdComp_infotype); - - tptr++; - } - - return rc; -} - -S32 xFactory::RegItemType(S32 tid, XGOFTypeInfoCreator create, XGOFTypeInfoDestroyer destroy) -{ - XGOFTypeInfo typerec[2] = {}; - - typerec[0].tid = tid; - typerec[0].creator = create; - typerec[0].destroyer = destroy; - - return RegItemType(typerec); -} - -void xFactory::GrowDataEnable(xBase* user, S32 isResume) -{ - if (isResume) - { - growContextData.Resume(user); - } - else - { - growContextData.Init(user); - } -} - -void xFactory::GrowDataDisable() -{ - growContextData.Done(); -} - -xFactoryInst* xFactory::CreateItem(S32 typeID, void* userdata, RyzMemGrow* callerzgrow) -{ - S32 idx; - xFactoryInst* item; - XGOFTypeInfo pattern = {}; - XGOFTypeInfo* darec = NULL; - RyzMemGrow* grow = callerzgrow; - - pattern.tid = typeID; - - idx = XOrdLookup(&infolist, &pattern, OrdTest_infotype); - - if (idx >= 0) - { - darec = (XGOFTypeInfo*)infolist.list[idx]; - } - - if (!darec) - { - return NULL; - } - - if (!darec->creator) - { - return NULL; - } - - if (!darec->destroyer) - { - return NULL; - } - - if (!grow && growContextData.IsEnabled()) - { - grow = &growContextData; - } - - item = darec->creator(darec->tid, grow, userdata); - - if (!item) - { - return item; - } - - item->itemType = darec->tid; - item->prevprod = NULL; - item->nextprod = NULL; - - if (products) - { - item->nextprod = products; - products->prevprod = item; - products = item; - } - else - { - products = item; - } - - return item; -} - -void xFactory::DestroyAll() -{ - while (products) - { - DestroyItem(products); - } -} - -void xFactory::DestroyItem(xFactoryInst* item) -{ - S32 idx; - XGOFTypeInfo pattern = {}; - - pattern.tid = item->itemType; - - if (item) - { - if (products == item) - { - products = item->nextprod; - - if (products) - { - products->prevprod = NULL; - } - } - - if (item->prevprod) - { - item->prevprod->nextprod = item->nextprod; - } - - if (item->nextprod) - { - item->nextprod->prevprod = item->prevprod; - } - - item->prevprod = NULL; - item->nextprod = NULL; - - idx = XOrdLookup(&infolist, &pattern, OrdTest_infotype); - - ((XGOFTypeInfo*)infolist.list[idx])->destroyer(item); - } -} - -static S32 OrdTest_infotype(const void* vkey, void* vitem) -{ - S32 rc; - - if (((XGOFTypeInfo*)vkey)->tid < ((XGOFTypeInfo*)vitem)->tid) - { - rc = -1; - } - else if (((XGOFTypeInfo*)vkey)->tid > ((XGOFTypeInfo*)vitem)->tid) - { - rc = 1; - } - else - { - rc = 0; - } - - return rc; -} - -static S32 OrdComp_infotype(void* vkey, void* vitem) -{ - S32 rc; - - if (((XGOFTypeInfo*)vkey)->tid < ((XGOFTypeInfo*)vitem)->tid) - { - rc = -1; - } - else if (((XGOFTypeInfo*)vkey)->tid > ((XGOFTypeInfo*)vitem)->tid) - { - rc = 1; - } - else - { - rc = 0; - } - - return rc; -} diff --git a/src/SB/Core/x/xFog.cpp b/src/SB/Core/x/xFog.cpp deleted file mode 100644 index e0a2f44..0000000 --- a/src/SB/Core/x/xFog.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "xFog.h" -#include "xEvent.h" - -#include "iCamera.h" - -#include - -void xFogClearFog() -{ - iCameraSetFogParams(NULL, 0.0f); -} - -void xFogInit(void* b, void* tasset) -{ - xFogInit((xBase*)b, (xFogAsset*)tasset); -} - -void xFogInit(xBase* ent, xFogAsset* tasset) -{ - xBaseInit(ent, (xBaseAsset*)tasset); - ent->eventFunc = xFogEventCB; - ((_xFog*)ent)->tasset = tasset; - if (ent->linkCount != 0) - { - ent->link = (xLinkAsset*)(((_xFog*)ent)->tasset + 1); - } - else - { - ent->link = NULL; - } -} - -void xFogReset(_xFog* ent) -{ - xBaseReset((xBase*)ent, (xBaseAsset*)ent->tasset); -} - -void xFogSave(_xFog* ent, xSerial* s) -{ - xBaseSave((xBase*)ent, s); -} - -void xFogLoad(_xFog* ent, xSerial* s) -{ - xBaseLoad((xBase*)ent, s); -} - -S32 xFogEventCB(xBase* to, xBase* from, U32 toEvent, const F32* toParam, xBase* b3) -{ - switch (toEvent) - { - case eEventOn: - iFogParams fog; - fog.type = rwFOGTYPELINEAR; - xFogAsset* fromFog = ((_xFog*)from)->tasset; - fog.start = fromFog->fogStart; - fog.stop = fromFog->fogStop; - fog.density = fromFog->fogDensity; - fog.fogcolor.red = fromFog->fogColor[0]; - fog.fogcolor.green = fromFog->fogColor[1]; - fog.fogcolor.blue = fromFog->fogColor[2]; - fog.fogcolor.alpha = fromFog->fogColor[3]; - fog.bgcolor.red = fromFog->bkgndColor[0]; - fog.bgcolor.green = fromFog->bkgndColor[1]; - fog.bgcolor.blue = fromFog->bkgndColor[2]; - fog.bgcolor.alpha = fromFog->bkgndColor[3]; - fog.table = NULL; - iCameraSetFogParams(&fog, fromFog->transitionTime); - break; - case eEventOff: - iCameraSetFogParams(NULL, 0.0f); - break; - case eEventReset: - xFogReset((_xFog*)from); - break; - } - return eEventEnable; -} - -void xFogUpdate(xBase* ent, xScene* sc, F32 dt) -{ -} diff --git a/src/SB/Core/x/xFont.cpp b/src/SB/Core/x/xFont.cpp deleted file mode 100644 index 594658a..0000000 --- a/src/SB/Core/x/xFont.cpp +++ /dev/null @@ -1,3705 +0,0 @@ -#include "xFont.h" - -#include "xMath.h" -#include "xstransvc.h" -#include "xModel.h" -#include "xColor.h" -#include "xTimer.h" -#include "xTextAsset.h" -#include "xModelBucket.h" - -#include "iTime.h" -#include "zScene.h" - -#include -#include - -/* xtextbox flags */ - -#define FLAG_UNK40 0x40 -#define FLAG_UNK80 0x80 - -#define WRAP_WORD 0x0 -#define WRAP_CHAR 0x10 -#define WRAP_NONE 0x20 -#define WRAP_MASK (WRAP_WORD | WRAP_CHAR | WRAP_NONE) - -#define XJUSTIFY_LEFT 0x0 -#define XJUSTIFY_RIGHT 0x1 -#define XJUSTIFY_CENTER 0x2 -#define XJUSTIFY_MASK (XJUSTIFY_LEFT | XJUSTIFY_RIGHT | XJUSTIFY_CENTER) - -#define YJUSTIFY_TOP 0x0 -#define YJUSTIFY_BOTTOM 0x4 -#define YJUSTIFY_CENTER 0x8 -#define YJUSTIFY_MASK (YJUSTIFY_TOP | YJUSTIFY_BOTTOM | YJUSTIFY_CENTER) - -extern substr _1615; -extern substr _1616; -extern xtextbox::tag_entry_list _1642; - -static const basic_rect screen_bounds = { 0, 0, 1, 1 }; - -namespace -{ - struct font_asset - { - U32 tex_id; - U16 u; - U16 v; - U8 du; - U8 dv; - U8 line_size; - U8 baseline; - struct - { - S16 x; - S16 y; - } space; // 0xC - U32 flags; // 0x10 - U8 char_set[128]; // 0x14 - struct - { - U8 offset; - U8 size; - } char_pos[127]; // 0x94 - }; - - struct font_data - { - font_asset* asset; - U32 index_max; - U8 char_index[256]; - F32 iwidth; - F32 iheight; - basic_rect tex_bounds[127]; - basic_rect bounds[127]; - xVec2 dstfrac[127]; - RwTexture* texture; - RwRaster* raster; - }; - - struct model_cache_entry - { - U32 id; - U32 order; - xModelInstance* model; - }; - - // clang-format off - const char* default_font_texture[] = - { - "font_sb", - "font1_sb", -#if 1 // needed until .sdata2 is decomped - "font_numbers\0 \t\n{}=*+:;," -#else - "font_numbers" -#endif - }; - - font_asset default_font_assets[4] = - { - // font1_sb (SpongeBob font) - 1, 0, 0, 18, 22, 14, 0, 0, 0, 0x1, - { - '~', '{', '}', '#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '?', '!', - '.', ',', '-', ':', '_', '"', '\'', '&', '(', ')', '<', '>', '/', '%', - '\xFC', '\xFB', '\xF9', '\xE2', '\xE4', '\xE0', '\xEA', '\xE8', '\xE9', - '\xEE', '\xF6', '\xF4', '\xE7', '\xDF', '\x2B' - }, - {}, - - // font_sb (Arial font) - 0, 0, 0, 18, 22, 14, 0, 1, 0, 0, - { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', - 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '?', '!', '.', ',', ';', ':', '+', '-', - '=', '/', '&', '(', ')', '%', '"', '\'', '_', '<', '>', '*', '[', ']', - '\xDC', '\xDB', '\xD9', '\xC2', '\xC4', '\xC0', '\xCA', '\xC8', '\xC9', - '\xCE', '\xD6', '\xD4', '\xC7', '\xDF', '\xFC', '\xFB', '\xF9', '\xE2', - '\xE4', '\xE0', '\xEA', '\xE8', '\xE9', '\xEE', '\xF6', '\xF4', '\xE7', - '~', '\xA9', '\xAE', '\x99', '@', '\x7C' - }, - {}, - - // font1_sb (System font) - 1, 148, 232, 6, 8, 18, 0, 0, 0, 0x9, - { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ',', '.', '/', '*', '+', '-', - '=', ':', ';', '%', '<', '>', '[', ']', '|', '(', ')', '_' - }, - {}, - - // font_numbers (SpongeBob numbers font) - 2, 0, 0, 32, 32, 4, 0, 0, 0, 0, - { - '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '/' - }, - {} - }; - // clang-format on - - font_data active_fonts[4]; - U32 active_fonts_size = 0; - -#define VERT_BUFFER_SIZE 120 - - RwIm2DVertex vert_buffer[VERT_BUFFER_SIZE]; - U32 vert_buffer_used = 0; - - F32 rcz = 0; - F32 nsz = 0; - -#define MODEL_CACHE_SIZE 8 - - model_cache_entry model_cache[MODEL_CACHE_SIZE]; - bool model_cache_inited = false; - - basic_rect find_bounds(const iColor_tag* bits, const basic_rect& r, S32 pitch) - { - S32 diff = pitch - r.w; - const iColor_tag* endp = bits + pitch * r.h; - const iColor_tag* p = bits; - S32 pmode = (p->r == p->g && p->g == p->b && p->r >= 240); - - S32 minx = r.x + r.w; - S32 maxx = r.x - 1; - S32 miny = r.y + r.h; - S32 maxy = r.y - 1; - - S32 y = r.y; - - while (p != endp) - { - const iColor_tag* endline = p + r.w; - S32 x = r.x; - - while (p != endline) - { - if ((pmode && p->a) || (!pmode && p->r)) - { - minx = MIN(x, minx); - maxx = MAX(x, maxx); - miny = MIN(y, miny); - maxy = MAX(y, maxy); - } - - p++; - x++; - } - - p += diff; - y++; - } - - basic_rect b; - b.x = minx; - b.y = miny; - b.w = maxx + 1 - minx; - b.h = maxy + 1 - miny; - - return b; - } - - bool reset_font_spacing(font_asset& a) - { - RwTexture* tex = (RwTexture*)xSTFindAsset(a.tex_id, NULL); - - if (!tex) - { - return false; - } - - basic_rect char_bounds; - char_bounds.w = a.du; - char_bounds.h = a.dv; - - U8 baseline_count[256]; - memset(baseline_count, 0, 256); - - a.baseline = 0; - - S32 width = RwRasterGetWidth(RwTextureGetRaster(tex)); - RwImage* image = RwImageCreate(width, RwRasterGetHeight(RwTextureGetRaster(tex)), 32); - - if (!image) - { - return false; - } - - RwImageAllocatePixels(image); - RwImageSetFromRaster(image, RwTextureGetRaster(tex)); - - iColor_tag* bits = (iColor_tag*)RwImageGetPixels(image); - - for (S32 i = 0; a.char_set[i] != '\0'; i++) - { - if (a.flags & 0x4) - { - char_bounds.x = a.u + char_bounds.w * (i / a.line_size); - char_bounds.y = a.v + char_bounds.h * (i % a.line_size); - } - else - { - char_bounds.x = a.u + char_bounds.w * (i % a.line_size); - char_bounds.y = a.v + char_bounds.h * (i / a.line_size); - } - - basic_rect r = - find_bounds(bits + width * char_bounds.y + char_bounds.x, char_bounds, width); - - if (a.flags & 0x8) - { - a.char_pos[i].offset = 0; - a.char_pos[i].size = char_bounds.w; - } - else - { - a.char_pos[i].offset = r.x - char_bounds.x; - a.char_pos[i].size = r.w; - } - - S32 baseline = r.y - char_bounds.y + r.h + 1; - - if (++baseline_count[baseline] > baseline_count[a.baseline]) - { - a.baseline = baseline; - } - } - - RwImageDestroy(image); - return true; - } - - // FIXME: Float conversions seem to need work - basic_rect get_tex_bounds(const font_data& fd, U8 c) - { - typedef __typeof__(((struct font_asset){ 0 }).char_pos[0]) char_pos_t; - - F32 boundX; - F32 boundY; - F32 boundW; - F32 boundH; - char_pos_t* temp_r8; - - if (fd.asset->flags & 0x4) - { - boundX = (F32)(c / fd.asset->line_size); - boundY = (F32)(c % fd.asset->line_size); - } - else - { - boundY = (F32)(c / fd.asset->line_size); - boundX = (F32)(c % fd.asset->line_size); - } - - temp_r8 = &fd.asset->char_pos[c]; - boundX = (F32)(temp_r8->offset + (fd.asset->du * boundX + (F32)fd.asset->u)); - boundW = (F32)temp_r8->size - 0.5f; - boundY = ((F32)fd.asset->dv * boundY) + (F32)fd.asset->v; - boundH = (F32)fd.asset->dv - 0.5f; - - basic_rect result = { boundX, boundY, boundW, boundH }; - result.scale((F32)fd.asset->dv, (F32)fd.asset->v); - return result; - } - -#if 1 - basic_rect get_bounds(const font_data& fd, U8 c); -#else - basic_rect get_bounds(const font_data& fd, U8 c) - { - // todo: uses int-to-float conversion - } -#endif - -#if 1 - bool init_font_data(font_data& fd); -#else - bool init_font_data(font_data& fd) - { - // todo: uses int-to-float conversion - } -#endif - - void start_tex_render(U32 font_id) - { - font_data& fd = active_fonts[font_id]; - - rcz = 1.0f / RwCameraGetNearClipPlane(RwCameraGetCurrentCamera()); - nsz = RwIm2DGetNearScreenZ(); - - xfont::set_render_state(fd.raster); - } - - void tex_flush() - { - if (vert_buffer_used) - { - RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, vert_buffer, vert_buffer_used); - vert_buffer_used = 0; - } - } - - void stop_tex_render() - { - tex_flush(); - xfont::restore_render_state(); - } - - void set_vert(RwIm2DVertex& vert, F32 x, F32 y, F32 u, F32 v, iColor_tag c); - - void tex_render(const basic_rect& src, const basic_rect& dst, - const basic_rect& clip, iColor_tag color) - { - basic_rect r = dst; - basic_rect rt = src; - - clip.clip(r, rt); - - if (r.empty()) - { - return; - } - - if (vert_buffer_used == VERT_BUFFER_SIZE) - { - RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, vert_buffer, VERT_BUFFER_SIZE); - vert_buffer_used = 0; - } - - RwIm2DVertex* vert = &vert_buffer[vert_buffer_used]; - - r.scale(640.0f, 480.0f); - - set_vert(vert[0], r.x, r.y, rt.x, rt.y, color); - set_vert(vert[1], r.x, r.y + r.h, rt.x, rt.y + rt.h, color); - set_vert(vert[2], r.x + r.w, r.y, rt.x + rt.w, rt.y, color); - - vert[3] = vert[2]; - vert[4] = vert[1]; - - set_vert(vert[5], r.x + r.w, r.y + r.h, rt.x + rt.w, rt.y + rt.h, color); - - vert_buffer_used += 6; - } -} // namespace - -namespace -{ - void set_vert(RwIm2DVertex& vert, F32 x, F32 y, F32 u, F32 v, iColor_tag c) - { - RwIm2DVertexSetScreenX(&vert, x); - RwIm2DVertexSetScreenY(&vert, y); - RwIm2DVertexSetScreenZ(&vert, nsz); - RwIm2DVertexSetU(&vert, u, rcz); - RwIm2DVertexSetV(&vert, v, rcz); - RwIm2DVertexSetIntRGBA(&vert, c.r, c.g, c.b, c.a); - } - - void init_model_cache() - { - struct model_pool - { - RwMatrix mat[MODEL_CACHE_SIZE]; - xModelInstance model[MODEL_CACHE_SIZE]; - }; - - // non-matching: two instructions swapped - - model_cache_inited = true; - - void* data = xMemAlloc(gActiveHeap, sizeof(model_pool), 16); - memset(data, 0, sizeof(model_pool)); - - model_pool& pool = *(model_pool*)data; - - for (U32 i = 0; i < MODEL_CACHE_SIZE; i++) - { - xModelInstance& model = pool.model[i]; - model_cache_entry& e = model_cache[i]; - - e.order = 0; - e.id = 0; - e.model = &model; - - model.Mat = &pool.mat[i]; - model.Flags = 0x1; - model.BoneCount = 1; - model.shadowID = 0xDEADBEEF; - } - } - -#ifndef NON_MATCHING - static U32 next_order_967; - static signed char init_968; - - xModelInstance* load_model(U32 id); -#else - xModelInstance* load_model(U32 id) - { - static U32 next_order = 0; - U32 oldest = 0; - - next_order++; - - for (U32 i = 0; i < MODEL_CACHE_SIZE; i++) - { - model_cache_entry& e = model_cache[i]; - - if (e.id == id) - { - e.order = next_order; - return e.model; - } - - if (e.order < model_cache[oldest].order) - { - oldest = i; - } - } - - RpAtomic* mf = (RpAtomic*)xSTFindAsset(id, NULL); - - if (!mf) - { - return NULL; - } - - // non-matching: instruction order - - model_cache_entry& e = model_cache[oldest]; - - e.id = id; - e.order = next_order; - - xModelInstance& model = *e.model; - - xMat4x3Identity((xMat4x3*)model.Mat); - - model.Data = mf; - model.Bucket = xModelBucket_GetBuckets(model.Data); - model.PipeFlags = - (model.Bucket) ? model.Bucket[0]->PipeFlags : xModelGetPipeFlags(model.Data); - - return &model; - } -#endif -} // namespace - -void xfont::init() -{ - active_fonts_size = 0; - - for (size_t i = 0; i < sizeof(default_font_assets) / sizeof(font_asset); i++) - { - if (default_font_assets[i].tex_id < sizeof(default_font_texture) / sizeof(const char*)) - { - default_font_assets[i].tex_id = - xStrHash(default_font_texture[default_font_assets[i].tex_id]); - } - - xSTFindAsset(default_font_assets[i].tex_id, NULL); - - if (reset_font_spacing(default_font_assets[i])) - { - font_data& fd = active_fonts[active_fonts_size]; - fd.asset = &default_font_assets[i]; - - if (init_font_data(fd)) - { - active_fonts_size++; - } - } - } - - init_model_cache(); -} - -namespace -{ - struct - { - S32 fogenable; - S32 vertexalphaenable; - S32 zwriteenable; - S32 ztestenable; - U32 srcblend; - U32 destblend; - U32 shademode; - RwRaster* textureraster; - RwTextureFilterMode filter; - } oldrs; -} // namespace - -void xfont::set_render_state(RwRaster* raster) -{ - RwRenderStateGet(rwRENDERSTATEFOGENABLE, (void*)&oldrs.fogenable); - RwRenderStateGet(rwRENDERSTATESRCBLEND, (void*)&oldrs.srcblend); - RwRenderStateGet(rwRENDERSTATEDESTBLEND, (void*)&oldrs.destblend); - RwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)&oldrs.vertexalphaenable); - RwRenderStateGet(rwRENDERSTATETEXTURERASTER, (void*)&oldrs.textureraster); - RwRenderStateGet(rwRENDERSTATESHADEMODE, (void*)&oldrs.shademode); - RwRenderStateGet(rwRENDERSTATEZWRITEENABLE, (void*)&oldrs.zwriteenable); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)&oldrs.ztestenable); // RwRenderStateSet lol - RwRenderStateGet(rwRENDERSTATETEXTUREFILTER, (void*)&oldrs.filter); - - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)raster); - RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR); -} - -void xfont::restore_render_state() -{ - RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)oldrs.fogenable); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)oldrs.srcblend); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)oldrs.destblend); - RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)oldrs.vertexalphaenable); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)oldrs.textureraster); - RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)oldrs.shademode); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)oldrs.zwriteenable); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)oldrs.ztestenable); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)oldrs.filter); -} - -basic_rect xfont::bounds(char c) const -{ - font_data& fd = active_fonts[id]; - U32 char_index = fd.char_index[c]; - - if (fd.char_index[c] == 0xFF) - { - // non-matching: scheduling - return basic_rect::m_Null; - } - - basic_rect r = fd.bounds[char_index]; - r.scale(width, height); - return r; -} - -basic_rect xfont::bounds(const char* text) const -{ - size_t size; - return bounds(text, 0x40000000, 1.0e38f, size); -} - -basic_rect xfont::bounds(const char* text, size_t text_size, F32 max_width, size_t& size) const -{ - font_data& fd = active_fonts[id]; - basic_rect r; - - r.x = 0.0f; - r.y = fd.bounds[0].y * height; - r.w = 0.0f; - r.h = fd.bounds[0].h * height; - - if (!text || !text_size) - { - size = 0; - return r; - } - - const char* s = text; - U32 i = 0; - - while (i < text_size && *s != '\0') - { - U32 charIndex = fd.char_index[*s]; - - if (charIndex != 0xFF) - { - F32 dx = fd.bounds[charIndex].w * width; - - if (r.w + dx > max_width) - { - break; - } - - r.w += dx + space; - } - - i++; - s++; - } - - if (r.w > 0.0f) - { - r.w -= space; - } - - size = s - text; - return r; -} - -void xfont::start_render() const -{ - start_tex_render(id); -} - -void xfont::stop_render() const -{ - stop_tex_render(); -} - -namespace -{ - void char_render(U8 c, U32 font_index, const basic_rect& bounds, - const basic_rect& clip, iColor_tag color) - { - font_data& fd = active_fonts[font_index]; - U32 char_index = fd.char_index[c]; - - if (char_index >= fd.index_max) - { - return; - } - - basic_rect dst = fd.bounds[char_index]; - dst.scale(bounds.w, bounds.h); - dst.x += bounds.x; - dst.y += bounds.y; - dst.w *= fd.dstfrac[char_index].x; - dst.h *= fd.dstfrac[char_index].y; - - tex_render(fd.tex_bounds[char_index], dst, clip, color); - } - - RwRaster* set_tex_raster(RwRaster* raster) - { - RwRaster* r; - RwRenderStateGet(rwRENDERSTATETEXTURERASTER, (void*)&r); - - if (raster == r) - { - return raster; - } - - tex_flush(); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)raster); - - return r; - } -} // namespace - -void xfont::irender(const char* text, F32 x, F32 y) const -{ - irender(text, 0x40000000, x, y); -} - -static const basic_rect _1107 = {}; - -void xfont::irender(const char* text, size_t text_size, F32 x, F32 y) const -{ - if (!text) - { - return; - } - - font_data& fd = active_fonts[id]; - - set_tex_raster(fd.raster); - - basic_rect bounds = { x, y, width, height }; - U32 i = 0; - - // non-matching: color not stored in r28 - - while (i < text_size && text[i] != '\0') - { - char c = text[i]; - - char_render(c, id, bounds, clip, color); - - U32 charIndex = fd.char_index[c]; - - if (charIndex != 255) - { - bounds.x += fd.bounds[charIndex].w * width + space; - } - - i++; - } -} - -extern substr text_delims; - -namespace -{ - - size_t parse_split_tag(xtextbox::split_tag& ti) - { - ti.value.size = 0; - ti.action.size = 0; - ti.name.size = 0; - - // non-matching: scheduling - - substr s; - - s.text = ti.tag.text; - s.size = ti.tag.size; - - s.text++; - s.size--; - - ti.name.text = skip_ws(s); - s.text = find_char(s, text_delims); - - if (!s.text) - { - return 0; - } - - ti.name.size = s.text - ti.name.text; - s.size -= ti.name.size; - ti.action.text = skip_ws(s); - - if (!s.size) - { - return 0; - } - - char c = s.text[0]; - - if (c == '\0' || c == '{') - { - return 0; - } - - s.text++; - s.size--; - - if (c == '}') - { - return ti.tag.size - s.size; - } - - ti.action.size = 1; - ti.value.text = skip_ws(s); - s.text = find_char(s, '}'); - s.size -= s.text - ti.value.text; - - if (!s.text) - { - return 0; - } - - ti.value.size = s.text - ti.value.text; - - rskip_ws(ti.value); - - s.text++; - s.size--; - - return ti.tag.size - s.size; - } - - const char* parse_next_tag_jot(xtextbox::jot& a, const xtextbox& tb, const xtextbox& ctb, - const char* text, size_t text_size) - { - xtextbox::split_tag ti = {}; - ti.tag.text = text; - ti.tag.size = text_size; - - size_t size = parse_split_tag(ti); - - if (!size) - { - return NULL; - } - - a.s.text = text; - a.s.size = size; - a.flag.invisible = a.flag.ethereal = true; - - if (icompare(ti.name, substr::create("~", 1)) == 0 || - icompare(ti.name, substr::create("reset", 5)) == 0) - { - a.tag = xtextbox::find_format_tag(ti.value); - - if (a.tag && a.tag->reset_tag) - { - a.tag->reset_tag(a, tb, ctb, ti); - } - } - else - { - a.tag = xtextbox::find_format_tag(ti.name); - - if (a.tag && a.tag->parse_tag) - { - a.tag->parse_tag(a, tb, ctb, ti); - } - } - - return text + size; - } - - const char* parse_next_text_jot(xtextbox::jot& a, const xtextbox& tb, const xtextbox& ctb, - const char* text, size_t text_size) - { - char c = text[0]; - - a.s.text = text; - a.s.size = 1; - a.flag.merge = true; - - if (c == '\n') - { - a.flag.line_break = true; - } - else if (c == '\t') - { - a.flag.tab = true; - } - else if (c == '-') - { - a.flag.word_end = true; - } - - if (is_ws(c)) - { - a.flag.invisible = a.flag.word_break = true; - } - - a.bounds = tb.font.bounds(c); - a.cb = &xtextbox::text_cb; - a.context = NULL; - a.context_size = 0; - - return a.s.text + a.s.size; - } - - const char* parse_next_jot(xtextbox::jot& a, const xtextbox& tb, const xtextbox& ctb, - const char* text, size_t text_size) - { - const char* ret; - - if (text[0] != '{' || !(ret = parse_next_tag_jot(a, tb, ctb, text, text_size))) - { - ret = parse_next_text_jot(a, tb, ctb, text, text_size); - } - - a.flag.merge = a.flag.merge && !(tb.flags & FLAG_UNK80); - return ret; - } - - struct tex_args - { - RwRaster* raster; - F32 rot; - basic_rect src; - basic_rect dst; - xVec2 off; - enum - { - SCALE_FONT, - SCALE_SCREEN, - SCALE_SIZE, - SCALE_FONT_WIDTH, - SCALE_FONT_HEIGHT, - SCALE_SCREEN_WIDTH, - SCALE_SCREEN_HEIGHT - } scale; - }; - - struct model_args - { - xModelInstance* model; - xVec3 rot; - basic_rect dst; - xVec2 off; - enum - { - SCALE_FONT, - SCALE_SCREEN, - SCALE_SIZE - } scale; - }; - - tex_args def_tex_args; - model_args def_model_args; - - void reset_tex_args(tex_args& ta) - { - ta.raster = NULL; - ta.rot = 0.0f; - ta.src = ta.dst = basic_rect::m_Unit; - ta.off.x = ta.off.y = 1.0f; - ta.scale = tex_args::SCALE_FONT; - } - - void load_tex_args(tex_args& ta, const substr& s) - { - xtextbox::tag_entry_list el = xtextbox::read_tag(s); - xtextbox::tag_entry* e; - - if (el.size == 0) - { - return; - } - - e = &el.entries[0]; - - if (e->op == ':' || (e->args_size == 1 && e->args[0].size)) - { - substr& name = e->args[0]; - U32 id; - - if (name.size == 10 && imemcmp(name.text, "0x", 2) == 0) - { - id = atox(substr::create(name.text + 2, 8)); - } - else - { - id = xStrHash(name.text, name.size); - } - - RwTexture* texture = (RwTexture*)xSTFindAsset(id, NULL); - - if (texture && texture->raster && texture->raster->width > 0 && - texture->raster->height > 0 && texture->raster->width <= 4096 && - texture->raster->height <= 4096) - { - RwTextureSetFilterMode(texture, rwFILTERLINEAR); - ta.raster = texture->raster; - } - } - - el.entries++; - el.size--; - - e = xtextbox::find_entry(el, substr::create("rot", 3)); - - if (e && e->op == '=' && e->args_size == 1) - { - xtextbox::read_list(*e, &ta.rot, 1); - } - - e = xtextbox::find_entry(el, substr::create("src", 3)); - - if (e && e->op == '=' && e->args_size == 4) - { - xtextbox::read_list(*e, (F32*)&ta.src, 4); - } - - e = xtextbox::find_entry(el, substr::create("dst", 3)); - - if (e && e->op == '=' && e->args_size == 4) - { - xtextbox::read_list(*e, (F32*)&ta.dst, 4); - } - - e = xtextbox::find_entry(el, substr::create("off", 3)); - - if (e && e->op == '=' && e->args_size == 2) - { - xtextbox::read_list(*e, (F32*)&ta.off, 2); - } - - e = xtextbox::find_entry(el, substr::create("scale", 5)); - - if (e && e->op == '=' && e->args_size == 1) - { - if (icompare(e->args[0], substr::create("font", 4)) == 0) - { - ta.scale = tex_args::SCALE_FONT; - } - else if (icompare(e->args[0], substr::create("screen", 6)) == 0) - { - ta.scale = tex_args::SCALE_SCREEN; - } - else if (icompare(e->args[0], substr::create("size", 4)) == 0) - { - ta.scale = tex_args::SCALE_SIZE; - } - else if (icompare(e->args[0], substr::create("font_width", 10)) == 0) - { - ta.scale = tex_args::SCALE_FONT_WIDTH; - } - else if (icompare(e->args[0], substr::create("font_height", 11)) == 0) - { - ta.scale = tex_args::SCALE_FONT_HEIGHT; - } - else if (icompare(e->args[0], substr::create("screen_width", 12)) == 0) - { - ta.scale = tex_args::SCALE_SCREEN_WIDTH; - } -#if 1 // needed until .sdata2 is decomped - else if (icompare(e->args[0], substr::create("screen_height\0=:+*;}\0,;}", 13)) == -#else - else if (icompare(e->args[0], substr::create("screen_height", 13)) == -#endif - 0) // screen_height - { - ta.scale = tex_args::SCALE_SCREEN_HEIGHT; - } - else - { - ta.scale = tex_args::SCALE_FONT; - } - } - } - - void reset_model_args(model_args& ma) - { - ma.model = NULL; - ma.rot = xVec3::m_Null; - ma.dst = basic_rect::m_Unit; - ma.off.x = ma.off.y = 1.0f; - ma.scale = model_args::SCALE_FONT; - } - - void load_model_args(model_args& ma, const substr& s) - { - xtextbox::tag_entry_list el = xtextbox::read_tag(s); - xtextbox::tag_entry* e; - - if (!el.size) - { - return; - } - - e = &el.entries[0]; - - if (e->op == ':' || (e->args_size == 1 && e->args[0].size)) - { - substr& name = e->args[0]; - - ma.model = load_model(xStrHash(name.text, name.size)); - } - - el.entries++; - el.size--; - - e = xtextbox::find_entry(el, substr::create("rot", 3)); - - if (e && e->op == '=' && e->args_size == 3) - { - xtextbox::read_list(*e, (F32*)&ma.rot, 3); - } - - e = xtextbox::find_entry(el, substr::create("dst", 3)); - - if (e && e->op == '=' && e->args_size == 4) - { - xtextbox::read_list(*e, (F32*)&ma.dst, 4); - } - - e = xtextbox::find_entry(el, substr::create("off", 3)); - - if (e && e->op == '=' && e->args_size == 2) - { - xtextbox::read_list(*e, (F32*)&ma.off, 2); - } - - e = xtextbox::find_entry(el, substr::create("scale", 5)); - - if (e && e->op == '=' && e->args_size == 1) - { - if (icompare(e->args[0], substr::create("screen", 6)) == 0) - { - ma.scale = model_args::SCALE_SCREEN; - } - else - { - ma.scale = model_args::SCALE_FONT; - } - } - } - - void start_layout(const xtextbox&) - { - reset_tex_args(def_tex_args); - reset_model_args(def_model_args); - } - - void stop_layout(const xtextbox&) - { - } - - void start_render(const xtextbox& tb) - { - tb.font.start_render(); - } - - void stop_render(const xtextbox& tb) - { - tb.font.stop_render(); - } -} // namespace - -void xtextbox::text_render(const jot& j, const xtextbox& tb, F32 x, F32 y) -{ - tb.font.irender(j.s.text, j.s.size, x, y); -} - -void xtextbox::set_text(const char* text) -{ - set_text(text, 0x40000000); -} - -void xtextbox::set_text(const char* text, size_t text_size) -{ - if (!text || !text_size) - { - texts_size = 0; - text_hash = 0; - return; - } - - this->text.text = text; - this->text.size = text_size; - - set_text(&this->text.text, &this->text.size, 1); -} - -void xtextbox::set_text(const char** texts, size_t size) -{ - set_text(texts, NULL, size); -} - -void xtextbox::set_text(const char** texts, const size_t* text_sizes, size_t size) -{ - this->texts_size = size; - this->text_hash = 0; - - if (!size) - { - return; - } - - this->texts = texts; - this->text_sizes = text_sizes; - - if (!text_sizes) - { - for (size_t i = 0; i < size; i++) - { - this->text_hash = this->text_hash * 131 + xStrHash(texts[i]); - } - } - else - { - for (size_t i = 0; i < size; i++) - { - this->text_hash = this->text_hash * 131 + xStrHash(texts[i], text_sizes[i]); - } - } -} - -namespace tweaker -{ - namespace - { - void log_cache(bool) - { - } - } // namespace -} // namespace tweaker - -namespace -{ - struct tl_cache_entry - { - U32 used; - iTime last_used; - xtextbox::layout tl; - }; - -#ifdef GAMECUBE -#define TL_CACHE_COUNT 1 -#else -#ifdef PS2 -#define TL_CACHE_COUNT 3 -#endif -#endif - - tl_cache_entry tl_cache[TL_CACHE_COUNT]; -} // namespace - -#if 1 - -#else -xtextbox::layout& xtextbox::temp_layout(bool cache) const -{ - // todo: uses int-to-float conversion -} -#endif - -void xtextbox::render(layout& l, S32 begin_jot, S32 end_jot) const -{ - l.render(*this, begin_jot, end_jot); -} - -F32 xtextbox::yextent(F32 max, S32& size, const layout& l, S32 begin_jot, S32 end_jot) const -{ - return l.yextent(max, size, begin_jot, end_jot); -} - -xtextbox::callback xtextbox::text_cb = { xtextbox::text_render, NULL, NULL }; - -#define skip_char_ptr(s, p) \ - { \ - const char* temp = (s).text; \ - (s).text = (p) + 1; \ - (s).size -= (p) + 1 - temp; \ - } - -#define skip_char(s, c) \ - { \ - const char* p = find_char((s), (c)); \ - if (p) \ - { \ - skip_char_ptr((s), p); \ - } \ - } - -#ifndef NON_MATCHING -static substr arg_buffer_1611[32]; -static xtextbox::tag_entry entry_buffer_1612[16]; - -#else -xtextbox::tag_entry_list xtextbox::read_tag(const substr& s) -{ - static substr arg_buffer[32]; - static xtextbox::tag_entry entry_buffer[16]; - - U32 entries_used = 0; - U32 args_used = 0; - - substr it = s; - - skip_char(it, '{'); - - substr delims = _1615; - substr sub_delims = _1616; - - while (it.size) - { - tag_entry& entry = entry_buffer[entries_used]; - - entry.args_size = 0; - entry.op = 0; - entry.name.text = it.text; - - const char* d = find_char(it, delims); - - entry.name.size = (d) ? it.size : d - it.text; - - trim_ws(entry.name); - - if (entry.name.size) - { - entries_used++; - } - - if (!d || *d == '}') - { - break; - } - - skip_char_ptr(it, d); - - if (*d != ';') - { - substr& arg = arg_buffer[args_used]; - - entry.op = *d; - entry.args = &arg; - - while (it.size) - { - arg.text = it.text; - - const char* d = find_char(it, sub_delims); - - if (!d) - { - arg.size = it.size; - it.size = 0; - } - else - { - arg.size = d - it.text; - it.size -= arg.size + 1; - it.text += arg.size + 1; - } - - trim_ws(arg); - - if (arg.size) - { - // non-matching: missing addi instruction - args_used++; - entry.args_size++; - } - - if (!d || *d == '}') - { - it.size = 0; - break; - } - else if (*d == ';') - { - break; - } - } - } - } - - tag_entry_list ret = _1642; - ret.size = entries_used; - - return ret; -} -#endif - -xtextbox::tag_entry* xtextbox::find_entry(const tag_entry_list& el, const substr& name) -{ - // non-matching: el.size and el.entries are not cached at the beginning - - for (size_t i = 0; i < el.size; i++) - { - tag_entry& e = el.entries[i]; - - if (icompare(name, e.name) == 0) - { - return &e; - } - } - - return NULL; -} - -size_t xtextbox::read_list(const tag_entry& e, F32* v, size_t vsize) -{ - size_t total = e.args_size; - - if (vsize < total) - { - total = vsize; - } - - // non-matching: e.args is not stored in r31 - - for (size_t i = 0; i < total; i++) - { - v[i] = xatof(e.args[i].text); - } - - return total; -} - -size_t xtextbox::read_list(const tag_entry& e, S32* v, size_t vsize) -{ - size_t total = e.args_size; - - if (vsize < total) - { - total = vsize; - } - - // non-matching: e.args is not stored in r31 - - for (size_t i = 0; i < total; i++) - { - v[i] = atoi(e.args[i].text); - } - - return total; -} - -void xtextbox::clear_layout_cache() -{ - for (U32 index = 0; index < TL_CACHE_COUNT; index++) - { - tl_cache[index].tl.clear(); - } -} - -void xtextbox::layout::refresh(const xtextbox& tb, bool force) -{ - if (force || changed(tb)) - { - this->tb = tb; - calc(tb, 0); - } -} - -void xtextbox::layout::refresh_end(const xtextbox& tb) -{ - size_t texts_size = this->tb.texts_size; - - if (texts_size > tb.texts_size) - { - this->tb = tb; - calc(tb, texts_size); - } -} - -void xtextbox::layout::clear() -{ - dynamics_size = 0; - context_buffer_size = 0; - _lines_size = 0; - _jots_size = 0; - tb = xtextbox::create(); -} - -void xtextbox::layout::trim_line(jot_line& line) -{ - // non-matching: mtctr and bdnz not generated - - for (S32 i = line.last - 1; i >= line.first; i--) - { - jot& a = _jots[i]; - - if (!a.flag.ethereal) - { - if (a.flag.invisible) - { - erase_jots(i, i + 1); - line.last--; - } - - break; - } - } - - for (S32 i = line.first; i < line.last; i++) - { - jot& a = _jots[i]; - - if (!a.flag.ethereal) - { - if (a.flag.invisible) - { - erase_jots(i, i + 1); - } - - break; - } - } -} - -void xtextbox::layout::erase_jots(size_t begin_jot, size_t end_jot) -{ - if (end_jot >= _jots_size) - { - _jots_size = begin_jot; - return; - } - - size_t erase_size = end_jot - begin_jot; - - _jots_size -= erase_size; - - for (size_t i = begin_jot; i < _jots_size; i++) - { - _jots[i] = _jots[i + erase_size]; - } -} - -void xtextbox::layout::merge_line(jot_line& line) -{ - size_t d = line.first; - size_t i = line.first + 1; - - while (i != line.last) - { - jot& a1 = _jots[d]; - jot& a2 = _jots[i]; - - if (!a1.flag.ethereal && !a2.flag.ethereal && a1.flag.merge && a2.flag.merge && - a1.cb == a2.cb) - { - a1.s.size = a2.s.text - a1.s.text + a2.s.size; - a1.bounds |= a2.bounds; - a1.intersect_flags(a2); - } - else - { - d++; - - if (d != i) - { - _jots[d] = a2; - } - } - - i++; - } - - erase_jots(d + 1, line.last); - line.last = d + 1; -} - -void xtextbox::layout::bound_line(jot_line& line) -{ - line.bounds.w = line.bounds.h = line.baseline = 0.0f; - - for (size_t i = line.first; i != line.last; i++) - { - jot& a = _jots[i]; - - if (!a.flag.ethereal && -a.bounds.y > line.baseline) - { - line.baseline = -a.bounds.y; - } - } - - for (size_t i = line.first; i != line.last; i++) - { - jot& a = _jots[i]; - - if (!a.flag.ethereal) - { - a.bounds.x = line.bounds.w; - line.bounds.w += a.bounds.w; - - F32 total_height = line.baseline + a.bounds.y + a.bounds.h; - - if (total_height > line.bounds.h) - { - line.bounds.h = total_height; - } - } - } - - line.page_break = (line.last > line.first && _jots[line.last - 1].flag.page_break); -} - -bool xtextbox::layout::fit_line() -{ - jot_line& line = _lines[_lines_size]; - - if (line.bounds.w > tb.bounds.w) - { - switch (tb.flags & WRAP_MASK) - { - case WRAP_CHAR: - { - if (line.last > line.first + 1) - { - line.last--; - } - - break; - } - case WRAP_NONE: - { - return false; - } - default: - { - for (S32 i = (S32)line.last - 1; i > (S32)line.first; i--) - { - if (_jots[i].flag.word_break) - { - line.last = i + 1; - break; - } - else if (_jots[i - 1].flag.word_end) - { - line.last = i; - break; - } - } - - if (line.last <= line.first) - { - line.last = line.first + 1; - } - - trim_line(line); - break; - } - } - } - - merge_line(line); - bound_line(line); - - return true; -} - -void xtextbox::layout::next_line() -{ - jot_line& line1 = _lines[_lines_size]; - - _lines_size++; - - jot_line& line2 = _lines[_lines_size]; - - line2.first = line1.last; - line2.last = _jots_size; - line2.bounds.x = 0.0f; - line2.bounds.y = line1.bounds.y + line1.bounds.h; - - bound_line(line2); -} - -void xtextbox::layout::calc(const xtextbox& ctb, size_t start_text) -{ - if (!start_text) - { - dynamics_size = 0; - context_buffer_size = 0; - _lines_size = 0; - _jots_size = 0; - } - - if (!tb.texts_size) - { - return; - } - - start_layout(ctb); - - jot_line& first_line = _lines[_lines_size]; - first_line.first = 0; - first_line.bounds.w = 0.0f; - first_line.bounds.x = 0.0f; - first_line.bounds.y = 0.0f; - first_line.baseline = 0.0f; - - struct - { - const char* s; - const char* end; - } text_stack[16]; - - size_t text_stack_size = 0; - size_t size = ((!tb.text_sizes) ? 0x40000000 : tb.text_sizes[start_text]); - size_t text_index = start_text + 1; - const char* s = tb.texts[start_text]; - const char* end = s + size; - const char* r25; - - while (true) - { - jot& a = _jots[_jots_size]; - jot_line& line = _lines[_lines_size]; - - a.context = &context_buffer[context_buffer_size]; - a.context_size = 0; - a.reset_flags(); - a.cb = NULL; - a.tag = NULL; - - if (s == end || *s == '\0') - { - if (text_stack_size) - { - text_stack_size--; - s = text_stack[text_stack_size].s; - end = text_stack[text_stack_size].end; - } - else if (text_index < tb.texts_size) - { - size = ((!tb.text_sizes) ? 0x40000000 : tb.text_sizes[text_index]); - - s = tb.texts[text_index]; - end = s + size; - text_index++; - } - else - { - break; - } - - a.flag.invisible = a.flag.ethereal = true; - a.s = substr::create(NULL, 0); - - _jots_size++; - } - else - { - r25 = parse_next_jot(a, tb, ctb, s, end - s); - - if (a.context == &context_buffer[context_buffer_size]) - { - context_buffer_size += ALIGN(a.context_size, 4); - } - - _jots_size++; - - if (a.cb && a.cb->layout_update) - { - a.cb->layout_update(a, tb, ctb); - } - - if (a.flag.stop) - { - break; - } - - if (!a.flag.ethereal) - { - a.bounds.x += line.bounds.w; - line.bounds.w += a.bounds.w; - - if (line.bounds.w >= tb.bounds.w) - { - line.last = _jots_size; - - if (!fit_line()) - { - break; - } - - next_line(); - } - } - - if (a.flag.line_break || a.flag.page_break) - { - line.last = _jots_size; - - if (!fit_line()) - { - break; - } - - next_line(); - } - - s = r25; - - if (a.flag.insert) - { - s = (const char*)a.context; - text_stack[text_stack_size].s = r25; - text_stack[text_stack_size].end = end; - text_stack_size++; - end = s + a.context_size; - } - } - } - - jot_line& last_line = _lines[_lines_size]; - - if (last_line.first < _jots_size) - { - last_line.last = _jots_size; - - if (fit_line()) - { - _lines_size++; - } - } - - for (size_t i = 0; i < _jots_size; i++) - { - if (_jots[i].flag.dynamic) - { - dynamics[dynamics_size++] = i; - } - } - - stop_layout(ctb); -} - -void xtextbox::layout::render(const xtextbox& ctb, S32 begin_jot, S32 end_jot) -{ - if (begin_jot < 0) - { - begin_jot = 0; - } - - if (end_jot < begin_jot) - { - end_jot = _jots_size; - } - - if (begin_jot >= end_jot) - { - return; - } - - tb = ctb; - start_render(ctb); - - S32 begin_line = 0; - - while (true) - { - if (begin_line >= (S32)_lines_size) - { - stop_render(ctb); - return; - } - - if ((S32)_lines[begin_line].last > begin_jot) - { - break; - } - - begin_line++; - } - - for (S32 i = 0; i < begin_jot; i++) - { - jot& j = _jots[i]; - - if (j.cb && j.cb->render_update) - { - j.cb->render_update(j, tb, ctb); - } - } - - F32 top = _lines[begin_line].bounds.y; - U32 li = begin_line - 1; - S32 line_last = -1; - F32 x, y; - - for (S32 i = begin_jot; i < end_jot; i++) - { - if (i >= line_last) - { - li++; - jot_line& line = _lines[li]; - - line_last = line.last; - - x = tb.bounds.x + line.bounds.x; - y = tb.bounds.y + line.bounds.y + line.baseline - top; - - U32 xj = tb.flags & XJUSTIFY_MASK; - - if (xj == XJUSTIFY_CENTER) - { - x += 0.5f * (tb.bounds.w - line.bounds.w); - } - else if (xj == XJUSTIFY_RIGHT) - { - x += tb.bounds.w - line.bounds.w; - } - - if (line.page_break && end_jot > line_last) - { - end_jot = line_last; - } - } - - jot& j = _jots[i]; - - if (j.cb) - { - if (j.cb->render_update) - { - j.cb->render_update(j, tb, ctb); - } - - if (!j.flag.ethereal && !j.flag.invisible && j.cb->render) - { - j.cb->render(j, tb, x + j.bounds.x, y); - } - } - } - - stop_render(ctb); -} - -// this is different than the one in xMath.h -#define min(a, b) ((a) >= (b) ? (b) : (a)) - -F32 xtextbox::layout::yextent(F32 max, S32& size, S32 begin_jot, S32 end_jot) const -{ - size = 0; - - if (begin_jot < 0) - { - begin_jot = 0; - } - - if (end_jot < begin_jot) - { - end_jot = _jots_size; - } - - if (begin_jot >= end_jot) - { - return 0.0f; - } - - S32 begin_line = 0; - - while (true) - { - if (begin_line >= (S32)_lines_size) - { - return 0.0f; - } - - if ((S32)_lines[begin_line].last > begin_jot) - { - break; - } - - begin_line++; - } - - // non-matching: wrong float registers - F32 top = _lines[begin_line].bounds.y; - S32 i = begin_line; - - while (true) - { - if (i == (S32)_lines_size) - { - break; - } - - // non-matching: r11 missing - const jot_line& line = _lines[i]; - - if (line.bounds.y + line.bounds.h > max + top) - { - i--; - break; - } - - if ((S32)line.last >= end_jot) - { - break; - } - - if (line.page_break) - { - break; - } - - i++; - } - - if (i < begin_line) - { - return 0.0f; - } - - const jot_line& line = _lines[i]; - - size = min((S32)line.last, end_jot) - begin_jot; - - return line.bounds.y + line.bounds.h - top; -} - -bool xtextbox::layout::changed(const xtextbox& ctb) -{ - U32 flags1 = tb.flags & (WRAP_MASK | FLAG_UNK40); - U32 flags2 = ctb.flags & (WRAP_MASK | FLAG_UNK40); - - if (tb.text_hash != ctb.text_hash || tb.font.id != ctb.font.id || - tb.font.width != ctb.font.width || tb.font.height != ctb.font.height || - tb.font.space != ctb.font.space || tb.bounds.w != ctb.bounds.w || flags1 != flags2 || - tb.line_space != ctb.line_space) - { - return true; - } - - S32 i = dynamics_size; - - while (i > 0) - { - i--; - - jot& j = _jots[dynamics[i]]; - U32 oldval = xStrHash((char*)j.context, j.context_size); - - parse_next_jot(j, tb, ctb, j.s.text, j.s.size); - - U32 val = xStrHash((char*)j.context, j.context_size); - - if (val != oldval) - { - return true; - } - } - - return false; -} - -namespace -{ - void update_tag_alpha(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.font.color.a = 255.0f * (F32&)j.context + 0.5f; - } - - void update_tag_reset_alpha(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.font.color.a = ctb.font.color.a; - } - - static const xtextbox::callback cb_2178 = { NULL, update_tag_alpha, update_tag_alpha }; - -#if 1 - void parse_tag_alpha(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti); -#else - void parse_tag_alpha(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - // todo: uses int-to-float conversion - } -#endif - - void reset_tag_alpha(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_alpha, - update_tag_reset_alpha }; - a.cb = &cb; - } - - void update_tag_red(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.font.color.r = 255.0f * (F32&)j.context + 0.5f; - } - - void update_tag_reset_red(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.font.color.r = ctb.font.color.r; - } - - static const xtextbox::callback cb_2217 = { NULL, update_tag_red, update_tag_red }; - -#if 1 - void parse_tag_red(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti); -#else - void parse_tag_red(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - // todo: uses int-to-float conversion - } -#endif - - void reset_tag_red(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_red, update_tag_reset_red }; - a.cb = &cb; - } - - void update_tag_green(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.font.color.g = 255.0f * (F32&)j.context + 0.5f; - } - - void update_tag_reset_green(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.font.color.g = ctb.font.color.g; - } - - static const xtextbox::callback cb_2255 = { NULL, update_tag_green, update_tag_green }; - -#if 1 - void parse_tag_green(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti); -#else - void parse_tag_green(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - // todo: uses int-to-float conversion - } -#endif - - void reset_tag_green(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_green, - update_tag_reset_green }; - a.cb = &cb; - } - - void update_tag_blue(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.font.color.b = 255.0f * (F32&)j.context + 0.5f; - } - - void update_tag_reset_blue(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.font.color.b = ctb.font.color.b; - } - - static const xtextbox::callback cb_2293 = { NULL, update_tag_blue, update_tag_blue }; - -#if 1 - void parse_tag_blue(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti); -#else - void parse_tag_blue(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - // todo: uses int-to-float conversion - } -#endif - - void reset_tag_blue(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_blue, update_tag_reset_blue }; - a.cb = &cb; - } - - void update_tag_width(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.font.width = (F32&)j.context; - } - - void update_tag_reset_width(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.font.width = ctb.font.width; - } - - void parse_tag_width(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, update_tag_width, update_tag_width }; - F32& v = (F32&)a.context; - - if (ti.value.size == 0 || ti.action.size == 0) - { - return; - } - - v = xatof(ti.value.text); - - switch (ti.action.text[0]) - { - case '=': - { - break; - } - case '+': - { - v += tb.font.width; - break; - } - case '*': - { - v *= tb.font.width; - break; - } - default: - { - return; - } - } - - if (v < 0.0f) - { - v = 0.0f; - } - else if (v > 1.0f) - { - v = 1.0f; - } - - a.cb = &cb; - } - - void reset_tag_width(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_width, - update_tag_reset_width }; - a.cb = &cb; - } - - void update_tag_height(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.font.height = (F32&)j.context; - } - - void update_tag_reset_height(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.font.height = ctb.font.height; - } - - void parse_tag_height(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, update_tag_height, update_tag_height }; - F32& v = (F32&)a.context; - - if (ti.value.size == 0 || ti.action.size == 0) - { - return; - } - - v = xatof(ti.value.text); - - switch (ti.action.text[0]) - { - case '=': - { - break; - } - case '+': - { - v += tb.font.height; - break; - } - case '*': - { - v *= tb.font.height; - break; - } - default: - { - return; - } - } - - if (v < 0.0f) - { - v = 0.0f; - } - else if (v > 1.0f) - { - v = 1.0f; - } - - a.cb = &cb; - } - - void reset_tag_height(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_height, - update_tag_reset_height }; - a.cb = &cb; - } - - void update_tag_left_indent(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.left_indent = (F32&)j.context; - } - - void update_tag_reset_left_indent(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.left_indent = ctb.left_indent; - } - - void parse_tag_left_indent(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, update_tag_left_indent, NULL }; - F32& v = (F32&)a.context; - - if (ti.value.size == 0 || ti.action.size == 0) - { - return; - } - - v = xatof(ti.value.text); - - switch (ti.action.text[0]) - { - case '=': - { - break; - } - case '+': - { - v += tb.left_indent; - break; - } - case '*': - { - v *= tb.left_indent; - break; - } - default: - { - return; - } - } - - if (v < -1.0f) - { - v = -1.0f; - } - else if (v > 1.0f) - { - v = 1.0f; - } - - a.cb = &cb; - } - - void reset_tag_left_indent(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_left_indent, NULL }; - a.cb = &cb; - } - - void update_tag_right_indent(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.right_indent = (F32&)j.context; - } - - void update_tag_reset_right_indent(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.right_indent = ctb.right_indent; - } - - void parse_tag_right_indent(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, update_tag_right_indent, NULL }; - F32& v = (F32&)a.context; - - if (ti.value.size == 0 || ti.action.size == 0) - { - return; - } - - v = xatof(ti.value.text); - - switch (ti.action.text[0]) - { - case '=': - { - break; - } - case '+': - { - v += tb.right_indent; - break; - } - case '*': - { - v *= tb.right_indent; - break; - } - default: - { - return; - } - } - - if (v < -1.0f) - { - v = -1.0f; - } - else if (v > 1.0f) - { - v = 1.0f; - } - - a.cb = &cb; - } - - void reset_tag_right_indent(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_right_indent, NULL }; - a.cb = &cb; - } - - void update_tag_tab_stop(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.tab_stop = (F32&)j.context; - } - - void update_tag_reset_tab_stop(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.tab_stop = ctb.tab_stop; - } - - void parse_tag_tab_stop(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, update_tag_tab_stop, NULL }; - F32& v = (F32&)a.context; - - if (ti.value.size == 0 || ti.action.size == 0) - { - return; - } - - v = xatof(ti.value.text); - - switch (ti.action.text[0]) - { - case '=': - { - break; - } - case '+': - { - v += tb.tab_stop; - break; - } - case '*': - { - v *= tb.tab_stop; - break; - } - default: - { - return; - } - } - - if (v < 0.0f) - { - v = 0.0f; - } - else if (v > 1.0f) - { - v = 1.0f; - } - - a.cb = &cb; - } - - void reset_tag_tab_stop(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_tab_stop, NULL }; - a.cb = &cb; - } - - void update_tag_xspace(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.font.space = (F32&)j.context; - } - - void update_tag_reset_xspace(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.font.space = ctb.font.space; - } - - void parse_tag_xspace(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, update_tag_xspace, update_tag_xspace }; - F32& v = (F32&)a.context; - - if (ti.value.size == 0 || ti.action.size == 0) - { - return; - } - - v = xatof(ti.value.text); - - switch (ti.action.text[0]) - { - case '=': - { - break; - } - case '+': - { - v += tb.font.space; - break; - } - case '*': - { - v *= tb.font.space; - break; - } - default: - { - return; - } - } - - if (v < -1.0f) - { - v = -1.0f; - } - else if (v > 1.0f) - { - v = 1.0f; - } - - a.cb = &cb; - } - - void reset_tag_xspace(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_xspace, - update_tag_reset_xspace }; - a.cb = &cb; - } - - void update_tag_yspace(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.line_space = (F32&)j.context; - } - - void update_tag_reset_yspace(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.line_space = ctb.line_space; - } - - void parse_tag_yspace(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, update_tag_yspace, NULL }; - F32& v = (F32&)a.context; - - if (ti.value.size == 0 || ti.action.size == 0) - { - return; - } - - v = xatof(ti.value.text); - - switch (ti.action.text[0]) - { - case '=': - { - break; - } - case '+': - { - v += tb.line_space; - break; - } - case '*': - { - v *= tb.line_space; - break; - } - default: - { - return; - } - } - - if (v < -1.0f) - { - v = -1.0f; - } - else if (v > 1.0f) - { - v = 1.0f; - } - - a.cb = &cb; - } - - void reset_tag_yspace(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_yspace, NULL }; - a.cb = &cb; - } - - void update_tag_reset_all(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb = ctb; - } - - void reset_tag_all(xtextbox::jot& j, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_all, update_tag_reset_all }; - j.cb = &cb; - } - - void update_tag_color(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.font.color = (iColor_tag&)j.context; - } - - void update_tag_reset_color(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.font.color = ctb.font.color; - } - - void parse_tag_color(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, update_tag_color, update_tag_color }; - iColor_tag& color = (iColor_tag&)a.context; - - if (ti.value.size < 6 || ti.action.size == 0) - { - return; - } - - size_t v = atox(ti.value); - - if (ti.value.size < 8) - { - v = (v & 0xff000000) | (tb.font.color.a << 24); - } - - switch (ti.action.text[0]) - { - case '=': - { - color.a = v >> 24 & 0xff; - color.r = v >> 16 & 0xff; - color.g = v >> 8 & 0xff; - color.b = v & 0xff; - break; - } - case '+': - { - U32 temp; - - temp = (v >> 24 & 0xff) + tb.font.color.a; - color.a = (temp <= 255) ? temp : 255; - - temp = (v >> 16 & 0xff) + tb.font.color.r; - color.r = (temp <= 255) ? temp : 255; - - temp = (v >> 8 & 0xff) + tb.font.color.g; - color.g = (temp <= 255) ? temp : 255; - - temp = (v & 0xff) + tb.font.color.b; - color.b = (temp <= 255) ? temp : 255; - - break; - } - case '*': - { - color.a = (v >> 24 & 0xff) * tb.font.color.a / 255; - color.r = (v >> 16 & 0xff) * tb.font.color.r / 255; - color.g = (v >> 8 & 0xff) * tb.font.color.g / 255; - color.b = (v & 0xff) * tb.font.color.b / 255; - break; - } - default: - { - return; - } - } - - a.cb = &cb; - } - - void reset_tag_color(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_color, - update_tag_reset_color }; - a.cb = &cb; - } - - void update_tag_font(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.font.id = (U32&)j.context; - } - - void update_tag_reset_font(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.font.id = ctb.font.id; - } - - void parse_tag_font(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, update_tag_font, update_tag_font }; - U32& id = (U32&)a.context; - - if (ti.action.size < 1 || ti.action.text[0] != '=' || ti.value.size == 0) - { - return; - } - - id = atoi(ti.value.text); - - if (id < active_fonts_size) - { - a.cb = &cb; - } - } - - void reset_tag_font(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_font, update_tag_reset_font }; - a.cb = &cb; - } - - void update_tag_wrap(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.flags = (tb.flags & ~WRAP_MASK) | ((U32&)j.context & WRAP_MASK); - } - - void update_tag_reset_wrap(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.flags = (tb.flags & ~WRAP_MASK) | (ctb.flags & WRAP_MASK); - } - - void parse_tag_wrap(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, update_tag_wrap, NULL }; - U32& flags = (U32&)a.context; - - if (ti.action.size < 1 || ti.action.text[0] != '=' || ti.value.size != 4) - { - return; - } - - if (imemcmp(ti.value.text, "word", 4) == 0) - { - flags = WRAP_WORD; - } - else if (imemcmp(ti.value.text, "char", 4) == 0) - { - flags = WRAP_CHAR; - } - else if (imemcmp(ti.value.text, "none", 4) == 0) - { - flags = WRAP_NONE; - } - else - { - return; - } - - a.cb = &cb; - } - - void reset_tag_wrap(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, update_tag_reset_wrap, NULL }; - a.cb = &cb; - } - - void update_tag_xjustify(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.flags = (tb.flags & ~XJUSTIFY_MASK) | ((U32&)j.context & XJUSTIFY_MASK); - } - - void update_tag_reset_xjustify(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.flags = (tb.flags & ~XJUSTIFY_MASK) | (ctb.flags & XJUSTIFY_MASK); - } - - void parse_tag_xjustify(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, NULL, update_tag_xjustify }; - U32& flags = (U32&)a.context; - - if (ti.action.size < 1 || ti.action.text[0] != '=') - { - return; - } - - if (icompare(ti.value, substr::create("left", 4)) == 0) - { - flags = XJUSTIFY_LEFT; - } - else if (icompare(ti.value, substr::create("center", 6)) == 0) - { - flags = XJUSTIFY_CENTER; - } - else if (icompare(ti.value, substr::create("right", 5)) == 0) - { - flags = XJUSTIFY_RIGHT; - } - else - { - return; - } - - a.cb = &cb; - } - - void reset_tag_xjustify(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, NULL, update_tag_reset_xjustify }; - a.cb = &cb; - } - - void update_tag_yjustify(const xtextbox::jot& j, xtextbox& tb, const xtextbox&) - { - tb.flags = (tb.flags & ~YJUSTIFY_MASK) | ((U32&)j.context & YJUSTIFY_MASK); - } - - void update_tag_reset_yjustify(const xtextbox::jot&, xtextbox& tb, const xtextbox& ctb) - { - tb.flags = (tb.flags & ~YJUSTIFY_MASK) | (ctb.flags & YJUSTIFY_MASK); - } - - void parse_tag_yjustify(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { NULL, NULL, update_tag_yjustify }; - U32& flags = (U32&)a.context; - - if (ti.action.size < 1 || ti.action.text[0] != '=') - { - return; - } - - if (icompare(ti.value, substr::create("top", 4)) == 0) - { - flags = YJUSTIFY_TOP; - } - else if (icompare(ti.value, substr::create("center", 4)) == 0) - { - flags = YJUSTIFY_CENTER; - } - else if (icompare(ti.value, substr::create("bottom", 4)) == 0) - { - flags = YJUSTIFY_BOTTOM; - } - else - { - return; - } - - a.cb = &cb; - } - - void reset_tag_yjustify(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - static const xtextbox::callback cb = { NULL, NULL, update_tag_reset_yjustify }; - a.cb = &cb; - } - - void parse_tag_open_curly(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - a.s.text = ti.tag.text; - a.s.size = 1; - - char c = a.s.text[0]; - - a.reset_flags(); - a.bounds = tb.font.bounds(c); - a.cb = tb.cb; - a.context = NULL; - } - - void parse_tag_newline(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag&) - { - a.flag.line_break = true; - a.flag.ethereal = false; - a.bounds = tb.font.bounds('\n'); - } - - void parse_tag_tab(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - a.flag.tab = true; - } - - void parse_tag_word_break(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - a.flag.word_break = true; - } - - void parse_tag_page_break(xtextbox::jot& a, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - a.flag.page_break = true; - } - - struct model_tag_context - { - xModelInstance* model; - xVec3 rot; - basic_rect dst; - xSphere o; - }; - - void render_tag_model(const xtextbox::jot& j, const xtextbox& tb, F32 x, F32 y) - { - model_tag_context& mtc = *(model_tag_context*)j.context; - - basic_rect dst = mtc.dst; - dst.move(x, y); - - xVec3 from = { 0, 0, 1.0f }; - xVec3 to = { 0, 0, -0.001f }; - - xMat4x3 frame; - - xMat3x3Euler(&frame, &mtc.rot); - - F32 scale = 1.001f * ((mtc.o.r <= 0.0f) ? 1.0f : 0.5f / mtc.o.r); - - frame.right *= scale; - frame.up *= scale; - frame.at *= scale; - frame.pos = mtc.o.center; - frame.flags = 0; - - xModelSetFrame(mtc.model, &frame); - xModelSetMaterialAlpha(mtc.model, tb.font.color.a); - - tex_flush(); - - RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE); - - xModelRender2D(*mtc.model, dst, from, to); - - RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE); - } - - void parse_tag_model(xtextbox::jot& a, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { render_tag_model, NULL, NULL }; - - load_model_args(def_model_args, ti.tag); - - if (def_model_args.model) - { - model_tag_context& mtc = *(model_tag_context*)a.context; - - mtc.model = def_model_args.model; - mtc.rot = def_model_args.rot; - mtc.rot *= 0.017453292f; - mtc.dst = def_model_args.dst; - - xSphere& o = *xModelGetLocalSBound(mtc.model); - mtc.o = o; - - mtc.dst.y -= def_model_args.off.y; - - a.bounds.assign(0.0f, -def_model_args.off.y, def_model_args.off.x, - def_model_args.off.y); - - switch (def_model_args.scale) - { - case model_args::SCALE_SIZE: - { - mtc.dst.scale(mtc.o.r); - a.bounds.scale(mtc.o.r); - break; - } - case model_args::SCALE_SCREEN: - { - break; - } - default: - { - mtc.dst.scale(tb.font.width, tb.font.height); - a.bounds.scale(tb.font.width, tb.font.height); - break; - } - } - - a.reset_flags(); - a.context_size = sizeof(model_tag_context); - a.cb = &cb; - } - } - - void reset_tag_model(xtextbox::jot&, const xtextbox&, const xtextbox&, - const xtextbox::split_tag&) - { - reset_model_args(def_model_args); - } - - struct tex_tag_context - { - RwRaster* raster; - F32 rot; - basic_rect src; - basic_rect dst; - }; - - void render_tag_tex(const xtextbox::jot& j, const xtextbox& tb, F32 x, F32 y) - { - tex_tag_context& ttc = *(tex_tag_context*)j.context; - - set_tex_raster(ttc.raster); - - basic_rect dst = ttc.dst; - dst.move(x, y); - - tex_render(ttc.src, dst, tb.font.clip, tb.font.color); - } - - xVec2 get_texture_size(RwRaster& raster); - - void parse_tag_tex(xtextbox::jot& j, const xtextbox& tb, const xtextbox&, - const xtextbox::split_tag& ti) - { - static const xtextbox::callback cb = { render_tag_tex, NULL, NULL }; - - load_tex_args(def_tex_args, ti.tag); - - if (def_tex_args.raster) - { - tex_tag_context& ttc = *(tex_tag_context*)j.context; - - ttc.raster = def_tex_args.raster; - ttc.rot = def_tex_args.rot; - ttc.src = def_tex_args.src; - ttc.dst = def_tex_args.dst; - ttc.dst.y -= def_tex_args.off.y; - - j.bounds.assign(0.0f, -def_tex_args.off.y, def_tex_args.off.x, def_tex_args.off.y); - - xVec2 size; - - switch (def_tex_args.scale) - { - case tex_args::SCALE_SCREEN: - { - size.assign(1.0f, 1.0f); - break; - } - case tex_args::SCALE_SIZE: - { - size = get_texture_size(*ttc.raster); - break; - } - case tex_args::SCALE_FONT_WIDTH: - { - size = get_texture_size(*ttc.raster); - size.y *= tb.font.width / size.x; - size.x = tb.font.width; - break; - } - case tex_args::SCALE_FONT_HEIGHT: - { - size = get_texture_size(*ttc.raster); - size.x *= tb.font.height / size.y; - size.y = tb.font.height; - break; - } - case tex_args::SCALE_SCREEN_WIDTH: - { - size = get_texture_size(*ttc.raster); - size.y *= 1.0f / size.x; - size.x = 1.0f; - break; - } - case tex_args::SCALE_SCREEN_HEIGHT: - { - size = get_texture_size(*ttc.raster); - size.x *= 1.0f / size.y; - size.y = 1.0f; - break; - } - default: - { - size.assign(tb.font.width, tb.font.height); - break; - } - } - - ttc.dst.scale(size.x, size.y); - j.bounds.scale(size.x, size.y); - j.reset_flags(); - j.context_size = sizeof(tex_tag_context); - j.cb = &cb; - } - } -} // namespace - -namespace -{ - xVec2 get_texture_size(RwRaster& raster) - { - xVec2 vec = { raster.width / 640.0f, raster.height / 480.0f }; - return vec; - } - - void reset_tag_tex(xtextbox::jot&, const xtextbox&, const xtextbox&, const xtextbox::split_tag&) - { - reset_tex_args(def_tex_args); - } - - void parse_tag_insert(xtextbox::jot& j, const xtextbox&, const xtextbox&, - const xtextbox::split_tag& ti) - { - j.reset_flags(); - j.flag.invisible = j.flag.ethereal = true; - - if (ti.action.size != 1 || ti.action.text[0] != ':' || ti.value.size == 0) - { - return; - } - - U32 id = xStrHash(ti.value.text, ti.value.size); - - if (id) - { - xTextAsset* ta = (xTextAsset*)xSTFindAsset(id, NULL); - - if (ta) - { - j.context = (char*)xTextAssetGetText(ta); - j.context_size = ta->len; - j.flag.insert = true; - } - } - } - - void parse_tag_insert_hash(xtextbox::jot& j, const xtextbox&, const xtextbox&, - const xtextbox::split_tag& ti) - { - j.reset_flags(); - j.flag.invisible = j.flag.ethereal = true; - - if (ti.action.size != 1 || ti.action.text[0] != ':' || ti.value.size == 0) - { - return; - } - - U32 id = atox(ti.value); - - if (id) - { - xTextAsset* ta = (xTextAsset*)xSTFindAsset(id, NULL); - - if (ta) - { - j.context = (char*)xTextAssetGetText(ta); - j.context_size = ta->len; - j.flag.insert = true; - } - } - } - - void parse_tag_pop(xtextbox::jot&, const xtextbox&, const xtextbox&, - const xtextbox::split_tag& ti) - { - if (ti.action.size != 1 || ti.action.text[0] != ':' || ti.value.size == 0) - { - return; - } - } - - void parse_tag_timer(xtextbox::jot& j, const xtextbox&, const xtextbox&, - const xtextbox::split_tag& ti) - { - j.reset_flags(); - j.flag.invisible = j.flag.ethereal = true; - - if (ti.action.size != 1 || ti.action.text[0] != ':' || ti.value.size == 0) - { - return; - } - - U32 id = xStrHash(ti.value.text, ti.value.size); - - if (id) - { - xTimer* ta = (xTimer*)zSceneFindObject(id); - - if (ta) - { - j.flag.insert = j.flag.dynamic = true; - - char buffer[64]; - U32 sec = (U32)ta->secondsLeft + 1; - U32 mn = sec / 60; - - if (mn) - { - sprintf(buffer, "%d:%02d", mn, sec - mn * 60); - } - else - { - sprintf(buffer, "%02d", sec); - } - - sprintf((char*)j.context, "%.*s", 15, buffer); - j.context_size = 16; - } - } - } - - // clang-format off - xtextbox::tag_type format_tags_buffer[2][128] = - { - SUBSTR(""), parse_tag_open_curly, NULL, NULL, - SUBSTR("a"), parse_tag_alpha, reset_tag_alpha, NULL, - SUBSTR("all"), NULL, reset_tag_all, NULL, - SUBSTR("alpha"), parse_tag_alpha, reset_tag_alpha, NULL, - SUBSTR("b"), parse_tag_blue, reset_tag_blue, NULL, - SUBSTR("blue"), parse_tag_blue, reset_tag_blue, NULL, - SUBSTR("c"), parse_tag_color, reset_tag_color, NULL, - SUBSTR("color"), parse_tag_color, reset_tag_color, NULL, - SUBSTR("f"), parse_tag_font, reset_tag_font, NULL, - SUBSTR("font"), parse_tag_font, reset_tag_font, NULL, - SUBSTR("g"), parse_tag_green, reset_tag_green, NULL, - SUBSTR("green"), parse_tag_green, reset_tag_green, NULL, - SUBSTR("h"), parse_tag_height, reset_tag_height, NULL, - SUBSTR("height"), parse_tag_height, reset_tag_height, NULL, - SUBSTR("i"), parse_tag_insert, NULL, NULL, - SUBSTR("ih"), parse_tag_insert_hash, NULL, NULL, - SUBSTR("insert"), parse_tag_insert, NULL, NULL, - SUBSTR("left_indent"), parse_tag_left_indent, reset_tag_left_indent, NULL, - SUBSTR("li"), parse_tag_left_indent, reset_tag_left_indent, NULL, - SUBSTR("model"), parse_tag_model, reset_tag_model, NULL, - SUBSTR("n"), parse_tag_newline, NULL, NULL, - SUBSTR("newline"), parse_tag_newline, NULL, NULL, - SUBSTR("page_break"), parse_tag_page_break, NULL, NULL, - SUBSTR("pb"), parse_tag_page_break, NULL, NULL, - SUBSTR("pop"), parse_tag_pop, NULL, NULL, - SUBSTR("r"), parse_tag_red, reset_tag_red, NULL, - SUBSTR("red"), parse_tag_red, reset_tag_red, NULL, - SUBSTR("ri"), parse_tag_right_indent, reset_tag_right_indent, NULL, - SUBSTR("right_indent"), parse_tag_right_indent, reset_tag_right_indent, NULL, - SUBSTR("t"), parse_tag_tab, NULL, NULL, - SUBSTR("tab"), parse_tag_tab, NULL, NULL, - SUBSTR("tab_stop"), parse_tag_tab_stop, reset_tag_tab_stop, NULL, - SUBSTR("tex"), parse_tag_tex, reset_tag_tex, NULL, - SUBSTR("timer"), parse_tag_timer, NULL, NULL, - SUBSTR("ts"), parse_tag_tab_stop, reset_tag_tab_stop, NULL, - SUBSTR("w"), parse_tag_width, reset_tag_width, NULL, - SUBSTR("wb"), parse_tag_word_break, NULL, NULL, - SUBSTR("width"), parse_tag_width, reset_tag_width, NULL, - SUBSTR("word_break"), parse_tag_word_break, NULL, NULL, - SUBSTR("wrap"), parse_tag_wrap, reset_tag_wrap, NULL, - SUBSTR("xj"), parse_tag_xjustify, reset_tag_xjustify, NULL, - SUBSTR("xjustify"), parse_tag_xjustify, reset_tag_xjustify, NULL, - SUBSTR("xs"), parse_tag_xspace, reset_tag_xspace, NULL, - SUBSTR("xspace"), parse_tag_xspace, reset_tag_xspace, NULL, - SUBSTR("yj"), parse_tag_yjustify, reset_tag_yjustify, NULL, - SUBSTR("yjustify"), parse_tag_yjustify, reset_tag_yjustify, NULL, - SUBSTR("ys"), parse_tag_yspace, reset_tag_yspace, NULL, - SUBSTR("yspace"), parse_tag_yspace, reset_tag_yspace, NULL - }; - // clang-format on - - xtextbox::tag_type* format_tags = format_tags_buffer[0]; - U32 format_tags_size = 48; -} // namespace - -void xtextbox::register_tags(const tag_type* t, size_t size) -{ - const tag_type *s1, *s2, *end1, *end2; - - s1 = format_tags; - end1 = s1 + format_tags_size; - s2 = t; - end2 = t + size; - - tag_type* d = (s1 == format_tags_buffer[0]) ? format_tags_buffer[1] : format_tags_buffer[0]; - - format_tags = d; - - while (s1 < end1 && s2 < end2) - { - S32 c = icompare(s1->name, s2->name); - - if (c < 0) - { - *d = *s1; - s1++; - } - else if (c > 0) - { - *d = *s2; - s2++; - } - else - { - *d = *s2; - s1++; - s2++; - } - - d++; - } - - while (s1 < end1) - { - *d = *s1; - d++; - s1++; - } - - while (s2 < end2) - { - *d = *s2; - d++; - s2++; - } - - format_tags_size = d - format_tags; -} - -xtextbox::tag_type* xtextbox::find_format_tag(const substr& s, S32& index) -{ - S32 start = 0; - S32 end = format_tags_size; - - while (start != end) - { - index = (start + end) / 2; - - tag_type& t = format_tags[index]; - S32 c = icompare(s, t.name); - - if (c < 0) - { - end = index; - } - else if (c > 0) - { - start = index + 1; - } - else - { - return &t; - } - } - - index = -1; - return NULL; -} - -namespace -{ - void set_rect_verts(RwIm2DVertex* verts, F32 x, F32 y, F32 w, F32 h, iColor_tag c, F32 rcz, - F32 nsz); - void set_rect_vert(RwIm2DVertex& vert, F32 x, F32 y, F32 z, iColor_tag c, F32 rcz); -} // namespace - -void render_fill_rect(const basic_rect& bounds, iColor_tag color) -{ - if (!bounds.empty()) - { - F32 rcz = 1.0f / RwCameraGetNearClipPlane(RwCameraGetCurrentCamera()); - F32 nsz = RwIm2DGetNearScreenZ(); - - xfont::set_render_state(NULL); - - RwIm2DVertex vert[4]; - basic_rect r = bounds; - - // non-matching: float scheduling - - r.scale(640.0f, 480.0f); - - set_rect_verts(vert, r.x, r.y, r.w, r.h, color, rcz, nsz); - RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vert, 4); - xfont::restore_render_state(); - } -} - -namespace -{ - void set_rect_verts(RwIm2DVertex* verts, F32 x, F32 y, F32 w, F32 h, iColor_tag c, F32 rcz, - F32 nsz) - { - set_rect_vert(verts[0], x, y, nsz, c, rcz); - set_rect_vert(verts[1], x, y + h, nsz, c, rcz); - set_rect_vert(verts[2], x + w, y, nsz, c, rcz); - set_rect_vert(verts[3], x + w, y + h, nsz, c, rcz); - } - - void set_rect_vert(RwIm2DVertex& vert, F32 x, F32 y, F32 z, iColor_tag c, F32 rcz) - { - RwIm2DVertexSetScreenX(&vert, x); - RwIm2DVertexSetScreenY(&vert, y); - RwIm2DVertexSetScreenZ(&vert, z); - RwIm2DVertexSetIntRGBA(&vert, c.r, c.g, c.b, c.a); - RwIm2DVertexSetRecipCameraZ(&vert, rcz); - } -} // namespace - -basic_rect& basic_rect::scale(F32 x, F32 y) -{ - return scale(x, y, x, y); -} - -basic_rect& basic_rect::scale(F32 x, F32 y, F32 w, F32 h) -{ - this->x *= x; - this->y *= y; - this->w *= w; - this->h *= h; - return *this; -} - -basic_rect& basic_rect::assign(F32 x, F32 y, F32 w, F32 h) -{ - this->x = x; - this->y = y; - this->w = w; - this->h = h; - return *this; -} - -bool basic_rect::empty() const -{ - return (w <= 0.0f || h <= 0.0f); -} - -void basic_rect::clip(basic_rect& a, basic_rect& b) const -{ - F32 bwaw = b.w / a.w; - F32 bwah = b.h / a.h; - - if (a.x < x) - { - F32 xax = x - a.x; - F32 bwawxax = bwaw * xax; - a.x = x; - a.w -= xax; - b.x += bwawxax; - b.w -= bwawxax; - } - - if (a.y < y) - { - F32 yay = y - a.y; - F32 bwahyay = bwah * yay; - a.y = y; - a.h -= yay; - b.y += bwahyay; - b.h -= bwahyay; - } - - F32 axaw = a.x + a.w; - F32 xw = x + w; - - if (axaw > xw) - { - F32 bwawaxawxw = bwaw * (axaw - xw); - b.w -= bwawaxawxw; - a.w = x + w - a.x; - } - - F32 ayah = a.y + a.h; - F32 yh = y + h; - - if (ayah > yh) - { - F32 bwahayahyh = bwah * (ayah - yh); - b.h -= bwahayahyh; - a.h = y + h - a.y; - } -} - -basic_rect& basic_rect::operator|=(const basic_rect& other) -{ - F32 x1, y1, x2, y2; - F32 _x1, _y1, _x2, _y2; - - this->get_bounds(x1, y1, x2, y2); - other.get_bounds(_x1, _y1, _x2, _y2); - - if (x1 > _x1) - { - x1 = _x1; - } - - if (y1 > _y1) - { - y1 = _y1; - } - - if (x2 < _x2) - { - x2 = _x2; - } - - if (y2 < _y2) - { - y2 = _y2; - } - - set_bounds(x1, y1, x2, y2); - - return *this; -} - -void basic_rect::set_bounds(F32 x1, F32 y1, F32 x2, F32 y2) -{ - x = x1; - w = x2 - x1; - y = y1; - h = y2 - y1; -} - -void basic_rect::get_bounds(F32& x1, F32& y1, F32& x2, F32& y2) const -{ - x1 = x; - x2 = x + w; - y1 = y; - y2 = y + h; -} - -basic_rect& basic_rect::move(F32 x, F32 y) -{ - this->x += x; - this->y += y; - return *this; -} - -basic_rect& basic_rect::scale(F32 s) -{ - return scale(s, s, s, s); -} - -xVec2& xVec2::assign(F32 x, F32 y) -{ - this->x = x; - this->y = y; - return *this; -} - -extern substr _427; - -substr substr::create(const char* text, size_t size) -{ - substr s = _427; - s.text = text; - s.size = size; - return s; -} - -size_t rskip_ws(substr& s) -{ - return rskip_ws(s.text, s.size); -} - -size_t rskip_ws(const char*& text, size_t& size) -{ - while (size && is_ws(text[size - 1])) - { - size--; - } - - return size; -} - -bool is_ws(char c) -{ - return (c == ' ' || c == '\t' || c == '\n'); -} - -const char* find_char(const substr& s, char c) -{ - if (!s.text) - { - return NULL; - } - - const char* text = s.text; - S32 size = s.size; - - while (size > 0 && *text != '\0') - { - if (*text == c) - { - return text; - } - - size--; - text++; - } - - return NULL; -} - -const char* skip_ws(substr& s) -{ - return skip_ws(s.text, s.size); -} - -const char* skip_ws(const char*& text, size_t& size) -{ - size_t i = 0; - - while (i < size && *text != '\0') - { - if (!is_ws(*text)) - { - size -= i; - break; - } - - text++; - i++; - } - - return text; -} - -size_t atox(const substr& s) -{ - size_t read_size; - return atox(s, read_size); -} - -size_t trim_ws(substr& s) -{ - return trim_ws(s.text, s.size); -} - -size_t trim_ws(const char*& text, size_t& size) -{ - skip_ws(text, size); - return rskip_ws(text, size); -} - -xtextbox::tag_type* xtextbox::find_format_tag(const substr& s) -{ - S32 index; - return find_format_tag(s, index); -} - -size_t xtextbox::layout::jots_size() const -{ - return _jots_size; -} - -xtextbox xtextbox::create() -{ - return create(xfont::create(), screen_bounds, 0, 0.0f, 0.0f, 0.0f, 0.0f); -} - -xfont xfont::create() -{ - return create(0, 0.0f, 0.0f, 0.0f, g_WHITE, screen_bounds); -} - -void xtextbox::jot::intersect_flags(const jot& other) -{ - *(U16*)&flag &= *(U16*)&other.flag; -} - -void xtextbox::jot::reset_flags() -{ - *(U16*)&flag = 0; -} - -xSphere* xModelGetLocalSBound(xModelInstance* model) -{ - return (xSphere*)RpAtomicGetBoundingSphere(model->Data); -} diff --git a/src/SB/Core/x/xGrid.cpp b/src/SB/Core/x/xGrid.cpp deleted file mode 100644 index 7ec9746..0000000 --- a/src/SB/Core/x/xGrid.cpp +++ /dev/null @@ -1,214 +0,0 @@ -#include "xGrid.h" - -#include "string.h" - -#include "xMath.h" -#include "xMemMgr.h" -#include "xEnt.h" - -extern float xGrid_float_0p001; -extern float xGrid_float_one; -extern float xGrid_float_one_quarter; - -void xGridBoundInit(xGridBound* bound, void* data) -{ - bound->data = data; - bound->gx = -1; - bound->gz = -1; - bound->ingrid = 0; - bound->oversize = 0; - bound->head = 0; - bound->next = 0; - bound->gpad = 0xea; -} - -// FIXME: Usual floating point problems, floating point loads get pulled to the start. -// Also, there's something funny going on with the malloc + memset at the end, -// I think they may not have used the obvious pattern for it, since changing -// the multiplication order for the second one generates closer machine code -// than the same for both lines. -void xGridInit(xGrid* grid, xBox* bounds, U16 nx, U16 nz, U8 ingrid_id) -{ - grid->ingrid_id = ingrid_id; - grid->nx = nx; - grid->nz = nz; - grid->minx = bounds->upper.x; - grid->minz = bounds->upper.z; - grid->maxx = bounds->lower.x; - grid->maxz = bounds->lower.z; - F32 gsizex = grid->maxx - grid->minx; - F32 gsizez = grid->maxz - grid->minz; - grid->csizex = gsizex / nx; - grid->csizez = gsizex / nz; - - if (__fabs(gsizex) <= xGrid_float_0p001) - { - grid->inv_csizex = xGrid_float_one; - } - else - { - grid->inv_csizex = nx / gsizex; - } - - if (__fabs(gsizez) <= xGrid_float_0p001) - { - grid->inv_csizez = xGrid_float_one; - } - else - { - grid->inv_csizez = nz / gsizez; - } - - grid->maxr = xGrid_float_one_quarter * MAX(grid->csizex, grid->csizez); - grid->cells = (xGridBound**)xMemAllocSize(nx * nz * sizeof(xGridBound*)); - memset(grid->cells, 0, sizeof(xGridBound*) * (nz * nx)); -} - -void xGridKill(xGrid* grid) -{ - xGridEmpty(grid); - grid->cells = NULL; -} - -void xGridEmpty(xGrid* grid) -{ - for (S32 x = 0; x < grid->nx; ++x) - { - for (S32 z = 0; z < grid->nz; ++z) - { - xGridBound** head = &grid->cells[z * grid->nx]; - xGridBound* curr = head[x]; - while (curr) - { - xGridBound* currnext = curr->next; - xGridBoundInit(curr, curr->data); - curr = currnext; - } - head[x] = NULL; - } - } - - xGridBound* curr = grid->other; - while (curr) - { - xGridBound* nextnext = curr->next; - xGridBoundInit(curr, curr->data); - curr = nextnext; - } - grid->other = NULL; -} - -bool xGridAddToCell(xGridBound** boundList, xGridBound* bound) -{ - if (bound->head) - { - if (gGridIterActive == 0) - { - if (!xGridRemove(bound)) - { - return false; - } - } - else - { - return false; - } - } - - bound->head = boundList; - bound->next = boundList[0]; - boundList[0] = bound; - return true; -} - -void xGridAdd(xGrid* grid, xGridBound* bound, S32 x, S32 z) -{ - xGridAddToCell(&grid->cells[z * grid->nx] + x, bound); -} - -S32 xGridRemove(xGridBound* bound) -{ - if (bound->head) - { - if (gGridIterActive) - { - bound->deleted = 1; - return 0; - } - else - { - xGridBound* curr = bound->head[0]; - xGridBound** prev = bound->head; - while (curr && curr != bound) - { - prev = &curr->next; - curr = curr->next; - } - - *prev = curr->next; - curr->next = NULL; - curr->head = NULL; - curr->ingrid = 0; - curr->deleted = 0; - curr->gx = -1; - curr->gz = -1; - } - } - return 1; -} - -void xGridUpdate(xGrid* grid, xEnt* ent) -{ - S32 dx; - S32 dz; - xGridGetCell(grid, ent, dx, dz); - - if (dx != ent->gridb.gx || dz != ent->gridb.gz) - { - if (xGridRemove(&ent->gridb)) - { - xGridAdd(grid, &ent->gridb, dx, dz); - } - } -} - -xGridBound** xGridGetCell(xGrid* grid, const xEnt* ent, S32& grx, S32& grz) -{ - const xBound* bound = &ent->bound; - const xVec3* center; - if (bound->type == XBOUND_TYPE_SPHERE) - { - center = &bound->sph.center; - } - else if (bound->type == XBOUND_TYPE_OBB) - { - center = &bound->box.center; - } - else if (bound->type == XBOUND_TYPE_BOX) - { - center = &bound->box.center; - } - else - { - return 0; - } - - xGridGetCell(grid, center->x, center->y, center->z, grx, grz); - return &grid->cells[grz * grid->nx] + grx; -} - -void xGridGetCell(xGrid* grid, F32 x, F32 y, F32 z, S32& grx, S32& grz) -{ - F32 pgridx = (x - grid->minx) * grid->inv_csizex; - F32 pgridz = (z - grid->minz) * grid->inv_csizez; - - grx = MIN(F32((grid->nx - 1) ^ 0x8000), MAX(0, pgridx)); - grz = MIN(F32((grid->nz - 1) ^ 0x8000), MAX(0, pgridx)); -} - -xGridBound* xGridIterFirstCell(xGrid* grid, F32 posx, F32 posy, F32 posz, S32& grx, S32& grz, - xGridIterator& iter) -{ - xGridGetCell(grid, posx, posy, posz, grx, grz); - return xGridIterFirstCell(grid, grx, grz, iter); -} diff --git a/src/SB/Core/x/xGroup.cpp b/src/SB/Core/x/xGroup.cpp deleted file mode 100644 index f907d8d..0000000 --- a/src/SB/Core/x/xGroup.cpp +++ /dev/null @@ -1,215 +0,0 @@ -#include "xGroup.h" - -#include "xMath.h" -#include "xMemMgr.h" -#include "zScene.h" - -#include - -void xGroupInit(void* b, void* asset) -{ - xGroupInit((xBase*)b, (xGroupAsset*)asset); -} - -void xGroupInit(xBase* b, xGroupAsset* asset) -{ - xGroup* t = (xGroup*)b; - - xBaseInit(b, (xBaseAsset*)asset); - b->eventFunc = xGroupEventCB; - t->asset = asset; - if (b->linkCount) - { - // Seek to then end of the xGroupAsset header and then seek to the end of the subsequent array of IDs - b->link = (xLinkAsset*)((U8*)(t->asset) + sizeof(xGroupAsset) + - asset->itemCount * sizeof(U32)); - } - else - { - b->link = NULL; - } - U32 numItems = xGroupGetCount(t); - xBase** item; - if (numItems != 0) - { - item = (xBase**)xMemAllocSize(numItems << 2); - } - else - { - item = NULL; - } - t->item = item; - t->last_index = 0; - t->flg_group = 0; -} - -void xGroupSetup(xGroup* g) -{ - if ((g->flg_group & 1) == 0) - { - U32 numItems = xGroupGetCount(g); - U32 i = 0; - U32 ind = 0; - while (i < numItems) - { - xBase* item = xGroupFindItemPtr(g, i); - i++; - *(g->item + ind) = item; - ind++; - } - g->flg_group |= 1; - } -} - -void xGroupSave(xGroup* ent, xSerial* s) -{ - xBaseSave((xBase*)ent, s); -} - -void xGroupLoad(xGroup* ent, xSerial* s) -{ - xBaseLoad((xBase*)ent, s); -} - -void xGroupReset(xGroup* ent) -{ - xBaseReset((xBase*)ent, (xBaseAsset*)ent->asset); - ent->last_index = 0; -} - -S32 xGroupEventCB(xBase* to, xBase* from, U32 toEvent, const F32* toParam, - xBase* toParamWidget) -{ - xGroup* g = (xGroup*)from; - switch (toEvent) - { - case eEventReset: - xGroupReset(g); - break; - case eEventDisableGroupContents: - toEvent = eEventDisable; - break; - } - S32 index = -1; - if (g->asset->groupFlags & 1) - { - U32 rand = xrand(); - index = rand % g->asset->itemCount; - } - else if (g->asset->groupFlags & 2) - { - index = g->last_index; - g->last_index = (g->last_index + 1) % g->asset->itemCount; - } - - switch (toEvent) - { - case eEventFastVisible: - for (S32 i = 0; i < g->asset->itemCount; i++) - { - if (!(index == -1 || index == i)) - { - continue; - } - - xBase* b = g->item[i]; - if (!b) - { - continue; - } - - if (b->baseFlags & 0x20) - { - xEntShow((xEnt*)b); - } - else - { - zEntEvent(b, toEvent, toParam, toParamWidget); - } - } - return 1; - case eEventFastInvisible: - for (S32 i = 0; i < g->asset->itemCount; i++) - { - if (!(index == -1 || index == i)) - { - continue; - } - - xBase* b = g->item[i]; - if (!b) - { - continue; - } - - if (b->baseFlags & 0x20) - { - xEntHide((xEnt*)b); - } - else - { - zEntEvent(b, toEvent, toParam, toParamWidget); - } - } - return 1; - default: - for (S32 i = 0; i < g->asset->itemCount; i++) - { - if (!(index == -1 || index == i)) - { - continue; - } - - xBase* b = g->item[i]; - if (!b) - { - continue; - } - - zEntEvent(b, toEvent, toParam, toParamWidget); - } - return 1; - } - - // Note (Square): This is unreachable. No idea what the default return was meant to bel - // but presumably it's different from the good path. - return 0; -} - -U32 xGroupGetCount(xGroup* g) -{ - return g->asset->itemCount; -} - -xBase* xGroupGetItemPtr(xGroup* g, U32 index) -{ - if ((g->flg_group & 1) == 0) - { - xGroupSetup(g); - } - return g->item != NULL ? g->item[index] : NULL; -} - -xBase* xGroupFindItemPtr(xGroup* g, U32 index) -{ - return (xBase*)zSceneFindObject((U32)((U32*)(g->asset + 1))[index]); -} - -U32 xGroupGetItem(xGroup* g, U32 index) -{ - return (U32)((U32*)(g->asset + 1))[index]; -} - -U32 xGroup::get_any() -{ - U16 numItems = this->asset->itemCount; - if (numItems == 0) - { - return NULL; - } - - U32 last = ((U32*)((U8*)this->asset + sizeof(xGroupAsset)))[this->last_index]; - U32 cnt = this->last_index + 1; - this->last_index = cnt % numItems; - return last; -} diff --git a/src/SB/Core/x/xHud.cpp b/src/SB/Core/x/xHud.cpp deleted file mode 100644 index 97db4b6..0000000 --- a/src/SB/Core/x/xHud.cpp +++ /dev/null @@ -1,469 +0,0 @@ -#include "xHud.h" -#include "xDebug.h" -#include "xEvent.h" -#include "xMath.h" -#include "xMathInlines.h" -#include "xstransvc.h" - -#include "zEnt.h" - -#include -#include - -namespace xhud -{ - - block_allocator* block_allocator::_head_alloc; - static bool inited; - - void block_allocator::flush_all() - { - for (block_allocator* allocator = _head_alloc; allocator != NULL; - allocator = allocator->_next_alloc) - { - allocator->flush(); - } - } - - block_allocator::block_allocator(U32 a0, U32 a1) - { - _block_size = ALIGN(a0, 4) + 4; - _top = NULL; - _next_alloc = _head_alloc; - _head_alloc = this; - set_increment(a1); - } - - void block_allocator::set_increment(U32 a0) - { - _alloc_size = _block_size * a0; - } - - void block_allocator::size_reserve(U32 size) - { - void** ppvVar1 = (void**)xMemAllocSize(size); - void** ppvVar2 = (void**)((U32)ppvVar1 + size); - for (; ppvVar1 < ppvVar2; ppvVar1 = (void**)((U32)ppvVar1 + _block_size)) - { - *ppvVar1 = _top; - _top = ppvVar1; - } - } - - void* block_allocator::alloc() - { - if (_top == NULL) - { - size_reserve(_alloc_size); - } - - void** ptr = (void**)_top; - _top = *ptr; - return ptr + 1; - } - - void block_allocator::free(void* ptr) - { - *(void**)((U32)ptr - 4) = _top; - _top = (void*)((U32)ptr - 4); - } - - void block_allocator::flush() - { - _top = NULL; - } - - block_allocator* widget::motive_allocator() - { - static block_allocator ba(40, 16); - return &ba; - } - - void init() - { - if (!inited) - { - inited = true; - } - else - { - widget::disable_all(true); - } - } - - void setup() - { - widget::setup_all(); - } - - void destroy() - { - xDebugRemoveTweak("HUD"); - widget::disable_all(true); - block_allocator::flush_all(); - } - - void update(F32 dt) - { - widget::update_all(dt); - } - - void render() - { - if (inited) - { - widget::render_all(); - } - } - - widget::widget(const asset& asset) - { - a = &asset; - _motive_top = NULL; - _motive_temp = NULL; - _motive_temp_tail = NULL; - flag.visible = 1; - flag.enabled = 0; - rc.loc = asset.loc; - rc.size = asset.size; - rc.r = rc.g = rc.b = rc.a = 1.0f; - start_rc = rc; - } - - void widget::init_base(xBase& b, const xBaseAsset& asset, unsigned long a2) - { - xBaseInit(&b, (xBaseAsset*)&asset); - b.eventFunc = cb_dispatch; - if (b.linkCount != 0) - { - b.link = (xLinkAsset*)((U32)&asset + a2); - } - } - - void widget::destruct() - { - disable(); - } - - void widget::presetup() - { - activity = ACT_NONE; - add_tweaks(); - } - - void widget::updater(F32 dt) - { - _motive_temp_tail = &_motive_temp; - motive_node** ppmVar2 = &_motive_top; - motive_node* top = _motive_top; - while (top != NULL) - { - bool unk = top->m.update(*this, dt); - if (!unk) - { - *ppmVar2 = top->next; - motive_allocator()->free(top); - } - else - { - ppmVar2 = &top->next; - } - top = *ppmVar2; - } - - if (_motive_temp != NULL) - { - *_motive_temp_tail = _motive_top; - _motive_top = _motive_temp; - _motive_temp = NULL; - } - - _motive_temp_tail = NULL; - if (_motive_top == NULL) - { - activity = ACT_NONE; - } - } - - void widget::dispatcher(xBase*, U32 event, const F32* toParam, xBase*) - { - switch (event) - { - case eEventEnable: - enable(); - break; - case eEventDisable: - disable(); - break; - case eEventVisible: - case eEventFastVisible: - flag.visible = 1; - break; - case eEventInvisible: - case eEventFastInvisible: - flag.visible = 0; - break; - case eEventDispatcher_ShowHud: - show(); - break; - case eEventDispatcher_HideHud: - hide(); - break; - } - } - - // Equivalent: scheduling - U32 widget::type() const - { - static U32 myid = xStrHash(a->type_name()); - return myid; - } - - bool widget::is(U32 id) const - { - return id == widget::type(); - } - - void widget::show() - { - clear_motives(); - - activity = ACT_SHOW; - - F32 dVar8 = start_rc.loc.x - rc.loc.x; - F32 dVar7 = start_rc.loc.y - rc.loc.y; - F32 fVar1 = dVar8 * dVar8 + dVar7 * dVar7; - if (fVar1 <= 0.000000009999999f) - { - rc.loc = start_rc.loc; - rc.a = start_rc.a; - } - else - { - F32 dVar4 = xsqrt(fVar1); - F32 dVar6 = 10.0f * dVar7; - fVar1 = 10.0f * dVar8; - F32 dVar5 = (-(fVar1 * fVar1 + (dVar6 * dVar6)) / (2.0f * dVar4)); - - add_motive(motive(&rc.loc.x, fVar1, dVar8, (dVar5 * dVar8) / dVar4, - accelerate_motive_update, NULL)); - - add_motive(motive(&rc.loc.y, dVar6, dVar7, (dVar5 * dVar7) / dVar4, - accelerate_motive_update, NULL)); - - fVar1 = start_rc.a - rc.a; - add_motive(motive(&rc.a, 3.0f * fVar1, fVar1, 0.0f, linear_motive_update, NULL)); - } - } - - // Nonmatching: not finished - void widget::hide() - { - activity = ACT_HIDE; - - F32 fVar1 = start_rc.size.x; - F32 fVar3 = start_rc.size.y; - F32 fVar7 = (start_rc.loc.x - 0.5f) + 0.5f * fVar1; - F32 fVar8 = (start_rc.loc.y - 0.5f) + 0.5f * fVar3; - if (iabs(iabs(fVar7) + iabs(fVar8)) <= 0.0001f) - { - rc.a = 0.0f; - } - else - { - F32 fVar5; - F32 fVar6; - if (iabs(fVar7) > iabs(fVar8)) - { - if (fVar8 >= 0.0f) - { - fVar6 = 0.5f + fVar3; - } - else - { - fVar6 = -0.5f - fVar3; - } - fVar5 = (fVar6 * fVar7) / fVar8; - } - else - { - if (fVar7 >= 0.5f) - { - fVar5 = 0.5f + fVar1; - } - else - { - fVar5 = -0.5f - fVar1; - } - fVar6 = (fVar5 * fVar8) / fVar7; - } - - F32 dVar11 = 255.0f + (fVar6 - 0.5f * fVar3) - rc.loc.y; - F32 dVar12 = 255.0f + (fVar5 - 0.5f * fVar1) - rc.loc.x; - F32 dVar10 = xsqrt(dVar12 * dVar12 + dVar11 * dVar11); - - add_motive( - motive(&rc.loc.x, 0.0f, dVar12, dVar12 * dVar10, accelerate_motive_update, NULL)); - - add_motive( - motive(&rc.loc.y, 0.0f, dVar11, dVar11 * dVar10, accelerate_motive_update, NULL)); - - fVar1 = -rc.a; - add_motive(motive(&rc.a, 0.4f * fVar1, dVar11, 0.0f, linear_motive_update, NULL)); - } - } - - namespace - { - - void fp_setup(widget& w) - { - w.setup(); - } - - void fp_render(widget& w) - { - if (w.visible()) - { - w.render(); - } - } - - } // namespace - - void widget::add_motive(const motive& m) - { - motive_node* node = (motive_node*)motive_allocator()->alloc(); - new (node) motive(m); - - if (_motive_temp_tail == NULL) - { - node->next = _motive_top; - _motive_top = node; - } - else - { - if (_motive_temp == NULL) - { - _motive_temp_tail = &node->next; - } - node->next = _motive_temp; - _motive_temp = node; - } - } - - void widget::clear_motives() - { - activity = ACT_NONE; - motive_node* node = _motive_top; - while (node != NULL) - { - node->m.finish(); - _motive_top = node->next; - motive_allocator()->free(node); - node = _motive_top; - } - } - - void widget::clear_motives(bool (*fp_update)(widget&, motive&, F32), void* context) - { - motive_node** ppmVar2 = &_motive_top; - motive_node* node = _motive_top; - - while (node != NULL) - { - if (node->m.fp_update == fp_update && node->m.context == context) - { - *ppmVar2 = node->next; - motive_allocator()->free(node); - } - else - { - ppmVar2 = &node->next; - } - node = *ppmVar2; - } - - if (_motive_top == NULL) - { - activity = ACT_NONE; - } - } - - bool linear_motive_update(widget& w, motive& m, F32 dt) - { - F32 fVar1 = dt * m.delta; - F32 fVar2 = m.max_offset - m.offset; - if ((fVar1 >= 0.0f && fVar1 >= fVar2) || (fVar1 < 0.0f && fVar1 <= fVar2)) - { - *m.value += fVar2; - m.offset = m.max_offset; - return false; - } - else - { - *m.value += fVar1; - m.offset += fVar1; - return true; - } - } - - // Equivalent: regalloc - bool accelerate_motive_update(widget& w, motive& m, F32 dt) - { - F32 fVar2; - F32 fVar1; - F32 delta; - - fVar1 = 0.5f * m.accel; - delta = m.delta; - m.delta = dt * m.accel + delta; - delta *= dt; - fVar1 *= dt; - fVar1 = dt * fVar1 + delta; - - fVar2 = m.max_offset - m.offset; - - if ((fVar1 >= 0.0f && fVar1 >= fVar2) || (fVar1 < 0.0f && fVar1 <= fVar2)) - { - *m.value += fVar2; - m.offset = m.max_offset; - return false; - } - else - { - *m.value += fVar1; - m.offset += fVar1; - return true; - } - } - - void __deadstripped_xHud() - { - // "%d" was used in a deadstripped function. This function forces it to be used. - xStrHash("%d"); - } - - xModelInstance* load_model(U32 modelID) - { - U32 size; - void* info = xSTFindAsset(xStrHashCat(modelID, ".minf"), &size); // xModelAssetInfo* - if (info != NULL) - { - return zEntRecurseModelInfo(info, NULL); - } - - info = xSTFindAsset(modelID, &size); // RpAtomic* - if (info == NULL) - { - info = xSTFindAsset(xStrHashCat(modelID, ".dff"), &size); // RpAtomic* - } - if (info == NULL) - { - return NULL; - } - - return xModelInstanceAlloc((RpAtomic*)info, NULL, 0, 0, NULL); - } - -} // namespace xhud diff --git a/src/SB/Core/x/xHudFontMeter.cpp b/src/SB/Core/x/xHudFontMeter.cpp deleted file mode 100644 index 99fba11..0000000 --- a/src/SB/Core/x/xHudFontMeter.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "xHudFontMeter.h" - -#include diff --git a/src/SB/Core/x/xHudMeter.cpp b/src/SB/Core/x/xHudMeter.cpp deleted file mode 100644 index aeadd57..0000000 --- a/src/SB/Core/x/xHudMeter.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "xHudMeter.h" - -#include diff --git a/src/SB/Core/x/xHudModel.cpp b/src/SB/Core/x/xHudModel.cpp deleted file mode 100644 index 3b61a73..0000000 --- a/src/SB/Core/x/xHudModel.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "xHudModel.h" -#include "xHud.h" -#include "xString.h" - -#include -#include - -xAnimTable* XHUD_AnimTable_Idle() -{ - xAnimTable* table = xAnimTableNew("XHUD_AnimTable_Idle", NULL, 0); - xAnimTableNewState(table, "Idle01", 0x10, 1, 1.0f, NULL, NULL, 0.0f, NULL, NULL, - xAnimDefaultBeforeEnter, NULL, NULL); - return table; -} - -namespace xhud -{ - - void model_widget::load(xBase& data, xDynAsset& asset, size_t) - { - init_base(data, asset, sizeof(xBase) + sizeof(model_widget)); - model_widget* widget = (model_widget*)(&data + 1); - new (widget) model_widget((model_asset&)asset); - } - - model_widget::model_widget(const model_asset& masset) - : widget(masset), mid(masset.model), model(NULL) - { - model = load_model(mid); - } - - void model_widget::destruct() - { - widget::destruct(); - } - - void model_widget::destroy() - { - destruct(); - } - - // Equivalent: scheduling - U32 model_widget::type() const - { - static U32 myid = xStrHash(model_asset::type_name()); - return myid; - } - - bool model_widget::is(U32 id) const - { - return id == model_widget::type() || widget::is(id); - } - - void model_widget::update(F32 dt) - { - widget::updater(dt); - - if (!visible() || rc.a <= (0.5f / 255.0f)) - { - return; - } - - xModelUpdate(model, dt); - xModelEval(model); - } - - void model_widget::render() - { - if (rc.a <= 0.0f) - { - return; - } - - render_model(*model, rc); - } - -} // namespace xhud diff --git a/src/SB/Core/x/xHudText.cpp b/src/SB/Core/x/xHudText.cpp deleted file mode 100644 index 5c9597a..0000000 --- a/src/SB/Core/x/xHudText.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "xHudText.h" -#include "xstransvc.h" -#include "xTextAsset.h" -#include "zScene.h" -#include "zTextBox.h" - -#include -#include -#include - -void xhud::text_widget::load(xBase& data, xDynAsset& asset, size_t) -{ - init_base(data, asset, sizeof(xBase) + sizeof(text_widget)); - text_widget* widget = (text_widget*)(&data + 1); - new (widget) text_widget((text_asset&)asset); -} - -xhud::text_widget::text_widget(const xhud::text_asset& asset) : widget(asset) -{ - text[0] = '\0'; -} - -void xhud::text_widget::destruct() -{ - widget::destruct(); -} - -void xhud::text_widget::setup() -{ - presetup(); - text_asset* asset = (text_asset*)a; - ztextbox* textbox = (ztextbox*)zSceneFindObject(asset->text_box); - if (textbox == NULL) - { - tb = xtextbox::create(); - return; - } - - textbox->refresh(); - tb = textbox->tb; - textbox->get_text(text, sizeof(text)); - if (asset->text != 0) - { - xTextAsset* tasset = (xTextAsset*)xSTFindAsset(asset->text, NULL); - if (tasset != NULL) - { - char* text_asset_text = xTextAssetGetText(tasset); - U32 len = strlen(text_asset_text); - if (len >= sizeof(text)) - { - len = sizeof(text) - 1; - } - memcpy(text, text_asset_text, len); - text[len] = '\0'; - } - } - - rc.r = tb.font.color.r / 255.0f; - rc.g = tb.font.color.g / 255.0f; - rc.b = tb.font.color.b / 255.0f; -} - -void xhud::text_widget::destroy() -{ - destruct(); -} - -// Equivalent: scheduling -U32 xhud::text_widget::type() const -{ - static U32 myid = xStrHash(text_asset::type_name()); - return myid; -} - -bool xhud::text_widget::is(U32 id) const -{ - return id == text_widget::type() || widget::is(id); -} - -void __deadstripped_xHudText(xhud::text_widget& w) -{ - // NOTE(tgsm): This function only exists to assure correct value ordering in .sdata2. - // I don't actually know what this function contains, and I wouldn't use it if I were you. - w.tb.font.width = 0.0f; -} - -void xhud::text_widget::update(F32 dt) -{ - updater(dt); - - tb.set_text(text); - tb.bounds.x = rc.loc.x; - tb.bounds.y = rc.loc.y; - tb.bounds.w = rc.size.x; - tb.bounds.h = rc.size.y; - tb.font.clip = tb.bounds; - - tb.font.color.r = (rc.r * 255.0f) + 0.5f; - tb.font.color.g = (rc.g * 255.0f) + 0.5f; - tb.font.color.b = (rc.b * 255.0f) + 0.5f; - tb.font.color.a = (rc.a * 255.0f) + 0.5f; -} - -void xhud::text_widget::render() -{ - F32 boundX = tb.bounds.x; - F32 boundY = tb.bounds.y; - U8 oldRed = tb.font.color.r; - U8 oldGreen = tb.font.color.g; - U8 oldBlue = tb.font.color.b; - U8 oldAlpha = tb.font.color.a; - - U8 alpha; - F32 fVar1 = (oldAlpha * 200.0f) / 255.0f; - if (fVar1 > 255.0f) - { - alpha = 0xFF; - } - else if (fVar1 < 0.0f) - { - alpha = 0; - } - else - { - alpha = fVar1; - } - - tb.bounds.x += 0.0075f; - tb.bounds.y += 0.0075f; - tb.font.color.r = 0x00; - tb.font.color.g = 0x46; - tb.font.color.b = 0x55; - tb.font.color.a = alpha; - tb.render(true); - - tb.bounds.x = boundX; - tb.bounds.y = boundY; - tb.font.color.r = oldRed; - tb.font.color.g = oldGreen; - tb.font.color.b = oldBlue; - tb.font.color.a = oldAlpha; - tb.render(true); -} diff --git a/src/SB/Core/x/xHudUnitMeter.cpp b/src/SB/Core/x/xHudUnitMeter.cpp deleted file mode 100644 index 0d90bd9..0000000 --- a/src/SB/Core/x/xHudUnitMeter.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "xHudUnitMeter.h" - -#include diff --git a/src/SB/Core/x/xIni.cpp b/src/SB/Core/x/xIni.cpp deleted file mode 100644 index d1a270b..0000000 --- a/src/SB/Core/x/xIni.cpp +++ /dev/null @@ -1,202 +0,0 @@ -#include "xIni.h" -#include "xString.h" -#include - -#include -#include -#include - -char* TrimWhitespace(char* string) -{ - // Skip through any leading whitespace - for (; *string == ' ' || *string == '\t'; string++) - { - } - // Return early if there's no other characters to go through - if (*string == '\0') - { - return string; - } - - // Find first non-whitespace character at the end of the string - char* substring = &string[strlen(string) - 1]; - for (; *substring == ' ' || *substring == '\t'; substring--) - { - } - - // Set the null-terminator accordingly - substring[1] = '\0'; - - return string; -} - -xIniFile* xIniParse(char* buf, S32 len) -{ - S32 i; - S32 ccr = 1; - S32 clf = 1; - S32 copen = 0; - S32 lastCRLF = -1; - for (i = 0; i < len; i++) - { - switch (buf[i]) - { - case '\n': - lastCRLF = i; - clf++; - break; - case '\r': - lastCRLF = i; - ccr++; - break; - case '[': - copen++; - break; - } - } - - if (clf > ccr) - { - ccr = clf; - } - - S32 sectionAlloc = copen; - S32 valueAlloc = ccr; - - xIniFile* ini = (xIniFile*)RwMalloc(sizeof(xIniFile) + (valueAlloc * sizeof(xIniValue)) + - (sectionAlloc * sizeof(xIniSection)) + (len - lastCRLF)); - ini->mem = NULL; - ini->NumValues = 0; - ini->NumSections = 0; - ini->Values = (xIniValue*)(ini + 1); - ini->Sections = (xIniSection*)(ini->Values + valueAlloc); - - char* lastLine = (char*)(ini->Sections + sectionAlloc); - strncpy(lastLine, buf + (lastCRLF + 1), len - (lastCRLF + 1)); - lastLine[len - (lastCRLF + 1)] = '\0'; - - if (lastCRLF >= 0) - { - buf[lastCRLF] = '\0'; - } - else - { - buf[0] = '\0'; - } - - char* ltoken; - char* line = xStrTok(buf, "\n\r", <oken); - if (line == NULL) - { - line = xStrTok(lastLine, "\n\r", <oken); - lastLine = NULL; - } - - while (line != NULL) - { - line = TrimWhitespace(line); - if (*line != '#' && *line != '\0') - { - if (*line == '[') - { - char* c = std::strstr(line, "]"); - if (c != NULL) - { - *c = '\0'; - c = TrimWhitespace(line + 1); - if (*c != '\0') - { - ini->Sections[ini->NumSections].sec = c; - ini->Sections[ini->NumSections].first = ini->NumValues; - ini->Sections[ini->NumSections].count = 0; - ini->NumSections++; - } - } - } - else - { - char* c = std::strstr(line, "="); - if (c != NULL) - { - *c = '\0'; - char* tok = TrimWhitespace(line); - if (*tok != '\0') - { - line = c + 1; - c = std::strstr(line, "#"); - if (c != NULL) - { - *c = '\0'; - } - char* val = TrimWhitespace(line); - ini->Values[ini->NumValues].tok = tok; - ini->Values[ini->NumValues].val = val; - ini->NumValues++; - if (ini->NumSections != 0) - { - ini->Sections[ini->NumSections - 1].count++; - } - } - } - } - } - - line = xStrTok(NULL, "\n\r", <oken); - if (line == NULL && lastLine != NULL) - { - line = xStrTok(lastLine, "\n\r", <oken); - lastLine = NULL; - } - } - - return ini; -} - -void xIniDestroy(xIniFile* ini) -{ - RwFree(ini->mem); - RwFree(ini); -} - -S32 xIniGetIndex(xIniFile* ini, char* tok) -{ - for (S32 i = 0; i < ini->NumValues; i++) - { - if (xStricmp(ini->Values[i].tok, tok) == 0) - { - return i; - } - } - - return -1; -} - -S32 xIniGetInt(xIniFile* ini, char* tok, S32 def) -{ - S32 index = xIniGetIndex(ini, tok); - if (index == -1) - { - return def; - } - return atoi(ini->Values[index].val); -} - -F32 xIniGetFloat(xIniFile* ini, char* tok, F32 def) -{ - S32 index = xIniGetIndex(ini, tok); - if (index == -1) - { - return def; - } - return atof(ini->Values[index].val); -} - -char* xIniGetString(xIniFile* ini, char* tok, char* def) -{ - S32 index = xIniGetIndex(ini, tok); - if (index == -1) - { - return def; - } - return ini->Values[index].val; -} diff --git a/src/SB/Core/x/xJSP.cpp b/src/SB/Core/x/xJSP.cpp deleted file mode 100644 index bec648a..0000000 --- a/src/SB/Core/x/xJSP.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "xJSP.h" - -#include -#include - -#include "xClumpColl.h" - -extern S32 sAtomicStartCount; // not exactly sure of the type -extern RwV3d* sCurrVert; // not sure if correct type. not sure what this is. -extern RwV3d* sAtomicStartVert; // I'm just going based on matt's assumption - -extern void* RwEngineInstance; - -// No dwarf info -// ghidra said return type and type of param_2 was void -// but changing it to return atomic matches. -RpAtomic* CountAtomicCB(RpAtomic* atomic, U32* param_2) -{ - sAtomicStartCount++; - *param_2 += atomic->geometry->mesh->totalIndicesInMesh; - return atomic; -} - -static RpMesh* AddMeshCB(RpMesh* mesh, RpMeshHeader* header, void* param_3) -{ - for (int i = 0; i < mesh->numIndices; i++) - { - **(RwV3d**)(param_3) = sCurrVert[mesh->indices[i]]; - *((S32*)(param_3)) += sizeof(RwV3d); - } - - return mesh; -} - -RpAtomic* AddAtomicCB(RpAtomic* atomic, void* data) -{ - // The dwarf defines this variable but it looks like it isnt used - // TempAtomicList** tmpList; - sAtomicStartCount--; - sAtomicStartVert[sAtomicStartCount] = *(RwV3d*)data; - sCurrVert = atomic->geometry->morphTarget->verts; - _rpMeshHeaderForAllMeshes(atomic->geometry->mesh, (RpMeshCallBack)&AddMeshCB, data); - return atomic; -} - -RpAtomic* AddAtomicPrecalcedVertCB(RpAtomic* atomic, void* data) -{ - sAtomicStartCount--; - sAtomicStartVert[sAtomicStartCount] = *(RwV3d*)data; - data = &data + atomic->geometry->mesh->totalIndicesInMesh * 0xc; - - return atomic; -} - -RpAtomic* ListAtomicCB(RpAtomic* atomic, void* data) -{ - // RpAtomic*** aList; <- declared in dwarf data - // ¯\_(ツ)_/¯ idk what's going on - **(RpAtomic***)data = atomic; - *(S32*)data += 4; - return atomic; -} diff --git a/src/SB/Core/x/xJaw.cpp b/src/SB/Core/x/xJaw.cpp deleted file mode 100644 index f94519f..0000000 --- a/src/SB/Core/x/xJaw.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "xJaw.h" - -#include "xstransvc.h" - -#include - -struct xJawDataTable -{ - U32 soundHashID; - U32 dataStart; - U32 dataLength; -}; - -void* xJaw_FindData(U32 soundID) -{ - S32 i, numJawTables; - - numJawTables = xSTAssetCountByType('JAW '); - - for (i = 0; i < numJawTables; i++) - { - U32 j; - void* data; - U32 jawcount; - xJawDataTable* tbl; - void* rawdata; - - data = xSTFindAssetByType('JAW ', i, NULL); - jawcount = *(U32*)data; - tbl = (xJawDataTable*)((U32*)data + 1); - rawdata = tbl + jawcount; - - for (j = 0; j < jawcount; j++) - { - if (soundID == tbl[j].soundHashID) - { - return (U8*)rawdata + tbl[j].dataStart; - } - } - } - - xSTAssetName(soundID); - return NULL; -} - -#define swap(data) \ - { \ - U8 c; \ - c = ((U8*)(data))[3]; \ - ((U8*)(data))[3] = ((U8*)(data))[0]; \ - ((U8*)(data))[0] = c; \ - c = ((U8*)(data))[2]; \ - ((U8*)(data))[2] = ((U8*)(data))[1]; \ - ((U8*)(data))[1] = c; \ - } - -F32 xJaw_EvalData(void* data, F32 time) -{ - F32 lerp; - S32 idx, numdata; - - numdata = *(S32*)data; - - if (numdata > (U32)0xFFFF) - { - swap(data); - } - - time *= 60.0f; - idx = std::floorf(time); - lerp = time - std::floorf(time); - - if (idx < 0) - { - return 0.0f; - } - else if (idx >= numdata - 1) - { - return 0.0f; - } - else - { - U8* jawdata; - jawdata = (U8*)data + 4; - - return ((1.0f - lerp) * jawdata[idx] + lerp * jawdata[idx + 1]) / 255.0f; - } -} diff --git a/src/SB/Core/x/xLaserBolt.cpp b/src/SB/Core/x/xLaserBolt.cpp deleted file mode 100644 index 423a004..0000000 --- a/src/SB/Core/x/xLaserBolt.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "xLaserBolt.h" -#include "xString.h" -#include "xstransvc.h" -#include "iParMgr.h" - -#include - -extern tagiRenderInput gRenderBuffer; -extern F32 lbl_803CF7A4; // 0.0f -extern F32 lbl_803CF7A8; // 255f - -void xLaserBoltEmitter::set_texture(char* name) -{ - set_texture(xStrHash(name)); -} - -void xLaserBoltEmitter::set_texture(U32 aid) -{ - set_texture((RwTexture*)xSTFindAsset(aid, NULL)); -} - -void xLaserBoltEmitter::set_texture(RwTexture* tex) -{ - if (tex == NULL) - { - this->bolt_raster = NULL; - } - else - { - set_texture(tex->raster); - } -} - -void xLaserBoltEmitter::set_texture(RwRaster* raster) -{ - this->bolt_raster = raster; -} - -void xLaserBoltEmitter::refresh_config() -{ - F32 alpha; - if (this->cfg.kill_dist <= this->cfg.fade_dist) - { - alpha = lbl_803CF7A4; - } - else - { - alpha = lbl_803CF7A8 / (this->cfg.kill_dist - this->cfg.fade_dist); - } - this->ialpha = alpha; -} - -void xLaserBoltEmitter::attach_effects(fx_when_enum when, effect_data* fx, size_t fxsize) -{ - // TODO!!! -} - -RxObjSpace3DVertex* xLaserBoltEmitter::get_vert_buffer(S32& dat) -{ - dat = (U32)0x1e0; - return gRenderBuffer.m_vertex; -} - -// WIP. -void xLaserBoltEmitter::reset_fx(fx_when_enum when) -{ - U32* sizePtr = &this->fxsize[when]; - effect_data** effect = &this->fx[when]; -} diff --git a/src/SB/Core/x/xLightKit.cpp b/src/SB/Core/x/xLightKit.cpp deleted file mode 100644 index 87866c2..0000000 --- a/src/SB/Core/x/xLightKit.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include "xLightKit.h" -#include "xMath.h" - -#include -#include - -S32 iModelHack_DisablePrelight; -xLightKit* gLastLightKit; - -xLightKit* xLightKit_Prepare(void* data) -{ - xLightKit* lkit = (xLightKit*)data; - lkit->lightList = (xLightKitLight*)((int*)data + 4); - xLightKitLight* currlight = (xLightKitLight*)((int*)data + 4); - - for (int i = 0; i < lkit->lightCount; currlight++, i++) - { - if (currlight->platLight != NULL) - { - return lkit; - } - - // If any of the colors is greater than 1.0, normalize back to 0-1 - if (currlight->color.red > 1.0f || currlight->color.green > 1.0f || - currlight->color.blue > 1.0f) - { - F32 s; - s = MAX(MAX(currlight->color.red, currlight->color.green), currlight->color.blue); - s = MAX(s, 0.00001f); - s = 1.0f / s; - currlight->color.red *= s; - currlight->color.green *= s; - currlight->color.blue *= s; - } - - switch (currlight->type) - { - case 1: - currlight->platLight = RpLightCreate(2); - break; - case 2: - currlight->platLight = RpLightCreate(1); - break; - case 3: - currlight->platLight = RpLightCreate(128); - break; - case 4: - currlight->platLight = RpLightCreate(130); - break; - default: - break; - } - RpLightSetColor(currlight->platLight, &currlight->color); - if (currlight->type >= 2) - { - RwFrame* frame = RwFrameCreate(); - RwMatrixTag tmpmat; - - memset(&tmpmat, 0, 64); - tmpmat.right.x = -currlight->matrix[0]; - tmpmat.right.y = -currlight->matrix[1]; - tmpmat.right.z = -currlight->matrix[2]; - tmpmat.up.x = currlight->matrix[4]; - tmpmat.up.y = currlight->matrix[5]; - tmpmat.up.z = currlight->matrix[6]; - tmpmat.at.x = -currlight->matrix[8]; - tmpmat.at.y = -currlight->matrix[9]; - tmpmat.at.z = -currlight->matrix[10]; - tmpmat.pos.x = currlight->matrix[12]; - tmpmat.pos.y = currlight->matrix[13]; - tmpmat.pos.z = currlight->matrix[14]; - RwV3dNormalize(&tmpmat.right, &tmpmat.right); - RwV3dNormalize(&tmpmat.up, &tmpmat.up); - RwV3dNormalize(&tmpmat.at, &tmpmat.at); - RwFrameTransform(frame, &tmpmat, rwCOMBINEREPLACE); - _rwObjectHasFrameSetFrame(currlight->platLight, frame); - } - if (currlight->type >= 3) - { - RpLightSetRadius(currlight->platLight, currlight->radius); - } - if (currlight->type >= 4) - { - RpLightSetConeAngle(currlight->platLight, currlight->angle); - } - } - - return (xLightKit*)data; -} - -void xLightKit_Enable(xLightKit* lkit, RpWorld* world) -{ - if (lkit != gLastLightKit) - { - int i; - if (gLastLightKit != NULL) - { - for (i = 0; i < gLastLightKit->lightCount; i++) - { - RpWorldRemoveLight(world, gLastLightKit->lightList[i].platLight); - } - } - gLastLightKit = lkit; - if (lkit != NULL) - { - iModelHack_DisablePrelight = 1; - for (i = 0; i < lkit->lightCount; i++) - { - RpWorldAddLight(world, lkit->lightList[i].platLight); - } - } - else - { - iModelHack_DisablePrelight = 0; - } - } -} - -xLightKit* xLightKit_GetCurrent(RpWorld* world) -{ - return gLastLightKit; -} - -void xLightKit_Destroy(xLightKit* lkit) -{ - if (lkit == NULL) - { - return; - } - - int i; - xLightKitLight* currLight = lkit->lightList; - - for (i = 0; i < lkit->lightCount; currLight++, i++) - { - if (currLight->platLight != NULL) - { - _rwFrameSyncDirty(); - RwFrame* tframe = (RwFrame*)(currLight->platLight->object).object.parent; - if (tframe != NULL) - { - _rwObjectHasFrameSetFrame(currLight->platLight, 0); - RwFrameDestroy(tframe); - } - RpLightDestroy(currLight->platLight); - currLight->platLight = 0; - } - } -} diff --git a/src/SB/Core/x/xMath.cpp b/src/SB/Core/x/xMath.cpp deleted file mode 100644 index bcaae2a..0000000 --- a/src/SB/Core/x/xMath.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "xMath.h" - -#include -#include - -#include "xMathInlines.h" - -extern S32 xmath_inited; -extern S32 xmath_exited; -extern volatile U32 rndseed; // made this volatile so xrand() matches - -void xMathInit() -{ - if (!xmath_inited) - { - xmath_inited = 1; - rndseed = 0; - } -} - -void xMathExit() -{ - if (!xmath_exited) - { - xmath_exited = 1; - } -} - -F32 xatof(const char* x) -{ - return atof(x); -} - -void xsrand(U32 seed) -{ - rndseed = seed; -} - -U32 xrand() -{ - rndseed = rndseed * 1103515245 + 12345; - return rndseed; -} - -F32 xurand() -{ - return xrand() * 2.3283064e-10f; -} - -U32 xMathSolveQuadratic(F32 a, F32 b, F32 c, F32* x1, F32* x2) -{ - F32 d; - F32 dx; - F32 p; - - if (a == 0.0f) - { - if (b == 0.0f) - { - return 0; - } - - *x1 = -c / b; - return 1; - } - - d = b * b - (4.0f * a * c); - - if (d < 0.0f) - { - return 0; - } - - dx = 1.0f / (2.0f * a); - - *x1 = -b * dx; - - if (d == 0.0f) - { - return 1; - } - - *x2 = *x1; - - p = dx * xsqrt(d); - - if (a > 0.0f) - { - *x1 -= p; - *x2 += p; - } - else - { - *x1 += p; - *x2 -= p; - } - - return 2; -} - -F32 xAngleClamp(F32 a) -{ - F32 rad360 = 2 * PI; - F32 rem = xfmod(a, rad360); - - if (rem < 0.0f) - { - return rem + rad360; - } - - return rem; -} - -F32 xAngleClampFast(F32 a) -{ - F32 rad360 = (2 * PI); - - if (a < 0.0f) - { - return a + rad360; - } - - if (a >= rad360) - { - return a - rad360; - } - - return a; -} - -F32 xDangleClamp(F32 a) -{ - F32 rad360 = 2 * PI; - F32 rem = xfmod(a, rad360); - - if (rem >= PI) - { - return rem - rad360; - } - - if (rem < -PI) - { - return rem + rad360; - } - - return rem; -} - -F32 xAccelMoveTime(F32 dx, F32 a, F32, F32 maxv) -{ - float time = a; - float atime = maxv / time; - dx *= 0.5f; - float adist = 0.5f * time * atime * atime; - - dx = (adist < dx) ? xsqrt(2.0f * dx / time) : (atime + (dx - adist) / maxv); - - return 2.0f * dx; -} \ No newline at end of file diff --git a/src/SB/Core/x/xMath2.cpp b/src/SB/Core/x/xMath2.cpp deleted file mode 100644 index 3c84bf3..0000000 --- a/src/SB/Core/x/xMath2.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "xMath2.h" - -const basic_rect basic_rect::m_Null = { 0.0f, 0.0f, 0.0f, 0.0f }; -const basic_rect basic_rect::m_Unit = { 0.0f, 0.0f, 1.0f, 1.0f }; \ No newline at end of file diff --git a/src/SB/Core/x/xMath3.cpp b/src/SB/Core/x/xMath3.cpp deleted file mode 100644 index a612628..0000000 --- a/src/SB/Core/x/xMath3.cpp +++ /dev/null @@ -1,766 +0,0 @@ -#include "xMath3.h" -#include "iMath3.h" - -#include -#include - -#include "iMath.h" -#include "xMath.h" // icos and isin -#include "xClimate.h" // xMat3x3Identity -#include "xMathInlines.h" // xasin, xatan2 -//#include "xVec3Inlines.h" // xVec3Init, imported, realized xClimate has a declaration as well though. - -const xVec3 g_O3 = { 0, 0, 0 }; -const xQuat g_IQ = { 0.0f, 0.0f, 0.0f, 1.0f }; - -S32 xPointInBox(const xBox* b, const xVec3* p) -{ - S32 ret = 0; - if ((p->x >=b->lower.x) && (p->x <= b->upper.x)) - { - if ((p->y>= b->lower.y) && (p->y <= b->upper.y)) - { - if ((p->z >= b->lower.z) && (p->z <= b->upper.z)) - { - ret = 1; - } - } - } - return (char)ret; -} - -void xMat4x3Copy(xMat4x3* o, const xMat4x3* m) -{ -} - -void xMat4x3Rot(xMat4x3* m, const xVec3* a, F32 t, const xVec3* p) -{ - xMat4x3 temp; - - xMat3x3RotC(m, a->x, a->y, a->z, t); - xVec3Copy(&m->pos, p); - xMat3x3Identity(&temp); - xVec3Inv(&temp.pos, p); - xMat4x3Mul(m, &temp, m); - -} - -/* xMat4x3Mul (xMat4x3 *, xMat4x3 const *, xMat4x3 const *) */ -void xMat4x3Mul(xMat4x3* o, const xMat4x3* a, const xMat4x3* b) -{ - xVec3 sp8; - - xMat4x3Toworld(&sp8, b, &a->pos); - xMat3x3Mul((xMat3x3*)o, (xMat3x3*)a, (xMat3x3*)b); - xVec3Copy(&o->pos, &sp8); -} - -/* xMat3x3Euler (xMat3x3 *, float, float, float) */ -void xMat3x3Euler(xMat3x3* m, F32 yaw, F32 pitch, F32 roll) -{ - F32 temp_f0; - F32 temp_f1; - F32 temp_f27; - F32 temp_f28; - F32 temp_f29; - F32 temp_f30; - F32 temp_f31; - F32 temp_f7; - - temp_f27 = isin(yaw); - temp_f28 = icos(yaw); - temp_f29 = isin(pitch); - temp_f30 = icos(pitch); - temp_f31 = isin(roll); - temp_f1 = icos(roll); - temp_f7 = temp_f27 * temp_f29; - temp_f0 = temp_f28 * temp_f29; - m->right.x = (temp_f28 * temp_f1) + (temp_f31 * temp_f7); - m->right.y = temp_f30 * temp_f31; - m->right.z = (-temp_f27 * temp_f1) + (temp_f31 * temp_f0); - m->up.x = (-temp_f28 * temp_f31) + (temp_f1 * temp_f7); - m->up.y = temp_f30 * temp_f1; - m->up.z = (temp_f27 * temp_f31) + (temp_f1 * temp_f0); - m->at.x = temp_f27 * temp_f30; - m->at.y = -temp_f29; - m->at.z = temp_f28 * temp_f30; - m->flags = 0; -} - -void xMat4x3Toworld(xVec3* o, const xMat4x3* m, const xVec3* v) -{ -} - -/* xMat3x3RotC (xMat3x3 *, float, float, float, float) */ -void xMat3x3RotC(xMat3x3* m, F32 _x, F32 _y, F32 _z, F32 t) -{ - F32 temp_f0; - F32 temp_f0_2; - F32 temp_f1; - F32 temp_f28; - F32 temp_f2; - F32 temp_f3; - F32 temp_f4; - F32 temp_f5; - F32 temp_f6; - F32 temp_f7; - F32 temp_f8; - - if (t == 0.0f) - { - xMat3x3Identity(m); - return; - } - temp_f28 = icos(t); - temp_f1 = isin(t); - temp_f5 = -temp_f1; - temp_f2 = 1.0f - temp_f28; - temp_f0 = temp_f2 * _x; - temp_f8 = temp_f2 * _z; - temp_f4 = temp_f2 * _y; - temp_f3 = _y * temp_f0; - temp_f6 = _x * temp_f8; - temp_f0_2 = (temp_f1 * _z) + temp_f3; - m->right.x = (_x * temp_f0) + temp_f28; - temp_f7 = _z * temp_f4; - m->right.y = temp_f0_2; - m->right.z = (temp_f5 * _y) + temp_f6; - m->up.x = (temp_f5 * _z) + temp_f3; - m->up.y = (_y * temp_f4) + temp_f28; - m->up.z = (temp_f1 * _x) + temp_f7; - m->at.x = (temp_f1 * _y) + temp_f6; - m->at.y = (temp_f5 * _x) + temp_f7; - m->at.z = (_z * temp_f8) + temp_f28; - m->flags = 0; -} - -void xMat3x3RotX(xMat3x3* m, F32 t) -{ - F32 cos = icos(t); - F32 sin = isin(t); - - xVec3Copy(&m->right, &g_X3); - xVec3Init(&m->up, 0.0f, cos, sin); - xVec3Init(&m->at, 0.0f, -sin, cos); - m->flags = 0; -} - -void xMat3x3RotY(xMat3x3* m, F32 t) -{ - F32 temp_f31; - F32 temp_f1; - - temp_f31 = icos(t); - temp_f1 = isin(t); - xVec3Init((xVec3*)m, temp_f31, 0.0f, -temp_f1); - xVec3Copy(&m->up, &g_Y3); - xVec3Init(&m->at, temp_f1, 0.0f, temp_f31); - m->flags = 0; -} - -void xMat3x3RotZ(xMat3x3* m, F32 t) -{ - F32 cos = icos(t); - F32 sin = isin(t); - - xVec3Init(&m->right, cos, sin, 0.0f); - xVec3Init(&m->up, -sin, cos, 0.0f); - xVec3Copy(&m->at, &g_Z3); - m->flags = 0; -} - -void xMat3x3MulRotC(xMat3x3* o, xMat3x3* m, F32 _x, F32 _y, F32 _z, F32 t) -{ -} - -void xMat4x3Identity(xMat4x3* m) -{ -} - -/* xMat3x3Normalize (xMat3x3 *, xMat3x3 const *) */ -void xMat3x3Normalize(xMat3x3* o, const xMat3x3* m) -{ - xVec3Normalize((xVec3*)o, (xVec3*)m); - xVec3Normalize(&o->up, &m->up); - xVec3Normalize(&o->at, &m->at); -} - -void xMat4x3Tolocal(xVec3* o, const xMat4x3* m, const xVec3* v) -{ -} - -/* xMat3x3Tolocal (xVec3 *, xMat3x3 const *, xVec3 const *) */ -void xMat3x3Tolocal(xVec3* o, const xMat3x3* m, const xVec3* v) -{ - F32 temp_f0; - F32 temp_f0_2; - F32 temp_f1; - F32 temp_f1_2; - F32 temp_f29; - F32 temp_f2; - F32 temp_f30; - F32 temp_f31; - F32 temp_f6; - F32 temp_f7; - F32 temp_f8; - F32 temp_f8_2; - - temp_f1 = m->right.x; - temp_f0 = m->right.y; - temp_f2 = m->up.x; - temp_f1_2 = m->up.y; - temp_f8 = m->at.x; - temp_f0_2 = m->at.y; - temp_f6 = m->right.z; - temp_f7 = m->up.z; - temp_f8_2 = m->at.z; - temp_f31 = (temp_f6 * temp_f6) + ((temp_f1 * temp_f1) + (temp_f0 * temp_f0)); - temp_f30 = (temp_f7 * temp_f7) + ((temp_f2 * temp_f2) + (temp_f1_2 * temp_f1_2)); - temp_f29 = (temp_f8_2 * temp_f8_2) + ((temp_f8 * temp_f8) + (temp_f0_2 * temp_f0_2)); - xMat3x3LMulVec(o, m, v); - o->x /= temp_f31; - o->y /= temp_f30; - o->z /= temp_f29; -} - -/* xMat4x3MoveLocalRight (xMat4x3 *, float) */ -void xMat4x3MoveLocalRight(xMat4x3* m, F32 mag) -{ - m->pos.x += m->right.x * mag; - m->pos.y += m->right.y * mag; - m->pos.z += m->right.z * mag; -} - -/* xMat4x3MoveLocalAt (xMat4x3 *, float) */ -void xMat4x3MoveLocalAt(xMat4x3* m, F32 mag) -{ - m->pos.x += m->at.x * mag; - m->pos.y += m->at.y * mag; - m->pos.z += m->at.z * mag; -} - -/* xMat4x3MoveLocalUp (xMat4x3 *, float) */ -void xMat4x3MoveLocalUp(xMat4x3* m, F32 mag) -{ - m->pos.x += m->up.x * mag; - m->pos.y += m->up.y * mag; - m->pos.z += m->up.z * mag; -} - -/* xMat3x3GetEuler (xMat3x3 const *, xVec3 *) */ -void xMat3x3GetEuler(const xMat3x3* m, xVec3* a) -{ - F32 yaw = -xasin(m->at.y); - - F32 roll; - F32 pitch; - - if (yaw < (PI / 2)) - { - if (yaw > -(PI / 2)) - { - pitch = xatan2(m->at.x, m->at.z); - roll = xatan2(m->right.y, m->up.y); - } - else - { - pitch = -xatan2(-m->up.x, m->right.x); - roll = 0.0f; - } - } - else - { - pitch = xatan2(-m->up.x, m->right.x); - roll = 0.0f; - } - - a->x = pitch; - a->y = yaw; - a->z = roll; -} - -/* xMat3x3Euler (xMat3x3 *, xVec3 const *) */ -void xMat3x3Euler(xMat3x3* m, const xVec3* ypr) -{ - xMat3x3Euler(m, ypr->x, ypr->y, ypr->z); -} - -/* xQuatToMat (xQuat const *, xMat3x3 *) */ -void xQuatToMat(const xQuat* q, xMat3x3* m) -{ - F32 tx = (2.0f * q->v.x); - F32 ty = (2.0f * q->v.y); - F32 tz = (2.0f * q->v.z); - F32 tsx = tx * q->s; - F32 tsy = ty * q->s; - F32 tsz = tz * q->s; - F32 txx = tx * q->v.x; - F32 txy = ty * q->v.x; - F32 txz = tz * q->v.x; - F32 tyy = ty * q->v.y; - F32 tyz = tz * q->v.y; - F32 tzz = tz * q->v.z; - - m->right.x = (1.0f - tyy) - tzz; - m->right.y = txy - tsz; - m->right.z = txz + tsy; - - m->up.x = txy + tsz; - m->up.y = (1.0f - tzz) - txx; - m->up.z = tyz - tsx; - - m->at.x = txz - tsy; - m->at.y = tyz + tsx; - m->at.z = (1.0f - txx) - tyy; - - m->flags = 0; -} - -/* xQuatDiff (xQuat *, xQuat const *, xQuat const *) */ -void xQuatDiff(xQuat* o, const xQuat* a, const xQuat* b) -{ - xQuatConj(o, a); - xQuatMul(o, o, b); - if (o->s < 0.0f) - { - xQuatFlip(o, o); - } -} - -F32 xQuatGetAngle(const xQuat* q) -{ - F32 angle; - angle = 5.0; - return angle; -} - -/* xQuatFromMat (xQuat *, xMat3x3 const *) */ -void xQuatFromMat(xQuat* q, const xMat3x3* m) -{ - static S32 nxt[3] = { 1, 2, 0 }; - - F32 temp_f1; - F32 temp_f1_2; - F32 temp_f1_3; - F32 temp_f5; - F32 temp_f6; - S32 temp_r25; - F32 temp_r28; - F32 temp_r30; - F32 temp_r31; - F32 temp_r8; - S32 var_r29; - - temp_f1 = m->at.z + (m->right.x + m->up.y); - if (temp_f1 > 0.0f) - { - temp_f1_2 = xsqrt(1.0f + temp_f1); - q->s = 0.5f * temp_f1_2; - temp_f5 = 0.5f / temp_f1_2; - q->v.x = temp_f5 * (m->at.y - m->up.z); - q->v.y = temp_f5 * (m->right.z - m->at.x); - q->v.z = temp_f5 * (m->up.x - m->right.y); - return; - } - var_r29 = 0; - if (m->up.y > m->right.x) - { - var_r29 = 1; - } - // if (m->at.z > F32 (*(m + (var_r29 * 0x14)))) { - // var_r29 = 2; - // } - // temp_r31 = var_r29 * 4; - // temp_r25 = nxt[var_r29]; - // temp_r30 = temp_r25 * 4; - // temp_r28 = nxt[temp_r25]; - // temp_f1_3 = xsqrt(1.0f + ((*(m + (var_r29 * 0x14)) - *(m + (temp_r25 * 0x14))) - *(m + (temp_r28 * 0x14)))); - // if ((F32) fabs(temp_f1_3) < 0.00001f) { - // xQuatCopy(q, &g_IQ); - // return; - // } - // temp_r8 = temp_r28 * 4; - // *(q + temp_r31) = 0.5f * temp_f1_3; - // temp_f6 = 0.5f / temp_f1_3; - // q->unkC = temp_f6 * (*(m + ((temp_r25 + temp_r8) * 4)) - *(m + ((temp_r28 + temp_r30) * 4))); - // *(q + temp_r30) = temp_f6 * (*(m + ((var_r29 + temp_r30) * 4)) + *(m + ((temp_r25 + temp_r31) * 4))); - // *(q + temp_r8) = temp_f6 * (*(m + ((var_r29 + temp_r8) * 4)) + *(m + ((temp_r28 + temp_r31) * 4))); - // if (q->unkC < 0.0f) { - // xQuatFlip(q, q); - // } -} - -void xQuatFromAxisAngle(xQuat* q, const xVec3* a, F32 t) -{ - F32 t_2; - - if (t == 0.0f) - { - xQuatCopy(q, &g_IQ); - } - else - { - t_2 = isin(t * 0.5f); - q->s = icos((t * 0.5f)); - xVec3SMul(&q->v, a, t_2); - } -} - -void xQuatToAxisAngle(const xQuat* q, xVec3* a, F32* t) -{ - *t = 2.0f * xacos(q->s); - xVec3Normalize(a, &q->v); -} - -/* xQuatSlerp (xQuat *, xQuat const *, xQuat const *, float) */ -void xQuatSlerp(xQuat* q, const xQuat* a, const xQuat* b, F32 t) -{ - xQuat sp28; - xQuat sp18; - F32 sp14; - F32 sp10; - F32 spC; - F32 sp8; - F32 temp_f0; - F32 temp_f1; - F32 temp_f28; - F32 temp_f2; - F32 temp_f3; - F32 temp_f4; - F32 var_f1; - F32 var_f29; - F32 var_f30; - const xQuat* var_r31; - - var_r31 = b; - var_f1 = xQuatDot(a, var_r31); - if (var_f1 < 0.0f) - { - var_f1 = -var_f1; - temp_f4 = -var_r31->v.x; - temp_f0 = var_r31->s; - temp_f3 = -var_r31->v.y; - temp_f2 = -var_r31->v.z; - var_r31 = (xQuat*)&sp8; - sp8 = temp_f4; - spC = temp_f3; - sp10 = temp_f2; - sp14 = -temp_f0; - } - //M2C_ERROR(/* unknown instruction: cror eq, gt, eq */); - if (var_f1 == 0.999f) - { - var_f30 = t; - var_f29 = 1.0f - t; - } - else - { - temp_f1 = xacos(var_f1); - temp_f28 = 1.0f / isin(temp_f1); - var_f29 = temp_f28 * isin((1.0f - t) * temp_f1); - var_f30 = temp_f28 * isin(t * temp_f1); - } - xQuatSMul(&sp28, a, var_f29); - xQuatSMul(&sp18, var_r31, var_f30); - xQuatAdd(q, &sp28, &sp18); - xQuatNormalize(q, q); -} - -/* xQuatMul (xQuat *, xQuat const *, xQuat const *) */ -void xQuatMul(xQuat* o, const xQuat* a, const xQuat* b) -{ - F32 temp_f10; - F32 temp_f11; - F32 temp_f4; - F32 temp_f5; - F32 temp_f6; - F32 temp_f7; - F32 temp_f8; - F32 temp_f9; - - temp_f4 = b->s; - temp_f11 = a->v.x; - temp_f5 = a->v.y; - temp_f8 = b->v.x; - temp_f7 = a->s; - temp_f9 = a->v.z; - temp_f6 = b->v.y; - temp_f10 = b->v.z; - o->v.x = -((temp_f9 * temp_f6) - - ((temp_f5 * temp_f10) + ((temp_f7 * temp_f8) + (temp_f11 * temp_f4)))); - o->v.y = -((temp_f11 * temp_f10) - - ((temp_f9 * temp_f8) + ((temp_f7 * temp_f6) + (temp_f5 * temp_f4)))); - o->v.z = -((temp_f5 * temp_f8) - - ((temp_f11 * temp_f6) + ((temp_f7 * temp_f10) + (temp_f9 * temp_f4)))); - o->s = -((temp_f9 * temp_f10) - - -((temp_f5 * temp_f6) - ((temp_f7 * temp_f4) - (temp_f11 * temp_f8)))); - xQuatNormalize(o, o); -} - -void xQuatConj(xQuat* o, const xQuat* q) -{ -} - -/* xQuatSMul (xQuat *, xQuat const *, float) */ -void xQuatSMul(xQuat* q, const xQuat* a, F32 t) -{ - q->s = a->s * t; - xVec3SMul((xVec3*)q, (xVec3*)a, t); -} - -/* xQuatAdd (xQuat *, xQuat const *, xQuat const *) */ -void xQuatAdd(xQuat* q, const xQuat* a, const xQuat* b) -{ - q->s = a->s + b->s; - xVec3Add((xVec3*)q, (xVec3*)a, (xVec3*)b); -} - -void xMat3x3LookAt(xMat3x3* m, const xVec3* pos, const xVec3* at) -{ -} - -/* xMat3x3LookVec (xMat3x3 *, xVec3 const *) */ -F32 xMat3x3LookVec(xMat3x3* m, const xVec3* at) -{ - F32 temp_f2; - F32 temp_f31; - xVec3* temp_r3; - - temp_f31 = xVec3Normalize(&m->at, at); - temp_r3 = &m->at; - xVec3Inv(temp_r3, temp_r3); - if ((F32)__fabs(1.0f - m->at.y) < 0.00001f) - { - m->right.x = 1.0f; - m->right.y = 0.0f; - m->right.z = 0.0f; - m->up.x = 0.0f; - m->up.y = 0.0f; - m->up.z = 1.0f; - m->at.x = 0.0f; - m->at.y = -1.0f; - m->at.z = 0.0f; - return temp_f31; - } - if ((F32)__fabs(1.0f + m->at.y) < 0.00001f) - { - m->right.x = -1.0f; - m->right.y = 0.0f; - m->right.z = 0.0f; - m->up.x = 0.0f; - m->up.y = 0.0f; - m->up.z = -1.0f; - m->at.x = 0.0f; - m->at.y = 1.0f; - m->at.z = 0.0f; - return temp_f31; - } - if (((F32)__fabs(at->z) < 0.00001f) && ((F32)__fabs(at->x) < 0.00001f)) - { - m->right.x = 1.0f; - m->right.y = 0.0f; - m->right.z = 0.0f; - m->up.x = 0.0f; - m->up.y = 1.0f; - m->up.z = 0.0f; - m->at.x = 0.0f; - m->at.y = 0.0f; - m->at.z = 1.0f; - return 0.0f; - } - m->right.x = m->at.z; - m->right.y = 0.0f; - m->right.z = -m->at.x; - xVec3Normalize((xVec3*)m, (xVec3*)m); - xVec3Cross(&m->up, &m->at, (xVec3*)m); - xVec3Cross((xVec3*)m, &m->up, &m->at); - m->flags = 0; - return temp_f31; -} - -void xBoxInitBoundOBB(xBox* o, const xBox* b, const xMat4x3* m) -{ -} - -void xMat3x3Scale(xMat3x3* m, const xVec3* s) -{ -} - -/* xMat3x3ScaleC (xMat3x3 *, float, float, float) */ -void xMat3x3ScaleC(xMat3x3* m, F32 x, F32 y, F32 z) -{ - xVec3Init((xVec3*)m, x, 0.0f, 0.0f); - xVec3Init(&m->up, 0.0f, y, 0.0f); - xVec3Init(&m->at, 0.0f, 0.0f, z); - m->flags = 0; -} - -void xMat3x3RMulRotY(xMat3x3* o, const xMat3x3* m, F32 t) -{ - F32 cos = icos(t); - F32 sin = isin(t); - if (o == m) - { - F32 temp = o->right.z; - o->right.z = ((cos * o->right.z) - (sin * o->right.x)); - o->right.x = ((cos * o->right.x) + (sin * temp)); - - temp = o->up.z; - o->up.z = ((cos * temp) - (sin * o->up.x)); - o->up.x = ((cos * o->up.x) + (sin * temp)); - - temp = o->at.z; - o->at.z = ((cos * temp) - (sin * o->at.x)); - o->at.x = ((cos * o->at.x) + (sin * temp)); - } - else - { - o->right.x = (cos * m->right.x + (sin * m->right.z)); - o->right.y = m->right.y; - o->right.z = (cos * m->right.z - (sin * m->right.x)); - - o->up.x = (cos * m->up.x + (sin * m->up.z)); - o->up.y = m->up.y; - o->up.z = (cos * m->up.z - (sin * m->up.x)); - - o->at.x = (cos * m->at.x + (sin * m->at.z)); - o->at.y = m->at.y; - o->at.z = (cos * m->at.z - (sin * m->at.x)); - - o->flags = 0; - } -} - -void xMat3x3Transpose(xMat3x3* o, const xMat3x3* m) -{ - F32 temp; - - if (o == m) - { - temp = o->right.y; - o->right.y = o->up.x; - o->up.x = temp; - - temp = o->right.z; - o->right.z = o->at.x; - o->at.x = temp; - - temp = o->up.z; - o->up.z = o->at.y; - o->at.y = temp; - - return; - } - - o->right.x = m->right.x; - o->right.y = m->up.x; - o->right.z = m->at.x; - - o->up.x = m->right.y; - o->up.y = m->up.y; - o->up.z = m->at.y; - - o->at.x = m->right.z; - o->at.y = m->up.z; - o->at.z = m->at.z; - - o->flags = 0; -} - -/* xMat3x3Mul (xMat3x3 *, xMat3x3 const *, xMat3x3 const *) */ -void xMat3x3Mul(xMat3x3* o, const xMat3x3* a, const xMat3x3* b) -{ - xMat3x3 sp8; - F32 temp_f0; - F32 temp_f0_2; - F32 temp_f10; - F32 temp_f10_2; - F32 temp_f12; - F32 temp_f13; - F32 temp_f1; - F32 temp_f25; - F32 temp_f26; - F32 temp_f27; - F32 temp_f29; - F32 temp_f2; - F32 temp_f30; - F32 temp_f3; - F32 temp_f4; - F32 temp_f4_2; - F32 temp_f5; - F32 temp_f9; - U8 var_r0; - xMat3x3* var_r6; - - var_r0 = 0; - if ((o == a) || (o == b)) - { - var_r0 = 1; - } - if (var_r0 != 0) - { - var_r6 = &sp8; - } - else - { - var_r6 = o; - } - temp_f4 = a->right.y; - temp_f3 = b->up.x; - temp_f2 = b->up.y; - temp_f1 = a->up.y; - temp_f10 = b->up.z; - temp_f0 = a->at.y; - temp_f26 = a->right.x; - temp_f27 = b->right.x; - temp_f30 = b->right.y; - temp_f9 = a->up.x; - temp_f12 = b->right.z; - temp_f4_2 = a->at.x; - temp_f25 = a->right.z; - temp_f0_2 = b->at.x; - temp_f29 = b->at.y; - temp_f13 = b->at.z; - temp_f10_2 = a->up.z; - temp_f5 = a->at.z; - var_r6->right.x = (temp_f25 * temp_f0_2) + ((temp_f26 * temp_f27) + (temp_f4 * temp_f3)); - var_r6->flags = 0; - var_r6->right.y = (temp_f25 * temp_f29) + ((temp_f26 * temp_f30) + (temp_f4 * temp_f2)); - var_r6->right.z = (temp_f25 * temp_f13) + ((temp_f26 * temp_f12) + (temp_f4 * temp_f10)); - var_r6->up.x = (temp_f10_2 * temp_f0_2) + ((temp_f9 * temp_f27) + (temp_f1 * temp_f3)); - var_r6->up.y = (temp_f10_2 * temp_f29) + ((temp_f9 * temp_f30) + (temp_f1 * temp_f2)); - var_r6->up.z = (temp_f10_2 * temp_f13) + ((temp_f9 * temp_f12) + (temp_f1 * temp_f10)); - var_r6->at.x = (temp_f5 * temp_f0_2) + ((temp_f4_2 * temp_f27) + (temp_f0 * temp_f3)); - var_r6->at.y = (temp_f5 * temp_f29) + ((temp_f4_2 * temp_f30) + (temp_f0 * temp_f2)); - var_r6->at.z = (temp_f5 * temp_f13) + ((temp_f4_2 * temp_f12) + (temp_f0 * temp_f10)); - // if (var_r0 != 0) { - // xMat3x3Copy__FP7xMat3x3PC7xMat3x3(o, var_r6); - // } -} - -void xMat3x3SMul(xMat3x3*, const xMat3x3*, F32) -{ -} - -void xBoxFromLine(xBox& box, const xLine3& line) -{ -} - -void xBoxFromRay(xBox& box, const xRay3& ray) -{ -} - -void xBoxUnion(xBox& a, const xBox& b, const xBox& c) -{ - a.upper.x = MAX(b.upper.x, c.upper.x); - a.upper.y = MAX(b.upper.y, c.upper.y); - a.upper.z = MAX(b.upper.z, c.upper.z); - - a.lower.x = MIN(b.lower.x, c.lower.x); - a.lower.y = MIN(b.lower.y, c.lower.y); - a.lower.z = MIN(b.lower.z, c.lower.z); -} - -void xMat3x3LMulVec(xVec3* o, const xMat3x3* m, const xVec3* v) -{ -} diff --git a/src/SB/Core/x/xMemMgr.cpp b/src/SB/Core/x/xMemMgr.cpp deleted file mode 100644 index f9cae4e..0000000 --- a/src/SB/Core/x/xMemMgr.cpp +++ /dev/null @@ -1,395 +0,0 @@ -#include "xMemMgr.h" - -#include -#include -#include - -#include "iSystem.h" -#include "iMemMgr.h" - -extern xMemInfo_tag gMemInfo; -extern xMemHeap_tag gxHeap[3]; -extern void (*sMemBaseNotifyFunc)(); - -void xMemDebug_SoakLog(const char*) -{ -} - -// The instructions putting 0/1/2 into registers happen in the wrong order. -void xMemInit() -{ - iMemInit(); - xMemInitHeap(&gxHeap[0], gMemInfo.DRAM.addr, gMemInfo.DRAM.size, 0x8826); - xMemInitHeap(&gxHeap[1], gMemInfo.DRAM.addr + gMemInfo.DRAM.size, gMemInfo.DRAM.size, 0x8925); - xMemInitHeap(&gxHeap[2], gMemInfo.DRAM.addr + gMemInfo.DRAM.size, gMemInfo.DRAM.size, 0x892A); - gxHeap[0].opp_heap[0] = 1; - gxHeap[0].opp_heap[1] = 2; - gxHeap[1].opp_heap[0] = 0; - gxHeap[1].opp_heap[1] = 2; - gxHeap[2].opp_heap[0] = 0; - gxHeap[2].opp_heap[1] = 1; - gActiveHeap = 0; -} - -void xMemExit() -{ - iMemExit(); -} - -void xMemInitHeap(xMemHeap_tag* heap, U32 base, U32 size, U32 flags) -{ - U32 old_base = base; - S32 align = 1 << ((flags >> 9) & 0x1F); - if (flags & 0x100) - { - base = base & -align; - size -= (old_base - base); - } - else - { - base = (old_base + align - 1) & -align; - size -= (base - old_base); - } - - heap->state_idx = 0; - heap->hard_base = base; - heap->size = size; - heap->flags = flags; - heap->lastblk = NULL; - xHeapState_tag* sp = &heap->state[heap->state_idx]; - sp->curr = base; - sp->blk_ct = 0; - - if (flags & 0x10000) - { - heap->max_blks = (1 << ((flags >> 14) & 0x1)); - heap->blk = (xMemBlock_tag*)malloc(heap->max_blks * sizeof(xMemBlock_tag)); - memset(heap->blk, 0, heap->max_blks * sizeof(xMemBlock_tag)); - } - else - { - heap->max_blks = -1; - heap->blk = 0; - } - heap->opp_heap[0] = -1; - heap->opp_heap[1] = -1; -} - -#if 0 -// Not particularly close. This function is a nightmare, it has so many -// variables to untangle. -void xMemGetBlockInfo(xMemHeap_tag* heap, U32 size, S32 align, xMemBlkInfo_tag* info) -{ - S32 hdr = 1; - xHeapState_tag* sp = &heap->state[heap->state_idx]; - if (heap->flags & 0x100) - { - hdr = -1; - } - - S32 remainder = 0xc & -(heap->flags & 0x10000); - S32 pre; - S32 post; - S32 block; - S32 r8; - if (heap->flags & 0x100) - { - block = -remainder; - pre = -(remainder + size + ((sp->curr - remainder - size) & (align - 1))); - post = pre + size; - r8 = -pre; - } - else - { - block = 0; - if (r8 = (align - 1) & (sp->curr + remainder)) - { - r8 = align; - } - pre = (align + remainder) - r8; - post = pre + size; - r8 = post; - } - - S32 total = (r8 + 3) & 0xFFFFFFFE; - if (heap->flags & 0x10000) - { - info->header = &heap->blk[sp->curr]; - } - else - { - info->header = (xMemBlock_tag*)(sp->curr + block); - } - info->pre = sp->curr + pre; - info->block = sp->curr + pre; - info->post = sp->curr + post; - info->curr = sp->curr + hdr * total; - info->waste = total - (remainder + size); - info->total = total; -} -#endif - -#if 0 -// Not particularly close. Not 100% confident that I understand what's going on, -// in particular the bit that goes: -// (heap->lastblk->size + size) - heap->lastblk->size; -// It really seems like the assembly code is adding and then immediately -// subtracting again, and I don't see why it would want to do that. -#undef xMemGrowAlloc -void* xMemGrowAlloc(U32 heapID, U32 size) -{ - size = (size + 3) & 0xFFFFFFFC; - xMemHeap_tag* heap = &gxHeap[heapID]; - xHeapState_tag* sp = &heap->state[heap->state_idx]; - // pad size to multiple of 4 bytes - xMemBlock_tag* hdr = heap->lastblk; - U32 anotherVar = (heap->lastblk->size + size) - heap->lastblk->size; - if (sp->used + anotherVar > heap->size) - { - return 0; - } - else - { - void* memptr; - if (heap->flags & 0x100) - { - memptr = (void*)(hdr->addr - size); - hdr->addr = (U32)memptr; - sp->curr -= anotherVar; - } - else - { - sp->curr += anotherVar; - memptr = (void*)(hdr->addr + heap->lastblk->size); - } - sp->used += anotherVar; - hdr->size += size; - memset(memptr, 0, size); - return memptr; - } -} -#endif - -// -void* xMemAlloc(U32 heapID, U32 size, S32 align) -{ - // This variable not in DWARF - S32 true_align; - - xMemHeap_tag* heap; - xMemBlock_tag* hdr; - xHeapState_tag* sp; - - heap = &gxHeap[heapID]; - sp = &heap->state[heap->state_idx]; - - true_align = 1 << (heap->flags >> 9 & 0x1f); - if (align > true_align) - { - true_align = align; - } - - if (size == 0) - { - return (void*)0xDEADBEEF; - } - - xMemBlkInfo_tag info; - U32 total = xMemGetBlockInfo(heap, size, true_align, &info); - hdr = info.header; - - if (sp->used + total > heap->size) - { - return NULL; - } - - sp->curr = info.curr; - sp->blk_ct += 1; - if (heap->flags & 0x10000) - { - return NULL; - } - - hdr->addr = info.block; - hdr->size = size; - hdr->align = true_align; - sp->used += total; - sp->wasted += info.waste; - - memset((void*)hdr->addr, 0, size); - heap->lastblk = hdr; - return (void*)hdr->addr; -} - -void* xMemPushTemp(U32 size) -{ - return RwMalloc(size); -} - -void xMemPopTemp(void* memory) -{ - RwFree(memory); -} - -S32 xMemPushBase(U32 heapID) -{ - xMemHeap_tag* heap = &gxHeap[heapID]; - - heap->state_idx += 1; - xHeapState_tag* sp = &heap->state[heap->state_idx]; - *sp = *(sp - 1); - - if (sMemBaseNotifyFunc != NULL) - { - sMemBaseNotifyFunc(); - } - return heap->state_idx - 1; -} - -S32 xMemPushBase() -{ - return xMemPushBase(gActiveHeap); -} - -// Load/Store swap of sMemBaseNotifyFunc and state_idx -S32 xMemPopBase(U32 heapID, S32 depth) -{ - xMemHeap_tag* heap = &gxHeap[heapID]; - if (depth < 0) - { - depth = heap->state_idx + depth; - } - - heap->state_idx = depth; - if (sMemBaseNotifyFunc != NULL) - { - sMemBaseNotifyFunc(); - } - - return heap->state_idx; -} - -S32 xMemPopBase(S32 depth) -{ - return xMemPopBase(gActiveHeap, depth); -} - -S32 xMemGetBase(U32 heapID) -{ - return gxHeap[heapID].state_idx; -} - -void xMemRegisterBaseNotifyFunc(void (*func)()) -{ - sMemBaseNotifyFunc = func; -} - -S32 xMemGetBase() -{ - return xMemGetBase(gActiveHeap); -} - -void xMemPoolAddElements(xMemPool* pool, void* buffer, U32 count) -{ - S32 i; - void* curr; - void (*initCB)(xMemPool*, void*); - U32 next; - U32 size; - - initCB = pool->InitCB; - next = pool->NextOffset; - size = pool->Size; - - curr = buffer; - for (i = 0; i < (S32)count - 1; i++) - { - *(void**)((U32)curr + next) = (void*)((U32)curr + size); - if (initCB != NULL) - { - initCB(pool, curr); - } - curr = (void*)((U32)curr + size); - } - - *(void**)((U32)curr + next) = pool->FreeList; - if (initCB != NULL) - { - initCB(pool, curr); - } - pool->FreeList = buffer; - pool->Total += count; -} - -void xMemPoolSetup(xMemPool* pool, void* buffer, U32 nextOffset, U32 flags, xMemPoolInitCB initCB, - U32 size, U32 count, U32 numRealloc) -{ - pool->FreeList = NULL; - pool->NextOffset = nextOffset; - pool->Flags = flags; - pool->UsedList = NULL; - pool->InitCB = initCB; - pool->Buffer = buffer; - pool->Size = size; - pool->NumRealloc = numRealloc; - pool->Total = 0; - xMemPoolAddElements(pool, buffer, count); -} - -void* xMemPoolAlloc(xMemPool* pool) -{ - void* retval = pool->FreeList; - U32 next = pool->NextOffset; - U32 flags = pool->Flags; - - if (retval == NULL) - { - xMemPoolAddElements(pool, xMemAlloc(gActiveHeap, pool->NumRealloc * pool->Size, 0), - pool->NumRealloc); - retval = pool->FreeList; - } - - pool->FreeList = *(void**)((U32)retval + next); - if (flags & 1) - { - *(void**)((U32)retval + next) = pool->UsedList; - pool->UsedList = retval; - } - - return retval; -} - -void xMemPoolFree(xMemPool* pool, void* data) -{ - void** prev; - void* freeList; - U32 next; - void* curr; - - if (data == NULL) - { - return; - } - - freeList = pool->FreeList; - next = pool->NextOffset; - if (pool->Flags & 1) - { - prev = &pool->UsedList; - curr = pool->UsedList; - - while (curr != NULL && curr != data) - { - prev = (void**)((U32)curr + next); - curr = *prev; - } - - if (curr != NULL) - { - *prev = *(void**)((U32)curr + next); - } - } - - *(void**)((U32)data + next) = freeList; - pool->FreeList = data; -} diff --git a/src/SB/Core/x/xModel.cpp b/src/SB/Core/x/xModel.cpp deleted file mode 100644 index 4991a48..0000000 --- a/src/SB/Core/x/xModel.cpp +++ /dev/null @@ -1,229 +0,0 @@ -#include "iModel.h" -#include "xModel.h" - -#include - -static xModelPool* sxModelPoolList; -static RwCamera* subcamera; -S32 xModelBucketEnabled; - -static RwCamera* CameraCreate(int a, int b, int c); -void CameraDestroy(RwCamera* cam); - -U32 xModelGetPipeFlags(RpAtomic* model) -{ - for (int i = 0; i < xModelLookupCount; i++) - { - if (xModelLookupList[i].model == model) - { - return xModelLookupList[i].PipeFlags; - } - } - return NULL; -} - -// Equivalent (regalloc) -void xModelInit() -{ - iModelInit(); - sxModelPoolList = NULL; - if (subcamera == NULL) - { - subcamera = CameraCreate(0,0,1); - } - xModelPipeNumTables = 0; -} - -static xModelInstance* FindChild(xModelInstance* model) -{ - xModelInstance* child = model->Next; - while (child != NULL) - { - if (child->Parent == model) - { - return child; - } - child = child->Next; - } - return NULL; -} - -void xModelInstanceFree(xModelInstance* model) -{ - xModelInstance* prev; - xModelInstance* curr; - - while (prev = FindChild(model), prev != NULL) - { - xModelInstanceFree(prev); - } - prev = model->Parent; - if (prev != NULL) - { - for (curr = prev->Next; (curr != NULL) && (curr != model); curr = curr->Next) - { - prev = curr; - } - prev->Next = curr->Next; - } - if (model->Anim != NULL) - { - xAnimPoolFree(model->Anim); - model->Anim = NULL; - } - if (model->Pool != NULL) - { - model->Next = model->Pool->List; - model->Pool->List = model; - } -} - -void xModelInstanceAttach(xModelInstance* inst, xModelInstance* parent) -{ - xModelInstance* curr = parent; - while (curr->Next != NULL) - { - curr = curr->Next; - } - curr->Next = inst; - inst->Parent = parent; - if ((inst->Flags & 0x2000) != 0) - { - inst->Mat = parent->Mat; - } -} - -void xModelUpdate(xModelInstance* modelInst, F32 timeDelta) -{ - for (; modelInst != NULL; modelInst = modelInst->Next) - { - if (modelInst->Anim != NULL) - { - if ((modelInst->Flags & 4) != 0) - { - if ((modelInst->Flags & 0x100) != 0) - { - xAnimPlayChooseTransition(modelInst->Anim); - } - xAnimPlayUpdate(modelInst->Anim, timeDelta); - } - } - } -} - -void xModelEvalSingle(xModelInstance* model); - -void xModelEval(xModelInstance* model) -{ - while (model != NULL) - { - xModelEvalSingle(model); - model = model->Next; - } -} - -void xModelRender(xModelInstance* model) -{ - while (model != NULL) - { - if (xModelBucketEnabled) - { - xModelBucket_Add(model); - } - else - { - xModelRenderSingle(model); - } - model = model->Next; - } -} - -static RwCamera* CameraCreate(int a, int b, int c) -{ - RwCamera* camera = RwCameraCreate(); - if (camera != NULL) - { - _rwObjectHasFrameSetFrame(camera, RwFrameCreate()); - camera->frameBuffer = RwRasterCreate(a, b, 0, 2); - if (c != 0) - { - camera->zBuffer = RwRasterCreate(a, b, 0, 1); - } - if (camera->object.object.parent != NULL) - { - if (camera->frameBuffer != NULL) - { - if ((c == 0) || (camera->zBuffer != NULL)) - { - return camera; - } - } - } - } - CameraDestroy(camera); - return NULL; -} - -void CameraDestroy(RwCamera* cam) -{ - RwFrame* frame; - if (cam != NULL) - { - _rwFrameSyncDirty(); - frame = (RwFrame*)cam->object.object.parent; - if (frame != NULL) - { - _rwObjectHasFrameSetFrame(cam, 0); - RwFrameDestroy(frame); - } - if (cam->frameBuffer != NULL) - { - RwRasterDestroy(cam->frameBuffer); - cam->frameBuffer = NULL; - } - if (cam->zBuffer != NULL) - { - RwRasterDestroy(cam->zBuffer); - cam->zBuffer = NULL; - } - RwCameraDestroy(cam); - } -} - -void xModelSetMaterialAlpha(xModelInstance* model, U8 alpha) -{ - iModelSetMaterialAlpha(model->Data, alpha); -} - -void xModelMaterialMul(xModelInstance* model, F32 rm, F32 gm, F32 bm) -{ - iModelMaterialMul(model->Data, rm, gm, bm); -} - -void xModelResetMaterial(xModelInstance* model) -{ - iModelResetMaterial(model->Data); -} - -void xModel_SceneEnter(RpWorld* world) -{ - RpWorldAddCamera(world, subcamera); -} - -void xModel_SceneExit(RpWorld* world) -{ - RpWorldRemoveCamera(world, subcamera); -} - -void xModelAnimCollStart(xModelInstance& model) -{ - model.Flags = (model.Flags & ~0x1000) | 0x800; - if (model.anim_coll.verts == NULL) - { - U32 size = iModelVertCount(model.Data); - if (size != 0) - { - model.anim_coll.verts = (xVec3*)xMemAlloc(gActiveHeap, size * sizeof(xVec3), 0); - } - } -} \ No newline at end of file diff --git a/src/SB/Core/x/xModelBucket.cpp b/src/SB/Core/x/xModelBucket.cpp deleted file mode 100644 index 790ebfd..0000000 --- a/src/SB/Core/x/xModelBucket.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "xModelBucket.h" - -#include "iCamera.h" - -#include -#include - -extern RpWorld* sBucketDummyWorld; -extern RwCamera* sBucketDummyCamera; -extern S32 xModelBucketEnabled; -extern S32 sBucketCurr; -extern S32 sBucketCount; -extern xModelBucket* sBucketList; -extern S32 sBucketClipCullCurr; -extern S32 sBucketClipCullCount; -extern xModelBucket** sBucketClipCullList; -extern S32 sAlphaCurr; -extern S32 sAlphaStart; -extern S32 sAlphaCount; -extern xModelAlphaBucket* sAlphaList; -extern F32 xModelBucket_f675; // 100000.0f -extern F32 xModelBucket_f676; // -100000.0f - -S32 CmpAlphaBucket(const void* _a, const void* _b) -{ - xModelAlphaBucket* a = (xModelAlphaBucket*)_a; - xModelAlphaBucket* b = (xModelAlphaBucket*)_b; - if (a->Layer > b->Layer) - { - return 1; - } - if (a->Layer < b->Layer) - { - return -1; - } - if (a->SortValue < b->SortValue) - { - return 1; - } - if (a->SortValue > b->SortValue) - { - return -1; - } - return 0; -} - -void xModelBucket_PreCountReset() -{ - sBucketCurr = 0; - sBucketCount = 0; - sBucketList = NULL; - sBucketClipCullCurr = 0; - sBucketClipCullCount = 0; - sBucketClipCullList = NULL; - sAlphaCurr = 0; - sAlphaCount = 0; - sAlphaList = NULL; -} - -void xModelBucket_PreCountAlloc(S32 maxAlphaModels) -{ - sAlphaCount = maxAlphaModels; - sBucketList = (xModelBucket*)xMemAllocSize(sBucketCount * sizeof(xModelBucket)); - sBucketClipCullList = - (xModelBucket**)xMemAllocSize(sBucketClipCullCount * sizeof(xModelBucket*)); - sAlphaList = (xModelAlphaBucket*)xMemAllocSize(sAlphaCount * sizeof(xModelAlphaBucket)); - RwBBox boundingBox; - boundingBox.sup.x = xModelBucket_f675; - boundingBox.sup.y = xModelBucket_f675; - boundingBox.sup.z = xModelBucket_f675; - boundingBox.inf.x = xModelBucket_f676; - boundingBox.inf.y = xModelBucket_f676; - boundingBox.inf.z = xModelBucket_f676; - sBucketDummyWorld = RpWorldCreate(&boundingBox); - sBucketDummyCamera = iCameraCreate(0, 0, 0); - RpWorldAddCamera(sBucketDummyWorld, sBucketDummyCamera); -} - -void xModelBucket_Init() -{ - if (sBucketDummyCamera != NULL) - { - RpWorldRemoveCamera(sBucketDummyWorld, sBucketDummyCamera); - iCameraDestroy(sBucketDummyCamera); - RpWorldDestroy(sBucketDummyWorld); - sBucketDummyCamera = NULL; - sBucketDummyWorld = NULL; - } -} - -void xModelBucket_Begin() -{ - for (S32 i = 0; i < sBucketCount; i++) - { - sBucketList[i].List = NULL; - } - xModelBucketEnabled = 1; -} - -// Scheduling! -void xModelBucket_RenderAlphaBegin() -{ - sAlphaStart = 0; - xModelBucketEnabled = 0; - if (sAlphaCurr) - { - qsort(sAlphaList, sAlphaCurr, sizeof(xModelAlphaBucket), CmpAlphaBucket); - } -} diff --git a/src/SB/Core/x/xMorph.cpp b/src/SB/Core/x/xMorph.cpp deleted file mode 100644 index ad2f91b..0000000 --- a/src/SB/Core/x/xMorph.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "xMorph.h" - -#include "xDebug.h" -#include "iModel.h" - -#include - -xMorphSeqFile* xMorphSeqSetup(void* data, xMorphFindAssetCallback FindAssetCB) -{ - S32 i, j; - RpAtomic* model; - xMorphTargetFile* mphtgt; - xMorphSeqFile* header; - F32* timelist; - xMorphFrame* framelist; - U32* assetlist; - char* namelist; - void* assetPtr; - U32 skipsize; - - header = (xMorphSeqFile*)data; - timelist = (F32*)(header + 1); - framelist = (xMorphFrame*)(timelist + header->TimeCount); - assetlist = (U32*)(framelist + header->TimeCount); - namelist = (char*)(assetlist + header->ModelCount * 2); - - if (header->Flags & 0x80000000) { - return header; - } - - header->Flags |= 0x80000000; - if (!(header->Flags & 0x1)) { - namelist = NULL; - } - - for (i = 0; i < (S32)header->ModelCount * 2; i++) { - if (assetlist[i]) { - assetPtr = FindAssetCB(assetlist[i], namelist); - assetlist[i] = (U32)assetPtr; - } - if (namelist) { - namelist = strlen(namelist) + 1 + namelist; - } - } - - for (i = 0; i < (S32)header->ModelCount; i++) { - if (assetlist[i*2+1]) { - model = (RpAtomic*)assetlist[i*2]; - mphtgt = (xMorphTargetFile*)assetlist[i*2+1]; - iMorphOptimize(model, mphtgt->Flags & 0x1); - } - } - - for (i = 0; i < (S32)header->TimeCount; i++) { - model = (RpAtomic*)assetlist[(U32)framelist[i].Model*2]; - mphtgt = (xMorphTargetFile*)assetlist[(U32)framelist[i].Model*2+1]; - framelist[i].Model = model; - for (j = 0; j < 4; j++) { - if ((U32)framelist[i].Targets[j] + 0x10000 == 0xFFFF) { - framelist[i].Targets[j] = NULL; - } else { - skipsize = (mphtgt->NumVerts * 3 + 7) & ~7; - if (mphtgt->Flags & 0x1) { - skipsize *= 2; - } - if (j == 0) { - framelist[i].Flags = mphtgt->Flags; - framelist[i].NumVerts = mphtgt->NumVerts; - framelist[i].Scale *= mphtgt->Scale; - } - framelist[i].Targets[j] = (S16*)((U8*)(mphtgt + 1) + skipsize * (U32)framelist[i].Targets[j] * 2); - } - } - } - - return header; -} - -void xMorphRender(xMorphSeqFile* seq, RwMatrix* mat, F32 time) -{ - F32 lerp; - U32 tidx, tcount; - S16 weight[4]; - S16* wptr; - F32* times; - xMorphFrame* frame; - - times = (F32*)(seq + 1); - tcount = seq->TimeCount; - frame = (xMorphFrame*)(times + seq->TimeCount); - - if (time < 0.0f) time = 0.0f; - if (time > times[tcount-1]) time = times[tcount-1]; - - tidx = (tcount-1) & 0x3; - while (times[tidx] < time) tidx += 4; - while (tidx && time < times[tidx]) tidx--; - - frame += tidx; - - if (!frame->Targets[0]) { - iModelRender(frame->Model, mat); - } else { - lerp = frame->RecipTime * (time - times[tidx]); - if (lerp == 0.0f) { - wptr = frame->WeightStart; - } else { - weight[0] = (S32)(lerp * (frame->WeightEnd[0] - frame->WeightStart[0])) + frame->WeightStart[0], - weight[1] = (S32)(lerp * (frame->WeightEnd[1] - frame->WeightStart[1])) + frame->WeightStart[1], - weight[2] = (S32)(lerp * (frame->WeightEnd[2] - frame->WeightStart[2])) + frame->WeightStart[2], - weight[3] = (S32)(lerp * (frame->WeightEnd[3] - frame->WeightStart[3])) + frame->WeightStart[3]; - wptr = weight; - } - - iMorphRender(frame->Model, mat, frame->Targets, wptr, frame->Flags & 0x1, frame->Scale); - } -} - -F32 xMorphSeqDuration(xMorphSeqFile* seq) -{ - return ((F32*)(seq+1))[seq->TimeCount-1]; -} diff --git a/src/SB/Core/x/xMovePoint.cpp b/src/SB/Core/x/xMovePoint.cpp deleted file mode 100644 index ce6682f..0000000 --- a/src/SB/Core/x/xMovePoint.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include "xMovePoint.h" - -#include - -#include "xMath.h" -#include "xScene.h" -#include "xMemMgr.h" - -F32 xVec3Hdng(xVec3* a, const xVec3* b, const xVec3* c); - -void xMovePointInit(xMovePoint* ent, xMovePointAsset* asset) -{ - xBaseInit(ent, asset); - ent->asset = asset; - - // They didn't use `&asset->pos` here as that doesn't generate a 100% match. - ent->pos = &ent->asset->pos; - ent->on = asset->on; - ent->delay = asset->delay; - ent->spl = NULL; - - if (asset->numPoints != 0) - { - ent->nodes = (xMovePoint**)xMemAllocSize(asset->numPoints * sizeof(xMovePoint*)); - } - else - { - ent->nodes = NULL; - } -} - -void xMovePointSave(xMovePoint* ent, xSerial* s) -{ - xBaseSave(ent, s); -} - -void xMovePointLoad(xMovePoint* ent, xSerial* s) -{ - xBaseLoad(ent, s); -} - -void xMovePointReset(xMovePoint* m) -{ - xBaseReset(m, m->asset); - - m->on = m->asset->on; - m->delay = m->asset->delay; -} - -void xMovePointSetup(xMovePoint* m, xScene* sc) -{ - m->node_wt_sum = 0; - U32* pointIds = (U32*)(m->asset + 1); - for (U16 idx = 0; idx < m->asset->numPoints; ++idx) - { - U32 id = pointIds[idx]; - m->nodes[idx] = (xMovePoint*)xSceneResolvID(sc, id); - m->node_wt_sum += m->nodes[idx]->asset->wt; - m->nodes[idx]->prev = m; - } -} - -void xMovePointSplineDestroy(xMovePoint* m) -{ - if (m->spl != NULL) - { - m->spl = NULL; - } -} - -void xMovePointSplineSetup(xMovePoint* m) -{ - xMovePoint *w0, *w1, *w2, *w3; - xVec3 points[2]; - xVec3 p1, p2; - - if (m->asset->bezIndex != 1) - return; - if (m->spl) - return; - - w0 = m->prev; - w1 = m; - w2 = m->nodes[0]; - - points[0] = *w0->pos; - if (w2->asset->bezIndex > 0) - { - w3 = w2->nodes[0]; - p1 = *w1->pos; - p2 = *w2->pos; - points[1] = *w3->pos; - } - else - { - p1.x = (1 / 3.f) * w0->pos->x + (2 / 3.f) * w1->pos->x; - p1.y = (1 / 3.f) * w0->pos->y + (2 / 3.f) * w1->pos->y; - p1.z = (1 / 3.f) * w0->pos->z + (2 / 3.f) * w1->pos->z; - p2.x = (2 / 3.f) * w1->pos->x + (1 / 3.f) * w2->pos->x; - p2.y = (2 / 3.f) * w1->pos->y + (1 / 3.f) * w2->pos->y; - p2.z = (2 / 3.f) * w1->pos->z + (1 / 3.f) * w2->pos->z; - points[1] = *w2->pos; - } - - m->spl = xSpline3_Bezier(points, NULL, 2, 0, &p1, &p2); - xSpline3_ArcInit(m->spl, 20); -} - -// If you uncomment the numPoints variable then this function is a perfect match -// minus ordering. In the original assembly some variable fetches are lifted to -// places earlier in the assembly listing than what this comiles to for some -// reason. -// The r27-30 registers used to hold the main varibles of the function are all -// perfect matches with this code. -extern float xMovePoint_float_0; -F32 xMovePointGetNext(xMovePoint* m, xMovePoint* prev, xMovePoint** next, xVec3* hdng) -{ - if (m->asset->numPoints < 1) - { - *next = NULL; - return xMovePoint_float_0; - } - - xMovePoint* previousOption = NULL; - - S32 rnd = xrand() % m->node_wt_sum; - - // The debug symbols don't show a dedicated numPoints var, but if it isn't - // present, then getting numPoints isn't lifted outside of the loop, which - // it is in the original assembly. - U16 numPoints = m->asset->numPoints; - - for (U16 idx = 0; idx < m->asset->numPoints; ++idx) - { - *next = m->nodes[idx]; - rnd -= (*next)->asset->wt; - if ((*next)->on == 0) - { - *next = NULL; - } - else - { - previousOption = *next; - if (*next == prev) - { - *next = NULL; - } - else if (rnd < 0) - { - break; - } - } - } - - if (*next == NULL) - { - if (previousOption != NULL) - { - *next = previousOption; - } - else - { - return xMovePoint_float_0; - } - } - - if (hdng) - { - return xVec3Hdng(hdng, m->pos, (*next)->pos); - } - else - { - return xMovePoint_float_0; - } -} - -xVec3* xMovePointGetPos(const xMovePoint* m) -{ - return m->pos; -} diff --git a/src/SB/Core/x/xNPCBasic.cpp b/src/SB/Core/x/xNPCBasic.cpp deleted file mode 100644 index 3b6cfbb..0000000 --- a/src/SB/Core/x/xNPCBasic.cpp +++ /dev/null @@ -1,366 +0,0 @@ -#include "xNPCBasic.h" - -#include -#include - -// Weird... why does x depend on z here? -#include "zEnt.h" -#include "zGrid.h" - -#include "xMath.h" -#include "xModel.h" -#include "xEntMotion.h" -#include "xCamera.h" -#include "xDraw.h" - -#include "iColor.h" -#include "xColor.h" -#include "iCollide.h" - -extern float xNPCBasic_float_0; -extern float xNPCBasic_float_1; -extern float xNPCBasic_float_onehalf; -extern float xNPCBasic_float_onequarter; -extern float xNPCBasic_float_15; -extern float xNCPBasic_float_0p10000000; -extern float xNPCBasic_float_0p75; -extern float xNPCBasic_float_1eminus5; -extern float xNPCBasic_float_0p2; -extern float xNPCBasic_float_thirty; -extern float xNPCBasic_float_0p04; -extern float xNPCBasic_float_0p025; - -extern xEntCollis g_colrec; -extern xVec3 lbl_8026A3F8; - -void NPC_alwaysUseSphere(xEnt*, xVec3*); -void NPC_entwrap_setup(xEnt*); -void NPC_entwrap_reset(xEnt*); -S32 NPC_entwrap_event(xBase*, xBase*, U32, const F32*, xBase*); -void NPC_entwrap_update(xEnt*, xScene*, F32); -void NPC_entwrap_bupdate(xEnt*, xVec3*); -void NPC_entwrap_move(xEnt*, xScene*, F32, xEntFrame*); -void NPC_entwrap_render(xEnt*); - -// The order of the function pointer assignment instructions at the end of the -void xNPCBasic::Init(xEntAsset* asset) -{ - if (xNPCBasic_float_0 == asset->scale.x) - { - asset->scale.x = xNPCBasic_float_1; - } - if (xNPCBasic_float_0 == asset->scale.y) - { - asset->scale.y = xNPCBasic_float_1; - } - if (xNPCBasic_float_0 == asset->scale.z) - { - asset->scale.z = xNPCBasic_float_1; - } - - xEnt* thisEnt = this; - xEntInit(thisEnt, asset); - collType = 8; - collLev = 4; - bound.type = XBOUND_TYPE_SPHERE; // [S8] 0x84 - moreFlags |= 0x10; - zEntParseModelInfo(thisEnt, asset->modelInfoID); - xEntInitForType(thisEnt); - xEntInitShadow(*thisEnt, entShadow_embedded); - simpShadow = &simpShadow_embedded; - xShadowSimple_CacheInit(simpShadow, thisEnt, 0x50); - if (bound.type == XBOUND_TYPE_BOX) - { - iBoxForModel(&bound.box.box, collModel ? collModel : model); - } - else if (bound.type == XBOUND_TYPE_OBB) - { - iBoxForModelLocal(&bound.box.box, collModel ? collModel : model); - } - - if (flags1.flg_basenpc & 0x1) - { - collis = (xEntCollis*)xMemAllocSize(sizeof(xEntCollis)); - memset(collis, 0, sizeof(xEntCollis)); - } - - if ((flags1.flg_basenpc & 0x2) == 0) - { - frame = (xEntFrame*)xMemAllocSize(sizeof(xEntFrame)); - memset(frame, 0, sizeof(xEntFrame)); - } - - RestoreColFlags(); - - f_setup = &NPC_entwrap_setup; - f_reset = &NPC_entwrap_reset; - eventFunc = &NPC_entwrap_event; - update = &NPC_entwrap_update; - bupdate = &NPC_entwrap_bupdate; - move = &NPC_entwrap_move; - render = &NPC_entwrap_render; - - baseFlags &= 0xffef; -} - -void xNPCBasic::Reset() -{ - xEntReset(this); - DBG_PStatClear(); - if (!(U32(flags1.flg_basenpc) & 0x2)) - { - xVec3Copy(&frame->drot.axis, &g_Y3); - frame->drot.angle = 0.0f; - xVec3Copy(&frame->rot.axis, &g_Y3); - frame->rot.angle = asset->ang.x; - } - - flags1.flg_basenpc |= 4; - colFreq = -1; - - colFreqReset = (15.0f * (0.25f * (xurand() - 0.5f))) + 15.0f; - RestoreColFlags(); -} - -void NPC_alwaysUseSphere(xEnt* ent, xVec3* value) -{ - xNPCBasic* npc = (xNPCBasic*)ent; - xVec3 bndcent = lbl_8026A3F8; - - xVec3Copy(&bndcent, xEntGetPos(npc)); - bndcent.y += xNPCBasic_float_0p75; - - npc->bound.type = XBOUND_TYPE_SPHERE; - xVec3Copy(&npc->bound.sph.center, &bndcent); - npc->bound.sph.r = xNPCBasic_float_0p75; - if (npc->bound.type != XBOUND_TYPE_NA) - { - xQuickCullForBound(&npc->bound.qcd, &npc->bound); - } - - zGridUpdateEnt(npc); - if (npc->DBG_IsNormLog(eNPCDCAT_Eight, 2) || npc->DBG_IsNormLog(eNPCDCAT_Seven, 2)) - { - xDrawSetColor(g_PIMP_GOLD); - xBoundDraw(&npc->bound); - } -} - -void NPC_spdBasedColFreq(xNPCBasic* npc, F32 dt) -{ - if (dt < xNPCBasic_float_1eminus5) - { - return; - } - F32 d = xVec3Length(&npc->frame->vel); - if (d < xNPCBasic_float_0p2) - { - return; - } - - F32 radius; - if (npc->bound.type == XBOUND_TYPE_SPHERE) - { - radius = npc->bound.sph.r; - } - else - { - radius = MAX(npc->bound.box.box.upper.x - npc->bound.box.box.lower.x, - npc->bound.box.box.upper.z - npc->bound.box.box.lower.z); - } - - S32 nf = xNPCBasic_float_thirty * (radius / d); - npc->colFreq = MIN(npc->colFreq, nf); -} - -void xNPCBasic::Process(xScene* xscn, F32 dt) -{ - xEnt* thisEnt = this; - void (*bak_bupdate)(xEnt*, xVec3*); - S32 hasgrav = 0; - - if (flags2.flg_colCheck || flags2.flg_penCheck) - { - colFreq -= 1; - } - else - { - colFreq = 1; - } - - if (pflags & 0x4) - { - hasgrav = 1; - } - - if (colFreq >= 0) - { - pflags &= 0xfb; - } - - if (pflags & 0x2) - { - xEntApplyPhysics(thisEnt, xscn, dt); - } - - if (pflags & 0x1) - { - xEntMove(thisEnt, xscn, dt); - } - - if (ffx != NULL) - { - xFFXApply(this, xscn, dt); - } - - if (frame != NULL && (flags1.flg_upward & 0x2)) - { - frame->dpos.y = MAX(xNPCBasic_float_0, frame->dpos.y); - frame->dvel.y = MAX(xNPCBasic_float_0, frame->dvel.y); - frame->vel.y = MAX(xNPCBasic_float_0, frame->vel.y); - frame->oldvel.y = MAX(xNPCBasic_float_0, frame->oldvel.y); - model->Mat->pos.y = MAX(model->Mat->pos.y, frame->oldmat.pos.y); - } - - if (colFreq < 0) - { - colFreq = colFreqReset; - - DBG_PStatCont(eNPCPerfEnable); - DBG_PStatOn(eNPCPerfDisable); - - if (collis == NULL) - { - memset(&g_colrec, 0, sizeof(g_colrec)); - collis = &g_colrec; - } - - collis->chk = flags2.flg_colCheck; - collis->pen = flags2.flg_penCheck; - - bak_bupdate = bupdate; - bupdate = &NPC_alwaysUseSphere; - xEntCollide(thisEnt, xscn, dt); - bupdate = bak_bupdate; - - CollideReview(); - - if ((flags1.flg_basenpc & 0x1) == 0) - { - collis = NULL; - } - - DBG_PStatCont(eNPCPerfDisable); - DBG_PStatOn(eNPCPerfEnable); - } - - if ((pflags & (0x2 | 0x1)) != 0 && xVec3Length2(&frame->vel) > xNCPBasic_float_0p10000000) - { - NPC_spdBasedColFreq(this, dt); - } - - if (hasgrav) - { - pflags |= 0x4; - } - - if (DBG_IsNormLog(eNPCDCAT_Seven, 2)) - { - xDrawSetColor(g_BLUE); - xBoundDraw(&bound); - } -} - -void xNPCBasic::CollideReview() -{ - if (DBG_IsNormLog(eNPCDCAT_Eight, 2)) - { - xDrawSetColor(g_LAVENDER); - xBoundDraw(&bound); - } -} - -void xNPCBasic::NewTime(xScene*, F32) -{ - flags1.flg_basenpc &= ~0x4; -} - -void NPC_entwrap_setup(xEnt* ent) -{ - xNPCBasic* npc = (xNPCBasic*)ent; - npc->DBG_HaltOnMe(0, NULL); - npc->Setup(); -} - -void NPC_entwrap_reset(xEnt* ent) -{ - xNPCBasic* npc = (xNPCBasic*)ent; - npc->DBG_HaltOnMe(0, NULL); - npc->Reset(); -} - -void NPC_entwrap_update(xEnt* ent, xScene* scn, F32 dt_caller) -{ - F32 dt = dt_caller; - if (dt > xNPCBasic_float_0p04) - { - dt = xNPCBasic_float_0p025; - } - - xNPCBasic* npc = (xNPCBasic*)ent; - xEntBeginUpdate(npc, scn, dt); - npc->flags1.inUpdate = 1; - npc->DBG_HaltOnMe(0, NULL); - npc->DBG_PStatOn(eNPCPerfEnable); - - if (npc->isCulled) - { - npc->model->Flags &= 0xfffd; - } - else if ((npc->flags1.flg_upward & 0x1) == 0) - { - npc->model->Flags |= 0x2; - } - - npc->Process(scn, dt); - - npc->DBG_PStatCont(eNPCPerfEnable); - npc->flags1.inUpdate = 0; - xEntEndUpdate(npc, scn, dt); - - npc->NewTime(scn, dt); -} - -void NPC_entwrap_bupdate(xEnt* ent, xVec3* pos) -{ - ((xNPCBasic*)ent)->BUpdate(pos); -} - -void NPC_entwrap_move(xEnt* ent, xScene* scn, F32 dt, xEntFrame* frame) -{ - ((xNPCBasic*)ent)->Move(scn, dt, frame); -} - -S32 NPC_entwrap_event(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* toParamWidget) -{ - S32 handled = 0; - return ((xNPCBasic*)to)->SysEvent(from, to, toEvent, toParam, toParamWidget, &handled); -} - -void NPC_entwrap_render(xEnt* ent) -{ - ((xNPCBasic*)ent)->Render(); -} - -void xNPCBasic::DBG_PStatClear() -{ -} - -void xNPCBasic::DBG_HaltOnMe(U32, char*) -{ -} - -void xNPCBasic::BUpdate(xVec3* v) -{ - xEntDefaultBoundUpdate(this, v); -} diff --git a/src/SB/Core/x/xPad.cpp b/src/SB/Core/x/xPad.cpp deleted file mode 100644 index 81b34d6..0000000 --- a/src/SB/Core/x/xPad.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "xPad.h" - -#include -#include - -S32 xPadInit() -{ - memset(mPad, 0, sizeof(mPad)); - memset(mRumbleList, 0, sizeof(mRumbleList)); - S32 code = iPadInit(); - if (!code) - { - return 0; - } - gPlayerPad = mPad; - return 1; -} - -// WIP. -_tagxPad* xPadEnable(S32 idx) -{ - _tagxPad* p = mPad + idx; - if (p->state == ePad_Disabled && idx == 0) - { - p = iPadEnable(mPad + idx, 0); - } - return p; -} - -void xPadRumbleEnable(S32 idx, S32 enable) -{ - _tagxPad* p = mPad + idx; - if (p->state != 2) - { - enable = 0; - } - if (enable) - { - if (p->flags & 4) - { - p->flags |= 8; - } - } - else - { - if (p->flags & 8) - { - p->flags ^= 8; - xPadDestroyRumbleChain(mPad + idx); - } - } -} - -void xPadAnalogIsDigital(S32 idx, S32 enable) -{ - if (idx != 0) - return; - - _tagxPad* pad = &mPad[idx]; - - if (enable) - { - pad->flags |= 0x10; - } - else - { - pad->flags &= ~0x10; - } - - if (pad->al2d_timer >= 0.35f) - { - pad->al2d_timer = 0.35f; - } - - if (pad->ar2d_timer >= 0.35f) - { - pad->ar2d_timer = 0.35f; - } - - if (pad->d_timer >= 0.35f) - { - pad->d_timer = 0.35f; - } -} - -void xPadKill() -{ - iPadKill(); -} - -// WIP. -_tagxRumble* xPadGetRumbleSlot() -{ - _tagxRumble* rum = mRumbleList; - for (S32 i = 0x20; i > 0; i--) - { - if (rum->active == 0) - { - memset(rum, 0, sizeof(_tagxRumble)); - return rum; - } - rum++; - } - return NULL; -} - -void xPadDestroyRumbleChain(_tagxPad* pad) -{ - iPadStopRumble(pad); - _tagxRumble* curr = pad->rumble_head.next; - while (curr != NULL) - { - memset(curr, 0, sizeof(_tagxRumble)); - curr = curr->next; - } - pad->rumble_head.next = NULL; -} - -void xPadDestroyRumbleChain(S32 idx) -{ - xPadDestroyRumbleChain(mPad + idx); -} diff --git a/src/SB/Core/x/xPar.cpp b/src/SB/Core/x/xPar.cpp deleted file mode 100644 index 91c48bd..0000000 --- a/src/SB/Core/x/xPar.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "xPar.h" - -#include - -#define PAR_POOL_SIZE 2000 - -extern xPar gParPool[PAR_POOL_SIZE]; -extern xPar* gParDead; -extern F32 lbl_803CCF10; // 0.0f -extern F32 lbl_803CCF14; // 255f - -// For some reason, it does not recompare gParDead and assumes the first comparison is valid for all. -void xParMemInit() -{ - for (S32 i = 0; i < PAR_POOL_SIZE; i++) - { - xPar* curr = &gParPool[i]; - curr->m_next = NULL; - curr->m_prev = NULL; - if (gParDead != NULL) - { - gParDead->m_prev = curr; - curr->m_next = gParDead; - } - gParDead = curr; - } -} - -xPar* xParAlloc() -{ - xPar* dead = gParDead; - if (gParDead == NULL) - { - return NULL; - } - if (gParDead->m_next != NULL) - { - gParDead->m_next->m_prev = NULL; - } - xPar** next = &dead->m_next; - gParDead = *next; - *next = NULL; - dead->m_prev = NULL; - return dead; -} - -void xParFree(xPar* par) -{ - if (par->m_next != NULL) - { - par->m_next->m_prev = par->m_prev; - } - if (par->m_prev != NULL) - { - par->m_prev->m_next = par->m_next; - } - if (gParDead != NULL) - { - gParDead->m_prev = par; - } - par->m_next = gParDead; - par->m_prev = NULL; - gParDead = par; -} - -void xParInit(xPar* p) -{ - p->m_pos.x = lbl_803CCF10; - p->m_pos.y = lbl_803CCF10; - p->m_pos.z = lbl_803CCF10; - p->m_vel.x = lbl_803CCF10; - p->m_vel.y = lbl_803CCF10; - p->m_vel.z = lbl_803CCF10; - p->m_size = lbl_803CCF10; - p->m_sizeVel = lbl_803CCF10; - p->m_lifetime = lbl_803CCF10; - p->m_cvel[0] = lbl_803CCF10; - p->m_cvel[1] = lbl_803CCF10; - p->m_cvel[2] = lbl_803CCF10; - p->m_cvel[3] = lbl_803CCF10; - p->m_cfl[0] = lbl_803CCF14; - p->m_cfl[1] = lbl_803CCF14; - p->m_cfl[2] = lbl_803CCF14; - p->m_cfl[3] = lbl_803CCF14; - p->m_c[0] = 0xff; - p->m_c[1] = 0xff; - p->m_c[2] = 0xff; - p->m_c[3] = 0xff; - p->m_flag = 0; - p->m_rotdeg[0] = 0; - p->m_rotdeg[1] = 0; - p->m_rotdeg[2] = 0; - p->m_next = NULL; - p->m_prev = NULL; - p->m_texIdx[0] = 0; - p->m_texIdx[1] = 0; -} diff --git a/src/SB/Core/x/xParCmd.cpp b/src/SB/Core/x/xParCmd.cpp deleted file mode 100644 index 572e9a2..0000000 --- a/src/SB/Core/x/xParCmd.cpp +++ /dev/null @@ -1,800 +0,0 @@ -#include "xParCmd.h" - -#include "xParGroup.h" -#include "xVec3Inlines.h" -#include "xMath.h" -#include "xMathInlines.h" - -struct xCmdInfo -{ - U32 type; - U32 size; - xParCmdUpdateFunc func; -}; - -static xCmdInfo sCmdInfo[XPARCMD_TYPE_COUNT] = {}; - -extern F32 _658_0; -extern F32 _691; -extern F32 _760; -extern F32 _772; -extern F32 _812; -extern F32 _830_1; -extern F32 _831_0; -extern F32 _857_0; -extern F32 _858; -extern F32 _1075; -extern F32 _1076; -extern F32 _1077; - -void xParCmdInit() -{ - xParCmdRegister(XPARCMD_TYPE_MOVE, sizeof(xParCmdMove), xParCmdMove_Update); - xParCmdRegister(XPARCMD_TYPE_MOVERANDOM, sizeof(xParCmdMove), xParCmdMoveRandom_Update); - xParCmdRegister(XPARCMD_TYPE_ACCELERATE, sizeof(xParCmdAccelerate), xParCmdAccelerate_Update); - xParCmdRegister(XPARCMD_TYPE_VELOCITYAPPLY, sizeof(xParCmdAsset), xParCmdVelocityApply_Update); - xParCmdRegister(XPARCMD_TYPE_UNK5, sizeof(xParCmdUnk5), NULL); - xParCmdRegister(XPARCMD_TYPE_KILLSLOW, sizeof(xParCmdKillSlow), xParCmdKillSlow_Update); - xParCmdRegister(XPARCMD_TYPE_FOLLOW, sizeof(xParCmdFollow), xParCmdFollow_Update); - xParCmdRegister(XPARCMD_TYPE_ORBITPOINT, sizeof(xParCmdOrbitPoint), xParCmdOrbitPoint_Update); - xParCmdRegister(XPARCMD_TYPE_ORBITLINE, sizeof(xParCmdOrbitLine), xParCmdOrbitLine_Update); - xParCmdRegister(XPARCMD_TYPE_MOVERANDOMPAR, sizeof(xParCmdMoveRandomPar), - xParCmdMoveRandomPar_Update); - xParCmdRegister(XPARCMD_TYPE_SCALE3RDPOLYREG, sizeof(xParCmdScale3rdPolyReg), - xParCmdScale3rdPolyReg_Update); - xParCmdRegister(XPARCMD_TYPE_TEX, sizeof(xParCmdTex), xParCmdTex_Update); - xParCmdRegister(XPARCMD_TYPE_TEXANIM, sizeof(xParCmdTexAnim), xParCmdTexAnim_Update); - xParCmdRegister(XPARCMD_TYPE_RANDOMVELOCITYPAR, sizeof(xParCmdRandomVelocityPar), - xParCmdRandomVelocityPar_Update); - xParCmdRegister(XPARCMD_TYPE_AGE, sizeof(xParCmdAge), xParCmdAge_Update); - xParCmdRegister(XPARCMD_TYPE_ALPHA3RDPOLYREG, sizeof(xParCmdAlpha3rdPolyReg), - xParCmdAlpha3rdPolyReg_Update); - xParCmdRegister(XPARCMD_TYPE_APPLYWIND, sizeof(xParCmdApplyWind), xParCmdApplyWind_Update); - xParCmdRegister(XPARCMD_TYPE_ROTPAR, sizeof(xParCmdRotPar), xParCmdRotPar_Update); - xParCmdRegister(XPARCMD_TYPE_ROTATEAROUND, sizeof(xParCmdRotateAround), - xParCmdRotateAround_Update); - xParCmdRegister(XPARCMD_TYPE_SMOKEALPHA, sizeof(xParCmdSmokeAlpha), xParCmdSmokeAlpha_Update); - xParCmdRegister(XPARCMD_TYPE_SCALE, sizeof(xParCmdScale), xParCmdScale_Update); - xParCmdRegister(XPARCMD_TYPE_COLLIDEFALL, sizeof(xParCmdCollideFall), - xParCmdCollideFall_Update); - xParCmdRegister(XPARCMD_TYPE_COLLIDEFALLSTICKY, sizeof(xParCmdCollideFallSticky), - xParCmdCollideFallSticky_Update); - xParCmdRegister(XPARCMD_TYPE_SHAPER, sizeof(xParCmdShaperData), xParCmd_Shaper_Update); - xParCmdRegister(XPARCMD_TYPE_ALPHAINOUT, sizeof(xParCmdAlphaInOutData), - xParCmd_AlphaInOut_Update); - xParCmdRegister(XPARCMD_TYPE_SIZEINOUT, sizeof(xParCmdSizeInOutData), xParCmd_SizeInOut_Update); - xParCmdRegister(XPARCMD_TYPE_DAMPENSPEED, sizeof(xParCmdDampenData), - xParCmd_DampenSpeed_Update); -} - -void xParCmdRegister(U32 parType, U32 size, xParCmdUpdateFunc func) -{ - sCmdInfo[parType].type = parType; - sCmdInfo[parType].size = size; - sCmdInfo[parType].func = func; -} - -U32 xParCmdGetSize(U32 parType) -{ - for (S32 i = 0; i < XPARCMD_TYPE_COUNT; i++) - { - if (sCmdInfo[i].type == parType) - { - return sCmdInfo[i].size; - } - } - - return 0; -} - -xParCmdUpdateFunc xParCmdGetUpdateFunc(U32 parType) -{ - for (S32 i = 0; i < XPARCMD_TYPE_COUNT; i++) - { - if (sCmdInfo[i].type == parType) - { - return sCmdInfo[i].func; - } - } - - return NULL; -} - -void xParCmdKillSlow_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - xParCmdKillSlow* cmd = (xParCmdKillSlow*)c->tasset; - F32 speedLimit = cmd->speedLimitSqr * dt; - - if (cmd->kill_less_than) - { - while (p) - { - if (xVec3Length2(&p->m_vel) < speedLimit) - { - p->m_lifetime = _658_0; - } - - p = p->m_next; - } - } - else - { - while (p) - { - if (xVec3Length2(&p->m_vel) > speedLimit) - { - p->m_lifetime = _658_0; - } - - p = p->m_next; - } - } -} - -void xParCmdAge_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - F32 age_rate = ((xParCmdAge*)c->tasset)->unknown * dt; - - while (p) - { - p->m_lifetime -= age_rate; - p = p->m_next; - } -} - -void xParCmdFollow_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - xParCmdFollow* cmd = (xParCmdFollow*)c->tasset; - F32 mdt = cmd->gravity * dt; - - while (p && p->m_next) - { - xVec3 var_38; - - xVec3Sub(&var_38, &p->m_next->m_pos, &p->m_pos); - - F32 f31 = xVec3Length2(&var_38); - F32 f1 = xVec3LengthFast(var_38.x, var_38.y, var_38.z); - - F32 force = mdt / (f1 * (f31 + cmd->epsilon)); - - p->m_vel.x += var_38.x * force; - p->m_vel.y += var_38.y * force; - p->m_vel.z += var_38.z * force; - - p = p->m_next; - } -} - -void xParCmdOrbitPoint_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - xParCmdOrbitPoint* cmd = (xParCmdOrbitPoint*)c->tasset; - F32 mdt = cmd->gravity * dt; - - while (p) - { - xVec3 var_38; - - xVec3Sub(&var_38, &cmd->center, &p->m_pos); - - F32 f31 = xVec3Length2(&var_38); - - if (f31 < cmd->maxRadiusSqr) - { - F32 f1 = xVec3LengthFast(var_38.x, var_38.y, var_38.z); - - F32 force = mdt / (f1 + (f31 + cmd->epsilon)); - - p->m_vel.x += var_38.x * force; - p->m_vel.y += var_38.y * force; - p->m_vel.z += var_38.z * force; - } - - p = p->m_next; - } -} - -void xParCmdOrbitLine_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - xParCmdOrbitLine* cmd = (xParCmdOrbitLine*)c->tasset; - F32 mdt = cmd->gravity * dt; - - while (p) - { - xVec3 var_34, var_40, var_4C, var_58; - - xVec3Sub(&var_34, &p->m_pos, &cmd->p); - xVec3Cross(&var_4C, &var_34, &cmd->axis); - xVec3Cross(&var_40, &cmd->axis, &var_4C); - xVec3Sub(&var_58, &var_40, &var_34); - - F32 f31 = xVec3Length2(&var_58); - - if (f31 < cmd->maxRadiusSqr) - { - F32 f1 = xVec3LengthFast(var_58.x, var_58.y, var_58.z); - - F32 force = mdt / (f1 + (f31 + cmd->epsilon)); - - p->m_vel.x += var_58.x * force; - p->m_vel.y += var_58.y * force; - p->m_vel.z += var_58.z * force; - } - - p = p->m_next; - } -} - -void xParCmdAccelerate_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p; - xParCmdAccelerate* cmd = (xParCmdAccelerate*)c->tasset; - - xVec3 var_28; - var_28 = cmd->acc; - - xVec3SMulBy(&var_28, dt); - - p = ps->m_root; - - while (p) - { - p->m_vel.x += var_28.x; - p->m_vel.y += var_28.y; - p->m_vel.z += var_28.z; - - p = p->m_next; - } -} - -void xParCmdMove_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p; - xParCmdMove* cmd = (xParCmdMove*)c->tasset; - - xVec3 var_28; - var_28 = cmd->dir; - - xVec3SMulBy(&var_28, dt); - - p = ps->m_root; - - while (p) - { - xVec3Add(&p->m_pos, &p->m_pos, &var_28); - - p = p->m_next; - } -} - -void xParCmdMoveRandom_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p; - xParCmdMove* cmd = (xParCmdMove*)c->tasset; - - xVec3 var_28; - var_28 = cmd->dir; - - var_28.x *= _760 * xurand(); - var_28.y *= _760 * xurand(); - var_28.z *= _760 * xurand(); - - xVec3Sub(&var_28, &var_28, &cmd->dir); - xVec3SMulBy(&var_28, dt); - - p = ps->m_root; - - while (p) - { - xVec3Add(&p->m_pos, &p->m_pos, &var_28); - - p = p->m_next; - } -} - -void xParCmdMoveRandomPar_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - xParCmdMoveRandomPar* cmd = (xParCmdMoveRandomPar*)c->tasset; - F32 f31 = cmd->dim.x * (dt * _772); - F32 f30 = cmd->dim.z * (dt * _772); - - while (p) - { - p->m_pos.x += f31 * (xurand() - _772); - p->m_pos.z += f30 * (xurand() - _772); - - p = p->m_next; - } -} - -void xParCmdScale3rdPolyReg_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ -} - -void xParCmdSmokeAlpha_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ -} - -void xParCmdScale_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ -} - -void xParCmdAlpha3rdPolyReg_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ -} - -void xParCmdRandomVelocityPar_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - xParCmdRandomVelocityPar* cmd = (xParCmdRandomVelocityPar*)c->tasset; - F32 f31 = cmd->x * dt; - F32 f30 = cmd->y * dt; - F32 f29 = cmd->z * dt; - - while (p) - { - xMat3x3 var_88; - - F32 y = _760 * (f31 * xurand()) - f31; - F32 x = _760 * (f30 * xurand()) - f30; - F32 z = _760 * (f29 * xurand()) - f29; - - xMat3x3Euler(&var_88, x, y, z); - xMat3x3LMulVec(&p->m_vel, &var_88, &p->m_vel); - - p = p->m_next; - } -} - -void xParCmdApplyWind_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - - // non-matching: f2 and f3 are combined into one register - F32 f2 = _812 * (((xParCmdApplyWind*)c->tasset)->unknown * dt); - F32 f3 = _812 * (((xParCmdApplyWind*)c->tasset)->unknown * dt); - - while (p) - { - p->m_vel.x += f2; - p->m_vel.z += f3; - - p = p->m_next; - } -} - -void xParCmdRotPar_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - xParCmdRotPar* cmd = (xParCmdRotPar*)c->tasset; - F32 f30 = _830_1 * ((cmd->max.x - cmd->min.x) / _831_0); - F32 f29 = _830_1 * ((cmd->max.y - cmd->min.y) / _831_0); - F32 f28 = _830_1 * ((cmd->max.z - cmd->min.z) / _831_0); - F32 f27 = _830_1 * (cmd->min.x / _831_0); - F32 f26 = _830_1 * (cmd->min.y / _831_0); - F32 f25 = _830_1 * (cmd->min.z / _831_0); - - while (p) - { - p->m_rotdeg[0] += (U8)(dt * (f30 * xurand() + f27)); - p->m_rotdeg[1] += (U8)(dt * (f29 * xurand() + f26)); - p->m_rotdeg[2] += (U8)(dt * (f28 * xurand() + f25)); - - p = p->m_next; - } -} - -void xParCmdVelocityApply_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - - while (p) - { - xVec3Add(&p->m_pos, &p->m_pos, &p->m_vel); - - p = p->m_next; - } -} - -void xParCmdRotateAround_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p = ps->m_root; - xParCmdRotateAround* cmd = (xParCmdRotateAround*)c->tasset; - - F32 yaw = _857_0 * (dt * cmd->yaw) / _858; - F32 radius_growth = dt * cmd->radius_growth; - - while (p) - { - xVec3 at; - xVec3Sub(&at, &cmd->pos, &p->m_pos); - - at.y = _691; - - xMat3x3 lookmat; - - F32 radius = xMat3x3LookVec(&lookmat, &at); - - xVec3 angles; - xMat3x3GetEuler(&lookmat, &angles); - - angles.x += yaw; - - xMat3x3 rotmat; - xMat3x3Euler(&rotmat, angles.x, angles.y, angles.z); - - xVec3 var_BC, var_C8; - - // non-matching: f0 and f1 swapped - - var_BC.x = _691; - var_BC.y = _691; - var_BC.z = radius + radius_growth; - - xMat3x3RMulVec(&var_C8, &rotmat, &var_BC); - - p->m_pos.x = var_C8.x + cmd->pos.x; - p->m_pos.z = var_C8.z + cmd->pos.z; - - p = p->m_next; - } -} - -void xParCmdTex_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ -} - -void xParCmdTexAnim_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p; - xParCmdTexAnim* cmd = (xParCmdTexAnim*)c->tasset; - xParCmdTex* tex = ps->m_cmdTex; - - if (!tex) - { - return; - } - - if (cmd->throttle_time > _691) - { - cmd->throttle_time_elapsed -= dt; - - if (cmd->throttle_time_elapsed > _691) - { - return; - } - - cmd->throttle_time_elapsed = cmd->throttle_time; - } - - p = ps->m_root; - - if (cmd->anim_mode == 0) - { - while (p) - { - p->m_texIdx[0] = xrand() % tex->cols; - p->m_texIdx[1] = xrand() % tex->rows; - - p = p->m_next; - } - } - else if (cmd->anim_mode == 1) - { - if (tex->cols > 1) - { - while (p) - { - p->m_texIdx[0]++; - - if (p->m_texIdx[0] >= tex->cols) - { - p->m_texIdx[0] = 0; - - if (cmd->anim_wrap_mode == 1) - { - p->m_texIdx[1]++; - - if (p->m_texIdx[1] >= tex->rows) - { - p->m_texIdx[1] = 0; - } - } - else if (cmd->anim_wrap_mode == 2) - { - if (p->m_texIdx[1] == 0) - { - p->m_texIdx[1] = tex->rows - 1; - } - else - { - p->m_texIdx[1]--; - } - } - else if (cmd->anim_wrap_mode == 3) - { - p->m_texIdx[1]++; - - if (p->m_texIdx[1] >= tex->rows) - { - p->m_texIdx[1] = tex->rows - 1; - p->m_texIdx[0] = tex->cols - 1; - } - } - } - - p = p->m_next; - } - } - } - else if (cmd->anim_mode == 2) - { - if (tex->cols > 1) - { - while (p) - { - if (p->m_texIdx[0] == 0) - { - p->m_texIdx[0] = tex->cols - 1; - - if (cmd->anim_wrap_mode == 1) - { - p->m_texIdx[1]++; - - if (p->m_texIdx[1] >= tex->rows) - { - p->m_texIdx[1] = 0; - } - } - else if (cmd->anim_wrap_mode == 2) - { - if (p->m_texIdx[1] == 0) - { - p->m_texIdx[1] = tex->rows - 1; - } - else - { - p->m_texIdx[1]--; - } - } - } - else - { - p->m_texIdx[0]--; - } - - p = p->m_next; - } - } - } - else if (cmd->anim_mode == 3) - { - if (tex->rows > 1) - { - while (p) - { - if (p->m_texIdx[1] == 0) - { - p->m_texIdx[1] = tex->rows - 1; - - if (cmd->anim_wrap_mode == 1) - { - p->m_texIdx[0]++; - - if (p->m_texIdx[0] >= tex->cols) - { - p->m_texIdx[0] = 0; - } - } - else if (cmd->anim_wrap_mode == 2) - { - if (p->m_texIdx[0] == 0) - { - p->m_texIdx[0] = tex->cols - 1; - } - else - { - p->m_texIdx[0]--; - } - } - } - else - { - p->m_texIdx[1]--; - } - - p = p->m_next; - } - } - } - else if (cmd->anim_mode == 4) - { - if (tex->rows > 1) - { - while (p) - { - p->m_texIdx[1]++; - - if (p->m_texIdx[1] >= tex->rows) - { - p->m_texIdx[1] = 0; - - if (cmd->anim_wrap_mode == 1) - { - p->m_texIdx[0]++; - - if (p->m_texIdx[0] >= tex->cols) - { - p->m_texIdx[0] = 0; - } - } - else if (cmd->anim_wrap_mode == 2) - { - if (p->m_texIdx[0] == 0) - { - p->m_texIdx[0] = tex->cols - 1; - } - else - { - p->m_texIdx[0]--; - } - } - } - - p = p->m_next; - } - } - } -} - -void xParCmdCollideFall_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xParCmdCollideFall& cmd = *(xParCmdCollideFall*)c->tasset; - xPar* p = ps->m_root; - - while (p) - { - F32& loc = p->m_pos.y; - F32& vel = p->m_vel.y; - F32 dloc = cmd.y - loc; - - if (dloc < _691) - { - // lol - } - else - { - loc = dloc * cmd.bounce + cmd.y; - - if (vel < _691) - { - vel = -vel * cmd.bounce; - } - } - - p = p->m_next; - } -} - -void xParCmdCollideFallSticky_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xParCmdCollideFallSticky& cmd = *(xParCmdCollideFallSticky*)c->tasset; - F32 xzdamp = _812 - cmd.sticky; - xPar* p = ps->m_root; - - while (p) - { - F32& loc = p->m_pos.y; - F32& vel = p->m_vel.y; - F32 dloc = cmd.y - loc; - - if (dloc < _691) - { - // lol - } - else - { - loc = dloc * cmd.bounce + cmd.y; - - if (vel < _691) - { - vel = -vel * cmd.bounce; - } - - p->m_vel.x *= xzdamp; - p->m_vel.z *= xzdamp; - } - - p = p->m_next; - } -} - -void xParCmd_DampenSpeed_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p; - xParCmdDampenData* cmd = (xParCmdDampenData*)c->tasset; - - if (cmd->enabled) - { - p = ps->m_root; - - F32 damp = dt * cmd->dampSpeed; - - while (p) - { - xVec3AddScaled(&p->m_vel, &p->m_vel, damp); - - p = p->m_next; - } - } -} - -void xParCmd_SizeInOut_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - xPar* p; - xParCmdSizeInOutData* cmd = (xParCmdSizeInOutData*)c->tasset; - - if (cmd->enabled) - { - p = ps->m_root; - - S32 i, seg; - F32 slope_size[3]; - - slope_size[0] = _1075 * (cmd->custSize[1] - cmd->custSize[0]); - slope_size[1] = _1075 * (cmd->custSize[2] - cmd->custSize[1]); - slope_size[2] = _1075 * (cmd->custSize[3] - cmd->custSize[2]); - - while (p) - { - // non-matching: there is definitely a clamp happening here, but it isn't using the CLAMP macro. - F32 frac = CLAMP(_812 - p->m_lifetime / p->totalLifespan, _691, _812); - - if (frac < _1076) - { - seg = 0; - } - else if (frac < _1077) - { - seg = 1; - } - else - { - seg = 2; - } - - for (S32 i = seg; i > 0; i--) - { - // non-matching: _1076 is cached before loop - frac -= _1076; - } - - p->m_size = frac * slope_size[seg] + cmd->custSize[seg]; - - p = p->m_next; - } - } -} - -void xParCmd_AlphaInOut_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - // todo: this is very similar to xParCmd_SizeInOut_Update -} - -void xParCmd_Shaper_Update(xParCmd* c, xParGroup* ps, F32 dt) -{ - // todo: part of this is very similar to xParCmd_SizeInOut_Update -} - -WEAK F32 xVec3LengthFast(F32 x, F32 y, F32 z) -{ - F32 len; - xsqrtfast(len, SQR(x) + SQR(y) + SQR(z)); - return len; -} diff --git a/src/SB/Core/x/xParEmitter.cpp b/src/SB/Core/x/xParEmitter.cpp deleted file mode 100644 index debde9e..0000000 --- a/src/SB/Core/x/xParEmitter.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "xParEmitter.h" - -#include diff --git a/src/SB/Core/x/xParEmitterType.cpp b/src/SB/Core/x/xParEmitterType.cpp deleted file mode 100644 index 9b94ea5..0000000 --- a/src/SB/Core/x/xParEmitterType.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "xParEmitterType.h" - -#include diff --git a/src/SB/Core/x/xParGroup.cpp b/src/SB/Core/x/xParGroup.cpp deleted file mode 100644 index 328593a..0000000 --- a/src/SB/Core/x/xParGroup.cpp +++ /dev/null @@ -1,303 +0,0 @@ -#include "xParGroup.h" - -#include "xMath.h" - -#define REG_TABLE_SIZE 255 - -S32 sParGroupRegTableInit = 0; -S32 sParGroupRegTableCount = 0; -extern xParGroup* sParGroupRegTable[REG_TABLE_SIZE]; // todo: move from bss.s - -extern F32 _708; -extern F32 _709; - -void xParGroupInit(xParGroup* ps) -{ - ps->m_root = NULL; - ps->m_dead = NULL; - ps->m_alive = 0; - ps->m_num_of_particles = 0; - ps->m_killWhenDead = 0; - ps->m_flags = 0; - ps->m_active = 1; - ps->m_culled = 0; - ps->m_visible = 1; - ps->m_cmdTex = NULL; - ps->m_priority = 0; - ps->m_next = NULL; - ps->m_prev = NULL; - - ps->m_flags |= XPARGROUP_ALLOCPARS; - ps->m_flags |= XPARGROUP_UNK1; -} - -static void xParGroupRegisterInit() -{ - for (S32 i = 0; i < REG_TABLE_SIZE; i++) - { - sParGroupRegTable[i] = NULL; - } - - sParGroupRegTableInit = 1; - sParGroupRegTableCount = 0; -} - -void xParGroupSetAging(xParGroup* ps, S32 age) -{ - if (age) - { - if (ps->m_flags & XPARGROUP_NOAGING) - { - ps->m_flags ^= XPARGROUP_NOAGING; - } - } - else - { - ps->m_flags |= XPARGROUP_NOAGING; - } -} - -void xParGroupSetBack2Life(xParGroup* ps, S32 b2l) -{ - if (b2l) - { - if (ps->m_flags & XPARGROUP_NOBACK2LIFE) - { - ps->m_flags ^= XPARGROUP_NOBACK2LIFE; - } - } - else - { - ps->m_flags |= XPARGROUP_NOBACK2LIFE; - } -} - -void xParGroupSetVisibility(xParGroup* ps, S32 vis) -{ - ps->m_visible = vis; -} - -void xParGroupSetPriority(xParGroup* ps, U8 val) -{ - ps->m_priority = val; -} - -void xParGroupRegister(xParGroup* ps) -{ - if (!sParGroupRegTableInit) - { - xParGroupRegisterInit(); - } - - for (U8 i = 0; i < REG_TABLE_SIZE; i++) - { - if (!sParGroupRegTable[i]) - { - sParGroupRegTable[i] = ps; - ps->m_regidx = i; - break; - } - } -} - -void xParGroupUnregister(xParGroup* ps) -{ - for (U8 i = 0; i < REG_TABLE_SIZE; i++) - { - if (sParGroupRegTable[i] == ps) - { - sParGroupRegTable[i] = NULL; - ps->m_regidx = 0; - break; - } - } -} - -void xParGroupSetActive(xParGroup* ps, U32 isActive) -{ - ps->m_active = isActive; -} - -void xParGroupKillAllParticles(xParGroup* ps) -{ - xPar* i = ps->m_root; - - while (i) - { - xPar* tmp = i; - - i = i->m_next; - - xParGroupKillPar(ps, tmp); - } -} - -#define clamp(x, a, b) (((x) < (a)) ? (a) : (((x) > (b)) ? (b) : (x))) - -void xParGroupAnimate(xParGroup* ps, F32 dt) -{ - xPar* i = ps->m_root; - xPar* tmp; - F32 age = dt; - - if (ps->m_flags & XPARGROUP_NOAGING) - { - age = _708; - } - - if (!ps->m_root) - { - ps->m_alive = 0; - } - - while (i) - { - if (i->m_lifetime < _708) - { - tmp = i; - - i = i->m_next; - - xParGroupKillPar(ps, tmp); - } - else - { - // non-matching: stack isn't resizing for each float-to-U8 conversion - i->m_c[0] = i->m_cfl[0] = clamp(i->m_cvel[0] * dt + i->m_cfl[0], _708, _709); - i->m_c[1] = i->m_cfl[1] = clamp(i->m_cvel[1] * dt + i->m_cfl[1], _708, _709); - i->m_c[2] = i->m_cfl[2] = clamp(i->m_cvel[2] * dt + i->m_cfl[2], _708, _709); - i->m_c[3] = i->m_cfl[3] = clamp(i->m_cvel[3] * dt + i->m_cfl[3], _708, _709); - i->m_size += i->m_sizeVel * dt; - i->m_lifetime -= age; - - i = i->m_next; - } - } -} - -void xParGroupAddParP(xParGroup* ps, xPar* p) -{ - ps->m_alive = 1; - ps->m_num_of_particles++; - - p->m_prev = NULL; - p->m_next = NULL; - - if (ps->m_root) - { - p->m_next = ps->m_root; - ps->m_root->m_prev = p; - ps->m_root = p; - } - else - { - ps->m_root = p; - } -} - -xPar* xParGroupAddPar(xParGroup* ps) -{ - xPar* p; - - if (ps->m_flags & XPARGROUP_ALLOCPARS) - { - p = xParAlloc(); - - if (!p) - { - S32 myPriority = ps->m_priority; - - for (U8 i = 0; i < REG_TABLE_SIZE; i++) - { - if (sParGroupRegTable[i] && sParGroupRegTable[i] != ps && - (sParGroupRegTable[i]->m_flags & XPARGROUP_ALLOCPARS) && - !(sParGroupRegTable[i]->m_flags & XPARGROUP_UNK10) && - sParGroupRegTable[i]->m_priority < myPriority && sParGroupRegTable[i]->m_root) - { - xParGroupKillPar(sParGroupRegTable[i], sParGroupRegTable[i]->m_root); - - p = xParAlloc(); - - break; - } - } - } - } - else if (ps->m_dead) - { - p = ps->m_dead; - ps->m_dead = p->m_next; - - if (ps->m_dead) - { - ps->m_dead->m_prev = NULL; - } - } - else - { - p = NULL; - } - - if (p) - { - xParInit(p); - xParGroupAddParP(ps, p); - } - - return p; -} - -void xParGroupKillPar(xParGroup* ps, xPar* p) -{ - if (p == ps->m_root) - { - ps->m_root = p->m_next; - - if (ps->m_root) - { - ps->m_root->m_prev = NULL; - } - - p->m_next = NULL; - p->m_prev = NULL; - } - else - { - if (p->m_next) - { - p->m_next->m_prev = p->m_prev; - } - - if (p->m_prev) - { - p->m_prev->m_next = p->m_next; - } - - p->m_prev = NULL; - p->m_next = NULL; - } - - ps->m_num_of_particles--; - - if (ps->m_flags & XPARGROUP_ALLOCPARS) - { - xParFree(p); - } - else - { - xParGroupAddParToDeadList(ps, p); - } -} - -void xParGroupAddParToDeadList(xParGroup* ps, xPar* p) -{ - if (ps->m_dead) - { - ps->m_dead->m_prev = p; - } - - p->m_next = ps->m_dead; - p->m_prev = NULL; - - ps->m_dead = p; -} diff --git a/src/SB/Core/x/xParMgr.cpp b/src/SB/Core/x/xParMgr.cpp deleted file mode 100644 index 0a5a3f9..0000000 --- a/src/SB/Core/x/xParMgr.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "iParMgr.h" - -#include "xPar.h" -#include "xParMgr.h" - -#include - -volatile static U32 sFrameCount; -static S32 sParMgrInit; - -void xParMgrInit() -{ - if (sParMgrInit == 0) - { - xParMemInit(); - iParMgrInit(); - sParMgrInit = 1; - } - else - { - xParMgrKillAllParticles(); - iParMgrInit(); - } -} - -void xParMgrKillAllParticles() -{ -} - -void xParMgrUpdate(F32 elapsedTime) -{ - iParMgrUpdate(elapsedTime); - - sFrameCount++; - - if (sFrameCount > 10) - { - sFrameCount = 1; - } - - U32 i; - for (i = sFrameCount; i >= 1; i--); - sFrameCount = i; -} - -void xParMgrRender() -{ - iParMgrRender(); -} diff --git a/src/SB/Core/x/xParSys.cpp b/src/SB/Core/x/xParSys.cpp deleted file mode 100644 index f53a8f3..0000000 --- a/src/SB/Core/x/xParSys.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "xParSys.h" - -#include diff --git a/src/SB/Core/x/xPartition.cpp b/src/SB/Core/x/xPartition.cpp deleted file mode 100644 index 8d7f412..0000000 --- a/src/SB/Core/x/xPartition.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "xPartition.h" -#include "xMemMgr.h" -#include - -void xPartitionReset() -{ -} - -_tagPartLink* PartitionGetFreeLink() -{ - return (_tagPartLink*)xMemAllocSize(sizeof(_tagPartLink)); -} - -void PartitionSpaceReset(_tagPartSpace* space) -{ - memset(space, 0, sizeof(_tagPartSpace)); -} - -void PartitionSpaceInsert(_tagPartSpace* space, void* data) -{ - space->total++; - _tagPartLink* head = &space->head; - _tagPartLink* tmp = head; - while (tmp->next != NULL) - { - tmp = tmp->next; - } - head = PartitionGetFreeLink(); - tmp->next = head; - tmp->next->data = data; - tmp->next->next = NULL; -} - -// Need to figure out the correct order. -S32 xPartitionGetTrueIdx(_tagPartition* part, S32 x_spaces, S32 y_spaces, S32 z_spaces) -{ - return part->total_x * z_spaces + part->total_x * y_spaces * part->total_z + x_spaces; -} - -void xPartitionDump(_tagPartition*, char*) -{ -} diff --git a/src/SB/Core/x/xPtankPool.cpp b/src/SB/Core/x/xPtankPool.cpp deleted file mode 100644 index df352bb..0000000 --- a/src/SB/Core/x/xPtankPool.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "xPtankPool.h" - -#include diff --git a/src/SB/Core/x/xQuickCull.cpp b/src/SB/Core/x/xQuickCull.cpp deleted file mode 100644 index 8feb55c..0000000 --- a/src/SB/Core/x/xQuickCull.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "xQuickCull.h" - -#include - -void xQuickCullInit(xQCControl* ctrl, F32 xmin, F32 ymin, F32 zmin, F32 xmax, F32 ymax, F32 zmax) -{ - ctrl->world_xmin = xmin; - ctrl->world_ymin = ymin; - ctrl->world_zmin = zmin; - ctrl->world_xmax = xmax; - ctrl->world_ymax = ymax; - ctrl->world_zmax = zmax; - ctrl->world_xsz = xmax - xmin; - ctrl->world_ysz = ymax - ymin; - ctrl->world_zsz = zmax - zmin; - if (((ctrl->world_xsz <= 0.0f) || (ctrl->world_ysz <= 0.0f)) || (ctrl->world_zsz <= 0.0f)) - { - ctrl->world_zsz = 1.0f; - ctrl->world_ysz = 1.0f; - ctrl->world_xsz = 1.0f; - } - ctrl->scale_x = 127.0f / ctrl->world_xsz; - ctrl->scale_y = 127.0f / ctrl->world_ysz; - ctrl->scale_z = 127.0f / ctrl->world_zsz; - ctrl->center_x = 0.5f * (xmax + xmin) + 0.5f / ctrl->scale_x; - ctrl->center_y = 0.5f * (ymax + ymin) + 0.5f / ctrl->scale_y; - ctrl->center_z = 0.5f * (zmax + zmin) + 0.5f / ctrl->scale_z; -} - -void xQuickCullInit(xQCControl* ctrl, const xBox* box) -{ - xQuickCullInit(ctrl, box->lower.x, box->lower.y, box->lower.z, box->upper.x, box->upper.y, - box->upper.z); -} - -// WIP. -S32 xQuickCullIsects(const xQCData* a, const xQCData* b) -{ - return a->xmin <= b->xmax && a->ymin <= b->ymax && a->zmin <= b->zmax && b->xmin <= a->xmax && - b->ymin <= a->ymax && b->zmin <= a->zmax; -} diff --git a/src/SB/Core/x/xRMemData.cpp b/src/SB/Core/x/xRMemData.cpp deleted file mode 100644 index 7a748e0..0000000 --- a/src/SB/Core/x/xRMemData.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "xRMemData.h" -#include "xMemMgr.h" - -#include -#include - -void* RyzMemData::operator new(size_t size, S32 amt, RyzMemGrow* growCtxt) -{ - S32 dogrow = true; - if (growCtxt == NULL) - { - dogrow = false; - } - else if (growCtxt->IsEnabled() == 0) - { - dogrow = false; - } - - void* mem; - if (dogrow) - { - mem = xMemGrowAllocSize(size); - } - else - { - mem = xMemAllocSize(size); - } - memset(mem, 0, 4); - return mem; -} - -void RyzMemData::operator delete(void* p) -{ -} - -RyzMemGrow* RyzMemGrow::Init(xBase* growuser) -{ - char* dat; - if (this->ptr != NULL) - { - return this; - } - this->amt_last = 0; - this->ptr_last = NULL; - this->user_last = NULL; - this->amt = 0x20; - dat = (char*)xMemAllocSize(this->amt); - this->ptr = dat; - this->user = growuser; - this->flg_grow = 1; - return this; -} - -RyzMemGrow* RyzMemGrow::Resume(xBase*) -{ - this->amt = this->amt_last; - this->ptr = this->ptr_last; - this->user = this->user_last; - this->flg_grow = 0b11; - return this; -} - -void RyzMemGrow::Done() -{ - this->amt_last = this->amt; - this->ptr_last = this->ptr; - this->user_last = this->user; - this->amt = 0; - this->ptr = NULL; - this->user = NULL; - this->flg_grow = 0; -} diff --git a/src/SB/Core/x/xRenderState.cpp b/src/SB/Core/x/xRenderState.cpp deleted file mode 100644 index 4a17ae2..0000000 --- a/src/SB/Core/x/xRenderState.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "xRenderState.h" - -static int sBlendTable[11] = -{ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 -}; - -void xRenderStateSetTexture(RwTexture* texture) -{ - if (texture != NULL) - { - if (texture->raster != NULL) - { - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)texture->raster); - } - } - else - { - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)NULL); - } -} - -void xRenderStateSetSrcBlendMode(int xmode) -{ - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)sBlendTable[xmode]); -} - -void xRenderStateSetDstBlendMode(int xmode) -{ - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)sBlendTable[xmode]); -} \ No newline at end of file diff --git a/src/SB/Core/x/xSFX.cpp b/src/SB/Core/x/xSFX.cpp deleted file mode 100644 index acf1e0a..0000000 --- a/src/SB/Core/x/xSFX.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "xSFX.h" - -#include "xSnd.h" -#include "xEvent.h" - -#include -#include - -extern xSFX* s_managedEnvSFX[1]; - -void xSFXEnvironmentalStreamSceneExit(void) -{ - memset(&s_managedEnvSFX, 0, 4); -} - -S32 xSFXWillSendDone(xSFX* param_1) -{ - S32 iLink = param_1->linkCount; - - if ((U32)iLink != 0) - { - xLinkAsset* pLink = param_1->link; - - for (; iLink > 0; iLink--) - { - if (pLink->srcEvent == 0xbf) - { - return 1; - } - pLink++; - } - } - - return 0; -} - -void xSFXInit(void* t, void* asset) - -{ - xSFXInit((xSFX*)t, (xSFXAsset*)asset); -} - -void xSFXInit(xSFX* t, xSFXAsset* asset) -{ - xBaseInit(t, asset); - - // S32 xSFXEventCB(xBase* to, xBase* from, U32 toEvent, const F32* toParam, xBase*) - t->eventFunc = &xSFXEventCB; - t->asset = asset; - - if (t->linkCount) - { - t->link = (xLinkAsset*)(t->asset + 1); - } - else - { - t->link = 0; - } - if (xSFXWillSendDone(t)) - { - asset->flagsSFX = asset->flagsSFX | 0x800; - } - t->sndID = 0; - t->asset->flagsSFX = t->asset->flagsSFX & 0xefff; - t->cachedOuterDistSquared = (t->asset->outerRadius * t->asset->outerRadius); -} - -void xSFXSave(xSFX* ent, xSerial* s) -{ - xBaseSave(ent, s); -} - -void xSFXLoad(xSFX* ent, xSerial* s) -{ - xBaseLoad(ent, s); -} - -void xSFXReset(xSFX* param_1) -{ - xBaseReset(param_1, param_1->asset); -} - -U32 xSFXConvertFlags(U32 param_1) -{ - return param_1 & 4 ? 0 : 0x800; -} - -void xSFXUpdate(xSFX* param_1) -{ - if ((param_1->asset->flagsSFX & 0x800) && (param_1->sndID) && - (!xSndIDIsPlaying(param_1->sndID))) - { - param_1->sndID = 0; - param_1->asset->flagsSFX = param_1->asset->flagsSFX & 0xefff; - zEntEvent(param_1, param_1, 0xbf); - } -} - -void xSFXStop(xSFX* param_1) -{ - xSndStop(param_1->sndID); - param_1->sndID = 0; -} diff --git a/src/SB/Core/x/xScene.cpp b/src/SB/Core/x/xScene.cpp deleted file mode 100644 index e2b6655..0000000 --- a/src/SB/Core/x/xScene.cpp +++ /dev/null @@ -1,433 +0,0 @@ -#include "xScene.h" - -#include "xMemMgr.h" -#include "xCollideFast.h" -#include "xMath.h" - -#include "iMath.h" -#include "iCollide.h" -#include "zBase.h" - -#include -#include -#include - -#include - -extern F32 lbl_803CCF78; - -namespace -{ - struct cb_ray_hits_ent - { - const xRay3& ray; - xCollis& coll; - U8 chkby; - U8 collType; - - cb_ray_hits_ent(const xRay3& ray, xCollis& coll, U8 chkby, U8 collType); - bool operator()(xEnt& ent, xGridBound& gridb); - }; -} // namespace - -void xSceneInit(xScene* sc, U16 num_trigs, U16 num_stats, U16 num_dyns, U16 num_npcs) -{ - sc->flags = 0; - sc->num_trigs_allocd = num_trigs; - sc->trigs = (xEnt**)xMemAllocSize(num_trigs * sizeof(xEnt*)); - sc->num_stats_allocd = num_stats; - sc->stats = (xEnt**)xMemAllocSize(num_stats * sizeof(xEnt*)); - sc->num_dyns_allocd = num_dyns; - sc->dyns = (xEnt**)xMemAllocSize(num_dyns * sizeof(xEnt*)); - sc->num_npcs_allocd = num_npcs; - sc->npcs = (xEnt**)xMemAllocSize(num_npcs * sizeof(xEnt*)); - sc->num_ents_allocd = (U32)num_trigs + (U32)num_stats + (U32)num_dyns + (U32)num_npcs; - sc->num_act_ents = 0; - sc->act_ents = (xEnt**)xMemAllocSize(sc->num_ents_allocd * sizeof(xEnt*)); - sc->num_nact_ents = 0; - sc->nact_ents = (xEnt**)xMemAllocSize(sc->num_ents_allocd * sizeof(xEnt*)); - sc->num_ents = 0; - sc->num_trigs = 0; - sc->num_stats = 0; - sc->num_dyns = 0; - sc->num_npcs = 0; - sc->resolvID = NULL; - - xAnimInit(); - xModelInit(); - xAnimPoolInit(&sc->mempool, 50, 1, 0x1, 4); - xModelPoolInit(49, 64); - xModelPoolInit(74, 8); - xModelPoolInit(164, 1); - xAnimTempTransitionInit(16); - xCollideInit(sc); - xCollideFastInit(sc); -} - -void xSceneExit(xScene* sc) -{ -} - -void xSceneSave(xScene* sc, xSerial* s) -{ -} - -void xSceneLoad(xScene* sc, xSerial* s) -{ -} - -void xSceneSetup(xScene* sc) -{ - xEnvSetup(sc->env); -} - -void xSceneAddEnt(xScene* sc, xEnt* ent) -{ - if (ent->collType == XENT_COLLTYPE_TRIG) - { - sc->trigs[sc->num_trigs++] = ent; - } - else if (ent->collType == XENT_COLLTYPE_STAT) - { - sc->stats[sc->num_stats++] = ent; - } - else if (ent->collType == XENT_COLLTYPE_DYN) - { - sc->dyns[sc->num_dyns++] = ent; - } - else if (ent->collType == XENT_COLLTYPE_NPC) - { - sc->npcs[sc->num_npcs++] = ent; - } - - sc->act_ents[sc->num_act_ents++] = ent; -} - -xBase* xSceneResolvID(xScene* sc, U32 id) -{ - if (sc->resolvID) - { - return sc->resolvID(id); - } - - return NULL; -} - -const char* xSceneID2Name(xScene* sc, U32 id) -{ - if (sc->id2Name) - { - return sc->id2Name(id); - } - - return NULL; -} - -void xSceneForAllEnts(xScene* sc, xSceneEntCallback func, void* data) -{ - for (U16 i = 0; i < sc->num_act_ents; i++) - { - if (!func(sc->act_ents[i], sc, data)) - { - break; - } - } -} - -void xSceneForAllStatics(xScene* sc, xSceneEntCallback func, void* data) -{ - for (U16 i = 0; i < sc->num_stats; i++) - { - if (!func(sc->stats[i], sc, data)) - { - break; - } - } -} - -void xSceneForAllDynamics(xScene* sc, xSceneEntCallback func, void* data) -{ - for (U16 i = 0; i < sc->num_dyns; i++) - { - if (!func(sc->dyns[i], sc, data)) - { - break; - } - } -} - -void xSceneForAllNPCs(xScene* sc, xSceneEntCallback func, void* data) -{ - for (U16 i = 0; i < sc->num_npcs; i++) - { - if (!func(sc->npcs[i], sc, data)) - { - break; - } - } -} - -void xRayHitsTikiLandableEnt(xScene* sc, xRay3* r, xQCData* qcr, xEnt* ent, void* colldata) -{ - xCollis* coll = (xCollis*)colldata; - xCollis c; - - if (ent->chkby == XENT_COLLTYPE_NONE) - { - return; - } - - if (ent->collType == XENT_COLLTYPE_NPC) - { - return; - } - - if (ent->baseType == eBaseTypeBoulder) - { - return; - } - - if (qcr && !xQuickCullIsects(qcr, &ent->bound.qcd)) - { - return; - } - - xRayHitsBound(r, &ent->bound, &c); - - if (!(c.flags & 0x1)) - { - return; - } - - if (ent->collLev == 0x5) - { - iRayHitsModel(r, ent->model, &c); - - if (!(c.flags & 0x1)) - { - return; - } - } - - if (c.dist < coll->dist) - { - coll->dist = c.dist; - coll->oid = ent->id; - coll->optr = ent; - coll->mptr = ent->model; - } -} - -void xRayHitsEnt(xScene* sc, xRay3* r, xQCData* qcr, xEnt* ent, void* colldata) -{ - xCollis* coll = (xCollis*)colldata; - xCollis c; - - if (ent->chkby == XENT_COLLTYPE_NONE) - { - return; - } - - if (qcr && !xQuickCullIsects(qcr, &ent->bound.qcd)) - { - return; - } - - xRayHitsBound(r, &ent->bound, &c); - - if (!(c.flags & 0x1)) - { - return; - } - - if (c.dist < coll->dist) - { - coll->dist = c.dist; - coll->oid = ent->id; - coll->optr = ent; - coll->mptr = ent->model; - } -} - -cb_ray_hits_ent::cb_ray_hits_ent(const xRay3& ray, xCollis& coll, U8 chkby, U8 collType) - : ray(ray), coll(coll), chkby(chkby), collType(collType) -{ -} - -void ProjectTriangle(xVec3* param_1, xVec3* param_2, float* param_3, float* param_4) -{ - float fVar1; - - *param_3 = param_1->x * param_2->x + param_1->y * param_2->y + param_1->z * param_2->z; - *param_4 = *param_3; - fVar1 = param_1->x * param_2[1].x + param_1->y * param_2[1].y + param_1->z * param_2[1].z; - if (fVar1 < *param_3) - { - *param_3 = fVar1; - } - else - { - if (fVar1 > *param_4) - { - *param_4 = fVar1; - } - } - fVar1 = param_1->x * param_2[2].x + param_1->y * param_2[2].y + param_1->z * param_2[2].z; - if (fVar1 < *param_3) - { - *param_3 = fVar1; - return; - } - if (fVar1 > *param_4) - { - *param_4 = fVar1; - } - return; -} - -void ProjectBox(xVec3* param_1, xBox* param_2, float* param_3, float* param_4) -{ - F32 fVar7 = lbl_803CCF78 * (param_1->x * ((param_2->upper).x + (param_2->lower).x) + - param_1->y * ((param_2->upper).y + (param_2->lower).y) + - param_1->z * ((param_2->upper).z + (param_2->lower).z)); - F32 fVar1 = lbl_803CCF78 * (iabs(param_1->x * ((param_2->upper).x - (param_2->lower).x)) + - iabs(param_1->y * ((param_2->upper).y - (param_2->lower).y)) + - iabs(param_1->z * ((param_2->upper).z - (param_2->lower).z))); - *param_3 = fVar7 - fVar1; - *param_4 = fVar7 + fVar1; -} - -static RpCollisionTriangle* nearestFloorCB(RpIntersection*, RpCollisionTriangle* collTriangle, F32, - void* data); - -static RpCollisionTriangle* sectorNearestFloorCB(RpIntersection* intersection, RpWorldSector*, - RpCollisionTriangle* collTriangle, F32 distance, - void* data) -{ - return nearestFloorCB(intersection, collTriangle, distance, data); -} - -bool cb_ray_hits_ent::operator()(xEnt& ent, xGridBound& gridb) -{ - xCollis c; - - if (!(ent.chkby & chkby)) - { - return true; - } - - if (!(ent.collType & collType)) - { - return true; - } - - c.flags = coll.flags; - - xRayHitsBound(&ray, &ent.bound, &c); - - if (!(c.flags & 0x1)) - { - return true; - } - - if (c.dist > coll.dist) - { - return true; - } - - if (ent.collLev == 0x5) - { - iRayHitsModel(&ray, ent.model, &c); - - if (!(c.flags & 0x1)) - { - return true; - } - - if (c.dist > coll.dist) - { - return true; - } - } - - memcpy(&coll, &c, sizeof(xCollis)); - - coll.oid = ent.id; - coll.optr = &ent; - coll.mptr = ent.model; - - return true; -} - -void xEntEnable(xEnt* ent) -{ - xBaseEnable(ent); -} - -template <> U16 range_limit(U16 v, U16 minv, U16 maxv) -{ - if (v <= minv) - { - return minv; - } - - if (v >= maxv) - { - return maxv; - } - - return v; -} - -void xBoxFromRay(xBox& box, const xRay3& ray) -{ - xLine3 line; - - if (ray.flags & 0x400) - { - F32 x = ray.dir.x * ray.min_t; - F32 y = ray.dir.y * ray.min_t; - F32 z = ray.dir.z * ray.min_t; - - line.p1.x = ray.origin.x + x; - line.p1.y = ray.origin.y + y; - line.p1.z = ray.origin.z + z; - } - else - { - line.p1.x = ray.origin.x; - line.p1.y = ray.origin.y; - line.p1.z = ray.origin.z; - } - - if (ray.flags & 0x800) - { - F32 dist = (ray.flags & 0x400) ? ray.max_t - ray.min_t : ray.max_t; - - line.p2.x = ray.dir.x * dist; - line.p2.y = ray.dir.y * dist; - line.p2.z = ray.dir.z * dist; - } - else - { - line.p2.x = ray.dir.x; - line.p2.y = ray.dir.y; - line.p2.z = ray.dir.z; - } - - line.p2.x = line.p1.x + line.p2.x; - line.p2.y = line.p1.y + line.p2.y; - line.p2.z = line.p1.z + line.p2.z; - - xBoxFromLine(box, line); -} - -void xBoxFromLine(xBox& box, const xLine3& line) -{ - box.upper.x = MAX(line.p1.x, line.p2.x); - box.upper.y = MAX(line.p1.y, line.p2.y); - box.upper.z = MAX(line.p1.z, line.p2.z); - box.lower.x = MIN(line.p1.x, line.p2.x); - box.lower.y = MIN(line.p1.y, line.p2.y); - box.lower.z = MIN(line.p1.z, line.p2.z); -} diff --git a/src/SB/Core/x/xScrFx.cpp b/src/SB/Core/x/xScrFx.cpp deleted file mode 100644 index deb1139..0000000 --- a/src/SB/Core/x/xScrFx.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "xScrFx.h" - -#include - -void xScrFxDistortionAdd(xVec3*, xVec3*, S32) -{ -} - -void xScrFxDistortionRender(RwCamera*) -{ -} diff --git a/src/SB/Core/x/xShadow.cpp b/src/SB/Core/x/xShadow.cpp deleted file mode 100644 index 455668d..0000000 --- a/src/SB/Core/x/xShadow.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#include "xShadow.h" - -#include "rpworld.h" - -#include "xMath.h" -#include "iModel.h" -#include "zGlobals.h" - -#include - -RwRGBAReal ShadowLightColor = { 1.0f, 1.0f, 1.0f, 1.0f }; - -RpLight* ShadowLight; -static F32 SHADOW_BOTH; -RwCamera* ShadowCamera; -RwRaster* ShadowCameraRaster; -static RwRaster* ShadowRenderRaster; -F32 gShadowObjectRadius; -static S32 shadow_ent_count; -static RwRaster* gc_saveraster; -static xShadowMgr* sMgrList; -static S32 sMgrCount; -static S32 sMgrTotal; - -void xShadowInit(); -static void ShadowCameraDestroy(RwCamera* shadowCamera); -static S32 SetupShadow(); -static RwRaster* ShadowRasterCreate(S32 res); -static RwCamera* ShadowCameraCreatePersp(S32 param); -U32 xShadowCameraCreate(); -void xShadowRenderWorld(xVec3* a, F32 b, F32 c); -void xShadow_ListAdd(xEnt* ent); -void xShadowManager_Add(xEnt* ent); -static void GCSaveFrameBuffer(); -RwCamera* ShadowCameraSetSpherePersp(RwCamera* camera, RwV3d* center, float radius); -int Im2DRenderQuad(float x1, float y1, float x2, float y2, float z, float recipCamZ, float uvOffset); - -/* Three more params than in DWARF. -RwCamera* ShadowCameraUpdate(RwCamera* shadowCamera, void* model, void(*renderCB)(void*)) -*/ -RwCamera* ShadowCameraUpdate(RwCamera* shadowCamera, void* model, void(*renderCB)(void*), RwV3d* center, float radius, int); - -void xShadowInit() -{ - xShadowCameraCreate(); - gc_saveraster = RwRasterCreate(256, 256, 32, 0x504); - shadow_ent_count = 0; - ShadowLight = RpLightCreate(1); - RpLightSetColor(ShadowLight, &ShadowLightColor); - RwFrame* frame = RwFrameCreate(); - _rwObjectHasFrameSetFrame(ShadowLight, frame); -} - -void xShadowRender(xVec3* a, F32 b, F32 c) -{ - xShadowRenderWorld(a, b, c); -} - -static S32 SetupShadow() -{ - S32 res = 256; - - // Continuously halve res until it is less than or - // equal to either display width or height. - // On GCN, this routine normally won't happen, - // as we're already below both dimensions. - for (; (res > 640) || (res > 480); res >>= 1); - - ShadowCamera = ShadowCameraCreatePersp(res); - if (ShadowCamera == NULL) - { - return 0; - } - ShadowCameraRaster = ShadowRasterCreate(res); - if (ShadowCameraRaster == NULL) - { - return 0; - } - ShadowCamera->frameBuffer = ShadowCameraRaster; - return 1; -} - -void xShadowSetWorld(RpWorld* world) -{ - RpWorldAddCamera(world, ShadowCamera); - SHADOW_BOTH = 2.0f; -} - -U32 xShadowCameraCreate() -{ - U32 setup = SetupShadow(); - return ((-setup | setup) >> 0x1f); -} - -void xShadowCameraUpdate(void* model, void(*renderCB)(void*), xVec3* center, float radius, int shadowMode) -{ - ShadowCameraSetSpherePersp(ShadowCamera, (RwV3d*)center, radius); - ShadowCameraUpdate(ShadowCamera, model, renderCB, (RwV3d*)center, radius, shadowMode); - ShadowRenderRaster = ShadowCameraRaster; -} - -static void modelRenderCB(void* param) -{ - xModelRender((xModelInstance*)param); -} - -S32 xShadowReceiveShadowSetup(xEnt* ent) -{ - if - ( - (ent->model != NULL) && - (xEntIsVisible(ent)) && - (ent->baseFlags & 0x10) && - (!iModelCull(ent->model->Data, ent->model->Mat)) - ) - { - return 1; - } - return 0; -} - -void xShadow_ListAdd(xEnt* ent) -{ - xShadowManager_Add(ent); -} - -void ShadowCameraDestroy(RwCamera* shadowCamera) -{ - if (shadowCamera == NULL) - { - return; - } - - _rwFrameSyncDirty(); - RwFrame* parent = (RwFrame*)shadowCamera->object.object.parent; - if (parent != NULL) - { - _rwObjectHasFrameSetFrame(shadowCamera, NULL); - RwFrameDestroy(parent); - } - - // Scheduling issue with RwRasterDestroy calls - - if (shadowCamera->zBuffer != NULL) - { - RwRasterDestroy(shadowCamera->zBuffer); - shadowCamera->zBuffer = NULL; - } - - if (shadowCamera->frameBuffer != NULL) - { - RwRasterDestroy(shadowCamera->frameBuffer); - shadowCamera->frameBuffer = NULL; - } - - RwCameraDestroy(shadowCamera); -} - -static RwRaster* ShadowRasterCreate(S32 res) -{ - return RwRasterCreate(res, res, 0, 5); -} - -void GCSaveFrameBuffer() -{ - RwGameCubeCameraTextureFlush(gc_saveraster, 0); -} - -static void GCRestoreFrameBuffer() -{ - RwCamera* cam = *(RwCamera**)RwEngineInstance; - F32 recipCamZ = (1.0f / cam->farPlane); - - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)2); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)1); - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)0); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)0); - RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)1); - RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gc_saveraster); - - Im2DRenderQuad(0.0f, 0.0f, 256.0f, 256.0f, RwIm2DGetFarScreenZ(), recipCamZ, 0.001953125f); - - RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)1); - RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1); - RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5); - RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6); -} - -static RwCamera* ShadowCameraCreatePersp(S32 param) -{ - RwCamera* cam = RwCameraCreate(); - if (cam != NULL) - { - _rwObjectHasFrameSetFrame(cam, RwFrameCreate()); - - RwV2d viewWin; - viewWin.x = DEG2RAD(10); - viewWin.y = DEG2RAD(10); - - RwCameraSetViewWindow(cam, &viewWin); - - if (cam->object.object.parent != NULL) - { - RwRaster* raster = RwRasterCreate(param, param, 0, 1); - if (raster != NULL) - { - cam->zBuffer = raster; - return cam; - } - } - } - ShadowCameraDestroy(cam); - return NULL; -} - -void xShadowManager_Init(S32 numEnts) -{ - sMgrList = (xShadowMgr*)xMemAlloc(gActiveHeap, numEnts << 4, 0); - sMgrTotal = numEnts; - sMgrCount = 0; // Scheduling off -} - -void xShadowManager_Reset() -{ - sMgrCount = 0; -} - -void xShadowManager_Add(xEnt* ent) -{ - for (int i = 0; i < sMgrCount; i++) - { - if (sMgrList[i].ent == ent) - { - return; - } - } - - if (sMgrCount < sMgrTotal) - { - sMgrList[sMgrCount].ent = ent; - sMgrList[sMgrCount].cache = 0; - sMgrList[sMgrCount].priority = 1000; - sMgrList[sMgrCount].cacheReady = 0; - sMgrCount++; - } -} - -void xShadowManager_Remove(xEnt* ent) -{ - int a = 0; - for (int i = 6; i < sMgrCount; i++) - { - sMgrList[i].cache = NULL; - a++; - } - - a = 0; - int i = 0; - while (a < sMgrCount) - { - if (ent == sMgrList[i].ent) - { - sMgrList[i] = sMgrList[sMgrCount - 1]; - sMgrCount--; - } - else - { - i++; - a++; - } - } -} diff --git a/src/SB/Core/x/xShadowSimple.cpp b/src/SB/Core/x/xShadowSimple.cpp deleted file mode 100644 index d18cb5f..0000000 --- a/src/SB/Core/x/xShadowSimple.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "xShadowSimple.h" - -#include diff --git a/src/SB/Core/x/xSkyDome.cpp b/src/SB/Core/x/xSkyDome.cpp deleted file mode 100644 index f8106c3..0000000 --- a/src/SB/Core/x/xSkyDome.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "xSkyDome.h" - -#include "xEvent.h" -#include "iModel.h" - -struct SkyDomeInfo -{ - xEnt* ent; - S32 sortorder; - S32 lockY; -}; - -static SkyDomeInfo sSkyList[8]; -static S32 sSkyCount; - -void xSkyDome_EmptyRender(xEnt*) -{ -} - -void xSkyDome_Setup() -{ - sSkyCount = 0; -} - -void xSkyDome_AddEntity(xEnt* ent, S32 sortorder, S32 lockY) -{ - S32 i, j; - - for (i = 0; i > sSkyCount; i++) - { - if (sSkyList[i].ent == ent) - { - return; - } - } - - for (i = 0; i < sSkyCount; i++) - { - if (sortorder < sSkyList[i].sortorder) - { - break; - } - } - - for (j = sSkyCount - 1; j >= i; j--) - { - sSkyList[j + 1] = sSkyList[j]; - } - - // non-matching: instruction order - - sSkyList[i].ent = ent; - sSkyList[i].sortorder = sortorder; - sSkyList[i].lockY = lockY; - - sSkyCount++; - - ent->render = xSkyDome_EmptyRender; - ent->model->Flags &= (U16)~0x1; - ent->baseFlags &= (U16)~0x10; - - zEntEvent(ent, eEventCollisionOff); - zEntEvent(ent, eEventCameraCollideOff); -} - -void xSkyDome_Render() -{ - RwMatrix* cammat = RwFrameGetMatrix(RwCameraGetFrame(RwCameraGetCurrentCamera())); - S32 i; - xEnt* ent; - - for (i = 0; i < sSkyCount; i++) - { - ent = sSkyList[i].ent; - - ent->render = xSkyDome_EmptyRender; - ent->model->Flags &= (U16)~0x1; - - if (ent->model && xEntIsVisible(ent)) - { - RwV3d pos; - - pos = ent->model->Mat->pos; - - ent->model->Mat->pos.x = cammat->pos.x; - ent->model->Mat->pos.z = cammat->pos.z; - - if (sSkyList[i].lockY) - { - ent->model->Mat->pos.y = cammat->pos.y; - } - - if (!iModelCull(ent->model->Data, ent->model->Mat)) - { - iModelRender(ent->model->Data, ent->model->Mat); - } - - ent->model->Mat->pos = pos; - } - } -} diff --git a/src/SB/Core/x/xSnd.cpp b/src/SB/Core/x/xSnd.cpp deleted file mode 100644 index 44db850..0000000 --- a/src/SB/Core/x/xSnd.cpp +++ /dev/null @@ -1,444 +0,0 @@ -#include "xSnd.h" - -#include - -#include "iSnd.h" -#include "xVec3.h" - -extern _xSndDelayed sDelayedSnd[16]; -extern U32 sDelayedPaused; - -extern F32 sTimeElapsed; -extern F32 _585; -extern F32 _586; -extern F32 _598; -extern F32 _599; -extern xSndGlobals gSnd; - -static S32 faders_active; - -void xSndInit() -{ - iSndInit(); - xSndVoiceInfo* voice = gSnd.voice; - for (S32 i = 0; i < 64; i++, voice++) - { - voice->flags = 0; - voice->lock_owner = 0; - } - - xSndSceneInit(); - - //Need this to only use f0 instead of f1 for _585 - for (int i = 0; i < 5; i++) - { - gSnd.categoryVolFader[i] = _585; - } - - gSnd.categoryVolFader[2] = _586; - - gSnd.stereo = 1; - iSndSuspendCD(1); - xSndDelayedInit(); - reset_faders(); -} - -void xSndSceneInit() -{ - gSnd.listenerMode = SND_LISTENER_MODE_PLAYER; - for (U32 i = 0; i < 2; i++) - { - gSnd.listenerMat[i].at.assign(_585, _598, _598); - gSnd.listenerMat[i].right.assign(_598, _585, _598); - gSnd.listenerMat[i].up.assign(_598, _598, _585); - gSnd.listenerMat[i].pos.assign(_599, _599, _599); - } - gSnd.at.assign(_585, _598, _598); - gSnd.right.assign(_598, _585, _598); - gSnd.up.assign(_598, _598, _585); - gSnd.pos.assign(_599, _599, _599); - iSndUpdate(); -} - -void xSndSetEnvironmentalEffect(sound_effect effectType) -{ - switch (effectType) - { - case SND_EFFECT_NONE: - iSndSetEnvironmentalEffect(iSND_EFFECT_NONE); - break; - case SND_EFFECT_CAVE: - iSndSetEnvironmentalEffect(iSND_EFFECT_CAVE); - break; - default: - break; - } -} - -void xSndSuspend() -{ - xSndPauseAll(1, 1); - sDelayedPaused = 1; - xSndUpdate(); -} - -void xSndResume() -{ - xSndPauseAll(0, 0); - sDelayedPaused = 0; -} - -void xSndPauseAll(U32 pause_effects, U32 pause_streams) -{ - sDelayedPaused = pause_effects; - - for (U32 i = 0; i < 0x40; i++) - { - if (gSnd.voice[i].flags & 1) - { - if (gSnd.voice[i].flags & 2) - { - iSndPause(gSnd.voice[i].sndID, pause_effects); - } - else if (gSnd.voice[i].flags & 4) - { - iSndPause(gSnd.voice[i].sndID, pause_streams); - } - } - } -} - -void xSndPauseCategory(U32 mask, U32 pause) -{ - for (U32 i = 0; i < 0x40; i++) - { - if ((gSnd.voice[i].flags & 1) && (mask & 1 << gSnd.voice[i].category)) - { - iSndPause(gSnd.voice[i].sndID, pause); - } - } -} - -void xSndStopAll(U32 mask) -{ - for (U32 i = 0; i < 0x40; i++) - { - if ((gSnd.voice[i].flags & 1) && (mask & 1 << gSnd.voice[i].category)) - { - iSndStop(gSnd.voice[i].sndID); - } - } - xSndDelayedInit(); -} - -void xSndSetCategoryVol(sound_category category, F32 vol) -{ - gSnd.categoryVolFader[category] = vol; -} - -void xSndDelayedInit() -{ - for (int i = 0; i < 16; i++) - { - //Alternates between f1 and f0 - sDelayedSnd[i].delay = *(volatile F32*)&_598; - } - sDelayedPaused = 0; -} - -void xSndAddDelayed(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, U32 parentID, xEnt* parentEnt, xVec3* pos, F32 innerRadius, F32 outerRadius, sound_category category, F32 delay) -{ - _xSndDelayed* snd = &sDelayedSnd[0]; - - for (U32 i = 0x10; i != 0; i--) - { - if (snd->delay <= 0.0f) - { - snd->id = id; - snd->vol = vol; - snd->pitch = pitch; - snd->priority = priority; - snd->flags = flags; - snd->parentID = parentID; - snd->parentEnt = parentEnt; - snd->pos = pos; - snd->innerRadius = innerRadius; - snd->outerRadius = outerRadius; - snd->category = category; - snd->delay = delay; - return; - } - snd++; - } -} - -void xSndCalculateListenerPosition() -{ - xMat4x3* pMat; - - switch (gSnd.listenerMode) - { - case SND_LISTENER_MODE_PLAYER: - pMat = &gSnd.listenerMat[0]; - gSnd.right = pMat->right; - gSnd.up = pMat->up; - gSnd.at = pMat->at; - gSnd.pos = gSnd.listenerMat[1].pos; - gSnd.pos.y += _585; - break; - case SND_LISTENER_MODE_CAMERA: - pMat = &gSnd.listenerMat[0]; - gSnd.right = pMat->right; - gSnd.up = pMat->up; - gSnd.at = pMat->at; - gSnd.pos = gSnd.listenerMat[0].pos; - break; - default: - break; - } -} - -void xSndInternalUpdateVoicePos(xSndVoiceInfo* pVoice) -{ - if ((pVoice->flags & 1) && (pVoice->flags & 8)) - { - if (pVoice->flags & 0x10) - { - if (pVoice->parentPos != NULL) - { - pVoice->actualPos = *pVoice->parentPos; - } - else if (pVoice->parentID != 0) - { - xEnt* ent = (xEnt*)(pVoice->parentID & 0xfffffffc); // uhh... - if (pVoice->flags & 0x800) - { - pVoice->actualPos = *(xVec3*)(ent); - } - else if (ent->baseFlags & 1) - { - xVec3Copy(&pVoice->actualPos, xEntGetPos(ent)); - } - else - { - pVoice->flags &= 0xffffffef; - } - } - else if (!(pVoice->flags & 8)) - { - pVoice->actualPos = gSnd.pos; - } - } - xSndProcessSoundPos(&pVoice->actualPos, &pVoice->playPos); - } -} - -void xSndUpdate() -{ - xSndCalculateListenerPosition(); - xSndDelayedUpdate(); - update_faders(sTimeElapsed); - iSndUpdate(); -} - -void xSndSetListenerData(sound_listener_type listenerType, const xMat4x3* matrix) -{ - /* - * This code appears to be correct but there appears to be a possibility - * of accessing this array out of bounds. - * It may be possible the dwarf data for sound_listener_type is incorrect - * Otherwise it could be a potential bug - * (Gamecube audio bug source????) - */ - int i = (int)listenerType; - gSnd.listenerMat[i] = *matrix; -} - -void xSndSelectListenerMode(sound_listener_game_mode listenerGameMode) -{ - gSnd.listenerMode = listenerGameMode; -} - -void xSndExit() -{ - iSndExit(); - reset_faders(); -} - -U32 xSndPlay(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, U32 parentID, - sound_category category, F32 delay) -{ - return xSndPlayInternal(id, vol, pitch, priority, flags, parentID, NULL, NULL, _598, _598, - category, delay); -} - -U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, xEnt* parent, F32 innerRadius, - F32 outerRadius, sound_category category, F32 delay) -{ - return xSndPlayInternal(id, vol, pitch, priority, flags, NULL, parent, NULL, innerRadius, - outerRadius, category, delay); -} - -U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, const xVec3* pos, - F32 innerRadius, F32 outerRadius, sound_category category, F32 delay) -{ - if (flags & 0x800) - { - return xSndPlayInternal(id, vol, pitch, priority, flags, NULL, (xEnt*)pos, NULL, - innerRadius, outerRadius, category, delay); - } - else - { - return xSndPlayInternal(id, vol, pitch, priority, flags, NULL, NULL, pos, innerRadius, - outerRadius, category, delay); - } -} - -void xSndStartStereo(U32 id1, U32 id2, F32 pitch) -{ - iSndStartStereo(id1, id2, pitch); -} - -U32 xSndIDIsPlaying(U32 sndID) -{ - xSndVoiceInfo* voice = gSnd.voice; - for (int i = 0; i < 64; i++, voice++) - { - if (voice->flags & 1 && voice->sndID == sndID) - { - return 1; - } - } - return 0; -} - -void xSndStop(U32 snd) -{ - iSndStop(snd); -} - -void xSndParentDied(U32 pid) -{ - xSndVoiceInfo* voice = gSnd.voice; - for (S32 i = 0; i < 64; i++, voice++) - { - if (voice->parentID == pid) - { - voice->flags = voice->flags & 0xffffffef; - } - } -} - -void xSndStopChildren(U32 pid) -{ - U32 i = 0; - xSndVoiceInfo* voice = gSnd.voice; - for (; i < 64; i++, voice++) - { - if ((voice->flags & 1) != 0 && voice->parentID == pid) - { - iSndStop(voice->sndID); - voice->flags = voice->flags & 0xffffffef; - } - } -} - -void xSndSetVol(U32 snd, F32 vol) -{ - iSndSetVol(snd, vol); -} - -void xSndSetPitch(U32 snd, F32 pitch) -{ - iSndSetPitch(snd, pitch); -} - -void xSndSetExternalCallback(void (*callback)(U32)) -{ - iSndSetExternalCallback(callback); -} - -void reset_faders() -{ - faders_active = 0; -} - -class fade_data { - // total size: 0x18 -public: - unsigned char in; // offset 0x0, size 0x1 - unsigned int handle; // offset 0x4, size 0x4 - float start_delay; // offset 0x8, size 0x4 - float time; // offset 0xC, size 0x4 - float end_time; // offset 0x10, size 0x4 - float volume; // offset 0x14, size 0x4 - - void operator=(const fade_data& rhs); -}; - -void fade_data::operator=(const fade_data& rhs) -{ - in = rhs.in; - handle = rhs.handle; - start_delay = rhs.start_delay; - time = rhs.time; - end_time = rhs.end_time; - volume = rhs.volume; -} - -U32 xSndStreamReady(U32 owner) -{ - xSndVoiceInfo* begin = gSnd.voice; - xSndVoiceInfo* end = begin + 6; - - for (xSndVoiceInfo* v = begin; v != end; v++) - { - if (v->lock_owner == owner) - { - if (v->flags & 1) - { - return 0; - } - else - { - return 1; - } - } - } - - return 0; -} - -void xSndStreamUnlock(U32 owner) -{ - xSndVoiceInfo* begin = gSnd.voice; - xSndVoiceInfo* end = begin + 6; - - for (xSndVoiceInfo* v = begin; v != end; v++) - { - if (v->lock_owner == owner) - { - v->lock_owner = 0; - return; - } - } -} - -#if 0 -U32 xSndCategoryGetsEffects(sound_category category) -{ - if (-(1 - category >> 1) + (~category | 1)) - { - return 0; - } - else - { - return 1; - } -} -#endif - -F32 xSndGetVol(U32 snd) -{ - return iSndGetVol(snd); -} diff --git a/src/SB/Core/x/xSnd.h b/src/SB/Core/x/xSnd.h index f494766..1873b48 100644 --- a/src/SB/Core/x/xSnd.h +++ b/src/SB/Core/x/xSnd.h @@ -124,6 +124,7 @@ void xSndInternalUpdateVoicePos(xSndVoiceInfo* voiceInfo); void xSndSetListenerData(sound_listener_type listenerType, const xMat4x3* matrix); void xSndSelectListenerMode(sound_listener_game_mode listenerGameMode); void xSndExit(); +void xSndMgrExit(); U32 xSndPlay(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, U32 parentID, sound_category category, F32 delay); U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, xEnt* parent, F32 innerRadius, diff --git a/src/SB/Core/x/xSpline.cpp b/src/SB/Core/x/xSpline.cpp deleted file mode 100644 index 86fa29b..0000000 --- a/src/SB/Core/x/xSpline.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "xSpline.h" - -#include diff --git a/src/SB/Core/x/xString.cpp b/src/SB/Core/x/xString.cpp deleted file mode 100644 index 9a0bebe..0000000 --- a/src/SB/Core/x/xString.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "xString.h" -#include "xMath.h" - -#include - -U32 xStrHash(const char* str) -{ - U32 hash = 0; - U32 i; - - while (i = *str, i != NULL) - { - hash = (i - (i & (S32)i >> 1 & 0x20) & 0xff) + hash * 0x83; - str++; - } - - return hash; -} - -U32 xStrHash(const char* str, size_t size) -{ - U32 hash = 0; - U32 i = 0; - U32 c; - - while (i < size && (c = *str, c != NULL)) - { - i++; - str++; - hash = (c - (c & (S32)c >> 1 & 0x20) & 0xff) + hash * 0x83; - } - - return hash; -} - -U32 xStrHashCat(U32 prefix, const char* str) -{ - U32 hash; - U32 i; - - while (i = *str, i != NULL) - { - str++; - hash = (i - (i & (S32)i >> 1 & 0x20) & 0xff) + hash * 0x83; - } - - return hash; -} - -char* xStrupr(char* string) -{ - char* p = string; - - while (*p != '\0') - { - *p = (*p >= 'a' && *p <= 'z' ? *p - 32 : *p); - - p++; - } - - return string; -} - -// @unnamed@xString_cpp@::tolower(char) -extern "C" { -U32 tolower__21_esc__2_unnamed_esc__2_xString_cpp_esc__2_Fc(U32 param_1) -{ - return tolower__21_esc__2_unnamed_esc__2_xString_cpp_esc__2_Fi(param_1 & 0xff); -} -} - -// @unnamed@xString_cpp@::tolower(int) -extern "C" { -U32 tolower__21_esc__2_unnamed_esc__2_xString_cpp_esc__2_Fi(U32 param_1) -{ - return param_1 | ((param_1 >> 1) & 32); -} -} - -S32 icompare(const substr& s1, const substr& s2) -{ - U32 len = MIN(s1.size, s2.size); - S32 result = imemcmp(s1.text, s2.text, len); - switch (result) - { - case 0: - if (s1.size == s2.size) - { - result = 0; - } - else - { - result = 1; - if (s1.size < s2.size) - { - result = -1; - } - } - break; - } - return result; -} diff --git a/src/SB/Core/x/xSurface.cpp b/src/SB/Core/x/xSurface.cpp deleted file mode 100644 index 21cdeab..0000000 --- a/src/SB/Core/x/xSurface.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "xSurface.h" -#include "xMemMgr.h" - -#include - -xSurface* surfs; -U16 nsurfs; - -void xSurfaceInit(U16 num_surfs) -{ - nsurfs = num_surfs; - if (num_surfs != 0) - { - surfs = (xSurface*)xMemAllocSize(num_surfs * sizeof(xSurface)); - for (U16 i = 0; i < nsurfs; i++) - { - surfs[i].idx = i; - } - } - else - { - surfs = NULL; - } -} - -// xSurface::operator= and xBase::operator= are placed here at link time, however nothing in -// xSurface.cpp calls them in the final executable. This likely means there was an -// unused/stripped function in xSurface.cpp that called xSurface::operator= (which calls -// xBase::operator=). -// Indeed, it turns out that Ratatouille's ratsgc_d.MAP file lists an unused function directly -// after xSurfaceInit__FUs: xSurfaceInit__FUsPC8xSurface, followed by __as__8xSurfaceFRC8xSurface -// and __as__5xBaseFRC5xBase. So it's safe to assume that this was the function that called -// xSurface::operator=, and it was likely also present in BfBB (sadly we don't have a .map file -// to 100% confirm). -// There's no way to know what code xSurfaceInit__FUsPC8xSurface may have contained other than the -// call to xSurface::operator=, so the following code is just speculation. It doesn't really -// matter what the code is for matching purposes since this function will get stripped out by the -// linker - the purpose is to force the compiler to generate xSurface::operator= here. -void xSurfaceInit(U16 n, const xSurface* ent) -{ - surfs[n] = *ent; -} - -void xSurfaceExit() -{ -} - -void xSurfaceSave(xSurface* ent, xSerial* s) -{ - xBaseSave((xBase*)ent, s); -} - -void xSurfaceLoad(xSurface* ent, xSerial* s) -{ - xBaseLoad((xBase*)ent, s); -} - -void xSurfaceReset(xSurface* ent) -{ -} - -U16 xSurfaceGetNumSurfaces() -{ - return nsurfs; -} - -xSurface* xSurfaceGetByIdx(U16 n) -{ - return surfs != NULL ? &surfs[n] : NULL; -} diff --git a/src/SB/Core/x/xTRC.cpp b/src/SB/Core/x/xTRC.cpp deleted file mode 100644 index a53fa71..0000000 --- a/src/SB/Core/x/xTRC.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "xTRC.h" -#include "xSnd.h" - -#include "zGame.h" -#include "zGlobals.h" - -#include -#include - -_tagTRCPadInfo gTrcPad[4]; -_tagTRCState gTrcDisk[2]; - -const char* message_text; - -void xTRCInit() -{ - memset(gTrcPad, 0, sizeof(gTrcPad)); - gTrcPad[0].id = 0; - gTrcPad[1].id = 1; - gTrcPad[2].id = 2; - gTrcPad[3].id = 3; - memset(gTrcDisk, 0, 8); -} - -void render_message(const char*); - -void xTRCRender() -{ - if (message_text != NULL) - { - render_message(message_text); - } -} - -void xTRCReset() -{ - message_text = NULL; - globals.dontShowPadMessageDuringLoadingOrCutScene = false; - - eGameMode mode = gGameMode; - bool isStall = mode == eGameMode_Stall; - - if (isStall) - { - zGameModeSwitch(eGameMode_Game); - } - - xSndResume(); -} - -// SDA relocation shenanigans -void xTRCDisk(_tagTRCState state) -{ - if (state != TRC_DiskNotIdentified) - { - gTrcDisk[0] = state; - gTrcDisk[1] = TRC_DiskIdentified; - } - else - { - gTrcDisk[1] = TRC_DiskNotIdentified; - } -} - -void xTRCPad(S32, _tagTRCState) -{ -} diff --git a/src/SB/Core/x/xTRC.h b/src/SB/Core/x/xTRC.h index cb25571..70a70b9 100644 --- a/src/SB/Core/x/xTRC.h +++ b/src/SB/Core/x/xTRC.h @@ -21,7 +21,7 @@ enum _tagTRCState TRC_Total }; -struct _tagTRCPadInfo : _tagiTRCPadInfo +struct _tagTRCPadInfo { S32 id; _tagTRCState state; diff --git a/src/SB/Core/x/xTimer.cpp b/src/SB/Core/x/xTimer.cpp deleted file mode 100644 index 7383cb6..0000000 --- a/src/SB/Core/x/xTimer.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "xTimer.h" -#include "xMath.h" - -#include - -static U32 sPauseTimerHash[] = -{ - 0xBC345600, 0xBC345609, - 0xBC345683, 0xBC34568C, - 0xBC345706, 0xBC34570F, - 0xBC345789, 0xBC345792, - 0xBC34580C, 0xBC345815, - 0xBC34588F, 0xBC345898, - 0xBC345912, 0xBC34591B, - 0xBC345995, 0xBC34599E, - 0xBC345A18, 0xBC345A21, - 0xBC345A9B, 0xBC345AA4, -}; - -F32 GetRandomizedTime(xTimerAsset* tasset) -{ - U32 halfRangeMilli = 1000.0f * tasset->randomRange; - if (halfRangeMilli == 0) { - return tasset->seconds; - } - - S32 offset = xrand() % (halfRangeMilli * 2) - halfRangeMilli; - F32 time = tasset->seconds + offset / 1000.0f; - return time; -} - -void xTimerInit(void* b, void* tasset) -{ - xTimerInit((xBase*)b, (xTimerAsset*)tasset); -} - -void xTimerSave(xTimer* ent, xSerial* s) -{ - xBaseSave(ent, s); - - s->Write(ent->state); - s->Write(ent->secondsLeft); -} - -void xTimerLoad(xTimer* ent, xSerial* s) -{ - xBaseLoad(ent, s); - - s->Read(&ent->state); - s->Read(&ent->secondsLeft); -} - -S32 xTimer_ObjIDIsPauseTimer(U32 id) -{ - if (id == 0xCB3F6340) return TRUE; - if (id >= 0x016FC9F0 && id <= 0x016FC9F9) return TRUE; - - S32 foo = (id >= 0xBC345600); - S32 bar = (id <= 0xBC345AA4); - if (foo && bar) { - for (S32 i = 0; i < 10; i++) { - if (id >= sPauseTimerHash[i*2] && id <= sPauseTimerHash[i*2+1]) { - return TRUE; - } - } - } - - return FALSE; -} - -void xTimerInit(xBase* b, xTimerAsset* tasset) -{ - xBaseInit(b, tasset); - - xTimer* t = (xTimer*)b; - - t->eventFunc = xTimerEventCB; - t->tasset = tasset; - - if (t->linkCount) { - t->link = (xLinkAsset*)((U8*)t->tasset + sizeof(xTimerAsset)); - } else { - t->link = NULL; - } - - t->state = 0; - t->secondsLeft = GetRandomizedTime(tasset); - t->runsInPause = xTimer_ObjIDIsPauseTimer(b->id); - t->flags = 0; -} - -void xTimerReset(xTimer* ent) -{ - xBaseReset(ent, ent->tasset); - ent->state = 0; - ent->secondsLeft = GetRandomizedTime(ent->tasset); - ent->flags = 0; -} \ No newline at end of file diff --git a/src/SB/Core/x/xUpdateCull.cpp b/src/SB/Core/x/xUpdateCull.cpp deleted file mode 100644 index 4be7bef..0000000 --- a/src/SB/Core/x/xUpdateCull.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "zGlobals.h" -#include "xUpdateCull.h" - -U32 xUpdateCull_AlwaysTrueCB(void* ent, void* cbdata) -{ - return 1; -} - -void xUpdateCull_Swap(xUpdateCullMgr* mgr, U32 a, U32 b) -{ - xUpdateCullEnt* pMgrAIndex; - - xUpdateCullEnt* pMgrBIndex = mgr->mgr[b]; - xUpdateCullEnt* pMgrIndex = pMgrAIndex = mgr->mgr[a]; - - do - { - pMgrIndex->index = (U16)b; - pMgrIndex = pMgrIndex->nextInGroup; - if (pMgrIndex == NULL) break; - } while (pMgrIndex != pMgrAIndex); - - pMgrIndex = pMgrBIndex; - do - { - pMgrIndex->index = (U16)a; - pMgrIndex = pMgrIndex->nextInGroup; - if (pMgrIndex == NULL) break; - } while (pMgrIndex != pMgrBIndex); - - // Set index and groupIndex together. - S32 uVar6 = *(S32 *)(&mgr->ent[a]); - *(S32 *)(&mgr->ent[a]) = *(S32 *)(&mgr->ent[b]); - *(S32 *)(&mgr->ent[b]) = uVar6; - - uVar6 = *(S32 *)(&mgr->mgr[a]); - *(S32 *)(&mgr->mgr[a]) = *(S32 *)(&mgr->mgr[b]); - *(S32 *)(&mgr->mgr[b]) = uVar6; -} - -void xUpdateCull_MakeActive(xUpdateCullMgr* m, xUpdateCullEnt* e) -{ - U32 eIndex = e->index; - U32 mEntActive = m->entActive; - - if (eIndex >= mEntActive) - { - if (eIndex != mEntActive) - { - xUpdateCull_Swap(m, eIndex, mEntActive); - } - if (m->activateCB != NULL) - { - m->activateCB(m->ent[e->index]); - } - m->entActive++; - } -} - -void xUpdateCull_MakeInactive(xUpdateCullMgr* m, xUpdateCullEnt* e) -{ - U32 eIndex = e->index; - U32 mEntActive = m->entActive; - - if (eIndex < mEntActive) - { - mEntActive--; - if (eIndex != mEntActive) - { - xUpdateCull_Swap(m, eIndex, mEntActive); - } - if (m->deactivateCB != NULL) - { - m->deactivateCB(m->ent[e->index]); - } - m->entActive--; - } -} - -void xUpdateCull_Reset(xUpdateCullMgr* m) -{ - for (U32 i = m->entActive; i < m->entCount; i++) - { - xUpdateCull_MakeActive(m, m->mgr[i]); - } -} - -void xUpdateCull_SetCB(xUpdateCullMgr* m, void* entity, xUpdateCullEntCallback cb, void* cbdata) -{ - for (U32 i = 0; i < m->mgrCount; i++) - { - if (*(void **)(&m->ent[m->mgrList[i].index]) == entity) - { - m->mgrList[i].cb = cb; - m->mgrList[i].cbdata = cbdata; - } - } -} \ No newline at end of file diff --git a/src/SB/Core/x/xVec3.cpp b/src/SB/Core/x/xVec3.cpp deleted file mode 100644 index b0da0a6..0000000 --- a/src/SB/Core/x/xVec3.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "xVec3.h" -#include "xCollide.h" -#include "xMathInlines.h" -#include "iMath.h" -#include "xMath.h" - -#include -#include - -const xVec3 xVec3::m_Null = { 0.0f, 0.0f, 0.0f }; -const xVec3 xVec3::m_UnitAxisX = { 1.0f, 0.0f, 0.0f }; -const xVec3 xVec3::m_UnitAxisY = { 0.0f, 1.0f, 0.0f }; - -F32 xVec3Normalize(xVec3* o, const xVec3* v) -{ - F32 x = v->x; - F32 x2 = SQR(v->x); - F32 y = v->y; - F32 y2 = SQR(v->y); - F32 z = v->z; - F32 z2 = SQR(v->z); - - F32 len; - F32 len2 = x2 + y2 + z2; - - if ((F32)iabs(len2 - 1.0f) <= 0.00001f) - { - o->x = x; - o->y = y; - o->z = z; - len = 1.0f; - } - else if ((F32)iabs(len2) <= 0.00001f) - { - o->x = 0.0f; - o->y = 1.0f; - o->z = 0.0f; - len = 0.0f; - } - else - { - len = xsqrt(len2); - F32 inv_len = 1.0f / len; - o->x = v->x * inv_len; - o->y = v->y * inv_len; - o->z = v->z * inv_len; - } - return len; -} - -F32 xVec3NormalizeFast(xVec3* o, const xVec3* v) -{ - F32 x = v->x; - F32 x2 = SQR(v->x); - F32 y = v->y; - F32 y2 = SQR(v->y); - F32 z = v->z; - F32 z2 = SQR(v->z); - - F32 len; - F32 len2 = x2 + y2 + z2; - - if ((F32)iabs(len2 - 1.0f) <= 0.00001f) - { - o->x = x; - o->y = y; - o->z = z; - len = 1.0f; - } - else if ((F32)iabs(len2) <= 0.00001f) - { - o->x = 0.0f; - o->y = 1.0f; - o->z = 0.0f; - len = 0.0f; - } - else - { - xsqrtfast(len, len2); - F32 inv_len = 1.0f / len; - o->x = v->x * inv_len; - o->y = v->y * inv_len; - o->z = v->z * inv_len; - } - return len; -} - -void xVec3Copy(register xVec3* dst, const register xVec3* src) -{ - PSVECCopy(dst, src); -} - -asm F32 xVec3Dot(const register xVec3* a, const register xVec3* b) -{ - PSVECDotProduct(a, b) -} diff --git a/src/SB/Core/x/xVolume.cpp b/src/SB/Core/x/xVolume.cpp deleted file mode 100644 index 06acc9f..0000000 --- a/src/SB/Core/x/xVolume.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include - -#include "xBound.h" -#include "xLinkAsset.h" -#include "xVolume.h" - -void xVolume::Init(xVolumeAsset* asset) -{ - xBaseInit(this, asset); - this->asset = asset; - - if (this->linkCount) - { - this->link = (xLinkAsset*)(this->asset + 1); - } - else - { - this->link = NULL; - } -} - -void xVolume::Reset() -{ - xBaseReset(this, this->asset); -} - -void xVolume::Save(xSerial* s) -{ - xBaseSave(this, s); -} - -void xVolume::Load(xSerial* s) -{ - xBaseLoad(this, s); -} - -xBound* xVolume::GetBound() -{ - return &this->asset->bound; -} diff --git a/src/SB/Core/x/xbinio.cpp b/src/SB/Core/x/xbinio.cpp deleted file mode 100644 index 49b30a4..0000000 --- a/src/SB/Core/x/xbinio.cpp +++ /dev/null @@ -1,734 +0,0 @@ -#include "xbinio.h" - -#include "xMath.h" - -#include - -#define LITTLE_ENDIAN 0 -#define BIG_ENDIAN 1 - -#ifdef GAMECUBE -#define ENDIAN BIG_ENDIAN -#else -#define ENDIAN LITTLE_ENDIAN -#endif - -struct st_BINIO_XTRADATA -{ - char* dbl_buf; - S32 dblbuf_size; - S32 dbl_beg; - S32 dbl_end; - S32 dbl_amt; - U32 fpos; - char* asyn_data; - S32 asyn_amt; - S32 asyn_elesize; - S32 asyn_ismot; - en_BIO_ASYNC_ERRCODES asyn_status; - U32 pad[3]; - S32 gcaskey; -}; - -static U32 g_loadlock = 0xFFFFFF00; -static st_FILELOADINFO g_loadinst[8] = {}; -static tag_xFile g_xfload[8] = {}; -static st_BINIO_XTRADATA g_xtraload[8] = {}; -static st_BINIO_XTRADATA* g_async_context = NULL; - -static void LoadDestroy(st_FILELOADINFO* fli); -static S32 SkipBytes(st_FILELOADINFO* fli, S32 fwd); -static S32 ReadSeek(st_FILELOADINFO* fli, S32 pos); -static void SetBuffer(st_FILELOADINFO* fli, char* dblbuffer, S32 bufsize); -static void DiscardBuffer(st_FILELOADINFO* fli); -static S32 ReadRaw(st_FILELOADINFO* fli, void* data, S32 size, S32 count); -static S32 ReadBytes(st_FILELOADINFO* fli, char* data, S32 count); -static S32 ReadMShorts(st_FILELOADINFO* fli, S16* data, S32 count); -static S32 ReadMLongs(st_FILELOADINFO* fli, S32* data, S32 count); -static S32 ReadMFloats(st_FILELOADINFO* fli, F32* data, S32 count); -static S32 ReadMDoubles(st_FILELOADINFO* fli, F64* data, S32 count); -static S32 ReadIShorts(st_FILELOADINFO* fli, S16* data, S32 count); -static S32 ReadILongs(st_FILELOADINFO* fli, S32* data, S32 count); -static S32 ReadIFloats(st_FILELOADINFO* fli, F32* data, S32 count); -static S32 ReadIDoubles(st_FILELOADINFO* fli, F64* data, S32 count); -static S32 AsyncMRead(st_FILELOADINFO* fli, S32 offset, char* data, S32 size, S32 n); -static S32 AsyncIRead(st_FILELOADINFO* fli, S32 offset, char* data, S32 size, S32 n); -static en_BIO_ASYNC_ERRCODES AsyncReadStatus(st_FILELOADINFO* fli); -static void Swap2(char* d, S32 n); -static void Swap4(char* d, S32 n); -static void Swap8(char* d, S32 n); -static tag_xFile* BFD_open(const char* filename, const char* mode, U32 lockid, S32, - void* xtradata); -static void BFD_close(tag_xFile* bffp, void* xtradata); -static S32 BFD_read(void* data, S32 elesize, S32 elecnt, tag_xFile* bffp, void* xtradata); -static S32 BFD_seek(tag_xFile* bffp, S32 offset, S32 whence, void* xtradata); -static S32 BFD_getLength(tag_xFile* bffp, void* xtradata); -static S32 BFD_startSector(const char* filename); -static void BFD_cb_GCP2_readasync(tag_xFile* bffp); -static S32 BFD_AsyncRead(st_FILELOADINFO* fli, S32 pos, void* data, S32 size, S32 n, - S32 endian); -static en_BIO_ASYNC_ERRCODES BFD_AsyncReadStatus(st_FILELOADINFO* fli); - -st_FILELOADINFO* xBinioLoadCreate(const char* filename) -{ - st_FILELOADINFO* fli = NULL; - tag_xFile* tmp_fp; - S32 i; - S32 uselock = -1; - - for (i = 0; i < 8; i++) - { - if (!(g_loadlock & (1 << i))) - { - g_loadlock |= 1 << i; - - uselock = i; - fli = &g_loadinst[i]; - - break; - } - } - - if (fli) - { - memset(fli, 0, sizeof(st_FILELOADINFO)); - - fli->lockid = uselock & ~(uselock >> 31); - fli->xtradata = &g_xtraload[uselock]; - fli->destroy = LoadDestroy; - fli->readBytes = ReadBytes; - fli->readMShorts = ReadMShorts; - fli->readMLongs = ReadMLongs; - fli->readMFloats = ReadMFloats; - fli->readMDoubles = ReadMDoubles; - fli->readIShorts = ReadIShorts; - fli->readILongs = ReadILongs; - fli->readIFloats = ReadIFloats; - fli->readIDoubles = ReadIDoubles; - fli->asyncIRead = AsyncIRead; - fli->asyncMRead = AsyncMRead; - fli->asyncReadStatus = AsyncReadStatus; - fli->skipBytes = SkipBytes; - fli->seekSpot = ReadSeek; - fli->setDoubleBuf = SetBuffer; - fli->discardDblBuf = DiscardBuffer; - fli->error = FIOERR_NONE; - fli->remain = 0; - fli->basesector = 0; - fli->filesize = 0; - fli->position = 0; - fli->basesector = 0; - - tmp_fp = BFD_open(filename, "rb", uselock, 0, fli->xtradata); - - if (tmp_fp) - { - fli->basesector = BFD_startSector(filename); - fli->privdata = tmp_fp; - fli->filesize = BFD_getLength(tmp_fp, fli->xtradata); - fli->remain = fli->filesize; - } - else - { - LoadDestroy(fli); - fli = NULL; - } - } - - return fli; -} - -static void LoadDestroy(st_FILELOADINFO* fli) -{ - tag_xFile* fp = (tag_xFile*)fli->privdata; - - if (fp) - { - BFD_close(fp, fli->xtradata); - } - - U32 lockid = fli->lockid; - - memset(fli, 0, sizeof(st_FILELOADINFO)); - - g_loadlock &= ~(1 << lockid); -} - -static S32 SkipBytes(st_FILELOADINFO* fli, S32 fwd) -{ - tag_xFile* file = (tag_xFile*)fli->privdata; - - if (fli->error != FIOERR_NONE) - { - return 0; - } - - if (fwd == 0) - { - return 1; - } - - if (fwd < 0) - { - fwd = 0; - } - - if (BFD_seek(file, fli->position + fwd, IFILE_SEEK_SET, fli->xtradata) != 0) - { - fli->error = FIOERR_SEEKFAIL; - } - else - { - fli->remain -= fwd; - fli->position += fwd; - } - - if (fli->error != FIOERR_NONE) - { - return 0; - } - - return 1; -} - -static S32 ReadSeek(st_FILELOADINFO* fli, S32 pos) -{ - tag_xFile* file = (tag_xFile*)fli->privdata; - - if (fli->error != FIOERR_NONE) - { - return 0; - } - - pos = MIN(pos, fli->filesize); - - if (BFD_seek(file, pos, IFILE_SEEK_SET, fli->xtradata) != 0) - { - fli->error = FIOERR_SEEKFAIL; - } - else - { - fli->position = pos; - fli->remain = fli->filesize - pos; - } - - if (fli->error != FIOERR_NONE) - { - return 0; - } - - return 1; -} - -static void SetBuffer(st_FILELOADINFO* fli, char* dblbuffer, S32 bufsize) -{ - st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)fli->xtradata; - - if (xtra) - { - xtra->dbl_buf = dblbuffer; - xtra->dblbuf_size = bufsize; - xtra->dbl_beg = 0; - xtra->dbl_end = 0; - xtra->dbl_amt = 0; - } -} - -static void DiscardBuffer(st_FILELOADINFO* fli) -{ - SetBuffer(fli, NULL, 0); -} - -static S32 ReadRaw(st_FILELOADINFO* fli, void* data, S32 size, S32 count) -{ - tag_xFile* file = (tag_xFile*)fli->privdata; - - if (fli->error != FIOERR_NONE) - { - return 0; - } - - S32 amt = (size * count > fli->remain) ? fli->remain / size : count; - - if (amt) - { - S32 n = BFD_read(data, size, amt, file, fli->xtradata); - - if (n != amt) - { - fli->error = FIOERR_READFAIL; - } - - fli->remain -= size * amt; - fli->position += size * amt; - } - - return amt; -} - -static S32 ReadBytes(st_FILELOADINFO* fli, char* data, S32 count) -{ - S32 act = ReadRaw(fli, data, sizeof(char), count); - return act; -} - -static S32 ReadMShorts(st_FILELOADINFO* fli, S16* data, S32 count) -{ - S32 act = ReadRaw(fli, data, sizeof(S16), count); - -#if ENDIAN == LITTLE_ENDIAN - Swap2((char*)data, act); -#endif - - return act; -} - -static S32 ReadMLongs(st_FILELOADINFO* fli, S32* data, S32 count) -{ - S32 act = ReadRaw(fli, data, sizeof(S32), count); - -#if ENDIAN == LITTLE_ENDIAN - Swap4((char*)data, act); -#endif - - return act; -} - -static S32 ReadMFloats(st_FILELOADINFO* fli, F32* data, S32 count) -{ - S32 act = ReadRaw(fli, data, sizeof(F32), count); - -#if ENDIAN == LITTLE_ENDIAN - Swap4((char*)data, act); -#endif - - return act; -} - -static S32 ReadMDoubles(st_FILELOADINFO* fli, F64* data, S32 count) -{ - S32 act = ReadRaw(fli, data, sizeof(F64), count); - -#if ENDIAN == LITTLE_ENDIAN - Swap8((char*)data, act); -#endif - - return act; -} - -static S32 ReadIShorts(st_FILELOADINFO* fli, S16* data, S32 count) -{ - S32 act = ReadRaw(fli, data, sizeof(S16), count); - -#if ENDIAN == BIG_ENDIAN - Swap2((char*)data, act); -#endif - - return act; -} - -static S32 ReadILongs(st_FILELOADINFO* fli, S32* data, S32 count) -{ - S32 act = ReadRaw(fli, data, sizeof(S32), count); - -#if ENDIAN == BIG_ENDIAN - Swap4((char*)data, act); -#endif - - return act; -} - -static S32 ReadIFloats(st_FILELOADINFO* fli, F32* data, S32 count) -{ - S32 act = ReadRaw(fli, data, sizeof(F32), count); - -#if ENDIAN == BIG_ENDIAN - Swap4((char*)data, act); -#endif - - return act; -} - -static S32 ReadIDoubles(st_FILELOADINFO* fli, F64* data, S32 count) -{ - S32 act = ReadRaw(fli, data, sizeof(F64), count); - -#if ENDIAN == BIG_ENDIAN - Swap8((char*)data, act); -#endif - - return act; -} - -static S32 AsyncMRead(st_FILELOADINFO* fli, S32 offset, char* data, S32 size, S32 n) -{ - return BFD_AsyncRead(fli, offset, data, size, n, BIG_ENDIAN); -} - -static S32 AsyncIRead(st_FILELOADINFO* fli, S32 offset, char* data, S32 size, S32 n) -{ - return BFD_AsyncRead(fli, offset, data, size, n, LITTLE_ENDIAN); -} - -static en_BIO_ASYNC_ERRCODES AsyncReadStatus(st_FILELOADINFO* fli) -{ - return BFD_AsyncReadStatus(fli); -} - -static void Swap2(char* d, S32 n) -{ - char t; - - while (n--) - { - t = d[0]; - d[0] = d[1]; - d[1] = t; - - d += 2; - } -} - -static void Swap4(char* d, S32 n) -{ - char t; - - while (n--) - { - t = d[0]; - d[0] = d[3]; - d[3] = t; - - t = d[1]; - d[1] = d[2]; - d[2] = t; - - d += 4; - } -} - -static void Swap8(char* d, S32 n) -{ - char t; - - while (n--) - { - t = d[0]; - d[0] = d[7]; - d[7] = t; - - t = d[1]; - d[1] = d[6]; - d[6] = t; - - t = d[2]; - d[2] = d[5]; - d[5] = t; - - t = d[3]; - d[3] = d[4]; - d[4] = t; - - d += 8; - } -} - -static tag_xFile* BFD_open(const char* filename, const char* mode, U32 lockid, S32, - void* xtradata) -{ - tag_xFile* bffp; - U32 orc; // open return code - st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)xtradata; - S32 xfflg = IFILE_OPEN_READ; - - if (strcmp(mode, "rb") == 0) - { - bffp = &g_xfload[lockid]; - xfflg = IFILE_OPEN_READ; - } - else if (strcmp(mode, "wb") == 0) - { - bffp = NULL; - xfflg = IFILE_OPEN_WRITE; - } - else - { - bffp = NULL; - } - - if (bffp) - { - strncpy(bffp->relname, filename, sizeof(bffp->relname) - 1); - bffp->relname[sizeof(bffp->relname) - 1] = '\0'; - - orc = iFileOpen(filename, xfflg, bffp); - - if (orc != 0) - { - bffp = NULL; - } - else - { - xtra->fpos = 0; - xtra->dbl_buf = NULL; - xtra->dblbuf_size = 0; - xtra->dbl_beg = 0; - xtra->dbl_end = 0; - xtra->dbl_amt = 0; - } - } - - return bffp; -} - -static void BFD_close(tag_xFile* bffp, void* xtradata) -{ - st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)xtradata; - - iFileClose(bffp); - - xtra->fpos = 0; - xtra->dbl_buf = NULL; - xtra->dblbuf_size = 0; - xtra->dbl_beg = 0; - xtra->dbl_end = 0; - xtra->dbl_amt = 0; -} - -static S32 BFD_read(void* data, S32 elesize, S32 elecnt, tag_xFile* bffp, void* xtradata) -{ - st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)xtradata; - char* dest = (char*)data; - S32 readbeg; - S32 refill = 0; - S32 remain; - S32 actual; - U32 holdpos; - U32 numBytes = 0; - U32 safety = 0; - S32 r26 = elesize * elecnt; - - if (r26 == 0) - { - return 0; - } - - if (!xtra->dbl_buf || xtra->dblbuf_size < 1 || r26 > xtra->dblbuf_size) - { - iFileSeek(bffp, xtra->fpos, IFILE_SEEK_SET); - numBytes = iFileRead(bffp, dest, r26); - - xtra->fpos += numBytes; - } - else - { - remain = r26; - - while (true) - { - if (xtra->fpos < xtra->dbl_beg) - { - refill = 1; - - xtra->dbl_beg = xtra->fpos - (xtra->fpos % xtra->dblbuf_size); - xtra->dbl_end = xtra->dbl_beg + xtra->dblbuf_size; - xtra->dbl_amt = 0; - } - else if (xtra->fpos >= xtra->dbl_end) - { - refill = 1; - - xtra->dbl_beg = xtra->fpos - (xtra->fpos % xtra->dblbuf_size); - xtra->dbl_end = xtra->dbl_beg + xtra->dblbuf_size; - xtra->dbl_amt = 0; - } - - if (refill) - { - holdpos = xtra->fpos; - - iFileSeek(bffp, xtra->dbl_beg, IFILE_SEEK_SET); - - xtra->fpos = holdpos; - xtra->dbl_amt = iFileRead(bffp, xtra->dbl_buf, xtra->dblbuf_size); - } - - readbeg = xtra->fpos - xtra->dbl_beg; - - if (xtra->dbl_amt > readbeg) - { - actual = MIN(remain, xtra->dbl_amt - readbeg); - - memcpy(dest + numBytes, xtra->dbl_buf + readbeg, actual); - - numBytes += actual; - remain -= actual; - - xtra->fpos += actual; - } - - if (numBytes == r26 || xtra->dbl_amt < 1 || safety++ > 60000) - { - break; - } - } - } - - return (S32)numBytes / elesize; -} - -static S32 BFD_seek(tag_xFile* bffp, S32 offset, S32 whence, void* xtradata) -{ - st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)xtradata; - S32 pos = iFileSeek(bffp, offset, whence); - - xtra->fpos = offset; - - if (pos == -1) - { - return 1; - } - - return 0; -} - -static S32 BFD_getLength(tag_xFile* bffp, void* xtradata) -{ - return iFileGetSize(bffp); -} - -static S32 BFD_startSector(const char* filename) -{ - tag_xFile file = {}; - U32 addr = 0; - U32 length = 0; - - if (!iFileFind(filename, &file)) - { - iFileGetInfo(&file, &addr, &length); - } - - iFileClose(&file); - - return addr; -} - -static void BFD_cb_GCP2_readasync(tag_xFile* bffp) -{ -} - -static S32 BFD_AsyncRead(st_FILELOADINFO* fli, S32 pos, void* data, S32 size, S32 n, - S32 endian) -{ - tag_xFile* file = (tag_xFile*)fli->privdata; - st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)fli->xtradata; - - if (fli->error != FIOERR_NONE) - { - return 0; - } - - if (g_async_context) - { - return 0; - } - - g_async_context = xtra; - - xtra->asyn_status = BINIO_ASYNC_INPROG; - xtra->asyn_data = (char*)data; - xtra->asyn_elesize = size; - xtra->asyn_amt = n; - xtra->asyn_ismot = 1; - - iFileSeek(file, pos, IFILE_SEEK_SET); - xFileSetUserData(file, fli); - - S32 result = iFileReadAsync(file, data, size * n, BFD_cb_GCP2_readasync, 0); - S32 rc; - - if (result < 0) - { - rc = 0; - } - else - { - xtra->gcaskey = result; - rc = 1; - } - - if (rc == 0) - { - g_async_context = NULL; - xtra->asyn_status = BINIO_ASYNC_NOOP; - } - - return 1; -} - -static en_BIO_ASYNC_ERRCODES BFD_AsyncReadStatus(st_FILELOADINFO* fli) -{ - en_BIO_ASYNC_ERRCODES status; - st_BINIO_XTRADATA* xtra = (st_BINIO_XTRADATA*)fli->xtradata; - - if (!g_async_context) - { - status = BINIO_ASYNC_NOOP; - } - else if (xtra != g_async_context) - { - status = BINIO_ASYNC_INPROG; - } - else - { - if (xtra->asyn_status == BINIO_ASYNC_INPROG) - { - XFILE_READSECTOR_STATUS xrdstat; - S32 amtsofar = 0; - - xrdstat = xFileReadAsyncStatus(xtra->gcaskey, &amtsofar); - - switch (xrdstat) - { - case XFILE_RDSTAT_INPROG: - case XFILE_RDSTAT_QUEUED: - { - xtra->asyn_status = BINIO_ASYNC_INPROG; - break; - } - case XFILE_RDSTAT_DONE: - { - xtra->asyn_status = BINIO_ASYNC_DONE; - break; - } - case XFILE_RDSTAT_FAIL: - case XFILE_RDSTAT_EXPIRED: - default: - { - xtra->asyn_status = BINIO_ASYNC_FAIL; - break; - } - } - } - - status = xtra->asyn_status; - - if (status == BINIO_ASYNC_FAIL || status == BINIO_ASYNC_DONE) - { - xtra->asyn_status = BINIO_ASYNC_NOOP; - g_async_context = NULL; - } - } - - return status; -} - -WEAK void xFileSetUserData(tag_xFile* file, void* userdata) -{ - file->user_data = userdata; -} - -WEAK XFILE_READSECTOR_STATUS xFileReadAsyncStatus(S32 key, S32* amtToFar) -{ - return (XFILE_READSECTOR_STATUS)iFileReadAsyncStatus(key, amtToFar); -} diff --git a/src/SB/Core/x/xhipio.cpp b/src/SB/Core/x/xhipio.cpp deleted file mode 100644 index 42b22a6..0000000 --- a/src/SB/Core/x/xhipio.cpp +++ /dev/null @@ -1,511 +0,0 @@ -#include "xhipio.h" - -#include - -static st_HIPLOADDATA* HIPLCreate(const char* filename, char* dblbuf, S32 bufsize); -static void HIPLDestroy(st_HIPLOADDATA* lddata); -static U32 HIPLBaseSector(st_HIPLOADDATA* lddata); -static S32 HIPLSetBypass(st_HIPLOADDATA* lddata, S32 enable, S32 use_async); -static void HIPLSetSpot(st_HIPLOADDATA* lddata, S32 spot); -static U32 HIPLBlockEnter(st_HIPLOADDATA* lddata); -static void HIPLBlockExit(st_HIPLOADDATA* lddata); -static S32 HIPLBlockRead(st_HIPLOADDATA* lddata, void* data, S32 cnt, S32 size); -static S32 HIPLBypassRead(st_HIPLOADDATA* lddata, void* data, S32 cnt, S32 size); -static S32 HIPLReadAsync(st_HIPLOADDATA* lddata, S32 pos, char* data, S32 cnt, S32 size); -static en_READ_ASYNC_STATUS HIPLPollRead(st_HIPLOADDATA* lddata); -static S32 HIPLReadBytes(st_HIPLOADDATA* lddata, char* data, S32 cnt); -static S32 HIPLReadShorts(st_HIPLOADDATA* lddata, S16* data, S32 cnt); -static S32 HIPLReadLongs(st_HIPLOADDATA* lddata, S32* data, S32 cnt); -static S32 HIPLReadFloats(st_HIPLOADDATA* lddata, F32* data, S32 cnt); -static S32 HIPLReadString(st_HIPLOADDATA* lddata, char* buf); - -static U32 g_loadlock = 0; - -static st_HIPLOADDATA g_hiploadinst[8] = {}; - -// clang-format off -static st_HIPLOADFUNCS g_map_HIPL_funcmap = -{ - HIPLCreate, - HIPLDestroy, - HIPLBaseSector, - HIPLBlockEnter, - HIPLBlockExit, - HIPLReadBytes, - HIPLReadShorts, - HIPLReadLongs, - HIPLReadFloats, - HIPLReadString, - HIPLSetBypass, - HIPLSetSpot, - HIPLPollRead -}; -// clang-format on - -st_HIPLOADFUNCS* get_HIPLFuncs() -{ - return &g_map_HIPL_funcmap; -} - -static st_HIPLOADDATA* HIPLCreate(const char* filename, char* dblbuf, S32 bufsize) -{ - st_HIPLOADDATA* lddata = NULL; - st_FILELOADINFO* fli; - st_HIPLOADBLOCK* tmp_blk; - S32 i; - S32 uselock = -1; - - for (i = 0; i < 8; i++) - { - if (!(g_loadlock & (1 << i))) - { - g_loadlock |= 1 << i; - - uselock = i; - lddata = &g_hiploadinst[i]; - - break; - } - } - - if (lddata) - { - memset(lddata, 0, sizeof(st_HIPLOADDATA)); - - lddata->lockid = uselock; - lddata->top = -1; - lddata->base_sector = 0; - lddata->use_async = 0; - lddata->asyn_stat = HIP_RDSTAT_NONE; - lddata->bypass = 0; - lddata->bypass_recover = -1; - lddata->pos = 0; - lddata->readTop = 0; - - for (i = 0; i < 8; i++) - { - tmp_blk = &lddata->stk[i]; - - tmp_blk->endpos = 0; - tmp_blk->blk_id = 0; - tmp_blk->blk_remain = 0; - tmp_blk->flags = 0; - } - - fli = xBinioLoadCreate(filename); - - if (fli) - { - lddata->fli = fli; - lddata->base_sector = fli->basesector; - - if (dblbuf && bufsize > 0) - { - fli->setDoubleBuf(fli, dblbuf, bufsize); - } - } - else - { - HIPLDestroy(lddata); - lddata = NULL; - } - } - - return lddata; -} - -static void HIPLDestroy(st_HIPLOADDATA* lddata) -{ - S32 lockid; - - if (lddata) - { - if (lddata->fli) - { - lddata->fli->destroy(lddata->fli); - } - - lockid = lddata->lockid; - - memset(lddata, 0, sizeof(st_HIPLOADDATA)); - - g_loadlock &= ~(1 << lockid); - } -} - -static U32 HIPLBaseSector(st_HIPLOADDATA* lddata) -{ - return lddata->base_sector; -} - -static S32 HIPLSetBypass(st_HIPLOADDATA* lddata, S32 enable, S32 use_async) -{ - lddata->fli->discardDblBuf(lddata->fli); - - if (enable && lddata->bypass) - { - return 0; - } - - if (!enable && !lddata->bypass) - { - return 0; - } - - if (enable) - { - lddata->bypass = 1; - lddata->use_async = use_async; - lddata->bypass_recover = lddata->fli->position; - } - else - { - lddata->fli->seekSpot(lddata->fli, lddata->bypass_recover); - lddata->bypass = 0; - lddata->use_async = 0; - lddata->bypass_recover = -1; - } - - return 1; -} - -static void HIPLSetSpot(st_HIPLOADDATA* lddata, S32 spot) -{ - if (lddata->bypass) - { - lddata->pos = spot; - lddata->fli->seekSpot(lddata->fli, spot); - } -} - -static U32 HIPLBlockEnter(st_HIPLOADDATA* lddata) -{ - st_HIPLOADBLOCK* top; - U32 cid = 0; - S32 size = 0; - - if (lddata->bypass) - { - return 0; - } - - if (lddata->top >= 0 && lddata->stk[lddata->top].blk_remain <= 0) - { - return 0; - } - - if (HIPLReadLongs(lddata, (S32*)&cid, -1) == 0) - { - cid = 0; - } - else - { - HIPLReadLongs(lddata, &size, -1); - - if (lddata->top >= 0) - { - lddata->stk[lddata->top].blk_remain -= size; - } - - top = &lddata->stk[++lddata->top]; - - top->blk_id = cid; - top->blk_remain = size; - top->endpos = lddata->pos + top->blk_remain + (top->blk_remain & 1); - top->flags = 0; - } - - return cid; -} - -static void HIPLBlockExit(st_HIPLOADDATA* lddata) -{ - st_HIPLOADBLOCK* top; - - if (!lddata->bypass) - { - top = &lddata->stk[lddata->top--]; - - lddata->fli->skipBytes(lddata->fli, top->endpos - lddata->pos); - lddata->pos = top->endpos; - } -} - -static S32 HIPLBlockRead(st_HIPLOADDATA* lddata, void* data, S32 cnt, S32 size) -{ - st_HIPLOADBLOCK* top; - S32 got = 0; - S32 left = 0; - S32 head = 0; - - if (lddata->bypass) - { - return 0; - } - - if (cnt == 0) - { - return 0; - } - - if (lddata->top < 0) - { - top = NULL; - } - else - { - top = &lddata->stk[lddata->top]; - left = top->blk_remain / size; - } - - if (cnt < 0) - { - cnt = -cnt; - head = 1; - - if (top && cnt > left) - { - cnt = left; - } - } - - if (!head && left < cnt) - { - cnt = left; - } - - if (cnt == 0) - { - got = 0; - } - else if (size == 1) - { - got = lddata->fli->readBytes(lddata->fli, (char*)data, cnt); - } - else if (size == 2) - { - got = lddata->fli->readMShorts(lddata->fli, (S16*)data, cnt); - } - else if (size == 4) - { - got = lddata->fli->readMLongs(lddata->fli, (S32*)data, cnt); - } - - got *= size; - - lddata->pos += got; - - if (top) - { - top->blk_remain -= got; - } - - return got; -} - -static S32 HIPLBypassRead(st_HIPLOADDATA* lddata, void* data, S32 cnt, S32 size) -{ - S32 got = 0; - - if (!lddata->bypass) - { - return 0; - } - - if (lddata->use_async) - { - return HIPLReadAsync(lddata, lddata->pos, (char*)data, cnt, size); - } - - if (cnt == 0) - { - return 0; - } - - if (cnt == 0) - { - got = 0; - } - else if (size == 1) - { - got = lddata->fli->readBytes(lddata->fli, (char*)data, cnt); - } - else if (size == 2) - { - got = lddata->fli->readMShorts(lddata->fli, (S16*)data, cnt); - } - else if (size == 4) - { - got = lddata->fli->readMLongs(lddata->fli, (S32*)data, cnt); - } - - return got * size; -} - -static S32 HIPLReadAsync(st_HIPLOADDATA* lddata, S32 pos, char* data, S32 cnt, S32 size) -{ - S32 rc; - - lddata->asyn_stat = HIP_RDSTAT_NONE; - - rc = lddata->fli->asyncMRead(lddata->fli, pos, data, cnt, size); - - lddata->asyn_stat = HIP_RDSTAT_INPROG; - - return rc; -} - -static en_READ_ASYNC_STATUS HIPLPollRead(st_HIPLOADDATA* lddata) -{ - en_READ_ASYNC_STATUS rdstat = HIP_RDSTAT_INPROG; - en_BIO_ASYNC_ERRCODES pollstat; - - if (!lddata->bypass) - { - return HIP_RDSTAT_NOBYPASS; - } - - if (!lddata->use_async) - { - return HIP_RDSTAT_NOASYNC; - } - - pollstat = lddata->fli->asyncReadStatus(lddata->fli); - - switch (pollstat) - { - case BINIO_ASYNC_INPROG: - { - rdstat = HIP_RDSTAT_INPROG; - break; - } - case BINIO_ASYNC_DONE: - { - rdstat = HIP_RDSTAT_SUCCESS; - lddata->asyn_stat = HIP_RDSTAT_NONE; - break; - } - case BINIO_ASYNC_FAIL: - { - rdstat = HIP_RDSTAT_FAILED; - lddata->asyn_stat = HIP_RDSTAT_NONE; - break; - } - default: - { - lddata->asyn_stat = HIP_RDSTAT_NONE; - break; - } - } - - return rdstat; -} - -static S32 HIPLReadBytes(st_HIPLOADDATA* lddata, char* data, S32 cnt) -{ - if (lddata->bypass) - { - return HIPLBypassRead(lddata, data, cnt, sizeof(char)); - } - else - { - return HIPLBlockRead(lddata, data, cnt, sizeof(char)); - } -} - -static S32 HIPLReadShorts(st_HIPLOADDATA* lddata, S16* data, S32 cnt) -{ - S32 got; - - if (lddata->bypass) - { - got = HIPLBypassRead(lddata, data, cnt, sizeof(S16)); - } - else - { - got = HIPLBlockRead(lddata, data, cnt, sizeof(S16)); - } - - got /= sizeof(S16); - - return got; -} - -static S32 HIPLReadLongs(st_HIPLOADDATA* lddata, S32* data, S32 cnt) -{ - S32 got; - - if (lddata->bypass) - { - got = HIPLBypassRead(lddata, data, cnt, sizeof(S32)); - } - else - { - got = HIPLBlockRead(lddata, data, cnt, sizeof(S32)); - } - - got /= sizeof(S32); - - return got; -} - -static S32 HIPLReadFloats(st_HIPLOADDATA* lddata, F32* data, S32 cnt) -{ - S32 got; - - if (lddata->bypass) - { - got = HIPLBypassRead(lddata, data, cnt, sizeof(F32)); - } - else - { - got = HIPLBlockRead(lddata, data, cnt, sizeof(F32)); - } - - got /= sizeof(F32); - - return got; -} - -static S32 HIPLReadString(st_HIPLOADDATA* lddata, char* buf) -{ - S32 n = 0; - char pad = 0; - - if (lddata->bypass) - { - while (HIPLBypassRead(lddata, &buf[n], 1, sizeof(char))) - { - if (buf[n] == '\0') - { - if (!(n & 1)) - { - HIPLBypassRead(lddata, &pad, 1, sizeof(char)); - } - - break; - } - - n++; - } - } - else - { - while (HIPLBlockRead(lddata, &buf[n], 1, sizeof(char))) - { - if (buf[n] == '\0') - { - if (!(n & 1)) - { - HIPLBlockRead(lddata, &pad, 1, sizeof(char)); - } - - break; - } - - n++; - } - } - - return n; -} diff --git a/src/SB/Core/x/xordarray.cpp b/src/SB/Core/x/xordarray.cpp deleted file mode 100644 index 85f8b41..0000000 --- a/src/SB/Core/x/xordarray.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "xordarray.h" -#include "xMemMgr.h" - -#include - -extern F32 lbl_803CCEE8; // 0.95f -extern F32 lbl_803CCEF0; // 176f - -void XOrdInit(st_XORDEREDARRAY* array, S32 size, S32 tempAlloc) -{ - U32 cnt = 1; - if (size >= 1) - { - cnt = size; - } - if (tempAlloc) - { - array->list = (void**)xMemPushTemp(cnt << 2); - } - else - { - array->list = (void**)xMemAlloc(gActiveHeap, cnt << 2, 0); - } - array->cnt = 0; - array->max = cnt; - array->warnlvl = lbl_803CCEE8 * (cnt ^ 0x80000000); - if (array->warnlvl == array->max) - { - cnt = array->max - 1; - array->warnlvl = cnt & ~((S32)cnt >> 0x1f); - } -} - -void XOrdReset(st_XORDEREDARRAY* array) -{ - array->cnt = 0; -} - -void XOrdDone(st_XORDEREDARRAY* array, S32 wasTempAlloc) -{ - if (array->max != 0 && wasTempAlloc != 0) - { - xMemPopTemp(array->list); - } - array->list = NULL; - array->cnt = 0; - array->max = 0; - array->warnlvl = 0; -} - -void XOrdAppend(st_XORDEREDARRAY* array, void* elt) -{ - if (array->cnt >= array->max) - { - return; - } - array->list[array->cnt++] = elt; -} - -void XOrdInsert(st_XORDEREDARRAY* array, void* elt, XOrdCompareCallback compare) -{ - if (array->cnt < array->max) - { - array->cnt++; - S32 pos = array->cnt - 1; - void* currElement = (void*)(pos * sizeof(void*)); - while (pos > 0) - { - // FIXME: currElement - // S32 score = compare(array->list + currElement - sizeof(void*), elt); - // if (score <= 0) - // { - // array->list[pos] = elt; - // return; - // } - // pos--; - // void* tmp = (void*)(array->list + currElement); - // currElement--; - // *tmp = tmp[-1]; - } - *array->list = elt; - } -} - -void* XOrdRemove(st_XORDEREDARRAY* array, void* elt, S32 index) -{ - if (elt == NULL) - { - if (index < 0) - { - return NULL; - } - if (index >= array->max) - { - return NULL; - } - } - - if ((index >= 0) && (index < array->max)) - { - elt = array->list[index]; - } - else if (elt != NULL) - { - index = -1; - int iVar4 = 0; - for (int i = array->cnt; i > 0; i--) - { - if (array->list[iVar4] == elt) - { - index = iVar4; - break; - } - iVar4++; - } - } - - if (index < 0) - { - return NULL; - } - - array->cnt--; - for (; index < array->cnt; index++) - { - array->list[index] = array->list[index + 1]; - } - - return elt; -} - -S32 XOrdLookup(st_XORDEREDARRAY* array, const void* key, XOrdTestCallback test) -{ - S32 v, index, rightBound, leftBound; - leftBound = 0; - index = array->cnt; - do - { - rightBound = index; - if (rightBound <= leftBound) - { - return -1; - } - index = (leftBound + rightBound) / 2; - v = test(key, array->list[index]); - if (v == 0) - break; - if (0 < v) - { - leftBound = index + 1; - index = rightBound; - } - } while (true); - return index; -} - -void XOrdSort(st_XORDEREDARRAY* array, S32 (*test)(void*, void*)) -{ - void** list = array->list; - S32 num = 1; - // FIXME: cnt?? - // while (num <= cnt) - // { - // num = num * 3 + 1; - // } - for (;;) - { - if (num == 1) - { - return; - } - num = num / 3 + (num >> 0x1f); - num = num - (num >> 0x1f); - S32 numPos = num * sizeof(void*); - void** currItem = list + num; - S32 i = num; - // FIXME: cnt?? - // while (i < cnt) - // { - // // TODO!!! - // } - } -} diff --git a/src/SB/Core/x/xpkrsvc.cpp b/src/SB/Core/x/xpkrsvc.cpp deleted file mode 100644 index 12b7d38..0000000 --- a/src/SB/Core/x/xpkrsvc.cpp +++ /dev/null @@ -1,1768 +0,0 @@ -#include "xpkrsvc.h" - -#include -#include -#include - -#include "xhipio.h" -#include "xutil.h" -#include "xMath.h" -#include "xMemMgr.h" - -extern char xpkrsvc_strings[]; - -// Square and JESway: Function relocation issues will resolve themselves when all the functions -// here 100% match, as it is apparently related to the instruction size of each function -static st_PACKER_READ_FUNCS g_pkr_read_funcmap_original = { 1, - PKR_ReadInit, - PKR_ReadDone, - PKR_LoadLayer, - PKR_GetAssetSize, - PKR_LoadAsset, - PKR_AssetByType, - PKR_AssetCount, - PKR_IsAssetReady, - PKR_SetActive, - PKR_AssetName, - PKR_GetBaseSector, - PKR_GetAssetInfo, - PKR_GetAssetInfoByType, - PKR_PkgHasAsset, - PKR_getPackTimestamp, - PKR_Disconnect }; -static st_PACKER_READ_FUNCS g_pkr_read_funcmap = g_pkr_read_funcmap_original; -st_PACKER_READ_DATA g_readdatainst[16] = {}; - -st_HIPLOADFUNCS* g_hiprf; -U32 g_loadlock; -S32 pkr_sector_size; -volatile S32 g_packinit; -volatile S32 g_memalloc_pair; -volatile S32 g_memalloc_runtot; -volatile S32 g_memalloc_runfree; - -st_PACKER_READ_FUNCS* PKRGetReadFuncs(S32 apiver) -{ - switch (apiver) - { - case 1: - return &g_pkr_read_funcmap; - default: - return NULL; - } -} - -S32 PKRStartup() -{ - if (g_packinit++ == 0) - { - g_pkr_read_funcmap = g_pkr_read_funcmap_original; - g_hiprf = get_HIPLFuncs(); - pkr_sector_size = 32; - } - return g_packinit; -} - -S32 PKRShutdown() -{ - g_packinit--; - return g_packinit; -} - -S32 PKRLoadStep(S32) -{ - return PKR_LoadStep_Async(); -} - -st_PACKER_READ_DATA* PKR_ReadInit(void* userdata, char* pkgfile, U32 opts, S32* cltver, - st_PACKER_ASSETTYPE* typelist) -{ - // I'm pretty sure this is just a pointer to an array on the heap - // But it needs to be an array of pointers to generate correct code ??? - char* tocbuf_RAW[1]; - tocbuf_RAW[0] = NULL; - st_PACKER_READ_DATA* pr = NULL; - S32 uselock = -1; - - PKR_alloc_chkidx(); - char* tocbuf_aligned = (char*)PKR_getmem('PTOC', 0x8000, 'PTOC', 0x40, 1, tocbuf_RAW); - - for (S32 i = 0; i < 16; i++) - { - if (!(g_loadlock & 1 << i)) - { - g_loadlock |= 1 << i; - pr = &g_readdatainst[i]; - uselock = i; - break; - } - } - - if (pr != NULL) - { - memset(pr, 0, sizeof(st_PACKER_READ_DATA)); - pr->lockid = uselock; - pr->userdata = userdata; - pr->opts = opts; - pr->types = typelist; - pr->cltver = -1; - strncpy(pr->packfile, pkgfile, 0x80); - - if (tocbuf_aligned == NULL) - { - pr->pkg = g_hiprf->create(pkgfile, NULL, 0); - } - else - { - pr->pkg = g_hiprf->create(pkgfile, tocbuf_aligned, 0x8000); - } - - if (pr->pkg != NULL) - { - pr->base_sector = g_hiprf->basesector(pr->pkg); - PKR_parse_TOC(pr->pkg, pr); - *cltver = pr->cltver; - g_hiprf->setBypass(pr->pkg, 1, 1); - } - else - { - PKR_ReadDone(pr); - pr = NULL; - *cltver = -1; - } - } - else - { - *cltver = -1; - pr = NULL; - } - - PKR_relmem('PTOC', 0x8000, (void*)tocbuf_RAW[0], 'PTOC', 1); - tocbuf_RAW[0] = NULL; - return pr; -} - -void PKR_ReadDone(st_PACKER_READ_DATA* pr) -{ - S32 i; - S32 j; - S32 lockid; - st_PACKER_ATOC_NODE* assnode; - st_PACKER_LTOC_NODE* laynode; - st_XORDEREDARRAY* tmplist; - - if (pr == NULL) - { - return; - } - for (i = pr->laytoc.cnt - 1; i >= 0; i--) - { - st_PACKER_LTOC_NODE* laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; - for (j = laynode->assref.cnt - 1; j >= 0; j--) - { - assnode = (st_PACKER_ATOC_NODE*)laynode->assref.list[j]; - if (assnode->typeref != NULL && assnode->typeref->assetUnloaded != NULL && - !(assnode->loadflag & 0x100000)) - { - assnode->typeref->assetUnloaded(assnode->memloc, assnode->aid); - } - } - } - - for (i = 0; i < pr->laytoc.cnt; i++) - { - laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; - if (laynode->laymem != NULL) - { - PKR_LayerMemRelease(pr, laynode); - laynode->laymem = NULL; - } - } - - PKR_kiilpool_anode(pr); - - for (i = 0; i < pr->laytoc.cnt; i++) - { - laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; - PKR_oldlaynode(laynode); - } - - XOrdDone(&pr->asstoc, false); - XOrdDone(&pr->laytoc, false); - - for (i = 0; i < 129; i++) - { - tmplist = &pr->typelist[i]; - if (tmplist->max != 0) - { - XOrdDone(tmplist, false); - } - } - - if (pr->pkg != NULL) - { - g_hiprf->destroy(pr->pkg); - pr->pkg = NULL; - } - - lockid = pr->lockid; - memset(pr, 0, sizeof(st_PACKER_READ_DATA)); - g_loadlock &= ~(1 << lockid); -} - -S32 PKR_SetActive(st_PACKER_READ_DATA* pr, en_LAYER_TYPE layer) -{ - S32 result; - S32 rc = 1; - S32 i; - S32 j; - st_PACKER_ATOC_NODE* assnode; - st_PACKER_LTOC_NODE* laynode; - - if (pr == NULL) - { - return 0; - } - - for (i = 0; i < pr->laytoc.cnt; i++) - { - laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; - if (layer > PKR_LTYPE_DEFAULT && laynode->laytyp != layer) - { - continue; - } - - for (j = 0; j < laynode->assref.cnt; j++) - { - assnode = (st_PACKER_ATOC_NODE*)laynode->assref.list[j]; - if (assnode->loadflag & 0x10000 || (assnode->loadflag & 0x80000) == 0) - { - continue; - } - - if (assnode->typeref == NULL) - { - assnode->Name(); - xUtil_idtag2string(assnode->asstype, 0); - } - else if (assnode->typeref->assetLoaded != NULL) - { - if (!(assnode->typeref->assetLoaded(pr->userdata, assnode->aid, assnode->memloc, - assnode->d_size))) - { - rc = 0; - } - else - { - assnode->loadflag |= 0x10000; - } - } - } - } - - return rc; -} - -S32 PKR_parse_TOC(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 done = 0; - S32 is_ok = 0; - U32 cid = g_hiprf->enter(pkg); - while (cid != false) - { - switch (cid) - { - case 'HIPA': - done = LOD_r_HIPA(pkg, pr); - break; - case 'PACK': - LOD_r_PACK(pkg, pr); - if (done) - { - if (pr->asscnt > 0) - { - XOrdInit(&pr->asstoc, pr->asscnt, 0); - PKR_makepool_anode(pr, pr->asscnt); - } - if (pr->laycnt > 0) - { - XOrdInit(&pr->laytoc, pr->laycnt, 0); - } - } - break; - case 'DICT': - LOD_r_DICT(pkg, pr); - PKR_bld_typecnt(pr); - is_ok = true; - break; - case 'STRM': - LOD_r_STRM(pkg, pr); - break; - } - - if (!done) - { - break; - } - - g_hiprf->exit(pkg); - - if (is_ok) - { - break; - } - - cid = g_hiprf->enter(pkg); - } - return done; -} - -S32 PKR_LoadStep_Async() -{ - S32 rc; - static st_PACKER_READ_DATA* curpr = NULL; - static st_PACKER_LTOC_NODE* asynlay = NULL; - - if (asynlay == NULL) - { - PKR_findNextLayerToLoad(&curpr, &asynlay); - - if (asynlay != NULL) - { - if (PKR_layerLoadDest(asynlay->laytyp) != PKR_LDDEST_SKIP && asynlay->laysize > 1 && - asynlay->assref.cnt > 0) - { - asynlay->laymem = PKR_LayerMemReserve(curpr, asynlay); - PKR_drv_guardLayer(asynlay); - st_PACKER_ATOC_NODE* tmpass = (st_PACKER_ATOC_NODE*)asynlay->assref.list[0]; - g_hiprf->setSpot(tmpass->ownpkg, tmpass->d_off); - - if (g_hiprf->readBytes(tmpass->ownpkg, asynlay->laymem, asynlay->laysize)) - { - asynlay->flg_ldstat |= 0x1000000; - } - else - { - PKR_LayerMemRelease(curpr, asynlay); - asynlay->flg_ldstat &= 0xfcffffff; - curpr = NULL; - asynlay = NULL; - } - - rc = 1; - } - else - { - rc = 1; - asynlay->flg_ldstat |= 0x2000000; - asynlay = NULL; - } - } - else - { - rc = 0; - curpr = NULL; - asynlay = NULL; - } - } - else - { - S32 moretodo = g_hiprf->pollRead(curpr->pkg); - if (moretodo == 1) - { - moretodo = PKR_drv_guardVerify(asynlay); - } - - if (!moretodo) - { - rc = 1; - } - else if (moretodo == 1) - { - PKR_updateLayerAssets(asynlay); - - if (PKR_layerTypeNeedsXForm(asynlay->laytyp)) - { - PKR_xformLayerAssets(asynlay); - } - - if (PKR_layerLoadDest(asynlay->laytyp) == PKR_LDDEST_RWHANDOFF) - { - PKR_LayerMemRelease(curpr, asynlay); - } - - rc = 1; - asynlay->flg_ldstat |= 0x2000000; - asynlay = NULL; - } - else - { - en_PKR_LAYER_LOAD_DEST loaddest = PKR_layerLoadDest(asynlay->laytyp); - if (asynlay->laymem != NULL && loaddest == PKR_LDDEST_RWHANDOFF) - { - PKR_LayerMemRelease(curpr, asynlay); - } - - rc = 1; - asynlay->flg_ldstat &= 0xfcffffff; - asynlay = NULL; - curpr = NULL; - } - } - - return rc; -} - -char* PKR_LayerMemReserve(st_PACKER_READ_DATA* pr, st_PACKER_LTOC_NODE* layer) -{ - char* mem = NULL; - if (layer->laymem != NULL) - { - return layer->laymem; - } - - switch (PKR_layerLoadDest(layer->laytyp)) - { - case PKR_LDDEST_SKIP: - break; - case PKR_LDDEST_KEEPSTATIC: - mem = (char*)PKR_getmem('LYR\0', layer->laysize, layer->laytyp + 0x8000, 0x40); - break; - case PKR_LDDEST_KEEPMALLOC: - mem = (char*)PKR_getmem('LYR\0', layer->laysize, layer->laytyp + 0x8000, 0x40, 1, - &layer->laytru); - break; - case PKR_LDDEST_RWHANDOFF: - PKR_push_memmark(); - mem = (char*)PKR_getmem('LYR\0', layer->laysize, layer->laytyp + 0x8000, 0x40); - break; - } - - return mem; -} - -void PKR_LayerMemRelease(st_PACKER_READ_DATA* pr, st_PACKER_LTOC_NODE* layer) -{ - switch (PKR_layerLoadDest(layer->laytyp)) - { - case PKR_LDDEST_SKIP: - break; - case PKR_LDDEST_RWHANDOFF: - PKR_relmem('LYR\0', layer->laysize, layer->laymem, layer->laytyp + 0x8000, 0); - PKR_pop_memmark(); - layer->laymem = NULL; - break; - case PKR_LDDEST_KEEPSTATIC: - PKR_relmem('LYR\0', layer->laysize, layer->laymem, layer->laytyp + 0x8000, 0); - break; - case PKR_LDDEST_KEEPMALLOC: - PKR_relmem('LYR\0', layer->laysize, layer->laytru, layer->laytyp + 0x8000, 1); - layer->laymem = NULL; - layer->laytru = NULL; - break; - } -} - -void PKR_drv_guardLayer(st_PACKER_LTOC_NODE*) -{ -} - -S32 PKR_drv_guardVerify(st_PACKER_LTOC_NODE*) -{ - return 1; -} - -en_PKR_LAYER_LOAD_DEST PKR_layerLoadDest(en_LAYER_TYPE layer) -{ - switch (layer) - { - case PKR_LTYPE_SRAM: - case PKR_LTYPE_CUTSCENE: - return PKR_LDDEST_SKIP; - case PKR_LTYPE_TEXTURE: - case PKR_LTYPE_BSP: - case PKR_LTYPE_MODEL: - return PKR_LDDEST_RWHANDOFF; - case PKR_LTYPE_ANIMATION: - case PKR_LTYPE_JSPINFO: - return PKR_LDDEST_KEEPMALLOC; - case PKR_LTYPE_DEFAULT: - case PKR_LTYPE_VRAM: - case PKR_LTYPE_SNDTOC: - case PKR_LTYPE_CUTSCENETOC: - return PKR_LDDEST_KEEPSTATIC; - default: - return PKR_LDDEST_KEEPSTATIC; - } -} - -S32 PKR_layerTypeNeedsXForm(en_LAYER_TYPE layer) -{ - switch (layer) - { - case PKR_LTYPE_TEXTURE: - case PKR_LTYPE_BSP: - case PKR_LTYPE_MODEL: - return true; - case PKR_LTYPE_DEFAULT: - case PKR_LTYPE_ANIMATION: - case PKR_LTYPE_VRAM: - case PKR_LTYPE_SNDTOC: - case PKR_LTYPE_CUTSCENETOC: - case PKR_LTYPE_JSPINFO: - return true; - case PKR_LTYPE_SRAM: - case PKR_LTYPE_CUTSCENE: - return false; - default: - return false; - } -} - -S32 PKR_findNextLayerToLoad(st_PACKER_READ_DATA** work_on_pkg, st_PACKER_LTOC_NODE** next_layer) -{ - st_PACKER_READ_DATA* tmppr; - st_PACKER_LTOC_NODE* tmplay; - - *next_layer = NULL; - if (*work_on_pkg != NULL) - { - tmppr = *work_on_pkg; - for (S32 i = 0; i < tmppr->laytoc.cnt; i++) - { - tmplay = (st_PACKER_LTOC_NODE*)tmppr->laytoc.list[i]; - if (!(tmplay->flg_ldstat & 0x2000000)) - { - *next_layer = tmplay; - *work_on_pkg = tmppr; - break; - } - } - } - - if (*next_layer == NULL) - { - tmppr = g_readdatainst; - for (S32 i = 0; i < 16; i++, tmppr++) - { - if ((g_loadlock & 1 << i) == 0 || tmppr == *work_on_pkg) - { - continue; - } - - for (S32 j = 0; j < tmppr->laytoc.cnt; j++) - { - tmplay = (st_PACKER_LTOC_NODE*)tmppr->laytoc.list[j]; - if (!(tmplay->flg_ldstat & 0x2000000)) - { - *next_layer = tmplay; - *work_on_pkg = tmppr; - break; - } - } - - if (*next_layer != NULL) - { - break; - } - } - } - - return *next_layer != NULL; -} - -void PKR_updateLayerAssets(st_PACKER_LTOC_NODE* laynode) -{ - st_PACKER_ATOC_NODE* tmpass = NULL; - for (S32 i = 0; i < laynode->assref.cnt; i++) - { - tmpass = (st_PACKER_ATOC_NODE*)laynode->assref.list[i]; - if (tmpass->d_off > 0 && tmpass->d_size > 0) - { - break; - } - tmpass = NULL; - } - - if (tmpass != NULL) - { - S32 lay_hip_pos = tmpass->d_off; - for (S32 i = 0; i < laynode->assref.cnt; i++) - { - st_PACKER_ATOC_NODE* tmpass = (st_PACKER_ATOC_NODE*)laynode->assref.list[i]; - if (!(tmpass->loadflag & 0x100000)) - { - if (tmpass->loadflag & 0x200000) - { - tmpass->Name(); - tmpass->memloc = NULL; - } - else - { - tmpass->memloc = laynode->laymem + (tmpass->d_off - lay_hip_pos); - tmpass->loadflag |= 0x80000; - tmpass->Name(); - } - } - } - } -} - -void PKR_xformLayerAssets(st_PACKER_LTOC_NODE* laynode) -{ - S32 i; - S32 will_be_dumped = false; - en_PKR_LAYER_LOAD_DEST loaddest = PKR_layerLoadDest(laynode->laytyp); - - if (loaddest == PKR_LDDEST_RWHANDOFF) - { - will_be_dumped = true; - } - - for (i = 0; i < laynode->assref.cnt; i++) - { - st_PACKER_ATOC_NODE* tmpass = (st_PACKER_ATOC_NODE*)laynode->assref.list[i]; - if ((tmpass->loadflag & 0x100000) == 0) - { - PKR_xform_asset(tmpass, will_be_dumped); - if (will_be_dumped && tmpass->x_size < 1) - { - tmpass->Name(); - tmpass->memloc = NULL; - } - } - } -} - -void PKR_xform_asset(st_PACKER_ATOC_NODE* assnode, S32 dumpable_layer) -{ - if (!(assnode->infoflag & 4)) - { - if (assnode->typeref == NULL) - { - return; - } - - if (assnode->typeref->readXForm != NULL) - { - assnode->Name(); - xUtil_idtag2string(assnode->asstype, 0); - } - else - { - return; - } - } - - st_PACKER_ASSETTYPE* atype = assnode->typeref; - if (atype == NULL) - { - assnode->Name(); - } - else if (atype->readXForm == NULL) - { - assnode->Name(); - } - else - { - if (assnode->d_size == 0) - { - assnode->Name(); - xUtil_idtag2string(assnode->asstype, 0); - assnode->memloc = NULL; - } - - char* xformloc = - (char*)atype->readXForm(assnode->ownpr->userdata, assnode->aid, assnode->memloc, - assnode->d_size, (U32*)&assnode->x_size); - if (!dumpable_layer && assnode->memloc == xformloc && assnode->x_size != 0) - { - assnode->Name(); - } - else if (assnode->d_size == 0 || assnode->x_size == 0) - { - assnode->memloc = NULL; - assnode->loadflag |= 0x200000; - } - else - { - assnode->memloc = xformloc; - } - } -} - -void* PKR_FindAsset(st_PACKER_READ_DATA* pr, U32 aid) -{ - st_PACKER_ATOC_NODE* assnode = NULL; - S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); - - if (idx >= 0) - { - assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; - } - - if (assnode != NULL) - { - if (assnode->memloc == NULL) - { - assnode->Name(); - } - - return assnode->memloc; - } - return NULL; -} - -S32 PKR_LoadLayer(st_PACKER_READ_DATA* pr, en_LAYER_TYPE layer) -{ - return 0; -} - -void* PKR_LoadAsset(st_PACKER_READ_DATA* pr, U32 aid, char*, void*) -{ - return PKR_FindAsset(pr, aid); -} - -U32 PKR_GetAssetSize(st_PACKER_READ_DATA* pr, U32 aid) -{ - st_PACKER_ATOC_NODE* assnode = NULL; - S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); - - if (idx > -1) - { - assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; - } - - if (assnode != NULL) - { - if (assnode->x_size > 0) - { - return assnode->x_size; - } - return assnode->d_size; - } - return 0; -} - -S32 PKR_AssetCount(st_PACKER_READ_DATA* pr, U32 type) -{ - S32 count = 0; - if (type == 0) - { - return pr->asstoc.cnt; - } - else - { - S32 idx = PKR_typeHdlr_idx(pr, type); - if (idx >= 0) - { - st_XORDEREDARRAY* tmplist = &pr->typelist[idx]; - count = tmplist->cnt; - } - } - return count; -} - -void* PKR_AssetByType(st_PACKER_READ_DATA* pr, U32 type, S32 idx, U32* size) -{ - if (size != NULL) - { - *size = 0; - } - - if (idx < 0) - { - idx = 0; - } - - S32 typeidx = PKR_typeHdlr_idx(pr, type); - if (typeidx < 0) - { - return 0; - } - - st_XORDEREDARRAY* tmplist = &pr->typelist[typeidx]; - if (idx >= tmplist->cnt) - { - return 0; - } - - st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)tmplist->list[idx]; - if (size != NULL) - { - *size = assnode->d_size; - } - return assnode->memloc; -} - -// -S32 PKR_IsAssetReady(st_PACKER_READ_DATA* pr, U32 aid) -{ - S32 ready = false; - S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); - if (idx >= 0) - { - st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; - if (assnode->loadflag & 0x80000) - { - ready = true; - } - else - { - ready = false; - } - } - - return ready; -} - -U32 PKR_getPackTimestamp(st_PACKER_READ_DATA* pr) -{ - return pr->time_made; -} - -void PKR_Disconnect(st_PACKER_READ_DATA* pr) -{ - if (pr->pkg != NULL) - { - g_hiprf->destroy(pr->pkg); - pr->pkg = NULL; - } -} - -U32 PKRAssetIDFromInst(void* inst) -{ - return ((st_PACKER_ATOC_NODE*)inst)->aid; -} - -char* PKR_AssetName(st_PACKER_READ_DATA* pr, U32 aid) -{ - char* name = NULL; - - if (aid == 0) - { - return NULL; - } - else - { - S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); - if (idx >= 0) - { - name = ((st_PACKER_ATOC_NODE*)pr->asstoc.list[idx])->Name(); - } - } - - return name; -} - -U32 PKR_GetBaseSector(st_PACKER_READ_DATA* pr) -{ - return pr->base_sector; -} - -S32 PKR_GetAssetInfo(st_PACKER_READ_DATA* pr, U32 aid, st_PKR_ASSET_TOCINFO* tocainfo) -{ - memset(tocainfo, 0, sizeof(st_PKR_ASSET_TOCINFO)); - S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); - if (idx >= 0) - { - st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; - tocainfo->aid = aid; - tocainfo->typeref = assnode->typeref; - tocainfo->sector = pr->base_sector + assnode->d_off / pkr_sector_size; - tocainfo->plus_offset = assnode->d_off % pkr_sector_size; - tocainfo->size = assnode->d_size; - tocainfo->mempos = assnode->memloc; - } - return idx >= 0 ? 1 : 0; -} - -S32 PKR_GetAssetInfoByType(st_PACKER_READ_DATA* pr, U32 type, S32 idx, - st_PKR_ASSET_TOCINFO* tocainfo) -{ - memset(tocainfo, 0, sizeof(st_PKR_ASSET_TOCINFO)); - if (idx < 0) - { - idx = 0; - } - - S32 typeidx = PKR_typeHdlr_idx(pr, type); - if (typeidx < 0) - { - return 0; - } - - st_XORDEREDARRAY* tmplist = &pr->typelist[typeidx]; - if (idx >= tmplist->cnt) - { - return 0; - } - - st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)tmplist->list[idx]; - tocainfo->aid = assnode->aid; - tocainfo->typeref = assnode->typeref; - tocainfo->sector = pr->base_sector + assnode->d_off / pkr_sector_size; - tocainfo->plus_offset = assnode->d_off % pkr_sector_size; - tocainfo->size = assnode->d_size; - tocainfo->mempos = assnode->memloc; - - return 1; -} - -S32 PKR_PkgHasAsset(st_PACKER_READ_DATA* pr, U32 aid) -{ - S32 idx = XOrdLookup(&pr->asstoc, (void*)aid, OrdTest_R_AssetID); - if (idx < 0) - { - return 0; - } - - S32 rc = 1; - st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; - if (assnode->loadflag & 0x100000) - { - rc = 0; - } - else if (assnode->loadflag & 0x200000) - { - rc = 0; - } - return rc; -} - -S32 PKR_FRIEND_assetIsGameDup(U32 aid, const st_PACKER_READ_DATA* skippr, S32 oursize, U32 ourtype, - U32 chksum, char*) -{ - S32 is_dup = 0; - if (aid == 0x7ab6743a) - { - return 0; - } - if (aid == 0x98a3f56c) - { - return 0; - } - - for (int i = 0; i < 16; i++) - { - if ((g_loadlock & 1 << i) == 0 || &g_readdatainst[i] == skippr) - { - continue; - } - - S32 idx = XOrdLookup(&g_readdatainst[i].asstoc, (void*)aid, OrdTest_R_AssetID); - if (idx < 0) - { - continue; - } - - st_PACKER_ATOC_NODE* tmp_ass = (st_PACKER_ATOC_NODE*)g_readdatainst[i].asstoc.list[idx]; - if ((tmp_ass->loadflag & 0x80000) == 0 && tmp_ass->asstype != 0x534e4420 && - tmp_ass->asstype != 0x534e4453) - { - continue; - } - - tmp_ass->Name(); - xUtil_idtag2string(tmp_ass->asstype, 0); - - if (ourtype != 0 && ourtype != tmp_ass->asstype) - { - tmp_ass->Name(); - xUtil_idtag2string(tmp_ass->asstype, 0); - xUtil_idtag2string(ourtype, 1); - } - if (oursize >= 0 && oursize != tmp_ass->d_size) - { - tmp_ass->Name(); - xUtil_idtag2string(tmp_ass->asstype, 0); - } - if (chksum != 0 && chksum != tmp_ass->d_chksum) - { - tmp_ass->Name(); - xUtil_idtag2string(tmp_ass->asstype, 0); - } - is_dup = 1; - break; - } - - return is_dup; -} - -S32 PKR_makepool_anode(st_PACKER_READ_DATA* pr, S32 cnt) -{ - if (cnt == 0) - { - return 0; - } - - st_PACKER_ATOC_NODE* assnode = - (st_PACKER_ATOC_NODE*)PKR_getmem('ANOD', cnt * sizeof(st_PACKER_ATOC_NODE), 'FAKE', 0x40); - if (assnode != NULL) - { - pr->pool_anode = assnode; - pr->pool_nextaidx = 0; - } - return assnode != NULL ? cnt * sizeof(st_PACKER_ATOC_NODE) : 0; -} - -void PKR_kiilpool_anode(st_PACKER_READ_DATA* pr) -{ - if (pr->asscnt == 0) - { - return; - } - - PKR_relmem('ANOD', pr->asscnt * sizeof(st_PACKER_ATOC_NODE), pr->pool_anode, 'FAKE', 0); - pr->pool_anode = NULL; - pr->pool_nextaidx = 0; -} - -// -st_PACKER_ATOC_NODE* PKR_newassnode(st_PACKER_READ_DATA* pr, U32 aid) -{ - S32 idx = pr->pool_nextaidx; - st_PACKER_ATOC_NODE* newnode = (st_PACKER_ATOC_NODE*)&pr->pool_anode[idx]; - pr->pool_nextaidx++; - - memset(newnode, 0, sizeof(st_PACKER_ATOC_NODE)); - newnode->aid = aid; - return newnode; -} - -st_PACKER_LTOC_NODE* PKR_newlaynode(en_LAYER_TYPE layer, S32 refcnt) -{ - st_PACKER_LTOC_NODE* newnode = - (st_PACKER_LTOC_NODE*)PKR_getmem('LNOD', sizeof(st_PACKER_LTOC_NODE), layer + 0x8000, 0x40); - memset(newnode, 0, sizeof(st_PACKER_LTOC_NODE)); - - newnode->laytyp = layer; - XOrdInit(&newnode->assref, refcnt <= 1 ? 2 : refcnt, 0); - return newnode; -} - -void PKR_oldlaynode(st_PACKER_LTOC_NODE* laynode) -{ - XOrdDone(&laynode->assref, 0); - PKR_relmem('LNOD', sizeof(st_PACKER_LTOC_NODE), laynode, laynode->laytyp + 0x8000, 0); -} - -S32 OrdComp_R_Asset(void* vkey, void* vitem) -{ - S32 rc; - if (*(U32*)vkey < *(U32*)vitem) - { - rc = -1; - } - else if (*(U32*)vkey > *(U32*)vitem) - { - rc = 1; - } - else - { - rc = 0; - } - return rc; -} - -S32 OrdTest_R_AssetID(const void* vkey, void* vitem) -{ - S32 rc; - if ((U32)vkey < *(U32*)vitem) - { - rc = -1; - } - else if ((U32)vkey > *(U32*)vitem) - { - rc = 1; - } - else - { - rc = 0; - } - return rc; -} - -S32 LOD_r_HIPA(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - pr->pkgver = 'HIPA'; - return 1; -} - -S32 LOD_r_PACK(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - U32 cid = g_hiprf->enter(pkg); - while (cid != 0) - { - switch (cid) - { - case 'PVER': - LOD_r_PVER(pkg, pr); - break; - case 'PFLG': - LOD_r_PFLG(pkg, pr); - break; - case 'PCNT': - LOD_r_PCNT(pkg, pr); - break; - case 'PCRT': - LOD_r_PCRT(pkg, pr); - break; - case 'PMOD': - LOD_r_PMOD(pkg, pr); - break; - case 'PLAT': - LOD_r_PLAT(pkg, pr); - break; - } - g_hiprf->exit(pkg); - cid = g_hiprf->enter(pkg); - } - return 1; -} - -S32 LOD_r_PVER(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 ver = 0; - g_hiprf->readLongs(pkg, &ver, 1); - pr->subver = ver; - - if (ver < 2) - { - PKR_spew_verhist(); - } - - // S32 amt = -1; - ver = -1; - g_hiprf->readLongs(pkg, &ver, 1); - pr->cltver = ver; - - ver = -1; - S32 amt = g_hiprf->readLongs(pkg, &ver, 1); - if (amt != 1) - { - pr->compatver = 1; - } - else - { - pr->compatver = ver; - } - return 1; -} - -S32 LOD_r_PFLG(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 flg = 0; - g_hiprf->readLongs(pkg, &flg, 1); - return 1; -} - -S32 LOD_r_PCNT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 cnt = 0; - g_hiprf->readLongs(pkg, &cnt, 1); - pr->asscnt = cnt; - g_hiprf->readLongs(pkg, &cnt, 1); - pr->laycnt = cnt; - g_hiprf->readLongs(pkg, &cnt, 1); - g_hiprf->readLongs(pkg, &cnt, 1); - g_hiprf->readLongs(pkg, &cnt, 1); - return 1; -} - -S32 LOD_r_PCRT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 time = 0; - char arr[256] = {}; - - g_hiprf->readLongs(pkg, &time, 1); - pr->time_made = time; - - if (pr->subver > 1) - { - g_hiprf->readString(pkg, arr); - } - return 1; -} - -S32 LOD_r_PMOD(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 time_mod = 0; - g_hiprf->readLongs(pkg, &time_mod, 1); - pr->time_mod = time_mod; - return 1; -} - -S32 ValidatePlatform(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr, S32 plattag, char* plat, - char* vid, char* lang, char* title) -{ - char fullname[128] = {}; - sprintf(fullname, "%s %s %s %s", plat, vid, lang, title); - - bool rc = false; - if ((strcmp(plat, "Game Cube") == 0 || strcmp(plat, "Xbox") == 0 || - strcmp(plat, "PlayStation 2") == 0)) - { - rc = true; - } - if (!rc) - { - return 0; - } - - rc = false; - if (strcmp(vid, "NTSC") == 0 || strcmp(vid, "PAL") == 0) - { - rc = true; - } - if (!rc) - { - return 0; - } - - rc = false; - if (strcmp(lang, "US Common") == 0 || strcmp(lang, "United Kingdom") == 0 || - strcmp(lang, "French") == 0 || strcmp(lang, "German") == 0) - { - rc = true; - } - if (!rc) - { - return 0; - } - - rc = false; - if (strcmp(title, "Sponge Bob") == 0 || strcmp(title, "Incredibles") == 0 || - strcmp(title, "Jimmy Newtron") == 0) - { - rc = true; - } - if (!rc) - { - return 0; - } - - rc = !(bool)(strcmp(plat, "Game Cube")); - if (!rc) - { - return 0; - } - - rc = !(strcmp(vid, "NTSC")); - if (!rc) - { - return 0; - } - - rc = !(strcmp(lang, "US Common")); - if (!rc) - { - return 0; - } - - rc = !(strcmp(title, "Sponge Bob")); - if (!rc) - { - return 0; - } - return 1; -} - -S32 LOD_r_PLAT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 result = 1; - S32 plattag = 0; - char platname[32] = {}; - char vidname[32] = {}; - char langname[32] = {}; - char titlename[32] = {}; - - g_hiprf->readLongs(pkg, &plattag, 1); - g_hiprf->readString(pkg, platname); - g_hiprf->readString(pkg, vidname); - g_hiprf->readString(pkg, langname); - if (g_hiprf->readString(pkg, titlename) == 0) - { - strcpy(titlename, ""); - } - if (ValidatePlatform(pkg, pr, plattag, platname, vidname, langname, titlename) == 0) - { - result = 0; - } - return result; -} - -S32 LOD_r_DICT(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - U32 cid = g_hiprf->enter(pkg); - while (cid != 0) - { - switch (cid) - { - case 'ATOC': - LOD_r_ATOC(pkg, pr); - XOrdSort(&pr->asstoc, OrdComp_R_Asset); - break; - case 'LTOC': - LOD_r_LTOC(pkg, pr); - break; - } - - g_hiprf->exit(pkg); - cid = g_hiprf->enter(pkg); - } - return 1; -} - -S32 LOD_r_ATOC(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - U32 cid = g_hiprf->enter(pkg); - while (cid != 0) - { - switch (cid) - { - case 'AINF': - LOD_r_AINF(pkg, pr); - break; - case 'AHDR': - LOD_r_AHDR(pkg, pr); - break; - } - g_hiprf->exit(pkg); - cid = g_hiprf->enter(pkg); - } - return 1; -} - -S32 LOD_r_AINF(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 ival = 0; - g_hiprf->readLongs(pkg, &ival, 1); - return 1; -} - -S32 LOD_r_AHDR(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 ival = 0; - - g_hiprf->readLongs(pkg, &ival, 1); - st_PACKER_ATOC_NODE* assnode = PKR_newassnode(pr, ival); - assnode->ownpr = pr; - assnode->ownpkg = pkg; - XOrdAppend(&pr->asstoc, assnode); - - g_hiprf->readLongs(pkg, &ival, 1); - assnode->asstype = ival; - assnode->typeref = PKR_type2typeref(assnode->asstype, pr->types); - - g_hiprf->readLongs(pkg, &ival, 1); - assnode->d_off = ival; - - g_hiprf->readLongs(pkg, &ival, 1); - assnode->d_size = ival; - assnode->readrem = ival; - assnode->readcnt = 0; - if (assnode->d_size < 1) - { - assnode->loadflag |= 0x200000; - } - - g_hiprf->readLongs(pkg, &ival, 1); - assnode->d_pad = ival; - - g_hiprf->readLongs(pkg, &ival, 1); - assnode->infoflag = ival; - - U32 cid = g_hiprf->enter(pkg); - while (cid != 0) - { - switch (cid) - { - case 'ADBG': - LOD_r_ADBG(pkg, pr, assnode); - } - g_hiprf->exit(pkg); - cid = g_hiprf->enter(pkg); - } - - S32 isdup = PKR_FRIEND_assetIsGameDup(assnode->aid, pr, assnode->d_size, assnode->asstype, - assnode->d_chksum, NULL); - if (isdup) - { - assnode->loadflag |= 0x100000; - } - return 1; -} - -S32 LOD_r_ADBG(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr, st_PACKER_ATOC_NODE* assnode) -{ - S32 ival = 0; - char tmpbuf[256] = {}; - - g_hiprf->readLongs(pkg, &ival, 1); - assnode->assalign = ival; - - g_hiprf->readString(pkg, tmpbuf); - tmpbuf[0] = 0; - - g_hiprf->readString(pkg, tmpbuf); - - if (pr->subver > 1) - { - g_hiprf->readLongs(pkg, &ival, 1); - assnode->d_chksum = ival; - } - - return 1; -} - -S32 LOD_r_LTOC(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - U32 cid = g_hiprf->enter(pkg); - while (cid != 0) - { - switch (cid) - { - case 'LINF': - LOD_r_LINF(pkg, pr); - break; - case 'LHDR': - LOD_r_LHDR(pkg, pr); - break; - } - g_hiprf->exit(pkg); - cid = g_hiprf->enter(pkg); - } - return 1; -} - -S32 LOD_r_LINF(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 ival = 0; - g_hiprf->readLongs(pkg, &ival, 1); - return 1; -} - -S32 LOD_r_LHDR(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 i; - S32 ival = 0; - S32 refcnt = 0; - - g_hiprf->readLongs(pkg, &ival, 1); - en_LAYER_TYPE laytyp = (en_LAYER_TYPE)ival; - g_hiprf->readLongs(pkg, &refcnt, 1); - st_PACKER_LTOC_NODE* laynode = PKR_newlaynode(laytyp, refcnt); - XOrdAppend(&pr->laytoc, laynode); - - for (i = 0; i < refcnt; i++) - { - g_hiprf->readLongs(pkg, &ival, 1); - S32 idx = XOrdLookup(&pr->asstoc, (void*)ival, OrdTest_R_AssetID); - st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)pr->asstoc.list[idx]; - XOrdAppend(&laynode->assref, assnode); - - if (i != refcnt - 1) - { - laynode->laysize += assnode->d_size + assnode->d_pad; - } - else - { - laynode->laysize += assnode->d_size; - } - } - - if (laynode->laysize > 0) - { - laynode->laysize = laynode->laysize + 0x7ff & 0xfffff800; - } - - U32 cid = g_hiprf->enter(pkg); - while (cid != NULL) - { - switch (cid) - { - case 'LDBG': - LOD_r_LDBG(pkg, pr, laynode); - break; - } - g_hiprf->exit(pkg); - cid = g_hiprf->enter(pkg); - } - return 1; -} - -S32 LOD_r_LDBG(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr, st_PACKER_LTOC_NODE* laynode) -{ - S32 ivar = 0; - if (pr->subver > 1) - { - g_hiprf->readLongs(pkg, &ivar, 1); - laynode->chksum = ivar; - } - return 1; -} - -S32 LOD_r_STRM(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - U32 cid = g_hiprf->enter(pkg); - while (cid != 0) - { - switch (cid) - { - case 'DHDR': - LOD_r_DHDR(pkg, pr); - break; - case 'DPAK': - LOD_r_DPAK(pkg, pr); - break; - } - g_hiprf->exit(pkg); - cid = g_hiprf->enter(pkg); - } - return 1; -} - -S32 LOD_r_DHDR(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - S32 ivar = 0; - g_hiprf->readLongs(pkg, &ivar, 1); - return 1; -} - -S32 LOD_r_DPAK(st_HIPLOADDATA* pkg, st_PACKER_READ_DATA* pr) -{ - return 1; -} - -void PKR_spew_verhist() -{ -} - -st_PACKER_ASSETTYPE* PKR_type2typeref(U32 asstype, st_PACKER_ASSETTYPE* types) -{ - st_PACKER_ASSETTYPE* da_type = NULL; - if (types != NULL) - { - for (st_PACKER_ASSETTYPE* tmptype = types; tmptype->typetag != 0; tmptype++) - { - if (tmptype->typetag == asstype) - { - da_type = tmptype; - break; - } - } - } - if (da_type == NULL) - { - xUtil_idtag2string(asstype, 0); - } - return da_type; -} - -void PKR_bld_typecnt(st_PACKER_READ_DATA* pr) -{ - st_PACKER_LTOC_NODE* laynode; - st_PACKER_ATOC_NODE* assnode; - S32 j; - S32 i; - S32 typcnt[129] = {}; - st_XORDEREDARRAY* tmplist; - U32 lasttype = 0; - S32 lastidx = 0; - - for (i = 0; i < pr->laytoc.cnt; i++) - { - laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; - for (j = 0; j < laynode->assref.cnt; j++) - { - assnode = (st_PACKER_ATOC_NODE*)laynode->assref.list[j]; - if (!(assnode->loadflag & 0x100000) && !(assnode->loadflag & 0x200000)) - { - S32 idx; - if (lasttype != 0 && assnode->asstype == lasttype) - { - idx = lastidx; - } - else - { - idx = PKR_typeHdlr_idx(pr, assnode->asstype); - lastidx = idx; - lasttype = assnode->asstype; - } - - if (idx < 0) - { - xUtil_idtag2string(assnode->asstype, 0); - assnode->Name(); - typcnt[128]++; - } - else - { - typcnt[idx]++; - } - } - } - } - - for (i = 0; i < 129; i++) - { - if (typcnt[i] >= 1) - { - XOrdInit(&pr->typelist[i], typcnt[i] > 1 ? typcnt[i] : 2, false); - } - } - - for (i = 0; i < pr->laytoc.cnt; i++) - { - st_PACKER_LTOC_NODE* laynode = (st_PACKER_LTOC_NODE*)pr->laytoc.list[i]; - for (j = 0; j < laynode->assref.cnt; j++) - { - st_PACKER_ATOC_NODE* assnode = (st_PACKER_ATOC_NODE*)laynode->assref.list[j]; - if (!(assnode->loadflag & 0x100000) && !(assnode->loadflag & 0x200000)) - { - S32 idx; - if (lasttype != 0 && assnode->asstype == lasttype) - { - idx = lastidx; - } - else - { - idx = PKR_typeHdlr_idx(pr, assnode->asstype); - lastidx = idx; - lasttype = assnode->asstype; - } - - st_XORDEREDARRAY* tmplist; - if (idx < 0) - { - tmplist = &pr->typelist[128]; - } - else - { - tmplist = &pr->typelist[idx]; - } - XOrdAppend(tmplist, assnode); - } - } - } -} - -S32 PKR_typeHdlr_idx(st_PACKER_READ_DATA* pr, U32 type) -{ - S32 idx = -1; - int i = 0; - st_PACKER_ASSETTYPE* tmptype = pr->types; - while (tmptype->typetag != 0) - { - if (tmptype->typetag == type) - { - idx = i; - break; - } - i++; - tmptype++; - } - - return idx; -} - -void PKR_alloc_chkidx() -{ -} - -void* PKR_getmem(U32 id, S32 amount, U32 ui, S32 align) -{ - return PKR_getmem(id, amount, ui, align, false, NULL); -} - -void* PKR_getmem(U32 id, S32 amount, U32, S32 align, S32 isTemp, char** memtrue) -{ - if (amount == 0) - { - return NULL; - } - - void* memptr; - - if (isTemp) - { - memptr = xMemPushTemp(amount + align); - - if (memtrue != NULL) - { - *memtrue = (char*)memptr; - } - - if (align != 0) - { - // TODO: wtf is this - memptr = (void*)(-align & (U32)((S32)memptr + align - 1)); - } - } - else - { - memptr = xMemAlloc(gActiveHeap, amount, align); - } - - if (memptr != NULL) - { - memset(memptr, 0, amount); - } - - g_memalloc_pair++; - g_memalloc_runtot += amount; - if (g_memalloc_runtot < 0) - { - g_memalloc_runtot = amount; - } - - if (memptr != NULL) - { - xUtil_idtag2string(id, 0); - } - else - { - xUtil_idtag2string(id, 0); - } - - return memptr; -} - -void PKR_relmem(U32 id, S32 blksize, void* memptr, U32, S32 isTemp) -{ - g_memalloc_pair--; - g_memalloc_runfree += blksize; - if (g_memalloc_runfree < 0) - { - g_memalloc_runfree = blksize; - } - - xUtil_idtag2string(id, 0); - if (memptr != NULL && blksize > 0) - { - if (isTemp) - { - xMemPopTemp(memptr); - } - else - { - xUtil_idtag2string(id, 1); - } - } -} - -void PKR_push_memmark() -{ - xMemPushBase(); -} - -void PKR_pop_memmark() -{ - xMemPopBase(xMemGetBase() - 1); -} - -char* st_PACKER_ATOC_NODE::Name() const -{ - return xpkrsvc_strings + 82; -} diff --git a/src/SB/Core/x/xsavegame.cpp b/src/SB/Core/x/xsavegame.cpp deleted file mode 100644 index ea40be0..0000000 --- a/src/SB/Core/x/xsavegame.cpp +++ /dev/null @@ -1,1480 +0,0 @@ -#include "xsavegame.h" - -#include -#include -#include - -#include "xutil.h" -#include "xMemMgr.h" -#include "isavegame.h" - -S32 g_xsginit; -st_XSAVEGAME_DATA g_xsgdata = {}; -st_XSAVEGAME_LEADER g_leaders[3] = {}; -static XSGAutoData g_autodata; - -S32 xSGStartup() -{ - if (g_xsginit++ == 0) - { - xUtilStartup(); - iSGStartup(); - memset(&g_xsgdata, 0, sizeof(st_XSAVEGAME_DATA)); - } - xSGAutoSave_Startup(); - return g_xsginit; -} - -S32 xSGShutdown() -{ - g_xsginit--; - if (g_xsginit == 0) - { - iSGShutdown(); - xUtilShutdown(); - } - return g_xsginit; -} - -st_XSAVEGAME_DATA* xSGInit(en_SAVEGAME_MODE mode) -{ - st_XSAVEGAME_DATA* xsgdata = &g_xsgdata; - if (g_xsgdata.stage != 0) - { - return NULL; - } - - xsgdata->mode = mode; - xsgdata->chksum = xUtil_crc_init(); - xsgdata->upd_tally = 1; - xsgdata->file_chksum = 0; - xsgdata->read_chksum = xUtil_crc_init(); - xsgdata->stage |= 1; - xsgdata->isgsess = iSGSessionBegin(xsgdata, xSG_cb_ISGChange, 0); - - if (mode == XSG_MODE_LOAD) - { - xSGAddLoadClient(xsgdata, 'LEDR', xsgdata, xSG_cb_leader_load); - } - else - { - xSGAddSaveClient(xsgdata, 'LEDR', xsgdata, xSG_cb_leader_svinfo, xSG_cb_leader_svproc); - } - - memset(&g_leaders, 0, sizeof(g_leaders)); - return xsgdata; -} - -S32 xSGDone(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - if (!(xsgdata->stage & 1)) - { - result = 0; - } - - if (xsgdata->isgsess != NULL) - { - iSGSessionEnd(xsgdata->isgsess); - } - if (xsgdata->mode == XSG_MODE_SAVE) - { - if (xsgdata->membuf != (char*)0x0) - { - xUtil_idtag2string('XSGS', 0); - xMemPopTemp(xsgdata->membuf); - xsgdata->membuf = (char*)0x0; - xsgdata->memsize = 0; - xsgdata->buf_curpos = (char*)0x0; - } - } - else if (xsgdata->mode == XSG_MODE_LOAD) - { - if (xsgdata->membuf != NULL) - { - xUtil_idtag2string('XSGL', 0); - xMemPopTemp(xsgdata->loadbuf); - xsgdata->loadbuf = NULL; - xsgdata->loadsize = 0; - xsgdata->walkpos = NULL; - xsgdata->walkremain = 0; - } - if (xsgdata->loadbuf != NULL) - { - xMemPopTemp(xsgdata->loadbuf); - xsgdata->loadbuf = NULL; - xsgdata->walkpos = NULL; - xsgdata->walkremain = 0; - } - } - - memset(&g_xsgdata, 0, sizeof(st_XSAVEGAME_DATA)); - memset(&g_leaders, 0, sizeof(g_leaders)); - return result; -} - -S32 xSGCheckForCorruptFiles(st_XSAVEGAME_DATA* xsgdata, char files[][64]) -{ - return iSGCheckForCorruptFiles(xsgdata->isgsess, files); -} - -S32 xSGTgtCount(st_XSAVEGAME_DATA* xsgdata, S32* max) -{ - return iSGTgtCount(xsgdata->isgsess, max); -} - -S32 xSGTgtPhysSlotIdx(st_XSAVEGAME_DATA* xsgdata, S32 tidx) -{ - return iSGTgtPhysSlotIdx(xsgdata->isgsess, tidx); -} - -S32 xSGTgtIsFormat(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32* badEncode) -{ - S32 result = 0; - U32 state = iSGTgtState(xsgdata->isgsess, tidx, NULL); - if (state & 0x4000000) - { - if (badEncode != NULL) - { - *badEncode = 1; - } - } - else if (state & 2) - { - result = 1; - } - - S32 rc = -1; - if (!(state & 0x1000000)) - { - rc = result; - } - return rc; -} - -S32 xSGTgtFormatTgt(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32* canRecover) -{ - return iSGTgtFormat(xsgdata->isgsess, tidx, 0, canRecover); -} - -S32 xSGTgtSelect(st_XSAVEGAME_DATA* xsgdata, S32 tidx) -{ - S32 result = iSGTgtSetActive(xsgdata->isgsess, tidx); - if (result != 0 && xSG_chdir_gamedir(xsgdata) != 0) - { - xSG_grab_leaders(xsgdata); - } - return result; -} - -S32 xSGTgtHasGameDir(st_XSAVEGAME_DATA* xsgdata, S32 tidx) -{ - S32 rc = iSGTgtSetActive(xsgdata->isgsess, tidx); - if (rc != 0) - { - return xSG_chdir_gamedir(xsgdata); - } - return rc; -} - -S32 xSGTgtHaveRoom(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32 fsize, S32 slotidx, - S32* bytesNeeded, S32* availOnDisk, S32* needFile) -{ - char fname[256] = {}; - - if (slotidx < 0) - { - return iSGTgtHaveRoom(xsgdata->isgsess, tidx, fsize, NULL, NULL, bytesNeeded, availOnDisk, - needFile); - } - - strcpy(fname, iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, slotidx)); - return iSGTgtHaveRoom(xsgdata->isgsess, tidx, fsize, NULL, fname, bytesNeeded, availOnDisk, - needFile); -} - -S32 xSGTgtHaveRoomStartup(st_XSAVEGAME_DATA* xsgdata, S32 tidx, S32 fsize, S32 slotidx, - S32* bytesNeeded, S32* availOnDisk, S32* needFile) -{ - char fname[256] = {}; - - if (slotidx < 0) - { - return iSGTgtHaveRoomStartup(xsgdata->isgsess, tidx, fsize, NULL, NULL, bytesNeeded, - availOnDisk, needFile); - } - - strcpy(fname, iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, slotidx)); - return iSGTgtHaveRoomStartup(xsgdata->isgsess, tidx, fsize, NULL, fname, bytesNeeded, - availOnDisk, needFile); -} - -U8 xSGCheckMemoryCard(st_XSAVEGAME_DATA* xsgdata, S32 index) -{ - return iSGCheckMemoryCard(xsgdata->isgsess, index); -} - -void xSGGameSet(st_XSAVEGAME_DATA* xsgdata, S32 gidx) -{ - xsgdata->gslot = gidx; -} - -S32 xSGGameIsEmpty(st_XSAVEGAME_DATA* xsgdata, S32 gidx) -{ - return xSGGameSize(xsgdata, gidx) <= 0; -} - -S32 xSGGameSize(st_XSAVEGAME_DATA* xsgdata, S32 gidx) -{ - S32 size = 0; - if (xSG_chdir_gamedir(xsgdata)) - { - char* fname = xSG_cm_slotname(xsgdata, gidx); - size = iSGFileSize(xsgdata->isgsess, fname); - } - return size; -} - -char* xSGGameModDate(st_XSAVEGAME_DATA* xsgdata, S32 gidx) -{ - static char da_date[32] = {}; - da_date[0] = '\0'; - if (xSG_chdir_gamedir(xsgdata)) - { - char* slotname = xSG_cm_slotname(xsgdata, gidx); - char* date = iSGFileModDate(xsgdata->isgsess, slotname); - if (date != NULL) - { - strcpy(da_date, date); - } - else - { - strcpy(da_date, -#if 1 // Need these strings and can't seem get them any other way - 0x409 + "The Mystery Machine\0" - "Mystery Machine\0" - "On Edge in the Hedge!\0" - "Hedges\0" - "It's a Mean Greenhouse, Scooby!\0" - "Greenhouse\0" - "Chills & Spills on Haunted Hill!\0" - "Haunted Hill\0" - "Scared Stiff at Skull Cliff!\0" - "Skull Cliff\0" - "Misbehavin'? Cause a Cave In\0" - "Caves\0" - "A Tight Spot for a Grave Plot!\0" - "Graves\0" - "A One Way Trip to the Crypt!\0" - "Crypts\0" - "Gloom & Doom Down in the Tomb!\0" - "Tombs\0" - "Shock on the Dock!\0" - "Docks\0" - "Fishy Clues for Scooby-Doo?\0" - "Cannery Row\0" - "Fear on the Pier!\0" - "Piers\0" - "Coast for Some Ghosts!\0" - "Shoreline\0" - "Going Down Witch Way?\0" - "Coastal Point\0" - "Lighthouse Fright House!\0" - "Lighthouse\0" - "Wreck on the Deck!\0" - "Danger Rocks\0" - "Aghast by the Mast!\0" - "Masts\0" - "Shiver Your Timbers, Scooby!\0" - "Shipwrecks\0" - "Clamor in the Manor!\0" - "Manor\0" - "Mind Your Manors!\0" - "Stairway\0" - "All Scares Upstairs!\0" - "Upstairs\0" - "Don't Look Down, Scooby-Doo!\0" - "Hallways\0" - "Panic in the Attic!\0" - "Attic\0" - "A Dark and Stormy Knight!\0" - "Rooftops\0" - "Who's Yella' in the Cellar?\0" - "Cellar\0" - "Creepy Crawlies in the Hallways\0" - "Catacombs\0" - "Gusts Abound Underground\0" - "Tunnels\0" - "Little Lab of Horrors\0" - "Secret Lab\0" - "Mastermind Unmasked!\0" - "Mastermind\0" - "Cower in the Tower!\0" - "Tower\0" - "Monster Gallery\0" -#endif - ""); - } - } - return da_date; -} - -char* xSGGameLabel(st_XSAVEGAME_DATA* xsgdata, S32 gidx) -{ - char* da_name = NULL; - if (xSG_chdir_gamedir(xsgdata) && g_leaders[gidx].gameLabel != NULL) - { - da_name = g_leaders[gidx].gameLabel; - } - return da_name; -} - -S32 xSGGameThumbIndex(st_XSAVEGAME_DATA* xsgdata, S32 gidx) -{ - S32 idx_thum = -1; - if (xSG_chdir_gamedir(xsgdata)) - { - st_XSAVEGAME_LEADER* lead = &g_leaders[gidx]; - idx_thum = lead->thumbIconIdx; - } - return idx_thum; -} - -S32 xSGGameProgress(st_XSAVEGAME_DATA* xsgdata, S32 gidx) -{ - S32 progress = -1; - if (xSG_chdir_gamedir(xsgdata)) - { - st_XSAVEGAME_LEADER* lead = &g_leaders[gidx]; - progress = lead->progress; - } - return progress; -} - -S32 xSGAddSaveClient(st_XSAVEGAME_DATA* xsgdata, U32 clttag, void* cltdata, - S32 (*infofunc)(void*, st_XSAVEGAME_DATA*, S32*, S32*), - S32 (*procfunc)(void*, st_XSAVEGAME_DATA*, st_XSAVEGAME_WRITECONTEXT*)) -{ - S32 result = 1; - if (xsgdata->stage & 0x40000000) - { - result = 0; - } - else if (!(xsgdata->stage & 1)) - { - result = 0; - } - - if (xsgdata->stkcnt + 1 >= 128) - { - xUtil_idtag2string(clttag, 0); - result = 0; - } - - st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[xsgdata->stkcnt++]; - clt->idtag = clttag; - clt->cltinfo = infofunc; - clt->cltproc = procfunc; - clt->cltdata = cltdata; - clt->needamt = 0; - clt->realamt = 0; - clt->buf_sizepos = NULL; - - xsgdata->stage |= 4; - if (result == 0) - { - xsgdata->stage |= 0x40000000; - } - return result; -} - -S32 xSGAddLoadClient(st_XSAVEGAME_DATA* xsgdata, U32 clttag, void* cltdata, - S32 (*loadfunc)(void*, st_XSAVEGAME_DATA*, st_XSAVEGAME_READCONTEXT*, - U32, S32)) -{ - S32 result = 1; - if (xsgdata->stage & 0x40000000) - { - result = 0; - } - else if (!(xsgdata->stage & 1)) - { - result = 0; - } - else if (xsgdata->stkcnt + 1 >= 128) - { - xUtil_idtag2string(clttag, 0); - result = 0; - } - - if (clttag != 0 || xsgdata->dfltloadclt.idtag == 0) - { - if (clttag == 0) - { - xsgdata->dfltloadclt.idtag = 1; - xsgdata->dfltloadclt.cltload = loadfunc; - xsgdata->dfltloadclt.cltdata = cltdata; - xsgdata->dfltloadclt.blokact = 0; - xsgdata->dfltloadclt.blokmax = 0; - xsgdata->dfltloadclt.blokpos = NULL; - xsgdata->dfltloadclt.readpos = NULL; - xsgdata->dfltloadclt.readremain = 0; - xsgdata->dfltloadclt.readamt = 0; - } - else - { - st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[xsgdata->stkcnt++]; - clt->idtag = clttag; - clt->cltload = loadfunc; - clt->cltdata = cltdata; - clt->blokact = 0; - clt->blokmax = 0; - clt->blokpos = NULL; - clt->readpos = NULL; - clt->readremain = 0; - clt->readamt = 0; - } - } - - xsgdata->stage |= 2; - if (result == 0) - { - xsgdata->stage |= 0x40000000; - } - return result; -} - -S32 xSGSetup(st_XSAVEGAME_DATA* xsgdata) -{ - return xSGSetup(xsgdata, 0, "nothing", -1, 0, 0); -} - -S32 xSGSetup(st_XSAVEGAME_DATA* xsgdata, S32 gidx, char* label, S32 progress, iTime playtime, - S32 thumbIconIdx) -{ - S32 result = 1; - if (xsgdata->stage & 0x40000000) - { - result = 0; - } - else if (!(xsgdata->stage & 1)) - { - result = 0; - } - - if (xsgdata->mode == XSG_MODE_SAVE) - { - xsgdata->gslot = gidx; - strncpy(xsgdata->label, label, 63); - xsgdata->label[63] = '\0'; - xsgdata->playtime = playtime; - xsgdata->progress = progress; - xsgdata->thumbIconIdx = thumbIconIdx; - if (result != 0 && xSG_sv_flipinfo(xsgdata) == 0) - { - result = 0; - } - if (result != 0 && xSG_sv_prepdest(xsgdata) == 0) - { - result = 0; - } - } - else - { - if (xSG_ld_prepload(xsgdata) == 0) - { - result = 0; - } - } - - xsgdata->stage |= 8; - if (result == 0) - { - xsgdata->stage |= 0x40000000; - } - return result; -} - -S32 xSGProcess(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - if (xsgdata->stage & 0x40000000) - { - result = 0; - } - else if (!(xsgdata->stage & 1)) - { - result = 0; - } - else if (!(xsgdata->stage & 8)) - { - result = 0; - } - - if (result != 0 && xsgdata->mode == XSG_MODE_SAVE) - { - if (xSG_smem_blkopen(xsgdata) == 0) - { - result = 0; - } - - if (result != 0 && xSG_sv_flipproc(xsgdata) == 0) - { - result = 0; - } - if (result != 0 && xSG_sv_bldchksum(xsgdata) == 0) - { - result = 0; - } - if (result != 0 && xSG_smem_blkclose(xsgdata) == 0) - { - result = 0; - } - - if (result != 0) - { - xSG_sv_commit(xsgdata); - } - } - else if (result != 0 && xsgdata->mode == XSG_MODE_LOAD) - { - if (xSG_ld_readgame(xsgdata) == 0) - { - result = 0; - } - } - - xsgdata->stage |= 0x10; - if (result == 0) - { - xsgdata->stage |= 0x40000000; - } - return result; -} - -S32 xSGWrapup(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - S32 rc = 0; - - if (xsgdata->stage & 0x40000000) - { - result = 0; - } - else if (!(xsgdata->stage & 1)) - { - result = 0; - } - else if (!(xsgdata->stage & 0x10)) - { - result = 0; - xsgdata->stage |= 0x40000000; - } - - if (xsgdata->mode != XSG_MODE_LOAD) - { - return result; - } - if (result == 0) - { - return result; - } - - if (result != 0) - { - rc = xSG_ld_readhead(xsgdata); - } - if (rc < 0) - { - xsgdata->stage |= 0x40000000; - return -1; - } - - if (rc == 0) - { - result = 0; - } - if (result != 0) - { - rc = xSG_ld_validate(xsgdata); - } - - if (rc < 0) - { - xsgdata->stage |= 0x40000000; - return -1; - } - - if (rc == 0) - { - result = 0; - } - if (result != 0) - { - rc = xSG_ld_findcltblk(xsgdata); - } - - if (rc == 0) - { - result = 0; - } - if (result != 0) - { - rc = xSG_ld_flipload(xsgdata); - } - - if (rc == 0) - { - result = 0; - } - if (result == 0) - { - xsgdata->stage |= 0x40000000; - } - - return result; -} - -en_XSGASYNC_STATUS xSGAsyncStatus(st_XSAVEGAME_DATA* xsgdata, S32 block, en_XSG_WHYFAIL* whyFail, - char* errmsg) -{ - en_XSGASYNC_STATUS xstat = XSG_ASTAT_NOOP; - en_ASYNC_OPERR whyerr = ISG_OPERR_NONE; - - if (errmsg != NULL) - { - errmsg[0] = '\0'; - } - - en_ASYNC_OPSTAT istat = iSGPollStatus(xsgdata->isgsess, 0, block); - switch (istat) - { - case ISG_OPSTAT_FAILURE: - xstat = XSG_ASTAT_FAILED; - whyerr = iSGOpError(xsgdata->isgsess, errmsg); - break; - case ISG_OPSTAT_INPROG: - xstat = XSG_ASTAT_INPROG; - break; - case ISG_OPSTAT_SUCCESS: - xstat = XSG_ASTAT_SUCCESS; - break; - } - - if (whyFail != NULL && whyerr != ISG_OPERR_NONE) - { - en_XSG_WHYFAIL con = XSG_WHYERR_NONE; - - switch (whyerr) - { - case ISG_OPERR_NONE: - break; - case ISG_OPERR_NOCARD: - con = XSG_WHYERR_NOCARD; - break; - case ISG_OPERR_NOROOM: - case ISG_OPERR_SVNOSPACE: - con = XSG_WHYERR_NOROOM; - break; - case ISG_OPERR_DAMAGE: - con = XSG_WHYERR_DAMAGE; - break; - case ISG_OPERR_SVWRITE: - con = XSG_WHYERR_CARDYANKED; - break; - default: - con = XSG_WHYERR_OTHER; - break; - } - *whyFail = con; - } - return xstat; -} - -S32 xSG_cb_leader_svinfo(void*, st_XSAVEGAME_DATA*, S32* cur_space, S32* max_fullgame) -{ - *cur_space = 0x100; - *max_fullgame = 0x100; - return 1; -} - -S32 xSG_cb_leader_svproc(void* cltdata, st_XSAVEGAME_DATA* original_xsgdata, - st_XSAVEGAME_WRITECONTEXT* wctxt) -{ - st_XSAVEGAME_DATA* xsg = (st_XSAVEGAME_DATA*)cltdata; - st_XSAVEGAME_LEADER leader = {}; - char fundata[] = "--TakeMeToYourLeader--"; - - strncpy(leader.gameLabel, xsg->label, 0x40); - leader.gameLabel[63] = 0; - leader.gametime = xsg->playtime; - leader.progress = xsg->progress; - leader.thumbIconIdx = xsg->thumbIconIdx; - - xSGWriteData(original_xsgdata, wctxt, leader.gameLabel, sizeof(st_XSAVEGAME_LEADER)); - xSGWriteData(original_xsgdata, wctxt, fundata, 0x16); - return 1; -} - -S32 xSG_cb_leader_load(void*, st_XSAVEGAME_DATA* original_xsgdata, - st_XSAVEGAME_READCONTEXT* rctxt, U32, S32) -{ - char fundata[32] = {}; - st_XSAVEGAME_LEADER discard = {}; - xSGReadData(original_xsgdata, rctxt, discard.gameLabel, sizeof(st_XSAVEGAME_LEADER)); - xSGReadData(original_xsgdata, rctxt, fundata, 0x16); - return 1; -} - -S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, char* data, - S32 elesiz, S32 n) -{ - S32 cnt; - S32 is_ok = 1; - - if (xsgdata->stage & 0x40000000) - { - return 0; - } - if (elesiz == 0) - { - return 0; - } - - cnt = n * elesiz; - if (cnt == 0) - { - return cnt; - } - - if (xsgdata->upd_tally != 0 && xsgdata->totamt + cnt > xsgdata->memsize) - { - xsgdata->stage |= 0x40000000; - return 0; - } - - void* mcprc; - mcprc = memcpy(xsgdata->buf_curpos, data, cnt); - if (mcprc == NULL) - { - is_ok = 0; - } - else - { - xsgdata->buf_curpos += cnt; - } - - // I wonder if this was supposed to be a boolean and - if (is_ok & xsgdata->upd_tally) - { - xsgdata->totamt += cnt; - if (wctxt != NULL) - { - st_XSAVEGAME_CLIENT* clt = (st_XSAVEGAME_CLIENT*)wctxt; - clt->realamt += cnt; - } - } - - if (is_ok == 0) - { - xsgdata->stage |= 0x40000000; - return 0; - } - else - { - return cnt / elesiz; - } - - return cnt; -} - -S32 xSGWriteStrLen(const char* str) -{ - S32 len = strlen(str); - len += (len + 1 & 1) + 1; - return len; -} - -S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, char* data, - S32 n) -{ - return xSGWriteData(xsgdata, wctxt, data, sizeof(char), n); -} - -S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, S32* data, - S32 n) -{ - return xSGWriteData(xsgdata, wctxt, (char*)data, sizeof(S32), n); -} - -S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, U32* data, - S32 n) -{ - return xSGWriteData(xsgdata, wctxt, (char*)data, sizeof(U32), n); -} - -S32 xSGWriteData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt, F32* data, - S32 n) -{ - return xSGWriteData(xsgdata, wctxt, (char*)data, sizeof(F32), n); -} - -S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, char* buff, - S32 elesiz, S32 n) -{ - S32 cnt; - if (elesiz == 0) - { - return 0; - } - - cnt = n * elesiz; - if (cnt == 0) - { - return cnt; - } - - st_XSAVEGAME_CLIENT* clt = (st_XSAVEGAME_CLIENT*)rctxt; - if (clt != NULL && cnt > clt->readremain) - { - xUtil_idtag2string(clt->idtag, 0); - return 0; - } - - if (clt != NULL) - { - memcpy(buff, clt->readpos, cnt); - } - else - { - memcpy(buff, xsgdata->walkpos, cnt); - } - - xsgdata->walkpos += cnt; - xsgdata->walkremain -= cnt; - - if (clt != NULL) - { - clt->readpos += cnt; - clt->readamt += cnt; - clt->readremain -= cnt; - } - - return cnt / elesiz; -} - -S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, char* buff, S32 n) -{ - return xSGReadData(xsgdata, rctxt, buff, sizeof(char), n); -} - -S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, S32* buff, S32 n) -{ - return xSGReadData(xsgdata, rctxt, (char*)buff, sizeof(S32), n); -} - -S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, U32* buff, - S32 n) -{ - return xSGReadData(xsgdata, rctxt, (char*)buff, sizeof(U32), n); -} - -S32 xSGReadData(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, F32* buff, - S32 n) -{ - return xSGReadData(xsgdata, rctxt, (char*)buff, sizeof(F32), n); -} - -S32 xSG_grab_leaders(st_XSAVEGAME_DATA* xsgdata) -{ - S32 num_found = 0; - char readbuf[116] = {}; - - memset(&g_leaders, 0, sizeof(g_leaders)); - - if (!xSG_chdir_gamedir(xsgdata)) - { - return 0; - } - - for (S32 i = 0; i < 3; i++) - { - if (!xSGGameIsEmpty(xsgdata, i)) - { - char* slotname = xSG_cm_slotname(xsgdata, i); - S32 rc = iSGReadLeader(xsgdata->isgsess, slotname, readbuf, sizeof(readbuf), 0); - if (rc != 0) - { - num_found++; - memcpy(&g_leaders[i], readbuf + 0x1c, sizeof(st_XSAVEGAME_LEADER)); - } - } - } - - return num_found; -} - -S32 xSG_chdir_gamedir(st_XSAVEGAME_DATA* xsgdata) -{ - S32 rc = 1; - char* name = iSGMakeName(ISG_NGTYP_GAMEDIR, NULL, 0); - if (!iSGSelectGameDir(xsgdata->isgsess, name)) - { - rc = 0; - } - return rc; -} - -char* xSG_cm_slotname(st_XSAVEGAME_DATA* xsgdata, S32 gidx) -{ - static char slotname[32] = {}; - slotname[0] = '\0'; - - char* tmp; - if (gidx == 0x9a5) - { - tmp = iSGMakeName(ISG_NGTYP_CONFIG, NULL, 0); - } - else - { - tmp = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, gidx); - } - strcpy(slotname, tmp); - return slotname; -} - -void xSG_areaComposeLabel(char* label, int, char*, int) -{ - char buf[64] = {}; - iSGMakeTimeStamp(buf); - sprintf(label, "%s", buf); -} - -S32 xSG_sv_flipinfo(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - S32 cltamt = 0; - S32 cltmax = 0; - - for (S32 i = 0; i < xsgdata->stkcnt; i++) - { - st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[i]; - cltamt = 0; - cltmax = 0; - - S32 rc = clt->cltinfo(clt->cltdata, xsgdata, &cltamt, &cltmax); - if (rc == 0) - { - xUtil_idtag2string(clt->idtag, 0); - result = 0; - } - else - { - clt->needamt = cltamt; - clt->maxamt = cltmax; - xsgdata->cltneed += cltamt; - xsgdata->cltmax += cltmax; - xsgdata->chdrneed += 0xc; - } - - if (result == 0) - { - xsgdata->stage |= 0x40000000; - break; - } - } - return result; -} - -S32 xSG_sv_prepdest(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - - if (xsgdata->cltneed < 1) - { - result = 0; - } - else - { - xsgdata->memsize = xsgdata->cltmax + xsgdata->chdrneed + 0x10; - xsgdata->membuf = (char*)xMemPushTemp(xsgdata->memsize); - - if (xsgdata->membuf == NULL) - { - result = 0; - } - else - { - xUtil_idtag2string('XSGS', 0); - memset(xsgdata->membuf, 0, xsgdata->memsize); - xsgdata->buf_curpos = xsgdata->membuf; - } - } - return result; -} - -S32 xSG_sv_flipproc(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - S32 rc; - char bfill = 0xbf; - - for (S32 i = 0; i < xsgdata->stkcnt; i++) - { - st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[i]; - - rc = xSG_smem_cltopen(xsgdata, clt); - if (rc != 0) - { - rc = clt->cltproc(clt->cltdata, xsgdata, (st_XSAVEGAME_WRITECONTEXT*)clt); - if (rc == 0) - { - xUtil_idtag2string(clt->idtag, 0); - result = 0; - } - - S32 needfill = clt->maxamt - clt->realamt; - xUtil_idtag2string(clt->idtag, 0); - while (needfill-- > 0) - { - xSGWriteData(xsgdata, NULL, &bfill, 1); - } - } - - if (rc != 0 && xSG_smem_cltclose(xsgdata, clt) == 0) - { - result = 0; - xUtil_idtag2string(clt->idtag, 0); - } - - if (result == 0) - { - break; - } - } - return result; -} - -S32 xSG_sv_bldchksum(st_XSAVEGAME_DATA* xsgdata) -{ - xsgdata->chksum = - xUtil_crc_update(xsgdata->chksum, xsgdata->membuf + 16, xsgdata->memsize - 16); - return 1; -} - -S32 xSG_smem_blkopen(st_XSAVEGAME_DATA* xsgdata) -{ - S32 i = '3333'; - S32 j = 'GDAT'; - S32 k = 1; - - xSGWriteData(xsgdata, 0, &j, 1); - xSGWriteData(xsgdata, 0, &k, 1); - - xsgdata->buf_sizespot = xsgdata->buf_curpos; - xSGWriteData(xsgdata, 0, &i, 1); - xsgdata->buf_cksmspot = xsgdata->buf_curpos; - xSGWriteData(xsgdata, 0, &i, 1); - return 1; -} - -S32 xSG_smem_blkclose(st_XSAVEGAME_DATA* xsgdata) -{ - xsgdata->upd_tally = 0; - - char* last_bufpos = xsgdata->buf_curpos; - xsgdata->buf_curpos = xsgdata->buf_sizespot; - xSGWriteData(xsgdata, NULL, &xsgdata->totamt, 1); - xsgdata->buf_curpos = last_bufpos; - - last_bufpos = xsgdata->buf_curpos; - xsgdata->buf_curpos = xsgdata->buf_cksmspot; - xSGWriteData(xsgdata, NULL, &xsgdata->chksum, 1); - xsgdata->buf_curpos = last_bufpos; - xsgdata->upd_tally = 1; - return 1; -} - -S32 xSG_smem_cltopen(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_CLIENT* clt) -{ - S32 i = '3333'; - S32 j = 0; - - xUtil_idtag2string(clt->idtag, 0); - j = clt->idtag; - xSGWriteData(xsgdata, 0, &j, 1); - clt->buf_maxpos = xsgdata->buf_curpos; - xSGWriteData(xsgdata, 0, &i, 1); - clt->buf_sizepos = xsgdata->buf_curpos; - xSGWriteData(xsgdata, 0, &i, 1); - xUtil_idtag2string(clt->idtag, 0); - return 1; -} - -S32 xSG_smem_cltclose(st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_CLIENT* clt) -{ - xUtil_idtag2string(clt->idtag, 0); - xsgdata->upd_tally = 0; - if (clt->needamt < clt->realamt) - { - xUtil_idtag2string(clt->idtag, 0); - } - - char* last_bufpos = xsgdata->buf_curpos; - xsgdata->buf_curpos = clt->buf_maxpos; - xSGWriteData(xsgdata, NULL, &clt->maxamt, 1); - xsgdata->buf_curpos = last_bufpos; - - xsgdata->buf_curpos = clt->buf_sizepos; - xSGWriteData(xsgdata, NULL, &clt->realamt, 1); - xsgdata->buf_curpos = last_bufpos; - xsgdata->upd_tally = 1; - - xUtil_idtag2string(clt->idtag, 0); - return 1; -} - -S32 xSG_sv_commit(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - S32 rc; - char browselabel[64] = {}; - - char* name = iSGMakeName(ISG_NGTYP_GAMEDIR, NULL, 0); - if (!iSGSetupGameDir(xsgdata->isgsess, name, 1)) - { - result = 0; - } - else - { - xSG_areaComposeLabel(browselabel, xsgdata->thumbIconIdx, xsgdata->label, - xsgdata->gslot + 1); - - if (!iSGSaveFile(xsgdata->isgsess, iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, xsgdata->gslot), - xsgdata->membuf, xsgdata->memsize, 1, browselabel)) - { - result = 0; - } - } - - return result; -} - -void xSG_cb_ISGChange(void*, en_CHGCODE what) -{ - XSGAutoData* asg = xSGAutoSave_GetCache(); - switch (what) - { - case ISG_CHG_NONE: - break; - case ISG_CHG_TARGET: - asg->MarkInvalid(); - break; - case ISG_CHG_GAMELIST: - asg->MarkInvalid(); - break; - } -} - -S32 xSG_ld_prepload(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - char* name = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, xsgdata->gslot); - xsgdata->loadsize = iSGFileSize(xsgdata->isgsess, name); - - if (xsgdata->loadsize < 1) - { - result = 0; - } - else - { - xsgdata->loadbuf = (char*)xMemPushTemp(xsgdata->loadsize); - memset(xsgdata->loadbuf, 0, xsgdata->loadsize); - } - return result; -} - -S32 xSG_ld_readgame(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - if (xsgdata->stage & 0x40000000) - { - result = 0; - } - - char* name = iSGMakeName(ISG_NGTYP_GAMEFILE, NULL, xsgdata->gslot); - if (!iSGLoadFile(xsgdata->isgsess, name, xsgdata->loadbuf, 1)) - { - result = 0; - } - - if (result == 0) - { - xsgdata->stage |= 0x40000000; - } - - return result; -} - -S32 xSG_ld_readhead(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - S32 ival = 0; - bool not_ok = 0; - - xsgdata->walkpos = xsgdata->loadbuf; - xsgdata->walkremain = xsgdata->loadsize; - xSGReadData(xsgdata, NULL, &ival, 1); - - if (ival != 'GDAT') - { - result = 0; - not_ok = 1; - } - - xSGReadData(xsgdata, NULL, &ival, 1); - if (ival != 1) - { - result = 0; - not_ok = 1; - } - - xSGReadData(xsgdata, NULL, &ival, 1); - xsgdata->readsize = ival; - - xSGReadData(xsgdata, NULL, &ival, 1); - xsgdata->file_chksum = ival; - if (not_ok) - { - return -1; - } - return result; -} - -S32 xSG_ld_validate(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - - xsgdata->loadsize = xsgdata->readsize; - xsgdata->walkpos = xsgdata->loadbuf + 0x10; - xsgdata->walkremain = xsgdata->loadsize - 0x10; - xsgdata->read_chksum = - xUtil_crc_update(xsgdata->read_chksum, xsgdata->walkpos, xsgdata->walkremain); - - if (xsgdata->read_chksum != xsgdata->file_chksum) - { - result = -1; - } - - return result; -} - -S32 xSG_ld_findcltblk(st_XSAVEGAME_DATA* xsgdata) -{ - S32 ival = 0; - U32 tag = 0; - S32 maxamt = 0; - S32 actamt = 0; - st_XSAVEGAME_CLIENT* dfltclt = &xsgdata->dfltloadclt; - - xsgdata->walkpos = xsgdata->loadbuf; - xsgdata->walkremain = xsgdata->loadsize; - xSGReadData(xsgdata, 0, &ival, 1); - xSGReadData(xsgdata, 0, &ival, 1); - xSGReadData(xsgdata, 0, &ival, 1); - xSGReadData(xsgdata, 0, &ival, 1); - - while (xsgdata->walkremain > 0) - { - tag = 0; - S32 found = 0; - maxamt = 0; - actamt = 0; - - xSGReadData(xsgdata, 0, &tag, 1); - xSGReadData(xsgdata, 0, &maxamt, 1); - xSGReadData(xsgdata, 0, &actamt, 1); - xUtil_idtag2string(tag, 0); - - for (S32 i = 0; i < xsgdata->stkcnt; i++) - { - st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[i]; - - if (clt->idtag == tag) - { - found = true; - clt->blokpos = xsgdata->walkpos; - clt->blokact = actamt; - clt->blokmax = maxamt; - clt->readpos = xsgdata->walkpos; - clt->readamt = 0; - clt->readremain = actamt; - break; - } - } - - if (!found) - { - if (dfltclt->idtag != 0) - { - xUtil_idtag2string(tag, 0); - dfltclt->blokpos = xsgdata->walkpos; - dfltclt->blokact = actamt; - dfltclt->blokmax = maxamt; - dfltclt->readpos = xsgdata->walkpos; - dfltclt->readamt = 0; - dfltclt->readremain = actamt; - - S32 rc = - dfltclt->cltload(dfltclt->cltdata, xsgdata, (st_XSAVEGAME_READCONTEXT*)dfltclt, - tag, dfltclt->blokact); - if (rc == 0) - { - xUtil_idtag2string(tag, 0); - } - - rc = dfltclt->readremain; - if (rc > 0) - { - xsgdata->walkpos += rc + (maxamt - actamt); - xsgdata->walkremain -= dfltclt->readremain + (maxamt - actamt); - } - } - else - { - xUtil_idtag2string(tag, 0); - xsgdata->walkpos += maxamt; - xsgdata->walkremain -= maxamt; - } - } - else - { - xsgdata->walkpos += maxamt; - xsgdata->walkremain -= maxamt; - } - } - return 1; -} - -S32 xSG_ld_flipload(st_XSAVEGAME_DATA* xsgdata) -{ - S32 result = 1; - S32 rc; - - for (S32 i = 0; i < xsgdata->stkcnt; i++) - { - st_XSAVEGAME_CLIENT* clt = &xsgdata->cltstk[i]; - if (clt->cltload != NULL && clt->blokact != 0 && clt->blokpos != NULL) - { - xUtil_idtag2string(clt->idtag, 0); - - rc = clt->cltload(clt->cltdata, xsgdata, (st_XSAVEGAME_READCONTEXT*)clt, clt->idtag, - clt->blokact); - if (rc == 0) - { - xUtil_idtag2string(clt->idtag, 0); - result = 0; - } - } - else - { - xUtil_idtag2string(clt->idtag, 0); - } - - if (result == 0) - { - break; - } - } - - return result; -} - -XSGAutoData* xSGAutoSave_GetCache() -{ - return &g_autodata; -} - -void xSGAutoSave_Startup() -{ - XSGAutoData* asg = xSGAutoSave_GetCache(); - asg->flg_autodata = 0; - asg->lastGame = -1; - asg->lastTarg = -1; - asg->lastPhysicalSlot = -1; - iSGAutoSave_Startup(); -} - -S32 XSGAutoData::IsValid() -{ - if (this->flg_autodata & 1 && !XSGAutoData::HWCheckConnect(this->lastTarg)) - { - this->flg_autodata &= 0x0fffffffe; - } - return this->flg_autodata & 1; -} - -void XSGAutoData::MarkInvalid() -{ - this->flg_autodata &= 0xfffffffe; -} - -S32 XSGAutoData::SetCache(S32 targ, S32 game, S32 physicalSlot) -{ - this->Discard(); - this->isg_monitor = this->HWConnect(targ); - if (this->isg_monitor == NULL) - { - return 0; - } - - this->lastTarg = targ; - this->lastGame = game; - this->lastPhysicalSlot = physicalSlot; - this->flg_autodata |= 1; - return 1; -} - -void XSGAutoData::Discard() -{ - this->flg_autodata = 0; - this->lastTarg = -1; - this->lastGame = -1; - this->lastPhysicalSlot = -1; - if (this->isg_monitor != NULL) - { - this->HWDisconnect(this->isg_monitor); - } - this->isg_monitor = NULL; -} - -st_ISGSESSION* XSGAutoData::HWConnect(S32 targ) -{ - return iSGAutoSave_Connect(targ, xSGAutoSave_GetCache(), ASG_ISG_changed); -} - -void XSGAutoData::HWDisconnect(st_ISGSESSION* isgsess) -{ - iSGAutoSave_Disconnect(isgsess); -} - -S32 XSGAutoData::HWCheckConnect(S32 targ) -{ - return iSGAutoSave_Monitor(this->isg_monitor, this->lastTarg); -} - -void ASG_ISG_changed(void*, en_CHGCODE what) -{ - XSGAutoData* asg = xSGAutoSave_GetCache(); - switch (what) - { - case ISG_CHG_NONE: - break; - case ISG_CHG_TARGET: - asg->MarkInvalid(); - break; - case ISG_CHG_GAMELIST: - asg->MarkInvalid(); - break; - } -} diff --git a/src/SB/Core/x/xserializer.cpp b/src/SB/Core/x/xserializer.cpp deleted file mode 100644 index f9fd640..0000000 --- a/src/SB/Core/x/xserializer.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "xserializer.h" - -#include diff --git a/src/SB/Core/x/xstransvc.cpp b/src/SB/Core/x/xstransvc.cpp deleted file mode 100644 index 199917f..0000000 --- a/src/SB/Core/x/xstransvc.cpp +++ /dev/null @@ -1,587 +0,0 @@ -#include "xstransvc.h" - -#include -#include -#include -#include "xString.h" -#include "xutil.h" -#include "xTRC.h" -#include "iFile.h" - -static st_STRAN_DATA g_xstdata = {}; -static S32 g_straninit; -static st_PACKER_READ_FUNCS* g_pkrf; -static st_PACKER_ASSETTYPE* g_typeHandlers; - -static st_STRAN_SCENE* XST_lock_next(); -static void XST_unlock_all(); -static S32 XST_cnt_locked(); -static S32 XST_PreLoadScene(st_STRAN_SCENE* sdata, const char* path); -static char* XST_translate_sid(U32 sid, char* extension); -static char* XST_translate_sid_path(U32 sid, char* extension); -static st_STRAN_SCENE* XST_find_bySID(U32 sid, S32 findTheHOP); -static void XST_reset_raw(); -static void XST_unlock(st_STRAN_SCENE* sdata); -static void XST_unlock_all(); -static st_STRAN_SCENE* XST_get_rawinst(S32 index); -static S32 XST_cnt_locked(); -static st_STRAN_SCENE* XST_nth_locked(S32 index); - -S32 xSTStartup(st_PACKER_ASSETTYPE* handlers) -{ - if (g_straninit++ == 0) - { - g_typeHandlers = handlers; - XST_reset_raw(); - PKRStartup(); - g_pkrf = PKRGetReadFuncs(1); - } - return g_straninit; -} - -S32 xSTShutdown() -{ - g_straninit--; - if (g_straninit == 0) - { - g_typeHandlers = 0; - XST_unlock_all(); - PKRShutdown(); - } - return g_straninit; -} - -// This doesn't seem exactly how HI would have written this, but it OKs -// TODO: Try to clean this up? -S32 xSTPreLoadScene(U32 sid, void* userdata, S32 flg_hiphop) -{ - S32 result; - S32 i = 0; - st_STRAN_SCENE* sdata; - char* path; - if ((flg_hiphop & 3) == 2) - { - sdata = XST_lock_next(); - sdata->scnid = sid; - sdata->userdata = userdata; - sdata->isHOP = 1; - - path = XST_translate_sid_path(sid, ".HOP"); - if (path != NULL) - { - strcpy(sdata->fnam, path); - i = XST_PreLoadScene(sdata, path); - } - if (i == 0) - { - path = XST_translate_sid(sid, ".HOP"); - if (path != NULL) - { - strcpy(sdata->fnam, path); - i = XST_PreLoadScene(sdata, path); - } - } - if (i == 0) - { - XST_unlock(sdata); - result = 0; - } - else - { - result = i; - } - } - else - { - do - { - sdata = XST_lock_next(); - sdata->scnid = sid; - sdata->userdata = userdata; - sdata->isHOP = 0; - - if (sid != 0x424f4f54 && sid != 0x464f4e54) - { - path = XST_translate_sid_path(sid, ".HIP"); - if (path != NULL) - { - strcpy(sdata->fnam, path); - i = XST_PreLoadScene(sdata, path); - } - } - if (i == 0) - { - path = XST_translate_sid(sid, ".HIP"); - if (path != NULL) - { - strcpy(sdata->fnam, path); - i = XST_PreLoadScene(sdata, path); - } - } - if (i == 0) - { - XST_unlock(sdata); - result = 0; - } - else - { - result = i; - } - } while (i == 0); - } - return result; -} - -S32 xSTQueueSceneAssets(U32 sid, S32 flg_hiphop) -{ - S32 result = 1; - st_STRAN_SCENE* sdata = XST_find_bySID(sid, (flg_hiphop & 3) == 2 ? 1 : 0); - if (sdata == NULL) - { - result = 0; - } - else - { - if (sdata->spkg != NULL) - { - g_pkrf->LoadLayer(sdata->spkg, PKR_LTYPE_ALL); - } - } - return result; -} - -void xSTUnLoadScene(U32 sid, S32 flg_hiphop) -{ - st_STRAN_SCENE* sdata; - if (sid == 0) - { - S32 cnt = XST_cnt_locked(); - - for (int i = 0; i < cnt; i++) - { - sdata = XST_nth_locked(i); - if (sdata->spkg != NULL) - { - g_pkrf->Done(sdata->spkg); - } - sdata->spkg = NULL; - } - XST_unlock_all(); - } - else - { - sdata = XST_find_bySID(sid, (flg_hiphop & 3) == 2 ? 1 : 0); - if (sdata != NULL) - { - if (sdata->spkg != NULL) - { - g_pkrf->Done(sdata->spkg); - } - sdata->spkg = NULL; - } - XST_unlock(sdata); - } -} - -F32 xSTLoadStep(U32) -{ - F32 pct = PKRLoadStep(0) != 0 ? 0.0f : 1.00001f; - - iTRCDisk::CheckDVDAndResetState(); - iFileAsyncService(); - return pct; -} - -void xSTDisconnect(U32 sid, S32 flg_hiphop) -{ - st_STRAN_SCENE* sdata = XST_find_bySID(sid, (flg_hiphop & 3) == 2 ? 1 : 0); - if (sdata != NULL) - { - g_pkrf->PkgDisconnect(sdata->spkg); - } -} - -S32 xSTSwitchScene(U32 sid, void* userdata, S32 (*progmon)(void*, F32)) -{ - st_STRAN_SCENE* sdata; - S32 rc = 0; - - for (S32 i = 1; i >= 0; i--) - { - sdata = XST_find_bySID(sid, i); - if (sdata != NULL) - { - if (progmon != NULL) - { - progmon(userdata, 0.0f); - } - rc = g_pkrf->SetActive(sdata->spkg, PKR_LTYPE_ALL); - if (progmon != NULL) - { - progmon(userdata, 1.0f); - } - } - } - - return rc; -} - -char* xSTAssetName(U32 aid) -{ - char* aname = NULL; - - S32 cnt = XST_cnt_locked(); - for (int i = 0; i < cnt; i++) - { - st_STRAN_SCENE* sdata = XST_nth_locked(i); - if (sdata->spkg != NULL) - { - aname = g_pkrf->AssetName(sdata->spkg, aid); - if (aname != NULL) - { - break; - } - } - } - - return aname; -} - -char* xSTAssetName(void* raw_HIP_asset) -{ - char* aname = NULL; - - S32 cnt = XST_cnt_locked(); - for (int i = 0; i < cnt; i++) - { - st_STRAN_SCENE* sdata = XST_nth_locked(i); - aname = g_pkrf->AssetName(sdata->spkg, PKRAssetIDFromInst(raw_HIP_asset)); - if (aname != NULL) - { - break; - } - } - - return aname; -} - -void* xSTFindAsset(U32 aid, U32* size) -{ - void* memloc = NULL; - if (aid == 0) - { - return memloc; - } - - S32 ready; - S32 scncount = XST_cnt_locked(); - for (S32 i = 0; i < scncount; i++) - { - st_STRAN_SCENE* sdata = XST_nth_locked(i); - if (g_pkrf->PkgHasAsset(sdata->spkg, aid)) - { - memloc = g_pkrf->LoadAsset(sdata->spkg, aid, NULL, NULL); - if (!g_pkrf->IsAssetReady(sdata->spkg, aid)) - { - memloc = NULL; - if (size != NULL) - { - *size = 0; - } - } - else - { - if (size != NULL) - { - *size = g_pkrf->GetAssetSize(sdata->spkg, aid); - } - } - break; - } - } - return memloc; -} - -S32 xSTAssetCountByType(U32 type) -{ - S32 sum = 0; - S32 cnt = XST_cnt_locked(); - for (S32 i = 0; i < cnt; i++) - { - st_STRAN_SCENE* sdata = XST_nth_locked(i); - sum += g_pkrf->AssetCount(sdata->spkg, type); - } - return sum; -} - -void* xSTFindAssetByType(U32 type, S32 idx, U32* size) -{ - void* memptr = NULL; - S32 i; - S32 sum = 0; - S32 cnt = XST_cnt_locked(); - for (i = 0; i < cnt; i++) - { - st_STRAN_SCENE* sdata = XST_nth_locked(i); - S32 scncnt = g_pkrf->AssetCount(sdata->spkg, type); - if (idx >= sum && idx < sum + scncnt) - { - memptr = g_pkrf->AssetByType(sdata->spkg, type, idx - sum, size); - break; - } - - sum += scncnt; - } - return memptr; -} - -S32 xSTGetAssetInfo(U32 aid, st_PKR_ASSET_TOCINFO* tocainfo) -{ - S32 rc = 0; - S32 scncnt = XST_cnt_locked(); - for (S32 i = 0; i < scncnt; i++) - { - st_STRAN_SCENE* sdata = XST_nth_locked(i); - if (g_pkrf->PkgHasAsset(sdata->spkg, aid) != NULL) - { - g_pkrf->GetBaseSector(sdata->spkg); - if (g_pkrf->GetAssetInfo(sdata->spkg, aid, tocainfo)) - { - rc = 1; - break; - } - } - } - return rc; -} - -// Equivalent: scheduling is off with the copy of tocinfo to ainfo -S32 xSTGetAssetInfoByType(U32 type, S32 idx, st_PKR_ASSET_TOCINFO* ainfo) -{ - S32 rc = 0; - S32 sum = 0; - st_PKR_ASSET_TOCINFO tocinfo = { 0, NULL, 0, 0, 0, NULL }; - memset(ainfo, 0, sizeof(st_PKR_ASSET_TOCINFO)); - - S32 found = XST_cnt_locked(); - for (S32 i = 0; i < found; i++) - { - st_STRAN_SCENE* sdata = XST_nth_locked(i); - S32 cnt = g_pkrf->AssetCount(sdata->spkg, type); - if (idx >= sum && idx < sum + cnt) - { - g_pkrf->GetBaseSector(sdata->spkg); - if (g_pkrf->GetAssetInfoByType(sdata->spkg, type, idx - sum, &tocinfo) != 0) - { - ainfo->aid = tocinfo.aid; - ainfo->sector = tocinfo.sector; - ainfo->plus_offset = tocinfo.plus_offset; - ainfo->size = tocinfo.size; - ainfo->mempos = tocinfo.mempos; - rc = 1; - break; - } - } - sum += cnt; - } - - return rc; -} - -S32 xSTGetAssetInfoInHxP(U32 aid, st_PKR_ASSET_TOCINFO* ainfo, U32 j) -{ - S32 rc = 0; - S32 cnt = XST_cnt_locked(); - for (S32 i = 0; i < cnt; i++) - { - st_STRAN_SCENE* sdata = XST_nth_locked(i); - if (j == xStrHash(sdata->fnam) && g_pkrf->PkgHasAsset(sdata->spkg, aid)) - { - g_pkrf->GetBaseSector(sdata->spkg); - if (g_pkrf->GetAssetInfo(sdata->spkg, aid, ainfo)) - { - rc = 1; - break; - } - } - } - return rc; -} - -char* xST_xAssetID_HIPFullPath(U32 aid) -{ - return xST_xAssetID_HIPFullPath(aid, 0); -} - -char* xST_xAssetID_HIPFullPath(U32 aid, U32* sceneID) -{ - char* id = NULL; - S32 cnt = XST_cnt_locked(); - for (int i = 0; i < cnt; i++) - { - st_STRAN_SCENE* sdata = XST_nth_locked(i); - if (g_pkrf->PkgHasAsset(sdata->spkg, aid)) - { - id = sdata->fnam; - if (sceneID != NULL) - { - *sceneID = sdata->scnid; - } - break; - } - } - - return id; -} - -// register crap -static S32 XST_PreLoadScene(st_STRAN_SCENE* sdata, const char* name) -{ - S32 buf = 0; - st_PACKER_READ_DATA* spkg = - g_pkrf->Init(sdata->userdata, (char*)name, 0x2e, &buf, g_typeHandlers); - sdata->spkg = spkg; - if (sdata->spkg != NULL) - { - return buf; - } - return NULL; -} - -static char* XST_translate_sid(U32 sid, char* extension) -{ - static char fname[0x40] = {}; - sprintf(fname, "%s%s", xUtil_idtag2string(sid, 0), extension); - return fname; -} - -static char* XST_translate_sid_path(U32 sid, char* extension) -{ - // NOTE: This buffer extends for 0x44 bytes in the rom - // However, I think that's most likely padding for the jumptable that occurs afterwards - static char fname[0x40] = {}; - char pathSeparator[2] = "/"; - sprintf(fname, "%c%c%s%s%s", *xUtil_idtag2string(sid, 0), *(xUtil_idtag2string(sid, 0) + 1), - pathSeparator, xUtil_idtag2string(sid, 0), extension); - return fname; -} - -static void XST_reset_raw() -{ - memset(&g_xstdata, 0, sizeof(st_STRAN_DATA)); -} - -static st_STRAN_SCENE* XST_lock_next() -{ - st_STRAN_SCENE* sdata = NULL; - S32 uselock = -1; - for (S32 i = 0; i < 16; i++) - { - if (!(g_xstdata.loadlock & 1 << i)) - { - g_xstdata.loadlock |= 1 << i; - sdata = &g_xstdata.hipscn[i]; - memset(sdata, 0, sizeof(st_STRAN_SCENE)); - uselock = i; - break; - } - } - - if (sdata != NULL) - { - sdata->lockid = uselock; - } - - return sdata; -} - -static void XST_unlock(st_STRAN_SCENE* sdata) -{ - if (sdata != NULL) - { - if (g_xstdata.loadlock & 1 << sdata->lockid) - { - // Can't figure out how to get the andc instruction instead of two instructions - // Seems to only generate andc if I remove the memset call. - // NOTE (Square): pulling 1 << sdata->lockid into a temp variable works but - // causes regswaps. - g_xstdata.loadlock &= ~(1 << sdata->lockid); - memset(sdata, 0, sizeof(st_STRAN_SCENE)); - } - } -} - -static void XST_unlock_all() -{ - if (g_xstdata.loadlock) - { - for (S32 i = 0; i < 16; i++) - { - if (g_xstdata.loadlock & 1 << i) - { - XST_unlock(XST_get_rawinst(i)); - } - } - } -} - -static st_STRAN_SCENE* XST_get_rawinst(S32 index) -{ - return &g_xstdata.hipscn[index]; -} - -static S32 XST_cnt_locked() -{ - S32 sum = 0; - for (int i = 0; i < 16; i++) - { - if (g_xstdata.loadlock & 1 << i) - { - sum++; - } - } - return sum; -} - -static st_STRAN_SCENE* XST_nth_locked(S32 index) -{ - st_STRAN_SCENE* sdata = NULL; - S32 cnt = 0; - for (S32 i = 0; i < 16; i++) - { - if (g_xstdata.loadlock & 1 << i) - { - if (cnt == index) - { - sdata = &g_xstdata.hipscn[i]; - break; - } - cnt += 1; - } - } - - return sdata; -} - -static st_STRAN_SCENE* XST_find_bySID(U32 sid, S32 findTheHOP) -{ - st_STRAN_SCENE* da_sdata = NULL; - - for (S32 i = 0; i < 16; i++) - { - st_STRAN_SCENE* sc = &g_xstdata.hipscn[i]; - if (g_xstdata.loadlock & 1 << i && sc->scnid == sid && (findTheHOP || !sc->isHOP)) - { - if (!findTheHOP || sc->isHOP) - { - da_sdata = sc; - break; - } - } - } - return da_sdata; -} - -WEAK void iFileAsyncService() -{ -} diff --git a/src/SB/Core/x/xutil.cpp b/src/SB/Core/x/xutil.cpp deleted file mode 100644 index 9a518ff..0000000 --- a/src/SB/Core/x/xutil.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include "xutil.h" - -#include "xMath.h" - -#include - -static volatile S32 g_xutilinit; // volatile so xUtilShutdown matches -static S32 g_crc_needinit = 1; -static U32 g_crc32_table[256] = {}; - -S32 xUtilStartup() -{ - if (!g_xutilinit++) - { - xUtil_crc_init(); - } - - return g_xutilinit; -} - -S32 xUtilShutdown() -{ - g_xutilinit--; - return g_xutilinit; -} - -char* xUtil_idtag2string(U32 srctag, S32 bufidx) -{ - U32 tag = srctag; - char* strptr; - char* uc = (char*)&tag; - S32 l; - char t; - static char buf[6][10] = {}; - - if (bufidx < 0 || bufidx >= 7) - { - strptr = buf[0]; - } - else - { - strptr = buf[bufidx]; - } - - // convert tag to big endian - - l = 1; - - if ((S32)((char*)&l)[3] != 0) - { - t = uc[0]; - uc[0] = uc[3]; - uc[3] = t; - - t = uc[1]; - uc[1] = uc[2]; - uc[2] = t; - } - - switch (bufidx) - { - case 4: - case 5: - strptr[0] = isprint(uc[0]) ? uc[0] : '?'; - strptr[1] = isprint(uc[1]) ? uc[1] : '?'; - strptr[2] = isprint(uc[2]) ? uc[2] : '?'; - strptr[3] = isprint(uc[3]) ? uc[3] : '?'; - break; - case 6: - default: - strptr[0] = isprint(uc[3]) ? uc[3] : '?'; - strptr[1] = isprint(uc[2]) ? uc[2] : '?'; - strptr[2] = isprint(uc[1]) ? uc[1] : '?'; - strptr[3] = isprint(uc[0]) ? uc[0] : '?'; - break; - } - - strptr[4] = '\0'; - - if (bufidx == 6) - { - strptr[4] = '/'; - strptr[5] = isprint(uc[0]) ? uc[0] : '?'; - strptr[6] = isprint(uc[1]) ? uc[1] : '?'; - strptr[7] = isprint(uc[2]) ? uc[2] : '?'; - strptr[8] = isprint(uc[3]) ? uc[3] : '?'; - strptr[9] = '\0'; - } - - return strptr; -} - -U32 xUtil_crc_init() -{ - S32 i, j; - U32 crc_accum; - - if (g_crc_needinit) - { - for (i = 0; i < 256; i++) - { - crc_accum = (U32)i << 24; - - for (j = 0; j < 8; j++) - { - if (crc_accum & (1 << 31)) - { - crc_accum = (crc_accum << 1) ^ 0x04C11DB7; - } - else - { - crc_accum = (crc_accum << 1); - } - } - - g_crc32_table[i] = crc_accum; - } - - g_crc_needinit = 0; - } - - return 0xFFFFFFFF; -} - -U32 xUtil_crc_update(U32 crc_accum, char* data, S32 datasize) -{ - S32 i, j; - - if (g_crc_needinit) - { - xUtil_crc_init(); - } - - for (i = 0; i < datasize; i++) - { - j = ((crc_accum >> 24) ^ *data++) & 0xff; - crc_accum = (crc_accum << 8) ^ g_crc32_table[j]; - } - - return crc_accum; -} - -S32 xUtil_yesno(F32 wt_yes) -{ - if (0.0f == wt_yes) - { - return 0; - } - - if (1.0f == wt_yes) - { - return 1; - } - - return (xurand() <= wt_yes); -} - -void xUtil_wtadjust(F32* wts, S32 cnt, F32 arbref) -{ - const volatile F32 ZERO = 0.0f; - - S32 i; - F32 sum = 0.0f, fac; - - for (i = 0; i < cnt; i++) - { - if (wts[i] < ZERO) - { - wts[i] = -wts[i]; - } - - sum += wts[i]; - } - - fac = arbref / sum; - - for (i = 0; i < cnt; i++) - { - wts[i] *= fac; - } -} diff --git a/src/SB/Game/zActionLine.h b/src/SB/Game/zActionLine.h new file mode 100644 index 0000000..3940263 --- /dev/null +++ b/src/SB/Game/zActionLine.h @@ -0,0 +1,17 @@ +#ifndef ZACTIONLINE_H +#define ZACTIONLINE_H + +#include "xVec3.h" + +struct _tagActionLine +{ + U32 flags; + xVec3 pos[4]; + F32 time_left; +}; + +void zActionLineInit(); +void zActionLineUpdate(F32 seconds); +void zActionLineRender(); + +#endif diff --git a/src/SB/Game/zAssetTypes.h b/src/SB/Game/zAssetTypes.h new file mode 100644 index 0000000..e583102 --- /dev/null +++ b/src/SB/Game/zAssetTypes.h @@ -0,0 +1,48 @@ +#ifndef ZASSETTYPES_H +#define ZASSETTYPES_H + +#include +#include +#include +#include "xSnd.h" + +#include "xJSP.h" + +#include "zEntCruiseBubble.h" +#include "zEntPlayerAnimationTables.h" +#include "xHudModel.h" +#include "zNPCTypeAmbient.h" +#include "zNPCTypeCommon.h" +#include "zNPCTypeBossPatrick.h" +#include "zNPCTypeBossPlankton.h" +#include "zNPCTypeBossSandy.h" +#include "zNPCTypeBossSB1.h" +#include "zNPCTypeBossSB2.h" +#include "zNPCTypeDuplotron.h" +#include "zNPCTypeDutchman.h" +#include "zNPCHazard.h" +#include "zNPCTypeKingJelly.h" +#include "zNPCTypePrawn.h" +#include "zNPCTypeRobot.h" +#include "zNPCTypeTest.h" +#include "zNPCTypeTiki.h" + +struct RwMemory +{ + U8* start; + U32 length; +}; + +class HackModelRadius { +public: + U32 assetid; + F32 radius; +}; + +void FootstepHackSceneEnter(); +void jsp_shadow_hack(xJSPHeader* param_1); + +U32 xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, xEnt* pos, F32 radius, + sound_category category, F32 delay); + +#endif diff --git a/src/SB/Game/zCamMarker.h b/src/SB/Game/zCamMarker.h new file mode 100644 index 0000000..f26cd4d --- /dev/null +++ b/src/SB/Game/zCamMarker.h @@ -0,0 +1,20 @@ +#ifndef ZCAMMARKER_H +#define ZCAMMARKER_H + +#include +#include "zCamera.h" +#include "xBase.h" +#include "xCamera.h" +#include "xEvent.h" + +struct zCamMarker : xBase +{ + xCamAsset* asset; +}; + +void zCamMarkerInit(xBase* b, xCamAsset* asset); +void zCamMarkerSave(zCamMarker* m, xSerial* s); +void zCamMarkerLoad(zCamMarker* m, xSerial* s); +int zCamMarkerEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* b3); + +#endif diff --git a/src/SB/Game/zCamera.h b/src/SB/Game/zCamera.h new file mode 100644 index 0000000..1d33f20 --- /dev/null +++ b/src/SB/Game/zCamera.h @@ -0,0 +1,122 @@ +#ifndef ZCAMERA_H +#define ZCAMERA_H + +#include "xCamera.h" + +enum WallJumpViewState +{ + WJVS_DISABLED, + WJVS_DISABLING, + WJVS_ENABLED, + WJVS_ENABLING +}; + +enum camera_owner_enum +{ + CO_BOULDER = 0x1, + CO_CRUISE_BUBBLE, + CO_BUNGEE = 0x4, + CO_BOSS = 0x8, + CO_OOB = 0x10, + CO_ZIPLINE = 0x20, + CO_TURRET = 0x40, + CO_REWARDANIM = 0x80 +}; + +struct zFlyKey +{ + S32 frame; + F32 matrix[12]; + F32 aperture[2]; + F32 focal; +}; + +extern F32 zcam_overrot_tmr; +extern S32 zcam_near; +extern S32 zcam_mode; +extern S32 zcam_bbounce; +extern S32 zcam_lbbounce; +extern S32 zcam_convers; +extern S32 zcam_lconvers; +extern S32 zcam_longbounce; +extern S32 zcam_highbounce; +extern S32 zcam_cutscene; +extern S32 zcam_reward; +extern xVec3* zcam_playervel; +extern S32 zcam_fly; +extern S32 zcam_flypaused; +extern void* zcam_flydata; +extern U32 zcam_flysize; +extern F32 zcam_flytime; +extern U32 zcam_flyasset_current; +extern xCamAsset* zcam_dest; +extern F32 zcam_tmr; +extern F32 zcam_ttm; +extern F32 zcam_fovcurr; +extern F32 zcam_fovdest; + +extern xCamera zcam_backupcam; +extern xCamera zcam_backupconvers; +extern xQuat zcam_quat; + +extern F32 zcam_pad_pyaw_scale; +extern F32 zcam_pad_pitch_scale; +extern F32 zcam_near_d; +extern F32 zcam_near_h; +extern F32 zcam_near_pitch; +extern F32 zcam_far_d; +extern F32 zcam_far_h; +extern F32 zcam_far_pitch; +extern F32 zcam_wall_d; +extern F32 zcam_wall_h; +extern F32 zcam_wall_pitch; +extern F32 zcam_above_d; +extern F32 zcam_above_h; +extern F32 zcam_above_pitch; +extern F32 zcam_below_d; +extern F32 zcam_below_h; +extern F32 zcam_below_pitch; +extern F32 zcam_highbounce_d; +extern F32 zcam_highbounce_h; +extern F32 zcam_highbounce_pitch; +extern F32 zcam_overrot_min; +extern F32 zcam_overrot_mid; +extern F32 zcam_overrot_max; +extern F32 zcam_overrot_rate; +extern F32 zcam_overrot_tstart; +extern F32 zcam_overrot_tend; +extern F32 zcam_overrot_velmin; +extern F32 zcam_overrot_velmax; +extern F32 zcam_overrot_tmanual; +extern F32 zcam_mintgtheight; + +void zCameraReset(xCamera* cam); +void zCameraSetBbounce(S32 bbouncing); +void zCameraSetHighbounce(S32 hbounce); +void zCameraSetLongbounce(S32 hbounce); +void zCameraSetPlayerVel(xVec3* vel); +void zCameraSetConvers(int on); +void zCameraDoTrans(xCamAsset* asset, float ttime); +U32 zCamera_FlyOnly(); +void zCameraTranslate(xCamera* camera, F32 x, F32 y, F32 z); +void zCameraReset(xCamera* camera); +void zCameraUpdate(xCamera* camera, F32 dt); + +void zCameraEnableInput(); +void zCameraDisableInput(); +U32 zCameraIsTrackingDisabled(); +void zCameraEnableTracking(camera_owner_enum owner); +void zCameraDisableTracking(camera_owner_enum owner); +void zCameraDisableLassoCam(); +void zCameraEnableLassoCam(); +void zCameraSetLassoCamFactor(F32 new_factor); +F32 zCameraGetLassoCamFactor(); +void zCameraEnableWallJump(xCamera* cam, const xVec3& collNormal); +S32 zCameraGetConvers(); +void zCameraTranslate(xCamera* cam, F32 x, F32 y, F32 z); +void zCameraDisableWallJump(xCamera* cam); +void zCameraSetReward(S32 reward); +void zCameraMinTargetHeightSet(F32 min_height); +void zCameraMinTargetHeightClear(); + +#endif diff --git a/src/SB/Game/zCameraFly.h b/src/SB/Game/zCameraFly.h new file mode 100644 index 0000000..f860041 --- /dev/null +++ b/src/SB/Game/zCameraFly.h @@ -0,0 +1,29 @@ +#ifndef ZCAMERAFLY_H +#define ZCAMERAFLY_H + +#include +#include "xBase.h" +#include "xDynAsset.h" +#include "xScene.h" + +struct CameraFly_asset : xDynAsset +{ + U32 flyID; +}; + +struct zCameraFly : xBase +{ + CameraFly_asset* casset; +}; + +void zCameraFly_Init(xBase& data, xDynAsset& asset, size_t); +void zCameraFly_Init(zCameraFly* data, CameraFly_asset* asset); +void zCameraFly_Setup(zCameraFly* fly); +void zCameraFly_Update(xBase* to, xScene* scene, F32 dt); +void zCameraFly_Save(zCameraFly* fly, xSerial* s); +void zCameraFly_Load(zCameraFly* fly, xSerial* s); +U32 zCameraFlyProcessStopEvent(); +void zCameraFlyStart(U32 id); +S32 zCameraFlyEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* b3); + +#endif diff --git a/src/SB/Game/zCameraTweak.h b/src/SB/Game/zCameraTweak.h new file mode 100644 index 0000000..ab90cbc --- /dev/null +++ b/src/SB/Game/zCameraTweak.h @@ -0,0 +1,30 @@ +#ifndef ZCAMERATWEAK_H +#define ZCAMERATWEAK_H + +#include "xDynAsset.h" + +#include + +struct CameraTweak_asset : xDynAsset +{ + S32 priority; + F32 time; + F32 pitch_adjust; + F32 dist_adjust; +}; + +struct zCameraTweak : xBase +{ + CameraTweak_asset* casset; +}; + +F32 zCameraTweakGlobal_GetPitch(); +F32 zCameraTweakGlobal_GetH(); +F32 zCameraTweakGlobal_GetD(); +void zCameraTweakGlobal_Update(F32 dt); +void zCameraTweakGlobal_Reset(); +void zCameraTweak_Init(xBase& data, xDynAsset& asset, size_t); +void zCameraTweak_Save(zCameraTweak* tweak, xSerial* s); +void zCameraTweak_Load(zCameraTweak* tweak, xSerial* s); + +#endif diff --git a/src/SB/Game/zCollGeom.h b/src/SB/Game/zCollGeom.h new file mode 100644 index 0000000..be51d59 --- /dev/null +++ b/src/SB/Game/zCollGeom.h @@ -0,0 +1,21 @@ +#ifndef ZCOLLGEOM_H +#define ZCOLLGEOM_H + +#include "xEnt.h" + +#include +#include + +struct zCollGeomTable +{ + RpAtomic* baseModel; + RpAtomic* colModel[1]; + RpAtomic* camcolModel; +}; + +U32 zCollGeom_EntSetup(xEnt* ent); +void zCollGeom_Init(); +void zCollGeom_CamEnable(xEnt* ent); +void zCollGeom_CamDisable(xEnt* ent); + +#endif diff --git a/src/SB/Game/zCombo.h b/src/SB/Game/zCombo.h new file mode 100644 index 0000000..3b1f317 --- /dev/null +++ b/src/SB/Game/zCombo.h @@ -0,0 +1,15 @@ +#ifndef ZCOMBO_H +#define ZCOMBO_H + +#include +#include "xFont.h" +#include "xHud.h" +#include "zEntPickup.h" + +void zCombo_Setup(); +void zCombo_Add(int); +void zCombo_Update(F32); +void zCombo_HideImmediately(); +void zComboHideMessage(xhud::widget& w, xhud::motive& motive); + +#endif diff --git a/src/SB/Game/zConditional.h b/src/SB/Game/zConditional.h new file mode 100644 index 0000000..816563f --- /dev/null +++ b/src/SB/Game/zConditional.h @@ -0,0 +1,32 @@ +#ifndef ZCONDITIONAL_H +#define ZCONDITIONAL_H + +#include "xBase.h" + +#define CONDITION_EQ 0 +#define CONDITION_GT 1 +#define CONDITION_LT 2 +#define CONDITION_GE 3 +#define CONDITION_LE 4 +#define CONDITION_NE 5 + +struct zCondAsset : xBaseAsset +{ + U32 constNum; + U32 expr1; + U32 op; + U32 value_asset; +}; + +struct _zConditional : xBase +{ + zCondAsset* asset; +}; + +void zConditionalInit(xBase* base, zCondAsset* asset); +void zConditionalInit(void* b, void* asset); +void zConditionalLoad(_zConditional* ent, xSerial* s); +void zConditionalSave(_zConditional* ent, xSerial* s); +U32 zConditional_Evaluate(_zConditional* c); + +#endif diff --git a/src/SB/Game/zCutsceneMgr.h b/src/SB/Game/zCutsceneMgr.h new file mode 100644 index 0000000..5c2719f --- /dev/null +++ b/src/SB/Game/zCutsceneMgr.h @@ -0,0 +1,47 @@ +#ifndef ZCUTSCENEMGR_H +#define ZCUTSCENEMGR_H + +#include "xCutsceneMgr.h" +#include "rpworld.h" + +struct xScene; +struct zCutsceneMgr : xCutsceneMgr +{ +}; + +struct zCutsceneHack +{ + char* cinname; + char* modelname; + F32 radius; + U32 tworoot; + U32 noshadow; + U32 alphaBits; + RpAtomic* (*renderCB)(RpAtomic*); +}; + +struct zCutSceneNames +{ + char name[64]; + S32 played; + S32 skipOK; +}; + +void zCutsceneMgrInit(void* b, void* tasset); +void zCutsceneMgrInit(xBase* b, xCutsceneMgrAsset* tasset); +void zCutsceneMgrReset(zCutsceneMgr* mgr); +void zCutsceneMgrSave(zCutsceneMgr*, xSerial* s); +void zCutsceneMgrLoad(zCutsceneMgr*, xSerial* s); +RpAtomic* HackBoundCB(RpAtomic* atomic, void* data); +RpMaterial* HackAlphaSetMaterialAlphaCB(RpMaterial* material, void* data); +RpAtomic* HackAlphaCB(RpAtomic* atomic, void* data); +void zCutSceneNamesTable_clearAll(); +void zCutsceneMgrPlayStart(zCutsceneMgr* t); +S32 zCutsceneMgrEventCB(xBase*, xBase* to, U32 toEvent, const F32*, xBase*); + +void zCutsceneMgrKillFX(zCutsceneMgr* t); +void zCutsceneMgrUpdateFX(zCutsceneMgr* t); +void zCutsceneMgrUpdate(xBase* to, xScene* sc, F32 dt); +void check_hide_entities(); + +#endif diff --git a/src/SB/Game/zDiscoFloor.h b/src/SB/Game/zDiscoFloor.h new file mode 100644 index 0000000..3b06d5e --- /dev/null +++ b/src/SB/Game/zDiscoFloor.h @@ -0,0 +1,97 @@ +#ifndef ZDISCOFLOOR_H +#define ZDISCOFLOOR_H + +#include "zEntSimpleObj.h" + +#include "xBase.h" +#include "xMath3.h" + +struct z_disco_floor_asset : xBaseAsset +{ + U32 flags; + struct + { + F32 transition; + F32 state; + } interval; + struct + { + U32 off; + U32 transition; + U32 on; + } prefix_offset; + U32 state_mask_size; + U32 states_offset; + U32 states_size; +}; + +struct z_disco_floor : xBase +{ + struct tile_data + { + bool culled; + zEntSimpleObj* ent; + xSphere sphere; + }; + + struct + { + bool enabled; + bool forward; + bool culled; + bool glow_culled; + } flag; + z_disco_floor_asset* asset; + + U8** state_masks; + U8* active_state_mask; + U8* next_state_mask; + const char* prefix[3]; + tile_data* tiles[3]; + U32 tiles_size; + U32 min_state; + U32 max_state; + U32 state; + U32 next_state; + U32 state_counter; + F32 transition_delay; + F32 state_delay; + F32 transition_time; + F32 state_time; + xSphere bound; + F32 pulse_time; + F32 pulse_glow[3]; + F32 cull_dist_glow; + F32 cull_dist_update; + F32 glow_fade; + F32 sound_delay; + S32 curr_note; + + static void init(); + static void init(void* ent, void* asset); + static void post_setup(); + static void destroy(); + static void render_all(); + static void effects_render_all(); + static S32 event_handler(xBase*, xBase* to, U32 event, const F32* argf, xBase*); + + void load(z_disco_floor_asset& asset); + void setup(); + void reset(); + void update(xScene&, F32 dt); + void set_state(size_t state, bool immediate); + void enable(); + void disable(); + void set_state_range(S32 min, S32 max, bool immediate); + void set_transition_delay(F32 s); + void set_state_delay(F32 s); + void refresh_spheres(); + void update_pulse(F32 dt); + void refresh_bound(); + void refresh_cull_dist(); + void distance_cull(); + void render(S32 group); + void effects_render(S32 group); +}; + +#endif diff --git a/src/SB/Game/zDispatcher.h b/src/SB/Game/zDispatcher.h new file mode 100644 index 0000000..e3abc3e --- /dev/null +++ b/src/SB/Game/zDispatcher.h @@ -0,0 +1,83 @@ +#ifndef ZDISPATCHER_H +#define ZDISPATCHER_H + +#include "xBase.h" + +struct st_ZDISPATCH_DATA : xBase +{ + xBaseAsset* rawass; + S32 placeholder; +}; + +struct st_ZDISPATCH_DEPOT +{ + st_ZDISPATCH_DATA* raw_pool; + S32 raw_cnt; +}; + +enum en_DISPATCH_COMMAND +{ + ZDSP_CMD_INITDFLT = 0xffffffff, + ZDSP_CMD_CTRL_CFGGET = 0, + ZDSP_CMD_CTRL_CFGSET, + ZDSP_CMD_CTRL_VIBEGET, + ZDSP_CMD_CTRL_VIBESET, + ZDSP_CMD_SNDMOD_GET, + ZDSP_CMD_SNDMOD_SET, + ZDSP_CMD_SNDVOL_GET, + ZDSP_CMD_SNDVOL_SET, + ZDSP_CMD_SNDVOL_INCR, + ZDSP_CMD_SNDVOL_DECR, + ZDSP_CMD_MUSVOL_GET, + ZDSP_CMD_MUSVOL_SET, + ZDSP_CMD_MUSVOL_INCR, + ZDSP_CMD_MUSVOL_DECR, + ZDSP_CMD_SFXVOL_GET, + ZDSP_CMD_SFXVOL_SET, + ZDSP_CMD_SFXVOL_INCR, + ZDSP_CMD_SFXVOL_DECR, + ZDSP_CMD_GSTATE_GET, + ZDSP_CMD_GSTATE_SET, + ZDSP_CMD_GMODE_GET, + ZDSP_CMD_GMODE_SET, + ZDSP_CHECKPNT_SET, + ZDSP_CMD_NOMORE +}; + +struct st_ZDISPATCH_CONTEXT +{ + en_DISPATCH_COMMAND cmd; + void* indata; + void* inxtra; + void* result; +}; + +struct zScene; + +void zDispatcher_Startup(); +void zDispatcher_Shutdown(); +void zDispatcher_scenePrepare(); +void zDispatcher_sceneFinish(); +st_ZDISPATCH_DATA* zDispatcher_memPool(S32 cnt); +st_ZDISPATCH_DATA* zDispatcher_getInst(st_ZDISPATCH_DATA* pool, S32 idx); +void zDispatcher_Init(st_ZDISPATCH_DATA* dspdata, xBaseAsset* bass); +void zDispatcher_InitDep(st_ZDISPATCH_DATA* dspdata, zScene*); +void zDispatcher_Save(st_ZDISPATCH_DATA* dspdata, xSerial* s); +void zDispatcher_Load(st_ZDISPATCH_DATA* dspdata, xSerial* s); +void ZDSP_instInit(st_ZDISPATCH_DATA* dspdata, xBaseAsset* bass); +void ZDSP_instInitDep(st_ZDISPATCH_DATA* dspdata, zScene* scene); +void ZDSP_instReset(st_ZDISPATCH_DATA* dspdata, zScene* scene); +void ZDSP_readAsset(st_ZDISPATCH_DATA* dspdata); +void ZDSP_injectCmd(st_ZDISPATCH_DATA* dspdata, en_DISPATCH_COMMAND cmd); +void ZDSP_injectCmd(st_ZDISPATCH_DATA* dspdata, en_DISPATCH_COMMAND cmd, S32); +void ZDSP_injectCmd(st_ZDISPATCH_DATA* dspdata, en_DISPATCH_COMMAND cmd, void* indata, void* inxtra, + void* result); +S32 ZDSP_doCommand(st_ZDISPATCH_DATA* dspdata, st_ZDISPATCH_CONTEXT* cmdCtxt); +void zDispatcherStoreOptions(); +void zDispatcherRestoreOptions(); +S32 ZDSP_elcb_event(xBase*, xBase* xb, U32 toEvent, const F32* toParam, + xBase* toParamWidget); +void WRAP_xsnd_setMusicVolume(S32 i); +void WRAP_xsnd_setSFXVolume(S32 i); + +#endif diff --git a/src/SB/Game/zEGenerator.h b/src/SB/Game/zEGenerator.h new file mode 100644 index 0000000..53c380e --- /dev/null +++ b/src/SB/Game/zEGenerator.h @@ -0,0 +1,46 @@ +#ifndef ZEGENERATOR_H +#define ZEGENERATOR_H + +#include "zEnt.h" +#include "zLightning.h" + +#include + +struct zEGenAsset : xEntAsset +{ + xVec3 src_dpos; + U8 damage_type; + U8 flags; + F32 ontime; + U32 onAnimID; +}; + +struct zEGenerator : zEnt +{ + zEGenAsset* zasset; + U16 flags; + U16 num_dsts; + F32 tmr; + xAnimFile* afile; + xVec3 src_pos; + xVec3 dst_pos; + xVec3 dst_off; + xBase* dst; + zLightning* lfx[2]; +}; + +void zEGenerator_Init(void* egen, void* asset); +void zEGenerator_Init(zEGenerator* egen, xEntAsset* asset); +void zEGenerator_Setup(zEGenerator* egen, xScene* sc); +void zEGenerator_Save(zEGenerator* ent, xSerial* s); +void zEGenerator_Load(zEGenerator* ent, xSerial* s); +void zEGenerator_Reset(zEGenerator* egen, xScene* sc); +void zEGenerator_Move(zEGenerator* egen, xScene* sc, F32 dt); +void zEGenerator_Render(zEGenerator* egen); +void zEGenerator_TurnOn(zEGenerator* egen); +void zEGenerator_TurnOff(zEGenerator* egen); +void zEGenerator_ToggleOn(zEGenerator* egen); +S32 zEGeneratorEventCB(xBase* to, xBase* from, U32 toEvent, const F32* toParam, + xBase* toParamWidget); + +#endif diff --git a/src/SB/Game/zEnt.cpp b/src/SB/Game/zEnt.cpp new file mode 100644 index 0000000..1355560 --- /dev/null +++ b/src/SB/Game/zEnt.cpp @@ -0,0 +1,935 @@ +#include "zEnt.h" + +#include + +#include "zGlobals.h" +#include "zAnimList.h" +#include "zNPCTypeCommon.h" +#include "xNPCBasic.h" +#include "xstransvc.h" +#include "xString.h" +#include "xMath.h" +#include "xutil.h" +#include "iModel.h" +#include "xSnd.h" +#include "xCollide.h" +#include "zNPCTypes.h" +#include +#include + +void zEntInit(zEnt* ent, xEntAsset* asset, U32 type) +{ + xEntInit(ent, asset); + ent->update = (xEntUpdateCallback)zEntUpdate; + + // Surprisingly, this is not a switch statement. + if (type == 0x504c5952) + { + ent->collType = 0x10; + ent->collLev = 0x4; + ent->bound.type = 0x1; + zEntParseModelInfo(ent, asset->modelInfoID); + } + else if (type == 0x56494c20) + { + ent->collType = 0x8; + ent->collLev = 0x4; + ent->bound.type = 0x1; + ent->moreFlags = ent->moreFlags | 0x10; + zEntParseModelInfo(ent, asset->modelInfoID); + } + else if (type == 0x4954454d) + { + ent->collType = 0x2; + ent->collLev = 0x4; + ent->bound.type = 0x1; + ent->eventFunc = NULL; + zEntParseModelInfo(ent, asset->modelInfoID); + } + else if (type == 0x504b5550) + { + ent->collType = 0; + ent->bound.type = 0; + } + else if (type == 0x504c4154) + { + ent->collType = 0x4; + if (asset->moreFlags & 2) + { + ent->collLev = 0x5; + } + else + { + ent->collLev = 0x4; + } + zEntParseModelInfo(ent, asset->modelInfoID); + ent->bound.type = 0x4; + ent->bound.mat = (xMat4x3*)ent->model->Mat; + } + else if (type == 0x50454e44) + { + ent->collType = 0x4; + if (asset->moreFlags & 2) + { + ent->collLev = 0x5; + } + else + { + ent->collLev = 0x4; + } + zEntParseModelInfo(ent, asset->modelInfoID); + ent->bound.type = 0x4; + ent->bound.mat = (xMat4x3*)ent->model->Mat; + } + else if (type == 0x54524947) + { + ent->collType = 0x1; + ent->bound.type = 0; + } + else if (type == 0x48414e47) + { + ent->collType = 0x4; + ent->collLev = 0x4; + ent->bound.type = 0x1; + zEntParseModelInfo(ent, asset->modelInfoID); + } + else if (type == 0x53494d50) + { + ent->collType = 0x2; + if (asset->moreFlags & 2) + { + ent->collLev = 0x5; + } + else + { + ent->collLev = 0x4; + } + ent->bound.type = 0x4; + zEntParseModelInfo(ent, asset->modelInfoID); + ent->bound.mat = (xMat4x3*)ent->model->Mat; + } + else if (type == 0x55492020) + { + } + else if (type == 0x4255544e) + { + ent->collType = 0x4; + if (asset->moreFlags & 2) + { + ent->collLev = 0x5; + } + else + { + ent->collLev = 0x4; + } + ent->bound.type = 0x4; + ent->moreFlags = ent->moreFlags | 0x10; + zEntParseModelInfo(ent, asset->modelInfoID); + ent->bound.mat = (xMat4x3*)ent->model->Mat; + } + else if (type == 0x44535452) + { + ent->collType = 0x4; + if (asset->moreFlags & 2) + { + ent->collLev = 0x5; + } + else + { + ent->collLev = 0x4; + } + ent->bound.type = 0x4; + ent->moreFlags = ent->moreFlags | 0x10; + zEntParseModelInfo(ent, asset->modelInfoID); + ent->bound.mat = (xMat4x3*)ent->model->Mat; + } + else if (type == 0x4547454e) + { + ent->collType = 0x4; + if (asset->moreFlags & 2) + { + ent->collLev = 0x5; + } + else + { + ent->collLev = 0x4; + } + ent->bound.type = 0x4; + zEntParseModelInfo(ent, asset->modelInfoID); + ent->bound.mat = (xMat4x3*)ent->model->Mat; + } + else if (type == 0x54424f58) + { + ent->collType = 0x2; + ent->collLev = 0x5; + ent->bound.type = 0x4; + zEntParseModelInfo(ent, asset->modelInfoID); + ent->bound.mat = (xMat4x3*)ent->model->Mat; + } + + if (asset->animListID != 0) + { + S32 num_used = zAnimListGetNumUsed(asset->animListID); + if (num_used > 0) + { + ent->atbl = zAnimListGetTable(asset->animListID); + xAnimPoolAlloc(&globals.sceneCur->mempool, ent, ent->atbl, ent->model); + xAnimState* ast = xAnimTableGetState(ent->atbl, "idle"); + if (ast != NULL) + { + xAnimSingle* single = ent->model->Anim->Single; + single->State = ast; + single->Time = 0.0f; + single->CurrentSpeed = 1.0f; + xModelEval(ent->model); + } + } + else + { + ent->atbl = NULL; + } + } + else + { + ent->atbl = NULL; + } + + xEntInitForType(ent); +} + +void zEntSetup(zEnt* ent) +{ + xEntSetup(ent); + checkpoint_collision_hack(ent); +} + +// Equivalent +// This function needs to be declared inline to generate the correct mangled name for model_id +inline void checkpoint_collision_hack(zEnt* ent) +{ + // instruction swap involving the guard for this static initializer. + // Might be due to the sda reloc access for model_id getting moved down + static U32 model_id = xStrHash("checkpoint_bind"); + if (ent->asset->modelInfoID == model_id) + { + ent->bound.type = 0x2; + xVec3* lower = &ent->bound.box.box.lower; + xVec3* upper = &ent->bound.box.box.upper; + *lower = *upper = xEntGetFrame(ent)->pos; + + lower->x += -0.5f; + lower->z += -0.5f; + + upper->x += 0.5f; + upper->y += 5.0f; + upper->z += 0.5f; + + xEntDefaultBoundUpdate(ent, &xEntGetFrame(ent)->pos); + + ent->miscflags = ent->miscflags | 8; + + xEntAnimateCollision(*ent, 0); + xModelAnimCollStop(*(ent->collModel != NULL ? ent->collModel : ent->model)); + + ent->moreFlags = ent->moreFlags & 0xdd; + ent->asset->moreFlags = ent->asset->moreFlags & 0xdd; + ent->baseFlags = ent->baseFlags & 0xffef; + ent->asset->baseFlags = ent->asset->baseFlags & 0xffef; + } +} + +void zEntSave(zEnt* ent, xSerial* s) +{ + xEntSave(ent, s); +} + +void zEntLoad(zEnt* ent, xSerial* s) +{ + xEntLoad(ent, s); +} + +void zEntReset(zEnt* ent) +{ + xEntReset(ent); + + if (ent->asset->animListID != 0 && ent->atbl != NULL) + { + xAnimState* ast = xAnimTableGetState(ent->atbl, "idle"); + if (ast != NULL) + { + xAnimSingle* single = ent->model->Anim->Single; + single->State = ast; + single->Time = 0.0f; + single->CurrentSpeed = 1.0f; + xModelEval(ent->model); + } + } + + if (!(ent->miscflags & 1) && ent->asset->modelInfoID != 0 && ent->model != NULL && + ent->model->Anim != NULL && ent->model->Anim->Table != NULL && + strcmp("xEntAutoEventSimple", ent->model->Anim->Table->Name) == 0) + { + ent->model->Anim = ent->model->Anim; + xAnimPlaySetState(ent->model->Anim->Single, ent->model->Anim->Table->StateList, 0.0f); + ent->miscflags = ent->miscflags | 1; + } + checkpoint_collision_hack(ent); +} + +void zEntUpdate(zEnt* ent, zScene* scene, F32 elapsedSec) +{ + xEntUpdate(ent, scene, elapsedSec); +} + +void zEntEventAll(xBase* from, U32 fromEvent, U32 toEvent, F32* toParam) +{ + zScene* s = globals.sceneCur; + for (U16 i = 0; i < s->num_base; i++) + { + zEntEvent(from, fromEvent, s->base[i], toEvent, toParam, NULL, 0); + } +} + +void zEntEventAllOfType(xBase* from, U32 fromEvent, U32 toEvent, F32* toParam, U32 type) +{ + zScene* s = globals.sceneCur; + if (s == NULL) + { + return; + } + + for (U16 i = 0; i < s->num_base; i++) + { + xBase* base = s->base[i]; + if (type == base->baseType) + { + zEntEvent(from, fromEvent, base, toEvent, toParam, NULL, 0); + } + } +} + +void zEntEventAllOfType(U32 toEvent, U32 type) +{ + zEntEventAllOfType(NULL, 0, toEvent, NULL, type); +} + +xModelInstance* zEntRecurseModelInfo(void* info, xEnt* ent) +{ + xModelAssetInfo* zinfo = (xModelAssetInfo*)info; + xModelAssetInst* zinst = (xModelAssetInst*)(zinfo + 1); + U32 bufsize; + xModelInstance* tempInst[64]; + + for (U32 i = 0; i < zinfo->NumModelInst; i++) + { + RpAtomic* imodel = (RpAtomic*)xSTFindAsset(zinst[i].ModelID, &bufsize); + if (*(U32*)&imodel->object.object == 0x464e494d) + { + tempInst[i] = zEntRecurseModelInfo(imodel, ent); + if (i != 0) + { + tempInst[i]->Flags |= zinst[i].Flags; + tempInst[i]->BoneIndex = zinst[i].Bone; + xModelInstanceAttach(tempInst[i], tempInst[zinst[i].Parent]); + } + } + else + { + if (i == 0) + { + tempInst[i] = xModelInstanceAlloc(imodel, ent, 0, 0, 0); + tempInst[i]->modelID = zinst[i].ModelID; + while (imodel = iModelFile_RWMultiAtomic(imodel), imodel != NULL) + { + xModelInstanceAttach(xModelInstanceAlloc(imodel, ent, 0x2000, 0, NULL), + tempInst[i]); + } + } + else + { + tempInst[i] = xModelInstanceAlloc(imodel, ent, zinst[i].Flags, zinst[i].Bone, NULL); + xModelInstanceAttach(tempInst[i], tempInst[zinst[i].Parent]); + + while (imodel = iModelFile_RWMultiAtomic(imodel), imodel != NULL) + { + xModelInstanceAttach(xModelInstanceAlloc(imodel, ent, 0x2000, 0, NULL), + tempInst[i]); + } + } + } + } + if (zinfo->AnimTableID != 0) + { + xAnimTable* table = (xAnimTable*)xSTFindAsset(zinfo->AnimTableID, &bufsize); + tempInst[0]->Anim = xAnimPoolAlloc(&globals.sceneCur->mempool, ent, table, tempInst[0]); + } + return tempInst[0]; +} + +void zEntParseModelInfo(xEnt* ent, U32 assetID) +{ + U32 bufsize[4]; + void* info = xSTFindAsset(assetID, bufsize); + if (*(U32*)info == 0x464e494d) + { + ent->model = zEntRecurseModelInfo(info, ent); + } + else + { + xEntLoadModel(ent, (RpAtomic*)info); + ent->model->modelID = assetID; + } +} + +// This function suffers from a couple floating point memes +// Additionally it has a jumptable that needs to be generated in the correct place. +void zEntAnimEvent(zEnt* ent, U32 animEvent, const F32* animParam) +{ + xAnimPlay* play = ent->model->Anim; + if (play == NULL) + { + return; + } + + xAnimSingle* single = play->Single; + if (single == NULL) + { + return; + } + + if (ent->miscflags & 1) + { + zEntAnimEvent_AutoAnim(ent, animEvent, animParam); + } + else + { + switch (animEvent) + { + case 0xc3: + case 0xc4: + if (animParam == NULL) + { + break; + } + + S32 anum = (int)*animParam - 1; + if (anum < 0 || anum >= 10 || ent->atbl == NULL) + { + break; + } + + char name[12]; + if (animEvent == 0xc4) + { + sprintf(name, "loop%d", anum); + } + else + { + sprintf(name, "stop%d", anum); + } + + xAnimState* ast = xAnimTableGetState(ent->atbl, name); + if (ast == NULL) + { + break; + } + + xAnimPlaySetState(single, ast, 0.0f); + single->CurrentSpeed = 1.0f; + xAnimPlayUpdate(play, 0.0f); + xAnimPlayEval(play); + + if (ent->asset->modelInfoID != 0x8D398D0C /*is this an address???*/ || + animEvent != 0xc3) + { + break; + } + + xSndPlay3D(xStrHash("Check1"), 0.77f, 0.0f, 0x80, 0, (xVec3*)&ent->model->Mat->pos, + 0.0f, SND_CAT_GAME, 0.0f); + + break; + case 0xc5: + if (strcmp(single->State->Name, "idle") == 0) + { + break; + } + char name2[12]; + strcpy(name2, single->State->Name); + name2[0] = 's'; + name2[1] = 't'; + + single->State = xAnimTableGetState(ent->atbl, name2); + break; + case 0xc6: + single->CurrentSpeed = 0.0f; + break; + case 199: + single->CurrentSpeed = 1.0f; + break; + case 200: + if (single->CurrentSpeed) + { + single->CurrentSpeed = 0.0f; + } + else + { + single->CurrentSpeed = 1.0f; + } + break; + case 0xc9: + if (animParam == NULL) + { + break; + } + + S32 anum2 = (int)animParam[0] - 1; + S32 anum3 = (int)animParam[1] - 1; + if (anum2 < 0 || anum2 > anum3 || anum3 >= 10 || ent->atbl == NULL) + { + break; + } + + S32 anum4 = xrand(); + anum3 = anum3 - anum2 + 1; + anum4 %= anum3; + + char name3[12]; + sprintf(name3, "stop%d", anum2 + anum4); + + xAnimState* ast2 = xAnimTableGetState(ent->atbl, name3); + if (ast2 == NULL) + { + break; + } + + xAnimPlaySetState(single, ast2, 0.0f); + single->CurrentSpeed = 1.0f; + xAnimPlayUpdate(play, 0.0f); + xAnimPlayEval(play); + break; + case 0xca: + if (animParam == NULL) + { + break; + } + + S32 anum5 = (int)*animParam - 1; + F32 prob = 0.01f * animParam[1]; + if (anum5 < 0 || anum5 >= 10) + { + break; + } + + // Inverting this if screws up the float comparison + if (xurand() < prob && ent->atbl != NULL) + { + char name4[12]; + sprintf(name4, "stop%d", anum5); + xAnimState* ast3 = xAnimTableGetState(ent->atbl, name4); + if (ast3 == NULL) + { + break; + } + + single->CurrentSpeed = 1.0f; + xAnimPlaySetState(single, ast3, 0.0f); + xAnimPlayUpdate(play, 0.0f); + xAnimPlayEval(play); + } + break; + } + } +} + +U32 g_hash_xentanim[5] = { 0 }; +char* g_strz_xentanim[5] = { + "Idle01", "Anim02", "Anim03", "Anim04", "Anim05", +}; +// Thank you floating point memes. Very cool. +xAnimTable* xEnt_AnimTable_AutoEventSmall() +{ + char** names = g_strz_xentanim; + U32* hash = g_hash_xentanim; + xAnimTransition* deftran = NULL; + if (*hash == 0) + { + for (S32 i = 0; i < 5; i++) + { + hash[i] = xStrHash(names[i]); + } + } + + xAnimTable* table = xAnimTableNew("xEntAutoEventSimple", NULL, 0); + + for (S32 i = 0; i < 5; i++) + { + if (i == 0) + { + xAnimTableNewState(table, names[i], 0x10, 1, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + } + else + { + xAnimTableNewState(table, names[i], 0x20, 1, 1.0f, NULL, NULL, 0.0f, NULL, NULL, + xAnimDefaultBeforeEnter, NULL, NULL); + } + if (deftran != NULL) + { + xAnimTableAddTransition(table, deftran, names[i]); + } + else + { + if (i != 0) + { + deftran = xAnimTableNewTransition(table, names[i], names[0], 0, 0, 0x10, 0, 0.0f, + 0.0f, 1, 0, 0.25f, 0); + } + } + } + return table; +} + +// This function needs the floats to be replaced with literals +// and the jumptable to be generated in the right spot. +void zEntAnimEvent_AutoAnim(zEnt* ent, U32 animEvent, const F32* animParam) +{ + xAnimPlay* play = ent->model->Anim; + xAnimSingle* single = play->Single; + + switch (animEvent) + { + case 0xc3: + case 0xc4: + if (animParam == NULL) + { + break; + } + + S32 anum = (int)*animParam + -1; + if (anum < 0 || anum >= 5) + { + break; + } + + xAnimTable* tab1 = ent->model->Anim->Table; + if (tab1 == NULL) + { + break; + } + + xAnimState* ast = xAnimTableGetStateID(tab1, g_hash_xentanim[anum]); + if (ast == NULL) + { + break; + } + + if (anum != 0) + { + if (animEvent == 0xc4) + { + ast->Flags = ast->Flags & 0xffffffdf; + ast->Flags = ast->Flags | 0x10; + } + else + { + ast->Flags = ast->Flags | 0x20; + ast->Flags = ast->Flags & 0xffffffef; + } + } + xAnimPlaySetState(single, ast, 0.0f); + single->CurrentSpeed = 1.0f; + xAnimPlayUpdate(play, 0.0f); + xAnimPlayEval(play); + break; + case 0xc5: + xAnimTable* tab2 = ent->model->Anim->Table; + if (tab2 == NULL) + { + break; + } + + xAnimState* ast2 = xAnimTableGetStateID(tab2, g_hash_xentanim[0]); + if (ast2 != 0) + { + xAnimPlaySetState(single, ast2, 0.0f); + single->CurrentSpeed = 0.0f; + xAnimPlayUpdate(play, 0.0f); + xAnimPlayEval(play); + } + break; + case 0xc6: + single->CurrentSpeed = 0.0f; + break; + case 199: + single->CurrentSpeed = 1.0f; + break; + case 200: + if (single->CurrentSpeed > 0.0f) + { + single->CurrentSpeed = 0.0f; + } + else + { + single->CurrentSpeed = 1.0f; + } + break; + case 0xc9: + if (animParam == NULL) + { + break; + } + + S32 anum1 = (int)animParam[0] - 1; + S32 anum2 = (int)animParam[1] - 1; + if (anum1 < 0 || anum2 < 0 || anum1 > anum2 || anum2 >= 5) + { + break; + } + + S32 anum3 = xrand(); + anum2 = anum2 - anum1 + 1; + anum3 %= anum2; + anum1 += anum3; + + xAnimTable* tab3 = ent->model->Anim->Table; + if (tab3 == NULL) + { + break; + } + + xAnimState* ast3 = xAnimTableGetStateID(tab3, g_hash_xentanim[anum1]); + if (ast3 == NULL) + { + break; + } + + if (anum1 != 0) + { + ast3->Flags = ast3->Flags | 0x20; + ast3->Flags = ast3->Flags & 0xffffffef; + } + xAnimPlaySetState(single, ast3, 0.0f); + single->CurrentSpeed = 1.0f; + xAnimPlayUpdate(play, 0.0f); + xAnimPlayEval(play); + break; + case 0xca: + if (xUtil_yesno(0.01f * animParam[1]) != 0) + { + zEntAnimEvent_AutoAnim(ent, 0xc3, animParam); + } + break; + } +} + +xModelAssetParam* zEntGetModelParams(U32 assetID, U32* size) +{ + U32 bufsize; + void* info = xSTFindAsset(assetID, &bufsize); + xModelAssetInfo* minf = (xModelAssetInfo*)info; + + if (minf->Magic == 0x464e494d) + { + *size = bufsize - (minf->NumModelInst * 0x38 + 0x14); + if (*size != 0) + { + return (xModelAssetParam*)((char*)minf + minf->NumModelInst * 0x38 + 0x14); + } + } + else + { + *size = 0; + } + + return NULL; +} + +char* zParamGetString(xModelAssetParam* param, U32 size, char* tok, char* def) +{ + U32 hash = xStrHash(tok); + + while (param != NULL && size != 0) + { + if (param->HashID == hash) + { + return (char*)param->String; + } + + // S32 i = param->WordLength * 4; + size -= param->WordLength * 4 + 8; + param = (xModelAssetParam*)((char*)param + (param->WordLength * 4 + 8)); + } + return def; +} + +S32 zParamGetInt(xModelAssetParam* param, U32 size, const char* tok, S32 def) +{ + return zParamGetInt(param, size, (char*)tok, def); +} + +S32 zParamGetInt(xModelAssetParam* param, U32 size, char* tok, S32 def) +{ + char* str = zParamGetString(param, size, tok, NULL); + if (str != NULL) + { + return atoi(str); + } + return def; +} + +F32 zParamGetFloat(xModelAssetParam* param, U32 size, const char* tok, F32 def) +{ + return zParamGetFloat(param, size, (char*)tok, def); +} + +F32 zParamGetFloat(xModelAssetParam* param, U32 size, char* tok, F32 def) +{ + char* str = zParamGetString(param, size, tok, NULL); + if (str != NULL) + { + return xatof(str); + } + return def; +} + +S32 zParamGetFloatList(xModelAssetParam* param, U32 size, const char* tok, S32 count, F32* def, + F32* result) +{ + return zParamGetFloatList(param, size, (char*)tok, count, def, result); +} + +S32 zParamGetFloatList(xModelAssetParam* param, U32 size, char* tok, S32 count, F32* def, + F32* result) +{ + char* str = zParamGetString(param, size, tok, NULL); + S32 act = 0; + + if (def != NULL) + { + for (S32 i = 0; i < count; i++) + { + result[i] = def[i]; + } + } + + if (str != NULL) + { + act = xStrParseFloatList(result, str, count); + } + return act; +} + +S32 zParamGetVector(xModelAssetParam* param, U32 size, const char* tok, xVec3 vec1, xVec3* vec2) +{ + return zParamGetVector(param, size, (char*)tok, vec1, vec2); +} + +S32 zParamGetVector(xModelAssetParam* param, U32 size, char* tok, xVec3 vec1, xVec3* vec2) +{ + char* str = zParamGetString(param, size, tok, NULL); + S32 list = 0; + + xVec3 vec = { 0 }; + + xVec3Copy(vec2, &vec1); + if (str != NULL) + { + list = xStrParseFloatList((F32*)&vec, str, 3); + if (list > 0) + { + vec2->x = vec.x; + } + + if (list > 1) + { + vec2->y = vec.y; + } + + if (list > 2) + { + vec2->z = vec.z; + } + } + return list; +} + +// clang-format off +_ShadowParams gShadowParams[] = { + {NPC_TYPE_HAMMER, 0.33f, 2.0f}, + {NPC_TYPE_GLOVE, 0.0f, 1.25f}, + {NPC_TYPE_PLANKNPC, -0.25f, 0.75f}, + {NPC_TYPE_SLEEPY, 0.5f, 1.0f}, + {NPC_TYPE_BOSSSANDY, 1.0f, 2.0f}, +}; +// clang-format on + +void zEntGetShadowParams(xEnt* ent, xVec3* center, F32* radius, xEntShadow::radius_enum rtype) +{ + *center = *xBoundCenter(&ent->bound); + F32 r; + if (ent->entShadow != NULL) + { + r = ent->entShadow->radius[rtype]; + if (r > 0.0f) + { + *radius = r; + return; + } + } + + if (ent->bound.type == 0x1) + { + r = ent->bound.sph.r; + } + else + { + xVec3* lower = &ent->bound.box.box.lower; + xVec3* upper = &ent->bound.box.box.upper; + r = 0.167f * (upper->x + upper->y + upper->z - lower->x - lower->y - lower->z); + } + + *radius = r < 0.01f ? 2.0f : 2.4f * r; + + if (ent == &globals.player.ent) + { + *radius *= 1.5f; + } + else if (ent->baseType == 0x2b) + { + zNPCCommon* zp = (zNPCCommon*)ent; + _ShadowParams* sp = gShadowParams; + for (U32 i = 0; i < 5; i++) + { + if (sp->type == zp->SelfType()) + { + xVec3* at = (xVec3*)&ent->model->Mat->at; + xVec3AddScaled(center, at, sp->at); + *radius *= sp->rad; + return; + } + sp++; + } + } +} + +void xModelAnimCollStop(xModelInstance& m) +{ + m.Flags = m.Flags & 0xe7ff; +} + +xMat4x3* xEntGetFrame(const xEnt* ent) +{ + return xModelGetFrame(ent->model); +} + +void xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, const xVec3* pos, F32 radius, + sound_category category, F32 delay) +{ + xSndPlay3D(id, vol, pitch, priority, flags, pos, radius / 4.0f, radius, category, delay); +} + +S32 xNPCBasic::SelfType() const +{ + return myNPCType; +}; diff --git a/src/SB/Game/zEnt.h b/src/SB/Game/zEnt.h new file mode 100644 index 0000000..71673ce --- /dev/null +++ b/src/SB/Game/zEnt.h @@ -0,0 +1,63 @@ +#ifndef ZENT_H +#define ZENT_H + +#include "xEnt.h" +#include "xAnim.h" + +#include "zScene.h" +#include "zEvent.h" + +//For inline/weak functions +#include "xSnd.h" + +struct zScene; + +struct _ShadowParams +{ + U32 type; + F32 at; + F32 rad; +}; + +struct zEnt : xEnt +{ + xAnimTable* atbl; +}; + +void checkpoint_collision_hack(zEnt* ent); +char* zParamGetString(xModelAssetParam* param, U32 size, char* tok, char* def); +S32 zParamGetFloatList(xModelAssetParam* param, U32 size, const char* tok, S32 count, + F32* def, F32* result); +void zEntGetShadowParams(xEnt* ent, xVec3* center, F32* radius, xEntShadow::radius_enum rtype); +S32 zParamGetVector(xModelAssetParam* param, U32 size, const char* tok, xVec3 result, xVec3*); +S32 zParamGetVector(xModelAssetParam* param, U32 size, char* tok, xVec3 result, xVec3*); +S32 zParamGetFloatList(xModelAssetParam* param, U32 size, char* tok, S32 count, F32* def, + F32* result); +S32 zParamGetFloatList(xModelAssetParam* param, U32 size, char* tok, S32 count, F32* def, + F32* result); +F32 zParamGetFloat(xModelAssetParam* param, U32 size, const char* tok, F32 def); +F32 zParamGetFloat(xModelAssetParam* param, U32 size, char* tok, F32 def); +S32 zParamGetInt(xModelAssetParam* param, U32 size, const char* tok, S32 def); +S32 zParamGetInt(xModelAssetParam* param, U32 size, char* tok, S32 def); +xModelAssetParam* zEntGetModelParams(U32 assetID, U32* size); +void zEntAnimEvent_AutoAnim(zEnt* ent, U32 animEvent, const F32* animParam); +xAnimTable* xEnt_AnimTable_AutoEventSmall(); +void zEntAnimEvent(zEnt* ent, U32 animEvent, const F32* animParam); +void zEntParseModelInfo(xEnt* ent, U32 assetID); +xModelInstance* zEntRecurseModelInfo(void* info, xEnt* ent); +void zEntEventAllOfType(U32 toEvent, U32 type); +void zEntEventAll(xBase* from, U32 fromEvent, U32 toEvent, F32* toParam); +void zEntUpdate(zEnt* ent, zScene* scene, F32 elapsedSec); +void zEntReset(zEnt* ent); +void zEntLoad(zEnt* ent, xSerial* s); +void zEntSave(zEnt* ent, xSerial* s); +void zEntSetup(zEnt* ent); +void zEntInit(zEnt* ent, xEntAsset* asset, U32 type); + +// TODO: Misplaced Inlines/Weak functions +WEAK void xModelAnimCollStop(xModelInstance& m); +WEAK xMat4x3* xEntGetFrame(const xEnt* ent); +WEAK void xSndPlay3D(U32 id, F32 vol, F32 pitch, U32 priority, U32 flags, + const xVec3* pos, F32 radius, sound_category category, F32 delay); + +#endif diff --git a/src/SB/Game/zEntButton.h b/src/SB/Game/zEntButton.h new file mode 100644 index 0000000..db2c527 --- /dev/null +++ b/src/SB/Game/zEntButton.h @@ -0,0 +1,48 @@ +#ifndef ZENTBUTTON_H +#define ZENTBUTTON_H + +#include "zEnt.h" + +#include "xEntMotion.h" + +struct zEntButtonAsset +{ + U32 modelPressedInfoID; + U32 actMethod; + S32 initButtonState; + S32 isReset; + F32 resetDelay; + U32 buttonActFlags; +}; + +struct _zEntButton : zEnt +{ + zEntButtonAsset* basset; + xEntMotion motion; + U32 state; + F32 speed; + U32 oldState; + S32 oldMotState; + F32 counter; + xModelInstance* modelPressed; + F32 holdTimer; + U32 hold; + F32 topHeight; +}; + +void zEntButton_Init(void* ent, void* asset); +void zEntButton_Init(_zEntButton* ent, xEntAsset* asset); +void zEntButton_Move(_zEntButton* ent, xScene* sc, F32 dt, xEntFrame* frame); +void zEntButton_Setup(_zEntButton* ent, xScene* sc); +void zEntButton_Save(_zEntButton* ent, xSerial* s); +void zEntButton_Load(_zEntButton* ent, xSerial* s); +void zEntButton_Reset(_zEntButton* ent, xScene* sc); +void zEntButton_Update(_zEntButton* ent, xScene* sc, F32 dt); +void zEntButton_Render(_zEntButton* ent); +void zEntButton_SetReady(_zEntButton* ent); +void zEntButton_Press(_zEntButton* ent); +void zEntButton_Press(_zEntButton* ent, U32 mask); +void zEntButton_Hold(_zEntButton* ent, U32 mask); +void zEntButton_SceneUpdate(F32 dt); + +#endif diff --git a/src/SB/Game/zEntCruiseBubble.h b/src/SB/Game/zEntCruiseBubble.h new file mode 100644 index 0000000..19ded2c --- /dev/null +++ b/src/SB/Game/zEntCruiseBubble.h @@ -0,0 +1,655 @@ +#ifndef ZENTCRUISEBUBBLE_H + +#define ZENTCRUISEBUBBLE_H + +#include "xDebug.h" + +#include "zNPCHazard.h" +#include "zShrapnel.h" +#include + +#include "zRumble.h" + +// I have no idea where to put this. This is only used by +// cruise_bubble::tweak_group::register_tweaks() so far. +// If you are searching the project for 'auto_tweak' you are +// probably working on one of the bosses which also seem to use this. +// As of now I'm not sure if you should include this declaration, +// define your own or find a good place for shared use. +// NOTE (Square): pretty sure this is from xDebug +namespace auto_tweak +{ + template + void load_param(T1&, T2, T2, T2, xModelAssetParam*, U32, const char*); +}; + +namespace cruise_bubble +{ + namespace + { + enum state_enum + { + BEGIN_STATE_PLAYER, + STATE_PLAYER_HALT = 0x0, + STATE_PLAYER_AIM, + STATE_PLAYER_FIRE, + STATE_PLAYER_WAIT, + END_STATE_PLAYER, + BEGIN_STATE_MISSLE = 0x4, + BACKUP_STATE_MISSLE = 0x3, + STATE_MISSLE_APPEAR, + STATE_MISSLE_FLY, + STATE_MISSLE_EXPLODE, + END_STATE_MISSLE, + BEGIN_STATE_CAMERA = 0x7, + BACKUP_STATE_CAMERA = 0x6, + STATE_CAMERA_AIM, + STATE_CAMERA_SEIZE, + STATE_CAMERA_ATTACH, + STATE_CAMERA_SURVEY, + STATE_CAMERA_RESTORE, + END_STATE_CAMERA, + MAX_STATE = 0xc, + BACKUP_STATE_PLAYER = 0xffffffff, + STATE_INVALID = 0xffffffff + }; + + enum thread_enum + { + THREAD_PLAYER, + THREAD_MISSLE, + THREAD_CAMERA, + MAX_THREAD + }; + + struct state_type + { + state_enum type; + + state_type(state_enum type); + + virtual void start(); + virtual void stop(); + virtual state_enum update(F32 dt) = 0; + virtual void render(); + virtual void abort(); + }; + + struct state_player_fire : state_type + { + U8 wand_shown; + + state_player_fire(); + + void start(); + void stop(); + state_enum update(F32 dt); + void update_wand(F32 dt); + }; + + struct state_camera_aim : state_type + { + F32 phi; + F32 phi_vel; + F32 height; + F32 height_vel; + F32 dist; + F32 dist_vel; + xQuat facing; + xQuat target; + F32 control_delay; + F32 seize_delay; + + state_camera_aim(); + + void start(); + void stop(); + state_enum update(F32 dt); + + void apply_turn() const; + void turn(F32 dt); + void collide_inward(); + void apply_motion() const; + void stop(F32 dt); + void move(F32 dt); + }; + + struct state_player_halt : state_type + { + U8 first_update; + F32 time; + xVec3 last_motion; + + state_player_halt(); + + void start(); + void stop(); + state_enum update(F32 dt); + }; + + struct state_missle_explode : state_type + { + F32 hit_time; + + state_missle_explode(); + + void start(); + void stop(); + state_enum update(F32 dt); + + F32 get_radius() const; + void start_effects(); + void cb_droplet(zFrag* frag, zFragAsset* fa); + void perturb_direction(const xVec3&, F32, F32, F32, F32); + void get_next_quadrant(F32&, F32&, F32&, F32&); + void reset_quadrants(U32 size, F32 ring); + void apply_damage(F32 radius); + void apply_damage_hazards(F32); + U8 hazard_check(NPCHazard& haz, void* context); + }; + + struct state_camera_attach : state_type + { + F32 reticle_delay; + + state_camera_attach(); + + void start(); + void stop(); + state_enum update(F32 dt); + + void lock_targets(); + void lock_hazard_targets(); + static U8 hazard_check(NPCHazard& haz, void* context); + void get_view_bound(xBound& bound) const; + }; + + struct state_missle_fly : state_type + { + F32 life; + F32 vel; + xVec3 rot; + // Offset: 0x1c + xVec3 rot_vel; + // Offset: 0x28 + F32 engine_pitch; + xVec3 last_loc; + // Offset: 0x38 + F32 flash_time; + + state_missle_fly(); + + void start(); + void stop(); + state_enum update(F32 dt); + void abort(); + void update_flash(F32 dt); + void update_engine_sound(F32 dt); + + U8 collide_hazards(); + static bool hazard_check(NPCHazard& haz, void* context); + U8 collide(); + U8 hit_test(xVec3& hit_loc, xVec3& hit_norm, xVec3& hit_depen, xEnt*& hit_ent) const; + void update_move(F32 dt); + void update_turn(F32 dt); + void calculate_rotation(xVec2& d1, xVec2& v1, F32 dt, const xVec2& d0, const xVec2& v0, + const xVec2& a0, const xVec2& a1) const; + }; + + struct state_missle_appear : state_type + { + state_missle_appear(); + + void start(); + void stop(); + state_enum update(F32 dt); + void move(); + void update_effects(F32 dt); + }; + + struct state_camera_seize : state_type + { + F32 blend_time; + xVec3 start_loc; + xQuat start_dir; + xQuat end_dir; + xQuat cur_dir; + F32 last_s; + F32 fov; + F32 wipe_bubbles; + + state_camera_seize(); + + void start(); + void stop(); + state_enum update(F32 dt); + + void refresh_missle_alpha(F32); + void update_turn(F32); + void update_move(F32); + }; + + struct state_player_aim : state_type + { + F32 yaw; + F32 yaw_vel; + F32 turn_delay; + + state_player_aim(); + + void start(); + void stop(); + state_enum update(F32 dt); + + void update_animation(F32 dt); + void apply_yaw(); + void face_camera(F32 dt); + }; + + struct state_camera_restore : state_type + { + F32 control_delay; + + state_camera_restore(); + + void start(); + void stop(); + state_enum update(F32 dt); + }; + + struct state_camera_survey : state_type + { + F32 time; + xVec2 start_sp; + F32 path_distance[127]; + + state_camera_survey(); + + void start(); + void stop(); + state_enum update(F32 dt); + + void move(); + void eval_missle_path(F32 dist, xVec3& loc, F32& roll) const; + void lerp(F32& x, F32 t, F32 a, F32 b) const; + void lerp(xVec3& v, F32 t, const xVec3& a, const xVec3& b) const; + S32 find_nearest(F32) const; + void init_path(); + bool control_jerked() const; + }; + + struct state_player_wait : state_type + { + state_player_wait(); + + void start(); + state_enum update(F32 dt); + }; + + // Size: 0x1b8 + struct tweak_group + { + F32 aim_delay; + // Size: 0x10, Offset: 0x4 + struct _class_2 + { + F32 halt_time; // 0x4 + struct _class_4 + { + F32 turn_speed; // 0x8 + F32 anim_delta; // 0xC + } aim; + struct _class_11 + { + F32 delay_wand; // 0x10 + } fire; + } player; + + // Size: 0x5c, Offset: 0x14 + struct _class_22 + { + F32 life; + F32 hit_dist; // 0x18 + F32 crash_angle; // 0x1c + F32 collide_twist; // 0x20 + S32 hit_tests; // 0x24 + struct _class_27 + { + F32 delay_show; // 0x28 + F32 delay_fly; // 0x2c + xVec3 offset; // 0x30 + } appear; + struct _class_32 + { + F32 accel; // 0x3c + F32 max_vel; // 0x40 + F32 engine_pitch_max; // 0x44 + F32 engine_pitch_sensitivity; // 0x48 + // Offset: 0x4c + F32 flash_interval; + struct _class_38 + { + F32 xdelta; // 0x50 + F32 ydelta; // 0x54 + F32 xdecay; // 0x58 + F32 ydecay; // 0x5c + F32 ybound; // 0x60 + F32 roll_frac; // 0x64 + } turn; + } fly; + struct _class_49 + { + F32 hit_radius; // 0x68 + F32 hit_duration; // 0x6c + } explode; + } missle; + + // Size: 0x5c, Offset: 0x70 + struct _class_10 + { + struct _class_15 + { + F32 dist; + F32 height; // 0x74 + F32 pitch; // 0x78 + F32 accel; // 0x7c + F32 max_vel; // 0x80 + F32 stick_decel; // 0x84 + F32 stick_accel; // 0x88 + F32 stick_max_vel; // 0x8c + F32 turn_speed; // 0x90 + } aim; + struct _class_24 + { + F32 delay; // 0x94 + F32 blend_time; // 0x98 + F32 fade_dist; // 0x9c + F32 hide_dist; // 0xa0 + F32 fov; // 0xa4 + } seize; + struct _class_30 + { + F32 duration; // 0xa8 + F32 min_duration; // 0xac + F32 min_dist; // 0xb0 + F32 cut_dist; // 0xb4 + F32 drift_dist; // 0xb8 + F32 drift_softness; // 0xbc + F32 jerk_offset; // 0xc0 + F32 jerk_deflect; // 0xc4 + } survey; + struct _class_39 + { + F32 control_delay; // 0xc8 + } restore; + } camera; + + // Size: 0x18, Offset: 0xcc + struct _class_48 + { + F32 env_alpha; + F32 env_coeff; // 0xd0 + U32 env_texture; // 0xd4 + F32 fresnel_alpha; // 0xd8 + F32 fresnel_coeff; // 0xdc + U32 fresnel_texture; // 0xe0 + } material; + + // Size: 0x14, Offset: 0xe4 + struct _class_9 + { + // Offset: 0xe4 + F32 dist_min; + F32 dist_max; + // Offset: 0xec + F32 ang_show; + F32 ang_hide; + F32 delay_retarget; + } reticle; + + // Size: 0x10, Offset: 0xf8 + struct _class_20 + { + // Offset: 0xf8 + F32 sample_rate; + F32 bubble_rate; // 0xfc + F32 bubble_emit_radius; // 0x100 + F32 wake_emit_radius; // 0x104 + } trail; + + // Size: 0x10, Offset: 0x108 + struct _class_29 + { + U32 emit; // 0x108 + F32 radius; // 0x10c + F32 vel; // 0x110 + F32 rand_vel; // 0x11 + } blast; + + // Size: 0x24, Offset: 0x118 + struct _class_35 + { + F32 dist_min; + F32 dist_max; + U32 emit_min; + U32 emit_max; + F32 vel_min; + F32 vel_max; + F32 vel_perturb; + F32 vel_angle; + F32 rot_vel_max; + } droplet; + + // Size: 0x44, Offset: 0x13c + struct _class_43 + { + F32 glow_size; + // Offset: 0x140 + F32 time_fade; + F32 time_glow; + struct _class_46 + { + F32 size; + F32 du; + F32 dv; + } swirl; + struct _class_5 + { + F32 size; + F32 du; + F32 dv; + } wind; + struct _class_12 + { + F32 size; + } reticle; + struct _class_18 + { + F32 size; + } target; + struct _class_23 + { + // Offset: 0x168 + S32 font; + F32 font_width; + F32 font_height; + F32 x; + F32 y; + // Offset: 0x17c + F32 glow_size; + } timer; + } hud; + + // Size: 0xc, Offset: 0x180 + struct _class_34 + { + F32 freq; + F32 decay; + F32 min_freq; + } dialog; + + void* context; + tweak_callback cb_missle_model; + + void load(xModelAssetParam* params, U32 size); + + void register_tweaks(bool init, xModelAssetParam* ap, U32 apsize, const char*); + }; + + struct uv_animated_model + { + RpAtomic* model; + RwTexCoords* uv; + S32 uvsize; + xVec2 offset; + xVec2 offset_vel; + + bool init(RpAtomic*); + bool clone_uv(RwTexCoords*&, S32&, RpAtomic*) const; + bool get_uv(RwTexCoords*&, S32&, RpAtomic*) const; + void update(F32 dt); + void refresh(); + }; + + struct sound_config + { + // offset 0x0 + char* name; + // offset 0x4 + F32 volume; + // offset 0x8 + F32 radius_inner; + // offset 0xc + F32 radius_outer; + // offset 0x10 + U8 streamed; // might be bool, not sure + U8 looping; // might be bool, not sure + // offset 0x14 + _tagSDRumbleType rumble; + // offset 0x18 + S32 first; + // offset 0x1c + S32 last; + // offset 0x20 + U32 id; + // offset 0x24 + U32 handle; + }; + + struct hud_gizmo + { + S32 flags; + basic_rect bound; + F32 alpha; + // Offset: 0x18 + F32 alpha_vel; + F32 glow; + F32 glow_vel; + F32 opacity; + const xVec3* target; + xModelInstance* model; + }; + + struct missle_record_data + { + xVec3 loc; + F32 roll; + + missle_record_data(const xVec3& loc, F32 roll); + }; + } // namespace + + void init_sound(); + void stop_sound(S32 which, U32 handle); + U32 play_sound(S32 which, F32 volFactor); + U32 play_sound(S32 which, F32 volFactor, const xVec3* pos); + void set_pitch(S32 which, F32 pitch, U32 handle); + void show_wand(); + void hide_wand(); + void show_missle(); + void hide_missle(); + void capture_camera(); + void release_camera(); + bool camera_taken(); + bool camera_leave(); + void start_damaging(); + // void damage_entity(xEnt& ent, const xVec3& loc, const xVec3& dir, const xVec3& hit_norm, + // F32 radius, bool explosive); + U8 can_damage(xEnt* ent); + U8 was_damaged(xEnt* ent); + void notify_triggers(xScene& s, const xSphere& o, const xVec3& dir); + void exit_triggers(xScene& s); + void signal_event(U32 toEvent); + void refresh_trail(xMat4x3& mat, xQuat& quat); + void start_trail(); + void stop_trail(); + void set_state(thread_enum thread, state_enum state); + bool check_launch(); + void kill(bool reset_camera, bool abortive); + void distort_screen(F32); + void update_player(xScene& s, F32 dt); + xVec3& get_player_loc(); + void render_player(); + void refresh_controls(); + void update_state(xScene* s, F32 dt); + void render_state(); + RpAtomic* custom_bubble_render(RpAtomic* atomic); + void init_states(); + void init_missle_model(); + void reset_wake_ribbons(); + void init_wake_ribbons(); + void reset_explode_decal(); + void init_explode_decal(); + void init_shrapnel(); + void add_trail_sample(const xVec3& loc0, const xVec3& dir0, const xVec3& loc1, + const xVec3& dir1, F32 dt); + void update_trail(F32 dt); + void refresh_missle_model(); + void update_missle(xScene& s, F32 dt); + void render_missle(); + xModelInstance* load_model(U32); + void render_model_2d(xModelInstance* m, const basic_rect& bound, F32 alpha); + void render_glow(xModelInstance* m, const basic_rect& r, F32 glow, F32 alpha); + void init_hud(); + void show_gizmo(hud_gizmo& gizmo, const basic_rect& rect, xModelInstance* m); + void update_gizmo(hud_gizmo& gizmo, F32 dt); + void flash_hud(); + void render_timer(F32 alpha, F32 glow); + void lerp(iColor_tag& c, F32 t, iColor_tag a, iColor_tag b); + void lerp(U8& x, F32 t, U8 a, U8 b); + void update_hud(F32 dt); + void render_hud(); + void show_hud(); + void hide_hud(); + xVec3 world_to_screen(const xVec3& loc); + S32 find_locked_target(const xVec3* target); + void lock_target(S32 index, const xVec3* target, F32 opacity); + void check_lock_target(const xVec3* target); + U32 check_anim_aim(xAnimTransition*, xAnimSingle*); + void load_cheat_tweak(); + void load_settings(); + void init(); + void init_debug(); + void reset(); + void launch(); + bool update(xScene* s, F32 dt); + bool render(); + void render_debug(); + void render_screen(); + void insert_player_animations(xAnimTable& table); + bool active(); + F32 exploding(); + void get_explode_sphere(xVec3& center, F32& radius); + xEnt** get_explode_hits(S32& size); + void add_life(F32, F32); + void set_life(F32 life); + void reset_life(); + // xBase* param names are guessed as they go unused and wont appear in dwarf + bool event_handler(xBase* from, U32 event, const F32* fparam, xBase* to); + xMat4x3* get_player_mat(); + xMat4x3* get_missle_mat(); +} // namespace cruise_bubble + +xAnimTable* anim_table(); + +#endif diff --git a/src/SB/Game/zEntDestructObj.h b/src/SB/Game/zEntDestructObj.h new file mode 100644 index 0000000..1b5e014 --- /dev/null +++ b/src/SB/Game/zEntDestructObj.h @@ -0,0 +1,78 @@ +#ifndef ZENTDESTRUCTOBJ_H +#define ZENTDESTRUCTOBJ_H + +#include "zEnt.h" +#include "xSFX.h" +#include "zParEmitter.h" +#include "zGlobals.h" +#include "zRumble.h" +#include "xVec3.h" +#include "xString.h" +#include "xstransvc.h" +#include "zShrapnel.h" +#include "zCollGeom.h" +#include "iCollide.h" + +#define DOBJ_STATE_INIT 0 +#define DOBJ_STATE_RESET 1 +#define DOBJ_STATE_DESTROYED 2 + +struct zEntDestructObjAsset +{ + F32 animSpeed; + U32 initAnimState; + U32 health; + U32 spawnItemID; + U32 dflags; // 0x10 + U8 collType; + U8 fxType; + U8 pad[2]; + F32 blast_radius; + F32 blast_strength; + U32 shrapnelID_destroy; // 0x20 + U32 shrapnelID_hit; // 0x24 + U32 sfx_destroy; // 0x28 + U32 sfx_hit; // 0x2C + U32 hitModelId; // 0x30 + U32 destroyModelId; // 0x34 +}; + +struct zEntDestructObj : zEnt +{ + zEntDestructObjAsset* dasset; // Offset 0xD4 + U32 state; + U32 healthCnt; + F32 fx_timer; // Offset 0xE0 + zParEmitter* fx_emitter; + F32 respawn_timer; + U32 throw_target; + zShrapnelAsset* shrapnel_destroy; // Offset 0xF0 + zShrapnelAsset* shrapnel_hit; + xModelInstance* base_model; + xModelInstance* hit_model; + xModelInstance* destroy_model; // Offset 0x100 + void (*destroy_notify)(zEntDestructObj&, void*); + void* notify_context; + xSFXAsset* sfx_destroy; // 0x10C + xSFXAsset* sfx_hit; // 0x110 +}; + +void zEntDestructObj_FindFX(); +void zEntDestructObj_Init(void* ent, void* asset); +void zEntDestructObj_Init(zEntDestructObj* ent, xEntAsset* asset); + +// TODO: update unk with callback signatures from zEnt +void zEntDestructObj_Move(zEntDestructObj* ent, xScene* scene, F32 unk, xEntFrame* frame); +void zEntDestructObj_Update(zEntDestructObj* ent, xScene* scene, F32 unk); +void zEntDestructObj_Hit(zEntDestructObj* ent, U32 mask); +U32 zEntDestructObj_GetHit(zEntDestructObj* ent, U32 mask); +void zEntDestructObj_Save(zEntDestructObj* ent, xSerial* s); +void zEntDestructObj_Load(zEntDestructObj* ent, xSerial* s); +void zEntDestructObj_Setup(zEntDestructObj* ent); +void zEntDestructObj_Reset(zEntDestructObj* ent, xScene* scene); +U32 zEntDestructObj_isDestroyed(zEntDestructObj* ent); +void zEntDestructObj_DestroyFX(zEntDestructObj* ent); +S32 zEntDestructObjEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, + xBase* baseUnk3); + +#endif diff --git a/src/SB/Game/zEntHangable.h b/src/SB/Game/zEntHangable.h new file mode 100644 index 0000000..5335607 --- /dev/null +++ b/src/SB/Game/zEntHangable.h @@ -0,0 +1,42 @@ +#ifndef ZENTHANGABLE_H +#define ZENTHANGABLE_H + +#include "zEnt.h" + +struct xEntHangableAsset +{ + U32 flags; + F32 pivotOffset; + F32 leverArm; + F32 gravity; + F32 accel; + F32 decay; + F32 grabDelay; + F32 stopDecel; +}; + +struct zEntHangable : zEnt +{ + xEntHangableAsset* hangInfo; + xVec3 pivot; + xVec3 endpos; + xVec3 vel; + xVec3 swingplane; + F32 grabTimer; + F32 spin; + U32 state; + zEnt* shaggy; + S32 enabled; + zEnt* follow; + S32 moving; + F32 candle_timer; + S32 candle_state; +}; + +void zEntHangable_SetupFX(); +void zEntHangable_Init(void* ent, void* asset); +void zEntHangable_Save(zEntHangable* ent, xSerial* s); +void zEntHangable_Load(zEntHangable* ent, xSerial* s); +void zEntHangable_Reset(zEntHangable* ent); + +#endif diff --git a/src/SB/Game/zEntPickup.h b/src/SB/Game/zEntPickup.h new file mode 100644 index 0000000..639a5c2 --- /dev/null +++ b/src/SB/Game/zEntPickup.h @@ -0,0 +1,89 @@ +#ifndef ZENTPICKUP_H +#define ZENTPICKUP_H + +#include "zEnt.h" +#include "zPickupTable.h" +#include "zParEmitter.h" + +#include "xEntDrive.h" +#include "xPar.h" +#include "xShadowSimple.h" +#include "iColor.h" + +struct zEntPickup : zEnt +{ + xShadowSimpleCache simpShadow_embedded; + U32 state; // 0x16C + zAssetPickup* p; + void* anim; + F32 animTime; + F32 timer; // 0x17C + F32 shake_timer; + xVec3 shake_pos; + S32 snackGateInfoDisplayed; + F32 fx_timer; + xPar* fx_par; + zParEmitter* fx_emit; + F32 fx_scale; + xVec3 grab_pos; + U32 flyflags; + S32 flg_opts; + xVec3 vel; + xVec3 droppos; + xBase* followTarget; + xVec3 followOffset; + xBase* dropParent; + xEnt* useThisEntPos; + xEntDrive drv; + U16 pickupFlags; // 0x264 +}; + +struct xEntPickupAsset +{ + U32 pickupHash; + U16 pickupFlags; + U16 pickupValue; +}; + +struct zPickupAuraInfo +{ + F32 size; + F32 yoffset; + iColor_tag color; +}; + +extern zParEmitter* gEmitShinySparkles; +extern U32 gEnableRewardsQueue; +extern zPickupAuraInfo zPickupAuraTable[]; + +void zEntPickup_Startup(); +void zEntPickupInit(void* ent, void* asset); +void zEntPickupInit(zEntPickup* ent, xEntAsset* asset); +void zEntPickup_Setup(zEntPickup* p); +void zEntPickup_Setup(); +S32 zEntPickupEventCB(xBase*, xBase* to, U32 toEvent, const F32* toParam, + xBase* toParamWidget); +void zEntPickup_FlyToInterface(zEntPickup*, F32); +void zEntPickup_CheckAllPickupsAgainstPlayer(xScene* sc, F32 dt); +void zEntPickup_DoPickup(zEntPickup* ent); +void zEntPickup_GivePickup(zEntPickup* ent); +void zEntPickup_GiveAllRewardsNow(); +void zEntPickup_Update(zEntPickup* ent, xScene* sc, F32 dt); +void zEntPickup_Reset(zEntPickup* ent); +void zEntPickup_Save(zEntPickup* ent, xSerial* s); +void zEntPickup_Load(zEntPickup* ent, xSerial* s); +void zEntPickup_FlushGrabbed(); +void zEntPickup_MakeDroppable(zEntPickup* ent, xVec3* pos, xBase* dropParent); +void zEntPickup_Drop(zEntPickup* ent); +void zEntPickup_Render(zEntPickup* plist, U32 pcount); +void zEntPickup_RenderOne(xEnt* ent); +void zEntPickup_RenderList(zEntPickup* plist, U32 pcount); +void zEntPickup_UpdateFlyToInterface(zEntPickup* ent, U32 pcount, F32 dt); +void zEntPickup_SceneEnter(); +void zEntPickup_SceneReset(); +void zEntPickup_SceneUpdate(F32 dt); +void zEntPickup_SpawnNRewards(U32* pickups, U32 num, xVec3* ppos); +void zEntPickup_SpawnNRewards(U32* pickups, U32 num, xVec3 pos); +void zEntPickup_RewardPostSetup(); + +#endif diff --git a/src/SB/Game/zEntPlayer.h b/src/SB/Game/zEntPlayer.h new file mode 100644 index 0000000..ae42d00 --- /dev/null +++ b/src/SB/Game/zEntPlayer.h @@ -0,0 +1,439 @@ +#ifndef ZENTPLAYER_H +#define ZENTPLAYER_H + +#include "xMath3.h" +#include "xEnt.h" +#include "xAnim.h" +#include "zEnt.h" +#include "zLasso.h" + +enum zControlOwner +{ + CONTROL_OWNER_GLOBAL = 0x1, + CONTROL_OWNER_EVENT, + CONTROL_OWNER_OOB = 0x4, + CONTROL_OWNER_BOSS = 0x8, + CONTROL_OWNER_TALK_BOX = 0x10, + CONTROL_OWNER_TAXI = 0x20, + CONTROL_OWNER_BUS_STOP = 0x40, + CONTROL_OWNER_TELEPORT_BOX = 0x80, + CONTROL_OWNER_CRUISE_BUBBLE = 0x100, + CONTROL_OWNER_FLY_CAM = 0x200, + CONTROL_OWNER_FROZEN = 0x400, + CONTROL_OWNER_TURRET = 0x800, + CONTROL_OWNER_REWARDANIM = 0x1000, + CONTROL_OWNER_BUNGEE = 0x2000, + CONTROL_OWNER_SPRINGBOARD = 0x4000, + CONTROL_OWNER_CUTSCENE = 0x8000 +}; + +enum _tagePlayerSnd +{ + ePlayerSnd_Invalid, + ePlayerSnd_Land, + ePlayerSnd_Jump, + ePlayerSnd_DoubleJump, + ePlayerSnd_BowlWindup, + ePlayerSnd_BowlRelease, + ePlayerSnd_BubbleBashStart, + ePlayerSnd_BubbleBashHit1, + ePlayerSnd_BubbleBashHitStart = 0x7, + ePlayerSnd_BubbleBashHit2, + ePlayerSnd_BubbleBashHitEnd = 0x8, + ePlayerSnd_BubbleWand, + ePlayerSnd_CruiseStart, + ePlayerSnd_CruiseNavigate, + ePlayerSnd_CruiseHit, + ePlayerSnd_BounceStrike, + ePlayerSnd_BoulderStart, + ePlayerSnd_BoulderRoll, + ePlayerSnd_BoulderEnd, + ePlayerSnd_BellyMelee, + ePlayerSnd_BellySmash, + ePlayerSnd_Lift1, + ePlayerSnd_Throw, + ePlayerSnd_Chop, + ePlayerSnd_Kick, + ePlayerSnd_Heli, + ePlayerSnd_LassoThrow, + ePlayerSnd_LassoYank, + ePlayerSnd_LassoStretch, + ePlayerSnd_Ouch1, + ePlayerSnd_OuchStart = 0x1b, + ePlayerSnd_Ouch2, + ePlayerSnd_Ouch3, + ePlayerSnd_Ouch4, + ePlayerSnd_OuchEnd = 0x1e, + ePlayerSnd_Death, + ePlayerSnd_FruitCrackle, + ePlayerSnd_CheckPoint, + ePlayerSnd_PickupSpatula, + ePlayerSnd_PickupUnderwear, + ePlayerSnd_Bus, + ePlayerSnd_Taxi, + ePlayerSnd_SlideLoop, + ePlayerSnd_BeginBungee, + ePlayerSnd_BungeeWind = 0x27, + ePlayerSnd_BungeeAttach, + ePlayerSnd_BungeeRelease, + ePlayerSnd_EndBungee = 0x29, + ePlayerSnd_PickupSpatulaComment, + ePlayerSnd_BungeeDive1, + ePlayerSnd_BungeeDive2, + ePlayerSnd_Sneak, + ePlayerSnd_SlipLoop, + ePlayerSnd_Total +}; + +enum _tagePlayerStreamSnd +{ + ePlayerStreamSnd_Invalid, + ePlayerStreamSnd_PickupSock1, + ePlayerStreamSnd_PickupSock2, + ePlayerStreamSnd_PickupSock3, + ePlayerStreamSnd_UnderwearComment1, + ePlayerStreamSnd_UnderwearComment2, + ePlayerStreamSnd_UnderwearComment3, + ePlayerStreamSnd_EnterScene1, + ePlayerStreamSnd_EnterScene2, + ePlayerStreamSnd_EnterScene3, + ePlayerStreamSnd_EnterScene4, + ePlayerStreamSnd_EnterScene5, + ePlayerStreamSnd_EnterScene6, + ePlayerStreamSnd_EnterScene7, + ePlayerStreamSnd_SpatulaComment1, + ePlayerStreamSnd_ShinyComment1, + ePlayerStreamSnd_ShinyComment2, + ePlayerStreamSnd_ShinyComment3, + ePlayerStreamSnd_ShinyComment4, + ePlayerStreamSnd_ShinyComment5, + ePlayerStreamSnd_SpongeBallComment1, + ePlayerStreamSnd_SpongeBallComment2, + ePlayerStreamSnd_SpongeBallComment3, + ePlayerStreamSnd_CruiseComment1, // 0x17 -> "Say hello to my little bubble friend." + ePlayerStreamSnd_CruiseComment2, // 0x18 -> "SpongeBob to mission control, the launch is a go." + ePlayerStreamSnd_CruiseComment3, // 0x19 -> "Bubble Power!" + ePlayerStreamSnd_BowlComment1, + ePlayerStreamSnd_BowlComment2, + ePlayerStreamSnd_BowlComment3, + ePlayerStreamSnd_BowlComment4, + ePlayerStreamSnd_BowlComment5, + ePlayerStreamSnd_PushButton1, + ePlayerStreamSnd_PushButton2, + ePlayerStreamSnd_PushButton3, + ePlayerStreamSnd_BellySmashComment1, + ePlayerStreamSnd_BellySmashComment2, + ePlayerStreamSnd_BellySmashComment3, + ePlayerStreamSnd_ChopComment1, + ePlayerStreamSnd_ChopComment2, + ePlayerStreamSnd_ChopComment3, + ePlayerStreamSnd_KickComment1, + ePlayerStreamSnd_KickComment2, + ePlayerStreamSnd_KickComment3, + ePlayerStreamSnd_RopingComment1, + ePlayerStreamSnd_RopingComment2, + ePlayerStreamSnd_RopingComment3, + ePlayerStreamSnd_HeliComment1, + ePlayerStreamSnd_HeliComment2, + ePlayerStreamSnd_HeliComment3, + ePlayerStreamSnd_DestroyTiki1, + ePlayerStreamSnd_DestroyTiki2, + ePlayerStreamSnd_DestroyTiki3, + ePlayerStreamSnd_DestroyRobot1, + ePlayerStreamSnd_DestroyRobot2, + ePlayerStreamSnd_DestroyRobot3, + ePlayerStreamSnd_SeeWoodTiki, + ePlayerStreamSnd_SeeLoveyTiki, + ePlayerStreamSnd_SeeShhhTiki, + ePlayerStreamSnd_SeeThunderTiki, + ePlayerStreamSnd_SeeStoneTiki, + ePlayerStreamSnd_SeeFodder, + ePlayerStreamSnd_SeeHammer, + ePlayerStreamSnd_SeeTarTar, + ePlayerStreamSnd_SeeGLove, + ePlayerStreamSnd_SeeMonsoon, + ePlayerStreamSnd_SeeSleepyTime, + ePlayerStreamSnd_SeeArf, + ePlayerStreamSnd_SeeTubelets, + ePlayerStreamSnd_SeeSlick, + ePlayerStreamSnd_SeeKingJellyfish, + ePlayerStreamSnd_SeePrawn, + ePlayerStreamSnd_SeeDutchman, + ePlayerStreamSnd_SeeSandyBoss, + ePlayerStreamSnd_SeePatrickBoss1, + ePlayerStreamSnd_SeePatrickBoss2, + ePlayerStreamSnd_SeeSpongeBobBoss, + ePlayerStreamSnd_SeeRobotPlankton, + ePlayerStreamSnd_PickupSpecialGeneric1, + ePlayerStreamSnd_PickupSpecialGeneric2, + ePlayerStreamSnd_GoldenUnderwear4, + ePlayerStreamSnd_GoldenUnderwear5, + ePlayerStreamSnd_GoldenUnderwear6, + ePlayerStreamSnd_Combo1, + ePlayerStreamSnd_Combo2, + ePlayerStreamSnd_Combo3, + ePlayerStreamSnd_Combo4, + ePlayerStreamSnd_Combo5, + ePlayerStreamSnd_BigCombo1, + ePlayerStreamSnd_BigCombo2, + ePlayerStreamSnd_BigCombo3, + ePlayerStreamSnd_BigCombo4, + ePlayerStreamSnd_BigCombo5, + ePlayerStreamSnd_Lift1, + ePlayerStreamSnd_Exclaim1, + ePlayerStreamSnd_Exclaim2, + ePlayerStreamSnd_Exclaim3, + ePlayerStreamSnd_Exclaim4, + ePlayerStreamSnd_BeginBungee, + ePlayerStreamSnd_BungeeAttachComment = 0x61, + ePlayerStreamSnd_BungeeBeginDive, + ePlayerStreamSnd_BungeeDive1 = 0x62, + ePlayerStreamSnd_BungeeDive2, + ePlayerStreamSnd_BungeeEndDive = 0x63, + ePlayerStreamSnd_BungeeBeginDeath, + ePlayerStreamSnd_BungeeDeath1 = 0x64, + ePlayerStreamSnd_BungeeDeath2, + ePlayerStreamSnd_BungeeDeath3, + ePlayerStreamSnd_BungeeDeath4, + ePlayerStreamSnd_BungeeDeath5, + ePlayerStreamSnd_BungeeDeath6, + ePlayerStreamSnd_BungeeDeath7, + ePlayerStreamSnd_BungeeDeath8, + ePlayerStreamSnd_BungeeDeath9, + ePlayerStreamSnd_BungeeDeath10, + ePlayerStreamSnd_BungeeDeath11, + ePlayerStreamSnd_BungeeDeath12, + ePlayerStreamSnd_BungeeDeath13, + ePlayerStreamSnd_BungeeDeath14, + ePlayerStreamSnd_BungeeDeath15, + ePlayerStreamSnd_BungeeDeath16, + ePlayerStreamSnd_BungeeDeath17, + ePlayerStreamSnd_BungeeDeath18, + ePlayerStreamSnd_BungeeEndDeath = 0x75, + ePlayerStreamSnd_EndBungee = 0x75, + ePlayerStreamSnd_Total +}; + +struct zDelayedStreamSound +{ + _tagePlayerStreamSnd start; + _tagePlayerStreamSnd end; + F32 delay; +}; + +struct zPlayerSndTimer +{ + F32 timer; + F32 time; +}; + +// TODO: Why are there two of these enums with the same effect, should there be? +enum _zPlayerType +{ + ePlayer_SB, + ePlayer_Patrick, + ePlayer_Sandy, + ePlayer_MAXTYPES +}; + +enum _CurrentPlayer +{ + eCurrentPlayerSpongeBob, + eCurrentPlayerPatrick, + eCurrentPlayerSandy, + eCurrentPlayerCount +}; + +enum _zPlayerWallJumpState +{ + k_WALLJUMP_NOT, + k_WALLJUMP_LAUNCH, + k_WALLJUMP_FLIGHT, + k_WALLJUMP_LAND +}; + +struct zJumpParam +{ + F32 PeakHeight; + F32 TimeGravChange; + F32 TimeHold; + F32 ImpulseVel; +}; + +struct zLedgeGrabParams +{ + F32 animGrab; + F32 zdist; + xVec3 tranTable[60]; + S32 tranCount; + xEnt* optr; + xMat4x3 omat; + F32 y0det; + F32 dydet; + F32 r0det; + F32 drdet; + F32 thdet; + F32 rtime; + F32 ttime; + F32 tmr; + xVec3 spos; + xVec3 epos; + xVec3 tpos; + S32 nrays; + S32 rrand; + F32 startrot; + F32 endrot; +}; + +// Size: 0x448 +struct zPlayerSettings +{ + _zPlayerType pcType; + F32 MoveSpeed[6]; + F32 AnimSneak[3]; + F32 AnimWalk[3]; + F32 AnimRun[3]; + F32 JumpGravity; + F32 GravSmooth; + F32 FloatSpeed; + F32 ButtsmashSpeed; + zJumpParam Jump; + zJumpParam Bounce; + zJumpParam Spring; + zJumpParam Wall; + zJumpParam Double; + zJumpParam SlideDouble; + zJumpParam SlideJump; + F32 WallJumpVelocity; + zLedgeGrabParams ledge; + F32 spin_damp_xz; + F32 spin_damp_y; + U8 talk_anims; + U8 talk_filter_size; + U8 talk_filter[4]; +}; + +struct zPlayerCarryInfo +{ + xEnt* grabbed; + U32 grabbedModelID; + xMat4x3 spin; + xEnt* throwTarget; + xEnt* flyingToTarget; + F32 minDist; + F32 maxDist; + F32 minHeight; + F32 maxHeight; + F32 maxCosAngle; + F32 throwMinDist; + F32 throwMaxDist; + F32 throwMinHeight; + F32 throwMaxHeight; + F32 throwMaxStack; + F32 throwMaxCosAngle; + F32 throwTargetRotRate; + F32 targetRot; + U32 grabTarget; + xVec3 grabOffset; + F32 grabLerpMin; + F32 grabLerpMax; + F32 grabLerpLast; + U32 grabYclear; + F32 throwGravity; + F32 throwHeight; + F32 throwDistance; + F32 fruitFloorDecayMin; + F32 fruitFloorDecayMax; + F32 fruitFloorBounce; + F32 fruitFloorFriction; + F32 fruitCeilingBounce; + F32 fruitWallBounce; + F32 fruitLifetime; + xEnt* patLauncher; +}; + +struct zPlayerLassoInfo +{ + xEnt* target; // 0x1880 in globals + F32 dist; + U8 destroy; + U8 targetGuide; + F32 lassoRot; + xEnt* swingTarget; // 0x1890 + xEnt* releasedSwing; + F32 copterTime; + S32 canCopter; + zLasso lasso; + xAnimState* zeroAnim; +}; + +#define SHINY_MAX 99999 + +extern _CurrentPlayer gCurrentPlayer; +extern S32 gWaitingToAutoSave; + +void zEntPlayer_Load(xEnt*, xSerial*); + +S32 zEntPlayer_Damage(xBase* src, U32 damage); +S32 zEntPlayer_Damage(xBase* src, U32 damage, const xVec3* knockback); + +xAnimTable* zSandy_AnimTable(); +xAnimTable* zPatrick_AnimTable(); +xAnimTable* zEntPlayer_AnimTable(); +xAnimTable* zSpongeBobTongue_AnimTable(); + +void zEntPlayerExit(xEnt*); +void zEntPlayerPreReset(); +void zEntPlayerReset(xEnt* ent); +void zEntPlayer_LoadSounds(); +void zEntPlayer_UnloadSounds(); +void zEntPlayer_ShadowModelEnable(); +void zEntPlayer_ShadowModelDisable(); + +void zEntPlayerJumpStart(class xEnt* ent, class zJumpParam* jump); +S32 zEntPlayer_IsSneaking(); + +void zEntPlayer_setBoulderMode(U32 mode); +void zEntPlayer_GiveHealth(S32); +void zEntPlayer_GiveSpatula(S32); +void zEntPlayer_GivePatsSocksCurrentLevel(S32 quantity); + +void zEntPlayer_LoadCheckPoint(); + +void zEntPlayer_MinimalRender(zEnt* ent); +U8 zEntPlayer_MinimalUpdate(xEnt* ent, xScene* sc, F32 dt, xVec3& drive_motion); + +S32 zEntPlayer_MoveInfo(); + +void zEntPlayer_SNDPlay(_tagePlayerSnd player_snd, F32 delay); +void zEntPlayer_SNDPlayRandom(_tagePlayerSnd player_snd_start, _tagePlayerSnd player_snd_end, + F32 delay); +void zEntPlayer_SNDPlayStream(_tagePlayerStreamSnd player_snd); +void zEntPlayer_SNDPlayStream(_tagePlayerStreamSnd player_snd, U32 flags); +// Only plays sound if player's spatula count is between lower and upper +void zEntPlayer_SNDPlayStream(U32 lower, U32 upper, _tagePlayerStreamSnd player_snd, U32 flags); + +// Only plays sound if player's spatula count is between lower and upper +void zEntPlayer_SNDPlayStreamRandom(U32 lower, U32 upper, _tagePlayerStreamSnd player_snd_start, + _tagePlayerStreamSnd player_snd_end, F32 delay); +void zEntPlayer_SNDPlayStreamRandom(_tagePlayerStreamSnd player_snd_start, + _tagePlayerStreamSnd player_snd_end, F32 delay); + +void zEntPlayer_SNDSetVol(_tagePlayerSnd player_snd, F32 new_vol); +void zEntPlayer_SNDSetPitch(_tagePlayerSnd player_snd, F32 new_pitch); +void zEntPlayer_SNDStop(_tagePlayerSnd player_snd); + +void zEntPlayerSpeakStop(); + +void zEntPlayerControlOff(zControlOwner owner); +void zEntPlayerControlOn(zControlOwner owner); + +void zEntPlayer_StoreCheckPoint(xVec3* pos, F32 rot, U32 initCamID); +S32 load_talk_filter(U8* filter, xModelAssetParam* params, U32 params_size, S32 max_size); + +S32 zEntPlayer_DamageNPCKnockBack(xBase* src, U32 damage, xVec3* npcPos); + +S32 zEntPlayer_DamageNPCKnockBack(xBase* src, U32 damage, xVec3* npcPos); +void zEntPlayer_PredictPos(xVec3* pos, F32 timeIntoFuture, F32 leadFactor, S32 useTurn); + +#endif diff --git a/src/SB/Game/zEntPlayerAnimationTables.h b/src/SB/Game/zEntPlayerAnimationTables.h new file mode 100644 index 0000000..efea2b7 --- /dev/null +++ b/src/SB/Game/zEntPlayerAnimationTables.h @@ -0,0 +1,4 @@ +#include "xAnim.h" + +xAnimTable* zEntPlayer_BoulderVehicleAnimTable(); +xAnimTable* zEntPlayer_TreeDomeSBAnimTable(); diff --git a/src/SB/Game/zEntPlayerBungeeState.h b/src/SB/Game/zEntPlayerBungeeState.h new file mode 100644 index 0000000..ac1dfbb --- /dev/null +++ b/src/SB/Game/zEntPlayerBungeeState.h @@ -0,0 +1,74 @@ +#ifndef ZENTPLAYERBUNGEESTATE_H +#define ZENTPLAYERBUNGEESTATE_H + +#include "xDynAsset.h" +#include "xEnt.h" + +namespace bungee_state +{ + struct hook_asset : xDynAsset + { + U32 entity; + xVec3 center; + struct + { + F32 dist; + F32 travel_time; + } attach; + struct + { + F32 dist; + F32 free_fall_time; + F32 accel; + } detach; + struct + { + F32 unused1; + F32 unused2; + } turn; + struct + { + F32 frequency; + F32 gravity; + F32 dive; + F32 min_dist; + F32 max_dist; + F32 damp; + } vertical; + struct + { + F32 max_dist; + } horizontal; + struct + { + F32 rest_dist; + F32 view_angle; + F32 offset; + F32 offset_dir; + F32 turn_speed; + F32 vel_scale; + F32 roll_speed; + xVec3 unused1; + } camera; + struct + { + F32 hit_loss; + F32 damage_velocity; + F32 hit_velocity; + } collision; + }; + + struct hook_type : xBase + { + hook_asset* asset; + xEnt* ent; + }; + + void load(xBase& data, xDynAsset& asset, size_t); + bool active(); + bool landed(); + bool destroy(); + void insert_animations(xAnimTable& table); +} // namespace bungee_state + +#endif diff --git a/src/SB/Game/zEntPlayerOOBState.h b/src/SB/Game/zEntPlayerOOBState.h new file mode 100644 index 0000000..42469d4 --- /dev/null +++ b/src/SB/Game/zEntPlayerOOBState.h @@ -0,0 +1,190 @@ +#ifndef ZENTPLAYEROOBSTATE_H +#define ZENTPLAYEROOBSTATE_H + +#include "xserializer.h" +#include "zTalkBox.h" +#include "zTaskBox.h" + +extern bool oob_player_teleported; + +namespace oob_state +{ + bool render(); + void fx_render(); + void read_persistent(xSerial& s); + void write_persistent(xSerial& s); + + float oob_timer(); + + bool IsPlayerInControl(); + + struct callback + { + virtual void on_stop(); + }; + + enum state_enum + { + STATE_INVALID = -1, + BEGIN_STATE, + STATE_IN = 0, + STATE_OUT, + STATE_GRAB, + STATE_DROP, + END_STATE, + MAX_STATE = 0x4 + }; + + namespace + { + struct state_type + { + state_enum type; + + void start(); + void stop(); + }; + + struct in_state_type : state_type + { + void start(); + void stop(); + }; + + struct out_state_type : state_type + { + void start(); + void stop(); + }; + + struct grab_state_type : state_type + { + enum substate_enum + { + SS_INVALID = -1, + SS_REORIENT, + SS_BEGIN_WAIT, + SS_MOVING_IN, + SS_STOPPING, + SS_STOPPED, + SS_TUTORIAL, + SS_STARTING, + SS_MOVING_OUT, + SS_START_FADE_OUT, + SS_FADE_OUT, + MAX_SS + }; + + struct tutorial_callback : callback + { + grab_state_type& owner; + + void on_stop(); + }; + + tutorial_callback cb; + substate_enum move_substate; + substate_enum fade_substate; + xVec3 player_start; + float reorient_time; + float angle_delta; + float delay; + float fade_start_time; + float fade_time; + unsigned int scene_reset; + + // Todo: this is not in the DWARF, but is required for + // tutorial_callback::on_stop to match. Probably + // not correct. + char pad[4]; + + unsigned char finished_tutorial; + + substate_enum (*updatess)(grab_state_type&, xScene&, float&)[10]; + bool update_reorient(xScene&, F32&); + substate_enum update_stopping(xScene&, float&); + + void start(); + void stop(); + }; + + struct _class_9 + { + int flags; + state_type* state; + unsigned char control; + state_type* states[4]; + float out_time; + float max_out_time; + float reset_time; + xModelInstance* model; + xVec2 loc; + xVec2 dir; + float fade_alpha; + unsigned char render_hand; + unsigned char vertical; + float vel; + float accel; + ztalkbox* tutorial; + struct + { + float near_d; + float near_h; + float near_pitch; + float far_d; + float far_h; + float far_pitch; + xMat4x3* tgt_mat; + xMat4x3* tgt_omat; + } cam_data; + }; + + struct tagFixed + { + float out_time; + float reset_time; + float cam_dist; + float cam_height; + float cam_pitch; + float reorient_time; + char* hand_model; + xVec2 in_loc; + xVec2 out_loc; + struct + { + float in_wait_time; + float in_vel; + float in_stop_dist; + float out_wait_time; + float out_vel; + float out_start_dist; + float fade_start_time; + float fade_time; + } grab; + struct + { + float in_vel; + float in_stop_dist; + float out_wait_time; + float out_vel; + float out_start_dist; + float fade_start_time; + float fade_time; + } drop; + float hand_size_x; + float hand_size_y; + float hand_yaw; + float hand_pitch; + float hand_roll; + }; + } // namespace + + struct idiot_level_data + { + bool triggered; // offset 0x0, size 0x1 + U32 scene; // offset 0x4, size 0x4 + }; + +} // namespace oob_state + +#endif diff --git a/src/SB/Game/zEntSimpleObj.h b/src/SB/Game/zEntSimpleObj.h new file mode 100644 index 0000000..dd4d4fb --- /dev/null +++ b/src/SB/Game/zEntSimpleObj.h @@ -0,0 +1,57 @@ +#ifndef ZENTSIMPLEOBJ_H +#define ZENTSIMPLEOBJ_H + +#include "zEnt.h" +#include "xShadow.h" +#include "xString.h" +#include "xstransvc.h" +#include "iAnim.h" +#include "iModel.h" +#include "zFX.h" +#include "xEnt.h" +#include "zCollGeom.h" +#include "zGlobals.h" +#include "xSkyDome.h" +#include "zGoo.h" +#include "zShrapnel.h" +#include "xMath.h" +#include "zGame.h" +#include "zLOD.h" + +struct xSimpleObjAsset +{ + F32 animSpeed; + U32 initAnimState; + U8 collType; + U8 flags; +}; + +struct zEntSimpleObj : zEnt +{ + xSimpleObjAsset* sasset; // 0xD4 + U32 sflags; + void* anim; + F32 animTime; +}; + +struct zScene; + +extern void iModelAnimMatrices(RpAtomic*, xQuat*, xVec3*, RwMatrixTag*); + +void zEntSimpleObj_MgrInit(zEntSimpleObj** entList, U32 entCount); +void zEntSimpleObj_MgrUpdateRender(RpWorld* world, F32 dt); +void zEntSimpleObj_MgrCustomUpdate(zScene* s, F32 dt); +void zEntSimpleObj_MgrCustomRender(); +void zEntTrackPhysics_Init(void* ent, void* asset); +void zEntSimpleObj_Init(void* ent, void* asset); +void zEntSimpleObj_Render(xEnt* ent); +void zEntSimpleObj_Init(zEntSimpleObj* ent, xEntAsset* asset, bool arg2); +void zEntSimpleObj_Move(xEnt*, xScene*, F32, xEntFrame*); +void zEntSimpleObj_Setup(zEntSimpleObj* ent); +void zEntSimpleObj_Update(zEntSimpleObj* ent, xScene* scene, F32 dt); +void zEntSimpleObj_Save(zEntSimpleObj* ent, xSerial* s); +void zEntSimpleObj_Load(zEntSimpleObj* ent, xSerial* s); +void zEntSimpleObj_Reset(zEntSimpleObj* ent, xScene* scene); +s32 zEntSimpleObjEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* base3); + +#endif diff --git a/src/SB/Game/zEntTeleportBox.h b/src/SB/Game/zEntTeleportBox.h new file mode 100644 index 0000000..5a45793 --- /dev/null +++ b/src/SB/Game/zEntTeleportBox.h @@ -0,0 +1,50 @@ +#ifndef ZENTTELEPORTBOX_H +#define ZENTTELEPORTBOX_H + +#include "zEnt.h" +#include "xDynAsset.h" + +struct teleport_asset : xDynAsset +{ + U32 marker; + U32 opened; + U32 launchAngle; + U32 camAngle; + U32 targetID; +}; + +struct _zEntTeleportBox : zEnt +{ + U32 status; + teleport_asset* tasset; + zEnt* target; + U32 currPlrState; + U32 prevPlrState; + U32 jumpInAnim; + U32 jumpOutAnim; + U32 JOtoOpenAnim; + U32 JItoOpenAnim; + xBox trig[2]; + U32 currPlayerIn; + U32 prevPlayerIn; + U32 currPlayerNear; + U32 prevPlayerNear; + F32 lastdt; + F32 plrCtrlTimer; +}; + +void zEntTeleportBox_Init(xBase& data, xDynAsset& asset, size_t); +void zEntTeleportBox_Init(_zEntTeleportBox* ent, teleport_asset* asset); +void zEntTeleportBox_InitAll(); +void zEntTeleportBox_Setup(_zEntTeleportBox* ent); +void zEntTeleportBox_Update(xEnt* rawent, xScene* sc, F32 dt); +void zEntTeleportBox_Save(_zEntTeleportBox* ent, xSerial* s); +void zEntTeleportBox_Load(_zEntTeleportBox* ent, xSerial* s); +void zEntTeleportBox_Open(_zEntTeleportBox* ent); +void zEntTeleportBox_Close(_zEntTeleportBox* ent); +S32 zEntTeleportBox_isOpen(_zEntTeleportBox* ent); +S32 zEntTeleportBox_isClosed(_zEntTeleportBox* ent); +S32 zEntTeleportBox_playerIn(); +S32 zEntTeleportBoxEventCB(xBase*, xBase* to, U32 toEvent, const F32*, xBase*); + +#endif diff --git a/src/SB/Game/zEntTrigger.h b/src/SB/Game/zEntTrigger.h new file mode 100644 index 0000000..d6c4f82 --- /dev/null +++ b/src/SB/Game/zEntTrigger.h @@ -0,0 +1,37 @@ +#ifndef ZENTTRIGGER_H +#define ZENTTRIGGER_H + +#include "zEnt.h" + +struct zEntTrigger : zEnt +{ + xMat4x3 triggerMatrix; + xBox triggerBox; + U32 entered; +}; + +struct xTriggerAsset +{ + xVec3 p[4]; + xVec3 direction; + U32 flags; +}; + +#define ZENTTRIGGER_TYPE_BOX 0 +#define ZENTTRIGGER_TYPE_SPHERE 1 +#define ZENTTRIGGER_TYPE_VCYLINDER 2 +#define ZENTTRIGGER_TYPE_VSPHERE 3 +#define ZENTTRIGGER_TYPE_4 4 +#define ZENTTRIGGER_TYPE_5 5 + +void zEntTriggerInit(void* ent, void* asset); +void zEntTriggerInit(zEntTrigger* ent, xEntAsset* asset); +void zEntTriggerUpdate(zEntTrigger* trig, xScene*, F32); +S32 zEntTriggerEventCB(xBase*, xBase* to, U32 toEvent, const F32*, xBase*); +void zEntTriggerSave(zEntTrigger* ent, xSerial* s); +void zEntTriggerLoad(zEntTrigger* ent, xSerial* s); +void zEntTriggerReset(zEntTrigger* ent); +bool zEntTriggerHitsSphere(const zEntTrigger& trig, const xSphere& o, const xVec3& dir); +xTriggerAsset* zEntTriggerAsset(const zEntTrigger& trig); + +#endif diff --git a/src/SB/Game/zEnv.h b/src/SB/Game/zEnv.h new file mode 100644 index 0000000..6c21e77 --- /dev/null +++ b/src/SB/Game/zEnv.h @@ -0,0 +1,22 @@ +#ifndef ZENV_H +#define ZENV_H + +#include "xBase.h" +#include "xEnv.h" + +struct _zEnv : xBase +{ + xEnvAsset* easset; +}; + +void zEnvInit(void* env, void* easset); +void zEnvInit(_zEnv* env, xEnvAsset* easset); +void zEnvSetup(_zEnv* env); +void zEnvStartingCamera(_zEnv* env); +void zEnvRender(xEnv* env); +void zEnvSave(_zEnv* ent, xSerial* s); +void zEnvLoad(_zEnv* ent, xSerial* s); +void zEnvReset(_zEnv* env); +S32 zEnvEventCB(xBase*, xBase* to, U32 toEvent, const F32* toParam, xBase*); + +#endif diff --git a/src/SB/Game/zEvent.h b/src/SB/Game/zEvent.h new file mode 100644 index 0000000..eacf35c --- /dev/null +++ b/src/SB/Game/zEvent.h @@ -0,0 +1,11 @@ +#ifndef ZEVENT_H +#define ZEVENT_H + +#include "xEvent.h" + +#include +#include "xEvent.h" + +char* zEventName(U32 eventEnum); + +#endif diff --git a/src/SB/Game/zFX.h b/src/SB/Game/zFX.h new file mode 100644 index 0000000..35ff944 --- /dev/null +++ b/src/SB/Game/zFX.h @@ -0,0 +1,102 @@ +#ifndef ZFX_H +#define ZFX_H + +#include "xString.h" +#include "xEnt.h" +#include "xFX.h" + +#include +#include + +struct tweak_info; +struct tweak_callback; + +enum zFXGooState +{ + zFXGooStateNormal, + zFXGooStateFreezing, + zFXGooStateFrozen, + zFXGooStateMelting, + zFXGooStateInactive = 0xdeadbeef, + zFXGooStateForce32Bit = 0xffffffff +}; + +struct zFXGooInstance +{ + RpAtomic* atomic; + S32 freezeGroup; + xVec3* orig_verts; + RwRGBA* orig_colors; + F32 time; + F32 timer; + F32 w0; + F32 w2; + F32 warbc[4]; + F32 state_time[4]; + xVec3 center; + S32 padding; // Padding used for zFXGoo_SceneExit(). + zFXGooState state; + F32 warb_time; + F32 alpha; + F32 min; + F32 max; + xVec3* ref_parentPos; + xVec3 pos_parentOnFreeze; +}; + +extern U32 gFXSurfaceFlags; + +void on_spawn_bubble_wall(const tweak_info& tweak); +void zFX_SceneEnter(RpWorld* world); +void zFX_SceneExit(RpWorld* world); +void zFX_SceneReset(); +void zFXHammer(xVec3* pos); +void zFXPorterWave(const xVec3* pos); + +void zFXGooEnable(RpAtomic* atomic, S32 freezeGroup); + +void zFXGoo_SceneEnter(); +void zFXGoo_SceneReset(); +void zFXGoo_SceneExit(); + +void zFXGooEventSetWarb(xEnt* obj, const F32* param); +void zFXGooEventSetFreezeDuration(xEnt* obj, const F32 param); +void zFXGooEventMelt(xEnt* obj); + +void zFXGooUpdate(F32 dt); + +void zFXUpdate(F32 dt); + +S32 zFXGooIs(xEnt* obj, F32& depth, U32 playerCheck); + +void zFX_SpawnBubbleHit(const xVec3* pos, U32 num); +void zFX_SpawnBubbleWall(); +void zFX_SpawnBubbleSlam(const xVec3* pos, U32 num, F32 rang, F32 bvel, F32 rvel); + +void reset_poppers(); + +void reset_entrails(); + +static void init_poppers(); + +void update_poppers(F32 dt); + +void update_entrails(F32 dt); + +void xDebugAddTweak(const char* unk1, const char* unk2, const tweak_callback* unk3, void* unk4, + U32 unk5); + +xFXRing* zFXMuscleArmWave(const xVec3* pos); + +void zFX_SpawnBubbleTrail(const xVec3*, unsigned int); +void zFX_SpawnBubbleTrail(const xVec3* pos, unsigned int num, const xVec3* pos_rnd, + const xVec3* vel_rnd); +void zFX_SpawnBubbleTrail(const xVec3*, const xVec3*, const xVec3*, const xVec3*, unsigned int, + const xVec3*, const xVec3*, float); +void zFX_SpawnBubbleMenuTrail(const xVec3* pos, U32 num, const xVec3* pos_rnd, + const xVec3* vel_rnd); + +void zFXPopOn(xEnt& ent, F32 rate, F32 time); +void zFXPopOff(xEnt& ent, F32 rate, F32 time); + +#endif diff --git a/src/SB/Game/zFeet.h b/src/SB/Game/zFeet.h new file mode 100644 index 0000000..f73d030 --- /dev/null +++ b/src/SB/Game/zFeet.h @@ -0,0 +1,8 @@ +#ifndef ZFEET_H +#define ZFEET_H + +#include + +void zFeetGetIDs(); + +#endif \ No newline at end of file diff --git a/src/SB/Game/zGame.h b/src/SB/Game/zGame.h new file mode 100644 index 0000000..beed9a9 --- /dev/null +++ b/src/SB/Game/zGame.h @@ -0,0 +1,119 @@ +#ifndef ZGAME_H +#define ZGAME_H + +#include "zEntPlayer.h" +#include "zGameState.h" + +extern _CurrentPlayer gPendingPlayer; +extern F32 sTimeElapsed; +extern U32 gLevelChanged; +extern U32 startPressed; +extern U8 sHackSmoothedUpdate; +extern U32 gBusStopIsRunning; + +enum eGameWhereAmI +{ + eGameWhere_NA, + eGameWhere_InitStart, + eGameWhere_InitScene, + eGameWhere_InitCamera, + eGameWhere_InitMusic, + eGameWhere_InitOther, + eGameWhere_InitEnd, + eGameWhere_ExitStart, + eGameWhere_ExitRumble, + eGameWhere_ExitHUD, + eGameWhere_ExitSound, + eGameWhere_ExitCamera, + eGameWhere_ExitScene, + eGameWhere_ExitEnd, + eGameWhere_SetupScene, + eGameWhere_SetupZFX, + eGameWhere_SetupPlayer, + eGameWhere_SetupCamera, + eGameWhere_SetupScrFX, + eGameWhere_SetupSceneLoad, + eGameWhere_SetupMusicNotify, + eGameWhere_SetupHudSetup, + eGameWhere_SetupSkydome, + eGameWhere_SetupSceneEvents, + eGameWhere_SetupUpdateCull, + eGameWhere_SetupLOD, + eGameWhere_SetupExtras, + eGameWhere_SetupEnd, + eGameWhere_LoopStart, + eGameWhere_CutsceneFinish, + eGameWhere_LoopDo, + eGameWhere_LoopCalcTime, + eGameWhere_LoopPadUpdate, + eGameWhere_LoopTRCCheck, + eGameWhere_LoopCheats, + eGameWhere_LoopSceneUpdate, + eGameWhere_LoopPlayerUpdate, + eGameWhere_LoopSoundUpdate, + eGameWhere_LoopSFXWidgets, + eGameWhere_LoopHUDUpdate, + eGameWhere_LoopCameraUpdate, + eGameWhere_LoopCameraFXUpdate, + eGameWhere_LoopFlyToInterface, + eGameWhere_LoopCameraBegin, + eGameWhere_LoopSceneRender, + eGameWhere_LoopCameraEnd, + eGameWhere_LoopCameraShowRaster, + eGameWhere_LoopCameraFXEnd, + eGameWhere_LoopMusicUpdate, + eGameWhere_LoopUpdateMode, + eGameWhere_LoopContinue, + eGameWhere_LoopEndGameLoop, + eGameWhere_SaveLoop, + eGameWhere_ModeSceneSwitch, + eGameWhere_ModeCutsceneFinish, + eGameWhere_ModeGameExit, + eGameWhere_ModeGameInit, + eGameWhere_ModeGameSetup, + eGameWhere_ModeSwitchAutoSave, + eGameWhere_ModeSwitchCutsceneFinish, + eGameWhere_ModeStoreCheckpoint, + eGameWhere_LoseChanceReset, + eGameWhere_LoseChanceResetDone, + eGameWhere_TransitionBubbles, + eGameWhere_TransitionBegin, + eGameWhere_TransitionSnapShot, + eGameWhere_TransitionUpdate, + eGameWhere_TransitionPadUpdate, + eGameWhere_TransitionTRCCheck, + eGameWhere_TransitionCameraClear, + eGameWhere_TransitionCameraBegin, + eGameWhere_TransitionRenderBackground, + eGameWhere_TransitionSpawnBubbles, + eGameWhere_TransitionDrawEnd, + eGameWhere_TransitionUpdateBubbles, + eGameWhere_TransitionCameraEnd, + eGameWhere_TransitionCameraShowRaster, + eGameWhere_TransitionUpdateEnd, + eGameWhere_TransitionUIRender, + eGameWhere_TransitionUIRenderEnd, + eGameWhere_TransitionEnd, + eGameWhere_TransitionEnded, + eGameWhere_SetupPlayerInit, + eGameWhere_SetupPlayerCamera, + eGameWhere_SetupPlayerEnd +}; + +extern iTime sTimeCurrent; +extern iTime sTimeLast; +extern F32 sTimeElapsed; + +void zGameSetupPlayer(); +void xDrawBegin(); +void xDrawEnd(); +S32 zGameIsPaused(); +void zGameScreenTransitionBegin(); +void zGameScreenTransitionUpdate(F32 percentComplete, char* msg); +void zGameScreenTransitionUpdate(F32 percentComplete, char* msg, U8* rgba); +void zGameScreenTransitionEnd(); +void zGameModeSwitch(eGameMode modeNew); +void zGameStall(); +void zGameStats_Init(); + +#endif diff --git a/src/SB/Game/zGameExtras.h b/src/SB/Game/zGameExtras.h new file mode 100644 index 0000000..a97ac48 --- /dev/null +++ b/src/SB/Game/zGameExtras.h @@ -0,0 +1,89 @@ +#ifndef ZGAMEEXTRAS_H +#define ZGAMEEXTRAS_H + +#include "xserializer.h" + +struct EGGItem; + +struct EGGMisc +{ + S32 other; +}; + +struct EGGData +{ + union + { + S32 placeholder; + EGGMisc misc; + }; +}; + +struct EGGItemFuncs +{ + void (*fun_update)(F32, EGGItem*); + void (*fun_init)(EGGItem*); + void (*fun_reset)(EGGItem*); + void (*fun_done)(EGGItem*); +}; + +struct EGGItem +{ + S32 (*fun_check)(EGGItem*); + EGGItemFuncs* funcs; + S32 enabled; + EGGData eggdata; +}; + +struct GECheat +{ + U32* key_code; + void (*fun_cheat)(); + S32 flg_keep; + S32 flg_mode; +}; + +S32 zGameExtras_ExtrasFlags(); +void zGameExtras_MoDay(S32* month, S32* day); +void zGameExtras_SceneReset(); +void zGameExtras_SceneInit(); +void zGameExtras_SceneExit(); +void zGameExtras_SceneUpdate(F32 dt); +S32 zGameExtras_CheatFlags(); +void zGameExtras_NewGameReset(); +void zGameExtras_Save(xSerial* xser); +void zGameExtras_Load(xSerial* xser); +S32 TestCheat(U32* cheat); +S32 EGG_check_ExtrasFlags(EGGItem* egg); +void AddToCheatPressed(U32 param_1); +void GEC_CheatFlagAdd(S32 bit); +void GEC_CheatFlagToggle(S32 bit); +void GEC_dfltSound(); +void GEC_cb_AddShiny(); +void GEC_cb_AddSpatulas(); +void GEC_cb_BubbleBowl(); +void GEC_cb_CruiseBubble(); +void GEC_cb_MonsterGallery(); +void GEC_cb_UnlockArtTheatre(); +void GEC_cb_ChaChing(); +void GEC_cb_RestoreHealth(); +void GEC_cb_ExpertMode(); +void GEC_cb_ShrapBobMode(); +void GEC_cb_NoPantsMode(); +void GEC_cb_CruiseControl(); +void GEC_cb_SwapCCLR(); +void GEC_cb_SwapCCUD(); +void GEC_villSound(); +void GEC_cb_BigPlank(); +void GEC_cb_Medics(); +void GEC_cb_DogTrix(); +void GEC_cb_SmallPeep(); +void GEC_cb_SmallCostars(); +void GEC_cb_RichPeep(); +void GEC_cb_PanHandle(); +void zGame_HackGalleryInit(); +U32 zGame_HackIsGallery(); + +template T xUtil_choose(T const* list, S32 size, F32 const* c); + +#endif diff --git a/src/SB/Game/zGameState.h b/src/SB/Game/zGameState.h new file mode 100644 index 0000000..8cc518d --- /dev/null +++ b/src/SB/Game/zGameState.h @@ -0,0 +1,108 @@ +#ifndef ZGAMESTATE_H +#define ZGAMESTATE_H + +#include + +enum _GameOstrich +{ + eGameOstrich_Loading, + eGameOstrich_PlayingMovie, + eGameOstrich_InScene, + eGameOstrich_Total +}; + +enum eGameMode +{ + eGameMode_Boot, + eGameMode_Intro, + eGameMode_Title, + eGameMode_Start, + eGameMode_Load, + eGameMode_Options, + eGameMode_Save, + eGameMode_Pause, + eGameMode_Stall, + eGameMode_WorldMap, + eGameMode_MonsterGallery, + eGameMode_ConceptArtGallery, + eGameMode_Game, + eGameMode_Count +}; + +// These enums are fake, but they're likely similar to how they were in the original code +// Enums are way easier to use than a bunch of macros in this case +// (taken from bfbbpc) + +enum eGameState +{ + eGameState_FirstTime, + eGameState_Play, + eGameState_LoseChance, + eGameState_GameOver, + eGameState_GameStats, + eGameState_SceneSwitch, + eGameState_Dead, + eGameState_Exit, + eGameState_Count +}; + +enum ePauseState +{ + ePauseState_Pause, + ePauseState_Options, + ePauseState_Count +}; + +enum eSaveState +{ + eSaveState_SelectMemCard, + eSaveState_SelectSlot, + eSaveState_Saving, + eSaveState_Count +}; + +enum eOptionsState +{ + eOptionsState_Options, + eOptionsState_Count +}; + +enum eLoadState +{ + eLoadState_SelectMemCard, + eLoadState_SelectSlot, + eLoadState_Loading, + eLoadState_Count +}; + +enum eTitleState +{ + eTitleState_Start, + eTitleState_Attract, + eTitleState_Count +}; + +enum eIntroState +{ + eIntroState_Sony, + eIntroState_Publisher, + eIntroState_Developer, + eIntroState_License, + eIntroState_Count +}; + +extern S32 gGameState; +extern eGameMode gGameMode; +extern _GameOstrich gGameOstrich; + +S32 zGameStateGet(); +eGameMode zGameModeGet(); +_GameOstrich zGameGetOstrich(); +void zGameSetOstrich(_GameOstrich o); +S32 zGameStateFindEvent(U32* eventList, S32 eventCount, S32 targetMode, S32 targetEvent, + S32* new_mode, S32* new_state); +void zGameStateSwitchEvent(S32 event); +void zGameStateSwitch(S32 theNewState); +void zGameModeSwitch(eGameMode modeNew); + +#endif diff --git a/src/SB/Game/zGlobals.h b/src/SB/Game/zGlobals.h new file mode 100644 index 0000000..348052a --- /dev/null +++ b/src/SB/Game/zGlobals.h @@ -0,0 +1,327 @@ +#ifndef ZGLOBALS_H +#define ZGLOBALS_H + +#include "xGlobals.h" +#include "xShadowSimple.h" +#include "xEntDrive.h" + +#include "zEnt.h" +#include "zEntPlayer.h" +#include "zScene.h" + +struct zGlobalSettings +{ + // 0x874 in globals + U16 AnalogMin; + U16 AnalogMax; + F32 SundaeTime; + F32 SundaeMult; + U32 InitialShinyCount; + U32 InitialSpatulaCount; + + // 0x888 in globals + S32 ShinyValuePurple; + S32 ShinyValueBlue; + S32 ShinyValueGreen; + S32 ShinyValueYellow; + S32 ShinyValueRed; + + // 0x89C in globals + S32 ShinyValueCombo0; + S32 ShinyValueCombo1; + S32 ShinyValueCombo2; + S32 ShinyValueCombo3; + S32 ShinyValueCombo4; + S32 ShinyValueCombo5; + S32 ShinyValueCombo6; + S32 ShinyValueCombo7; + S32 ShinyValueCombo8; + S32 ShinyValueCombo9; + S32 ShinyValueCombo10; + S32 ShinyValueCombo11; + S32 ShinyValueCombo12; + S32 ShinyValueCombo13; + S32 ShinyValueCombo14; + S32 ShinyValueCombo15; + + // 0x8DC in globals + F32 ComboTimer; + U32 Initial_Specials; + U32 TakeDamage; + F32 DamageTimeHit; + F32 DamageTimeSurface; + F32 DamageTimeEGen; + F32 DamageSurfKnock; + F32 DamageGiveHealthKnock; + U32 CheatSpongeball; + U32 CheatPlayerSwitch; + U32 CheatAlwaysPortal; + U32 CheatFlyToggle; + U32 DisableForceConversation; + F32 StartSlideAngle; + F32 StopSlideAngle; + F32 RotMatchMaxAngle; + F32 RotMatchMatchTime; + F32 RotMatchRelaxTime; + F32 Gravity; + F32 BBashTime; + F32 BBashHeight; + F32 BBashDelay; + F32 BBashCVTime; + F32 BBounceSpeed; + F32 BSpinMinFrame; + F32 BSpinMaxFrame; + F32 BSpinRadius; + F32 SandyMeleeMinFrame; + F32 SandyMeleeMaxFrame; + F32 SandyMeleeRadius; + F32 BubbleBowlTimeDelay; + F32 BubbleBowlLaunchPosLeft; + F32 BubbleBowlLaunchPosUp; + F32 BubbleBowlLaunchPosAt; + F32 BubbleBowlLaunchVelLeft; + F32 BubbleBowlLaunchVelUp; + F32 BubbleBowlLaunchVelAt; + F32 BubbleBowlPercentIncrease; + F32 BubbleBowlMinSpeed; + F32 BubbleBowlMinRecoverTime; + F32 SlideAccelVelMin; + F32 SlideAccelVelMax; + F32 SlideAccelStart; + F32 SlideAccelEnd; + F32 SlideAccelPlayerFwd; + F32 SlideAccelPlayerBack; + F32 SlideAccelPlayerSide; + F32 SlideVelMaxStart; + F32 SlideVelMaxEnd; + F32 SlideVelMaxIncTime; + F32 SlideVelMaxIncAccel; + F32 SlideAirHoldTime; + F32 SlideAirSlowTime; + F32 SlideAirDblHoldTime; + F32 SlideAirDblSlowTime; + F32 SlideVelDblBoost; + U8 SlideApplyPhysics; + // 0x9BD in globals + U8 PowerUp[2]; + U8 InitialPowerUp[2]; +}; + +struct xEntBoulder; +struct zEntHangable; +struct zPlatform; +struct xSurface; +struct zAssetPickupTable; +struct zCutsceneMgr; + +struct zCheckPoint +{ + xVec3 pos; + F32 rot; + U32 initCamID; +}; + +#define LEVEL_COUNT 15 + +struct zPlayerGlobals +{ + // 0x6E0 in globals + zEnt ent; + + // 0x7B4 in globals + xEntShadow entShadow_embedded; + xShadowSimpleCache simpShadow_embedded; + + // 0x874 in globals + zGlobalSettings g; + + // 0x9C4 in globals + zPlayerSettings* s; + zPlayerSettings sb; + zPlayerSettings patrick; + zPlayerSettings sandy; + + // 0x16A0 in globals + xModelInstance* model_spongebob; + xModelInstance* model_patrick; + xModelInstance* model_sandy; + + // 0x16AC in globals + U32 Visible; + U32 Health; // 0x16b0 + S32 Speed; + F32 SpeedMult; + S32 Sneak; + S32 Teeter; + F32 SlipFadeTimer; + S32 Slide; + F32 SlideTimer; + S32 Stepping; + S32 JumpState; + S32 LastJumpState; + + // 0x16DC in globals + F32 JumpTimer; + F32 LookAroundTimer; + U32 LookAroundRand; + U32 LastProjectile; + F32 DecelRun; + F32 DecelRunSpeed; + F32 HotsauceTimer; + F32 LeanLerp; + F32 ScareTimer; + xBase* ScareSource; + F32 CowerTimer; + F32 DamageTimer; // 0x1708 + F32 SundaeTimer; + F32 ControlOffTimer; + F32 HelmetTimer; + + // Offset: 0x1718 + U32 WorldDisguise; + U32 Bounced; + F32 FallDeathTimer; + F32 HeadbuttVel; + F32 HeadbuttTimer; + U32 SpecialReceived; + xEnt* MountChimney; + F32 MountChimOldY; + U32 MaxHealth; + + // Offset: 0x173C + U32 DoMeleeCheck; + F32 VictoryTimer; + F32 BadGuyNearTimer; + F32 ForceSlipperyTimer; + F32 ForceSlipperyFriction; + F32 ShockRadius; + F32 ShockRadiusOld; + F32 Face_ScareTimer; + + // Offset: 0x175C + U32 Face_ScareRandom; + U32 Face_Event; + F32 Face_EventTimer; + F32 Face_PantTimer; + U32 Face_AnimSpecific; + U32 IdleRand; + F32 IdleMinorTimer; + F32 IdleMajorTimer; + F32 IdleSitTimer; + S32 Transparent; + zEnt* FireTarget; + U32 ControlOff; // 0x1788 + U32 ControlOnEvent; + + // Offset: 0x1790 + U32 AutoMoveSpeed; + F32 AutoMoveDist; + xVec3 AutoMoveTarget; + xBase* AutoMoveObject; + zEnt* Diggable; + F32 DigTimer; // 0x17AC + zPlayerCarryInfo carry; + zPlayerLassoInfo lassoInfo; + xModelTag BubbleWandTag[2]; + xModelInstance* model_wand; // 0x19E0 + xEntBoulder* bubblebowl; + F32 bbowlInitVel; // 0x19E8 + zEntHangable* HangFound; + zEntHangable* HangEnt; + zEntHangable* HangEntLast; + xVec3 HangPivot; + xVec3 HangVel; + F32 HangLength; + xVec3 HangStartPos; + F32 HangStartLerp; + xModelTag HangPawTag[4]; + F32 HangPawOffset; + F32 HangElapsed; + F32 Jump_CurrGravity; + F32 Jump_HoldTimer; + F32 Jump_ChangeTimer; + + // Offset: 0x1AB8 + S32 Jump_CanDouble; + S32 Jump_CanFloat; + S32 Jump_SpringboardStart; + zPlatform* Jump_Springboard; + S32 CanJump; + S32 CanBubbleSpin; + S32 CanBubbleBounce; + S32 CanBubbleBash; + + // Offset: 0x1AD8 in globals + S32 IsJumping; + S32 IsDJumping; + S32 IsBubbleSpinning; + S32 IsBubbleBouncing; + S32 IsBubbleBashing; + S32 IsBubbleBowling; + S32 WasDJumping; + S32 IsCoptering; + _zPlayerWallJumpState WallJumpState; + S32 cheat_mode; + + // Offset: 0x1B00 in globals + U32 Inv_Shiny; + U32 Inv_Spatula; + U32 Inv_PatsSock[LEVEL_COUNT]; + U32 Inv_PatsSock_Max[LEVEL_COUNT]; + + // Offset: 0x1B80 in globals + U32 Inv_PatsSock_CurrentLevel; + U32 Inv_LevelPickups[LEVEL_COUNT]; + U32 Inv_LevelPickups_CurrentLevel; + + // Offset: 0x1BC4 in globals + U32 Inv_PatsSock_Total; + xModelTag BubbleTag; + xEntDrive drv; + xSurface* floor_surf; + xVec3 floor_norm; + + // Offset: 0x1C74 in globals + S32 slope; + xCollis earc_coll; + xSphere head_sph; + xModelTag center_tag; + xModelTag head_tag; + U32 TongueFlags[2]; + xVec3 RootUp; + xVec3 RootUpTarget; + zCheckPoint cp; + U32 SlideTrackSliding; + U32 SlideTrackCount; + xEnt* SlideTrackEnt[111]; + U32 SlideNotGroundedSinceSlide; + xVec3 SlideTrackDir; + xVec3 SlideTrackVel; + F32 SlideTrackDecay; + F32 SlideTrackLean; + F32 SlideTrackLand; + U8 sb_model_indices[14]; + xModelInstance* sb_models[14]; + U32 currentPlayer; + xVec3 PredictRotate; + xVec3 PredictTranslate; + F32 PredictAngV; + xVec3 PredictCurrDir; + F32 PredictCurrVel; + F32 KnockBackTimer; + F32 KnockIntoAirTimer; // 0x1FB4 +}; + +struct zGlobals : xGlobals +{ + zPlayerGlobals player; + zAssetPickupTable* pickupTable; // 0x1FB8 + zCutsceneMgr* cmgr; // 0x1FBC + zScene* sceneCur; // 0x1FC0 + zScene* scenePreload; +}; + +extern zGlobals globals; +extern xGlobals* xglobals; + +#endif diff --git a/src/SB/Game/zGoo.h b/src/SB/Game/zGoo.h new file mode 100644 index 0000000..bcb8314 --- /dev/null +++ b/src/SB/Game/zGoo.h @@ -0,0 +1,18 @@ +#ifndef ZGOO_H +#define ZGOO_H + +#include "xEnt.h" + +#include +#include + +void zGooInit(S32 nobj); +void zGooExit(); +S32 zGooAdd(xEnt* obj, F32 depth, S32 freezeGroup); +S32 zGooIs(xEnt* obj, F32& depth, U32 playerCheck); +void zGooCollsBegin(); +void zGooCollsEnd(); +void zGooStopTide(); +void zGooMeltFinished(RpAtomic* atomic); + +#endif diff --git a/src/SB/Game/zGrid.h b/src/SB/Game/zGrid.h new file mode 100644 index 0000000..40b0645 --- /dev/null +++ b/src/SB/Game/zGrid.h @@ -0,0 +1,18 @@ +#ifndef ZGRID_H +#define ZGRID_H + +#include "zScene.h" + +#include "xEnt.h" +#include "xGrid.h" + +extern xGrid colls_grid; +extern xGrid colls_oso_grid; +extern xGrid npcs_grid; + +void zGridUpdateEnt(xEnt* ent); +void zGridExit(zScene*); +void zGridInit(zScene* s); +void zGridReset(zScene* s); + +#endif diff --git a/src/SB/Game/zGust.h b/src/SB/Game/zGust.h new file mode 100644 index 0000000..a30bf70 --- /dev/null +++ b/src/SB/Game/zGust.h @@ -0,0 +1,44 @@ +#ifndef ZGUST_H +#define ZGUST_H + +#include "xBase.h" +#include "xMath3.h" + +#include "zVolume.h" + +#include + +struct zGustAsset : xBaseAsset +{ + U32 flags; + U32 volumeID; + U32 effectID; + xVec3 vel; + F32 fade; + F32 partMod; +}; + +struct zGust : xBase +{ + U32 flags; + zGustAsset* asset; + zVolume* volume; + zVolume* fx_volume; + F32 debris_timer; +}; + +struct zGustData +{ + U32 gust_on; + zGust* g[4]; + float lerp[4]; +}; + +void zGustInit(); +void zGustSetup(); +zGust* zGustGetGust(U16 n); +void zGustSave(zGust* ent, xSerial* s); +void zGustLoad(zGust* ent, xSerial* s); +void zGustUpdateFX(F32 seconds); + +#endif diff --git a/src/SB/Game/zHud.h b/src/SB/Game/zHud.h new file mode 100644 index 0000000..89aa8a7 --- /dev/null +++ b/src/SB/Game/zHud.h @@ -0,0 +1,17 @@ +#ifndef ZHUD_H +#define ZHUD_H + +#include + +namespace zhud +{ + void render(); + void update(F32 dt); + void show(); + void hide(); + void init(); + void destroy(); + void setup(); +} // namespace zhud + +#endif diff --git a/src/SB/Game/zLOD.h b/src/SB/Game/zLOD.h new file mode 100644 index 0000000..3b85a82 --- /dev/null +++ b/src/SB/Game/zLOD.h @@ -0,0 +1,29 @@ +#ifndef ZLOD_H +#define ZLOD_H + +#include "xModelBucket.h" + +struct zLODTable +{ + xModelBucket** baseBucket; + F32 noRenderDist; + xModelBucket** lodBucket[3]; + F32 lodDist[3]; +}; + +struct zLODManager +{ + S32 numextra; + zLODTable* lod; + xModelInstance* model; + F32 adjustNoRenderDist; +}; + +void zLOD_Setup(); +void zLOD_Update(U32 percent_update); +zLODTable* zLOD_Get(xEnt* ent); +void AddToLODList(xModelInstance* model); +xEnt* AddToLODList(xEnt* ent); +void zLOD_UseCustomTable(xEnt* ent, zLODTable* lod); + +#endif diff --git a/src/SB/Game/zLasso.h b/src/SB/Game/zLasso.h new file mode 100644 index 0000000..f307d43 --- /dev/null +++ b/src/SB/Game/zLasso.h @@ -0,0 +1,59 @@ +#ifndef ZLASSO_H +#define ZLASSO_H + +#include "xMath3.h" +#include "xModel.h" +#include "xString.h" +#include "zEnt.h" + +struct zLasso +{ + U32 flags; + F32 secsTotal; + F32 secsLeft; + F32 stRadius; + F32 tgRadius; // 0x10 + F32 crRadius; + xVec3 stCenter; // 0x18 + xVec3 tgCenter; // 0x24 + xVec3 crCenter; // 0x30 + xVec3 stNormal; // 0x3C + xVec3 tgNormal; + xVec3 crNormal; // 0x48 + xVec3 honda; + F32 stSlack; + F32 stSlackDist; + F32 tgSlack; + F32 tgSlackDist; + F32 crSlack; + F32 currDist; + F32 lastDist; + xVec3 lastRefs[5]; + U8 reindex[5]; + xVec3 anchor; + xModelTag tag; + xModelInstance* model; +}; + +struct zLassoGuide +{ + xModelInstance* poly; + xAnimState* lassoAnim; + S32 vertMap[16]; +}; + +struct zLassoGuideList // Size: 0xE0 +{ + xEnt* target; + U32 numGuides; + zLassoGuide guide[3]; +}; + +void zLasso_scenePrepare(); +void zLasso_InitTimer(zLasso* lasso, F32 interpTime); +void zLasso_ResetTimer(zLasso* lasso, F32 interpTime); +void zLasso_AddGuide(xEnt* ent, xAnimState* lassoAnim, xModelInstance modelInst); +void zLasso_SetGuide(xEnt* ent, xAnimState* lassoAnim); +void zLasso_InterpToGuide(zLasso* lasso); + +#endif diff --git a/src/SB/Game/zLight.h b/src/SB/Game/zLight.h new file mode 100644 index 0000000..85429ec --- /dev/null +++ b/src/SB/Game/zLight.h @@ -0,0 +1,65 @@ +#ifndef ZLIGHT_H +#define ZLIGHT_H + +#include "zVolume.h" + +#include "xEnt.h" +#include "xEnv.h" +#include "iLight.h" + +// Size: 0x38 +struct zLightAsset : xBaseAsset +{ + // 0x8 + U8 lightType; + U8 lightEffect; + U8 lightPad[2]; + U32 lightFlags; + + // 0x10 + F32 lightColor[4]; + xVec3 lightDir; + + // 0x20 + F32 lightConeAngle; + xSphere lightSphere; + U32 attachID; +}; + +// Size: 0x64 +struct _zLight : xBase +{ + // 0x10 + U32 flags; + zLightAsset* tasset; + + // 0x18 + iLight light; + xBase* attached_to; + S32 true_idx; + F32* reg; + + // 0x60 + S32 effect_idx; +}; + +struct xScene; + +void zLightInit(void* b, void* tasset); +void zLightInit(xBase* b, zLightAsset* tasset); +void zLightResolveLinks(); +void zLightSave(_zLight* ent, xSerial* s); +void zLightLoad(_zLight* ent, xSerial* s); +void zLightAddLocalEnv(); +void zLightAddLocal(xEnt* ent); +void zLightRemoveLocalEnv(); +void zLightResetAll(xEnv* env); +void zLightReset(_zLight* param_1); +void zLightSetVolume(zVolume* vol); +void zLightDestroyAll(); +void zLightDestroy(_zLight* param_1); +void zLightUpdate(xBase* to, xScene*, F32 dt); +S32 zLightEventCB(xBase* param_1, xBase* to, U32 toEvent, const float* param_4, + xBase* param_5); + +#endif diff --git a/src/SB/Game/zLightEffect.h b/src/SB/Game/zLightEffect.h new file mode 100644 index 0000000..19f2a69 --- /dev/null +++ b/src/SB/Game/zLightEffect.h @@ -0,0 +1,29 @@ +#ifndef ZLIGHTEFFECT_H +#define ZLIGHTEFFECT_H + +#include "iLight.h" +#include "xBase.h" +#include "zLight.h" + +#include + +typedef void (*lightInitFunc)(_zLight*); + +void zLightEffectSet(_zLight* zlight, S32 idx); +void zLightOn(_zLight* zl, S32 on); +static F32 leGetRandom(); +void zLightEffectInitStrobe(_zLight* zlight); +void zLightEffectInitDim(_zLight* zlight); +void zLightEffectInitHalfDim(_zLight* zlight); +void zLightEffectInitRandomCol(_zLight* zlight); +void zLightEffectInitFlicker(_zLight* zlight); +static void EffectFlicker(_zLight* zlight, F32 seconds, F32 min, F32 rnd); +void zLightEffectFlicker(_zLight* zlight, F32 seconds); +void zLightEffectFlickerSlow(_zLight* zlight, F32 seconds); +void zLightEffectFlickerErratic(_zLight* zlight, F32 seconds); + +void zLightEffectInitCauldron(_zLight* zlight); +static F32 leBlendToCol(F32 f1, F32 f2, F32 f3); +void zLightEffectCauldron(_zLight* zlight, F32 seconds); + +#endif diff --git a/src/SB/Game/zLightning.h b/src/SB/Game/zLightning.h new file mode 100644 index 0000000..ad8fb7c --- /dev/null +++ b/src/SB/Game/zLightning.h @@ -0,0 +1,116 @@ +#ifndef ZLIGHTNING_H +#define ZLIGHTNING_H + +#include "xMath3.h" +#include "iColor.h" + +#include "zFX.h" + +struct _tagLightningAdd +{ + U32 type; + F32 setup_degrees; + F32 move_degrees; + F32 rot_radius; + xVec3* start; + xVec3* end; + S16 total_points; + S16 end_points; + F32 time; + F32 arc_height; + F32 thickness; + iColor_tag color; + F32 rand_radius; + U32 flags; + F32 zeus_normal_offset; + F32 zeus_back_offset; + F32 zeus_side_offset; +}; + +struct _tagLightningLine +{ + F32 unused; +}; + +struct _tagLightningRot +{ + F32 deg[16]; + F32 degrees; + F32 height; +}; + +struct _tagLightningZeus +{ + F32 normal_offset; + F32 back_offset; + F32 side_offset; +}; + +struct zLightning +{ + U32 type; + U32 flags; + union + { + struct + { + xVec3 base_point[16]; + xVec3 point[16]; + S16 total_points; + S16 end_points; + F32 arc_height; + xVec3 arc_normal; + F32 thickness[16]; + union + { + _tagLightningLine line; + _tagLightningRot rot; + _tagLightningZeus zeus; + }; + F32 rand_radius; + } legacy; + struct + { + xVec3 endPoint[2]; + xVec3 direction; + F32 length; + F32 scale; + F32 width; + F32 endParam[2]; + F32 endVel[2]; + F32 paramSpan[2]; + F32 arc_height; + xVec3 arc_normal; + } func; + }; + iColor_tag color; + F32 time_left; + F32 time_total; +}; + +void lightningTweakChangeType(tweak_info& t); +void lightningTweakStart(tweak_info& t); +void zLightningInit(); +zLightning* zLightningAdd(_tagLightningAdd* add); +void UpdateLightning(zLightning* l, F32 seconds); +void zLightningUpdate(F32 seconds); +void zLightningFunc_Render(zLightning* l); +void zLightningShow(zLightning* l, S32 show); +void zLightningKill(zLightning* l); +void RenderLightning(zLightning* l); +void zLightningRender(); +void zLightningModifyEndpoints(zLightning* l, xVec3* start, xVec3* end); +void xDebugAddTweak(char* name, U8* property, U8 param_3, U8 param_4, tweak_callback* callback, + void* param_6, U32 param_7); +void xDebugAddFlagTweak(char* name, U32* property, U32 param_3, tweak_callback* callback, + void* param_5, U32 param_6); +void xDebugAddSelectTweak(char* name, U32* param_2, char** param_3, U32* param_4, U32 param_5, + tweak_callback* callback, void* param_7, U32 param_8); +void xDebugAddTweak(char* name, S16* property, S16 param_3, S16 param_4, tweak_callback* callback, + void* param_6, U32 param_7); + +void zLightningInit(); +void zLightningUpdate(F32 seconds); +void zLightningRender(); + +#endif diff --git a/src/SB/Game/zMain.h b/src/SB/Game/zMain.h new file mode 100644 index 0000000..8d04588 --- /dev/null +++ b/src/SB/Game/zMain.h @@ -0,0 +1,4 @@ +#ifndef ZMAIN_H +#define ZMAIN_H + +#endif \ No newline at end of file diff --git a/src/SB/Game/zMenu.h b/src/SB/Game/zMenu.h new file mode 100644 index 0000000..fd444b7 --- /dev/null +++ b/src/SB/Game/zMenu.h @@ -0,0 +1,18 @@ +#ifndef ZMENU_H +#define ZMENU_H + +#include + +bool menu_fmv_played; + +U32 zMenuUpdateMode(); +U32 zMenuIsPaused(); +S32 zMenuLoopContinue(); +void zMenuFirstBootSet(U32 isFirstBoot); +void zMenuFMVPlay(char*, U32, F32, bool, bool); +bool zMenuCardCheckStartup(S32* bytesNeeded, S32* availOnDisk, S32* neededFiles); +S32 zMenuGetBadCard(); +U32 zMenuGetCorruptFiles(char name[][64]); +S32 zMenuIsFirstBoot(); + +#endif diff --git a/src/SB/Game/zMusic.cpp b/src/SB/Game/zMusic.cpp new file mode 100644 index 0000000..3f6e499 --- /dev/null +++ b/src/SB/Game/zMusic.cpp @@ -0,0 +1,495 @@ +#include +#include "zMusic.h" +#include "xSnd.h" +#include "xMath.h" +#include "xString.h" +#include "zGlobals.h" +#include "zGameState.h" +#include "zScene.h" +#include + +#define TRACK_COUNT 2 + +static U32 sMusicSoundID[24][TRACK_COUNT]; +static zMusicTrackInfo sMusicTrack[TRACK_COUNT]; +static zVolumeInfo volume; + +// clang-format off +static zMusicSituation sMusicInfo[8] = { + { 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0, 0, 0, 0}, + { 1, 0, 0, 0.0f, 1.0f, 0.0f, 0, 0, 1, 0, 0}, + { 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0, 2, 0, 0}, + { 0, 0, 0, 0.0f, 2.0f, 0.0f, 0, 0, 3, 0, 0}, + { 0, 0, 0, 0.0f, 1.0f, 0.0f, 0, 0, 4, 0, 0}, + { 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0, 5, 0, 0}, + { 1, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0, 6, 0, 0}, + { 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0, 7, 0, 0}, +}; +// clang-format on + +static U32 sMusicPaused; +static zMusicSituation* sMusicQueueData[TRACK_COUNT]; + +static S32 sMusicLastEnum[TRACK_COUNT] = { 0.0f, 0.0f }; +static F32 sMusicTimer[TRACK_COUNT] = { 0.0f, 0.0f }; + +extern eGameMode gGameMode; +extern zGlobals globals; + +static const F32 minDelay = 0.001f; + +static void volume_update(F32 vol); + +static void volume_reset() +{ + volume.cur = 0.0f; + volume.end = 1.0f; + volume.inc = 0.0f; + + memset(volume.adjusted, 0, sizeof(volume.adjusted)); +} + +// Reset both music tracks to their default volume. +void zMusicRefreshVolume() +{ + for (S32 i = 0; i < 2; i++) + { + zMusicTrackInfo* track = &sMusicTrack[i]; + if (track->snd_id != 0) + { + // Only reset volume if the sound ID is not blank. + xSndSetVol(track->snd_id, volume.cur); + } + } +} + +void zMusicInit() +{ + sMusicPaused = 0; + + for (int i = 0; i < sizeof(sMusicTrack) / sizeof(sMusicTrack[0]); i++) + { + sMusicTrack[i].snd_id = 0; + sMusicTrack[i].loop = 0; + sMusicTrack[i].situation = 0; + } + + sMusicSoundID[0][0] = xStrHash("music_00_hb_44"); + sMusicSoundID[0][1] = 1; + sMusicSoundID[1][0] = xStrHash("music_01_jf_44"); + sMusicSoundID[1][1] = 1; + sMusicSoundID[2][0] = xStrHash("music_02_bb_44"); + sMusicSoundID[2][1] = 1; + sMusicSoundID[3][0] = xStrHash("music_03_gl_44"); + sMusicSoundID[3][1] = 1; + sMusicSoundID[4][0] = xStrHash("music_04_b1_44"); + sMusicSoundID[4][1] = 1; + sMusicSoundID[5][0] = xStrHash("music_05_rb_44"); + sMusicSoundID[5][1] = 1; + sMusicSoundID[6][0] = xStrHash("music_06_bc_44"); + sMusicSoundID[6][1] = 1; + sMusicSoundID[7][0] = xStrHash("music_07_sm_44"); + sMusicSoundID[7][1] = 1; + sMusicSoundID[8][0] = xStrHash("music_08_b2_44"); + sMusicSoundID[8][1] = 1; + sMusicSoundID[9][0] = xStrHash("music_09_kf_44"); + sMusicSoundID[9][1] = 1; + sMusicSoundID[10][0] = xStrHash("music_10_gy_44"); + sMusicSoundID[10][1] = 1; + sMusicSoundID[11][0] = xStrHash("music_11_db_44"); + sMusicSoundID[11][1] = 1; + sMusicSoundID[12][0] = xStrHash("music_12_b3_44"); + sMusicSoundID[12][1] = 1; + sMusicSoundID[13][0] = xStrHash("music_13_mnu3_44"); + sMusicSoundID[13][1] = 1; + sMusicSoundID[14][0] = xStrHash("music_14_mnu4_44"); + sMusicSoundID[14][1] = 1; + sMusicSoundID[15][0] = xStrHash("music_15_slide_44"); + sMusicSoundID[15][1] = 1; + sMusicSoundID[16][0] = xStrHash("music_16_ambush_44"); + sMusicSoundID[16][1] = 1; + sMusicSoundID[17][0] = xStrHash("music_17_subboss_44"); + sMusicSoundID[17][1] = 1; + sMusicSoundID[18][0] = xStrHash("music_18_skatepark_44"); + sMusicSoundID[18][1] = 1; + sMusicSoundID[21][0] = xStrHash("music_21_Calliope1"); + sMusicSoundID[21][1] = 1; + sMusicSoundID[22][0] = xStrHash("music_22_Calliope2"); + sMusicSoundID[22][1] = 1; + sMusicSoundID[23][0] = xStrHash("music_23_Calliope3"); + sMusicSoundID[23][1] = 1; + + for (int i = 0; i < sizeof(sMusicInfo) / sizeof(sMusicInfo[0]); i++) + { + sMusicInfo[i].elapsedTime = sMusicInfo[i].delay; + sMusicInfo[i].count = 0; + } + volume_reset(); +} + +static S32 getCurrLevelMusicEnum() +{ + S32 snd_enum; + + switch (zSceneGetLevelIndex()) + { + case 0: + snd_enum = 0; + break; + case 1: + snd_enum = 1; + break; + case 2: + snd_enum = 2; + break; + case 3: + snd_enum = 3; + break; + case 4: + snd_enum = 4; + break; + case 5: + snd_enum = 5; + break; + case 6: + snd_enum = 6; + break; + case 7: + snd_enum = 0; + break; + case 8: + snd_enum = 8; + break; + case 9: + snd_enum = 9; + break; + case 10: + snd_enum = 10; + break; + case 11: + snd_enum = 11; + break; + case 12: + snd_enum = 12; + break; + case 13: + snd_enum = 2; + break; + case 14: + snd_enum = 13; + break; + default: + snd_enum = (xrand() % 23) + 1; + if (24 <= snd_enum) + { + snd_enum--; + } + if (((snd_enum == 4) || (snd_enum == 7)) || (snd_enum == 8)) + { + snd_enum = 5; + } + break; + } + + return snd_enum; +} + +static S32 zMusicDo(S32 track) +{ + S32 snd_enum; + F32 vol; + F32 pitch; + + vol = 1.0f; + if (globals.NoMusic != FALSE) + { + return 0; + } + + snd_enum = xrand() % 0x18; + switch (sMusicQueueData[track]->situation) + { + case 3: + case 5: + snd_enum = sMusicQueueData[track]->music_enum; + break; + case 6: + snd_enum = sMusicQueueData[track]->music_enum; + break; + case 0: + snd_enum = getCurrLevelMusicEnum(); + break; + case 7: + snd_enum = sMusicLastEnum[0]; + break; + case 2: + snd_enum = 1; + break; + case 4: + break; + default: + snd_enum = xrand() % 0x18; + } + + if (sMusicTrack[track].snd_id != 0) + { + xSndStop(sMusicTrack[track].snd_id); + sMusicTrack[track].snd_id = 0; + } + + sMusicTrack[track].loop = sMusicSoundID[snd_enum][1]; + + pitch = 0.0f; + if (snd_enum == 9 && globals.scenePreload->sceneID == 'KF04') + { + pitch = -12.0f; + vol *= 0.7f; + } + + // FIXME: loop operator + U32 snd_id = sMusicSoundID[snd_enum][track]; + sMusicTrack[track].snd_id = + xSndPlay(snd_id, vol, pitch, 0xFF, sMusicTrack[track].loop, 0, SND_CAT_MUSIC, 0.0f); + + // FIXME: This isn't quite right + if (sMusicTrack[track].snd_id != 0) + { + sMusicTrack[track].snd_id = snd_id; + sMusicTrack[track].assetID = sMusicSoundID[snd_enum][track]; + sMusicTrack[track].lastVol = vol; + if (sMusicQueueData[track] != NULL) + { + sMusicQueueData[track]->sndid = snd_id; + sMusicQueueData[track]->elapsedTime = 0.0f; + sMusicQueueData[track]->count += 1; + sMusicQueueData[track] = NULL; + } + sMusicLastEnum[track] = snd_enum; + return 1; + } + + return 0; +} + +void zMusicNotify(S32 situation) +{ + zMusicSituation* s; + S32 track; + + if (sMusicPaused) + { + return; + } + + s = &sMusicInfo[situation]; + + if (s->countMax != NULL && s->count >= s->countMax) + { + return; + } + + if (s->delay > s->elapsedTime) + { + return; + } + + track = s->track; + sMusicQueueData[track] = &sMusicInfo[situation]; + sMusicTimer[track] = s->punchDelay; + sMusicQueueData[track]->game_state = (gGameMode == eGameMode_Game); +} + +void zMusicNotifyEvent(const F32* toParam, xBase* base) +{ + S32 track; + zMusicSituation* s; + size_t musicInfoIdx; + S32 musicEnum; + + if (sMusicPaused) + { + return; + } + + if (toParam[1] == 0.0f) + { + musicInfoIdx = 5; + } + else + { + musicInfoIdx = 6; + } + musicEnum = toParam[0]; + s = &sMusicInfo[musicInfoIdx]; + track = s->track; + + // FIXME: Body (and maybe conditions) aren't quite right + if (musicEnum != sMusicLastEnum[track] && sMusicQueueData[track] == NULL && + (s->countMax == 0 || s->count < s->countMax) && !(s->delay > s->elapsedTime)) + { + sMusicTimer[track] = s->punchDelay; + sMusicQueueData[track] = s; + sMusicQueueData[track]->game_state = (gGameMode == eGameMode_Game); + sMusicQueueData[track]->music_enum = musicEnum; + } +} + +void zMusicUpdate(F32 dt) +{ + S32 i; + if (sMusicPaused == FALSE) + { + for (i = 0; i < 8; i++) + { + sMusicInfo[i].elapsedTime += dt; + } + + for (i = 0; i < TRACK_COUNT; i++) + { + // FIXME: This conditional isn't quite right + if ((sMusicTimer[i] != 0.0f || sMusicQueueData[i] != NULL) && + gGameMode & 0xC == sMusicQueueData[i]->game_state) + { + if (sMusicTimer[i] < 0.0f) + { + sMusicTimer[i] -= dt; + if (sMusicTimer[i] < 0.0f) + { + sMusicTimer[i] = 0.0f; + } + } + + if (sMusicTimer[i] == 0.0f && sMusicQueueData[i] != NULL) + { + zMusicDo(i); + } + } + } + + volume_update(dt); + } +} + +static void volume_update(F32 vol) +{ + F32 oldVol = volume.cur; + if (volume.inc >= 1e-5f && volume.inc <= -1e-5f) + { + volume.cur = volume.end; + } + else + { + volume.cur = volume.inc * vol + volume.cur; + } + + if ((volume.inc < 0.0f && volume.cur <= volume.end) || + (!(volume.inc < 0.0f) && volume.cur >= volume.end)) + { + volume.end = volume.cur; + volume.inc = 0.0f; + } + + for (S32 trackIdx = 0; trackIdx < TRACK_COUNT; trackIdx++) + { + if (sMusicTrack[trackIdx].snd_id != 0 && + (oldVol != volume.cur || volume.adjusted[trackIdx] != sMusicTrack[trackIdx].snd_id)) + { + F32 setVol = volume.cur * sMusicTrack[trackIdx].lastVol; + if (setVol > 1.0f) + { + setVol = 1.0f; + } + + xSndSetVol(sMusicTrack[trackIdx].snd_id, setVol); + volume.adjusted[trackIdx] = sMusicTrack[trackIdx].snd_id; + } + } +} + +// Stop all tracks and set them to null. +void zMusicKill() +{ + for (S32 i = 0; i < 2; i++) + { + zMusicTrackInfo* track = &sMusicTrack[i]; + if (track->snd_id != 0) + { + xSndStop(track->snd_id); + track->snd_id = 0; + track->loop = 0; + track->situation = NULL; + } + } +} + +// Pause music by stopping any non-null tracks. +void zMusicPause() +{ + if (sMusicPaused == 0) + { + for (S32 i = 0; i < 2; i++) + { + zMusicTrackInfo* track = &sMusicTrack[i]; + if (track->snd_id != 0) + { + xSndStop(track->snd_id); + } + } + sMusicPaused = 1; + } +} + +void zMusicUnpause(S32 kill) +{ + if (sMusicPaused == 0) + { + return; + } + + for (S32 i = 0; i < 2; i++) + { + zMusicTrackInfo* track = &sMusicTrack[i]; + if (track->snd_id == 0) + { + continue; + } + + if (kill != 0) + { + track->snd_id = 0; + } + else + { + S32 flags = i * 0x800; + flags |= ((track->loop != 0) ? 0x8000 : 0) | 0x10000; + flags |= 0x20000; + track->snd_id = + xSndPlay(track->assetID, track->lastVol, 0.0f, 0xff, flags, 0, SND_CAT_MUSIC, 0.0f); + } + } + + sMusicPaused = 0; +} + +// This version of it matches 33%. It's also functionally incorrect. +void zMusicSetVolume(float vol, float delay) +{ + volume.cur = vol; // This makes it introduce the "frsp" instruction. + volume.inc = vol - volume.cur; + + if (delay > + minDelay) // Doing the if statement likes this makes it generate the "blelr" instruction + { + volume.inc = vol / delay; + } +} + +void zMusicReset() +{ + S32 currMusic; + currMusic = getCurrLevelMusicEnum(); + if (sMusicLastEnum[0] != currMusic) + { + zMusicNotify(0); + } +} diff --git a/src/SB/Game/zMusic.h b/src/SB/Game/zMusic.h new file mode 100644 index 0000000..fd3790c --- /dev/null +++ b/src/SB/Game/zMusic.h @@ -0,0 +1,50 @@ +#ifndef ZMUSIC_H +#define ZMUSIC_H + +#include +#include "xBase.h" + +struct zMusicSituation +{ + S32 track; + U32 priority; + U32 countMax; + F32 delay; + F32 punchDelay; + F32 elapsedTime; + U32 count; + U32 sndid; + S32 situation; + S32 music_enum; + S32 game_state; +}; + +struct zVolumeInfo +{ + F32 cur; + F32 end; + F32 inc; + U32 adjusted[2]; +}; + +struct zMusicTrackInfo +{ + U32 snd_id; + U32 loop; + zMusicSituation* situation; + U32 assetID; + F32 lastVol; +}; + +void zMusicRefreshVolume(); +void zMusicNotify(S32 situation); +void zMusicNotifyEvent(const F32* toParam, xBase* base); +void zMusicSetVolume(F32 vol, F32 delay); +void zMusicKill(); +void zMusicPause(); +void zMusicUnpause(S32 kill); +void zMusicReset(); +void zMusicInit(); +void zMusicUpdate(F32 dt); + +#endif diff --git a/src/SB/Game/zParCmd.h b/src/SB/Game/zParCmd.h new file mode 100644 index 0000000..047d05a --- /dev/null +++ b/src/SB/Game/zParCmd.h @@ -0,0 +1,8 @@ +#ifndef ZPARCMD_H +#define ZPARCMD_H + +// Note: all the xParCmd structs and functions are defined in xParCmd.h, don't redefine them here + +void zParCmdFindClipVolumes(); + +#endif \ No newline at end of file diff --git a/src/SB/Game/zParPTank.h b/src/SB/Game/zParPTank.h new file mode 100644 index 0000000..37aa421 --- /dev/null +++ b/src/SB/Game/zParPTank.h @@ -0,0 +1,34 @@ +#ifndef ZPARPTANK_H +#define ZPARPTANK_H + +#include + +struct xVec3; + +struct RpAtomic; +struct zParPTank; +typedef void (*zParPTankUpdateCallback)(zParPTank*, float); + +// total size: 0x14 +struct zParPTank +{ + // 0x2 == Update when paused + U32 flags; // offset 0x0, size 0x4 + zParPTankUpdateCallback update; // offset 0x4, size 0x4 + RpAtomic* ptank; // offset 0x8, size 0x4 + U32 num_particles; // offset 0xC, size 0x4 + U32 max_particles; // offset 0x10, size 0x4 +}; + +void zParPTankInit(); +void zParPTankSceneEnter(); +void zParPTankSceneExit(); +void zParPTankSpawnBubbles(xVec3* pos, xVec3* vel, U32 count, F32 scale); +void zParPTankSpawnSnow(xVec3* pos, xVec3* vel, U32 count); +void zParPTankExit(); +void zParPTankRender(); +void zParPTankUpdate(F32 dt); + +extern const U32 gPTankDisable; + +#endif diff --git a/src/SB/Game/zParSys.h b/src/SB/Game/zParSys.h new file mode 100644 index 0000000..813c4c6 --- /dev/null +++ b/src/SB/Game/zParSys.h @@ -0,0 +1,10 @@ +#ifndef ZPARSYS_H +#define ZPARSYS_H + +#include "xParSys.h" + +struct zParSys : xParSys +{ +}; + +#endif diff --git a/src/SB/Game/zPendulum.h b/src/SB/Game/zPendulum.h new file mode 100644 index 0000000..0f2d1dd --- /dev/null +++ b/src/SB/Game/zPendulum.h @@ -0,0 +1,30 @@ +#ifndef ZPENDULUM_H +#define ZPENDULUM_H + +#include "xEntMotion.h" + +#include "zEnt.h" + +#include + +struct _zPendulum : zEnt +{ + xEntMotion motion; + F32 lt; + F32 q1t; + F32 q3t; +}; + +void zPendulum_Init(void* pend, void* asset); +void zPendulum_Init(_zPendulum* pend, xEntAsset* asset); +void zPendulum_Save(_zPendulum* pend, xSerial* s); +void zPendulum_Load(_zPendulum* pend, xSerial* s); +void zPendulum_Setup(_zPendulum* pend, xScene* sc); +void zPendulum_Reset(_zPendulum* pend, xScene* sc); +void zPendulum_Update(_zPendulum* pend, xScene* sc, F32 dt); +void zPendulum_Move(_zPendulum* pend, xScene* sc, F32 dt, xEntFrame* frame); +void zPendulumTranslate(xEnt* xent, xVec3* dpos, xMat4x3* dmat); +S32 zPendulumEventCB(xBase* from, xBase* to, U32 event, const F32* toParam, + xBase* toParamWidget); + +#endif diff --git a/src/SB/Game/zPickupTable.h b/src/SB/Game/zPickupTable.h new file mode 100644 index 0000000..b90cfa1 --- /dev/null +++ b/src/SB/Game/zPickupTable.h @@ -0,0 +1,23 @@ +#ifndef ZPICKUPTABLE_H +#define ZPICKUPTABLE_H + +#include + +struct zAssetPickupTable +{ + U32 Magic; + U32 Count; +}; + +struct zAssetPickup +{ + U32 pickupHash; + U8 pickupType; + U8 pickupIndex; + U16 pickupFlags; + U32 quantity; + U32 modelID; + U32 animID; +}; + +#endif diff --git a/src/SB/Game/zPlatform.h b/src/SB/Game/zPlatform.h new file mode 100644 index 0000000..3be6b6f --- /dev/null +++ b/src/SB/Game/zPlatform.h @@ -0,0 +1,183 @@ +#ifndef ZPLATFORM_H +#define ZPLATFORM_H + +#include "zEnt.h" +#include "xEntMotion.h" +#include "xEntDrive.h" + +struct xPlatformERData +{ + S32 nodata; +}; + +struct xPlatformOrbitData +{ + S32 nodata; +}; + +struct xPlatformSplineData +{ + S32 nodata; +}; + +struct xPlatformMPData +{ + S32 nodata; +}; + +struct xPlatformMechData +{ + S32 nodata; +}; + +struct xPlatformPenData +{ + S32 nodata; +}; + +struct xPlatformConvBeltData +{ + F32 speed; +}; + +struct xPlatformFallingData +{ + F32 speed; + U32 bustModelID; +}; + +struct xPlatformFRData +{ + F32 fspeed; + F32 rspeed; + F32 ret_delay; + F32 post_ret_delay; +}; + +struct xPlatformBreakawayData +{ + F32 ba_delay; + U32 bustModelID; + F32 reset_delay; + U32 breakflags; +}; + +struct xPlatformSpringboardData +{ + F32 jmph[3]; + F32 jmpbounce; + U32 animID[3]; + xVec3 jmpdir; + U32 springflags; +}; + +struct xPlatformTeeterData +{ + F32 itilt; + F32 maxtilt; + F32 invmass; +}; + +struct xPlatformPaddleData +{ + S32 startOrient; + S32 countOrient; + F32 orientLoop; + F32 orient[6]; + U32 paddleFlags; + F32 rotateSpeed; + F32 accelTime; + F32 decelTime; + F32 hubRadius; +}; + +struct xPlatformFMData +{ + S32 nothingyet; +}; + +struct xPlatformAsset +{ + U8 type; + U8 pad; + U16 flags; + union + { + xPlatformERData er; + xPlatformOrbitData orb; + xPlatformSplineData spl; + xPlatformMPData mp; + xPlatformMechData mech; + xPlatformPenData pen; + xPlatformConvBeltData cb; + xPlatformFallingData fall; + xPlatformFRData fr; + xPlatformBreakawayData ba; + xPlatformSpringboardData sb; + xPlatformTeeterData teet; + xPlatformPaddleData paddle; + xPlatformFMData fm; + }; +}; + +struct zPlatFMRunTime +{ + U32 flags; + F32 tmrs[12]; + F32 ttms[12]; + F32 atms[12]; + F32 dtms[12]; + F32 vms[12]; + F32 dss[12]; +}; + +struct zPlatform : zEnt +{ + xPlatformAsset* passet; // 0xD4 + xEntMotion motion; + U16 state; // 0x144 + U16 plat_flags; // 0x146 + F32 tmr; // 0x148 + S32 ctr; // 0x14C + xMovePoint* src; // 0x150 + xModelInstance* am; // 0x154 + xModelInstance* bm; // 0x158 + S32 moving; + xEntDrive drv; + zPlatFMRunTime* fmrt; + F32 pauseMult; + F32 pauseDelta; +}; + +#define ZPLATFORM_SUBTYPE_PLATFORM 0 +#define ZPLATFORM_SUBTYPE_MECH 4 +#define ZPLATFORM_SUBTYPE_PEN 5 +#define ZPLATFORM_SUBTYPE_CONVBELT 6 +#define ZPLATFORM_SUBTYPE_FALLING 7 +#define ZPLATFORM_SUBTYPE_FR 8 +#define ZPLATFORM_SUBTYPE_BREAKAWAY 9 +#define ZPLATFORM_SUBTYPE_SPRINGBOARD 10 +#define ZPLATFORM_SUBTYPE_TEETER 11 +#define ZPLATFORM_SUBTYPE_PADDLE 12 +#define ZPLATFORM_SUBTYPE_FM 13 + +#define ZPLATFORM_STATE_INIT 0x0 +#define ZPLATFORM_STATE_UNK1 0x3 +#define ZPLATFORM_STATE_UNK2 0x1 +#define ZPLATFORM_STATE_UNK3 0x2 +#define ZPLATFORM_STATE_UNK4 0x4 + +void zPlatform_Init(void* plat, void* asset); +void zPlatform_Init(zPlatform* plat, xEntAsset* asset); +void zPlatform_Setup(zPlatform* plat, xScene* sc); +void zPlatform_Save(zPlatform* ent, xSerial* s); +void zPlatform_Load(zPlatform* ent, xSerial* s); +void zPlatform_Reset(zPlatform* plat, xScene* sc); +void zPlatform_PaddleStartRotate(class xEnt* entplat, S32 direction, S32 stutter); +void zPlatform_Update(xEnt* ent, xScene* sc, float dt); +void zPlatform_Shake(zPlatform* plat, F32 _unused, F32 ampl, F32 freq); +U32 zPlatform_PaddleCollide(xCollis* coll, const xVec3* hitsource, const xVec3* hitvel, + U32 worldSpaceNorm); +S32 zPlatformEventCB(xBase* from, xBase* to, U32 toEvent, const F32* toParam, xBase* base3); + +#endif diff --git a/src/SB/Game/zRenderState.h b/src/SB/Game/zRenderState.h new file mode 100644 index 0000000..c9b793e --- /dev/null +++ b/src/SB/Game/zRenderState.h @@ -0,0 +1,38 @@ +#ifndef ZRENDERSTATE_H +#define ZRENDERSTATE_H + +#include + +enum _SDRenderState +{ + SDRS_Unknown, + SDRS_Default, + SDRS_OpaqueModels, + SDRS_AlphaModels, + SDRS_Bubble, + SDRS_Projectile, + SDRS_Font, + SDRS_HUD, + SDRS_Particles, + SDRS_Lightning, + SDRS_Streak, + SDRS_SkyBack, + SDRS_Environment, + SDRS_Fill, + SDRS_NPCVisual, + SDRS_OOBFade, + SDRS_OOBPlayerZ, + SDRS_OOBPlayerAlpha, + SDRS_OOBHand, + SDRS_Glare, + SDRS_Newsfish, + SDRS_CruiseHUD, + SDRS_DiscoFloorGlow, + SDRS_Total = 0xffffffff +}; + +void zRenderStateInit(); +_SDRenderState zRenderStateCurrent(); +void zRenderState(_SDRenderState newState); + +#endif \ No newline at end of file diff --git a/src/SB/Game/zRumble.h b/src/SB/Game/zRumble.h new file mode 100644 index 0000000..4c79463 --- /dev/null +++ b/src/SB/Game/zRumble.h @@ -0,0 +1,41 @@ +#ifndef ZRUMBLE_H +#define ZRUMBLE_H + +#include +#include "xEnt.h" +#include "xPad.h" + +enum _tagSDRumbleType +{ + SDR_None, + SDR_Test, + SDR_Damage, + SDR_Bounce, + SDR_EventLight, + SDR_EventMedium, + SDR_EventHeavy, + SDR_DustDestroyedObj, + SDR_XploDestroyedObj, + SDR_WebDestroyed, + SDR_Tiki, + SDR_LassoDestroy, + SDR_DamageByEGen, + SDR_BounceHit, + SDR_CruiseBubbleLaunch, + SDR_CruiseBubbleExplode, + SDR_TeleportStart, + SDR_Teleport, + SDR_TeleportEject, + SDR_Total +}; + +void zRumbleStart(S32 pad_id, _tagSDRumbleType rumble_type, xEnt* ent); +void zRumbleStart(S32 pad_id, _tagSDRumbleType rumble_type); +void zRumbleStart(_tagSDRumbleType rumble_type); +void zRumbleStart(_tagSDRumbleType rumble_type, xEnt* ent); +void zRumbleStartDistance(S32 pad_id, F32 real_dist, F32 max_dist, _tagRumbleType type, + F32 maxTime); +void zRumbleStartEntDistance(xEnt* ent, F32 dist, _tagRumbleType type, F32 maxTime); +S32 zPadAddRumble(_tagRumbleType type, F32 time, S32 replace, U32 fxflags); + +#endif diff --git a/src/SB/Game/zSaveLoad.h b/src/SB/Game/zSaveLoad.h new file mode 100644 index 0000000..aea967d --- /dev/null +++ b/src/SB/Game/zSaveLoad.h @@ -0,0 +1,105 @@ +#ifndef ZSAVELOAD_H +#define ZSAVELOAD_H + +#include +#include "xsavegame.h" +struct st_XSAVEGAME_DATA; + +struct zSaveLoadGame +{ + char label[64]; + char date[32]; + S32 progress; + U32 size; + S8 thumbIconIndex; +}; + +struct zSaveLoadUI +{ + U32 entry; + U32 nameID; + char* name; +}; + + +zSaveLoadGame zSaveLoadGameTable[3]; + +void zUpdateThumbIcon(); +void zSaveLoad_Tick(); +S32 zSaveLoad_poll(S32 i); +void zSendEventToThumbIcon(U32 toEvent); +void zChangeThumbIcon(const char* icon); + +void zSaveLoadInit(); +void zSaveLoadGameTableInit(zSaveLoadGame* saveTable); +void zSaveLoadUITableInit(zSaveLoadUI* saveTable); +void zSaveLoad_UIEvent(S32 p1, U32 p2); +st_XSAVEGAME_DATA* zSaveLoadSGInit(en_SAVEGAME_MODE mode); + +S32 zSaveLoadSGDone(st_XSAVEGAME_DATA* data); +S32 zSaveLoad_getgame(); +S32 zSaveLoad_getcard(); +S32 zSaveLoad_getMCavailable(); +S32 zSaveLoad_getMCneeded(); +S32 zSaveLoad_getMCAccessType(); +S32 zSaveLoadGetAutoSaveCard(); +S32 format(S32 num, S32 mode); +S32 CardtoTgt(S32 card); +S32 zSaveLoad_CardCount(); +S32 zSaveLoad_CardPrompt(S32 cardNumber); +S32 zSaveLoad_CardPromptFormat(S32 mode); +S32 zSaveLoad_CardPromptSpace(S32 mode); +S32 zSaveLoad_CardPromptGames(S32 mode); +S32 zSaveLoad_CardPromptGameSlotEmpty(); +S32 zSaveLoad_CardPromptOverwrite(); +S32 zSaveLoad_CardPromptOverwriteDamaged(); +S32 zSaveLoad_ErrorPrompt(S32 cardNumber); +S32 zSaveLoad_DamagedSaveGameErrorPrompt(S32 cardNumber); +S32 zSaveLoad_CardWrongDeviceErrorPrompt(S32 mode); +S32 zSaveLoad_CardDamagedErrorPrompt(S32 mode); +S32 zSaveLoad_SaveDamagedErrorPrompt(S32 cardNumber); +S32 zSaveLoad_CardYankedErrorPrompt(S32 cardNumber); +S32 zSaveLoad_ErrorFormatPrompt(S32 cardNumber); +S32 zSaveLoad_ErrorFormatCardYankedPrompt(S32 cardNumber); +S32 zSaveLoad_CardCheckSingle(S32 cardNumber); +S32 zSaveLoad_CardCheckFormattedSingle(S32 cardNumber); +S32 zSaveLoad_CardCheckSpaceSingle_doCheck(st_XSAVEGAME_DATA* xsgdata, S32 cardNumber); +S32 zSaveLoad_CardCheckSpaceSingle(S32 cardNumber); +S32 zSaveLoad_CardCheckGamesSingle_doCheck(st_XSAVEGAME_DATA* xsgdata, S32 cardNumber); +S32 zSaveLoad_CardCheckGamesSingle(S32 cardNumber); +S32 zSaveLoad_CardCheckSlotEmpty_hasGame_doCheck(st_XSAVEGAME_DATA* xsgdata, S32 cardNumber, + S32 gameNumber); +S32 zSaveLoad_CardCheckSlotEmpty_hasGame(S32 cardNumber, S32 gameNumber); +S32 zSaveLoad_CardCheckSlotOverwrite_Free(S32 cardNumber, S32 gameNumber); +S32 zSaveLoad_CardCheck(S32 cardNumber, S32 mode); +S32 zSaveLoad_CardCheckValid(S32 cardNumber, S32 mode); +S32 zSaveLoad_CardCheckSpace(S32 cardNumber, S32 mode); +S32 zSaveLoad_CardCheckGames(S32 cardNumber, S32 mode); +S32 zSaveLoad_CardCheckGameSlot(S32 cardNumber, S32 gameNumber, S32 mode); +S32 zSaveLoad_CardCheckSlotEmpty(S32 cardNumber, S32 gameNumber); +S32 zSaveLoad_CardCheckSlotOverwrite(S32 cardNumber, S32 gameNumber); +S32 zSaveLoad_CardPick(S32 mode); +bool IsValidName(char* name); +void BuildIt(char* build_txt, S32 i); +void zSaveLoad_BuildName(char* name_txt, S32 idx); +S32 zSaveLoad_GameSelect(S32 mode); +U8 zSaveLoadGetPreAutoSave(); +void zSaveLoadPreAutoSave(bool onOff); +void zSaveLoadAutoSaveUpdate(); +S32 zSaveLoad_DoAutoSave(); +S32 zSaveLoad_SaveGame(); +S32 zSaveLoad_LoadGame(); +U32 zSaveLoad_LoadLoop(); +U32 zSaveLoad_SaveLoop(); +void zSaveLoad_DispatchCB(U32 dispatchEvent, const F32* toParam); +S32 xSGT_SaveInfoCB(void* vp, st_XSAVEGAME_DATA* xsgdata, S32* need, S32* most); +S32 xSGT_SaveProcCB(void* vp, st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt); +S32 xSGT_SaveInfoPrefsCB(void* p1, st_XSAVEGAME_DATA* data, S32* i, S32* j); +S32 xSGT_SaveProcPrefsCB(void* vp, st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_WRITECONTEXT* wctxt); +S32 xSGT_LoadLoadCB(void* vp, st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, + U32 ui, S32 i); +S32 xSGT_LoadPrefsCB(void* vp, st_XSAVEGAME_DATA* xsgdata, st_XSAVEGAME_READCONTEXT* rctxt, + U32 ui, S32 i); +U32 zSaveLoad_slotIsEmpty(U32 slot); + +#endif