/**
 * d_mesg.cpp
 * Textboxes (cutscenes)
 */

#include "d/dolzel.h" // IWYU pragma: keep
#include "d/d_mesg.h"
#include "JSystem/J2DGraph/J2DOrthoGraph.h"
#include "JSystem/J2DGraph/J2DPicture.h"
#include "JSystem/J2DGraph/J2DScreen.h"
#include "JSystem/J2DGraph/J2DTextBox.h"
#include "JSystem/JKernel/JKRExpHeap.h"
#include "JSystem/JMessage/resource.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "d/d_com_inf_game.h"
#include "d/d_meter.h"
#if VERSION == VERSION_DEMO
#include "d/d_s_play.h"
#endif
#include "f_op/f_op_msg.h"
#include "f_op/f_op_msg_mng.h"
#include "m_Do/m_Do_audio.h"
#include "m_Do/m_Do_controller_pad.h"
#include "stdio.h"

JMessage::TResourceContainer* dMesg_gpResourceContainer;
dMesg_tControl* dMesg_gpControl;
dMesg_tSequenceProcessor* dMesg_gpSequenceProcessor;
dMesg_tRenderingProcessor* dMesg_gpRenderingProcessor;
JUTFont* dMesg_gpFont;
JUTFont* dMesg_gpRFont;
bool dMesg_gbUpdate;
bool m_strSizeFlag;
bool s_strSizeFlag;
void* header;
u32 nowMesgCode;
int oldMesgCode;
void* header2;
bool headerFlag;
short messageOffsetY;
u8 zenkaku;
u16 zenkakuCode;
int retFlag;
JMessage::TParse* oParse;
s16 linemax = 4;

void dMesg_fontsizeCenter(sub_mesg_class*, int, int);
void dMesg_fontsizeCenter(sub_mesg_class*, int, int, int, int);

/* 801DFEE4-801E000C       .text _create__15dMesg_outFont_cFv */
void dMesg_outFont_c::_create() {
    icon = new J2DPicture("font_07_02.bti");
    JUT_ASSERT(117, icon != NULL);
    kage = new J2DPicture("font_07_02.bti");
    JUT_ASSERT(119, kage != NULL);

    fopMsgM_blendInit(icon,"font_00.bti");
    fopMsgM_blendInit(kage,"font_00.bti");
    _initialize();
}

/* 801E000C-801E0074       .text _delete__15dMesg_outFont_cFv */
void dMesg_outFont_c::_delete() {
    delete icon;
    delete kage;
}

/* 801E0074-801E0120       .text _initialize__15dMesg_outFont_cFv */
void dMesg_outFont_c::_initialize() {
    field_0xc = 0;
    field_0x14 = 0;
    field_0x12 = 0;
    field_0x10 = 0;
    mTimer = -1;
    field_0x19 = -1;
    icon->hide();
    icon->rotate(0.0f);
    icon->setAlpha(0);
    kage->hide();
    kage->rotate(0.0f);
    kage->setAlpha(0);
}

/* 801E0120-801E0184       .text _set__15dMesg_outFont_cFsssUlUc */
bool dMesg_outFont_c::_set(s16 param_1, s16 param_2, s16 param_3, u32 param_4, u8 param_5) {
    if (field_0x19 == 0xFF) {
        field_0x10 = param_1;
        field_0x12 = param_2;
        field_0x14 = param_3;
        field_0xc = param_4;
        field_0x19 = param_5;
        fopMsgM_outFontSet(icon, kage, &mTimer, field_0xc, field_0x19);
        return true;
    }
    return false;
}

/* 801E0184-801E01D0       .text _draw__15dMesg_outFont_cFv */
void dMesg_outFont_c::_draw() {
    if (field_0x19 != 0xFF) {
        fopMsgM_outFontDraw(icon, kage, field_0x10, field_0x12, field_0x14, &mTimer, mAlpha, field_0x19);
    }
}

/* 801E01D0-801E01E4       .text _setAlpha__15dMesg_outFont_cFUc */
void dMesg_outFont_c::_setAlpha(u8 alpha) {
    if (field_0x19 == 0xFF) {
        return;
    }
    mAlpha = alpha;
}

/* 801E01E4-801E0274       .text __ct__14dMesg_tControlFv */
dMesg_tControl::dMesg_tControl() {
    mMainFont = NULL;
    mLineCount = 0;
    mLineStart = 0;
    mInitFontSize = g_msgHIO.field_0x70;
    mNowFontSize = g_msgHIO.field_0x70;
    mCharSpace = 0;
    mCharCode = 0;
    mTextBoxWidth = 486;
    mbHeader = 0;
    mCode16Fg = 0;
    mLineLength[3] = 0.0f;
    mLineLength[2] = 0.0f;
    mLineLength[1] = 0.0f;
    mLineLength[0] = 0.0f;
}

/* 801E0274-801E0288       .text do_word__14dMesg_tControlFUl */
const char* dMesg_tControl::do_word(u32 param_1) {
    static const char* name[] = {
        "Link",
        "リンク",
        "りんく",
    };

    return name[param_1];
}

/* 801E0288-801E0364       .text __ct__24dMesg_tSequenceProcessorFPQ28JMessage8TControl */
dMesg_tSequenceProcessor::dMesg_tSequenceProcessor(JMessage::TControl* param_1) : TSequenceProcessor(param_1) {
    field_0x44 = 0.0;
    field_0x48 = 0.0;
    field_0x4c = 0.0;
    field_0x50 = 0.0;
    field_0x54 = 0.0;
    mNowColor = 0xffffffff;
    field_0x70 = 0;
    field_0x74 = 0;
    field_0x8c = 1;
    mWaitRest = 0;
    mStopFlag = 0;
    field_0x160 = 0;
    mShortCutFlag = 0;
    field_0x162 = 0;
    field_0x163 = 0;
    field_0x96 = 0;
    field_0x95 = 0;
    field_0x94 = 0;
    field_0x7c[3] = 0;
    field_0x7c[2] = 0;
    field_0x7c[1] = 0;
    field_0x7c[0] = 0;
    field_0x68 = 0;
    field_0x64 = 0;
    field_0x60 = 0;
    field_0x5c = 0;
    strcpy(field_0x97, "");
    strcpy(field_0xfb, "");
}

/* 801E0364-801E061C       .text initialize__24dMesg_tSequenceProcessorFi */
void dMesg_tSequenceProcessor::initialize(int param_1) {
    dMesg_tControl* mesgControl = (dMesg_tControl*)getControl();
    if (retFlag) {
        retFlag = 0;
    }
    s_strSizeFlag = false;
    m_strSizeFlag = false;
    dMesg_tMeasureProcessor processor(getControl(), param_1);
    processor.setBegin(field_0x3c, field_0x40);
    processor.process(NULL);

    int r31_2 = mesgControl->getLineCount();
    JMSMesgEntry_c stack_8c = *(JMSMesgEntry_c*)dMesg_gpControl->getMessageEntry(nowMesgCode);

    for (int i = 0; i < r31_2; i++) {
        if (stack_8c.mTextAlignment != 3) {
            field_0x7c[i] = 0;
        } else {
            field_0x7c[i] = mesgControl->getLineLength(i);
        }
    }

    mesgControl->setNowFontSize(mesgControl->getInitFontSize());
    mesgControl->setCharCode(0);
    mesgControl->setHeaderOff();
    mesgControl->setCode16FgOff();
    field_0x44 = 0.0f;
    field_0x50 = 0.0f;
    field_0x70 = 0;
    mShortCutFlag = 0;
    mStopFlag = 0;
    field_0x160 = 0;
    field_0x162 = 0;
    field_0x163 = 0;
    field_0x68 = 0;
    field_0x64 = 0;
    field_0x60 = 0;
    field_0x5c = 0;
    if (m_strSizeFlag) {
        retFlag--;
    }
    mMesg->screen->shiftSet(0, g_msgHIO.field_0x5e * (4 - (mesgControl->getLineCount() - retFlag)) / 2);
    char buffer[16];
    sprintf(buffer, "\x1b" "CR[%d]", field_0x7c[field_0x70]);
    strcat(mMesg->text[0], buffer);
    strcat(mMesg->text[2], buffer);
    field_0x44 = field_0x7c[field_0x70];
    field_0x8c = 1;
    resetWaitRest();
}

/* 801E067C-801E06A8       .text do_begin__24dMesg_tSequenceProcessorFPCvPCc */
void dMesg_tSequenceProcessor::do_begin(const void* param_1, const char* param_2) {
    field_0x3c = param_1;
    field_0x40 = param_2;
    initialize(0);
}

/* 801E06A8-801E06C8       .text do_end__24dMesg_tSequenceProcessorFv */
void dMesg_tSequenceProcessor::do_end() {
    setCharacter();
}

/* 801E06C8-801E0834       .text do_isReady__24dMesg_tSequenceProcessorFv */
bool dMesg_tSequenceProcessor::do_isReady() {
    bool ret = false;
    if (mStopFlag == 0) {
        JMSMesgEntry_c stack_2c = *(JMSMesgEntry_c*)dMesg_gpControl->getMessageEntry(nowMesgCode);
        if (stack_2c.mDrawType == 1) {
            mShortCutFlag = 1;
#if VERSION > VERSION_DEMO
            if (field_0x160) {
                mShortCutFlag = 0;
            }
        } else if (stack_2c.mDrawType == 2) {
            mShortCutFlag = 0;
            #endif
        }
        if (CPad_CHECK_TRIG_A(0) || CPad_CHECK_TRIG_B(0)) {
            if (stack_2c.mDrawType != 2 && field_0x160 == 0) {
                mShortCutFlag = 1;
            }
        }
        if (mWaitRest <= 0 || mShortCutFlag) {
            ret = true;
#if VERSION > VERSION_DEMO
            field_0x160 = 0;
#endif
        } else {
            mWaitRest--;
        }
#if VERSION > VERSION_DEMO
        if (zenkaku) {
            ret = true;
        }
#endif
    }
    return ret;
}

/* 801E0834-801E0864       .text do_jump_isReady__24dMesg_tSequenceProcessorFv */
bool dMesg_tSequenceProcessor::do_jump_isReady() {
    if (CPad_CHECK_TRIG_A(0) || CPad_CHECK_TRIG_B(0)) {
        return true;
    }
    return false;
}

/* 801E0864-801E0870       .text do_jump__24dMesg_tSequenceProcessorFPCvPCc */
void dMesg_tSequenceProcessor::do_jump(const void*, const char*) {
    mWaitRest = 0;
}

/* 801E0870-801E0874       .text do_branch_query__24dMesg_tSequenceProcessorFUs */
void dMesg_tSequenceProcessor::do_branch_query(u16) {
}

/* 801E0874-801E087C       .text do_branch_queryResult__24dMesg_tSequenceProcessorFv */
int dMesg_tSequenceProcessor::do_branch_queryResult() {
    return 0xFF;
}

/* 801E087C-801E0888       .text do_branch__24dMesg_tSequenceProcessorFPCvPCc */
void dMesg_tSequenceProcessor::do_branch(const void*, const char*) {
    mWaitRest = 0;
}

