diff --git a/src/SB/Core/gc/iMix.c b/src/SB/Core/gc/iMix.c index c4e123ac0..a8e02bd91 100644 --- a/src/SB/Core/gc/iMix.c +++ b/src/SB/Core/gc/iMix.c @@ -230,8 +230,8 @@ void MIXInit() __MIXSoundMode = OSGetSoundMode(); } -void MIXInitChannel(S32 param_1, U32 param_2, S32 param_3, S32 param_4, S32 param_5, - S32 param_6, S32 param_7, S32 param_8) +void MIXInitChannel(S32 param_1, U32 param_2, S32 param_3, S32 param_4, S32 param_5, S32 param_6, + S32 param_7, S32 param_8) { struct MIXChannel* chan = &__MIXChannel[*(S32*)((S32)param_1 + 0x18)]; @@ -271,8 +271,7 @@ void MIXInitChannel(S32 param_1, U32 param_2, S32 param_3, S32 param_4, S32 para { *(U16*)(&chan->data[0x12]) = __MIXGetVolume(chan->data[3] + chan->data[10]); *(U16*)(&chan->data[0x13]) = __MIXGetVolume(chan->data[3] + chan->data[10]); - *(U16*)(&chan->data[0x14]) = - __MIXGetVolume(chan->data[3] + chan->data[11] - 0x3c); + *(U16*)(&chan->data[0x14]) = __MIXGetVolume(chan->data[3] + chan->data[11] - 0x3c); } else { @@ -288,8 +287,7 @@ void MIXInitChannel(S32 param_1, U32 param_2, S32 param_3, S32 param_4, S32 para { *(U16*)(&chan->data[0x15]) = __MIXGetVolume(chan->data[4] + chan->data[10]); *(U16*)(&chan->data[0x16]) = __MIXGetVolume(chan->data[4] + chan->data[10]); - *(U16*)(&chan->data[0x17]) = - __MIXGetVolume(chan->data[4] + chan->data[11] - 0x3c); + *(U16*)(&chan->data[0x17]) = __MIXGetVolume(chan->data[4] + chan->data[11] - 0x3c); } else { @@ -305,10 +303,8 @@ void MIXInitChannel(S32 param_1, U32 param_2, S32 param_3, S32 param_4, S32 para case 1: case 2: - *(U16*)(&chan->data[0xf]) = - __MIXGetVolume(chan->data[7] + chan->data[8] + chan->data[10]); - *(U16*)(&chan->data[0x10]) = - __MIXGetVolume(chan->data[7] + chan->data[9] + chan->data[10]); + *(U16*)(&chan->data[0xf]) = __MIXGetVolume(chan->data[7] + chan->data[8] + chan->data[10]); + *(U16*)(&chan->data[0x10]) = __MIXGetVolume(chan->data[7] + chan->data[9] + chan->data[10]); *(U16*)(&chan->data[0x11]) = __MIXGetVolume(chan->data[7] + chan->data[11]); if ((chan->data[1] & 1) != 0) @@ -317,8 +313,7 @@ void MIXInitChannel(S32 param_1, U32 param_2, S32 param_3, S32 param_4, S32 para __MIXGetVolume(chan->data[3] + chan->data[8] + chan->data[10]); *(U16*)(&chan->data[0x13]) = __MIXGetVolume(chan->data[3] + chan->data[9] + chan->data[10]); - *(U16*)(&chan->data[0x14]) = - __MIXGetVolume(chan->data[3] + chan->data[11] + -0x3c); + *(U16*)(&chan->data[0x14]) = __MIXGetVolume(chan->data[3] + chan->data[11] + -0x3c); } else { @@ -335,8 +330,7 @@ void MIXInitChannel(S32 param_1, U32 param_2, S32 param_3, S32 param_4, S32 para __MIXGetVolume(chan->data[4] + chan->data[8] + chan->data[10]); *(U16*)(&chan->data[0x16]) = __MIXGetVolume(chan->data[4] + chan->data[9] + chan->data[10]); - *(U16*)(&chan->data[0x17]) = - __MIXGetVolume(chan->data[4] + chan->data[11] + -0x3c); + *(U16*)(&chan->data[0x17]) = __MIXGetVolume(chan->data[4] + chan->data[11] + -0x3c); } else { @@ -350,14 +344,10 @@ void MIXInitChannel(S32 param_1, U32 param_2, S32 param_3, S32 param_4, S32 para break; case 3: - *(U16*)(&chan->data[15]) = - __MIXGetVolume(chan->data[7] + chan->data[8] + chan->data[10]); - *(U16*)(&chan->data[16]) = - __MIXGetVolume(chan->data[7] + chan->data[9] + chan->data[10]); - *(U16*)(&chan->data[21]) = - __MIXGetVolume(chan->data[7] + chan->data[12] + chan->data[11]); - *(U16*)(&chan->data[22]) = - __MIXGetVolume(chan->data[7] + chan->data[13] + chan->data[11]); + *(U16*)(&chan->data[15]) = __MIXGetVolume(chan->data[7] + chan->data[8] + chan->data[10]); + *(U16*)(&chan->data[16]) = __MIXGetVolume(chan->data[7] + chan->data[9] + chan->data[10]); + *(U16*)(&chan->data[21]) = __MIXGetVolume(chan->data[7] + chan->data[12] + chan->data[11]); + *(U16*)(&chan->data[22]) = __MIXGetVolume(chan->data[7] + chan->data[13] + chan->data[11]); if ((chan->data[1] & 1) != 0) { @@ -388,8 +378,7 @@ void MIXInitChannel(S32 param_1, U32 param_2, S32 param_3, S32 param_4, S32 para int enabled = OSDisableInterrupts(); - *(U16*)((S32)param_1 + 0x19c) = - *(U16*)(&chan->data[0xe]); + *(U16*)((S32)param_1 + 0x19c) = *(U16*)(&chan->data[0xe]); *(U16*)((S32)param_1 + 0x19e) = 0; if ((*(U16*)((S32)param_1 + 0x14a) = *(U16*)(&chan->data[0xf]))) { @@ -496,4 +485,4 @@ S32 MIXGetFader(S32* param_1) { S32* handle = &__MIXChannel[*(param_1 + 6)].data[0]; return handle[7]; -} \ No newline at end of file +} diff --git a/src/SB/Core/gc/iSystem.cpp b/src/SB/Core/gc/iSystem.cpp index 967189b30..6f33000d3 100644 --- a/src/SB/Core/gc/iSystem.cpp +++ b/src/SB/Core/gc/iSystem.cpp @@ -62,6 +62,70 @@ U16 my_dsc(U16 dsc) return dsc; } +void FloatingPointErrorHandler(U16 last, OSContext* ctxt, U64 unk1, U64 unk2) +{ + U32 uVar2; + uVar2 = (ctxt->fpscr) & 0xf8 << 0x16 | 0x1f80700; + if ((uVar2 & 0x20000000) != 0) + { + OSReport("FPE: Invalid operation: "); + + if ((uVar2 & 0x1000000) != 0) + { + OSReport("SNaN\n"); + } + if ((uVar2 & 0x800000) != 0) + { + OSReport("Infinity - Infinity\n"); + } + if ((uVar2 & 0x400000) != 0) + { + OSReport("Infinity / Infinity\n"); + } + if ((uVar2 & 0x200000) != 0) + { + OSReport("0 / 0\n"); + } + if ((uVar2 & 0x100000) != 0) + { + OSReport("Infinity * 0\n"); + } + if ((uVar2 & 0x80000) != 0) + { + OSReport("Invalid compare\n"); + } + if ((uVar2 & 0x400) != 0) + { + OSReport("Software request\n"); + } + if ((uVar2 & 0x200) != 0) + { + OSReport("Invalid square root\n"); + } + if ((uVar2 & 0x100) != 0) + { + OSReport("Invalid integer convert\n"); + } + } + if ((uVar2 & 0x10000000) != 0) + { + OSReport("FPE: Overflow\n"); + } + if ((uVar2 & 0x8000000) != 0) + { + OSReport("FPE: Underflow\n"); + } + if ((uVar2 & 0x4000000) != 0) + { + OSReport("FPE: Zero division\n"); + } + if ((uVar2 & 0x2000000) != 0) + { + OSReport("FPE: Inexact result\n"); + } + ctxt->srr0 = ctxt->srr0 + 4; +} + void MemoryProtectionErrorHandler(U16 last, OSContext* ctx, U64 unk1, U64 unk2) { last_error = last; diff --git a/src/SB/Core/gc/iSystem.h b/src/SB/Core/gc/iSystem.h index 83191f2a5..f0c620a86 100644 --- a/src/SB/Core/gc/iSystem.h +++ b/src/SB/Core/gc/iSystem.h @@ -21,6 +21,7 @@ U16 my_dsc(U16 dsc); void iSystemInit(U32 options); void iSystemExit(); void MemoryProtectionErrorHandler(U16 last, OSContext* ctx, U64 unk1, U64 unk2); +void FloatingPointErrorHandler(U16 last, OSContext* ctxt, U64 unk1, U64 unk2); void TRCInit(); void null_func(); diff --git a/src/SB/Core/x/containers.h b/src/SB/Core/x/containers.h index ff9688cb8..befdffb6f 100644 --- a/src/SB/Core/x/containers.h +++ b/src/SB/Core/x/containers.h @@ -51,6 +51,7 @@ template struct fixed_queue void reset(); void push_front(const T& element); + void push_back(); bool full() const; void pop_back(); bool empty() const; diff --git a/src/SB/Core/x/xScrFx.cpp b/src/SB/Core/x/xScrFx.cpp index deb113982..2d14f9efb 100644 --- a/src/SB/Core/x/xScrFx.cpp +++ b/src/SB/Core/x/xScrFx.cpp @@ -2,6 +2,145 @@ #include +U8 g_debugRenderSafeArea; + +static F32 mLetterboxO; +static F32 mLetterboxTO; +static F32 sLetterBoxSize; +static U8 sLetterBoxAlpha = 255; +F32 sFullScreenGlareIntensity; // Needs to be initialized + +static _xFadeData mFade; +xGlare sGlare[10]; + +extern RwGlobals* RwEngineInstance; +extern RwInt32 RwEngineGetCurrentVideoMode(void); +extern RwVideoMode* RwEngineGetVideoModeInfo(RwVideoMode* modeinfo, RwInt32 modeIndex); + +void xScrFxInit() +{ + xScrFxFadeInit(); + xScrFxLetterBoxInit(); + xScrFXGlareInit(); + iScrFxInit(); +} + +void xScrFxReset() +{ + xScrFXGlareReset(); +} + +void xScrFxUpdate(RwCamera* cam, F32 dt) +{ + iScrFxBegin(); + xScrFxUpdateFade(cam, dt); + xScrFxUpdateLetterBox(cam, dt); + xScrFXGlareUpdate(dt); + xScrFxDistortionUpdate(dt); +} + +void xScrFxRender(RwCamera* cam) +{ + iScrFxBegin(); + xScrFxDistortionRender((RwCamera*)RwEngineInstance->curCamera); + if (g_debugRenderSafeArea != '\0') + { + xScrFxDrawSafeArea(); + } + iScrFxEnd(); +} + +void xScrFxDrawScreenSizeRectangle() +{ + // I honestly dont know how to complete this function + // FIXME: First 2 params of xScrFxDrawBox seem to be correct + // The rest of them confuse me. + + RwVideoMode video_mode; + + F32 x2 = 0; + F32 y2 = 0; + U8 red = 0; + U8 green = 0; + U8 blue = 0; + U8 alpha = 255; + F32 ushift = 0; + F32 vshift = 0; + + S32 mode = RwEngineGetCurrentVideoMode(); + RwEngineGetVideoModeInfo(&video_mode, mode); + xScrFxDrawBox((F32)video_mode.width, (F32)video_mode.height, x2, y2, red, green, blue, alpha, + ushift, vshift); +} + +void xScrFxFadeInit() +{ + memset(&mFade, 0, 0x1c); +} + +void InterpCol(F32 unk, U8 unk1, U8 unk2) +{ +} + +void xScrFxFade(iColor_tag* base, iColor_tag* dest, F32 seconds, void (*callback)(), S32 hold) +{ + mFade.active = 1; + base->operator=(*(iColor_tag*)dest); +} + +void xScrFxStopFade() +{ + mFade.active = 0; +} + +S32 xScrFxIsFading() +{ + return mFade.active; +} + +void xScrFxLetterBoxInit() +{ + mLetterboxO = 0.0f; + mLetterboxTO = 0.0f; +} + +void xScrFxLetterboxReset() +{ + mLetterboxO = 0.0f; + mLetterboxTO = 0.0f; +} + +void xScrFxLetterBoxSetSize(F32 size) +{ + sLetterBoxSize = size; +} + +void xScrFxLetterBoxSetAlpha(U8 alpha) +{ + sLetterBoxAlpha = alpha; +} + +void xScrFxLetterbox(S32 enable) +{ + if (zMenuRunning() != 0) + { + enable = 0; + } + if (enable != 0) + { + mLetterboxTO = sLetterBoxSize; + } + else + { + mLetterboxTO = 0.0f; + } +} + +S32 xScrFxIsLetterbox() +{ + return (((mLetterboxTO > 0.0f) << 2) << 0x1c) >> 0x1e; +} + void xScrFxDistortionAdd(xVec3*, xVec3*, S32) { } @@ -9,3 +148,17 @@ void xScrFxDistortionAdd(xVec3*, xVec3*, S32) void xScrFxDistortionRender(RwCamera*) { } + +void xScrFXGlareInit() +{ + sGlare->flags = 0; + for (S32 i = 1; i < 10; i++) + { + sGlare[i].flags = 0; + } +} + +void xScrFXGlareReset() +{ + xScrFXGlareInit(); +} diff --git a/src/SB/Core/x/xScrFx.h b/src/SB/Core/x/xScrFx.h index 6760b961b..b550c3152 100644 --- a/src/SB/Core/x/xScrFx.h +++ b/src/SB/Core/x/xScrFx.h @@ -3,24 +3,67 @@ #include "xCamera.h" #include "iColor.h" +#include "iScrFX.h" +#include "zMenu.h" #include +#include -void xScrFxInit (); -void xScrFxLetterBoxSetSize(F32); -void xScrFxLetterBoxSetAlpha(U8); +struct _xFadeData +{ + S32 active; // offset 0x0, size 0x4 + S32 hold; // offset 0x4, size 0x4 + iColor_tag src; // offset 0x8, size 0x4 + iColor_tag dest; // offset 0xC, size 0x4 + F32 time_passed; // offset 0x10, size 0x4 + F32 time_total; // offset 0x14, size 0x4 + void (*cb)(); // offset 0x18, size 0x4 +}; + +struct xGlare +{ + S32 flags; // offset 0x0, size 0x4 + xVec3 pos; // offset 0x4, size 0xC + F32 intensity; // offset 0x10, size 0x4 + F32 intensityFadeRate; // offset 0x14, size 0x4 + F32 lifetime; // offset 0x18, size 0x4 + F32 size; // offset 0x1C, size 0x4 + RwRGBAReal col; // offset 0x20, size 0x10 + RwRaster* raster; // offset 0x30, size 0x4 +}; + +void xScrFxInit(); +void xScrFxReset(); 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 xScrFxFadeInit(); +void InterpCol(F32, U8, U8); +void xScrFxFade(iColor_tag* base, iColor_tag* dest, F32 seconds, void (*callback)(), S32 hold); +void xScrFxStopFade(); +S32 xScrFxIsFading(); +void xScrFxUpdateFade(F32 seconds); +void xScrFxUpdateFade(RwCamera* cam, F32 seconds); +void xScrFxLetterBoxInit(); void xScrFxLetterboxReset(); -S32 xScrFXGlareAdd(xVec3* pos, F32 life, F32 intensity, F32 size, F32 r, - F32 g, F32 b, F32 a, RwRaster* raster); +void xScrFxLetterBoxSetSize(F32); +void xScrFxLetterBoxSetAlpha(U8); +void xScrFxLetterbox(S32 enable); +void xScrFxUpdateLetterBox(F32 seconds); +void xScrFxUpdateLetterBox(RwCamera* cam, F32 seconds); +S32 xScrFxIsLetterbox(); +void xScrFxDrawSafeArea(); +void xScrFxDistortionAdd(xVec3*, xVec3*, S32); +static void xScrFxDistortionUpdate(F32 dt); +static void xScrFxDistortionRender(RwCamera*); +void xScrFXGlareInit(); +void xScrFXGlareReset(); +S32 xScrFXGlareAdd(xVec3* pos, F32 life, F32 intensity, F32 size, F32 r, F32 g, F32 b, F32 a, + RwRaster* raster); +void xScrFXGlareUpdate(F32); // Return type may be wrong, Not in dwarf void xScrFXFullScreenGlareRender(); void xScrFXGlareRender(xCamera* cam); -void xScrFxLetterbox(S32 enable); -void xScrFxReset(); +void xScrFxDrawBox(F32 x1, F32 y1, F32 x2, F32 y2, U8 red, U8 green, U8 blue, U8 alpha, F32 ushift, + F32 vshift); #endif diff --git a/src/SB/Game/zMenu.h b/src/SB/Game/zMenu.h index 94efeea52..30a2cac3c 100644 --- a/src/SB/Game/zMenu.h +++ b/src/SB/Game/zMenu.h @@ -3,6 +3,7 @@ #include +S32 zMenuRunning(); U32 zMenuUpdateMode(); U32 zMenuIsPaused(); S32 zMenuLoopContinue(); diff --git a/src/SB/Game/zTalkBox.cpp b/src/SB/Game/zTalkBox.cpp index bb168d7bc..96c1c8c6b 100644 --- a/src/SB/Game/zTalkBox.cpp +++ b/src/SB/Game/zTalkBox.cpp @@ -5,23 +5,102 @@ namespace { - struct SharedTalkboxState - { - void* padding[2]; // FIXME: variables not verified - ztalkbox* active; - U8 unkC[0x8D48 - 0xC]; - U32 unk8D48; - U8 unk8D4C[0x8D78 - 0x8D4C]; - U8 unk8D78; - U8 unk8D79; - U8 unk8D7A; - }; // size: 0x8E9C? - - SharedTalkboxState shared; + shared_type shared; void stop_audio_effect(); - void deactivate() { + void speak_stop() + { + if (shared.speak_npc != NULL) + { + shared.speak_npc->SpeakStop(); + shared.speak_npc = NULL; + } + + if (shared.speak_player != 0) + { + zEntPlayerSpeakStop(); + shared.speak_player = 0; + } + } + + static void trigger(U32 event) + { + // shared.delay_events = 0; // -0x7286 + // shared.triggered._first = 0; // -0x7280 + + if (shared.delay_events == 0) + { + zEntEvent(shared.active, shared.active, event); + } + else + { + shared.triggered.push_back(); + } + } + + void trigger_pads(U32 pressed) + { + if ((pressed & 0x10) != 0) + { + trigger(73); + } + if ((pressed & 0x40) != 0) + { + trigger(74); + } + if ((pressed & 0x80) != 0) + { + trigger(76); + } + if ((pressed & 0x20) != 0) + { + trigger(75); + } + if ((pressed & 1) != 0) + { + trigger(71); + } + if ((pressed & 2) != 0) + { + trigger(72); + } + if ((pressed & 0x1000) != 0) + { + trigger(69); + } + if ((pressed & 0x2000) != 0) + { + trigger(70); + } + if ((pressed & 0x100) != 0) + { + trigger(67); + } + if ((pressed & 0x200) != 0) + { + trigger(68); + } + if ((pressed & 0x10000) != 0) + { + trigger(63); + } + if ((pressed & 0x20000) != 0) + { + trigger(65); + } + if ((pressed & 0x40000) != 0) + { + trigger(66); + } + if ((pressed & 0x80000) != 0) + { + trigger(64); + } + } + + void deactivate() + { stop_audio_effect(); ztalkbox* active = shared.active; @@ -46,91 +125,93 @@ namespace // Equivalent: see fixme S32 cb_dispatch(xBase*, xBase* to, U32 event, const F32* argf, xBase*) { - shared.unk8D7A = 1; + //shared.unk8D7A = 1; ztalkbox& talkbox = *(ztalkbox*)to; switch (event) { - case 10: - case 88: - talkbox.reset(); - break; - case 4: - case 504: - talkbox.hide(); - break; - case 3: - case 503: - talkbox.show(); - break; - case 335: { - U32 textID = ((U32*)argf == NULL) ? 0 : *(U32*)argf; - talkbox.start_talk(textID, NULL, NULL); - flush_triggered(); - break; + case 10: + case 88: + talkbox.reset(); + break; + case 4: + case 504: + talkbox.hide(); + break; + case 3: + case 503: + talkbox.show(); + break; + case 335: + { + U32 textID = ((U32*)argf == NULL) ? 0 : *(U32*)argf; + talkbox.start_talk(textID, NULL, NULL); + flush_triggered(); + break; + } + case 336: + talkbox.stop_talk(); + flush_triggered(); + break; + case 352: + if (argf == NULL) + { + stop_wait(talkbox, NULL, 0); + } + else + { + stop_wait(talkbox, argf, 4); + } + flush_triggered(); + break; + case 334: + if ((U32*)argf != NULL) + { + talkbox.set_text(*(U32*)argf); } - case 336: - talkbox.stop_talk(); - flush_triggered(); - break; - case 352: - if (argf == NULL) - { - stop_wait(talkbox, NULL, 0); - } - else - { - stop_wait(talkbox, argf, 4); - } - flush_triggered(); - break; - case 334: - if ((U32*)argf != NULL) - { - talkbox.set_text(*(U32*)argf); - } - break; - case 338: - if ((U32*)argf != NULL) - { - talkbox.add_text(*(U32*)argf); - } - break; - case 339: - talkbox.clear_text(); - break; - - // FIXME: Figure out the right no-op cases - case 75: - case 76: - case 342: - case 343: - case 344: - case 345: - case 346: - case 347: - case 348: - case 349: - case 350: - case 351: - case 353: - case 356: - case 357: - case 358: - case 359: - // case 452: - // case 453: - // case 454: - case 465: - case 466: - break; + break; + case 338: + if ((U32*)argf != NULL) + { + talkbox.add_text(*(U32*)argf); + } + break; + case 339: + talkbox.clear_text(); + break; + + // FIXME: Figure out the right no-op cases + case 75: + case 76: + case 342: + case 343: + case 344: + case 345: + case 346: + case 347: + case 348: + case 349: + case 350: + case 351: + case 353: + case 356: + case 357: + case 358: + case 359: + // case 452: + // case 453: + // case 454: + case 465: + case 466: + break; } - shared.unk8D7A = 0; + //shared.unk8D7A = 0; return 1; } - char* load_text(U32 id) { + char* load_text(U32 id) + { if (id == 0) { return NULL; @@ -146,7 +227,7 @@ namespace // HACK return (char*)(asset) + 4; } -} +} // namespace void ztalkbox::load(const asset_type& tasset) { @@ -191,11 +272,33 @@ void ztalkbox::load(const asset_type& tasset) void ztalkbox::reset() { flag.visible = true; - if (shared.active == this) { + if (shared.active == this) + { deactivate(); } } +namespace +{ + + struct state_type + { + state_enum type; + + void start(); + void stop(); + }; + + void state_type::start() + { + } + + void state_type::stop() + { + } + +} // namespace + void ztalkbox::clear_text() { set_text((const char*)NULL); @@ -213,7 +316,7 @@ void ztalkbox::stop_wait(U32 unk) { if (shared.active == this) { - shared.unk8D48 |= unk; + //shared.unk8D48 |= unk; } } @@ -231,10 +334,10 @@ void ztalkbox::show() prompt_box->activate(); } - if (shared.unk8D78 != 0 && prompt.quit != 0 && quit_box != NULL) - { - quit_box->activate(); - } + // if (shared.unk8D78 != 0 && prompt.quit != 0 && quit_box != NULL) + // { + // quit_box->activate(); + // } } void ztalkbox::hide() @@ -256,3 +359,9 @@ ztalkbox* ztalkbox::get_active() { return shared.active; } + +void ztalkbox::permit(U32 add_flags, U32 remove_flags) +{ + shared.permit &= ~remove_flags; + shared.permit |= add_flags; +} diff --git a/src/SB/Game/zTalkBox.h b/src/SB/Game/zTalkBox.h index e7c75e60c..8f41492af 100644 --- a/src/SB/Game/zTalkBox.h +++ b/src/SB/Game/zTalkBox.h @@ -4,9 +4,29 @@ #include "zTextBox.h" #include "zNPCTypeCommon.h" #include "xIni.h" +#include "containers.h" +#include "zEntPlayer.h" #include "xScene.h" +enum state_enum +{ + STATE_INVALID = -1, + BEGIN_STATE = 0, + STATE_START = 1, + STATE_NEXT = 2, + STATE_WAIT = 3, + STATE_STOP = 4, + END_STATE = 5, + MAX_STATE = 5, +}; + +enum query_enum +{ + Q_SKIP, + Q_YESNO +}; + struct ztalkbox : xBase { struct asset_type : xDynAsset @@ -106,4 +126,155 @@ struct ztalkbox : xBase void hide(); }; +struct state_type +{ + state_enum type; +}; + +struct jot; + +struct callback +{ + void (*render)(jot&, xtextbox&, F32, F32); + void (*layout_update)(jot&, xtextbox&, xtextbox&); + void (*render_update)(jot&, xtextbox&, xtextbox&); +}; + +struct split_tag +{ + substr tag; + substr name; + substr action; + substr value; +}; + +struct tag_type +{ + substr name; + void (*parse_tag)(jot&, xtextbox&, xtextbox&, split_tag&); + void (*reset_tag)(jot&, xtextbox&, xtextbox&, split_tag&); + void* context; +}; + +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; + callback* cb; + tag_type* tag; + + void intersect_flags(const jot& other); + void reset_flags(); +}; + +struct jot_line +{ + basic_rect bounds; + F32 baseline; + U32 first; + U32 last; + U8 page_break; +}; + +struct layout +{ + xtextbox tb; // offset 0x0, size 0x68 + jot _jots[512]; // offset 0x68, size 0x7000 + U32 _jots_size; // offset 0x7068, size 0x4 + jot_line _lines[128]; // offset 0x706C, size 0x1000 + U32 _lines_size; // offset 0x806C, size 0x4 + U8 context_buffer[1024]; // offset 0x8070, size 0x400 + U32 context_buffer_size; // offset 0x8470, size 0x4 + U16 dynamics[64]; // offset 0x8474, size 0x80 + U32 dynamics_size; // offset 0x84F4, size 0x4 +}; + +struct wait_context +{ + struct + { + U8 time : 1; // offset 0x0, size 0x1 + U8 prompt : 1; // offset 0x0, size 0x1 + U8 sound : 1; // offset 0x0, size 0x1 + U8 event : 1; // offset 0x0, size 0x1 + U16 pad : 12; // offset 0x0, size 0x2 + } type; // offset 0x0, size 0x2 + U8 need; // offset 0x2, size 0x1 + F32 delay; // offset 0x4, size 0x4 + U32 event_mask; // offset 0x8, size 0x4 + query_enum query; // offset 0xC, size 0x4 +}; + +struct sound_queue +{ + U32 _playing[5]; + S32 head; + S32 tail; +}; + +struct trigger_pair +{ + ztalkbox* origin; + U32 event; +}; + +struct shared_type +{ + S32 flags; // offset 0x0, size 0x4 + U32 permit; // offset 0x4, size 0x4 + ztalkbox* active; // offset 0x8, size 0x4 + state_type* state; // offset 0xC, size 0x4 + state_type* states[5]; // offset 0x10, size 0x14 + layout lt; // offset 0x24, size 0x84F8 + S32 begin_jot; // offset 0x851C, size 0x4 + S32 end_jot; // offset 0x8520, size 0x4 + S32 page_end_jot; // offset 0x8524, size 0x4 + wait_context wait; // offset 0x8528, size 0x10 + wait_context auto_wait; // offset 0x8538, size 0x10 + U32 wait_event_mask; // offset 0x8548, size 0x4 + F32 prompt_delay; // offset 0x854C, size 0x4 + F32 quit_delay; // offset 0x8550, size 0x4 + U8 prompt_ready; // offset 0x8554, size 0x1 + U8 quit_ready; // offset 0x8555, size 0x1 + U8 stream_locked[2]; // offset 0x8556, size 0x2 + S32 next_stream; // offset 0x8558, size 0x4 + // The below builds perfectly fine, unsure if its 100% correct though + sound_queue<4> sounds; // offset 0x855C, size 0x1C + U8 allow_quit; // offset 0x8578, size 0x1 + U8 quitting; // offset 0x8579, size 0x1 + U8 delay_events; // offset 0x857A, size 0x1 + callback* cb; // offset 0x857C, size 0x4 + // The below builds perfectly fine, unsure if its 100% correct though + fixed_queue triggered; // offset 0x8580, size 0x110 + F32 volume; // offset 0x8690, size 0x4 + zNPCCommon* speak_npc; // offset 0x8694, size 0x4 + U32 speak_player; // offset 0x8698, size 0x4 +}; + #endif