diff --git a/src/SB/Core/x/xCM.cpp b/src/SB/Core/x/xCM.cpp index 49d8e1cff..c4a8984cb 100644 --- a/src/SB/Core/x/xCM.cpp +++ b/src/SB/Core/x/xCM.cpp @@ -1,3 +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 index 5062a5d20..e0ceb582a 100644 --- a/src/SB/Core/x/xCM.h +++ b/src/SB/Core/x/xCM.h @@ -2,6 +2,7 @@ #define XCM_H #include +#include "xColor.h" #include "xBase.h" struct xCreditsData @@ -9,8 +10,87 @@ 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();