/* 801E0888-801E0DE8       .text do_character__24dMesg_tSequenceProcessorFi */
void dMesg_tSequenceProcessor::do_character(int param_1) {
    dMesg_tControl* mesgControl = (dMesg_tControl*)getControl();
    u8 r30 = 0;
    setCharacter();
    if (headerFlag) {
        if ((param_1 & 0xf0) == 0x80 || (param_1 & 0xf0) == 0x90 || zenkaku) {
            if (zenkaku == 0) {
                zenkakuCode = param_1 << 8;
                zenkaku = 1;
                return;
            } else {
                zenkakuCode |= u16(param_1);
                zenkaku = 0;
                for (int i = 0; i < 97; i++) {
                    if (zfont[i][0] == zenkakuCode) {
                        param_1 = zfont[i][1];
                        break;
                    }
                }
                mesgControl->setCharCode(param_1);
                field_0x94 = (param_1 >> 8) & 0xFF;
                field_0x95 = (param_1) & 0xFF;
            }
        } else {
            field_0x94 = param_1;
            field_0x95 = 0;
            mesgControl->setCharCode(param_1);
            if (param_1 == 10) {
                r30 = 1;
            } else if (param_1 == 0) {
                r30 = 2;
            }
            zenkaku = 0;
        }
#if VERSION > VERSION_DEMO
    } else {
        field_0x94 = param_1;
        field_0x95 = 0;
        mesgControl->setCharCode(param_1);
        if (param_1 == 10) {
            r30 = 1;
        } else if (param_1 == 0) {
            r30 = 2;
        }
#endif
    }

    f32 f31 = f32(mesgControl->getNowFontSize()) / f32(mesgControl->getMainFont()->getCellWidth());
    int char_code = mesgControl->getCharCode();
    int width = mesgControl->getMainFont()->getWidth(char_code);
    if (!mesgControl->isHeader()) {
        field_0x44 += width * f31;
        mesgControl->setHeaderOn();
    } else {
        field_0x44 += width * f31 + mesgControl->getCharSpace();
    }
    if (field_0x74 > 0) {
        field_0x74--;
        if (field_0x74 == 0) {
            f31 = (field_0x48 + (field_0x44 - field_0x48) / 2.0f) - field_0x54 / 2.0f;
            char buffer[16];
            buffer[0] = 0;
            if (field_0x163) {
                mMesg->text[1][field_0x60] = '\0';
                mMesg->text[3][field_0x68] = '\0';
                strcat(mMesg->text[1], field_0xfb);
                strcat(mMesg->text[3], field_0xfb);
                field_0x163 = 0;
            }
            if (field_0x50 < f31) {
                f31 -= field_0x50;
                sprintf(buffer, "\x1b" "CR[%d]", int(f31 + 0.5f));
                field_0x50 += f31;
            } else {
                if (0.0f == field_0x50) {
                    f31 = field_0x50 - f31;
                    sprintf(buffer, "\x1b" "CL[%d]", int(f31 + 0.5f));
                    field_0x50 -= f31;
                }
            }
            field_0x50 += field_0x54;
            strcat(mMesg->text[1], buffer);
            strcat(mMesg->text[3], buffer);
            strcat(mMesg->text[1], field_0x97);
            strcat(mMesg->text[3], field_0x97);
            strcpy(field_0xfb, field_0x97);
        }
    }
    if (r30 == 1) {
        strcat(mMesg->text[0], &field_0x94);
        strcat(mMesg->text[1], &field_0x94);
        strcat(mMesg->text[2], &field_0x94);
        strcat(mMesg->text[3], &field_0x94);
        field_0x44 = 0.0f;
        field_0x50 = 0.0f;
        field_0x70 += 1;
        if (field_0x70 == mesgControl->getLineCount()) {
            mStopFlag = 1;
            return;
        } else {
            mesgControl->setHeaderOff();
            char buffer[16];
            sprintf(buffer, "\x1b" "CR[%d]", field_0x7c[field_0x70]);
            strcat(mMesg->text[0], buffer);
            strcat(mMesg->text[2], buffer);
            field_0x44 = field_0x7c[field_0x70];
        }
    } else {
        strcat(mMesg->text[0], &field_0x94);
        strcat(mMesg->text[2], &field_0x94);
    }
    // 0x8140: '　' (Ideographic space)
    // 0x8141: '、' (Ideographic comma)
    // 0x20: ' ' (Space)
    if (mesgControl->getCharCode() == 0x8140 || mesgControl->getCharCode() == 0x8141 || mesgControl->getCharCode() == 0x20 || r30 == 1) {
        if (field_0x8c != 0) {
            mWaitRest = 1;
        }
    } else {
        mWaitRest = field_0x8c;
    }
}

/* 801E0DE8-801E161C       .text do_tag__24dMesg_tSequenceProcessorFUlPCvUl */
bool dMesg_tSequenceProcessor::do_tag(u32 param_1, const void* param_2, u32 param_3) {
    dMesg_tControl* mesgControl = (dMesg_tControl*)getControl();
    int r30 = param_1 & 0xFF0000;
    bool r29 = false;
    if (field_0x162) {
        mMesg->text[0][field_0x5c] = 0;
        mMesg->text[2][field_0x64] = 0;
        field_0x162 = 0;
        strcat(mMesg->text[0], &field_0x94);
        strcat(mMesg->text[2], &field_0x94);
        field_0x96 = 0;
        field_0x95 = 0;
        field_0x94 = 0;
    }

    switch (r30) {
    case 0:
        switch (param_1) {
        case 0: {
            r29 = true;
            int r30 = 0;
            char sp54[17];
            JMSMesgEntry_c sp38 = *(JMSMesgEntry_c*)dMesg_gpControl->getMessageEntry(nowMesgCode);

            strcpy(sp54, dComIfGs_getPlayerName());
#if VERSION > VERSION_JPN
            if (dComIfGs_getPalLanguage() == 1) {
                // Specific msg nos that have the 's possessive after the player's name.
                if (sp38.mMsgNo == 0x33b ||
                    sp38.mMsgNo == 0xc8b ||
                    sp38.mMsgNo == 0x1d21 ||
                    sp38.mMsgNo == 0x31d7 ||
                    sp38.mMsgNo == 0x37dd ||
                    sp38.mMsgNo == 0x37de
                ) {
                    char c = sp54[strlen(sp54) - 1];
                    if (c == 's' || c == 'S' || c == 'z' || c == 'Z' || c == 'x' || c == 'X') {
                        strcat(sp54, "'");
                    } else {
                        strcat(sp54, "s");
                    }
                }
            }
#endif

            char sp14[3];
            while (sp54[r30]) {
                int char_code;
                u8 byte = sp54[r30];
                if (byte >> 4 == 8 || byte >> 4 == 9) {
                    sp14[0] = sp54[r30++];
                    char_code = ((byte << 8) & ~0xFF);
                    byte = sp54[r30];
                    char_code |= (byte & 0xFF);
                    sp14[1] = sp54[r30++];
                    sp14[2] = 0;
                } else {
                    char_code = byte;
                    sp14[0] = sp54[r30++];
                    sp14[1] = 0;
                }

                f32 f29 = f32(mesgControl->getNowFontSize()) / f32(mesgControl->getMainFont()->getCellWidth());
                int width = mesgControl->getMainFont()->getWidth(char_code);
                if (field_0x44 == 0.0f) {
                    f32 temp2 = width * f29;
                    field_0x44 = temp2;
                } else {
                    f32 temp2 = width * f29;
                    field_0x44 += temp2 + mesgControl->getCharSpace();
                }
                strcat(mMesg->text[0], sp14);
                strcat(mMesg->text[2], sp14);
            };
            break;
        }
        case 1:
            field_0x8c = 0;
            r29 = true;
            break;
        case 2:
            field_0x8c = 1;
            r29 = true;
            break;
        case 3:
            r29 = true;
            break;
        case 4:
            r29 = true;
            mWaitRest = *(u16*)param_2;
            field_0x160 = 1;
            mStopFlag = 2;
            break;
        case 5:
        case 6:
            r29 = true;
            break;
        case 7:
            r29 = true;
            mWaitRest = *(u16*)param_2;
            field_0x160 = 1;
            break;
        case 8:
        case 9:
            field_0x8c = 0;
            r29 = true;
            break;
        case 10:
        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
        case 16:
        case 17:
        case 18:
        case 19:
        case 20:
        case 21:
        case 22:
        case 23:
        case 24:
        case 25:
        case 26:
        case 27:
        case 28:
        case 29: {
            u8 r29_2 = param_1 - 10;
            s16 r30 = field_0x44 + mMesg->screen->getTextPosX(0) + 0.5f;
            s16 r24 = field_0x70 * g_msgHIO.field_0x5e + (mMesg->screen->getTextPosY(0) + (g_msgHIO.field_0x5e * (4 - mesgControl->getLineCount())) / 2);
            setCharacter();
            for (int i = 0; i < 18; i++) {
                if (mMesg->outfont[i]->_set(r30, r24, mesgControl->getNowFontSize(), mNowColor, r29_2)) {
                    mMesg->outfont[i]->_setAlpha(255);
                    break;
                }
            }
            field_0x44 += (mesgControl->getNowFontSize() + mesgControl->getCharSpace());
            char sp18[16];
            sprintf(sp18, "\x1b" "CR[%d]", mesgControl->getNowFontSize());
            strcat(mMesg->text[0], sp18);
            strcat(mMesg->text[2], sp18);
            mWaitRest = field_0x8c;
            r29 = true;
            break;
        }
        case 41: {
            r29 = true;
            int r30 = 0;
            char sp28[17];
            fopMsgM_passwordGet(sp28, dComIfGs_getEventReg(dSv_event_flag_c::UNK_BA0F) + 0x1B37);
            char sp10[3];
            while (sp28[r30]) {
                int char_code;
                u8 byte = sp28[r30];
                if (byte >> 4 == 8 || byte >> 4 == 9) {
                    sp10[0] = sp28[r30++];
                    char_code = ((byte << 8) & ~0xFF);
                    byte = sp28[r30];
                    char_code |= (byte & 0xFF);
                    sp10[1] = sp28[r30++];
                    sp10[2] = 0;
                } else {
                    char_code = byte;
                    sp10[0] = sp28[r30++];
                    sp10[1] = 0;
                }

                int r25 = mesgControl->getNowFontSize();
                f32 f29 = f32(r25) / f32(mesgControl->getMainFont()->getCellWidth());
                int width = mesgControl->getMainFont()->getWidth(char_code);
                if (field_0x44 == 0.0f) {
                    field_0x44 = width * f29;
                } else {
                    field_0x44 += width * f29 + mesgControl->getCharSpace();
                }
                strcat(mMesg->text[0], sp10);
                strcat(mMesg->text[2], sp10);
            }
        }
        }
        break;
    case 0x10000: {
        u16 r24 = param_1 & 0xFFFF;
        s8 tmp = dComIfGp_getReverb(dComIfGp_roomControl_getStayNo());
        if (r24 == 8) {
            mDoAud_messageSePlay(r24, NULL, tmp);
        } else {
            mDoAud_messageSePlay(r24, NULL, tmp);
        }
        r29 = true;
        break;
    }
    case 0x20000: {
        u16 temp = param_1 & 0xFFFF;
        dComIfGp_setMesgCameraTagInfo(temp);
        r29 = true;
        break;
    }
    case 0x30000:
        dComIfGp_setMesgAnimeTagInfo(param_1);
        r29 = true;
        break;
    }
    return r29;
}

/* 801E161C-801E16F4       .text setCharacter__24dMesg_tSequenceProcessorFv */
void dMesg_tSequenceProcessor::setCharacter() {
    if (field_0x162) {
        mMesg->text[0][field_0x5c] = 0;
        mMesg->text[2][field_0x64] = 0;
        strcat(mMesg->text[0], &field_0x94);
        strcat(mMesg->text[2], &field_0x94);
        field_0x162 = 0;
    }
    if (field_0x163) {
        mMesg->text[1][field_0x60] = 0;
        mMesg->text[3][field_0x68] = 0;
        strcat(mMesg->text[1], field_0xfb);
        strcat(mMesg->text[3], field_0xfb);
        field_0x163 = 0;
    }
}

