diff --git a/configure.py b/configure.py index e03a1124..76728dc5 100755 --- a/configure.py +++ b/configure.py @@ -165,7 +165,7 @@ LIBS = [ "MetroidPrime/CDecalManager", "MetroidPrime/ScriptObjects/CScriptSpiderBallWaypoint", "MetroidPrime/Enemies/CBloodFlower", - "MetroidPrime/TGameTypes", + ["MetroidPrime/TGameTypes", True], "MetroidPrime/CPhysicsActor", ["MetroidPrime/CPhysicsState", True], "MetroidPrime/CRipple", diff --git a/include/Kyoto/Streams/CInputStream.hpp b/include/Kyoto/Streams/CInputStream.hpp index 99640a1e..30c0be8a 100644 --- a/include/Kyoto/Streams/CInputStream.hpp +++ b/include/Kyoto/Streams/CInputStream.hpp @@ -27,7 +27,7 @@ public: void Get(void* dest, unsigned long len); template < typename T > - inline T Get(const TType< T >& type) { + inline T Get(const TType< T >& type = TType()) { return cinput_stream_helper(type, *this); } diff --git a/include/MetroidPrime/CArchitectureQueue.hpp b/include/MetroidPrime/CArchitectureQueue.hpp index 41f16009..e44e40ad 100644 --- a/include/MetroidPrime/CArchitectureQueue.hpp +++ b/include/MetroidPrime/CArchitectureQueue.hpp @@ -9,7 +9,9 @@ class CArchitectureQueue { public: - void Push(const CArchitectureMessage&); // TODO + bool Push(const CArchitectureMessage& msg) { + x0_queue.push_back(msg); + } void Pop(); // TODO void Clear(); // TODO bool IsEmpty() const; // TODO diff --git a/include/MetroidPrime/CInputGenerator.hpp b/include/MetroidPrime/CInputGenerator.hpp index b6d81eb8..35c1f58a 100644 --- a/include/MetroidPrime/CInputGenerator.hpp +++ b/include/MetroidPrime/CInputGenerator.hpp @@ -9,11 +9,12 @@ class COsContext; class IController; +class CArchitectureQueue; class CInputGenerator { public: - CInputGenerator(COsContext*, float, float); - + CInputGenerator(COsContext*, float leftDiv, float rightDiv); + bool Update(float dt, CArchitectureQueue& queue); IController* GetController() const { return x4_controller.get(); } private: diff --git a/include/MetroidPrime/Decode.hpp b/include/MetroidPrime/Decode.hpp index 0720e672..e01429a2 100644 --- a/include/MetroidPrime/Decode.hpp +++ b/include/MetroidPrime/Decode.hpp @@ -1,6 +1,7 @@ #ifndef _DECODE #define _DECODE +#include "MetroidPrime/CArchitectureMessage.hpp" #include "MetroidPrime/CArchMsgParmInt32.hpp" #include "MetroidPrime/CArchMsgParmInt32Int32VoidPtr.hpp" #include "MetroidPrime/CArchMsgParmNull.hpp" @@ -9,6 +10,10 @@ #include "MetroidPrime/CArchMsgParmControllerStatus.hpp" namespace MakeMsg { + CArchitectureMessage CreateControllerStatus(EArchMsgTarget target, ushort chan, bool connected); + + CArchitectureMessage CreateUserInput(EArchMsgTarget target, const CFinalInput& input); + const CArchMsgParmReal32& GetParmTimerTick(const CArchitectureMessage& msg); } diff --git a/include/MetroidPrime/TGameTypes.hpp b/include/MetroidPrime/TGameTypes.hpp index df204203..e5757d21 100644 --- a/include/MetroidPrime/TGameTypes.hpp +++ b/include/MetroidPrime/TGameTypes.hpp @@ -10,9 +10,9 @@ struct TAreaId; struct TEditorId; struct TUniqueId; -extern TAreaId kInvalidAreaId; -extern TEditorId kInvalidEditorId; -extern TUniqueId kInvalidUniqueId; +extern const TAreaId kInvalidAreaId; +extern const TEditorId kInvalidEditorId; +extern const TUniqueId kInvalidUniqueId; struct TAreaId { int value; diff --git a/include/WorldFormat/CWorldLight.hpp b/include/WorldFormat/CWorldLight.hpp new file mode 100644 index 00000000..964b5d7c --- /dev/null +++ b/include/WorldFormat/CWorldLight.hpp @@ -0,0 +1,42 @@ +#ifndef _CWORLDLIGHT +#define _CWORLDLIGHT + + +#include "Kyoto/Math/CVector3f.hpp" +#include "Kyoto/Graphics/CLight.hpp" + +class CInputStream; +class CWorldLight { + static const CVector3f kDefaultPosition; + static const CVector3f kDefaultDirection; +public: + + enum EWorldLightType { + kWLT_LocalAmbient, + kWLT_Directional, + kWLT_Custom, + kWLT_Spot, + kWLT_Spot2, + kWLT_LocalAmbient2, + }; + + CWorldLight(CInputStream& in); + + + CLight GetAsCGraphicsLight() const; +public: + EWorldLightType x0_type; + CVector3f x4_color; + CVector3f x10_position; + CVector3f x1c_direction; + float x28_q; + float x2c_cutoffAngle; + float x30_; + bool x34_castShadows; + float x38_; + EFalloffType x3c_falloff; + float x40_; +}; + + +#endif // _CWORLDLIGHT diff --git a/obj_files.mk b/obj_files.mk index 2eef5269..2477b3d8 100644 --- a/obj_files.mk +++ b/obj_files.mk @@ -132,7 +132,7 @@ METROIDPRIME :=\ $(BUILD_DIR)/asm/MetroidPrime/CDecalManager.o\ $(BUILD_DIR)/asm/MetroidPrime/ScriptObjects/CScriptSpiderBallWaypoint.o\ $(BUILD_DIR)/asm/MetroidPrime/Enemies/CBloodFlower.o\ - $(BUILD_DIR)/asm/MetroidPrime/TGameTypes.o\ + $(BUILD_DIR)/src/MetroidPrime/TGameTypes.o\ $(BUILD_DIR)/asm/MetroidPrime/CPhysicsActor.o\ $(BUILD_DIR)/src/MetroidPrime/CPhysicsState.o\ $(BUILD_DIR)/asm/MetroidPrime/CRipple.o\ diff --git a/src/MetroidPrime/CInputGenerator.cpp b/src/MetroidPrime/CInputGenerator.cpp new file mode 100644 index 00000000..b47c4245 --- /dev/null +++ b/src/MetroidPrime/CInputGenerator.cpp @@ -0,0 +1,52 @@ +#include "MetroidPrime/CInputGenerator.hpp" + +#include "MetroidPrime/CArchitectureQueue.hpp" +#include "MetroidPrime/Decode.hpp" + +#include "Kyoto/Basics/COsContext.hpp" +CInputGenerator::CInputGenerator(COsContext* ctx, float leftDiv, float rightDiv) +: x0_context(ctx) +, x4_controller(IController::Create(*ctx)) +, xc_leftDiv(leftDiv) +, x10_rightDiv(rightDiv) { + for (uint i = 0; i <= kIOP_Player4; ++i) { + x8_connectedControllers[i] = false; + } +} +bool CInputGenerator::Update(float dt, CArchitectureQueue& queue) { + bool ret; + if (!x0_context->Update()) { + ret = false; + } else { + int availSlot = 0; + bool firstController = false; + if (!x4_controller.null()) { + x4_controller->Poll(); + for (int i = 0; i < x4_controller->GetDeviceCount(); ++i) { + if (i == 0) { + firstController = true; + } + + CControllerGamepadData cont = x4_controller->GetGamepadData(i); + if (cont.DeviceIsPresent()) { + queue.Push(MakeMsg::CreateUserInput(kAMT_Game, + CFinalInput(i, dt, cont, xc_leftDiv, x10_rightDiv))); + ++availSlot; + } + + if (x8_connectedControllers[i] != cont.DeviceIsPresent()) { + queue.Push(MakeMsg::CreateControllerStatus(kAMT_Game, i, cont.DeviceIsPresent())); + x8_connectedControllers[i] = cont.DeviceIsPresent(); + } + } + } + + if (firstController) { + queue.Push(MakeMsg::CreateUserInput(kAMT_Game, CFinalInput(availSlot, dt, *x0_context))); + } else { + queue.Push(MakeMsg::CreateUserInput(kAMT_Game, CFinalInput(0, dt, *x0_context))); + } + ret = true; + } + return ret; +} diff --git a/src/MetroidPrime/TGameTypes.cpp b/src/MetroidPrime/TGameTypes.cpp new file mode 100644 index 00000000..04a75b20 --- /dev/null +++ b/src/MetroidPrime/TGameTypes.cpp @@ -0,0 +1,12 @@ +#include "MetroidPrime/TGameTypes.hpp" +#include "Kyoto/Streams/CInputStream.hpp" + +const TEditorId kInvalidEditorId = TEditorId(-1); +const TUniqueId kInvalidUniqueId = TUniqueId(-1, -1); +const TAreaId kInvalidAreaId = TAreaId(-1); +const TEditorId kUnkId = TEditorId(-1); + + + +TEditorId::TEditorId(CInputStream& in) +: value(in.Get()) {} diff --git a/src/WorldFormat/CWorldLight.cpp b/src/WorldFormat/CWorldLight.cpp new file mode 100644 index 00000000..76073844 --- /dev/null +++ b/src/WorldFormat/CWorldLight.cpp @@ -0,0 +1,59 @@ +#include "WorldFormat/CWorldLight.hpp" + +#include "Kyoto/Streams/CInputStream.hpp" +#include +#include + +const CVector3f CWorldLight::kDefaultPosition = CVector3f(0.f, 0.f, 0.f); +FORCEPADDING(sizeof(CVector3f)) kPadding; +const CVector3f CWorldLight::kDefaultDirection = CVector3f(0.f, 1.f, 0.f); + +CWorldLight::CWorldLight(CInputStream& in) +: x0_type((EWorldLightType)in.Get< uint >()) +, x4_color(in) +, x10_position(in) +, x1c_direction(in) +, x28_q(in.Get< float >()) +, x2c_cutoffAngle(in.Get< float >()) +, x30_(in.Get< float >()) +, x34_castShadows(in.Get< bool >()) +, x38_(in.Get< float >()) +, x3c_falloff((EFalloffType)in.Get< uint >()) +, x40_(in.Get< float >()) {} + +CLight CWorldLight::GetAsCGraphicsLight() const { + float R = x4_color.GetX(); + float G = x4_color.GetY(); + float B = x4_color.GetZ(); + CColor color(R, G, B); + + float q = x28_q < FLT_EPSILON ? 0.000001f : x28_q; + if (x0_type == kWLT_LocalAmbient) { + R *= q; + G *= q; + B *= q; + + R = rstl::min_val(1.f, R); + G = rstl::min_val(1.f, G); + B = rstl::min_val(1.f, B); + return CLight::BuildLocalAmbient(x10_position, CColor(R, G, B)); + } + if (x0_type == kWLT_Directional) { + return CLight::BuildDirectional(x10_position, color); + } + if (x0_type == kWLT_Spot) { + CLight light = + CLight::BuildSpot(x10_position, x1c_direction.AsNormalized(), color, x2c_cutoffAngle * .5f); + float quadratic = x3c_falloff == kFT_Quadratic ? (25000.0f / q) : 0.f; + float linear = x3c_falloff == kFT_Linear ? (250.f / q) : 0.f; + float constant = x3c_falloff == kFT_Constant ? (2.0f / q) : 0.f; + + light.SetAttenuation(constant, linear, quadratic); + return light; + } + float quadratic = x3c_falloff == kFT_Quadratic ? (25000.0f / q) : 0.f; + float linear = x3c_falloff == kFT_Linear ? (250.f / q) : 0.f; + float constant = x3c_falloff == kFT_Constant ? (2.0f / q) : 0.f; + return CLight::BuildCustom(x10_position, CVector3f(1.f, 0.f, 0.f), color, constant, linear, + quadratic, 1.f, 0.f, 0.f); +}