diff --git a/src/SB/Core/gc/iColor.h b/src/SB/Core/gc/iColor.h index d7b0baf3..c01e8ba4 100644 --- a/src/SB/Core/gc/iColor.h +++ b/src/SB/Core/gc/iColor.h @@ -9,6 +9,15 @@ struct iColor_tag 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/iMorph.h b/src/SB/Core/gc/iMorph.h index 292a0ab7..a3b03333 100644 --- a/src/SB/Core/gc/iMorph.h +++ b/src/SB/Core/gc/iMorph.h @@ -1,4 +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/x/xDebug.cpp b/src/SB/Core/x/xDebug.cpp index 7a091e4c..1d0a099b 100644 --- a/src/SB/Core/x/xDebug.cpp +++ b/src/SB/Core/x/xDebug.cpp @@ -1,18 +1,20 @@ #include "xDebug.h" +#include "xFont.h" + +#include "iColor.h" #include U32 gFrameCount; -extern F32 _781; // 0.0020833334f. -extern F32 _783; // 0.0015625f. +// Remaining weak definitions will match once referenced e.g. iColor_tag::operator= void xprintf(const char* msg, ...) { // Redacted. :} } -S32 xDebugModeAdd(char* mode, void(*debugFunc)) +S32 xDebugModeAdd(const char* mode, void(*debugFunc)()) { // Redacted. :} return -1; @@ -45,10 +47,10 @@ void xtextbox::render(bool cache) const F32 NSCREENY(F32 scale) { - return _781 * scale; + return (1.0f / 480) * scale; } F32 NSCREENX(F32 scale) { - return _783 * scale; -} + return (1.0f / 640) * scale; +} \ No newline at end of file diff --git a/src/SB/Core/x/xFont.h b/src/SB/Core/x/xFont.h index fcd228a0..055fa11f 100644 --- a/src/SB/Core/x/xFont.h +++ b/src/SB/Core/x/xFont.h @@ -32,6 +32,23 @@ struct xfont 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 diff --git a/src/SB/Core/x/xMorph.cpp b/src/SB/Core/x/xMorph.cpp index 2c9775b1..ad2f91bc 100644 --- a/src/SB/Core/x/xMorph.cpp +++ b/src/SB/Core/x/xMorph.cpp @@ -1,3 +1,122 @@ #include "xMorph.h" -#include +#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 index 7439a9f4..3ee24ac1 100644 --- a/src/SB/Core/x/xMorph.h +++ b/src/SB/Core/x/xMorph.h @@ -1,4 +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 index 07d88fbf..9a52c740 100644 --- a/src/SB/Core/x/xMovePoint.cpp +++ b/src/SB/Core/x/xMovePoint.cpp @@ -68,6 +68,42 @@ void xMovePointSplineDestroy(xMovePoint* m) } } +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 0 // 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 @@ -138,7 +174,7 @@ F32 xMovePointGetNext(xMovePoint* m, xMovePoint* prev, xMovePoint** next, xVec3* } #endif -xVec3* xMovePointGetPos(xMovePoint* m) +xVec3* xMovePointGetPos(const xMovePoint* m) { return m->pos; } diff --git a/src/SB/Core/x/xPad.cpp b/src/SB/Core/x/xPad.cpp index ab40ef46..2fddb945 100644 --- a/src/SB/Core/x/xPad.cpp +++ b/src/SB/Core/x/xPad.cpp @@ -54,6 +54,38 @@ void xPadRumbleEnable(S32 idx, S32 enable) } } +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(); diff --git a/src/SB/Core/x/xPad.h b/src/SB/Core/x/xPad.h index aaf97dbf..c4ef619f 100644 --- a/src/SB/Core/x/xPad.h +++ b/src/SB/Core/x/xPad.h @@ -108,4 +108,6 @@ 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/xRenderState.cpp b/src/SB/Core/x/xRenderState.cpp index 93f4fedd..4a17ae24 100644 --- a/src/SB/Core/x/xRenderState.cpp +++ b/src/SB/Core/x/xRenderState.cpp @@ -1,6 +1,9 @@ #include "xRenderState.h" -extern int sBlendTable[11]; +static int sBlendTable[11] = +{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +}; void xRenderStateSetTexture(RwTexture* texture) { diff --git a/src/SB/Core/x/xSpline.h b/src/SB/Core/x/xSpline.h index dfbe0e17..50a103e4 100644 --- a/src/SB/Core/x/xSpline.h +++ b/src/SB/Core/x/xSpline.h @@ -31,4 +31,7 @@ struct xSpline3 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/xTimer.cpp b/src/SB/Core/x/xTimer.cpp index 7d836d57..7383cb63 100644 --- a/src/SB/Core/x/xTimer.cpp +++ b/src/SB/Core/x/xTimer.cpp @@ -34,6 +34,22 @@ 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; diff --git a/src/SB/Game/zMusic.cpp b/src/SB/Game/zMusic.cpp index cddb8c58..12122893 100644 --- a/src/SB/Game/zMusic.cpp +++ b/src/SB/Game/zMusic.cpp @@ -114,8 +114,6 @@ void zMusicInit() volume_reset(); } -// WIP. -#ifdef NON_MATCHING // Correct, but won't work due to the switch case jump table (messes with offsets) S32 getCurrLevelMusicEnum() { @@ -183,7 +181,6 @@ S32 getCurrLevelMusicEnum() return snd_enum; } -#endif #if 0 // Probably floating point memes idk