/* 801E16F4-801E1858       .text ruby_character__24dMesg_tSequenceProcessorFPci */
char* dMesg_tSequenceProcessor::ruby_character(char* param_1, int param_2) {
    dMesg_tControl* mesgControl = (dMesg_tControl*)getControl();
    f32 f31 = f32(g_msgHIO.field_0x68) / f32(((dMesg_tControl*)getControl())->getRubyFont()->getCellWidth());
    char buffer[3];
    char* src = param_1 + param_2;
    buffer[0] = src[0];
    buffer[1] = src[1];
    buffer[2] = 0;
    u8 byte = src[0];
    int char_code = (byte << 8);
    byte = src[1];
    char_code |= byte;
    f32 tmp = (f32)mesgControl->getRubyFont()->getWidth(char_code);
    if (param_2 == 1) {
        if (field_0x50 == 0.0f) {
            field_0x54 = tmp * f31;
        } else {
            field_0x54 = tmp * f31;
        }
    } else {
        field_0x54 += g_msgHIO.field_0x5c + tmp * f31;
    }
    return buffer;
}

/* 801E1858-801E1B5C       .text do_systemTagCode__24dMesg_tSequenceProcessorFUsPCvUl */
bool dMesg_tSequenceProcessor::do_systemTagCode(u16 param_1, const void* param_2, u32 param_3) {
    /* Nonmatching */
    static const u32 colorTable[] = {
        0xFFFFFFFF,
        0xFF5A5AFF,
        0x78FF78FF,
        0x7878FFFF,
        0xFFFF32FF,
        0x82FFFFFF,
        0xDC6EFFFF,
        0xA0A0A0FF,
        0xFF8200FF,
    };

    dMesg_tControl* mesgControl = (dMesg_tControl*)getControl();

#if VERSION > VERSION_DEMO
    if (field_0x162) {
        mMesg->text[0][field_0x5c] = 0;
        mMesg->text[2][field_0x64] = 0;
        field_0x162 = 0;
    }
#endif

    switch (param_1) {
    case 0:
        if (param_3 == 1) {
            mNowColor = colorTable[u8(*(u8*)param_2)];
            char buffer[32];
            sprintf(buffer, "\x1b" "CC[%08x]" "\x1b" "GM[0]", mNowColor);
            strcat(mMesg->text[0], buffer);
        }
        return true;
    case 1:
    case 6:
        if (param_3 == 2) {
            u16 tmp = *(u16*)param_2;
            int r31 = mesgControl->getNowFontSize();
            int r29 = (tmp * mesgControl->getInitFontSize()) / 100.0f + 0.5f;
            mesgControl->setNowFontSize(r29);
            if (field_0x70 == 0) {
                dMesg_fontsizeCenter(mMesg, r31, r29);
            } else {
                if (tmp > 100 && s_strSizeFlag == 0) {
                    strcat(this->mMesg->text[0], "\n");
                    strcat(this->mMesg->text[1], "\n");
                    strcat(this->mMesg->text[2], "\n");
                    strcat(this->mMesg->text[3], "\n");
                    char buffer[16];
                    sprintf(buffer, "\x1b" "CR[%d]", int(field_0x44));
                    strcat(mMesg->text[0], buffer);
                    strcat(mMesg->text[2], buffer);
                    s_strSizeFlag = true;
                }
                dMesg_fontsizeCenter(mMesg, r31, r29, mesgControl->getInitFontSize(), g_msgHIO.field_0x5e);
            }
        }
        return true;
    case 2:
        if (field_0x44 == 0.0f) {
            field_0x48 = field_0x44;
        } else {
            field_0x48 = field_0x44 + mesgControl->getCharSpace();
        }
        field_0x54 = 0.0f;
        strcpy(field_0x97, "");
        field_0x74 = *(u8*)param_2;
        for (int i = 1; i < int(param_3); i += 2) {
            strcat(field_0x97, ruby_character((char*)param_2, i));
        }
        return true;
    case 3:
        return true;
    }
    return true;
}

/* 801E1B5C-801E1C00       .text __ct__23dMesg_tMeasureProcessorFPQ28JMessage8TControli */
dMesg_tMeasureProcessor::dMesg_tMeasureProcessor(JMessage::TControl* param_1, int param_2) : TSequenceProcessor(param_1) {
    field_0x48 = 0.0f;
    field_0x4c = param_2;
    field_0x50 = 0;
    field_0x54 = 0;
    linemax = 4;
    dMesg_tControl* mesgControl = (dMesg_tControl*)getControl();
    mesgControl->setNowFontSize(mesgControl->getInitFontSize());
    mesgControl->setLineCount(0);
    mesgControl->setCharCode(0);
    mesgControl->setHeaderOff();
    mesgControl->setCode16FgOff();
    for (int i = 0; i < 4; i++) {
        field_0x38[i] = 0.0f;
        mesgControl->setLineLength(i, 0.0f);
    }
}

/* 801E1C00-801E1EC0       .text do_character__23dMesg_tMeasureProcessorFi */
void dMesg_tMeasureProcessor::do_character(int param_1) {
    dMesg_tControl* mesgControl = (dMesg_tControl*)getControl();
    int r30 = field_0x50 - field_0x4c;
    bool r29 = false;
    if (param_1 == 10) {
        if (r30 >= 0 && r30 < linemax - 1) {
            retFlag++;
        }
        field_0x50++;
        mesgControl->setHeaderOff();
    } else {
        if (retFlag && r30 >= 0 && r30 < linemax) {
            retFlag = 0;
        }
        r29 = true;
        JMSMesgEntry_c stack_58 = *(JMSMesgEntry_c*)dMesg_gpControl->getMessageEntry(nowMesgCode);
        if (dComIfGs_getClearCount() == 0 && stack_58.mTextboxType == 12) {
            for (int i = 0; i < 97; i++) {
                if (zfont[i][0] == u16(param_1)) {
                    param_1 = zfont[i][1];
                    break;
                }
            }
        }
        mesgControl->setCharCode(param_1);
    }
    if (r29 && r30 >= 0 && r30 <= linemax) {
        f32 f31 = f32(mesgControl->getNowFontSize()) / f32(mesgControl->getMainFont()->getCellWidth());
        int char_code = mesgControl->getCharCode();
        int width = mesgControl->getMainFont()->getWidth(char_code);
        if (!mesgControl->isHeader()) {
            field_0x38[r30] += width * f31;
            mesgControl->setHeaderOn();
        } else {
            field_0x38[r30] += mesgControl->getCharSpace() + width * f31;
        }
    }
}

/* 801E1EC0-801E1F9C       .text do_end__23dMesg_tMeasureProcessorFv */
void dMesg_tMeasureProcessor::do_end() {
    dMesg_tControl* mesgControl = (dMesg_tControl*)getControl();
    int var2 = (field_0x50 - field_0x4c) + 1;
    if (var2 > linemax) {
        var2 = linemax;
    }
    mesgControl->setLineCount(var2);
    mesgControl->setLineStart(field_0x4c + var2);

    for (int i = 0; i < 4; i++) {
        f32 var1;
        if (field_0x54 == 2 && (i == 1 || i == 2)) {
            var1 = field_0x48;
        } else if (field_0x54 == 3 && (i == 0 || i == 1 || i == 2)) {
            var1 = field_0x48;
        } else {
            var1 = (mesgControl->getTextBoxWidth() - field_0x38[i]) / 2.0f;
        }
        mesgControl->setLineLength(i, var1);
    }
}

/* 801E1F9C-801E27BC       .text do_tag__23dMesg_tMeasureProcessorFUlPCvUl */
bool dMesg_tMeasureProcessor::do_tag(u32 param_1, const void* param_2, u32 param_3) {
    /* Nonmatching */
    dMesg_tControl* mesgControl = (dMesg_tControl*)getControl();
    u32 r6 = param_1 & 0xFF0000;
    int r27 = field_0x50 - field_0x4c;
    bool r26 = false;
    switch(r6) {
    case 0:
        switch(param_1) {
        case 0: {
            r26 = true;
            int r25 = 0;
            char sp44[17];
#if VERSION > VERSION_DEMO
            JMSMesgEntry_c stack_98 = *(JMSMesgEntry_c*)dMesg_gpControl->getMessageEntry(nowMesgCode);

            strcpy(sp44, dComIfGs_getPlayerName());
#endif
#if VERSION > VERSION_JPN
            if (dComIfGs_getPalLanguage() == 1) {
                // Specific msg nos that have the 's possessive after the player's name.
                if (stack_98.mMsgNo == 0x33b ||
                    stack_98.mMsgNo == 0xc8b ||
                    stack_98.mMsgNo == 0x1d21 ||
                    stack_98.mMsgNo == 0x31d7 ||
                    stack_98.mMsgNo == 0x37dd ||
                    stack_98.mMsgNo == 0x37de
                ) {
                    char c = sp44[strlen(sp44) - 1];
                    if (c == 's' || c == 'S' || c == 'z' || c == 'Z' || c == 'x' || c == 'X') {
                        strcat(sp44, "'");
                    } else {
                        strcat(sp44, "s");
                    }
                }
            }
#endif
#if VERSION > VERSION_DEMO
            if (retFlag && r27 >= 0 && r27 < linemax) {
                retFlag = 0;
            }
#endif
            while (sp44[r25]) {
                int char_code;
                u8 byte = sp44[r25];
                if (byte >> 4 == 8 || byte >> 4 == 9) {
                    byte = sp44[r25++];
                    char_code = ((byte << 8) & ~0xFF);
                    byte = sp44[r25++];
                    char_code |= (byte & 0xFF);
                } else {
                    byte = sp44[r25++];
                    char_code = byte;
                }

                int r23 = mesgControl->getNowFontSize();
                f32 f30 = f32(r23) / f32(mesgControl->getMainFont()->getCellWidth());
                int width = mesgControl->getMainFont()->getWidth(char_code);
                if (r27 >= 0 && r27 <= linemax) {
                    if (field_0x38[r27] == 0.0f) {
                        field_0x38[r27] = width * f30;
                    } else {
                        field_0x38[r27] += width * f30 + mesgControl->getCharSpace();
                    }
                }
            }

            break;
        }
        case 10:
        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
        case 16:
        case 17:
        case 18:
        case 19:
        case 20:
        case 21:
        case 22:
        case 23:
        case 24:
        case 25:
        case 26:
        case 27:
        case 28:
        case 29:
#if VERSION > VERSION_DEMO
            if (retFlag && r27 >= 0 && r27 < linemax) {
                retFlag = 0;
            }
#endif
            if (r27 >= 0 && r27 <= 3) {
                field_0x38[r27] += (mesgControl->getNowFontSize() + mesgControl->getCharSpace());
            }
            r26 = true;
            break;
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
            r26 = true;
            break;
        case 8:
            field_0x54 = 2;
            for (int i = 0; i < 2; i++) {
#if VERSION == VERSION_DEMO
                // 0x8267: 'Ｈ' (Fullwidth capital H)
                int char_code = g_msgDHIO.field_0x08 == 0 ? 0x8267 : 'H';
#else
                int char_code = 'H';
#endif

                f32 f29 = f32(mesgControl->getNowFontSize()) / f32(mesgControl->getMainFont()->getCellWidth());
                int width = mesgControl->getMainFont()->getWidth(char_code);
                if (field_0x48 == 0.0f) {
                    field_0x48 = width * f29;
                } else {
                    field_0x48 += mesgControl->getCharSpace() + width * f29;
                }
            }
            r26 = true;
            break;
        case 9:
            field_0x54 = 3;
            for (int i = 0; i < 2; i++) {
#if VERSION == VERSION_DEMO
                // 0x8267: 'Ｈ' (Fullwidth capital H)
                int char_code = g_msgDHIO.field_0x08 == 0 ? 0x8267 : 'H';
#else
                int char_code = 'H';
#endif

                f32 f29 = f32(mesgControl->getNowFontSize()) / f32(mesgControl->getMainFont()->getCellWidth());
                int width = mesgControl->getMainFont()->getWidth(char_code);
                if (field_0x48 == 0.0f) {
                    field_0x48 = width * f29;
                } else {
                    field_0x48 += mesgControl->getCharSpace() + width * f29;
                }
            }
            r26 = true;
            break;
        case 41: {
            r26 = true;
            int r25 = 0;
            char sp18[17];
            u32 tmp = dComIfGs_getEventReg(dSv_event_flag_c::UNK_BA0F);
            fopMsgM_passwordGet(sp18, tmp + 0x1B37);
#if VERSION > VERSION_DEMO
            if (retFlag && r27 >= 0 && r27 < linemax) {
                retFlag = 0;
            }
#endif

            while (sp18[r25]) {
                int char_code;
                u8 byte = sp18[r25];
                if (byte >> 4 == 8 || byte >> 4 == 9) {
                    byte = sp18[r25++];
                    char_code = ((byte << 8) & ~0xFF);
                    byte = sp18[r25++];
                    char_code |= (byte & 0xFF);
                } else {
                    byte = sp18[r25++];
                    char_code = byte;
                }

                f32 f30 = f32(mesgControl->getNowFontSize()) / f32(mesgControl->getMainFont()->getCellWidth());
                int width = mesgControl->getMainFont()->getWidth(char_code);
                if (r27 >= 0 && r27 <= linemax) {
                    if (field_0x38[r27] == 0.0f) {
                        field_0x38[r27] = width * f30;
                    } else {
                        field_0x38[r27] += width * f30 + mesgControl->getCharSpace();
                    }
                }
            }

            break;
        }
        }
        break;
    case 0x10000:
        r26 = true;
        break;
    case 0x20000:
        r26 = true;
        break;
    case 0x30000:
        r26 = true;
        break;
    }
    return r26;
}

/* 801E27BC-801E28A8       .text do_systemTagCode__23dMesg_tMeasureProcessorFUsPCvUl */
bool dMesg_tMeasureProcessor::do_systemTagCode(u16 param_1, const void* param_2, u32 param_3) {
    /* Nonmatching */
    dMesg_tControl* mesgControl = (dMesg_tControl*)getControl();
    int var2 = field_0x50 - field_0x4c;
    switch (param_1) {
    case 1:
        if (param_3 == 2) {
            u16 var1 = *(u16*)param_2;
            mesgControl->setNowFontSize((var1 * mesgControl->getInitFontSize()) / 100.0f + 0.5f);
            if (var2 >= 1 && var2 <= 2 && var1 > 100 && m_strSizeFlag == 0) {
                linemax--;
                m_strSizeFlag = true;
            }
        }
        return true;
    case 0:
    case 2:
    case 3:
    case 6:
        return true;
    }
    return true;
}

/* 801E28A8-801E28E4       .text __ct__25dMesg_tRenderingProcessorFPQ28JMessage8TControl */
dMesg_tRenderingProcessor::dMesg_tRenderingProcessor(JMessage::TControl* param_1) : TRenderingProcessor(param_1) {
}

/* 801E28E4-801E28E8       .text do_begin__25dMesg_tRenderingProcessorFPCvPCc */
void dMesg_tRenderingProcessor::do_begin(const void*, const char*) {
}

/* 801E28E8-801E28EC       .text do_end__25dMesg_tRenderingProcessorFv */
void dMesg_tRenderingProcessor::do_end() {
}

/* 801E28EC-801E28F0       .text do_character__25dMesg_tRenderingProcessorFi */
void dMesg_tRenderingProcessor::do_character(int) {
}

/* 801E28F0-801E2970       .text do_tag__25dMesg_tRenderingProcessorFUlPCvUl */
bool dMesg_tRenderingProcessor::do_tag(u32 param_1, const void*, u32) {
    bool ret = false;
    switch (param_1 & 0xff0000) {
    case 0:
        switch(param_1) {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
        case 9:
        case 10:
        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
        case 16:
        case 17:
        case 18:
        case 19:
        case 20:
        case 21:
        case 22:
        case 23:
        case 24:
        case 25:
        case 26:
        case 27:
        case 28:
        case 29:
        case 41:
            ret = true;
            break;
        }
        break;
    case 0x10000:
        ret = true;
        break;
    case 0x20000:
        ret = true;
        break;
    case 0x30000:
        ret = true;
        break;
    }
    return ret;
}

/* 801E2970-801E29A4       .text do_systemTagCode__25dMesg_tRenderingProcessorFUsPCvUl */
bool dMesg_tRenderingProcessor::do_systemTagCode(u16 param_1, const void*, u32) {
    switch (param_1) {
        case 0:
        case 1:
        case 2:
        case 3:
        case 6:
            return true;
    }
    return true;
}

/* 801E29A4-801E2C04       .text setCommonData__18dMesg_screenData_cFv */
void dMesg_screenData_c::setCommonData() {
    ((J2DTextBox*)field_0x88[0].pane)->setFont(field_0x10);
    ((J2DTextBox*)field_0x88[1].pane)->setFont(field_0x14);
    ((J2DTextBox*)field_0x88[2].pane)->setFont(field_0x10);
    ((J2DTextBox*)field_0x88[3].pane)->setFont(field_0x14);

    J2DTextBox::TFontSize fontSize;
    fontSize.mSizeX = g_msgHIO.field_0x70;
    fontSize.mSizeY = g_msgHIO.field_0x70;
    ((J2DTextBox*)field_0x88[0].pane)->setFontSize(fontSize);
    ((J2DTextBox*)field_0x88[2].pane)->setFontSize(fontSize);

    ((J2DTextBox*)field_0x88[0].pane)->setCharSpace(g_msgHIO.field_0x5a);
    ((J2DTextBox*)field_0x88[1].pane)->setCharSpace(g_msgHIO.field_0x5c);
    ((J2DTextBox*)field_0x88[2].pane)->setCharSpace(g_msgHIO.field_0x5a);
    ((J2DTextBox*)field_0x88[3].pane)->setCharSpace(g_msgHIO.field_0x5c);

    ((J2DTextBox*)field_0x88[0].pane)->setLineSpace(g_msgHIO.field_0x5e);
    ((J2DTextBox*)field_0x88[2].pane)->setLineSpace(g_msgHIO.field_0x5e);
    mTimer = 0;
    field_0x1b0.set(((J2DPicture*)field_0x18.pane)->getBlack());
    field_0x1ac.set(((J2DPicture*)field_0x18.pane)->getWhite());
}

/* 801E2C04-801E2CB0       .text initString__18dMesg_screenData_cFPci */
void dMesg_screenData_c::initString(char* param_1, int param_2) {
    char buffer[24];

    u32 color = dMesg_gpSequenceProcessor->getNowColor();

    switch (param_2){
    case 0:
        sprintf(buffer, "\x1b" "CC[%08x]" "\x1b" "GM[0]", color);
        strcpy(param_1, buffer);
        break;
    case 1:
        strcpy(param_1, "\x1b" "CC[FFFFFFFF]" "\x1b" "GM[0]");
        break;
    case 2:
    case 3:
        strcpy(param_1,"\x1b" "CC[000000FF]" "\x1b" "GM[0]");
        break;
    }
}

/* 801E2CB0-801E2CE0       .text setString__18dMesg_screenData_cFPci */
void dMesg_screenData_c::setString(char* param_1, int param_2) {
    ((J2DTextBox*)field_0x88[param_2].pane)->setString(param_1, param_2);
}

/* 801E2CE0-801E2D40       .text shiftSet__18dMesg_screenData_cFii */
void dMesg_screenData_c::shiftSet(int param_1, int param_2) {
    for (int i = 0; i < 4; i++) {
        J2DTextBox* textBox = (J2DTextBox*)field_0x88[i].pane;
        textBox->field_0xd8 = param_1;
        textBox->field_0xdc = param_2;
    }
}

/* 801E2D40-801E2D98       .text arwAnimeInit__18dMesg_screenData_cFv */
void dMesg_screenData_c::arwAnimeInit() {
    fopMsgM_setNowAlphaZero(&field_0x50);
    field_0x50.mPosCenter = field_0x50.mPosCenterOrig;
    field_0x50.mSize = field_0x50.mSizeOrig;
    resetTimer();
}

/* 801E2D98-801E315C       .text arwAnime__18dMesg_screenData_cFv */
void dMesg_screenData_c::arwAnime() {
    static const f32 scaleX[] = {1.0f, 1.3f, 0.8f, 1.2f, 1.0f};
    static const f32 scaleY[] = {1.0f, 0.3f, 1.1f, 0.8f, 1.0f};
    static const s16 step[] = {60, 67, 71, 74, 76};

    mTimer++;
    if (field_0x50.mNowAlpha < field_0x50.mInitAlpha) {
        fopMsgM_setNowAlpha(&field_0x50, fopMsgM_valueIncrease(10, mTimer, 0));
        if (mTimer == 10) {
            resetTimer();
        }
    } else {
        f32 f1, f3;
        if (mTimer <= step[0]) {
            f1 = f3 = 1.0f;
        } else if (mTimer <= step[1]) {
            f32 temp = f32(mTimer) - f32(step[0]);
            temp = (temp * temp) / (f32(step[1] - step[0]) * f32(step[1] - step[0]));
            f3 = temp * (scaleX[1] - scaleX[0]) + scaleX[0];
            f1 = temp * (scaleY[1] - scaleY[0]) + scaleY[0];
        } else if (mTimer <= step[2]) {
            f32 temp = f32(mTimer) - f32(step[1]);
            temp = (temp * temp) / (f32(step[2] - step[1]) * f32(step[2] - step[1]));
            f3 = temp * (scaleX[2] - scaleX[1]) + scaleX[1];
            f1 = temp * (scaleY[2] - scaleY[1]) + scaleY[1];
        } else if (mTimer <= step[3]) {
            f32 temp = f32(mTimer) - f32(step[2]);
            temp = (temp * temp) / (f32(step[3] - step[2]) * f32(step[3] - step[2]));
            f3 = temp * (scaleX[3] - scaleX[2]) + scaleX[2];
            f1 = temp * (scaleY[3] - scaleY[2]) + scaleY[2];
        } else if (mTimer <= step[4]) {
            f32 temp = f32(mTimer) - f32(step[3]);
            temp = (temp * temp) / (f32(step[4] - step[3]) * f32(step[4] - step[3]));
            f3 = temp * (scaleX[4] - scaleX[3]) + scaleX[3];
            f1 = temp * (scaleY[4] - scaleY[3]) + scaleY[3];
        } else {
            f1 = f3 = 1.0f;
            resetTimer();
        }
        field_0x50.mSize.x = field_0x50.mSizeOrig.x * f3;
        field_0x50.mSize.y = field_0x50.mSizeOrig.y * f1;
        field_0x50.mPosCenter.y = f32(g_msgHIO.field_0x66) + (f32(field_0x1a4) - field_0x50.mSize.y / 2.0f);
        fopMsgM_cposMove(&field_0x50);
    }
}

/* 801E315C-801E3194       .text dotAnimeInit__18dMesg_screenData_cFv */
void dMesg_screenData_c::dotAnimeInit() {
    fopMsgM_setNowAlphaZero(&field_0x18);
    resetTimer();
}

/* 801E3194-801E36A8       .text dotAnime__18dMesg_screenData_cFv */
void dMesg_screenData_c::dotAnime() {
    /* Nonmatching */
    f32 f31 = 150.0f - field_0x1b0.r;
    f32 f30 = 150.0f - field_0x1b0.g;
    f32 f29 = 150.0f - field_0x1b0.b;
    f32 f28 = 255.0f - field_0x1ac.r;
    f32 f27 = 255.0f - field_0x1ac.g;
    f32 f26 = 220.0f - field_0x1ac.b;
    f32 f25 = 255.0f - field_0x18.mInitAlpha;
    JUtility::TColor black;
    JUtility::TColor white;
    mTimer++;
    black.a = field_0x1b0.a;
    white.a = field_0x1ac.a;
    if (field_0x18.mNowAlpha < field_0x18.mInitAlpha) {
        fopMsgM_setNowAlpha(&field_0x18, fopMsgM_valueIncrease(10, mTimer, 0));
        if (mTimer == 10) {
            resetTimer();
        }
    } else {
        if (mTimer >= 60) {
            black = field_0x1b0;
            white = field_0x1ac;
            fopMsgM_setInitAlpha(&field_0x18);
            resetTimer();
        } else if (mTimer > 30) {
            f32 tmp = fopMsgM_valueIncrease(30, 60 - mTimer, 0);
            black.r = field_0x1b0.r + f31 * tmp;
            black.g = field_0x1b0.g + f30 * tmp;
            black.b = field_0x1b0.b + f29 * tmp;
            white.r = field_0x1ac.r + f28 * tmp;
            white.g = field_0x1ac.g + f27 * tmp;
            white.b = field_0x1ac.b + f26 * tmp;
            field_0x18.mNowAlpha = field_0x18.mInitAlpha + f25 * tmp;
        } else {
            f32 tmp = fopMsgM_valueIncrease(30, mTimer, 0);
            black.r = field_0x1b0.r + f31 * tmp;
            black.g = field_0x1b0.g + f30 * tmp;
            black.b = field_0x1b0.b + f29 * tmp;
            white.r = field_0x1ac.r + f28 * tmp;
            white.g = field_0x1ac.g + f27 * tmp;
            white.b = field_0x1ac.b + f26 * tmp;
            field_0x18.mNowAlpha = field_0x18.mInitAlpha + f25 * tmp;
        }
        ((J2DPicture*)field_0x18.pane)->setBlack(black);
        ((J2DPicture*)field_0x18.pane)->setWhite(white);
    }
}

/* 801E36A8-801E3998       .text createScreen__22dMesg_screenDataTalk_cFv */
void dMesg_screenDataTalk_c::createScreen() {
    JUtility::TColor white(30, 30, 30, 215);
    JUtility::TColor black(30, 30, 75, 0);
    scrn = new J2DScreen();
    JUT_ASSERT(2145, scrn != NULL);
#if VERSION == VERSION_DEMO
    scrn->set("hukidashi_d00.blo", dComIfGp_getMsgArchive());
#else
    scrn->set("hukidashi_d00.blo", dComIfGp_getDmsgArchive());
#endif
    fopMsgM_setPaneData(&field_0x18, scrn->search('dt00'));
    fopMsgM_setPaneData(&field_0x50, scrn->search('yz00'));
    fopMsgM_setPaneData(&field_0x88[0], scrn->search('tx02'));
    fopMsgM_setPaneData(&field_0x88[1], scrn->search('tx03'));
    fopMsgM_setPaneData(&field_0x88[2], scrn->search('txt0'));
    fopMsgM_setPaneData(&field_0x88[3], scrn->search('tx01'));
    fopMsgM_setPaneData(&field_0x168, scrn->search('ms00'));
    if (dComIfGs_getOptRuby()) {
        field_0x88[1].pane->hide();
        field_0x88[3].pane->hide();
        messageOffsetY = -4;
    } else {
        field_0x88[1].pane->show();
        field_0x88[3].pane->show();
        messageOffsetY = 0;
    }
    ((J2DPicture*)field_0x168.pane)->setWhite(white);
    ((J2DPicture*)field_0x168.pane)->setBlack(black);
    setCommonData();
}

/* 801E3998-801E39F8       .text changeFont__22dMesg_screenDataTalk_cFP7JUTFont */
void dMesg_screenDataTalk_c::changeFont(JUTFont* font) {
    ((J2DTextBox*)field_0x88[0].pane)->setFont(font);
    ((J2DTextBox*)field_0x88[1].pane)->setFont(font);
    ((J2DTextBox*)field_0x88[2].pane)->setFont(font);
    ((J2DTextBox*)field_0x88[3].pane)->setFont(font);
}

/* 801E39F8-801E3BBC       .text openAnime__22dMesg_screenDataTalk_cFv */
bool dMesg_screenDataTalk_c::openAnime() {
    /* Nonmatching - fpr regswap */
    f32 f31, f30, f29, f28, tmp;
    bool ret = false;
    mTimer++;
    if (mTimer >= 13) {
        field_0x168.mPosCenter = field_0x168.mPosCenterOrig;
        fopMsgM_paneScaleXY(&field_0x168, 1.0f);
        fopMsgM_setInitAlpha(&field_0x168);
        for (int i = 0; i < 4; i++) {
            fopMsgM_setInitAlpha(&field_0x88[i]);
        }
        ret = true;
    } else {
        if (mTimer < 10) {
            f31 = 100.0f;
            f30 = (f31 * field_0x168.mSizeOrig.y) / field_0x168.mSizeOrig.x;
            f29 = field_0x168.mSizeOrig.x - f31;
            f28 = field_0x168.mSizeOrig.y - f30;
            tmp = fopMsgM_valueIncrease(10, mTimer, 0);
        } else {
            f32 tmp2 = field_0x168.mSizeOrig.x;
            f31 = tmp2;
            f32 tmp3 = field_0x168.mSizeOrig.y;
            f30 = tmp3;
            f29 = 580.0f - f31;
            f28 = (f30 * 580.0f) / f31 - f30;
            tmp = JMASSin((mTimer - 10) * (0x10000 / 6.0f));
        }
        field_0x168.mSize.x = f31 + f29 * tmp;
        field_0x168.mSize.y = f30 + f28 * tmp;
        fopMsgM_cposMove(&field_0x168);
        field_0x1b4 = fopMsgM_valueIncrease(13, mTimer, 0);
        fopMsgM_setNowAlpha(&field_0x168, field_0x1b4);
    }
    return ret;
}

/* 801E3BBC-801E3CE0       .text closeAnime__22dMesg_screenDataTalk_cFv */
bool dMesg_screenDataTalk_c::closeAnime() {
    /* Nonmatching - fpr regswap */
    bool ret = false;
    if (mTimer == 0) {
        for (int i = 0; i < 4; i++) {
            fopMsgM_setNowAlphaZero(&field_0x88[i]);
        }
    }
    mTimer++;
    if (mTimer >= 10) {
        fopMsgM_setNowAlphaZero(&field_0x168);
        ret = true;
    } else {
        f32 f31 = field_0x168.mSizeOrig.x;
        f32 f30 = field_0x168.mSizeOrig.y;
        f32 tmp2 = 620.0f - f31;
        f32 f29 = (f30 / f31) * 620.0f - field_0x168.mSizeOrig.y;
        f32 f1 = fopMsgM_valueIncrease(10, mTimer, 0);
        field_0x168.mSize.x = f31 + tmp2 * f1;
        field_0x168.mSize.y = f30 + f29 * f1;
        field_0x1b4 = 1.0f - f1;
        fopMsgM_cposMove(&field_0x168);
        fopMsgM_setNowAlpha(&field_0x168, field_0x1b4);
    }
    return ret;
}

/* 801E3CE0-801E402C       .text setTextPosition__22dMesg_screenDataTalk_cFUc */
void dMesg_screenDataTalk_c::setTextPosition(u8 param_1) {
    if (param_1 == 1) {
        field_0x168.mPosTopLeftOrig.y = 21.0f;
        field_0x50.mPosTopLeftOrig.y = 180.0f;
        field_0x18.mPosTopLeftOrig.y = 180.0f;
        field_0x88[0].mPosTopLeftOrig.y = messageOffsetY + 64;
        field_0x88[1].mPosTopLeftOrig.y = messageOffsetY + 51;
        field_0x88[2].mPosTopLeftOrig.y = messageOffsetY + 66;
        field_0x88[3].mPosTopLeftOrig.y = messageOffsetY + 53;
    } else if (param_1 == 2) {
        field_0x168.mPosTopLeftOrig.y = 144.0f;
        field_0x50.mPosTopLeftOrig.y = 303.0f;
        field_0x18.mPosTopLeftOrig.y = 303.0f;
        field_0x88[0].mPosTopLeftOrig.y = messageOffsetY + 184;
        field_0x88[1].mPosTopLeftOrig.y = messageOffsetY + 171;
        field_0x88[2].mPosTopLeftOrig.y = messageOffsetY + 186;
        field_0x88[3].mPosTopLeftOrig.y = messageOffsetY + 173;
    } else {
        field_0x168.mPosTopLeftOrig.y = 273.0f;
        field_0x50.mPosTopLeftOrig.y = 432.0f;
        field_0x18.mPosTopLeftOrig.y = 432.0f;
        field_0x88[0].mPosTopLeftOrig.y = messageOffsetY + 318;
        field_0x88[1].mPosTopLeftOrig.y = messageOffsetY + 305;
        field_0x88[2].mPosTopLeftOrig.y = messageOffsetY + 320;
        field_0x88[3].mPosTopLeftOrig.y = messageOffsetY + 307;
    }
    field_0x168.mPosCenterOrig.y = field_0x168.mPosTopLeftOrig.y + field_0x168.mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x168, 0.0f, 0.0f);
    field_0x50.mPosCenterOrig.y = field_0x50.mPosTopLeftOrig.y + field_0x50.mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x50, 0.0f, 0.0f);
    field_0x18.mPosCenterOrig.y = field_0x18.mPosTopLeftOrig.y + field_0x18.mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x18, 0.0f, 0.0f);
    field_0x88[0].mPosCenterOrig.y = field_0x88[0].mPosTopLeftOrig.y + field_0x88[0].mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x88[0], 0.0f, 0.0f);
    field_0x88[1].mPosCenterOrig.y = field_0x88[1].mPosTopLeftOrig.y + field_0x88[1].mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x88[1], 0.0f, 0.0f);
    field_0x88[2].mPosCenterOrig.y = field_0x88[2].mPosTopLeftOrig.y + field_0x88[2].mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x88[2], 0.0f, 0.0f);
    field_0x88[3].mPosCenterOrig.y = field_0x88[3].mPosTopLeftOrig.y + field_0x88[3].mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x88[3], 0.0f, 0.0f);
    field_0x1a4 = field_0x50.mPosTopLeft.y + field_0x50.mSizeOrig.y;
}

/* 801E402C-801E40CC       .text draw__22dMesg_screenDataTalk_cFv */
void dMesg_screenDataTalk_c::draw() {
    fopMsgM_setAlpha(&field_0x18);
    fopMsgM_setAlpha(&field_0x50);
    for (int i = 0; i < 4; i++) {
        fopMsgM_setAlpha(&field_0x88[i]);
    }
    fopMsgM_setAlpha(&field_0x168);
    J2DOrthoGraph* graph = dComIfGp_getCurrentGrafPort();
    graph->setPort();
    scrn->draw(0.0f, 0.0f, graph);
}

/* 801E40CC-801E48D0       .text createScreen__22dMesg_screenDataItem_cFv */
void dMesg_screenDataItem_c::createScreen() {
    scrn = new J2DScreen();
    JUT_ASSERT(2421, scrn != NULL);

    texBuffer = (ResTIMG*)mHeap->alloc(0xc00, 0x20);
    JUT_ASSERT(2424, texBuffer != NULL);

    field_0x3e4 = NULL;
#if VERSION == VERSION_DEMO
    scrn->set("hukidashi_d09.blo", dComIfGp_getMsgArchive());
#else
    scrn->set("hukidashi_d09.blo", dComIfGp_getDmsgArchive());
#endif
    fopMsgM_setPaneData(&field_0x18, scrn->search('dt90'));
    fopMsgM_setPaneData(&field_0x50, scrn->search('yz90'));
    fopMsgM_setPaneData(&field_0x88[0], scrn->search('tx92'));
    fopMsgM_setPaneData(&field_0x88[1], scrn->search('tx93'));
    fopMsgM_setPaneData(&field_0x88[2], scrn->search('tx90'));
    fopMsgM_setPaneData(&field_0x88[3], scrn->search('tx91'));
    fopMsgM_setPaneData(&field_0x168, scrn->search('ms90'));
    fopMsgM_setPaneData(&field_0x1b4, scrn->search('item'));
    fopMsgM_setPaneData(&field_0x1ec, scrn->search('rin1'));
    fopMsgM_setPaneData(&field_0x224[0], scrn->search('lig1'));
    fopMsgM_setPaneData(&field_0x224[1], scrn->search('lig2'));
    fopMsgM_setPaneData(&field_0x224[2], scrn->search('lig3'));
    fopMsgM_setPaneData(&field_0x224[3], scrn->search('lig4'));
    fopMsgM_setPaneData(&field_0x224[4], scrn->search('lig5'));
    fopMsgM_setPaneData(&field_0x224[5], scrn->search('lig6'));
    fopMsgM_setPaneData(&field_0x224[6], scrn->search('lig7'));
    fopMsgM_setPaneData(&field_0x224[7], scrn->search('lig8'));
    if (dComIfGs_getOptRuby()) {
        field_0x88[1].pane->hide();
        field_0x88[3].pane->hide();
        messageOffsetY = -4;
    } else {
        field_0x88[1].pane->show();
        field_0x88[3].pane->show();
        messageOffsetY = 0;
    }
    JMSMesgEntry_c stack_message = *(JMSMesgEntry_c*)dMesg_gpControl->getMessageEntry(nowMesgCode);
    if (dItem_data::getTexture(stack_message.mMsgNo - 101)) {
        JKRArchive* archive = dComIfGp_getItemIconArchive();
        JKRArchive::readTypeResource(texBuffer, 0xc00, 'TIMG', dItem_data::getTexture(stack_message.mMsgNo - 101), archive);
        ((J2DPicture*)field_0x1b4.pane)->changeTexture(texBuffer, 0);
    }
    field_0x168.mPosTopLeftOrig.y += 1.0f;
    field_0x168.mPosCenterOrig.y = field_0x168.mPosTopLeftOrig.y + field_0x168.mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x168, 0.0f, 0.0f);
    field_0x50.mPosTopLeftOrig.y += 1.0f;
    field_0x50.mPosCenterOrig.y = field_0x50.mPosTopLeftOrig.y + field_0x50.mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x50, 0.0f, 0.0f);
    field_0x18.mPosTopLeftOrig.y += 1.0f;
    field_0x18.mPosCenterOrig.y = field_0x18.mPosTopLeftOrig.y + field_0x18.mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x18, 0.0f, 0.0f);
    field_0x88[0].mPosTopLeftOrig.y -= (messageOffsetY + 5);
    field_0x88[0].mPosCenterOrig.y = field_0x88[0].mPosTopLeftOrig.y + field_0x88[0].mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x88[0], 0.0f, 0.0f);
    field_0x88[1].mPosTopLeftOrig.y -= (messageOffsetY + 8);
    field_0x88[1].mPosCenterOrig.y = field_0x88[1].mPosTopLeftOrig.y + field_0x88[1].mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x88[1], 0.0f, 0.0f);
    field_0x88[2].mPosTopLeftOrig.y -= (messageOffsetY + 5);
    field_0x88[2].mPosCenterOrig.y = field_0x88[2].mPosTopLeftOrig.y + field_0x88[2].mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x88[2], 0.0f, 0.0f);
    field_0x88[3].mPosTopLeftOrig.y -= (messageOffsetY + 8);
    field_0x88[3].mPosCenterOrig.y = field_0x88[3].mPosTopLeftOrig.y + field_0x88[3].mSizeOrig.y / 2.0f;
    fopMsgM_paneTrans(&field_0x88[3], 0.0f, 0.0f);
    setCommonData();
    field_0x1a4 = field_0x50.mPosTopLeft.y + field_0x50.mSizeOrig.y;
    if (nowMesgCode == 0x113A) {
        field_0x1b4.pane->hide();
    } else if (nowMesgCode == 0x7f) {
        f32 y = (field_0x1b4.mSize.y / 2.0f + field_0x1b4.pane->getGlbBounds().i.y - 240.0f) - 10.0f;
        f32 x = (field_0x1b4.mSize.x / 2.0f + field_0x1b4.pane->getGlbBounds().i.x - 320.0f) + 10.0f;
        cXyz pos(x, y, 0.0f);
        field_0x3e4 = dComIfGp_particle_set2Dfore(dPa_name::ID_HM_J2_ARWG_FLAME00, &pos);
    }
}

/* 801E48D0-801E4930       .text changeFont__22dMesg_screenDataItem_cFP7JUTFont */
void dMesg_screenDataItem_c::changeFont(JUTFont* font) {
    ((J2DTextBox*)field_0x88[0].pane)->setFont(font);
    ((J2DTextBox*)field_0x88[1].pane)->setFont(font);
    ((J2DTextBox*)field_0x88[2].pane)->setFont(font);
    ((J2DTextBox*)field_0x88[3].pane)->setFont(font);
}

/* 801E4930-801E49B4       .text deleteScreen__22dMesg_screenDataItem_cFv */
void dMesg_screenDataItem_c::deleteScreen() {
    delete scrn;
    if (field_0x3e4) {
        field_0x3e4->becomeInvalidEmitter();
        field_0x3e4->quitImmortalEmitter();
    }
    mHeap->free(texBuffer);
}

/* 801E49B4-801E4AE8       .text openAnime__22dMesg_screenDataItem_cFv */
bool dMesg_screenDataItem_c::openAnime() {
    static const f32 frameScale[] = {0.6f, 1.1f, 1.0f};

    bool ret = false;
    mTimer++;
    if (mTimer >= 8) {
        field_0x168.mPosCenter.x = field_0x168.mPosCenterOrig.x;
        field_0x168.mPosCenter.y = field_0x168.mPosCenterOrig.y;
        fopMsgM_paneScaleXY(&field_0x168, 1.0f);
        fopMsgM_setInitAlpha(&field_0x168);
        for (int i = 0; i < 4; i++) {
            fopMsgM_setInitAlpha(&field_0x88[i]);
        }
        ret = true;
    } else if (mTimer <= 5) {
        f32 f31, tmp;
        f31 = tmp = fopMsgM_valueIncrease(5, mTimer, 0);
        f31 = f31 * (frameScale[1] - frameScale[0]) + frameScale[0];
        fopMsgM_paneScaleXY(&field_0x168, f31);
        fopMsgM_setNowAlpha(&field_0x168, tmp);
    } else {
        f32 f1, tmp;
        f1 = tmp = fopMsgM_valueIncrease(3, mTimer - 5, 0);
        tmp = tmp * (frameScale[2] - frameScale[1]) + frameScale[1];
        fopMsgM_paneScaleXY(&field_0x168, tmp);
        fopMsgM_setInitAlpha(&field_0x168);
    }
    return ret;
}

/* 801E4AE8-801E4C40       .text closeAnime__22dMesg_screenDataItem_cFv */
bool dMesg_screenDataItem_c::closeAnime() {
    /* Nonmatching - fpr regswap */
    bool ret = false;
    if (mTimer == 0) {
        for (int i = 0; i < 4; i++) {
            fopMsgM_setNowAlphaZero(&field_0x88[i]);
        }
        fopMsgM_setNowAlphaZero(&field_0x1b4);
        fopMsgM_setNowAlphaZero(&field_0x1ec);
        for (int i = 0; i < 8; i++) {
            fopMsgM_setNowAlphaZero(&field_0x224[i]);
        }
    }
    mTimer++;
    if (mTimer >= 10) {
        fopMsgM_setNowAlphaZero(&field_0x168);
        ret = true;
    } else {
        f32 f31 = field_0x168.mSizeOrig.x;
        f32 f30 = field_0x168.mSizeOrig.y;
        f32 tmp2 = 620.0f - f31;
        f32 f29 = (f30 / f31) * 620.0f - field_0x168.mSizeOrig.y;
        f32 f1 = fopMsgM_valueIncrease(10, mTimer, 0);
        field_0x168.mSize.x = f31 + tmp2 * f1;
        field_0x168.mSize.y = f30 + f29 * f1;
        field_0x3e8 = 1.0f - f1;
        fopMsgM_cposMove(&field_0x168);
        fopMsgM_setNowAlpha(&field_0x168, field_0x3e8);
    }
    return ret;
}

/* 801E4C40-801E4D04       .text move__22dMesg_screenDataItem_cFv */
void dMesg_screenDataItem_c::move() {
    ringMove();
    lightMove();
    cornerMove();
    if (field_0x3e4) {
        cXyz sp08(
            (field_0x1b4.mSize.x / 2.0f + field_0x1b4.pane->getGlbBounds().i.x - 320.0f) + 10.0f,
            (field_0x1b4.mSize.y / 2.0f + field_0x1b4.pane->getGlbBounds().i.y - 240.0f) - 10.0f,
            0.0f
        );
        field_0x3e4->setGlobalTranslation(sp08);
        field_0x3e4->playDrawParticle();
        field_0x3e4->setGlobalAlpha(field_0x1b4.mNowAlpha);
    }
}

/* 801E4D04-801E4E14       .text draw__22dMesg_screenDataItem_cFv */
void dMesg_screenDataItem_c::draw() {
    fopMsgM_setAlpha(&field_0x18);
    fopMsgM_setAlpha(&field_0x50);
    for (int i = 0; i < 4; i++) {
        fopMsgM_setAlpha(&field_0x88[i]);
    }
    fopMsgM_setAlpha(&field_0x168);
    fopMsgM_setAlpha(&field_0x1b4);
    fopMsgM_setAlpha(&field_0x1ec);
    for (int i = 0; i < 8; i++) {
        fopMsgM_setAlpha(&field_0x224[i]);
    }
    J2DOrthoGraph* graph = dComIfGp_getCurrentGrafPort();
    graph->setPort();
    scrn->draw(0.0f, 0.0f, graph);
    for (int i = 0; i < 18; i++) {
        if (mMesg->outfont[i] && mMesg->outfont[i]->getTimer() != -1) {
            mMesg->outfont[i]->_draw();
        }
    }
}

/* 801E4E14-801E4EBC       .text ringMove__22dMesg_screenDataItem_cFv */
void dMesg_screenDataItem_c::ringMove() {
    field_0x1ec.mUserArea++;
    if (field_0x1ec.mUserArea >= 120) {
        field_0x1ec.mUserArea = 0;
    }
    f32 tmp;
    if (field_0x1ec.mUserArea < 60) {
        tmp = fopMsgM_valueIncrease(60, field_0x1ec.mUserArea, 0);
    } else {
        tmp = fopMsgM_valueIncrease(60, 120 - field_0x1ec.mUserArea, 0);
    }
    if (field_0x168.mNowAlpha == field_0x168.mInitAlpha && field_0x168.mSize.x == field_0x168.mSizeOrig.x) {
        fopMsgM_setNowAlpha(&field_0x1ec, tmp * 0.25f + 0.25f);
    }
}

/* 801E4EBC-801E524C       .text lightMove__22dMesg_screenDataItem_cFv */
void dMesg_screenDataItem_c::lightMove() {
    field_0x224[0].mUserArea++;
    if (field_0x224[0].mUserArea >= 800) {
        field_0x224[0].mUserArea = 0;
    }
    f32 f31 = (field_0x224[0].mUserArea / 800.0f) * 360.0f;
    field_0x224[0].pane->rotate((int)field_0x224[0].mSize.x, 0.0f, ROTATE_Z, -f31);
    field_0x224[1].pane->rotate(0.0f, 0.0f, ROTATE_Z, -f31);
    field_0x224[2].pane->rotate((int)field_0x224[2].mSize.x, (int)field_0x224[2].mSize.y, ROTATE_Z, -f31);
    field_0x224[3].pane->rotate(0.0f, (int)field_0x224[3].mSize.y, ROTATE_Z, -f31);
    field_0x224[4].pane->rotate((int)field_0x224[4].mSize.x, 0.0f, ROTATE_Z, f31);
    field_0x224[5].pane->rotate(0.0f, 0.0f, ROTATE_Z, f31);
    field_0x224[6].pane->rotate((int)field_0x224[6].mSize.x, (int)field_0x224[6].mSize.y, ROTATE_Z, f31);
    field_0x224[7].pane->rotate(0.0f, (int)field_0x224[7].mSize.y, ROTATE_Z, f31);
    if (field_0x168.mNowAlpha == field_0x168.mInitAlpha && field_0x168.mSize.x == field_0x168.mSizeOrig.x) {
        for (int i = 0; i < 8; i++) {
            fopMsgM_setInitAlpha(&field_0x224[i]);
        }
        fopMsgM_setInitAlpha(&field_0x1b4);
    }
}

/* 801E524C-801E5938       .text cornerMove__22dMesg_screenDataItem_cFv */
void dMesg_screenDataItem_c::cornerMove() {
    static const u8 cc_r[] = {200, 0, 0, 0};
    static const u8 cc_g[] = {128, 0, 0, 0};
    static const u8 cc_b[] = {255, 0, 255, 0};

    int r4 = g_msgHIO.field_0x7f * 4;
    field_0x168.mUserArea++;
    if (field_0x168.mUserArea >= r4) {
        field_0x168.mUserArea = 0;
    }
    f32 tmp = fopMsgM_valueIncrease(g_msgHIO.field_0x7f, field_0x168.mUserArea % g_msgHIO.field_0x7f, 2);
    GXColor local_68[4];
    for (int i = 0; i < 4; i++) {
        int r9 = i + 1;
        if (r9 >= 4) {
            r9 = 0;
        }
        local_68[i].r = cc_r[i] + tmp * (cc_r[r9] - cc_r[i]);
        local_68[i].g = cc_g[i] + tmp * (cc_g[r9] - cc_g[i]);
        local_68[i].b = cc_b[i] + tmp * (cc_b[r9] - cc_b[i]);
        local_68[i].a = 255;
    }
    if (field_0x168.mUserArea < g_msgHIO.field_0x7f) {
        ((J2DPicture*)field_0x168.pane)->setCornerColor(local_68[0], local_68[1], local_68[3], local_68[2]);
    } else if (field_0x168.mUserArea < g_msgHIO.field_0x7f * 2) {
        ((J2DPicture*)field_0x168.pane)->setCornerColor(local_68[1], local_68[2], local_68[0], local_68[3]);
    } else if (field_0x168.mUserArea < g_msgHIO.field_0x7f * 3) {
        ((J2DPicture*)field_0x168.pane)->setCornerColor(local_68[2], local_68[3], local_68[1], local_68[0]);
    } else {
        ((J2DPicture*)field_0x168.pane)->setCornerColor(local_68[3], local_68[0], local_68[2], local_68[1]);
    }
}

/* 801E5938-801E5ADC       .text dMesg_initialize__FP14sub_mesg_class */
void dMesg_initialize(sub_mesg_class* i_Msg) {
    dMesg_gpResourceContainer = new JMessage::TResourceContainer();
    JUT_ASSERT(2901, dMesg_gpResourceContainer != NULL);

    dMesg_gpControl = dComIfGp_demo_get()->getMesgControl();
    dMesg_gpSequenceProcessor = new dMesg_tSequenceProcessor(dMesg_gpControl);
    JUT_ASSERT(2906, dMesg_gpSequenceProcessor != NULL);

    dMesg_gpRenderingProcessor = new dMesg_tRenderingProcessor(dMesg_gpControl);
    JUT_ASSERT(2909, dMesg_gpRenderingProcessor != NULL);

    dMesg_gpControl->mResourceContainer = dMesg_gpResourceContainer;
    dMesg_gpControl->setSequenceProcessor(dMesg_gpSequenceProcessor);
    dMesg_gpControl->setRenderingProcessor(dMesg_gpRenderingProcessor);
    dMesg_gpControl->setMainFont(dMesg_gpFont);
    dMesg_gpControl->setRubyFont(dMesg_gpRFont);
    dMesg_gpSequenceProcessor->setMesg(i_Msg);
    oldMesgCode = 0;
}

/* 801E5ADC-801E5B58       .text dMesg_finalize__Fv */
void dMesg_finalize() {
    delete dMesg_gpResourceContainer;
    delete dMesg_gpSequenceProcessor;
    delete dMesg_gpRenderingProcessor;
}

/* 801E5C8C-801E5E14       .text dMesg_parse__Fv */
int dMesg_parse() {
#if VERSION > VERSION_JPN
    headerFlag = false;
#endif
    header = JKRGetResource('ROOT', "zel_00.bmg", dComIfGp_getMsgDtArchive());
    JUT_ASSERT(2956, header != NULL);
#if VERSION > VERSION_JPN
    header2 = JKRGetResource('ROOT', "zel_01.bmg", dComIfGp_getMsgDt2Archive());
    JUT_ASSERT(2961, header2 != NULL);
#endif
    oParse = new JMessage::TParse(dMesg_gpResourceContainer);
    JUT_ASSERT(2964, oParse != NULL);

    oParse->parse(header, 0);
#if VERSION > VERSION_JPN
    oParse->parse(header2, 0);
#endif
    return 1;
}

/* 801E5E14-801E5E38       .text dMesg_reset__Fv */
void dMesg_reset() {
    dMesg_gpControl->reset();
}

/* 801E5E38-801E5E60       .text dMesg_update__Fv */
void dMesg_update() {
    dMesg_gbUpdate = dMesg_gpControl->update();
}

/* 801E5E60-801E5E84       .text dMesg_render__Fv */
void dMesg_render() {
    dMesg_gpControl->render();
}

/* 801E5E84-801E5FB0       .text dMesg_fontsizeCenter__FP14sub_mesg_classii */
void dMesg_fontsizeCenter(sub_mesg_class* i_Msg, int param_2, int param_3) {
    char local_38[12];
    char local_2c[24];

    int var1 = param_3 - param_2;
    int var2 = var1 / 2;
    if (var2 > 0) {
        sprintf(local_2c, "\x1b" "FX[%d]" "\x1b" "FY[%d]", param_3, param_3);
        local_38[0] = 0;
        strcat(i_Msg->text[0], local_2c);
        strcat(i_Msg->text[1], local_38);
        strcat(i_Msg->text[2], local_2c);
        strcat(i_Msg->text[3], local_38);
    } else if (var2 < 0) {
        sprintf(local_2c, "\x1b" "FX[%d]" "\x1b" "FY[%d]", param_3, param_3);
        local_38[0] = 0;
        strcat(i_Msg->text[0], local_2c);
        strcat(i_Msg->text[1], local_38);
        strcat(i_Msg->text[2], local_2c);
        strcat(i_Msg->text[3], local_38);
    } else if (param_2 != param_3) {
        sprintf(local_2c, "\x1b" "FX[%d]" "\x1b" "FY[%d]", param_3, param_3);
        strcat(i_Msg->text[0], local_2c);
        strcat(i_Msg->text[2], local_2c);
    }
}

/* 801E5FB0-801E627C       .text dMesg_hyrule_language_check__FUl */
bool dMesg_hyrule_language_check(u32 param_1) {
    if (dComIfGs_getClearCount()) {
        return false;
    }
    switch (param_1) {
    case 0x3a3:
        dMesg_gpControl->setMessageCode(1, 0);
        return true;
    case 0x3a5:
        dMesg_gpControl->setMessageCode(1, 1);
        return true;
    case 0x3a7:
        dMesg_gpControl->setMessageCode(1, 2);
        return true;
    case 0x3a9:
        dMesg_gpControl->setMessageCode(1, 3);
        return true;
    case 0x3ab:
        dMesg_gpControl->setMessageCode(1, 4);
        return true;
    case 0x3ad:
        dMesg_gpControl->setMessageCode(1, 5);
        return true;
    case 0x3ae:
        dMesg_gpControl->setMessageCode(1, 6);
        return true;
    case 0x3af:
        dMesg_gpControl->setMessageCode(1, 7);
        return true;
    case 0x3b1:
        dMesg_gpControl->setMessageCode(1, 8);
        return true;
    case 0x3b3:
        dMesg_gpControl->setMessageCode(1, 9);
        return true;
    case 0x4e8:
        dMesg_gpControl->setMessageCode(1, 10);
        return true;
    case 0x4ea:
        dMesg_gpControl->setMessageCode(1, 11);
        return true;
    case 0x500:
        dMesg_gpControl->setMessageCode(1, 12);
        return true;
    case 0x501:
        dMesg_gpControl->setMessageCode(1, 13);
        return true;
    case 0x70a:
        dMesg_gpControl->setMessageCode(1, 14);
        return true;
    }
    return false;
}

/* 801E627C-801E62F8       .text dMesg_fontsizeCenter__FP14sub_mesg_classiiii */
void dMesg_fontsizeCenter(sub_mesg_class* i_Msg, int param_2, int param_3, int param_4, int param_5) {
    char local_38[12];
    char local_2c[24];

    sprintf(local_2c, "\x1b" "FX[%d]" "\x1b" "FY[%d]", param_3, param_3);
    local_38[0] = 0;
    strcat(i_Msg->text[0], local_2c);
    strcat(i_Msg->text[1], local_38);
    strcat(i_Msg->text[2], local_2c);
    strcat(i_Msg->text[3], local_38);
}

/* 801E62F8-801E6760       .text dMesg_waitProc__FP14sub_mesg_class */
void dMesg_waitProc(sub_mesg_class* i_Msg) {
    nowMesgCode = dMesg_gpControl->getMessageCode();
    zenkaku = 0;
    zenkakuCode = 0;
    if (oldMesgCode != nowMesgCode) {
        if (dMesg_hyrule_language_check(dMesg_gpControl->getMessageCode())) {
            nowMesgCode = dMesg_gpControl->getMessageCode();
            if (!headerFlag) {
                dMesg_gpControl->setMainFont(dMesg_gpRFont);
                headerFlag = true;
            }
        } else {
            if (headerFlag) {
                dMesg_gpControl->setMainFont(dMesg_gpFont);
                headerFlag = false;
            }
        }
        i_Msg->field_0x100 = JKRCreateExpHeap(0xa32d, i_Msg->heap, false);
        JKRHeap* heap = mDoExt_setCurrentHeap(i_Msg->field_0x100);
        for (int i = 0; i < 4; i++) {
            if (!i_Msg->text[i]) {
                i_Msg->text[i] = (char*)i_Msg->field_0x100->alloc(1001, 4);
                JUT_ASSERT(3304, i_Msg->text[i] != NULL);
            }
        }
        if (!i_Msg->screen) {
            JMSMesgEntry_c stack_3c = *(JMSMesgEntry_c*)dMesg_gpControl->getMessageEntry(nowMesgCode);
            if (stack_3c.mTextboxType == 9) {
                i_Msg->screen = new dMesg_screenDataItem_c();
            } else {
                i_Msg->screen = new dMesg_screenDataTalk_c();
            }
            JUT_ASSERT(3317, i_Msg->screen != NULL);
            i_Msg->screen->setMesg(i_Msg);
            i_Msg->screen->setHeap(i_Msg->field_0x100);
            if (headerFlag) {
                i_Msg->screen->setFont(dMesg_gpRFont, dMesg_gpRFont);
            } else {
                i_Msg->screen->setFont(dMesg_gpFont, dMesg_gpRFont);
            }
            i_Msg->screen->createScreen();
            i_Msg->screen->setTextPosition(stack_3c.mTextboxPosition);
            dMesg_gbUpdate = true;
            i_Msg->field_0x164 = 2;
            dMesg_gpSequenceProcessor->setNowColor(0xFFFFFFFF);
            mDoAud_talkIn();
            mDoAud_seStart(JA_SE_TALK_WIN_OPEN);
        } else if (headerFlag) {
            i_Msg->screen->changeFont(dMesg_gpRFont);
        } else {
            i_Msg->screen->changeFont(dMesg_gpFont);
        }
        for (int i = 0; i < 18; i++) {
            if (!i_Msg->outfont[i]) {
                i_Msg->outfont[i] = new dMesg_outFont_c();
                JUT_ASSERT(3360, i_Msg->outfont[i]);
                i_Msg->outfont[i]->_create();
            }
        }
        oldMesgCode = nowMesgCode;
        mDoExt_setCurrentHeap(heap);
    }
}

/* 801E67C8-801E6908       .text dMesg_openProc__FP14sub_mesg_class */
void dMesg_openProc(sub_mesg_class* i_Msg) {
    JKRHeap* oldHeap = mDoExt_setCurrentHeap(i_Msg->field_0x100);
    if (i_Msg->screen->openAnime()) {
        for (int i = 0; i < 4; i++) {
            i_Msg->screen->initString(i_Msg->text[i], i);
            i_Msg->screen->setString(i_Msg->text[i], i);
        }
        i_Msg->field_0x164 = 6;
        JMSMesgEntry_c stack_3c = *(JMSMesgEntry_c*)dMesg_gpControl->getMessageEntry(nowMesgCode);
        if (stack_3c.mInitialSound) {
            mDoAud_messageSePlay(stack_3c.mInitialSound, NULL, dComIfGp_getReverb(dComIfGp_roomControl_getStayNo()));
        }
    }
    mDoExt_setCurrentHeap(oldHeap);
}

/* 801E6908-801E69D4       .text dMesg_outnowProc__FP14sub_mesg_class */
void dMesg_outnowProc(sub_mesg_class* i_Msg) {
    JKRHeap* oldHeap = mDoExt_setCurrentHeap(i_Msg->field_0x100);
    dMesg_update();
    dMesg_render();
    for (int i = 0; i < 4; i++) {
        i_Msg->screen->setString(i_Msg->text[i], i);
    }
    if (dMesg_gpSequenceProcessor->getStopFlag() == 1) {
        i_Msg->screen->arwAnimeInit();
        i_Msg->field_0x164 = 5;
    } else if (dMesg_gpSequenceProcessor->getStopFlag() == 2) {
        i_Msg->field_0x164 = 7;
    } else if (dMesg_gbUpdate == 0) {
        i_Msg->screen->dotAnimeInit();
        i_Msg->field_0x164 = 10;
    }
    mDoExt_setCurrentHeap(oldHeap);
}

/* 801E69D4-801E6B10       .text dMesg_outwaitProc__FP14sub_mesg_class */
void dMesg_outwaitProc(sub_mesg_class* i_Msg) {
    JKRHeap* oldHeap = mDoExt_setCurrentHeap(i_Msg->field_0x100);
    if (CPad_CHECK_TRIG_A(0) || CPad_CHECK_TRIG_B(0)) {
        for (int i = 0; i < 4; i++) {
            i_Msg->screen->initString(i_Msg->text[i], i);
            i_Msg->screen->setString(i_Msg->text[i], i);
        }
        i_Msg->screen->arwAnimeInit();
        dMesg_gpSequenceProcessor->initialize(dMesg_gpControl->getLineStart());
        if (CPad_CHECK_TRIG_B(0)) {
            dMesg_gpSequenceProcessor->setShortCutFlag();
        }
        for (int i = 0; i < 18; i++) {
            i_Msg->outfont[i]->_initialize();
        }
        i_Msg->field_0x164 = 6;
        mDoAud_seStart(JA_SE_TALK_NEXT);
    } else {
        i_Msg->screen->arwAnime();
    }
    mDoExt_setCurrentHeap(oldHeap);
}

/* 801E6B10-801E6BB8       .text dMesg_stopProc__FP14sub_mesg_class */
void dMesg_stopProc(sub_mesg_class* i_Msg) {
    JKRHeap* oldHeap = mDoExt_setCurrentHeap(i_Msg->field_0x100);
    if (dMesg_gpSequenceProcessor->decWaitRest() == 0) {
        i_Msg->field_0x164 = 18;
        mDoAud_talkOut();
        mDoAud_seStart(JA_SE_TALK_WIN_CLOSE);
    }
    mDoExt_setCurrentHeap(oldHeap);
}

/* 801E6BB8-801E6C6C       .text dMesg_closewaitProc__FP14sub_mesg_class */
void dMesg_closewaitProc(sub_mesg_class* i_Msg) {
    JKRHeap* oldHeap = mDoExt_setCurrentHeap(i_Msg->field_0x100);
    if (CPad_CHECK_TRIG_A(0) || CPad_CHECK_TRIG_B(0)) {
        i_Msg->screen->dotAnimeInit();
        i_Msg->field_0x164 = 18;
        mDoAud_talkOut();
        mDoAud_seStart(JA_SE_TALK_WIN_CLOSE);
    } else {
        i_Msg->screen->dotAnime();
    }
    mDoExt_setCurrentHeap(oldHeap);
}

/* 801E6C6C-801E6E00       .text dMesg_closeProc__FP14sub_mesg_class */
void dMesg_closeProc(sub_mesg_class* i_Msg) {
    JKRHeap* oldHeap = mDoExt_setCurrentHeap(i_Msg->field_0x100);
    if (i_Msg->screen->closeAnime()) {
        i_Msg->screen->deleteScreen();
#if VERSION == VERSION_DEMO
        dComIfGp_getMsgArchive()->removeResourceAll();
#else
        dComIfGp_getDmsgArchive()->removeResourceAll();
#endif
        delete (void*)i_Msg->screen;
        i_Msg->screen = NULL;
        dMesg_reset();
        for (int i = 0; i < 18; i++) {
            if (i_Msg->outfont[i]) {
                i_Msg->outfont[i]->_delete();
                delete (void*)i_Msg->outfont[i];
                i_Msg->outfont[i] = NULL;
            }
        }
        for (int i = 0; i < 4; i++) {
            i_Msg->field_0x100->free(i_Msg->text[i]);
            i_Msg->text[i] = NULL;
        }
        mDoExt_setCurrentHeap(oldHeap);
        i_Msg->field_0x100->freeAll();
        i_Msg->field_0x100->destroy();
        i_Msg->field_0x100 = NULL;
        i_Msg->field_0x164 = 0;
        dComIfGp_demo_get()->getControl()->unsuspend(1);
    } else {
        for (int i = 0; i < 18; i++) {
            if (i_Msg->outfont[i]) {
                i_Msg->outfont[i]->_setAlpha(0);
            }
        }
        mDoExt_setCurrentHeap(oldHeap);
    }
}

/* 801E6E00-801E6E44       .text dMsg_Draw__FP14sub_mesg_class */
static BOOL dMsg_Draw(sub_mesg_class* i_Msg) {
    if (i_Msg->screen) {
        dComIfGd_set2DOpa(i_Msg->screen);
    }
    return true;
}

/* 801E6E44-801E6F34       .text dMsg_Execute__FP14sub_mesg_class */
static BOOL dMsg_Execute(sub_mesg_class* i_Msg) {
    JKRHeap* oldHeap = mDoExt_setCurrentHeap(i_Msg->heap);
    if (i_Msg->field_0x164 == 0) {
        dMesg_waitProc(i_Msg);
    } else if (i_Msg->field_0x164 == 2) {
        dMesg_openProc(i_Msg);
    } else if (i_Msg->field_0x164 == 6) {
        dMesg_outnowProc(i_Msg);
    } else if (i_Msg->field_0x164 == 5) {
        dMesg_outwaitProc(i_Msg);
    } else if (i_Msg->field_0x164 == 7) {
        dMesg_stopProc(i_Msg);
    } else if (i_Msg->field_0x164 == 10) {
        dMesg_closewaitProc(i_Msg);
    } else if (i_Msg->field_0x164 == 18) {
        dMesg_closeProc(i_Msg);
    }
    if (i_Msg->screen) {
        i_Msg->screen->move();
    }
    mDoExt_setCurrentHeap(oldHeap);
    return true;
}

/* 801E6F38-801E6F40       .text dMsg_IsDelete__FP14sub_mesg_class */
static BOOL dMsg_IsDelete(sub_mesg_class*) {
    return 1;
}

/* 801E6F40-801E7130       .text dMsg_Delete__FP14sub_mesg_class */
static BOOL dMsg_Delete(sub_mesg_class* i_Msg) {
    JKRHeap* heap = mDoExt_setCurrentHeap(i_Msg->heap);
    mDoExt_removeMesgFont();
    mDoExt_removeRubyFont();
    if (i_Msg->field_0x100) {
        mDoExt_setCurrentHeap(i_Msg->field_0x100);
        if (i_Msg->screen) {
            i_Msg->screen->deleteScreen();
#if VERSION == VERSION_DEMO
            dComIfGp_getMsgArchive()->removeResourceAll();
#else
            dComIfGp_getDmsgArchive()->removeResourceAll();
#endif
            delete (void*)i_Msg->screen;
            i_Msg->screen = NULL;
        }
        for (int i = 0; i < 18; i++) {
            if (i_Msg->outfont[i]) {
                i_Msg->outfont[i]->_delete();
                delete (void*)i_Msg->outfont[i];
                i_Msg->outfont[i] = NULL;
            }
        }
        for (int i = 0; i < 4; i++) {
            i_Msg->field_0x100->free(i_Msg->text[i]);
            i_Msg->text[i] = NULL;
        }
        if (i_Msg->field_0x100) {
            i_Msg->field_0x100->freeAll();
            i_Msg->field_0x100->destroy();
            i_Msg->field_0x100 = NULL;
        }
    }

    dMesg_gpResourceContainer->Clear_destroy();

    dMesg_finalize();
    if (header) {
        JKRFileLoader::removeResource(header, NULL);
    } if (header2) {
        JKRFileLoader::removeResource(header2, NULL);
    }
    if (oParse) {
        delete oParse;
    }
    mDoExt_setCurrentHeap(heap);
    fopMsgM_destroyExpHeap(i_Msg->heap);
    return 1;
}

/* 801E7130-801E7290       .text dMsg_Create__FP9msg_class */
static cPhs_State dMsg_Create(msg_class* i_this) {
    sub_mesg_class* i_Msg = (sub_mesg_class*)i_this;
    i_Msg->heap = fopMsgM_createExpHeap(0xb6b5);
    JUT_ASSERT(3864, i_Msg->heap != NULL);
    JKRHeap* oldHeap = mDoExt_setCurrentHeap(i_Msg->heap);

    dMesg_gpFont = mDoExt_getMesgFont();
    JUT_ASSERT(3869, dMesg_gpFont != NULL);

    dMesg_gpRFont = mDoExt_getRubyFont();
    JUT_ASSERT(3872, dMesg_gpRFont != NULL);

    dMesg_initialize(i_Msg);
    dMesg_parse();
    for (int i = 0; i < 4; i++) {
        i_Msg->text[i] = NULL;
    }
    i_Msg->field_0x164 = 0;
    mDoExt_setCurrentHeap(oldHeap);
    return cPhs_COMPLEATE_e;
}

/* 801E7290-801E72D8       .text __dt__15dMesg_outFont_cFv */
dMesg_outFont_c::~dMesg_outFont_c() {
}

static msg_method_class l_dMesg_Method = {
    (process_method_func)dMsg_Create, (process_method_func)dMsg_Delete,
    (process_method_func)dMsg_Execute, (process_method_func)dMsg_IsDelete,
    (process_method_func)dMsg_Draw
};

msg_process_profile_definition g_profile_MESG = {
    /* Layer ID     */ fpcLy_CURRENT_e,
    /* List ID      */ 12,
    /* List Prio    */ fpcPi_CURRENT_e,
    /* Proc Name    */ fpcNm_MESG_e,
    /* Proc SubMtd  */ &g_fpcLf_Method.base,
    /* Size         */ sizeof(sub_mesg_class),
    /* Size Other   */ 0,
    /* Parameters   */ 0,
    /* Leaf SubMtd  */ &g_fopMsg_Method,
    /* Draw Prio    */ fpcDwPi_MESG_e,
    /* Msg SubMtd   */ &l_dMesg_Method,
};
