diff options
Diffstat (limited to 'arm9/src/bg_window.c')
-rw-r--r-- | arm9/src/bg_window.c | 5456 |
1 files changed, 5456 insertions, 0 deletions
diff --git a/arm9/src/bg_window.c b/arm9/src/bg_window.c new file mode 100644 index 00000000..2986645f --- /dev/null +++ b/arm9/src/bg_window.c @@ -0,0 +1,5456 @@ +#include "global.h" +#include "bg_window.h" +#include "GX_layers.h" +#include "game_init.h" +#include "gx.h" +#include "heap.h" + +const u8 sTilemapWidthByBufferSize[] = { + [GF_BG_SCR_SIZE_128x128] = 0x10, + [GF_BG_SCR_SIZE_256x256] = 0x20, + [GF_BG_SCR_SIZE_256x512] = 0x20, + [GF_BG_SCR_SIZE_512x256] = 0x20, + [GF_BG_SCR_SIZE_512x512] = 0x20, + [GF_BG_SCR_SIZE_1024x1024] = 0x20, +}; + +void (*const sScheduleWindowCopyToVramFuncs[])(struct Window *) = { + ScheduleWindowCopyToVram_TextMode, + ScheduleWindowCopyToVram_AffineMode, + ScheduleWindowCopyToVram_TextMode, +}; + +void (*const sClearWindowTilemapAndCopyToVramFuncs[])(struct Window *) = { + ClearWindowTilemapAndCopyToVram_TextMode, + ClearWindowTilemapAndCopyToVram_AffineMode, + ClearWindowTilemapAndCopyToVram_TextMode, +}; + +void (*const sClearWindowTilemapAndScheduleTransferFuncs[])(struct Window *) = { + ClearWindowTilemapAndScheduleTransfer_TextMode, + ClearWindowTilemapAndScheduleTransfer_AffineMode, + ClearWindowTilemapAndScheduleTransfer_TextMode, +}; + +void (*const sPutWindowTilemapFuncs[])(struct Window *) = { + PutWindowTilemap_TextMode, + PutWindowTilemap_AffineMode, + PutWindowTilemap_TextMode, +}; + +void (*const sCopyWindowToVramFuncs[])(struct Window *) = { + CopyWindowToVram_TextMode, + CopyWindowToVram_AffineMode, + CopyWindowToVram_TextMode, +}; + +void (*const sClearWindowTilemapFuncs[])(struct Window *) = { + ClearWindowTilemapText, + ClearWindowTilemapAffine, + ClearWindowTilemapText, +}; + +THUMB_FUNC struct BgConfig *BgConfig_Alloc(u32 heap_id) +{ + struct BgConfig *ptr = AllocFromHeap(heap_id, sizeof(struct BgConfig)); + memset(ptr, 0, sizeof(struct BgConfig)); + ptr->heap_id = heap_id; + ptr->scrollScheduled = 0; + ptr->bufferTransferScheduled = 0; + + return ptr; +} + +THUMB_FUNC u32 BgConfig_GetHeapId(struct BgConfig *bgConfig) +{ + return bgConfig->heap_id; +} + +THUMB_FUNC void SetBothScreensModesAndDisable(const struct GraphicsModes *modes) +{ + GX_SetGraphicsMode(modes->dispMode, modes->bgMode, modes->_2d3dMode); + GXS_SetGraphicsMode(modes->subMode); + GX_SetBGScrOffset(0); + GX_SetBGCharOffset(0); + + GX_DisableEngineALayers(); + GX_DisableEngineBLayers(); +} + +THUMB_FUNC void SetScreenModeAndDisable(const struct GraphicsModes *gfxModes, u32 whichScreen) +{ + if (whichScreen == 0) + { + GX_SetGraphicsMode(gfxModes->dispMode, gfxModes->bgMode, gfxModes->_2d3dMode); + GX_DisableEngineALayers(); + } + else + { + GXS_SetGraphicsMode(gfxModes->subMode); + GX_DisableEngineBLayers(); + } +} + +THUMB_FUNC void InitBgFromTemplate( + struct BgConfig *bgConfig, u8 bgId, const struct BgTemplate *template, u8 bgMode) +{ + u8 screenSize = TranslateGFBgModePairToGXScreenSize(template->size, bgMode); + switch (bgId) + { + case GF_BG_LYR_MAIN_0: + GX_EngineAToggleLayers(GF_BG_LYR_MAIN_0_F, GX_LAYER_TOGGLE_ON); + G2_SetBG0Control(screenSize, template->colorMode, template->screenBase, template->charBase, template->bgExtPltt); + G2_SetBG0Priority(template->priority); + G2_BG0Mosaic(template->mosaic); + break; + + case GF_BG_LYR_MAIN_1: + GX_EngineAToggleLayers(GF_BG_LYR_MAIN_1_F, GX_LAYER_TOGGLE_ON); + G2_SetBG1Control(screenSize, template->colorMode, template->screenBase, template->charBase, template->bgExtPltt); + G2_SetBG1Priority(template->priority); + G2_BG1Mosaic(template->mosaic); + break; + + case GF_BG_LYR_MAIN_2: + GX_EngineAToggleLayers(GF_BG_LYR_MAIN_2_F, GX_LAYER_TOGGLE_ON); + switch (bgMode) + { + default: + case GF_BG_TYPE_TEXT: + G2_SetBG2ControlText(screenSize, template->colorMode, template->screenBase, template->charBase); + break; + case GF_BG_TYPE_AFFINE: + G2_SetBG2ControlAffine(screenSize, template->areaOver, template->screenBase, template->charBase); + break; + case GF_BG_TYPE_256x16PLTT: + G2_SetBG2Control256x16Pltt(screenSize, template->areaOver, template->screenBase, template->charBase); + break; + } + G2_SetBG2Priority(template->priority); + G2_BG2Mosaic(template->mosaic); + break; + + case GF_BG_LYR_MAIN_3: + GX_EngineAToggleLayers(GF_BG_LYR_MAIN_3_F, GX_LAYER_TOGGLE_ON); + switch (bgMode) + { + default: + case GF_BG_TYPE_TEXT: + G2_SetBG3ControlText(screenSize, template->colorMode, template->screenBase, template->charBase); + break; + case GF_BG_TYPE_AFFINE: + G2_SetBG3ControlAffine(screenSize, template->areaOver, template->screenBase, template->charBase); + break; + case GF_BG_TYPE_256x16PLTT: + G2_SetBG3Control256x16Pltt(screenSize, template->areaOver, template->screenBase, template->charBase); + break; + } + G2_SetBG3Priority(template->priority); + G2_BG3Mosaic(template->mosaic); + break; + + case GF_BG_LYR_SUB_0: + GX_EngineBToggleLayers(GF_BG_LYR_SUB_0_F, GX_LAYER_TOGGLE_ON); + G2S_SetBG0Control(screenSize, template->colorMode, template->screenBase, template->charBase, template->bgExtPltt); + G2S_SetBG0Priority(template->priority); + G2S_BG0Mosaic(template->mosaic); + break; + + case GF_BG_LYR_SUB_1: + GX_EngineBToggleLayers(GF_BG_LYR_SUB_1_F, GX_LAYER_TOGGLE_ON); + G2S_SetBG1Control(screenSize, template->colorMode, template->screenBase, template->charBase, template->bgExtPltt); + G2S_SetBG1Priority(template->priority); + G2S_BG1Mosaic(template->mosaic); + break; + + case GF_BG_LYR_SUB_2: + GX_EngineBToggleLayers(GF_BG_LYR_SUB_2_F, GX_LAYER_TOGGLE_ON); + switch (bgMode) + { + default: + case GF_BG_TYPE_TEXT: + G2S_SetBG2ControlText(screenSize, template->colorMode, template->screenBase, template->charBase); + break; + case GF_BG_TYPE_AFFINE: + G2S_SetBG2ControlAffine(screenSize, template->areaOver, template->screenBase, template->charBase); + break; + case GF_BG_TYPE_256x16PLTT: + G2S_SetBG2Control256x16Pltt(screenSize, template->areaOver, template->screenBase, template->charBase); + break; + } + G2S_SetBG2Priority(template->priority); + G2S_BG2Mosaic(template->mosaic); + break; + + case GF_BG_LYR_SUB_3: + GX_EngineBToggleLayers(GF_BG_LYR_SUB_3_F, GX_LAYER_TOGGLE_ON); + switch (bgMode) + { + default: + case GF_BG_TYPE_TEXT: + G2S_SetBG3ControlText(screenSize, template->colorMode, template->screenBase, template->charBase); + break; + case GF_BG_TYPE_AFFINE: + G2S_SetBG3ControlAffine(screenSize, template->areaOver, template->screenBase, template->charBase); + break; + case GF_BG_TYPE_256x16PLTT: + G2S_SetBG3Control256x16Pltt(screenSize, template->areaOver, template->screenBase, template->charBase); + break; + } + G2S_SetBG3Priority(template->priority); + G2S_BG3Mosaic(template->mosaic); + break; + } + + bgConfig->bgs[bgId].rotation = 0; + bgConfig->bgs[bgId].xScale = FX32_ONE; + bgConfig->bgs[bgId].yScale = FX32_ONE; + bgConfig->bgs[bgId].centerX = 0; + bgConfig->bgs[bgId].centerY = 0; + + if (template->bufferSize != 0) + { + bgConfig->bgs[bgId].tilemapBuffer = AllocFromHeap(bgConfig->heap_id, template->bufferSize); + + MI_CpuClear16(bgConfig->bgs[bgId].tilemapBuffer, template->bufferSize); + + bgConfig->bgs[bgId].bufferSize = template->bufferSize; + bgConfig->bgs[bgId].baseTile = template->baseTile; + } + else + { + bgConfig->bgs[bgId].tilemapBuffer = NULL; + bgConfig->bgs[bgId].bufferSize = 0; + bgConfig->bgs[bgId].baseTile = 0; + } + + bgConfig->bgs[bgId].size = template->size; + bgConfig->bgs[bgId].mode = bgMode; + bgConfig->bgs[bgId].colorMode = template->colorMode; + + if (bgMode == GF_BG_TYPE_TEXT && template->colorMode == GX_BG_COLORMODE_16) + { + bgConfig->bgs[bgId].tileSize = 0x20; + } + else + { + bgConfig->bgs[bgId].tileSize = 0x40; + } + + BgSetPosTextAndCommit(bgConfig, bgId, BG_POS_OP_SET_X, template->x); + BgSetPosTextAndCommit(bgConfig, bgId, BG_POS_OP_SET_Y, template->y); +} + +THUMB_FUNC void SetBgControlParam(struct BgConfig *config, u8 bgId, u32 attr, u8 value) +{ + if (attr == GF_BG_CNT_SET_COLOR_MODE) + { + config->bgs[bgId].colorMode = value; + } + + switch (bgId) + { + case GF_BG_LYR_MAIN_0: + GXBg01Control bg0cnt = G2_GetBG0Control(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg0cnt.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg0cnt.charBase = value; + } + + G2_SetBG0Control(bg0cnt.screenSize, config->bgs[bgId].colorMode, bg0cnt.screenBase, bg0cnt.charBase, bg0cnt.bgExtPltt); + break; + case GF_BG_LYR_MAIN_1: + GXBg01Control bg1cnt = G2_GetBG1Control(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg1cnt.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg1cnt.charBase = value; + } + + G2_SetBG1Control(bg1cnt.screenSize, config->bgs[bgId].colorMode, bg1cnt.screenBase, bg1cnt.charBase, bg1cnt.bgExtPltt); + break; + case GF_BG_LYR_MAIN_2: + switch (config->bgs[bgId].mode) + { + default: + case GF_BG_TYPE_TEXT: + GXBg23ControlText bg2cnt_tx = G2_GetBG2ControlText(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg2cnt_tx.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg2cnt_tx.charBase = value; + } + + G2_SetBG2ControlText(bg2cnt_tx.screenSize, config->bgs[bgId].colorMode, bg2cnt_tx.screenBase, bg2cnt_tx.charBase); + break; + case GF_BG_TYPE_AFFINE: + GXBg23ControlAffine bg2cnt_aff = G2_GetBG2ControlAffine(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg2cnt_aff.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg2cnt_aff.charBase = value; + } + + G2_SetBG2ControlAffine(bg2cnt_aff.screenSize, bg2cnt_aff.areaOver, bg2cnt_aff.screenBase, + bg2cnt_aff.charBase); + break; + case GF_BG_TYPE_256x16PLTT: + GXBg23Control256x16Pltt bg2cnt_256x16pltt = G2_GetBG2Control256x16Pltt(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg2cnt_256x16pltt.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg2cnt_256x16pltt.charBase = value; + } + + G2_SetBG2Control256x16Pltt(bg2cnt_256x16pltt.screenSize, bg2cnt_256x16pltt.areaOver, + bg2cnt_256x16pltt.screenBase, bg2cnt_256x16pltt.charBase); + break; + } + break; + case GF_BG_LYR_MAIN_3: + switch (config->bgs[bgId].mode) + { + default: + case GF_BG_TYPE_TEXT: + GXBg23ControlText bg3cnt_tx = G2_GetBG3ControlText(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg3cnt_tx.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg3cnt_tx.charBase = value; + } + + G2_SetBG3ControlText(bg3cnt_tx.screenSize, config->bgs[bgId].colorMode, bg3cnt_tx.screenBase, bg3cnt_tx.charBase); + break; + case GF_BG_TYPE_AFFINE: + GXBg23ControlAffine bg3cnt_aff = G2_GetBG3ControlAffine(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg3cnt_aff.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg3cnt_aff.charBase = value; + } + + G2_SetBG3ControlAffine(bg3cnt_aff.screenSize, bg3cnt_aff.areaOver, bg3cnt_aff.screenBase, + bg3cnt_aff.charBase); + break; + case GF_BG_TYPE_256x16PLTT: + GXBg23Control256x16Pltt bg3cnt_256x16pltt = G2_GetBG3Control256x16Pltt(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg3cnt_256x16pltt.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg3cnt_256x16pltt.charBase = value; + } + + G2_SetBG3Control256x16Pltt(bg3cnt_256x16pltt.screenSize, bg3cnt_256x16pltt.areaOver, + bg3cnt_256x16pltt.screenBase, bg3cnt_256x16pltt.charBase); + break; + } + break; + case GF_BG_LYR_SUB_0: + GXBg01Control bg0cntsub = G2S_GetBG0Control(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg0cntsub.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg0cntsub.charBase = value; + } + + G2S_SetBG0Control(bg0cntsub.screenSize, config->bgs[bgId].colorMode, bg0cntsub.screenBase, bg0cntsub.charBase, bg0cntsub.bgExtPltt); + break; + case GF_BG_LYR_SUB_1: + GXBg01Control bg1cntsub = G2S_GetBG1Control(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg1cntsub.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg1cntsub.charBase = value; + } + + G2S_SetBG1Control(bg1cntsub.screenSize, config->bgs[bgId].colorMode, bg1cntsub.screenBase, bg1cntsub.charBase, bg1cntsub.bgExtPltt); + break; + case GF_BG_LYR_SUB_2: + switch (config->bgs[bgId].mode) + { + default: + case GF_BG_TYPE_TEXT: + GXBg23ControlText bg2cntsub_tx = G2S_GetBG2ControlText(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg2cntsub_tx.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg2cntsub_tx.charBase = value; + } + + G2S_SetBG2ControlText(bg2cntsub_tx.screenSize, config->bgs[bgId].colorMode, bg2cntsub_tx.screenBase, bg2cntsub_tx.charBase); + break; + case GF_BG_TYPE_AFFINE: + GXBg23ControlAffine bg2cntsub_aff = G2S_GetBG2ControlAffine(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg2cntsub_aff.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg2cntsub_aff.charBase = value; + } + + G2S_SetBG2ControlAffine(bg2cntsub_aff.screenSize, bg2cntsub_aff.areaOver, bg2cntsub_aff.screenBase, + bg2cntsub_aff.charBase); + break; + case GF_BG_TYPE_256x16PLTT: + GXBg23Control256x16Pltt bg2cntsub_256x16pltt = G2S_GetBG2Control256x16Pltt(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg2cntsub_256x16pltt.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg2cntsub_256x16pltt.charBase = value; + } + + G2S_SetBG2Control256x16Pltt(bg2cntsub_256x16pltt.screenSize, bg2cntsub_256x16pltt.areaOver, + bg2cntsub_256x16pltt.screenBase, bg2cntsub_256x16pltt.charBase); + break; + } + break; + case GF_BG_LYR_SUB_3: + switch (config->bgs[bgId].mode) + { + default: + case GF_BG_TYPE_TEXT: + GXBg23ControlText bg3cntsub_tx = G2S_GetBG3ControlText(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg3cntsub_tx.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg3cntsub_tx.charBase = value; + } + + G2S_SetBG3ControlText(bg3cntsub_tx.screenSize, config->bgs[bgId].colorMode, bg3cntsub_tx.screenBase, bg3cntsub_tx.charBase); + break; + case GF_BG_TYPE_AFFINE: + GXBg23ControlAffine bg3cntsub_aff = G2S_GetBG3ControlAffine(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg3cntsub_aff.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg3cntsub_aff.charBase = value; + } + + G2S_SetBG3ControlAffine(bg3cntsub_aff.screenSize, bg3cntsub_aff.areaOver, bg3cntsub_aff.screenBase, + bg3cntsub_aff.charBase); + break; + case GF_BG_TYPE_256x16PLTT: + GXBg23Control256x16Pltt bg3cntsub_256x16pltt = G2S_GetBG3Control256x16Pltt(); + if (attr == GF_BG_CNT_SET_SCREEN_BASE) + { + bg3cntsub_256x16pltt.screenBase = value; + } + else if (attr == GF_BG_CNT_SET_CHAR_BASE) + { + bg3cntsub_256x16pltt.charBase = value; + } + + G2S_SetBG3Control256x16Pltt(bg3cntsub_256x16pltt.screenSize, bg3cntsub_256x16pltt.areaOver, + bg3cntsub_256x16pltt.screenBase, bg3cntsub_256x16pltt.charBase); + break; + } + break; + } +} + +THUMB_FUNC u8 TranslateGFBgModePairToGXScreenSize(u8 size, u32 bgMode) +{ + switch (bgMode) + { + case GF_BG_TYPE_TEXT: + + if (size == GF_BG_SCR_SIZE_256x256) + { + return GX_BG_SCRSIZE_TEXT_256x256; + } + else if (size == GF_BG_SCR_SIZE_256x512) + { + return GX_BG_SCRSIZE_TEXT_256x512; + } + else if (size == GF_BG_SCR_SIZE_512x256) + { + return GX_BG_SCRSIZE_TEXT_512x256; + } + else if (size == GF_BG_SCR_SIZE_512x512) + { + return GX_BG_SCRSIZE_TEXT_512x512; + } + break; + + case GF_BG_TYPE_AFFINE: + + if (size == GF_BG_SCR_SIZE_128x128) + { + return GX_BG_SCRSIZE_AFFINE_128x128; + } + else if (size == GF_BG_SCR_SIZE_256x256) + { + return GX_BG_SCRSIZE_AFFINE_256x256; + } + else if (size == GF_BG_SCR_SIZE_512x512) + { + return GX_BG_SCRSIZE_AFFINE_512x512; + } + else if (size == GF_BG_SCR_SIZE_1024x1024) + { + return GX_BG_SCRSIZE_AFFINE_1024x1024; + } + break; + + case GF_BG_TYPE_256x16PLTT: + + if (size == GF_BG_SCR_SIZE_128x128) + { + return GX_BG_SCRSIZE_256x16PLTT_128x128; + } + else if (size == GF_BG_SCR_SIZE_256x256) + { + return GX_BG_SCRSIZE_256x16PLTT_256x256; + } + else if (size == GF_BG_SCR_SIZE_512x512) + { + return GX_BG_SCRSIZE_256x16PLTT_512x512; + } + else if (size == GF_BG_SCR_SIZE_1024x1024) + { + return GX_BG_SCRSIZE_256x16PLTT_1024x1024; + } + break; + } + + return GX_BG_SCRSIZE_TEXT_256x256; // GX_BG_SCRSIZE_AFFINE_128x128; GX_BG_SCRSIZE_256x16PLTT_128x128; +} + +THUMB_FUNC void GetBgScreenDimensions(u32 screenSize, u8 *width_p, u8 *height_p) +{ + switch (screenSize) + { + case GF_BG_SCR_SIZE_128x128: + *width_p = 0x10; + *height_p = 0x10; + break; + case GF_BG_SCR_SIZE_256x256: + *width_p = 0x20; + *height_p = 0x20; + break; + case GF_BG_SCR_SIZE_256x512: + *width_p = 0x20; + *height_p = 0x40; + break; + case GF_BG_SCR_SIZE_512x256: + *width_p = 0x40; + *height_p = 0x20; + break; + case GF_BG_SCR_SIZE_512x512: + *width_p = 0x40; + *height_p = 0x40; + break; + case GF_BG_SCR_SIZE_1024x1024: + *width_p = 0x80; + *height_p = 0x80; + break; + } +} + +THUMB_FUNC void FreeBgTilemapBuffer(struct BgConfig *bgConfig, u32 bgId) +{ + if (bgConfig->bgs[bgId].tilemapBuffer != NULL) + { + FreeToHeap(bgConfig->bgs[bgId].tilemapBuffer); + bgConfig->bgs[bgId].tilemapBuffer = NULL; + } +} + +THUMB_FUNC void SetBgPriority(u32 bgId, u16 priority) +{ + switch (bgId) + { + case GF_BG_LYR_MAIN_0: + G2_SetBG0Priority(priority); + break; + case GF_BG_LYR_MAIN_1: + G2_SetBG1Priority(priority); + break; + case GF_BG_LYR_MAIN_2: + G2_SetBG2Priority(priority); + break; + case GF_BG_LYR_MAIN_3: + G2_SetBG3Priority(priority); + break; + case GF_BG_LYR_SUB_0: + G2S_SetBG0Priority(priority); + break; + case GF_BG_LYR_SUB_1: + G2S_SetBG1Priority(priority); + break; + case GF_BG_LYR_SUB_2: + G2S_SetBG2Priority(priority); + break; + case GF_BG_LYR_SUB_3: + G2S_SetBG3Priority(priority); + break; + } +} + +THUMB_FUNC void ToggleBgLayer(u32 bgId, GX_LayerToggle toggle) +{ + switch (bgId) + { + case GF_BG_LYR_MAIN_0: + GX_EngineAToggleLayers(GF_BG_LYR_MAIN_0_F, toggle); + break; + case GF_BG_LYR_MAIN_1: + GX_EngineAToggleLayers(GF_BG_LYR_MAIN_1_F, toggle); + break; + case GF_BG_LYR_MAIN_2: + GX_EngineAToggleLayers(GF_BG_LYR_MAIN_2_F, toggle); + break; + case GF_BG_LYR_MAIN_3: + GX_EngineAToggleLayers(GF_BG_LYR_MAIN_3_F, toggle); + break; + case GF_BG_LYR_SUB_0: + GX_EngineBToggleLayers(GF_BG_LYR_SUB_0_F, toggle); + break; + case GF_BG_LYR_SUB_1: + GX_EngineBToggleLayers(GF_BG_LYR_SUB_1_F, toggle); + break; + case GF_BG_LYR_SUB_2: + GX_EngineBToggleLayers(GF_BG_LYR_SUB_2_F, toggle); + break; + case GF_BG_LYR_SUB_3: + GX_EngineBToggleLayers(GF_BG_LYR_SUB_3_F, toggle); + break; + } +} + +THUMB_FUNC void BgSetPosTextAndCommit(struct BgConfig *bgConfig, u32 bgId, u32 op, fx32 val) +{ + Bg_SetPosText(&bgConfig->bgs[bgId], op, val); + + u32 x = (u32)bgConfig->bgs[bgId].hOffset; + u32 y = (u32)bgConfig->bgs[bgId].vOffset; + switch (bgId) + { + case GF_BG_LYR_MAIN_0: + G2_SetBG0Offset(x, y); + break; + case GF_BG_LYR_MAIN_1: + G2_SetBG1Offset(x, y); + break; + case GF_BG_LYR_MAIN_2: + if (bgConfig->bgs[GF_BG_LYR_MAIN_2].mode == 0) + { + G2_SetBG2Offset(x, y); + } + else + { + BgAffineReset(bgConfig, GF_BG_LYR_MAIN_2); + } + + break; + case GF_BG_LYR_MAIN_3: + if (bgConfig->bgs[GF_BG_LYR_MAIN_3].mode == 0) + { + G2_SetBG3Offset(x, y); + } + else + { + BgAffineReset(bgConfig, GF_BG_LYR_MAIN_3); + } + break; + case GF_BG_LYR_SUB_0: + G2S_SetBG0Offset(x, y); + break; + case GF_BG_LYR_SUB_1: + G2S_SetBG1Offset(x, y); + break; + case GF_BG_LYR_SUB_2: + if (bgConfig->bgs[GF_BG_LYR_SUB_2].mode == 0) + { + G2S_SetBG2Offset(x, y); + } + else + { + BgAffineReset(bgConfig, GF_BG_LYR_SUB_2); + } + break; + case GF_BG_LYR_SUB_3: + if (bgConfig->bgs[GF_BG_LYR_SUB_3].mode == 0) + { + G2S_SetBG3Offset(x, y); + } + else + { + BgAffineReset(bgConfig, GF_BG_LYR_SUB_3); + } + break; + } +} + +THUMB_FUNC fx32 Bg_GetXpos(struct BgConfig *bgConfig, u32 bgId) +{ + return bgConfig->bgs[bgId].hOffset; +} + +THUMB_FUNC fx32 Bg_GetYpos(struct BgConfig *bgConfig, u32 bgId) +{ + return bgConfig->bgs[bgId].vOffset; +} + +THUMB_FUNC void Bg_SetTextDimAndAffineParams(struct BgConfig *bgConfig, + u32 bgId, + u32 txOp, + fx32 txVal, + struct Mtx22 *mtx, + fx32 centerX, + fx32 centerY) +{ + Bg_SetPosText(&bgConfig->bgs[bgId], txOp, txVal); + SetBgAffine(bgConfig, bgId, mtx, centerX, centerY); +} + +THUMB_FUNC void Bg_SetPosText(struct Bg *bg, u32 op, fx32 val) +{ + switch (op) + { + case BG_POS_OP_SET_X: + bg->hOffset = val; + break; + case BG_POS_OP_ADD_X: + bg->hOffset += val; + break; + case BG_POS_OP_SUB_X: + bg->hOffset -= val; + break; + case BG_POS_OP_SET_Y: + bg->vOffset = val; + break; + case BG_POS_OP_ADD_Y: + bg->vOffset += val; + break; + case BG_POS_OP_SUB_Y: + bg->vOffset -= val; + break; + } +} + +THUMB_FUNC void SetBgAffine( + struct BgConfig *bgConfig, u32 bgId, struct Mtx22 *mtx, fx32 centerX, fx32 centerY) +{ + switch (bgId) + { + case GF_BG_LYR_MAIN_2: + G2_SetBG2Affine(mtx, centerX, centerY, bgConfig->bgs[bgId].hOffset, bgConfig->bgs[bgId].vOffset); + break; + case GF_BG_LYR_MAIN_3: + G2_SetBG3Affine(mtx, centerX, centerY, bgConfig->bgs[bgId].hOffset, bgConfig->bgs[bgId].vOffset); + break; + case GF_BG_LYR_SUB_2: + G2S_SetBG2Affine(mtx, centerX, centerY, bgConfig->bgs[bgId].hOffset, bgConfig->bgs[bgId].vOffset); + break; + case GF_BG_LYR_SUB_3: + G2S_SetBG3Affine(mtx, centerX, centerY, bgConfig->bgs[bgId].hOffset, bgConfig->bgs[bgId].vOffset); + break; + } +} + +THUMB_FUNC void BgAffineReset(struct BgConfig *bgConfig, u32 bgId) +{ + struct Mtx22 mtx; + MTX22_2DAffine(&mtx, 0, FX32_ONE, FX32_ONE, 0); + SetBgAffine(bgConfig, bgId, &mtx, 0, 0); +} + +THUMB_FUNC void CopyOrUncompressTilemapData(const void *src, void *dest, u32 size) +{ + if (size == 0) + { + MI_UncompressLZ8(src, dest); + return; + } + + if (((u32)src % 4) == 0 && ((u32)dest % 4) == 0 && ((u16)size % 4) == 0) + { + MI_CpuCopy32(src, dest, size); + return; + } + + MI_CpuCopy16(src, dest, size); +} + +THUMB_FUNC void BgCommitTilemapBufferToVram(struct BgConfig *bgConfig, u32 bgId) +{ + BgCopyOrUncompressTilemapBufferRangeToVram(bgConfig, + bgId, + bgConfig->bgs[bgId].tilemapBuffer, + bgConfig->bgs[bgId].bufferSize, + bgConfig->bgs[bgId].baseTile); +} + +THUMB_FUNC void BgCopyOrUncompressTilemapBufferRangeToVram( + struct BgConfig *bgConfig, u32 bgId, u32 *src, u32 size, u32 tileOffset) +{ + if (size == 0) + { + void *tilemapBuffer = bgConfig->bgs[bgId].tilemapBuffer; + if (tilemapBuffer != 0) + { + CopyOrUncompressTilemapData(src, tilemapBuffer, size); + LoadBgVramScr(bgId, tilemapBuffer, bgConfig->bgs[bgId].baseTile * 2, bgConfig->bgs[bgId].bufferSize); + return; + } + + u32 uncompSize = src[0] >> 8; + void *ptr = AllocFromHeapAtEnd(bgConfig->heap_id, uncompSize); + CopyOrUncompressTilemapData(src, ptr, size); + LoadBgVramScr(bgId, ptr, tileOffset * 2, uncompSize); + FreeToHeap(ptr); + return; + } + + LoadBgVramScr(bgId, src, tileOffset * 2, size); +} + +THUMB_FUNC void LoadBgVramScr(u32 bgId, void *buffer_p, u32 offset, u32 size) +{ + DC_FlushRange(buffer_p, size); + + switch (bgId) + { + case 0: + GX_LoadBG0Scr(buffer_p, offset, size); + break; + case 1: + GX_LoadBG1Scr(buffer_p, offset, size); + break; + case 2: + GX_LoadBG2Scr(buffer_p, offset, size); + break; + case 3: + GX_LoadBG3Scr(buffer_p, offset, size); + break; + case 4: + GXS_LoadBG0Scr(buffer_p, offset, size); + break; + case 5: + GXS_LoadBG1Scr(buffer_p, offset, size); + break; + case 6: + GXS_LoadBG2Scr(buffer_p, offset, size); + break; + case 7: + GXS_LoadBG3Scr(buffer_p, offset, size); + break; + } +} + +THUMB_FUNC void BG_LoadScreenTilemapData( + struct BgConfig *bgConfig, u32 bgId, void *src, u32 numTiles) +{ + CopyOrUncompressTilemapData(src, bgConfig->bgs[bgId].tilemapBuffer, numTiles); +} + +THUMB_FUNC void BG_LoadCharTilesData( + struct BgConfig *bgConfig, u32 bgId, u32 *charData, u32 offset, u32 numTiles) +{ + if (bgConfig->bgs[bgId].colorMode == GX_BG_COLORMODE_16) + { + BG_LoadCharPixelData(bgConfig, bgId, charData, offset, numTiles << 5); + return; + } + BG_LoadCharPixelData(bgConfig, bgId, charData, offset, numTiles << 6); +} + +THUMB_FUNC void BG_LoadCharPixelData( + struct BgConfig *bgConfig, u32 bgId, u32 *charData, u32 size, u32 offset) +{ + if (size == 0) + { + + u32 uncompressedSize = charData[0] >> 8; + void *ptr = AllocFromHeapAtEnd(bgConfig->heap_id, uncompressedSize); + CopyOrUncompressTilemapData(charData, ptr, size); + LoadBgVramChar(bgId, ptr, offset, uncompressedSize); + FreeToHeap(ptr); + return; + } + + LoadBgVramChar(bgId, charData, offset, size); +} + +THUMB_FUNC void LoadBgVramChar(u32 bgId, void *buffer_p, u32 offset, u32 size) +{ + DC_FlushRange(buffer_p, size); + + switch (bgId) + { + case GF_BG_LYR_MAIN_0: + GX_LoadBG0Char(buffer_p, offset, size); + break; + case GF_BG_LYR_MAIN_1: + GX_LoadBG1Char(buffer_p, offset, size); + break; + case GF_BG_LYR_MAIN_2: + GX_LoadBG2Char(buffer_p, offset, size); + break; + case GF_BG_LYR_MAIN_3: + GX_LoadBG3Char(buffer_p, offset, size); + break; + case GF_BG_LYR_SUB_0: + GXS_LoadBG0Char(buffer_p, offset, size); + break; + case GF_BG_LYR_SUB_1: + GXS_LoadBG1Char(buffer_p, offset, size); + break; + case GF_BG_LYR_SUB_2: + GXS_LoadBG2Char(buffer_p, offset, size); + break; + case GF_BG_LYR_SUB_3: + GXS_LoadBG3Char(buffer_p, offset, size); + break; + } +} + +THUMB_FUNC void BG_ClearCharDataRange(u32 bgId, u32 size, u32 offset, u32 heap_id) +{ + void *ptr = AllocFromHeapAtEnd(heap_id, size); + memset(ptr, 0, size); + + LoadBgVramChar(bgId, ptr, offset, size); + FreeToHeapExplicit(heap_id, ptr); +} + +THUMB_FUNC void BG_FillCharDataRange( + struct BgConfig *param0, u32 bgId, u32 fillValue, u32 count, u32 offset) +{ + void *st4; + u32 size = count * param0->bgs[bgId].tileSize; + u32 r5 = fillValue; + st4 = AllocFromHeapAtEnd(param0->heap_id, size); + + if (param0->bgs[bgId].tileSize == 0x20) + { + r5 = (r5 << 0xc | r5 << 0x8 | r5 << 0x4 | r5); + r5 |= r5 << 0x10; + } + else + { + r5 = r5 << 0x18 | r5 << 0x10 | r5 << 8 | r5; + } + + MI_CpuFillFast(st4, r5, size); + + LoadBgVramChar((u8)bgId, st4, param0->bgs[bgId].tileSize * offset, size); + FreeToHeap(st4); +} + +THUMB_FUNC void BG_LoadPlttData(u32 bgId, void *plttData, u32 size, u32 offset) +{ + DC_FlushRange(plttData, size); + if (bgId < GF_BG_LYR_MAIN_CNT) + { + GX_LoadBGPltt(plttData, offset, size); + return; + } + + GXS_LoadBGPltt(plttData, offset, size); +} + +THUMB_FUNC void BG_SetMaskColor(u32 bgId, u32 value) +{ + BG_LoadPlttData(bgId, &value, 2, 0); +} + +THUMB_FUNC u16 GetTileMapIndexFromCoords(u8 x, u8 y, u8 screenSize) +{ + switch (screenSize) + { + case GF_BG_SCR_SIZE_128x128: + return (u16)(x + (y << 4)); + case GF_BG_SCR_SIZE_256x256: + case GF_BG_SCR_SIZE_256x512: + return (u16)(x + (y << 5)); + case GF_BG_SCR_SIZE_512x256: + return (u16)((x & 0x1f) + ((y + (x & ~0x1f)) << 5)); + case GF_BG_SCR_SIZE_512x512: + u16 res = (u16)(((u16)((x >> 5) + (y >> 5) * 2)) << 10); + res += (x & 0x1f) + ((y & 0x1f) << 5); + return res; + case GF_BG_SCR_SIZE_1024x1024: + return 0; + } + + return x; +} + +THUMB_FUNC u16 GetSrcTileMapIndexFromCoords(u8 x, u8 y, u8 width, u8 height) +{ + u8 coordType = 0; + u16 r3 = 0; + s16 r4 = (s16)(width - 32); + s16 r5 = (s16)(height - 32); + + if (((u32)x >> 5) != 0) + { + coordType++; + } + + if (((u32)y >> 5) != 0) + { + coordType += 2; + } + + switch (coordType) + { + case 0: + if (r4 >= 0) + { + r3 += x + (y << 5); + } + else + { + r3 += x + y * width; + } + break; + case 1: + if (r5 >= 0) + { + r3 += 0x400; + } + else + { + r3 += (height << 5); + } + + r3 += (x & 0x1f) + y * r4; + break; + case 2: + r3 += width << 5; + if (r4 >= 0) + { + r3 += x + ((y & 0x1f) << 5); + } + else + { + r3 += x + (y & 0x1f) * width; + } + break; + case 3: + r3 += (width + r5) << 5; + r3 += (x & 0x1f) + (y & 0x1f) * r4; + break; + } + + return r3; +} + +THUMB_FUNC void LoadRectToBgTilemapRect(struct BgConfig *bgConfig, + u32 bgId, + void *src, + u8 dstX, + u8 dstY, + u8 width, + u8 height) +{ + CopyToBgTilemapRect(bgConfig, bgId, dstX, dstY, width, height, src, 0, 0, width, height); +} + +THUMB_FUNC void CopyToBgTilemapRect(struct BgConfig *bgConfig, + u32 bgId, + u8 dstX, + u8 dstY, + u8 dstWidth, + u8 dstHeight, + void *src, + u8 srcX, + u8 srcY, + u8 srcWidth, + u8 srcHeight) +{ + if (bgConfig->bgs[bgId].mode != 1) + { + CopyBgTilemapRectText(&bgConfig->bgs[bgId], + dstX, + dstY, + dstWidth, + dstHeight, + (u16 *) src, + srcX, + srcY, + srcWidth, + srcHeight, + 0); + } + else + { + CopyBgTilemapRectAffine(&bgConfig->bgs[bgId], + dstX, + dstY, + dstWidth, + dstHeight, + (u8 *) src, + srcX, + srcY, + srcWidth, + srcHeight, + 0); + } +} + +THUMB_FUNC void CopyRectToBgTilemapRect(struct BgConfig *bgConfig, + u32 bgId, + u8 dstX, + u8 dstY, + u8 dstWidth, + u8 dstHeight, + void *src, + u8 srcX, + u8 srcY, + u8 srcWidth, + u8 srcHeight) +{ + if (bgConfig->bgs[bgId].mode != 1) + { + CopyBgTilemapRectText(&bgConfig->bgs[bgId], + dstX, + dstY, + dstWidth, + dstHeight, + (u16 *) src, + srcX, + srcY, + srcWidth, + srcHeight, + TRUE); + } + else + { + CopyBgTilemapRectAffine(&bgConfig->bgs[bgId], + dstX, + dstY, + dstWidth, + dstHeight, + (u8 *) src, + srcX, + srcY, + srcWidth, + srcHeight, + TRUE); + } +} + +THUMB_FUNC void CopyBgTilemapRectText(struct Bg *bg, + u8 dstX, + u8 dstY, + u8 dstWidth, + u8 dstHeight, + u16 *src, + u8 srcX, + u8 srcY, + u8 srcWidth, + u8 srcHeight, + u8 adjustForSrcDims) +{ + u16 *tilemapBuffer = bg->tilemapBuffer; + + if (tilemapBuffer == 0) + { + return; + } + + u8 screenWidth; + u8 screenHeight; + GetBgScreenDimensions(bg->size, &screenWidth, &screenHeight); + + u8 i; + u8 j; + if (adjustForSrcDims == 0) + { + for (i = 0; i < dstHeight; i++) + { + + if (dstY + i >= screenHeight) + { + break; + } + + if (srcY + i >= srcHeight) + { + break; + } + + for (j = 0; j < dstWidth; j++) + { + + if (dstX + j >= screenWidth) + { + break; + } + + if (srcX + j >= srcWidth) + { + break; + } + + ((u16 *)tilemapBuffer)[GetTileMapIndexFromCoords((u8) (dstX + j), (u8) (dstY + i), bg->size)] = + src[srcX + srcWidth * (srcY + i) + j]; + } + } + } + else + { + for (i = 0; i < dstHeight; i++) + { + + if (dstY + i >= screenHeight) + { + break; + } + + if (srcY + i >= srcHeight) + { + break; + } + + for (j = 0; j < dstWidth; j++) + { + + if (dstX + j >= screenWidth) + { + break; + } + + if (srcX + j >= srcWidth) + { + break; + } + + ((u16 *)tilemapBuffer)[GetTileMapIndexFromCoords((u8) (dstX + j), (u8) (dstY + i), bg->size)] = + src[GetSrcTileMapIndexFromCoords((u8) (srcX + j), (u8) (srcY + i), srcWidth, srcHeight)]; + } + } + } +} + +THUMB_FUNC void CopyBgTilemapRectAffine(struct Bg *bg, + u8 dstX, + u8 dstY, + u8 dstWidth, + u8 dstHeight, + u8 *src, + u8 srcX, + u8 srcY, + u8 srcWidth, + u8 srcHeight, + u8 adjustForSrcDims) +{ + void *tilemapBuffer = bg->tilemapBuffer; + + if (tilemapBuffer == 0) + { + return; + } + + u8 screenWidth; + u8 screenHeight; + GetBgScreenDimensions(bg->size, &screenWidth, &screenHeight); + + u8 i; + u8 j; + if (adjustForSrcDims == 0) + { + for (i = 0; i < dstHeight; i++) + { + + if (dstY + i >= screenHeight) + { + break; + } + + if (srcY + i >= srcHeight) + { + break; + } + + for (j = 0; j < dstWidth; j++) + { + + if (dstX + j >= screenWidth) + { + break; + } + + if (srcX + j >= srcWidth) + { + break; + } + + ((u8 *)tilemapBuffer)[GetTileMapIndexFromCoords((u8) (dstX + j), (u8) (dstY + i), bg->size)] = + src[srcX + srcWidth * (srcY + i) + j]; + } + } + } + else + { + for (i = 0; i < dstHeight; i++) + { + + if (dstY + i >= screenHeight) + { + break; + } + + if (srcY + i >= srcHeight) + { + break; + } + + for (j = 0; j < dstWidth; j++) + { + + if (dstX + j >= screenWidth) + { + break; + } + + if (srcX + j >= srcWidth) + { + break; + } + + ((u8 *)tilemapBuffer)[GetTileMapIndexFromCoords((u8) (dstX + j), (u8) (dstY + i), bg->size)] = + src[GetSrcTileMapIndexFromCoords((u8) (srcX + j), (u8) (srcY + i), srcWidth, srcHeight)]; + } + } + } +} + +THUMB_FUNC void FillBgTilemapRect(struct BgConfig *bgConfig, + u32 bgId, + u16 fillValue, + u8 x, + u8 y, + u8 width, + u8 height, + u8 paletteNum) +{ + if (bgConfig->bgs[bgId].mode != 1) + { + + FillBgTilemapRectText(&bgConfig->bgs[bgId], fillValue, x, y, width, height, paletteNum); + } + else + { + FillBgTilemapRectAffine(&bgConfig->bgs[bgId], (u8) fillValue, x, y, width, height); + } +} + +THUMB_FUNC void FillBgTilemapRectText(struct Bg *bg, + u16 fillValue, + u8 x, + u8 y, + u8 width, + u8 height, + u8 paletteNum) +{ + void *tilemapBuffer = bg->tilemapBuffer; + + if (tilemapBuffer != 0) + { + + u8 screenWidth; + u8 screenHeight; + GetBgScreenDimensions(bg->size, &screenWidth, &screenHeight); + + u8 i; + u8 j; + for (i = y; i < y + height; i++) + { + if (i >= screenHeight) + { + break; + } + + for (j = x; j < x + width; j++) + { + if (j >= screenWidth) + { + break; + } + + u16 idx = GetTileMapIndexFromCoords(j, i, bg->size); + + if (paletteNum == 0x11) + { + ((u16 *)tilemapBuffer)[idx] = fillValue; + } + else if (paletteNum == 0x10) + { + ((u16 *)tilemapBuffer)[idx] = (u16)((((u16 *)tilemapBuffer)[idx] & 0xF000) + fillValue); + } + else + { + ((u16 *)tilemapBuffer)[idx] = (u16)((paletteNum << 0xc) + fillValue); + } + } + } + } +} + +THUMB_FUNC void FillBgTilemapRectAffine( + struct Bg *bg, u8 fillValue, u8 x, u8 y, u8 width, u8 height) +{ + void *tilemapBuffer = bg->tilemapBuffer; + + if (tilemapBuffer != 0) + { + + u8 screenWidth; + u8 screenHeight; + GetBgScreenDimensions(bg->size, &screenWidth, &screenHeight); + + u8 i; + u8 j; + for (i = y; i < y + height; i++) + { + if (i >= screenHeight) + { + break; + } + + for (j = x; j < x + width; j++) + { + if (j >= screenWidth) + { + break; + } + + ((u8 *)tilemapBuffer)[GetTileMapIndexFromCoords(j, i, bg->size)] = fillValue; + } + } + } +} + +THUMB_FUNC void BgTilemapRectChangePalette(struct BgConfig *bgConfig, + u32 bgId, + u8 x, + u8 y, + u8 width, + u8 height, + u8 paletteNum) +{ + void *tilemapBuffer = bgConfig->bgs[bgId].tilemapBuffer; + + if (tilemapBuffer != NULL) + { + u8 screenWidth; + u8 screenHeight; + GetBgScreenDimensions(bgConfig->bgs[bgId].size, &screenWidth, &screenHeight); + + u8 i; + u8 j; + for (i = y; i < y + height; i++) + { + if (i >= screenHeight) + { + break; + } + + for (j = x; j < x + width; j++) + { + if (j >= screenWidth) + { + break; + } + + u16 idx = GetTileMapIndexFromCoords(j, i, bgConfig->bgs[bgId].size); + ((u16 *)tilemapBuffer)[idx] = (u16)((((u16 *)tilemapBuffer)[idx] & 0xfff) | (paletteNum << 0xc)); + } + } + } +} + +THUMB_FUNC void BgClearTilemapBufferAndCommit(struct BgConfig *bgConfig, u32 bgId) +{ + if (bgConfig->bgs[bgId].tilemapBuffer != NULL) + { + MI_CpuClear16(bgConfig->bgs[bgId].tilemapBuffer, bgConfig->bgs[bgId].bufferSize); + BgCommitTilemapBufferToVram(bgConfig, bgId); + } +} + +THUMB_FUNC void BgFillTilemapBufferAndCommit(struct BgConfig *bgConfig, u32 bgId, u16 fillValue) +{ + if (bgConfig->bgs[bgId].tilemapBuffer != NULL) + { + MI_CpuFill16(bgConfig->bgs[bgId].tilemapBuffer, fillValue, bgConfig->bgs[bgId].bufferSize); + BgCommitTilemapBufferToVram(bgConfig, bgId); + } +} + +THUMB_FUNC void BgFillTilemapBufferAndSchedule(struct BgConfig *bgConfig, u32 bgId, u16 fillValue) +{ + if (bgConfig->bgs[bgId].tilemapBuffer != NULL) + { + MI_CpuFill16(bgConfig->bgs[bgId].tilemapBuffer, fillValue, bgConfig->bgs[bgId].bufferSize); + ScheduleBgTilemapBufferTransfer(bgConfig, bgId); + } +} + +THUMB_FUNC void *BgGetCharPtr(u32 bgId) +{ + switch (bgId) + { + case GF_BG_LYR_MAIN_0: + return G2_GetBG0CharPtr(); + case GF_BG_LYR_MAIN_1: + return G2_GetBG1CharPtr(); + case GF_BG_LYR_MAIN_2: + return G2_GetBG2CharPtr(); + case GF_BG_LYR_MAIN_3: + return G2_GetBG3CharPtr(); + case GF_BG_LYR_SUB_0: + return G2S_GetBG0CharPtr(); + case GF_BG_LYR_SUB_1: + return G2S_GetBG1CharPtr(); + case GF_BG_LYR_SUB_2: + return G2S_GetBG2CharPtr(); + case GF_BG_LYR_SUB_3: + return G2S_GetBG3CharPtr(); + } + + return NULL; +} + +THUMB_FUNC void Convert4bppTo8bppInternal(u8 *src4bpp, u32 size, u8 (*dest8bpp), u8 paletteNum) +{ + paletteNum <<= 4; + for (u32 i = 0; i < size; i++) + { + dest8bpp[i * 2 + 0] = (u8)(src4bpp[i] & 0xf); + if (dest8bpp[i * 2 + 0] != 0) + { + dest8bpp[i * 2 + 0] += paletteNum; + } + + dest8bpp[i * 2 + 1] = (u8)((src4bpp[i] >> 4) & 0xf); + if (dest8bpp[i * 2 + 1] != 0) + { + dest8bpp[i * 2 + 1] += paletteNum; + } + } +} + +THUMB_FUNC u8 *Convert4bppTo8bpp(u8 *src4Bpp, u32 size, u8 paletteNum, u32 heap_id) +{ + u8 *ptr = (u8*)AllocFromHeap(heap_id, size * 2); + + Convert4bppTo8bppInternal(src4Bpp, size, ptr, paletteNum); + + return ptr; +} + +THUMB_FUNC void *GetBgTilemapBuffer(struct BgConfig *bgConfig, u8 bgId) +{ + return bgConfig->bgs[bgId].tilemapBuffer; +} + +THUMB_FUNC u16 GetBgAffineRotation(struct BgConfig *bgConfig, u32 bgId) +{ + return bgConfig->bgs[bgId].rotation; +} + +THUMB_FUNC u8 GetBgPriority(struct BgConfig *bgConfig, u32 bgId) +{ + switch (bgId) + { + case GF_BG_LYR_MAIN_0: + return G2_GetBG0Control().priority; + case GF_BG_LYR_MAIN_1: + return G2_GetBG1Control().priority; + case GF_BG_LYR_MAIN_2: + switch (bgConfig->bgs[bgId].mode) + { + default: + case GF_BG_TYPE_TEXT: + return G2_GetBG2ControlText().priority; + case GF_BG_TYPE_AFFINE: + return G2_GetBG2ControlAffine().priority; + case GF_BG_TYPE_256x16PLTT: + return G2_GetBG2Control256x16Pltt().priority; + } + break; + case GF_BG_LYR_MAIN_3: + switch (bgConfig->bgs[bgId].mode) + { + default: + case GF_BG_TYPE_TEXT: + return G2_GetBG3ControlText().priority; + case GF_BG_TYPE_AFFINE: + return G2_GetBG3ControlAffine().priority; + case GF_BG_TYPE_256x16PLTT: + return G2_GetBG3Control256x16Pltt().priority; + } + break; + + case GF_BG_LYR_SUB_0: + return G2S_GetBG0Control().priority; + case GF_BG_LYR_SUB_1: + return G2S_GetBG1Control().priority; + + case GF_BG_LYR_SUB_2: + switch (bgConfig->bgs[bgId].mode) + { + default: + case GF_BG_TYPE_TEXT: + return G2S_GetBG2ControlText().priority; + case GF_BG_TYPE_AFFINE: + return G2S_GetBG2ControlAffine().priority; + case GF_BG_TYPE_256x16PLTT: + return G2S_GetBG2Control256x16Pltt().priority; + } + break; + case GF_BG_LYR_SUB_3: + switch (bgConfig->bgs[bgId].mode) + { + default: + case GF_BG_TYPE_TEXT: + return G2S_GetBG3ControlText().priority; + case GF_BG_TYPE_AFFINE: + return G2S_GetBG3ControlAffine().priority; + case GF_BG_TYPE_256x16PLTT: + return G2S_GetBG3Control256x16Pltt().priority; + } + break; + } + + return 0; +} + +THUMB_FUNC void BlitBitmapRect4Bit(const struct Bitmap *src, + const struct Bitmap *dst, + u16 srcX, + u16 srcY, + u16 dstX, + u16 dstY, + u16 width, + u16 height, + u16 colorKey) +{ + int xEnd, yEnd; + int multiplierSrcY, multiplierDstY; + int loopSrcY, loopDstY; + int loopSrcX, loopDstX; + int toOrr, toShift; + u8 * pixelsSrc, * pixelsDst; + + if (dst->width - dstX < width) + xEnd = dst->width - dstX + srcX; + else + xEnd = width + srcX; + if (dst->height - dstY < height) + yEnd = dst->height - dstY + srcY; + else + yEnd = height + srcY; + multiplierSrcY = (src->width + (src->width & 7)) >> 3; + multiplierDstY = (dst->width + (dst->width & 7)) >> 3; + + if (colorKey == 0xFFFF) + { + for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++) + { + for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++) + { + pixelsSrc = (u8 *)(src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX << 2) & 0x3FE0) + (((loopSrcY << 2) & 0x3FE0) * multiplierSrcY) + (((loopSrcY << 2) & 0x1C))); + pixelsDst = (u8 *)(dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX << 2) & 0x3FE0) + (((loopDstY << 2) & 0x3FE0) * multiplierDstY) + (((loopDstY << 2) & 0x1C))); + + toOrr = (*pixelsSrc >> ((loopSrcX & 1) * 4)) & 0xF; + toShift = (loopDstX & 1) * 4; + *pixelsDst = ((toOrr << toShift) | (*pixelsDst & (0xF0 >> toShift))); + } + } + } + else + { + for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++) + { + for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++) + { + pixelsSrc = (u8 *)(src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX << 2) & 0x3FE0) + (((loopSrcY << 2) & 0x3FE0) * multiplierSrcY) + ((u32)((loopSrcY << 2) & 0x1C))); + pixelsDst = (u8 *)(dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX << 2) & 0x3FE0) + (((loopDstY << 2) & 0x3FE0) * multiplierDstY) + ((u32)((loopDstY << 2) & 0x1C))); + + toOrr = (*pixelsSrc >> ((loopSrcX & 1) * 4)) & 0xF; + if (toOrr != colorKey) + { + toShift = (loopDstX & 1) * 4; + *pixelsDst = (u8) ((toOrr << toShift) | (*pixelsDst & (0xF0 >> toShift))); + } + } + } + } +} + +THUMB_FUNC void BlitBitmapRect8Bit(const struct Bitmap *src, + const struct Bitmap *dst, + u16 srcX, + u16 srcY, + u16 dstX, + u16 dstY, + u16 width, + u16 height, + u16 colorKey) +{ + int xEnd, yEnd; + int multiplierSrcY, multiplierDstY; + int loopSrcY, loopDstY; + int loopSrcX, loopDstX; + u8 * pixelsSrc, * pixelsDst; + + if (dst->width - dstX < width) + xEnd = dst->width - dstX + srcX; + else + xEnd = width + srcX; + if (dst->height - dstY < height) + yEnd = dst->height - dstY + srcY; + else + yEnd = height + srcY; + multiplierSrcY = (src->width + (src->width & 7)) >> 3; + multiplierDstY = (dst->width + (dst->width & 7)) >> 3; + + if (colorKey == 0xFFFF) + { + for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++) + { + for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++) + { + pixelsSrc = (u8 *)(src->pixels + ((loopSrcX >> 0) & 7) + ((loopSrcX << 3) & 0x7FC0) + (((loopSrcY << 3) & 0x7FC0) * multiplierSrcY) + (((loopSrcY << 3) & 0x38))); + pixelsDst = (u8 *)(dst->pixels + ((loopDstX >> 0) & 7) + ((loopDstX << 3) & 0x7FC0) + (((loopDstY << 3) & 0x7FC0) * multiplierDstY) + (((loopDstY << 3) & 0x38))); + + *pixelsDst = *pixelsSrc; + } + } + } + else + { + for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++) + { + for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++) + { + pixelsSrc = (u8 *)(src->pixels + ((loopSrcX >> 0) & 7) + ((loopSrcX << 3) & 0x7FC0) + (((loopSrcY << 3) & 0x7FC0) * multiplierSrcY) + (((loopSrcY << 3) & 0x38))); + pixelsDst = (u8 *)(dst->pixels + ((loopDstX >> 0) & 7) + ((loopDstX << 3) & 0x7FC0) + (((loopDstY << 3) & 0x7FC0) * multiplierDstY) + (((loopDstY << 3) & 0x38))); + + if (*pixelsSrc != colorKey) + *pixelsDst = *pixelsSrc; + } + } + } +} + +THUMB_FUNC void FillBitmapRect4Bit( + struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue) +{ + + int r6 = x + width; + if (r6 > surface->width) + { + r6 = surface->width; + } + + int r12 = y + height; + if (r12 > surface->height) + { + r12 = surface->height; + } + + int lr = (((surface->width) + (surface->width & 7)) >> 3); + + for (int i = y; i < r12; i++) + { + + for (int j = x; j < r6; j++) + { + + u8 *unk = (u8 *)((u8 *)surface->pixels + ((j >> 1) & 3) + ((j << 2) & 0x3fe0) + + (((i << 2) & 0x3fe0) * lr) + ((i << 2) & 0x1c)); + + if ((j & 1) != 0) + { + *unk &= 0xf; + *unk |= (fillValue << 4); + } + else + { + *unk &= 0xf0; + *unk |= fillValue; + } + } + } +} + +THUMB_FUNC void FillBitmapRect8Bit( + struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue) +{ + + int r6 = x + width; + if (r6 > surface->width) + { + r6 = surface->width; + } + + int r12 = y + height; + if (r12 > surface->height) + { + r12 = surface->height; + } + + int lr = (((surface->width) + (surface->width & 7)) >> 3); + + for (int i = y; i < r12; i++) + { + + for (int j = x; j < r6; j++) + { + + u8 *unk = (u8 *)((u8 *)surface->pixels + (j & 7) + ((j << 3) & 0x7fc0) + + (((i << 3) & 0x7fc0) * lr) + ((i << 3) & 0x38)); + + *unk = fillValue; + } + } +} + +THUMB_FUNC struct Window *AllocWindows(u32 heap_id, s32 size) +{ + struct Window *ptr = AllocFromHeap(heap_id, (u32)(size << 4)); + + for (u16 i = 0; i < size; i++) + { + InitWindow(&ptr[i]); + } + + return ptr; +} + +THUMB_FUNC void InitWindow(struct Window *window) +{ + window->bgConfig = NULL; + window->bgId = GF_BG_LYR_UNALLOC; + window->tilemapLeft = 0; + window->tilemapTop = 0; + window->width = 0; + window->height = 0; + window->paletteNum = 0; + + window->baseTile = 0; + window->pixelBuffer = NULL; + + window->colorMode = GF_BG_CLR_4BPP; +} + +THUMB_FUNC BOOL WindowIsInUse(struct Window *window) +{ + if (window->bgConfig == NULL || window->bgId == 0xff || window->pixelBuffer == NULL) + { + return FALSE; + } + + return TRUE; +} + +THUMB_FUNC void AddWindowParameterized(struct BgConfig *param0, + struct Window *window, + u8 bgId, + u8 tilemapLeft, + u8 tilemapTop, + u8 width, + u8 height, + u8 paletteNum, + u16 baseTile) +{ + if (param0->bgs[bgId].tilemapBuffer == NULL) + { + return; + } + + void *ptr = AllocFromHeap(param0->heap_id, (u32)(width * height * param0->bgs[bgId].tileSize)); + + if (ptr == NULL) + { + return; + } + window->bgConfig = param0; + window->bgId = bgId; + window->tilemapLeft = tilemapLeft; + window->tilemapTop = tilemapTop; + window->width = width; + window->height = height; + window->paletteNum = paletteNum; + + window->baseTile = baseTile; + window->pixelBuffer = ptr; + + window->colorMode = param0->bgs[bgId].colorMode == GX_BG_COLORMODE_16 ? GF_BG_CLR_4BPP : GF_BG_CLR_8BPP; +} + +THUMB_FUNC void AddTextWindowTopLeftCorner(struct BgConfig *param0, + struct Window *window, + u8 width, + u8 height, + u16 baseTile, + u8 paletteNum) +{ + u32 size = (u32)(width * height * 32); + + void *ptr = AllocFromHeap(param0->heap_id, size); + + paletteNum |= (paletteNum * 16); + memset(ptr, paletteNum, size); + + if (ptr != NULL) + { + window->bgConfig = param0; + window->width = width; + window->height = height; + window->baseTile = baseTile; + window->pixelBuffer = ptr; + window->colorMode = GF_BG_CLR_4BPP; + } +} + +THUMB_FUNC void AddWindow( + struct BgConfig *bgConfig, struct Window *window, const struct WindowTemplate *template) +{ + + AddWindowParameterized(bgConfig, + window, + template->bgId, + template->tilemapLeft, + template->tilemapTop, + template->width, + template->height, + template->paletteNum, + template->baseTile); +} + +THUMB_FUNC void RemoveWindow(struct Window *window) +{ + FreeToHeap(window->pixelBuffer); + + window->bgConfig = NULL; + window->bgId = 0xff; + window->tilemapLeft = 0; + window->tilemapTop = 0; + window->width = 0; + window->height = 0; + window->paletteNum = 0; + window->baseTile = 0; + window->pixelBuffer = NULL; +} + +THUMB_FUNC void WindowArray_dtor(struct Window *windows, int count) +{ + for (u16 i = 0; i < count; i++) + { + if (windows[i].pixelBuffer != NULL) + { + FreeToHeap(windows[i].pixelBuffer); + } + } + + FreeToHeap(windows); +} + +THUMB_FUNC void CopyWindowToVram(struct Window *window) +{ + + GF_ASSERT(window != NULL); + GF_ASSERT(window->bgConfig != NULL); + GF_ASSERT(window->bgId < NELEMS(window->bgConfig->bgs)); + GF_ASSERT(window->bgConfig->bgs[window->bgId].mode < NELEMS(sCopyWindowToVramFuncs)); + + sCopyWindowToVramFuncs[window->bgConfig->bgs[window->bgId].mode](window); +} + +THUMB_FUNC void ScheduleWindowCopyToVram(struct Window *window) +{ + + GF_ASSERT(window); + GF_ASSERT(window->bgConfig); + GF_ASSERT(window->bgId < NELEMS(window->bgConfig->bgs)); + GF_ASSERT(window->bgConfig->bgs[window->bgId].mode < NELEMS(sScheduleWindowCopyToVramFuncs)); + + sScheduleWindowCopyToVramFuncs[window->bgConfig->bgs[window->bgId].mode](window); +} + +THUMB_FUNC void PutWindowTilemap(struct Window *window) +{ + sPutWindowTilemapFuncs[window->bgConfig->bgs[window->bgId].mode](window); +} + +THUMB_FUNC void PutWindowTilemapRectAnchoredTopLeft(struct Window *window, u8 width, u8 height) +{ + u8 widthBak = window->width; + u8 heightBak = window->height; + + window->width = width; + window->height = height; + sPutWindowTilemapFuncs[window->bgConfig->bgs[window->bgId].mode](window); + + window->width = widthBak; + window->height = heightBak; +} + +THUMB_FUNC void ClearWindowTilemap(struct Window *window) +{ + sClearWindowTilemapFuncs[window->bgConfig->bgs[window->bgId].mode](window); +} + +THUMB_FUNC void PutWindowTilemap_TextMode(struct Window *param0) +{ + u32 i, j; + u32 r3; + u32 iCount, jCount; + u16 *st4 = param0->bgConfig->bgs[param0->bgId].tilemapBuffer; + + if (st4 == NULL) + { + return; + } + + r3 = param0->baseTile; + jCount = (u32)(param0->tilemapLeft + param0->width); + iCount = (u32)(param0->tilemapTop + param0->height); + + for (i = param0->tilemapTop; i < iCount; i++) + { + for (j = param0->tilemapLeft; j < jCount; j++) + { + st4[((i & 0x20) * 32) + ((j & 0x20) * 32) + ((i & 0x1f) << 5) + (j & 0x1f)] = + (u16)(r3 | (param0->paletteNum << 12)); + + r3++; + } + } +} + +THUMB_FUNC void PutWindowTilemap_AffineMode(struct Window *window) +{ + int j, i; + u8 *dst; + + int tileId; + int tilemapWidth; + + if (window->bgConfig->bgs[window->bgId].tilemapBuffer == NULL) + { + return; + } + + tilemapWidth = sTilemapWidthByBufferSize[window->bgConfig->bgs[window->bgId].size]; + + dst = window->bgConfig->bgs[window->bgId].tilemapBuffer + window->tilemapTop * tilemapWidth + window->tilemapLeft; + tileId = window->baseTile; + + for (i = 0; i < window->height; i++) + { + for (j = 0; j < window->width; j++) + { + dst[j] = (u8)tileId; + tileId++; + } + dst += tilemapWidth; + } +} + +THUMB_FUNC void ClearWindowTilemapText(struct Window *window) +{ + + u32 i, j; + + u32 yEnd, xEnd; + u32 tilemapWidth; + + u16 *dst; + + if (window->bgConfig->bgs[window->bgId].tilemapBuffer == NULL) + { + return; + } + dst = window->bgConfig->bgs[window->bgId].tilemapBuffer; + + tilemapWidth = sTilemapWidthByBufferSize[window->bgConfig->bgs[window->bgId].size]; + xEnd = (u32)(window->tilemapLeft + window->width); + yEnd = (u32)(window->tilemapTop + window->height); + + for (i = window->tilemapTop; i < yEnd; i++) + { + for (j = window->tilemapLeft; j < xEnd; j++) + { + dst[((i & 0x20) * 32) + ((j & 0x20) * 32) + ((i & 0x1f) * tilemapWidth) + (j & 0x1f)] = 0; + } + } +} + +THUMB_FUNC void ClearWindowTilemapAffine(struct Window *window) +{ + + int j, i; + u8 *dstPos; + + int tilemapWidth; + + if (window->bgConfig->bgs[window->bgId].tilemapBuffer == NULL) + { + return; + } + + tilemapWidth = sTilemapWidthByBufferSize[window->bgConfig->bgs[window->bgId].size]; + dstPos = window->bgConfig->bgs[window->bgId].tilemapBuffer + window->tilemapTop * tilemapWidth + window->tilemapLeft; + + for (i = 0; i < window->height; i++) + { + for (j = 0; j < window->width; j++) + { + dstPos[j] = 0; + } + dstPos += tilemapWidth; + } +} + +THUMB_FUNC void CopyWindowToVram_TextMode(struct Window *window) +{ + PutWindowTilemap_TextMode(window); + CopyWindowPixelsToVram_TextMode(window); + BgCopyOrUncompressTilemapBufferRangeToVram(window->bgConfig, + window->bgId, + window->bgConfig->bgs[window->bgId].tilemapBuffer, + window->bgConfig->bgs[window->bgId].bufferSize, + window->bgConfig->bgs[window->bgId].baseTile); +} + +THUMB_FUNC void ScheduleWindowCopyToVram_TextMode(struct Window *window) +{ + PutWindowTilemap_TextMode(window); + ScheduleBgTilemapBufferTransfer(window->bgConfig, window->bgId); + CopyWindowPixelsToVram_TextMode(window); +} + +THUMB_FUNC void CopyWindowToVram_AffineMode(struct Window *window) +{ + PutWindowTilemap_AffineMode(window); + BgCopyOrUncompressTilemapBufferRangeToVram(window->bgConfig, + window->bgId, + window->bgConfig->bgs[window->bgId].tilemapBuffer, + window->bgConfig->bgs[window->bgId].bufferSize, + window->bgConfig->bgs[window->bgId].baseTile); + + BG_LoadCharTilesData(window->bgConfig, + window->bgId, + window->pixelBuffer, + (u32)(window->width * window->height * 64), + window->baseTile); +} + +THUMB_FUNC void ScheduleWindowCopyToVram_AffineMode(struct Window *window) +{ + PutWindowTilemap_AffineMode(window); + ScheduleBgTilemapBufferTransfer(window->bgConfig, window->bgId); + BG_LoadCharTilesData(window->bgConfig, + window->bgId, + window->pixelBuffer, + (u32)(window->width * window->height * 64), + window->baseTile); +} + +THUMB_FUNC void CopyWindowPixelsToVram_TextMode(struct Window *window) +{ + BG_LoadCharTilesData(window->bgConfig, + window->bgId, + window->pixelBuffer, + (u32)(window->width * window->height * window->bgConfig->bgs[window->bgId].tileSize), + window->baseTile); +} + +THUMB_FUNC void ClearWindowTilemapAndCopyToVram(struct Window *window) +{ + sClearWindowTilemapAndCopyToVramFuncs[window->bgConfig->bgs[window->bgId].mode](window); +} + +THUMB_FUNC void ClearWindowTilemapAndScheduleTransfer(struct Window *window) +{ + sClearWindowTilemapAndScheduleTransferFuncs[window->bgConfig->bgs[window->bgId].mode](window); +} + +THUMB_FUNC void ClearWindowTilemapAndCopyToVram_TextMode(struct Window *window) +{ + ClearWindowTilemapText(window); + BgCopyOrUncompressTilemapBufferRangeToVram(window->bgConfig, + window->bgId, + window->bgConfig->bgs[window->bgId].tilemapBuffer, + window->bgConfig->bgs[window->bgId].bufferSize, + window->bgConfig->bgs[window->bgId].baseTile); +} + +THUMB_FUNC void ClearWindowTilemapAndScheduleTransfer_TextMode(struct Window *window) +{ + ClearWindowTilemapText(window); + ScheduleBgTilemapBufferTransfer(window->bgConfig, window->bgId); +} + +THUMB_FUNC void ClearWindowTilemapAndCopyToVram_AffineMode(struct Window *window) +{ + ClearWindowTilemapAffine(window); + BgCopyOrUncompressTilemapBufferRangeToVram(window->bgConfig, + window->bgId, + window->bgConfig->bgs[window->bgId].tilemapBuffer, + window->bgConfig->bgs[window->bgId].bufferSize, + window->bgConfig->bgs[window->bgId].baseTile); +} + +THUMB_FUNC void ClearWindowTilemapAndScheduleTransfer_AffineMode(struct Window *window) +{ + ClearWindowTilemapAffine(window); + ScheduleBgTilemapBufferTransfer(window->bgConfig, window->bgId); +} + +THUMB_FUNC void FillWindowPixelBuffer(struct Window *window, u8 param1) +{ + if (window->bgConfig->bgs[window->bgId].tileSize == 0x20) + { + param1 |= param1 << 4; + } + + MI_CpuFillFast( + window->pixelBuffer, + (u32)((param1 << 0x18) | (param1 << 0x10) | (param1 << 0x8) | param1), + (u32)(window->bgConfig->bgs[window->bgId].tileSize * window->width * window->height)); +} + +THUMB_FUNC void BlitBitmapRectToWindow(struct Window *window, + const void *src, + u16 srcX, + u16 srcY, + u16 srcWidth, + u16 srcHeight, + u16 dstX, + u16 dstY, + u16 dstWidth, + u16 dstHeight) +{ + BlitBitmapRect( + window, src, srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, 0); +} + +THUMB_FUNC void BlitBitmapRect(struct Window *window, + void *param1, + u16 param2, + u16 param3, + u16 param4, + u16 param5, + u16 param6, + u16 param7, + u16 param8, + u16 param9, + u16 param10) +{ + struct Bitmap st1c = { param1, param4, param5 }; + struct Bitmap st14 = { + window->pixelBuffer, (u16)(window->width << 3), (u16)(window->height << 3) + }; + + if (window->bgConfig->bgs[window->bgId].colorMode == GX_BG_COLORMODE_16) + { + BlitBitmapRect4Bit(&st1c, &st14, param2, param3, param6, param7, param8, param9, param10); + } + else + { + BlitBitmapRect8Bit(&st1c, &st14, param2, param3, param6, param7, param8, param9, param10); + } +} + +THUMB_FUNC void FillWindowPixelRect( + struct Window *window, u8 fillValue, u16 x, u16 y, u16 width, u16 height) +{ + struct Bitmap st8 = { + window->pixelBuffer, (u16)(window->width << 3), (u16)(window->height << 3) + }; + + if (window->bgConfig->bgs[window->bgId].colorMode == GX_BG_COLORMODE_16) + { + FillBitmapRect4Bit(&st8, x, y, width, height, fillValue); + } + else + { + FillBitmapRect8Bit(&st8, x, y, width, height, fillValue); + } +} + +#ifdef NONMATCHING +THUMB_FUNC void CopyGlyphToWindow( + struct Window *window, u32 *param1, u32 param2, u32 param3, u16 param4, u16 param5, u32 param6) +{ + u32 str330 = param6; + u32 *st0 = param1; + u16 st5c = param4; + + void *st278 = window->unk0c; + u16 st58 = window->width << 3; + + int st8 = st58 - st5c; + + if (st8 >= param2) + { + st8 = param2; + } + + int st4 = (u16)(window->height << 3) - param5; + u16 st48 = param5; + + if (st4 >= param3) + { + st4 = param3; + } + + u8 r4 = 0; + if (st8 > 8) + { + r4 |= 1; + } + + if (st4 > 8) + { + r4 |= 2; + } + + if (window->unk0b_15 == 0) + { + switch (r4) + { + case 0: + u8 st70 = param6; + for (u32 st274 = 0; st274 < st4; st274++) + { + u32 st6c = (st58 + (st58 & 7)) >> 3; + + u32 st26c = st0[0]; + u8 st270 = (u8)((st70 >> st274) & 1); + u32 r2 = st5c; + + for (u32 r1 = 0; r1 < st8; r1++) + { + u32 r3 = st5c << 2; + u32 st68 = ((st48 << 2) & 0x3fe0) * st6c; + u32 r7 = (st48 << 2) & 0x1c; + u32 st64 = (((st48 + 1) << 2) & 0x3fe0) * st6c; + u32 st60 = ((st48 + 1) << 2) & 0x1c; + u32 r4 = r1; + + void *st27c = st278 + ((r2 >> 1) & 3) + (r3 & 0x3fe0); + u8 *r0 = st27c + st68; + + u8 r5 = (u8)((st26c >> r4) & 0xf); + if (r5 != 0) + { + u32 st280 = (r5 << ((r2 & 1) << 2)); + u32 st284 = r0[r7]; + + u8 r5 = ((0xf0 >> ((r2 & 1) << 2)) & st284) | st280; + r0[r7] = r5; + + if (st270 != 0) + { + *(u8 *)(st27c + st64 + st60) = r5; + } + } + + r4 += 4; + r3 += 4; + r2 += 1; + } + + if (st270 != 0) + { + st48 += 2; + } + else + { + st48++; + } + + st0++; + } + + break; + + case 1: + u32 *st25c = st0; + u32 st264 = st48; + u8 st54 = param6; + u8 st84 = param6; + + for (u32 st268 = 0; st268 < st4; st268++) + { + u32 st80 = (st58 + (st58 & 7)) >> 3; + + u32 st258 = *st25c; + u32 r2 = st5c; + u8 st260 = (st84 >> st268) & 1; + u32 r3 = st5c << 2; + u32 st7c = ((st264 << 2) & 0x3fe0) * st80; + u32 r7 = (st264 << 2) & 0x1c; + u32 st78 = (((st264 + 1) << 2) & 0x3fe0) * st80; + u32 st74 = ((st264 + 1) << 2) & 0x1c; + u32 r4 = 0; + + for (u32 r1 = 0; r1 < 8; r1++) + { + void *st288 = st278 + ((r2 >> 1) & 3) + (r3 & 0x3fe0); + u8 *r0 = st288 + st7c; + u8 r5 = (st258 >> r4) & 0xf; + if (r5 != 0) + { + u32 st28c = r5 << ((r2 & 1) << 2); + u32 st290 = r0[r7]; + u8 r5 = ((0xf0 >> ((r2 & 1) << 2)) & st290) | st28c; + r0[r7] = r5; + + if (st260 != 0) + { + *(u8 *)(st288 + st78 + st74) = r5; + } + } + + r4 += 4; + r3 += 4; + r2++; + } + + if (st260 != 0) + { + st264 += 2; + } + else + { + st264++; + } + + st25c++; + } + + st0 += 0x20; + u8 st98 = st54; + + for (u32 st254 = 0; st254 < st4; st254++) + { + st5c += 8; + u32 st94 = (st58 + (st58 & 7)) >> 3; + + //_02019A00 + } + + break; + + case 2: + // TODO + break; + case 3: + // TODO + break; + } + } + else + { + // TODO: _0201A12C + } +} +#else +asm void CopyGlyphToWindow( + struct Window *window, const char *param1, u16 param2, u16 param3, u16 param4, u16 param5, u16 param6) +{ + // clang-format off + push {r4-r7, lr} + sub sp, #0x1fc + sub sp, #0x118 + add r5, r0, #0x0 + ldr r0, [sp, #0x330] + str r1, [sp, #0x0] + str r0, [sp, #0x330] + add r1, sp, #0x318 + ldrh r1, [r1, #0x10] + ldr r0, [r5, #0xc] + str r1, [sp, #0x5c] + ldrb r1, [r5, #0x7] + str r0, [sp, #0x278] + ldrb r0, [r5, #0x8] + lsl r1, r1, #0x13 + lsr r4, r1, #0x10 + ldr r1, [sp, #0x5c] + lsl r0, r0, #0x13 + sub r1, r4, r1 + lsr r0, r0, #0x10 + str r4, [sp, #0x58] + str r1, [sp, #0x8] + cmp r1, r2 + blt _0201977E + str r2, [sp, #0x8] +_0201977E: + add r1, sp, #0x318 + ldrh r1, [r1, #0x14] + sub r0, r0, r1 + str r1, [sp, #0x48] + str r0, [sp, #0x4] + cmp r0, r3 + blt _0201978E + str r3, [sp, #0x4] +_0201978E: + ldr r0, [sp, #0x8] + mov r4, #0x0 + cmp r0, #0x8 + ble _0201979E + mov r0, #0x1 + orr r0, r4 + lsl r0, r0, #0x18 + lsr r4, r0, #0x18 +_0201979E: + ldr r0, [sp, #0x4] + cmp r0, #0x8 + ble _020197AC + mov r0, #0x2 + orr r0, r4 + lsl r0, r0, #0x18 + lsr r4, r0, #0x18 +_020197AC: + ldrh r0, [r5, #0xa] + lsl r0, r0, #0x10 + lsr r0, r0, #0x1f + beq _020197B8 + bl _0201A12C +_020197B8: + cmp r4, #0x3 + bls _020197C0 + bl _0201A8BC +_020197C0: + add r0, r4, r4 + add r0, pc + ldrh r0, [r0, #0x6] + lsl r0, r0, #0x10 + asr r0, r0, #0x10 + add pc, r0 +_020197CC: + lsl r6, r0, #0 + lsl r0, r1, #4 + lsl r0, r3, #12 + lsl r0, r7, #20 + // jump table (using 16-bit offset) + // .short _020197D4 - _020197CC - 2; case 0 + // .short _020198D6 - _020197CC - 2; case 1 + // .short _02019AE6 - _020197CC - 2; case 2 + // .short _02019D06 - _020197CC - 2; case 3 +_020197D4: + ldr r0, [sp, #0x330] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x70] + mov r0, #0x0 + str r0, [sp, #0x274] + ldr r0, [sp, #0x4] + cmp r0, #0x0 + bgt _020197EA + bl _0201A8BC +_020197EA: + ldr r0, [sp, #0x58] + mov r1, #0x7 + and r1, r0 + add r0, r0, r1 + asr r0, r0, #0x3 + str r0, [sp, #0x6c] +_020197F6: + ldr r0, [sp, #0x0] + ldr r1, [sp, #0x70] + ldr r0, [r0, #0x0] + ldr r2, [sp, #0x5c] + str r0, [sp, #0x26c] + ldr r0, [sp, #0x274] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x270] + ldr r0, [sp, #0x8] + mov r1, #0x0 + cmp r0, #0x0 + ble _020198AA + ble _020198AA + add r0, r2, #0x0 + lsl r3, r0, #0x2 + ldr r0, [sp, #0x48] + ldr r6, [sp, #0x6c] + lsl r5, r0, #0x2 + ldr r0, =0x00003FE0 + add r7, r5, #0x0 + and r0, r5 + mul r6, r0 + mov r0, #0x1c + and r7, r0 + ldr r0, [sp, #0x48] + str r6, [sp, #0x68] + add r0, r0, #0x1 + lsl r6, r0, #0x2 + ldr r0, =0x00003FE0 + ldr r5, [sp, #0x6c] + and r0, r6 + mul r5, r0 + mov r0, #0x1c + and r0, r6 + add r4, r1, #0x0 + str r5, [sp, #0x64] + str r0, [sp, #0x60] +_02019848: + asr r5, r2, #0x1 + mov r0, #0x3 + and r5, r0 + ldr r0, [sp, #0x278] + add r0, r0, r5 + ldr r5, =0x00003FE0 + and r5, r3 + add r5, r0, r5 + ldr r0, [sp, #0x68] + str r5, [sp, #0x27c] + add r0, r5, r0 + ldr r5, [sp, #0x26c] + add r6, r5, #0x0 + lsr r6, r4 + mov r5, #0xf + and r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + beq _0201989C + lsl r6, r2, #0x1f + lsr r6, r6, #0x1d + lsl r5, r6 + str r5, [sp, #0x280] + ldrb r5, [r0, r7] + str r5, [sp, #0x284] + mov r5, #0xf0 + asr r5, r6 + ldr r6, [sp, #0x284] + and r6, r5 + ldr r5, [sp, #0x280] + orr r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + strb r5, [r0, r7] + ldr r0, [sp, #0x270] + cmp r0, #0x0 + beq _0201989C + ldr r6, [sp, #0x27c] + ldr r0, [sp, #0x64] + add r6, r6, r0 + ldr r0, [sp, #0x60] + strb r5, [r0, r6] +_0201989C: + ldr r0, [sp, #0x8] + add r1, r1, #0x1 + add r4, r4, #0x4 + add r3, r3, #0x4 + add r2, r2, #0x1 + cmp r1, r0 + blt _02019848 +_020198AA: + ldr r0, [sp, #0x270] + cmp r0, #0x0 + beq _020198B8 + ldr r0, [sp, #0x48] + add r0, r0, #0x2 + str r0, [sp, #0x48] + b _020198BE +_020198B8: + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_020198BE: + ldr r0, [sp, #0x0] + add r0, r0, #0x4 + str r0, [sp, #0x0] + ldr r0, [sp, #0x274] + add r1, r0, #0x1 + ldr r0, [sp, #0x4] + str r1, [sp, #0x274] + cmp r1, r0 + blt _020197F6 + add sp, #0x1fc + add sp, #0x118 + pop {r4-r7, pc} +_020198D6: + ldr r0, [sp, #0x0] + str r0, [sp, #0x25c] + ldr r0, [sp, #0x48] + str r0, [sp, #0x264] + ldr r0, [sp, #0x330] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x54] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x84] + mov r0, #0x0 + str r0, [sp, #0x268] + ldr r0, [sp, #0x4] + cmp r0, #0x0 + ble _020199D2 + ldr r0, [sp, #0x58] + mov r1, #0x7 + and r1, r0 + add r0, r0, r1 + asr r0, r0, #0x3 + str r0, [sp, #0x80] +_02019902: + ldr r0, [sp, #0x25c] + ldr r1, [sp, #0x84] + ldr r0, [r0, #0x0] + ldr r2, [sp, #0x5c] + str r0, [sp, #0x258] + ldr r0, [sp, #0x268] + ldr r6, [sp, #0x80] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x260] + add r0, r2, #0x0 + lsl r3, r0, #0x2 + ldr r0, [sp, #0x264] + mov r1, #0x0 + lsl r5, r0, #0x2 + ldr r0, =0x00003FE0 + add r7, r5, #0x0 + and r0, r5 + mul r6, r0 + mov r0, #0x1c + and r7, r0 + ldr r0, [sp, #0x264] + str r6, [sp, #0x7c] + add r0, r0, #0x1 + lsl r6, r0, #0x2 + ldr r0, =0x00003FE0 + ldr r5, [sp, #0x80] + and r0, r6 + mul r5, r0 + mov r0, #0x1c + and r0, r6 + add r4, r1, #0x0 + str r5, [sp, #0x78] + str r0, [sp, #0x74] +_0201994C: + asr r5, r2, #0x1 + mov r0, #0x3 + and r5, r0 + ldr r0, [sp, #0x278] + add r0, r0, r5 + ldr r5, =0x00003FE0 + and r5, r3 + add r5, r0, r5 + ldr r0, [sp, #0x7c] + str r5, [sp, #0x288] + add r0, r5, r0 + ldr r5, [sp, #0x258] + add r6, r5, #0x0 + lsr r6, r4 + mov r5, #0xf + and r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + beq _020199A0 + lsl r6, r2, #0x1f + lsr r6, r6, #0x1d + lsl r5, r6 + str r5, [sp, #0x28c] + ldrb r5, [r0, r7] + str r5, [sp, #0x290] + mov r5, #0xf0 + asr r5, r6 + ldr r6, [sp, #0x290] + and r6, r5 + ldr r5, [sp, #0x28c] + orr r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + strb r5, [r0, r7] + ldr r0, [sp, #0x260] + cmp r0, #0x0 + beq _020199A0 + ldr r6, [sp, #0x288] + ldr r0, [sp, #0x78] + add r6, r6, r0 + ldr r0, [sp, #0x74] + strb r5, [r0, r6] +_020199A0: + add r1, r1, #0x1 + add r4, r4, #0x4 + add r3, r3, #0x4 + add r2, r2, #0x1 + cmp r1, #0x8 + blt _0201994C + ldr r0, [sp, #0x260] + cmp r0, #0x0 + beq _020199BA + ldr r0, [sp, #0x264] + add r0, r0, #0x2 + str r0, [sp, #0x264] + b _020199C0 +_020199BA: + ldr r0, [sp, #0x264] + add r0, r0, #0x1 + str r0, [sp, #0x264] +_020199C0: + ldr r0, [sp, #0x25c] + add r0, r0, #0x4 + str r0, [sp, #0x25c] + ldr r0, [sp, #0x268] + add r1, r0, #0x1 + ldr r0, [sp, #0x4] + str r1, [sp, #0x268] + cmp r1, r0 + blt _02019902 +_020199D2: + ldr r0, [sp, #0x0] + add r0, #0x20 + str r0, [sp, #0x0] + ldr r0, [sp, #0x54] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x98] + mov r0, #0x0 + str r0, [sp, #0x254] + ldr r0, [sp, #0x4] + cmp r0, #0x0 + bgt _020199EE + bl _0201A8BC +_020199EE: + ldr r0, [sp, #0x5c] + mov r1, #0x7 + add r0, #0x8 + str r0, [sp, #0x5c] + ldr r0, [sp, #0x58] + and r1, r0 + add r0, r0, r1 + asr r0, r0, #0x3 + str r0, [sp, #0x94] +_02019A00: + ldr r0, [sp, #0x0] + ldr r1, [sp, #0x98] + ldr r0, [r0, #0x0] + ldr r2, [sp, #0x5c] + str r0, [sp, #0x24c] + ldr r0, [sp, #0x254] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x250] + ldr r0, [sp, #0x8] + mov r1, #0x0 + str r0, [sp, #0x294] + sub r0, #0x8 + str r0, [sp, #0x294] + cmp r0, #0x0 + ble _02019ABA + ble _02019ABA + add r0, r2, #0x0 + lsl r3, r0, #0x2 + ldr r0, [sp, #0x48] + ldr r6, [sp, #0x94] + lsl r5, r0, #0x2 + ldr r0, =0x00003FE0 + add r7, r5, #0x0 + and r0, r5 + mul r6, r0 + mov r0, #0x1c + and r7, r0 + ldr r0, [sp, #0x48] + str r6, [sp, #0x90] + add r0, r0, #0x1 + lsl r6, r0, #0x2 + ldr r0, =0x00003FE0 + ldr r5, [sp, #0x94] + and r0, r6 + mul r5, r0 + mov r0, #0x1c + and r0, r6 + add r4, r1, #0x0 + str r5, [sp, #0x8c] + str r0, [sp, #0x88] +_02019A58: + asr r5, r2, #0x1 + mov r0, #0x3 + and r5, r0 + ldr r0, [sp, #0x278] + add r0, r0, r5 + ldr r5, =0x00003FE0 + and r5, r3 + add r5, r0, r5 + ldr r0, [sp, #0x90] + str r5, [sp, #0x298] + add r0, r5, r0 + ldr r5, [sp, #0x24c] + add r6, r5, #0x0 + lsr r6, r4 + mov r5, #0xf + and r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + beq _02019AAC + lsl r6, r2, #0x1f + lsr r6, r6, #0x1d + lsl r5, r6 + str r5, [sp, #0x29c] + ldrb r5, [r0, r7] + str r5, [sp, #0x2a0] + mov r5, #0xf0 + asr r5, r6 + ldr r6, [sp, #0x2a0] + and r6, r5 + ldr r5, [sp, #0x29c] + orr r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + strb r5, [r0, r7] + ldr r0, [sp, #0x250] + cmp r0, #0x0 + beq _02019AAC + ldr r6, [sp, #0x298] + ldr r0, [sp, #0x8c] + add r6, r6, r0 + ldr r0, [sp, #0x88] + strb r5, [r0, r6] +_02019AAC: + ldr r0, [sp, #0x294] + add r1, r1, #0x1 + add r4, r4, #0x4 + add r3, r3, #0x4 + add r2, r2, #0x1 + cmp r1, r0 + blt _02019A58 +_02019ABA: + ldr r0, [sp, #0x250] + cmp r0, #0x0 + beq _02019AC8 + ldr r0, [sp, #0x48] + add r0, r0, #0x2 + str r0, [sp, #0x48] + b _02019ACE +_02019AC8: + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_02019ACE: + ldr r0, [sp, #0x0] + add r0, r0, #0x4 + str r0, [sp, #0x0] + ldr r0, [sp, #0x254] + add r1, r0, #0x1 + ldr r0, [sp, #0x4] + str r1, [sp, #0x254] + cmp r1, r0 + blt _02019A00 + add sp, #0x1fc + add sp, #0x118 + pop {r4-r7, pc} +_02019AE6: + ldr r0, [sp, #0x0] + mov r1, #0x7 + str r0, [sp, #0x23c] + ldr r0, [sp, #0x48] + str r0, [sp, #0x244] + mov r0, #0x0 + str r0, [sp, #0x248] + ldr r0, [sp, #0x330] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0xa8] + ldr r0, [sp, #0x58] + and r1, r0 + add r0, r0, r1 + asr r0, r0, #0x3 + str r0, [sp, #0x40] +_02019B06: + ldr r0, [sp, #0x23c] + ldr r1, [sp, #0xa8] + ldr r0, [r0, #0x0] + ldr r2, [sp, #0x5c] + str r0, [sp, #0x238] + ldr r0, [sp, #0x248] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x240] + ldr r0, [sp, #0x8] + mov r1, #0x0 + cmp r0, #0x0 + ble _02019BC2 + ble _02019BC2 + add r0, r2, #0x0 + lsl r3, r0, #0x2 + ldr r0, [sp, #0x244] + ldr r6, [sp, #0x40] + lsl r5, r0, #0x2 + ldr r0, =0x00003FE0 + add r7, r5, #0x0 + and r0, r5 + mul r6, r0 + mov r0, #0x1c + and r7, r0 + ldr r0, [sp, #0x244] + str r6, [sp, #0xa4] + add r0, r0, #0x1 + lsl r6, r0, #0x2 + ldr r0, =0x00003FE0 + ldr r5, [sp, #0x40] + and r0, r6 + mul r5, r0 + mov r0, #0x1c + and r0, r6 + add r4, r1, #0x0 + str r5, [sp, #0xa0] + str r0, [sp, #0x9c] +_02019B58: + asr r5, r2, #0x1 + mov r0, #0x3 + and r5, r0 + ldr r0, [sp, #0x278] + add r0, r0, r5 + ldr r5, =0x00003FE0 +// b _02019B6C +// nop +// _02019B68: .word 0x00003FE0 +// _02019B6C: + and r5, r3 + add r5, r0, r5 + ldr r0, [sp, #0xa4] + str r5, [sp, #0x2a4] + add r0, r5, r0 + ldr r5, [sp, #0x238] + add r6, r5, #0x0 + lsr r6, r4 + mov r5, #0xf + and r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + beq _02019BB4 + lsl r6, r2, #0x1f + lsr r6, r6, #0x1d + lsl r5, r6 + str r5, [sp, #0x2a8] + ldrb r5, [r0, r7] + str r5, [sp, #0x2ac] + mov r5, #0xf0 + asr r5, r6 + ldr r6, [sp, #0x2ac] + and r6, r5 + ldr r5, [sp, #0x2a8] + orr r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + strb r5, [r0, r7] + ldr r0, [sp, #0x240] + cmp r0, #0x0 + beq _02019BB4 + ldr r6, [sp, #0x2a4] + ldr r0, [sp, #0xa0] + add r6, r6, r0 + ldr r0, [sp, #0x9c] + strb r5, [r0, r6] +_02019BB4: + ldr r0, [sp, #0x8] + add r1, r1, #0x1 + add r4, r4, #0x4 + add r3, r3, #0x4 + add r2, r2, #0x1 + cmp r1, r0 + blt _02019B58 +_02019BC2: + ldr r0, [sp, #0x240] + cmp r0, #0x0 + beq _02019BD0 + ldr r0, [sp, #0x244] + add r0, r0, #0x2 + str r0, [sp, #0x244] + b _02019BD6 +_02019BD0: + ldr r0, [sp, #0x244] + add r0, r0, #0x1 + str r0, [sp, #0x244] +_02019BD6: + ldr r0, [sp, #0x23c] + add r0, r0, #0x4 + str r0, [sp, #0x23c] + ldr r0, [sp, #0x248] + add r0, r0, #0x1 + str r0, [sp, #0x248] + cmp r0, #0x8 + blt _02019B06 + ldr r0, [sp, #0x0] + mov r2, #0x0 + add r0, #0x40 + str r0, [sp, #0x0] + ldr r0, [sp, #0x48] + mov r1, #0x1 + add r0, #0x8 + str r0, [sp, #0x48] +_02019BF6: + ldr r0, [sp, #0x330] + asr r0, r2 + tst r0, r1 + beq _02019C04 + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_02019C04: + add r2, r2, #0x1 + cmp r2, #0x8 + blt _02019BF6 + ldr r0, [sp, #0x330] + asr r0, r0, #0x8 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0xb8] + mov r0, #0x0 + str r0, [sp, #0x20] + ldr r0, [sp, #0x4] + sub r0, #0x8 + cmp r0, #0x0 + bgt _02019C24 + bl _0201A8BC +_02019C24: + ldr r0, [sp, #0x0] + ldr r1, [sp, #0xb8] + ldr r0, [r0, #0x0] + ldr r2, [sp, #0x5c] + str r0, [sp, #0x230] + ldr r0, [sp, #0x20] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x234] + ldr r0, [sp, #0x8] + mov r1, #0x0 + cmp r0, #0x0 + ble _02019CD8 + ble _02019CD8 + add r0, r2, #0x0 + lsl r3, r0, #0x2 + ldr r0, [sp, #0x48] + ldr r6, [sp, #0x40] + lsl r5, r0, #0x2 + ldr r0, =0x00003FE0 + add r7, r5, #0x0 + and r0, r5 + mul r6, r0 + mov r0, #0x1c + and r7, r0 + ldr r0, [sp, #0x48] + str r6, [sp, #0xb4] + add r0, r0, #0x1 + lsl r6, r0, #0x2 + ldr r0, =0x00003FE0 + ldr r5, [sp, #0x40] + and r0, r6 + mul r5, r0 + mov r0, #0x1c + and r0, r6 + add r4, r1, #0x0 + str r5, [sp, #0xb0] + str r0, [sp, #0xac] +_02019C76: + asr r5, r2, #0x1 + mov r0, #0x3 + and r5, r0 + ldr r0, [sp, #0x278] + add r0, r0, r5 + ldr r5, =0x00003FE0 + and r5, r3 + add r5, r0, r5 + ldr r0, [sp, #0xb4] + str r5, [sp, #0x2b0] + add r0, r5, r0 + ldr r5, [sp, #0x230] + add r6, r5, #0x0 + lsr r6, r4 + mov r5, #0xf + and r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + beq _02019CCA + lsl r6, r2, #0x1f + lsr r6, r6, #0x1d + lsl r5, r6 + str r5, [sp, #0x2b4] + ldrb r5, [r0, r7] + str r5, [sp, #0x2b8] + mov r5, #0xf0 + asr r5, r6 + ldr r6, [sp, #0x2b8] + and r6, r5 + ldr r5, [sp, #0x2b4] + orr r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + strb r5, [r0, r7] + ldr r0, [sp, #0x234] + cmp r0, #0x0 + beq _02019CCA + ldr r6, [sp, #0x2b0] + ldr r0, [sp, #0xb0] + add r6, r6, r0 + ldr r0, [sp, #0xac] + strb r5, [r0, r6] +_02019CCA: + ldr r0, [sp, #0x8] + add r1, r1, #0x1 + add r4, r4, #0x4 + add r3, r3, #0x4 + add r2, r2, #0x1 + cmp r1, r0 + blt _02019C76 +_02019CD8: + ldr r0, [sp, #0x234] + cmp r0, #0x0 + beq _02019CE6 + ldr r0, [sp, #0x48] + add r0, r0, #0x2 + str r0, [sp, #0x48] + b _02019CEC +_02019CE6: + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_02019CEC: + ldr r0, [sp, #0x0] + ldr r1, [sp, #0x4] + add r0, r0, #0x4 + str r0, [sp, #0x0] + ldr r0, [sp, #0x20] + sub r1, #0x8 + add r0, r0, #0x1 + str r0, [sp, #0x20] + cmp r0, r1 + blt _02019C24 + add sp, #0x1fc + add sp, #0x118 + pop {r4-r7, pc} +_02019D06: + ldr r0, [sp, #0x0] + str r0, [sp, #0x220] + ldr r0, [sp, #0x48] + str r0, [sp, #0x228] + ldr r0, [sp, #0x330] + lsl r0, r0, #0x18 + lsr r1, r0, #0x18 + mov r0, #0x0 + str r0, [sp, #0x22c] + lsl r0, r1, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x3c] + ldr r0, [sp, #0x58] + mov r1, #0x7 + and r1, r0 + add r0, r0, r1 + asr r0, r0, #0x3 + str r0, [sp, #0x38] +_02019D2A: + ldr r0, [sp, #0x220] + ldr r1, [sp, #0x3c] + ldr r0, [r0, #0x0] + ldr r2, [sp, #0x5c] + str r0, [sp, #0x21c] + ldr r0, [sp, #0x22c] + ldr r6, [sp, #0x38] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x224] + add r0, r2, #0x0 + lsl r3, r0, #0x2 + ldr r0, [sp, #0x228] + mov r1, #0x0 + lsl r5, r0, #0x2 + ldr r0, =0x00003FE0 + add r7, r5, #0x0 + and r0, r5 + mul r6, r0 + mov r0, #0x1c + and r7, r0 + ldr r0, [sp, #0x228] + str r6, [sp, #0xc4] + add r0, r0, #0x1 + lsl r6, r0, #0x2 + ldr r0, =0x00003FE0 + ldr r5, [sp, #0x38] + and r0, r6 + mul r5, r0 + mov r0, #0x1c + and r0, r6 + str r3, [sp, #0x34] + add r4, r1, #0x0 + str r5, [sp, #0xc0] + str r0, [sp, #0xbc] +_02019D76: + asr r5, r2, #0x1 + mov r0, #0x3 + and r5, r0 + ldr r0, [sp, #0x278] + add r0, r0, r5 + ldr r5, =0x00003FE0 + and r5, r3 + add r5, r0, r5 + ldr r0, [sp, #0xc4] + str r5, [sp, #0x2bc] + add r0, r5, r0 + ldr r5, [sp, #0x21c] + add r6, r5, #0x0 + lsr r6, r4 + mov r5, #0xf + and r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + beq _02019DCA + lsl r6, r2, #0x1f + lsr r6, r6, #0x1d + lsl r5, r6 + str r5, [sp, #0x2c0] + ldrb r5, [r0, r7] + str r5, [sp, #0x2c4] + mov r5, #0xf0 + asr r5, r6 + ldr r6, [sp, #0x2c4] + and r6, r5 + ldr r5, [sp, #0x2c0] + orr r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + strb r5, [r0, r7] + ldr r0, [sp, #0x224] + cmp r0, #0x0 + beq _02019DCA + ldr r6, [sp, #0x2bc] + ldr r0, [sp, #0xc0] + add r6, r6, r0 + ldr r0, [sp, #0xbc] + strb r5, [r0, r6] +_02019DCA: + add r1, r1, #0x1 + add r4, r4, #0x4 + add r3, r3, #0x4 + add r2, r2, #0x1 + cmp r1, #0x8 + blt _02019D76 + ldr r0, [sp, #0x224] + cmp r0, #0x0 + beq _02019DE4 + ldr r0, [sp, #0x228] + add r0, r0, #0x2 + str r0, [sp, #0x228] + b _02019DEA +_02019DE4: + ldr r0, [sp, #0x228] + add r0, r0, #0x1 + str r0, [sp, #0x228] +_02019DEA: + ldr r0, [sp, #0x220] + add r0, r0, #0x4 + str r0, [sp, #0x220] + ldr r0, [sp, #0x22c] + add r0, r0, #0x1 + str r0, [sp, #0x22c] + cmp r0, #0x8 + blt _02019D2A + ldr r0, [sp, #0x0] + str r0, [sp, #0x20c] + add r0, #0x20 + str r0, [sp, #0x20c] + ldr r0, [sp, #0x48] + str r0, [sp, #0x214] + mov r0, #0x0 + str r0, [sp, #0x218] + ldr r0, [sp, #0x5c] + str r0, [sp, #0xd4] + add r0, #0x8 + str r0, [sp, #0xd4] +_02019E12: + ldr r0, [sp, #0x20c] + ldr r1, [sp, #0x3c] + ldr r0, [r0, #0x0] + ldr r2, [sp, #0xd4] + str r0, [sp, #0x208] + ldr r0, [sp, #0x218] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x210] + ldr r0, [sp, #0x8] + mov r1, #0x0 + str r0, [sp, #0x2c8] + sub r0, #0x8 + str r0, [sp, #0x2c8] + cmp r0, #0x0 + ble _02019ECC + ble _02019ECC + add r0, r2, #0x0 + lsl r3, r0, #0x2 + ldr r0, [sp, #0x214] + ldr r6, [sp, #0x38] + lsl r5, r0, #0x2 + ldr r0, =0x00003FE0 + add r7, r5, #0x0 + and r0, r5 + mul r6, r0 + mov r0, #0x1c + and r7, r0 + ldr r0, [sp, #0x214] + str r6, [sp, #0xd0] + add r0, r0, #0x1 + lsl r6, r0, #0x2 + ldr r0, =0x00003FE0 + ldr r5, [sp, #0x38] + and r0, r6 + mul r5, r0 + mov r0, #0x1c + and r0, r6 + add r4, r1, #0x0 + str r5, [sp, #0xcc] + str r0, [sp, #0xc8] +_02019E6A: + asr r5, r2, #0x1 + mov r0, #0x3 + and r5, r0 + ldr r0, [sp, #0x278] + add r0, r0, r5 + ldr r5, =0x00003FE0 + and r5, r3 + add r5, r0, r5 + ldr r0, [sp, #0xd0] + str r5, [sp, #0x2cc] + add r0, r5, r0 + ldr r5, [sp, #0x208] + add r6, r5, #0x0 + lsr r6, r4 + mov r5, #0xf + and r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + beq _02019EBE + lsl r6, r2, #0x1f + lsr r6, r6, #0x1d + lsl r5, r6 + str r5, [sp, #0x2d0] + ldrb r5, [r0, r7] + str r5, [sp, #0x2d4] + mov r5, #0xf0 + asr r5, r6 + ldr r6, [sp, #0x2d4] + and r6, r5 + ldr r5, [sp, #0x2d0] + orr r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + strb r5, [r0, r7] + ldr r0, [sp, #0x210] + cmp r0, #0x0 + beq _02019EBE + ldr r6, [sp, #0x2cc] + ldr r0, [sp, #0xcc] + add r6, r6, r0 + ldr r0, [sp, #0xc8] + strb r5, [r0, r6] +_02019EBE: + ldr r0, [sp, #0x2c8] + add r1, r1, #0x1 + add r4, r4, #0x4 + add r3, r3, #0x4 + add r2, r2, #0x1 + cmp r1, r0 + blt _02019E6A +_02019ECC: + ldr r0, [sp, #0x210] + cmp r0, #0x0 + beq _02019EDA + ldr r0, [sp, #0x214] + add r0, r0, #0x2 + str r0, [sp, #0x214] + b _02019EE0 +_02019EDA: + ldr r0, [sp, #0x214] + add r0, r0, #0x1 + str r0, [sp, #0x214] +_02019EE0: + ldr r0, [sp, #0x20c] + add r0, r0, #0x4 + str r0, [sp, #0x20c] + ldr r0, [sp, #0x218] + add r0, r0, #0x1 + str r0, [sp, #0x218] + cmp r0, #0x8 + blt _02019E12 + ldr r0, [sp, #0x0] + mov r2, #0x0 + str r0, [sp, #0x1fc] + add r0, #0x40 + str r0, [sp, #0x1fc] + ldr r0, [sp, #0x48] + mov r1, #0x1 + add r0, #0x8 + str r0, [sp, #0x48] + str r0, [sp, #0x204] +_02019F04: + ldr r0, [sp, #0x330] + asr r0, r2 + tst r0, r1 + beq _02019F12 + ldr r0, [sp, #0x204] + add r0, r0, #0x1 + str r0, [sp, #0x204] +_02019F12: + add r2, r2, #0x1 + cmp r2, #0x8 + blt _02019F04 + ldr r0, [sp, #0x330] + asr r0, r0, #0x8 + str r0, [sp, #0x50] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0xe4] + mov r0, #0x0 + str r0, [sp, #0x1c] + ldr r0, [sp, #0x4] + sub r0, #0x8 + cmp r0, #0x0 + ble _0201A008 +_02019F30: + ldr r0, [sp, #0x1fc] + ldr r1, [sp, #0xe4] + ldr r0, [r0, #0x0] + ldr r6, [sp, #0x38] + str r0, [sp, #0x1f8] + ldr r0, [sp, #0x1c] + ldr r2, [sp, #0x5c] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x200] + ldr r0, [sp, #0x204] + mov r1, #0x0 + lsl r5, r0, #0x2 + ldr r0, =0x00003FE0 + add r7, r5, #0x0 + and r0, r5 + mul r6, r0 + mov r0, #0x1c + and r7, r0 + ldr r0, [sp, #0x204] + str r6, [sp, #0xe0] + add r0, r0, #0x1 + lsl r6, r0, #0x2 + ldr r0, =0x00003FE0 + ldr r5, [sp, #0x38] + and r0, r6 + mul r5, r0 + mov r0, #0x1c + and r0, r6 + ldr r3, [sp, #0x34] + add r4, r1, #0x0 + str r5, [sp, #0xdc] + str r0, [sp, #0xd8] +_02019F78: + asr r5, r2, #0x1 + mov r0, #0x3 + and r5, r0 + ldr r0, [sp, #0x278] + add r0, r0, r5 + ldr r5, =0x00003FE0 +// b _02019F8C +// nop +// _02019F88: .word 0x00003FE0 +// _02019F8C: + and r5, r3 + add r5, r0, r5 + ldr r0, [sp, #0xe0] + str r5, [sp, #0x2d8] + add r0, r5, r0 + ldr r5, [sp, #0x1f8] + add r6, r5, #0x0 + lsr r6, r4 + mov r5, #0xf + and r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + beq _02019FD4 + lsl r6, r2, #0x1f + lsr r6, r6, #0x1d + lsl r5, r6 + str r5, [sp, #0x2dc] + ldrb r5, [r0, r7] + str r5, [sp, #0x2e0] + mov r5, #0xf0 + asr r5, r6 + ldr r6, [sp, #0x2e0] + and r6, r5 + ldr r5, [sp, #0x2dc] + orr r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + strb r5, [r0, r7] + ldr r0, [sp, #0x200] + cmp r0, #0x0 + beq _02019FD4 + ldr r6, [sp, #0x2d8] + ldr r0, [sp, #0xdc] + add r6, r6, r0 + ldr r0, [sp, #0xd8] + strb r5, [r0, r6] +_02019FD4: + add r1, r1, #0x1 + add r4, r4, #0x4 + add r3, r3, #0x4 + add r2, r2, #0x1 + cmp r1, #0x8 + blt _02019F78 + ldr r0, [sp, #0x200] + cmp r0, #0x0 + beq _02019FEE + ldr r0, [sp, #0x204] + add r0, r0, #0x2 + str r0, [sp, #0x204] + b _02019FF4 +_02019FEE: + ldr r0, [sp, #0x204] + add r0, r0, #0x1 + str r0, [sp, #0x204] +_02019FF4: + ldr r0, [sp, #0x1fc] + ldr r1, [sp, #0x4] + add r0, r0, #0x4 + str r0, [sp, #0x1fc] + ldr r0, [sp, #0x1c] + sub r1, #0x8 + add r0, r0, #0x1 + str r0, [sp, #0x1c] + cmp r0, r1 + blt _02019F30 +_0201A008: + ldr r0, [sp, #0x0] + mov r2, #0x0 + add r0, #0x60 + str r0, [sp, #0x0] + mov r1, #0x1 +_0201A012: + ldr r0, [sp, #0x330] + asr r0, r2 + tst r0, r1 + beq _0201A020 + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_0201A020: + add r2, r2, #0x1 + cmp r2, #0x8 + blt _0201A012 + ldr r0, [sp, #0x50] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0xf4] + mov r0, #0x0 + str r0, [sp, #0x18] + ldr r0, [sp, #0x4] + sub r0, #0x8 + cmp r0, #0x0 + bgt _0201A03E + bl _0201A8BC +_0201A03E: + ldr r0, [sp, #0x5c] + add r0, #0x8 + str r0, [sp, #0x5c] +_0201A044: + ldr r0, [sp, #0x0] + ldr r1, [sp, #0xf4] + ldr r0, [r0, #0x0] + ldr r2, [sp, #0x5c] + str r0, [sp, #0x1f0] + ldr r0, [sp, #0x18] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x1f4] + ldr r0, [sp, #0x8] + mov r1, #0x0 + str r0, [sp, #0x2e4] + sub r0, #0x8 + str r0, [sp, #0x2e4] + cmp r0, #0x0 + ble _0201A0FE + ble _0201A0FE + add r0, r2, #0x0 + lsl r3, r0, #0x2 + ldr r0, [sp, #0x48] + ldr r6, [sp, #0x38] + lsl r5, r0, #0x2 + ldr r0, =0x00003FE0 + add r7, r5, #0x0 + and r0, r5 + mul r6, r0 + mov r0, #0x1c + and r7, r0 + ldr r0, [sp, #0x48] + str r6, [sp, #0xf0] + add r0, r0, #0x1 + lsl r6, r0, #0x2 + ldr r0, =0x00003FE0 + ldr r5, [sp, #0x38] + and r0, r6 + mul r5, r0 + mov r0, #0x1c + and r0, r6 + add r4, r1, #0x0 + str r5, [sp, #0xec] + str r0, [sp, #0xe8] +_0201A09C: + asr r5, r2, #0x1 + mov r0, #0x3 + and r5, r0 + ldr r0, [sp, #0x278] + add r0, r0, r5 + ldr r5, =0x00003FE0 + and r5, r3 + add r5, r0, r5 + ldr r0, [sp, #0xf0] + str r5, [sp, #0x2e8] + add r0, r5, r0 + ldr r5, [sp, #0x1f0] + add r6, r5, #0x0 + lsr r6, r4 + mov r5, #0xf + and r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + beq _0201A0F0 + lsl r6, r2, #0x1f + lsr r6, r6, #0x1d + lsl r5, r6 + str r5, [sp, #0x2ec] + ldrb r5, [r0, r7] + mov r12, r5 + mov r5, #0xf0 + asr r5, r6 + mov r6, r12 + and r6, r5 + ldr r5, [sp, #0x2ec] + orr r5, r6 + lsl r5, r5, #0x18 + lsr r5, r5, #0x18 + strb r5, [r0, r7] + ldr r0, [sp, #0x1f4] + cmp r0, #0x0 + beq _0201A0F0 + ldr r6, [sp, #0x2e8] + ldr r0, [sp, #0xec] + add r6, r6, r0 + ldr r0, [sp, #0xe8] + strb r5, [r0, r6] +_0201A0F0: + ldr r0, [sp, #0x2e4] + add r1, r1, #0x1 + add r4, r4, #0x4 + add r3, r3, #0x4 + add r2, r2, #0x1 + cmp r1, r0 + blt _0201A09C +_0201A0FE: + ldr r0, [sp, #0x1f4] + cmp r0, #0x0 + beq _0201A10C + ldr r0, [sp, #0x48] + add r0, r0, #0x2 + str r0, [sp, #0x48] + b _0201A112 +_0201A10C: + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_0201A112: + ldr r0, [sp, #0x0] + ldr r1, [sp, #0x4] + add r0, r0, #0x4 + str r0, [sp, #0x0] + ldr r0, [sp, #0x18] + sub r1, #0x8 + add r0, r0, #0x1 + str r0, [sp, #0x18] + cmp r0, r1 + blt _0201A044 + add sp, #0x1fc + add sp, #0x118 + pop {r4-r7, pc} +_0201A12C: // 0x0201A12C + lsl r1, r2, #0x2 + mul r1, r3 + ldr r3, [r5, #0x0] + ldrb r2, [r5, #0x9] + ldr r0, [sp, #0x0] + ldr r3, [r3, #0x0] + lsl r1, r1, #0x3 + bl Convert4bppTo8bpp + str r0, [sp, #0x1ec] + cmp r4, #0x3 + bhi _0201A21E + add r0, r4, r4 + add r0, pc + ldrh r0, [r0, #0x6] + lsl r0, r0, #0x10 + asr r0, r0, #0x10 + add pc, r0 +_0201A150: + + lsl r6, r0, #0 + lsl r6, r1, #3 + lsl r0, r7, #9 + lsl r4, r3, #16 + // jump table (using 16-bit offset) + // .short _0201A158 - _0201A150 - 2; case 0 + // .short _0201A220 - _0201A150 - 2; case 1 + // .short _0201A3CA - _0201A150 - 2; case 2 + // .short _0201A56E - _0201A150 - 2; case 3 +_0201A158: + ldr r0, [sp, #0x330] + ldr r7, [sp, #0x1ec] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x10c] + mov r0, #0x0 + str r0, [sp, #0x1e8] + ldr r0, [sp, #0x4] + cmp r0, #0x0 + ble _0201A21E + ldr r0, [sp, #0x58] + mov r1, #0x7 + and r1, r0 + add r0, r0, r1 + asr r0, r0, #0x3 + str r0, [sp, #0x108] +_0201A178: + ldr r1, [sp, #0x10c] + ldr r0, [sp, #0x1e8] + mov r4, #0x0 + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x310] + ldr r0, [sp, #0x8] + ldr r5, [sp, #0x5c] + cmp r0, #0x0 + ble _0201A1FC + ble _0201A1FC + add r0, r5, #0x0 + lsl r6, r0, #0x3 + ldr r0, [sp, #0x48] + ldr r2, [sp, #0x108] + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + mov r3, #0x38 + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r0, [sp, #0x100] + ldr r0, [sp, #0x48] + str r2, [sp, #0x104] + add r0, r0, #0x1 + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + ldr r2, [sp, #0x108] + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r2, [sp, #0xfc] + str r0, [sp, #0xf8] +_0201A1C4: + mov r0, #0x7 + add r1, r5, #0x0 + and r1, r0 + ldr r0, [sp, #0x278] + add r1, r0, r1 + ldr r0, =0x00007FC0 + and r0, r6 + add r3, r1, r0 + ldr r0, [sp, #0x104] + ldrb r1, [r7, r4] + add r2, r3, r0 + cmp r1, #0x0 + beq _0201A1F0 + ldr r0, [sp, #0x100] + strb r1, [r2, r0] + ldr r0, [sp, #0x310] + cmp r0, #0x0 + beq _0201A1F0 + ldr r0, [sp, #0xfc] + add r2, r3, r0 + ldr r0, [sp, #0xf8] + strb r1, [r0, r2] +_0201A1F0: + ldr r0, [sp, #0x8] + add r4, r4, #0x1 + add r6, #0x8 + add r5, r5, #0x1 + cmp r4, r0 + blt _0201A1C4 +_0201A1FC: + ldr r0, [sp, #0x310] + cmp r0, #0x0 + beq _0201A20A + ldr r0, [sp, #0x48] + add r0, r0, #0x2 + str r0, [sp, #0x48] + b _0201A210 +_0201A20A: + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_0201A210: + ldr r0, [sp, #0x1e8] + add r7, #0x8 + add r1, r0, #0x1 + ldr r0, [sp, #0x4] + str r1, [sp, #0x1e8] + cmp r1, r0 + blt _0201A178 +_0201A21E: + b _0201A8B6 +_0201A220: + ldr r0, [sp, #0x48] + ldr r7, [sp, #0x1ec] + str r0, [sp, #0x1e0] + ldr r0, [sp, #0x330] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x4c] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x124] + mov r0, #0x0 + str r0, [sp, #0x1e4] + ldr r0, [sp, #0x4] + cmp r0, #0x0 + ble _0201A2E6 + ldr r0, [sp, #0x58] + mov r1, #0x7 + and r1, r0 + add r0, r0, r1 + asr r0, r0, #0x3 + str r0, [sp, #0x120] +_0201A24A: + ldr r1, [sp, #0x124] + ldr r0, [sp, #0x1e4] + ldr r5, [sp, #0x5c] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x30c] + add r0, r5, #0x0 + lsl r6, r0, #0x3 + ldr r0, [sp, #0x1e0] + ldr r2, [sp, #0x120] + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + mov r3, #0x38 + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r0, [sp, #0x118] + ldr r0, [sp, #0x1e0] + str r2, [sp, #0x11c] + add r0, r0, #0x1 + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + ldr r2, [sp, #0x120] + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + mov r4, #0x0 + str r2, [sp, #0x114] + str r0, [sp, #0x110] +_0201A28E: + mov r0, #0x7 + add r1, r5, #0x0 + and r1, r0 + ldr r0, [sp, #0x278] + add r1, r0, r1 + ldr r0, =0x00007FC0 + and r0, r6 + add r3, r1, r0 + ldr r0, [sp, #0x11c] + ldrb r1, [r7, r4] + add r2, r3, r0 + cmp r1, #0x0 + beq _0201A2BA + ldr r0, [sp, #0x118] + strb r1, [r2, r0] + ldr r0, [sp, #0x30c] + cmp r0, #0x0 + beq _0201A2BA + ldr r0, [sp, #0x114] + add r2, r3, r0 + ldr r0, [sp, #0x110] + strb r1, [r0, r2] +_0201A2BA: + add r4, r4, #0x1 + add r6, #0x8 + add r5, r5, #0x1 + cmp r4, #0x8 + blt _0201A28E + ldr r0, [sp, #0x30c] + cmp r0, #0x0 + beq _0201A2D2 + ldr r0, [sp, #0x1e0] + add r0, r0, #0x2 + str r0, [sp, #0x1e0] + b _0201A2D8 +_0201A2D2: + ldr r0, [sp, #0x1e0] + add r0, r0, #0x1 + str r0, [sp, #0x1e0] +_0201A2D8: + ldr r0, [sp, #0x1e4] + add r7, #0x8 + add r1, r0, #0x1 + ldr r0, [sp, #0x4] + str r1, [sp, #0x1e4] + cmp r1, r0 + blt _0201A24A +_0201A2E6: + ldr r0, [sp, #0x1ec] + str r0, [sp, #0x308] + add r0, #0x40 + str r0, [sp, #0x308] + ldr r0, [sp, #0x4c] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x13c] + mov r0, #0x0 + str r0, [sp, #0x1dc] + ldr r0, [sp, #0x4] + cmp r0, #0x0 + ble _0201A3C8 + ldr r0, [sp, #0x5c] + mov r1, #0x7 + add r0, #0x8 + str r0, [sp, #0x5c] + ldr r0, [sp, #0x58] + and r1, r0 + add r0, r0, r1 + asr r0, r0, #0x3 + str r0, [sp, #0x138] +_0201A312: + ldr r1, [sp, #0x13c] + ldr r0, [sp, #0x1dc] + ldr r7, [sp, #0x8] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + sub r7, #0x8 + mov r4, #0x0 + str r0, [sp, #0x1d8] + ldr r5, [sp, #0x5c] + cmp r7, #0x0 + ble _0201A398 + ble _0201A398 + add r0, r5, #0x0 + lsl r6, r0, #0x3 + ldr r0, [sp, #0x48] + ldr r2, [sp, #0x138] + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + mov r3, #0x38 + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r0, [sp, #0x130] + ldr r0, [sp, #0x48] + str r2, [sp, #0x134] + add r0, r0, #0x1 + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + ldr r2, [sp, #0x138] + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r2, [sp, #0x12c] + str r0, [sp, #0x128] +_0201A360: + mov r0, #0x7 + add r1, r5, #0x0 + and r1, r0 + ldr r0, [sp, #0x278] + add r1, r0, r1 + ldr r0, =0x00007FC0 + and r0, r6 + add r3, r1, r0 + ldr r0, [sp, #0x134] + add r2, r3, r0 + ldr r0, [sp, #0x308] + ldrb r1, [r0, r4] + cmp r1, #0x0 + beq _0201A38E + ldr r0, [sp, #0x130] + strb r1, [r2, r0] + ldr r0, [sp, #0x1d8] + cmp r0, #0x0 + beq _0201A38E + ldr r0, [sp, #0x12c] + add r2, r3, r0 + ldr r0, [sp, #0x128] + strb r1, [r0, r2] +_0201A38E: + add r4, r4, #0x1 + add r6, #0x8 + add r5, r5, #0x1 + cmp r4, r7 + blt _0201A360 +_0201A398: + ldr r0, [sp, #0x1d8] + cmp r0, #0x0 + beq _0201A3B0 + ldr r0, [sp, #0x48] + add r0, r0, #0x2 + str r0, [sp, #0x48] + b _0201A3B6 +// nop +// _0201A3A8: .word 0x00003FE0 +// _0201A3AC: .word 0x00007FC0 +_0201A3B0: + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_0201A3B6: + ldr r0, [sp, #0x308] + add r0, #0x8 + str r0, [sp, #0x308] + ldr r0, [sp, #0x1dc] + add r1, r0, #0x1 + ldr r0, [sp, #0x4] + str r1, [sp, #0x1dc] + cmp r1, r0 + blt _0201A312 +_0201A3C8: + b _0201A8B6 +_0201A3CA: + ldr r0, [sp, #0x48] + mov r1, #0x7 + str r0, [sp, #0x1d0] + mov r0, #0x0 + str r0, [sp, #0x1d4] + ldr r0, [sp, #0x330] + ldr r7, [sp, #0x1ec] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x150] + ldr r0, [sp, #0x58] + and r1, r0 + add r0, r0, r1 + asr r0, r0, #0x3 + str r0, [sp, #0x30] +_0201A3E8: + ldr r1, [sp, #0x150] + ldr r0, [sp, #0x1d4] + mov r4, #0x0 + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x304] + ldr r0, [sp, #0x8] + ldr r5, [sp, #0x5c] + cmp r0, #0x0 + ble _0201A46C + ble _0201A46C + add r0, r5, #0x0 + lsl r6, r0, #0x3 + ldr r0, [sp, #0x1d0] + ldr r2, [sp, #0x30] + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + mov r3, #0x38 + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r0, [sp, #0x148] + ldr r0, [sp, #0x1d0] + str r2, [sp, #0x14c] + add r0, r0, #0x1 + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + ldr r2, [sp, #0x30] + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r2, [sp, #0x144] + str r0, [sp, #0x140] +_0201A434: + mov r0, #0x7 + add r1, r5, #0x0 + and r1, r0 + ldr r0, [sp, #0x278] + add r1, r0, r1 + ldr r0, =0x00007FC0 + and r0, r6 + add r3, r1, r0 + ldr r0, [sp, #0x14c] + ldrb r1, [r7, r4] + add r2, r3, r0 + cmp r1, #0x0 + beq _0201A460 + ldr r0, [sp, #0x148] + strb r1, [r2, r0] + ldr r0, [sp, #0x304] + cmp r0, #0x0 + beq _0201A460 + ldr r0, [sp, #0x144] + add r2, r3, r0 + ldr r0, [sp, #0x140] + strb r1, [r0, r2] +_0201A460: + ldr r0, [sp, #0x8] + add r4, r4, #0x1 + add r6, #0x8 + add r5, r5, #0x1 + cmp r4, r0 + blt _0201A434 +_0201A46C: + ldr r0, [sp, #0x304] + cmp r0, #0x0 + beq _0201A47A + ldr r0, [sp, #0x1d0] + add r0, r0, #0x2 + str r0, [sp, #0x1d0] + b _0201A480 +_0201A47A: + ldr r0, [sp, #0x1d0] + add r0, r0, #0x1 + str r0, [sp, #0x1d0] +_0201A480: + ldr r0, [sp, #0x1d4] + add r7, #0x8 + add r0, r0, #0x1 + str r0, [sp, #0x1d4] + cmp r0, #0x8 + blt _0201A3E8 + ldr r0, [sp, #0x48] + ldr r7, [sp, #0x1ec] + add r0, #0x8 + str r0, [sp, #0x48] + add r7, #0x80 + mov r0, #0x0 + mov r2, #0x1 +_0201A49A: + ldr r1, [sp, #0x330] + asr r1, r0 + tst r1, r2 + beq _0201A4A8 + ldr r1, [sp, #0x48] + add r1, r1, #0x1 + str r1, [sp, #0x48] +_0201A4A8: + add r0, r0, #0x1 + cmp r0, #0x8 + blt _0201A49A + ldr r0, [sp, #0x330] + asr r0, r0, #0x8 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x164] + mov r0, #0x0 + str r0, [sp, #0x14] + ldr r0, [sp, #0x4] + sub r0, #0x8 + cmp r0, #0x0 + ble _0201A56C +_0201A4C4: + ldr r1, [sp, #0x164] + ldr r0, [sp, #0x14] + mov r4, #0x0 + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x300] + ldr r0, [sp, #0x8] + ldr r5, [sp, #0x5c] + cmp r0, #0x0 + ble _0201A548 + ble _0201A548 + add r0, r5, #0x0 + lsl r6, r0, #0x3 + ldr r0, [sp, #0x48] + ldr r2, [sp, #0x30] + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + mov r3, #0x38 + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r0, [sp, #0x15c] + ldr r0, [sp, #0x48] + str r2, [sp, #0x160] + add r0, r0, #0x1 + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + ldr r2, [sp, #0x30] + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r2, [sp, #0x158] + str r0, [sp, #0x154] +_0201A510: + mov r0, #0x7 + add r1, r5, #0x0 + and r1, r0 + ldr r0, [sp, #0x278] + add r1, r0, r1 + ldr r0, =0x00007FC0 + and r0, r6 + add r3, r1, r0 + ldr r0, [sp, #0x160] + ldrb r1, [r7, r4] + add r2, r3, r0 + cmp r1, #0x0 + beq _0201A53C + ldr r0, [sp, #0x15c] + strb r1, [r2, r0] + ldr r0, [sp, #0x300] + cmp r0, #0x0 + beq _0201A53C + ldr r0, [sp, #0x158] + add r2, r3, r0 + ldr r0, [sp, #0x154] + strb r1, [r0, r2] +_0201A53C: + ldr r0, [sp, #0x8] + add r4, r4, #0x1 + add r6, #0x8 + add r5, r5, #0x1 + cmp r4, r0 + blt _0201A510 +_0201A548: + ldr r0, [sp, #0x300] + cmp r0, #0x0 + beq _0201A556 + ldr r0, [sp, #0x48] + add r0, r0, #0x2 + str r0, [sp, #0x48] + b _0201A55C +_0201A556: + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_0201A55C: + ldr r0, [sp, #0x14] + ldr r1, [sp, #0x4] + add r0, r0, #0x1 + sub r1, #0x8 + add r7, #0x8 + str r0, [sp, #0x14] + cmp r0, r1 + blt _0201A4C4 +_0201A56C: + b _0201A8B6 +_0201A56E: + ldr r0, [sp, #0x48] + ldr r7, [sp, #0x1ec] + str r0, [sp, #0x1c8] + ldr r0, [sp, #0x330] + lsl r0, r0, #0x18 + lsr r1, r0, #0x18 + mov r0, #0x0 + str r0, [sp, #0x1cc] + lsl r0, r1, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x2c] + ldr r0, [sp, #0x58] + mov r1, #0x7 + and r1, r0 + add r0, r0, r1 + asr r0, r0, #0x3 + str r0, [sp, #0x28] +_0201A590: + ldr r1, [sp, #0x2c] + ldr r0, [sp, #0x1cc] + ldr r5, [sp, #0x5c] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x2fc] + add r0, r5, #0x0 + lsl r6, r0, #0x3 + ldr r0, [sp, #0x1c8] + ldr r2, [sp, #0x28] + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + mov r3, #0x38 + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r0, [sp, #0x170] + ldr r0, [sp, #0x1c8] + str r2, [sp, #0x174] + add r0, r0, #0x1 + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + ldr r2, [sp, #0x28] + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + mov r4, #0x0 + str r6, [sp, #0x24] + str r2, [sp, #0x16c] + str r0, [sp, #0x168] +_0201A5D6: + mov r0, #0x7 + add r1, r5, #0x0 + and r1, r0 + ldr r0, [sp, #0x278] + add r1, r0, r1 + ldr r0, =0x00007FC0 + and r0, r6 + add r3, r1, r0 + ldr r0, [sp, #0x174] + ldrb r1, [r7, r4] + add r2, r3, r0 + cmp r1, #0x0 + beq _0201A602 + ldr r0, [sp, #0x170] + strb r1, [r2, r0] + ldr r0, [sp, #0x2fc] + cmp r0, #0x0 + beq _0201A602 + ldr r0, [sp, #0x16c] + add r2, r3, r0 + ldr r0, [sp, #0x168] + strb r1, [r0, r2] +_0201A602: + add r4, r4, #0x1 + add r6, #0x8 + add r5, r5, #0x1 + cmp r4, #0x8 + blt _0201A5D6 + ldr r0, [sp, #0x2fc] + cmp r0, #0x0 + beq _0201A61A + ldr r0, [sp, #0x1c8] + add r0, r0, #0x2 + str r0, [sp, #0x1c8] + b _0201A620 +_0201A61A: + ldr r0, [sp, #0x1c8] + add r0, r0, #0x1 + str r0, [sp, #0x1c8] +_0201A620: + ldr r0, [sp, #0x1cc] + add r7, #0x8 + add r0, r0, #0x1 + str r0, [sp, #0x1cc] + cmp r0, #0x8 + blt _0201A590 + ldr r0, [sp, #0x1ec] + str r0, [sp, #0x2f8] + add r0, #0x40 + str r0, [sp, #0x2f8] + ldr r0, [sp, #0x48] + str r0, [sp, #0x1c0] + mov r0, #0x0 + str r0, [sp, #0x1c4] + ldr r0, [sp, #0x5c] + str r0, [sp, #0x188] + add r0, #0x8 + str r0, [sp, #0x188] +_0201A644: + ldr r1, [sp, #0x2c] + ldr r0, [sp, #0x1c4] + ldr r7, [sp, #0x8] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + sub r7, #0x8 + mov r4, #0x0 + str r0, [sp, #0x1bc] + ldr r5, [sp, #0x188] + cmp r7, #0x0 + ble _0201A6CA + ble _0201A6CA + add r0, r5, #0x0 + lsl r6, r0, #0x3 + ldr r0, [sp, #0x1c0] + ldr r2, [sp, #0x28] + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + mov r3, #0x38 + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r0, [sp, #0x180] + ldr r0, [sp, #0x1c0] + str r2, [sp, #0x184] + add r0, r0, #0x1 + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + ldr r2, [sp, #0x28] + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r2, [sp, #0x17c] + str r0, [sp, #0x178] +_0201A692: + mov r0, #0x7 + add r1, r5, #0x0 + and r1, r0 + ldr r0, [sp, #0x278] + add r1, r0, r1 + ldr r0, =0x00007FC0 + and r0, r6 + add r3, r1, r0 + ldr r0, [sp, #0x184] + add r2, r3, r0 + ldr r0, [sp, #0x2f8] + ldrb r1, [r0, r4] + cmp r1, #0x0 + beq _0201A6C0 + ldr r0, [sp, #0x180] + strb r1, [r2, r0] + ldr r0, [sp, #0x1bc] + cmp r0, #0x0 + beq _0201A6C0 + ldr r0, [sp, #0x17c] + add r2, r3, r0 + ldr r0, [sp, #0x178] + strb r1, [r0, r2] +_0201A6C0: + add r4, r4, #0x1 + add r6, #0x8 + add r5, r5, #0x1 + cmp r4, r7 + blt _0201A692 +_0201A6CA: + ldr r0, [sp, #0x1bc] + cmp r0, #0x0 + beq _0201A6D8 + ldr r0, [sp, #0x1c0] + add r0, r0, #0x2 + str r0, [sp, #0x1c0] + b _0201A6DE +_0201A6D8: + ldr r0, [sp, #0x1c0] + add r0, r0, #0x1 + str r0, [sp, #0x1c0] +_0201A6DE: + ldr r0, [sp, #0x2f8] + add r0, #0x8 + str r0, [sp, #0x2f8] + ldr r0, [sp, #0x1c4] + add r0, r0, #0x1 + str r0, [sp, #0x1c4] + cmp r0, #0x8 + blt _0201A644 + ldr r0, [sp, #0x48] + ldr r7, [sp, #0x1ec] + add r0, #0x8 + add r7, #0x80 + str r0, [sp, #0x48] + str r0, [sp, #0x1b8] + mov r0, #0x0 + mov r2, #0x1 +_0201A6FE: + ldr r1, [sp, #0x330] + asr r1, r0 + tst r1, r2 + beq _0201A70C + ldr r1, [sp, #0x1b8] + add r1, r1, #0x1 + str r1, [sp, #0x1b8] +_0201A70C: + add r0, r0, #0x1 + cmp r0, #0x8 + blt _0201A6FE + ldr r0, [sp, #0x330] + asr r0, r0, #0x8 + str r0, [sp, #0x44] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x19c] + mov r0, #0x0 + str r0, [sp, #0x10] + ldr r0, [sp, #0x4] + sub r0, #0x8 + cmp r0, #0x0 + ble _0201A7CE +_0201A72A: + ldr r1, [sp, #0x19c] + ldr r0, [sp, #0x10] + ldr r2, [sp, #0x28] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x2f4] + ldr r0, [sp, #0x1b8] + mov r3, #0x38 + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 +// b _0201A74C +// nop +// _0201A748: .word 0x00007FC0 +// _0201A74C: + ldr r5, [sp, #0x5c] + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r0, [sp, #0x194] + ldr r0, [sp, #0x1b8] + str r2, [sp, #0x198] + add r0, r0, #0x1 + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + ldr r2, [sp, #0x28] + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + ldr r6, [sp, #0x24] + mov r4, #0x0 + str r2, [sp, #0x190] + str r0, [sp, #0x18c] +_0201A774: + mov r0, #0x7 + add r1, r5, #0x0 + and r1, r0 + ldr r0, [sp, #0x278] + add r1, r0, r1 + ldr r0, =0x00007FC0 + and r0, r6 + add r3, r1, r0 + ldr r0, [sp, #0x198] + ldrb r1, [r7, r4] + add r2, r3, r0 + cmp r1, #0x0 + beq _0201A7A0 + ldr r0, [sp, #0x194] + strb r1, [r2, r0] + ldr r0, [sp, #0x2f4] + cmp r0, #0x0 + beq _0201A7A0 + ldr r0, [sp, #0x190] + add r2, r3, r0 + ldr r0, [sp, #0x18c] + strb r1, [r0, r2] +_0201A7A0: + add r4, r4, #0x1 + add r6, #0x8 + add r5, r5, #0x1 + cmp r4, #0x8 + blt _0201A774 + ldr r0, [sp, #0x2f4] + cmp r0, #0x0 + beq _0201A7B8 + ldr r0, [sp, #0x1b8] + add r0, r0, #0x2 + str r0, [sp, #0x1b8] + b _0201A7BE +_0201A7B8: + ldr r0, [sp, #0x1b8] + add r0, r0, #0x1 + str r0, [sp, #0x1b8] +_0201A7BE: + ldr r0, [sp, #0x10] + ldr r1, [sp, #0x4] + add r0, r0, #0x1 + sub r1, #0x8 + add r7, #0x8 + str r0, [sp, #0x10] + cmp r0, r1 + blt _0201A72A +_0201A7CE: + ldr r0, [sp, #0x1ec] + mov r2, #0x0 + str r0, [sp, #0x2f0] + add r0, #0xc0 + str r0, [sp, #0x2f0] + mov r1, #0x1 +_0201A7DA: + ldr r0, [sp, #0x330] + asr r0, r2 + tst r0, r1 + beq _0201A7E8 + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_0201A7E8: + add r2, r2, #0x1 + cmp r2, #0x8 + blt _0201A7DA + ldr r0, [sp, #0x44] + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + str r0, [sp, #0x1b0] + mov r0, #0x0 + str r0, [sp, #0xc] + ldr r0, [sp, #0x4] + sub r0, #0x8 + cmp r0, #0x0 + ble _0201A8B6 + ldr r0, [sp, #0x5c] + add r0, #0x8 + str r0, [sp, #0x5c] +_0201A808: + ldr r1, [sp, #0x1b0] + ldr r0, [sp, #0xc] + ldr r7, [sp, #0x8] + asr r1, r0 + mov r0, #0x1 + and r0, r1 + lsl r0, r0, #0x18 + lsr r0, r0, #0x18 + sub r7, #0x8 + mov r4, #0x0 + str r0, [sp, #0x1b4] + ldr r5, [sp, #0x5c] + cmp r7, #0x0 + ble _0201A88E + ble _0201A88E + add r0, r5, #0x0 + lsl r6, r0, #0x3 + ldr r0, [sp, #0x48] + ldr r2, [sp, #0x28] + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + mov r3, #0x38 + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r0, [sp, #0x1a8] + ldr r0, [sp, #0x48] + str r2, [sp, #0x1ac] + add r0, r0, #0x1 + lsl r1, r0, #0x3 + ldr r0, =0x00007FC0 + ldr r2, [sp, #0x28] + and r0, r1 + mul r2, r0 + add r0, r1, #0x0 + and r0, r3 + str r2, [sp, #0x1a4] + str r0, [sp, #0x1a0] +_0201A856: + mov r0, #0x7 + add r1, r5, #0x0 + and r1, r0 + ldr r0, [sp, #0x278] + add r1, r0, r1 + ldr r0, =0x00007FC0 + and r0, r6 + add r3, r1, r0 + ldr r0, [sp, #0x1ac] + add r2, r3, r0 + ldr r0, [sp, #0x2f0] + ldrb r1, [r0, r4] + cmp r1, #0x0 + beq _0201A884 + ldr r0, [sp, #0x1a8] + strb r1, [r2, r0] + ldr r0, [sp, #0x1b4] + cmp r0, #0x0 + beq _0201A884 + ldr r0, [sp, #0x1a4] + add r2, r3, r0 + ldr r0, [sp, #0x1a0] + strb r1, [r0, r2] +_0201A884: + add r4, r4, #0x1 + add r6, #0x8 + add r5, r5, #0x1 + cmp r4, r7 + blt _0201A856 +_0201A88E: + ldr r0, [sp, #0x1b4] + cmp r0, #0x0 + beq _0201A89C + ldr r0, [sp, #0x48] + add r0, r0, #0x2 + str r0, [sp, #0x48] + b _0201A8A2 +_0201A89C: + ldr r0, [sp, #0x48] + add r0, r0, #0x1 + str r0, [sp, #0x48] +_0201A8A2: + ldr r0, [sp, #0x2f0] + ldr r1, [sp, #0x4] + add r0, #0x8 + str r0, [sp, #0x2f0] + ldr r0, [sp, #0xc] + sub r1, #0x8 + add r0, r0, #0x1 + str r0, [sp, #0xc] + cmp r0, r1 + blt _0201A808 +_0201A8B6: + ldr r0, [sp, #0x1ec] + bl FreeToHeap +_0201A8BC: // 0x0201A8BC + add sp, #0x1fc + add sp, #0x118 + pop {r4-r7, pc} + // clang-format on +} +#endif + +THUMB_FUNC void ScrollWindow(struct Window *window, u32 param1, u8 param2, u8 param3) +{ + if (window->bgConfig->bgs[window->bgId].colorMode == GX_BG_COLORMODE_16) + { + ScrollWindow4bpp(window, param1, param2, param3); + } + else + { + ScrollWindow8bpp(window, param1, param2, param3); + } +} + +THUMB_FUNC void ScrollWindow4bpp(struct Window *window, u32 param1, u8 param2, u8 fillValue) +{ + void *r2; + int r5, r1, r3; + int st4, stc; + u32 st8; + int i, j; + + r2 = window->pixelBuffer; + st4 = (fillValue << 0x18) | (fillValue << 0x10) | (fillValue << 0x8) | fillValue; + stc = window->height * window->width * 32; + st8 = window->width; + + switch (param1) + { + case 0: + for (i = 0; i < stc; i += 32) + { + r3 = param2; + for (j = 0; j < 8; j++) + { + r5 = i + (j << 2); + r1 = i + (int)(((st8 * (r3 & ~7)) | (r3 & 7)) << 2); + + if (r1 < stc) + { + *(u32 *)(r2 + r5) = *(u32 *)(r2 + r1); + } + else + { + *(u32 *)(r2 + r5) = (u32)st4; + } + + r3++; + } + } + + break; + case 1: + r2 += stc - 4; + for (i = 0; i < stc; i += 32) + { + r3 = param2; + for (j = 0; j < 8; j++) + { + r5 = i + (j << 2); + r1 = i + (int)(((st8 * (r3 & ~7)) | (r3 & 7)) << 2); + + if (r1 < stc) + { + *(u32 *)(r2 - r5) = *(u32 *)(r2 - r1); + } + else + { + *(u32 *)(r2 - r5) = (u32)st4; + } + + r3++; + } + } + + break; + case 2: + case 3: + break; + } +} + +THUMB_FUNC void ScrollWindow8bpp(struct Window *window, u32 param1, u8 param2, u8 fillValue) +{ + + void *pixelBuffer; + int dstOffs, srcOffs, r3; + int st4, size; + u32 srcWidth; + int i, j; + + pixelBuffer = (u8 *)window->pixelBuffer; + st4 = (fillValue << 0x18) | (fillValue << 0x10) | (fillValue << 0x8) | fillValue; + size = window->height * window->width * 64; + srcWidth = window->width; + + switch (param1) + { + case 0: + for (i = 0; i < size; i += 64) + { + r3 = param2; + for (j = 0; j < 8; j++) + { + dstOffs = i + (j << 3); + srcOffs = i + (int)(((srcWidth * (r3 & ~7)) | (r3 & 7)) << 3); + + if (srcOffs < size) + { + *(u32 *)(pixelBuffer + dstOffs) = *(u32 *)(pixelBuffer + srcOffs); + } + else + { + *(u32 *)(pixelBuffer + dstOffs) = (u32)st4; + } + + dstOffs += 4; + srcOffs += 4; + if (srcOffs < size + 4) + { + *(u32 *)(pixelBuffer + dstOffs) = *(u32 *)(pixelBuffer + srcOffs); + } + else + { + *(u32 *)(pixelBuffer + dstOffs) = (u32)st4; + } + + r3++; + } + } + + break; + case 1: + pixelBuffer += size - 8; + for (i = 0; i < size; i += 64) + { + r3 = param2; + for (j = 0; j < 8; j++) + { + dstOffs = i + (j << 3); + srcOffs = i + (int)(((srcWidth * (r3 & ~7)) | (r3 & 7)) << 3); + + if (srcOffs < size) + { + *(u32 *)(pixelBuffer - dstOffs) = *(u32 *)(pixelBuffer - srcOffs); + } + else + { + *(u32 *)(pixelBuffer - dstOffs) = (u32)st4; + } + + dstOffs -= 4; + srcOffs -= 4; + if (srcOffs < size - 4) + { + *(u32 *)(pixelBuffer - dstOffs) = *(u32 *)(pixelBuffer - srcOffs); + } + else + { + *(u32 *)(pixelBuffer - dstOffs) = (u32)st4; + } + + r3++; + } + } + + break; + case 2: + case 3: + break; + } +} + +THUMB_FUNC u8 GetWindowBgId(struct Window *window) +{ + return window->bgId; +} + +THUMB_FUNC u8 GetWindowWidth(struct Window *window) +{ + return window->width; +} +THUMB_FUNC u8 GetWindowHeight(struct Window *window) +{ + return window->height; +} +THUMB_FUNC u8 GetWindowX(struct Window *window) +{ + return window->tilemapLeft; +} +THUMB_FUNC u8 GetWindowY(struct Window *window) +{ + return window->tilemapTop; +} +THUMB_FUNC void MoveWindowX(struct Window *window, u8 x) +{ + window->tilemapLeft = x; +} +THUMB_FUNC void MoveWindowY(struct Window *window, u8 y) +{ + window->tilemapTop = y; +} +THUMB_FUNC void SetWindowPaletteNum(struct Window *window, u8 paletteNum) +{ + window->paletteNum = paletteNum; +} + +THUMB_FUNC NNSG2dCharacterData * LoadCharacterDataFromFile(void **char_ret, u32 heap_id, const char *path) +{ + void *ptr = AllocAndReadFile(heap_id, path); + *char_ret = ptr; + NNSG2dCharacterData *st0; + NNS_G2dGetUnpackedBGCharacterData(ptr, &st0); + + return st0; +} + +THUMB_FUNC NNSG2dPaletteData * LoadPaletteDataFromFile(void **pltt_ret, u32 heap_id, const char *path) +{ + void *ptr = AllocAndReadFile(heap_id, path); + *pltt_ret = ptr; + NNSG2dPaletteData *st0; + NNS_G2dGetUnpackedPaletteData(ptr, &st0); + + return st0; +} + +THUMB_FUNC void DoScheduledBgGpuUpdates(struct BgConfig *bgConfig) +{ + ApplyScheduledBgPosUpdate(bgConfig); + DoScheduledBgTilemapBufferTransfers(bgConfig); + + bgConfig->scrollScheduled = 0; + bgConfig->bufferTransferScheduled = 0; +} + +THUMB_FUNC void DoScheduledBgTilemapBufferTransfers(struct BgConfig *bgConfig) +{ + if ((bgConfig->bufferTransferScheduled & (1 << GF_BG_LYR_MAIN_0)) != 0) + { + LoadBgVramScr(GF_BG_LYR_MAIN_0, bgConfig->bgs[GF_BG_LYR_MAIN_0].tilemapBuffer, bgConfig->bgs[GF_BG_LYR_MAIN_0].baseTile * 2, bgConfig->bgs[GF_BG_LYR_MAIN_0].bufferSize); + } + + if ((bgConfig->bufferTransferScheduled & (1 << GF_BG_LYR_MAIN_1)) != 0) + { + LoadBgVramScr(GF_BG_LYR_MAIN_1, bgConfig->bgs[GF_BG_LYR_MAIN_1].tilemapBuffer, bgConfig->bgs[GF_BG_LYR_MAIN_1].baseTile * 2, bgConfig->bgs[GF_BG_LYR_MAIN_1].bufferSize); + } + + if ((bgConfig->bufferTransferScheduled & (1 << GF_BG_LYR_MAIN_2)) != 0) + { + LoadBgVramScr(GF_BG_LYR_MAIN_2, bgConfig->bgs[GF_BG_LYR_MAIN_2].tilemapBuffer, bgConfig->bgs[GF_BG_LYR_MAIN_2].baseTile * 2, bgConfig->bgs[GF_BG_LYR_MAIN_2].bufferSize); + } + + if ((bgConfig->bufferTransferScheduled & (1 << GF_BG_LYR_MAIN_3)) != 0) + { + LoadBgVramScr(GF_BG_LYR_MAIN_3, bgConfig->bgs[GF_BG_LYR_MAIN_3].tilemapBuffer, bgConfig->bgs[GF_BG_LYR_MAIN_3].baseTile * 2, bgConfig->bgs[GF_BG_LYR_MAIN_3].bufferSize); + } + + if ((bgConfig->bufferTransferScheduled & (1 << GF_BG_LYR_SUB_0)) != 0) + { + LoadBgVramScr(GF_BG_LYR_SUB_0, bgConfig->bgs[GF_BG_LYR_SUB_0].tilemapBuffer, bgConfig->bgs[GF_BG_LYR_SUB_0].baseTile * 2, bgConfig->bgs[GF_BG_LYR_SUB_0].bufferSize); + } + + if ((bgConfig->bufferTransferScheduled & (1 << GF_BG_LYR_SUB_1)) != 0) + { + LoadBgVramScr(GF_BG_LYR_SUB_1, bgConfig->bgs[GF_BG_LYR_SUB_1].tilemapBuffer, bgConfig->bgs[GF_BG_LYR_SUB_1].baseTile * 2, bgConfig->bgs[GF_BG_LYR_SUB_1].bufferSize); + } + + if ((bgConfig->bufferTransferScheduled & (1 << GF_BG_LYR_SUB_2)) != 0) + { + LoadBgVramScr(GF_BG_LYR_SUB_2, bgConfig->bgs[GF_BG_LYR_SUB_2].tilemapBuffer, bgConfig->bgs[GF_BG_LYR_SUB_2].baseTile * 2, bgConfig->bgs[GF_BG_LYR_SUB_2].bufferSize); + } + + if ((bgConfig->bufferTransferScheduled & (1 << GF_BG_LYR_SUB_3)) != 0) + { + LoadBgVramScr(GF_BG_LYR_SUB_3, bgConfig->bgs[GF_BG_LYR_SUB_3].tilemapBuffer, bgConfig->bgs[GF_BG_LYR_SUB_3].baseTile * 2, bgConfig->bgs[GF_BG_LYR_SUB_3].bufferSize); + } +} + +THUMB_FUNC void ScheduleBgTilemapBufferTransfer(struct BgConfig *bgConfig, u32 bgId) +{ + bgConfig->bufferTransferScheduled |= 1 << bgId; +} + +THUMB_FUNC void ApplyScheduledBgPosUpdate(struct BgConfig *bgConfig) +{ + if ((bgConfig->scrollScheduled & (1 << GF_BG_LYR_MAIN_0)) != 0) + { + G2_SetBG0Offset(bgConfig->bgs[GF_BG_LYR_MAIN_0].hOffset, bgConfig->bgs[GF_BG_LYR_MAIN_0].vOffset); + } + + if ((bgConfig->scrollScheduled & (1 << GF_BG_LYR_MAIN_1)) != 0) + { + G2_SetBG1Offset(bgConfig->bgs[GF_BG_LYR_MAIN_1].hOffset, bgConfig->bgs[GF_BG_LYR_MAIN_1].vOffset); + } + + if ((bgConfig->scrollScheduled & (1 << GF_BG_LYR_MAIN_2)) != 0) + { + if (bgConfig->bgs[GF_BG_LYR_MAIN_2].mode == 0) + { + G2_SetBG2Offset(bgConfig->bgs[GF_BG_LYR_MAIN_2].hOffset, bgConfig->bgs[GF_BG_LYR_MAIN_2].vOffset); + } + else + { + struct Mtx22 st38; + MTX22_2DAffine( + &st38, bgConfig->bgs[GF_BG_LYR_MAIN_2].rotation, bgConfig->bgs[GF_BG_LYR_MAIN_2].xScale, bgConfig->bgs[GF_BG_LYR_MAIN_2].yScale, 2); + G2_SetBG2Affine( + &st38, + bgConfig->bgs[GF_BG_LYR_MAIN_2].centerX, + bgConfig->bgs[GF_BG_LYR_MAIN_2].centerY, + bgConfig->bgs[GF_BG_LYR_MAIN_2].hOffset, + bgConfig->bgs[GF_BG_LYR_MAIN_2].vOffset); + } + } + + if ((bgConfig->scrollScheduled & (1 << GF_BG_LYR_MAIN_3)) != 0) + { + if (bgConfig->bgs[GF_BG_LYR_MAIN_3].mode == 0) + { + G2_SetBG3Offset(bgConfig->bgs[GF_BG_LYR_MAIN_3].hOffset, bgConfig->bgs[GF_BG_LYR_MAIN_3].vOffset); + } + else + { + struct Mtx22 st28; + MTX22_2DAffine( + &st28, bgConfig->bgs[GF_BG_LYR_MAIN_3].rotation, bgConfig->bgs[GF_BG_LYR_MAIN_3].xScale, bgConfig->bgs[GF_BG_LYR_MAIN_3].yScale, 2); + G2_SetBG3Affine( + &st28, + bgConfig->bgs[GF_BG_LYR_MAIN_3].centerX, + bgConfig->bgs[GF_BG_LYR_MAIN_3].centerY, + bgConfig->bgs[GF_BG_LYR_MAIN_3].hOffset, + bgConfig->bgs[GF_BG_LYR_MAIN_3].vOffset); + } + } + + if ((bgConfig->scrollScheduled & (1 << GF_BG_LYR_SUB_0)) != 0) + { + G2S_SetBG0Offset(bgConfig->bgs[GF_BG_LYR_SUB_0].hOffset, bgConfig->bgs[GF_BG_LYR_SUB_0].vOffset); + } + + if ((bgConfig->scrollScheduled & (1 << GF_BG_LYR_SUB_1)) != 0) + { + G2S_SetBG1Offset(bgConfig->bgs[GF_BG_LYR_SUB_1].hOffset, bgConfig->bgs[GF_BG_LYR_SUB_1].vOffset); + } + + if ((bgConfig->scrollScheduled & (1 << GF_BG_LYR_SUB_2)) != 0) + { + if (bgConfig->bgs[GF_BG_LYR_SUB_2].mode == 0) + { + G2S_SetBG2Offset(bgConfig->bgs[GF_BG_LYR_SUB_2].hOffset, bgConfig->bgs[GF_BG_LYR_SUB_2].vOffset); + } + else + { + struct Mtx22 st18; + MTX22_2DAffine( + &st18, bgConfig->bgs[GF_BG_LYR_SUB_2].rotation, bgConfig->bgs[GF_BG_LYR_SUB_2].xScale, bgConfig->bgs[GF_BG_LYR_SUB_2].yScale, 2); + G2S_SetBG2Affine( + &st18, + bgConfig->bgs[GF_BG_LYR_SUB_2].centerX, + bgConfig->bgs[GF_BG_LYR_SUB_2].centerY, + bgConfig->bgs[GF_BG_LYR_SUB_2].hOffset, + bgConfig->bgs[GF_BG_LYR_SUB_2].vOffset); + } + } + + if ((bgConfig->scrollScheduled & (1 << GF_BG_LYR_SUB_3)) != 0) + { + if (bgConfig->bgs[GF_BG_LYR_SUB_3].mode == 0) + { + G2S_SetBG3Offset(bgConfig->bgs[GF_BG_LYR_SUB_3].hOffset, bgConfig->bgs[GF_BG_LYR_SUB_3].vOffset); + } + else + { + struct Mtx22 st08; + MTX22_2DAffine( + &st08, bgConfig->bgs[GF_BG_LYR_SUB_3].rotation, bgConfig->bgs[GF_BG_LYR_SUB_3].xScale, bgConfig->bgs[GF_BG_LYR_SUB_3].yScale, 2); + G2S_SetBG3Affine( + &st08, + bgConfig->bgs[GF_BG_LYR_SUB_3].centerX, + bgConfig->bgs[GF_BG_LYR_SUB_3].centerY, + bgConfig->bgs[GF_BG_LYR_SUB_3].hOffset, + bgConfig->bgs[GF_BG_LYR_SUB_3].vOffset); + } + } +} + +THUMB_FUNC void ScheduleSetBgPosText( + struct BgConfig *bgConfig, u32 bgId, u32 op, fx32 value) +{ + Bg_SetPosText(&bgConfig->bgs[bgId], op, value); + bgConfig->scrollScheduled |= 1 << bgId; +} + +THUMB_FUNC void ScheduleSetBgAffineRotation( + struct BgConfig *bgConfig, u32 bgId, u32 op, u16 value) +{ + Bg_SetAffineRotation(&bgConfig->bgs[bgId], op, value); + bgConfig->scrollScheduled |= 1 << bgId; +} + +THUMB_FUNC void Bg_SetAffineRotation(struct Bg *bg, u32 op, u16 val) +{ + switch (op) + { + case BG_POS_OP_SET_ROT: + bg->rotation = val; + break; + case BG_POS_OP_ADD_ROT: + bg->rotation += val; + break; + case BG_POS_OP_SUB_ROT: + bg->rotation -= val; + break; + } +} + +THUMB_FUNC void ScheduleSetBgAffinePos( + struct BgConfig *bgConfig, u32 bgId, u32 op, fx32 value) +{ + Bg_SetAffinePos(&bgConfig->bgs[bgId], op, value); + bgConfig->scrollScheduled |= 1 << bgId; +} + +THUMB_FUNC void Bg_SetAffinePos(struct Bg *bg, u32 op, fx32 val) +{ + switch (op) + { + case BG_POS_OP_SET_CENTERX: + bg->centerX = val; + break; + case BG_POS_OP_ADD_CENTERX: + bg->centerX += val; + break; + case BG_POS_OP_SUB_CENTERX: + bg->centerX -= val; + break; + case BG_POS_OP_SET_CENTERY: + bg->centerY = val; + break; + case BG_POS_OP_ADD_CENTERY: + bg->centerY += val; + break; + case BG_POS_OP_SUB_CENTERY: + bg->centerY -= val; + break; + } +} + +THUMB_FUNC u32 DoesPixelAtScreenXYMatchPtrVal( + struct BgConfig *bgConfig, u8 bgId, u8 x, u8 y, u16 *src) +{ + void *bgCharPtr; + u16 tilemapIdx; + u8 xPixOffs; + u8 yPixOffs; + u8 pixelValue; + u8 i; + + if (bgConfig->bgs[bgId].tilemapBuffer == NULL) + { + return 0; + } + + tilemapIdx = GetTileMapIndexFromCoords((u8) (x >> 3), (u8) (y >> 3), bgConfig->bgs[bgId].size); + bgCharPtr = BgGetCharPtr(bgId); + + xPixOffs = (u8)(x & 7); + yPixOffs = (u8)(y & 7); + + if (bgConfig->bgs[bgId].colorMode == GX_BG_COLORMODE_16) + { + u16 *tilemapBuffer = bgConfig->bgs[bgId].tilemapBuffer; + u8 *ptr = AllocFromHeapAtEnd(bgConfig->heap_id, 0x40); + + bgCharPtr += ((tilemapBuffer[tilemapIdx] & 0x3ff) << 5); + for (i = 0; i < 0x20; i++) + { + ptr[(i << 1)] = (u8)(((u8 *)bgCharPtr)[i] & 0xf); + ptr[(i << 1) + 1] = (u8)(((u8 *)bgCharPtr)[i] >> 4); + } + + ApplyFlipFlagsToTile(bgConfig, (u8)((tilemapBuffer[tilemapIdx] >> 0xa) & 3), ptr); + + pixelValue = ptr[xPixOffs + (yPixOffs << 3)]; + FreeToHeap(ptr); + + if ((src[0] & (1 << pixelValue)) != 0) + { + return 1; + } + } + else + { + if (bgConfig->bgs[bgId].mode != GF_BG_TYPE_AFFINE) + { + u16 *tilemapBuffer = bgConfig->bgs[bgId].tilemapBuffer; + u8 *ptr = AllocFromHeapAtEnd(bgConfig->heap_id, 0x40); + + memcpy(ptr, bgCharPtr + ((tilemapBuffer[tilemapIdx] & 0x3ff) << 6), 0x40); + + ApplyFlipFlagsToTile(bgConfig, (u8)((tilemapBuffer[tilemapIdx] >> 0xa) & 3), ptr); + + pixelValue = ptr[xPixOffs + (yPixOffs << 3)]; + FreeToHeap(ptr); + } + else + { + pixelValue = ((u8 *)bgCharPtr)[(((u8 *)bgConfig->bgs[bgId].tilemapBuffer)[tilemapIdx] << 6) + xPixOffs + (yPixOffs << 3)]; + } + + // BUG: Infinite loop + while (TRUE) + { + if (src[0] == 0xffff) + { + break; + } + if (pixelValue == (u8)(src[0])) + { + return 1; + } + } + } + return 0; +} + +THUMB_FUNC void ApplyFlipFlagsToTile(struct BgConfig *bgConfig, u8 flag, u8 *src) +{ + u8 i, j; + if (flag != 0) + { + u8 *ptr = AllocFromHeapAtEnd(bgConfig->heap_id, 0x40); + + if ((flag & 1) != 0) + { + for (i = 0; i < 8; i++) + { + for (j = 0; j < 8; j++) + { + ptr[i * 8 + j] = src[i * 8 + (7 - j)]; + } + } + + memcpy(src, ptr, 0x40); + } + + if ((flag & 2) != 0) + { + for (i = 0; i < 8; i++) + { + u8 *r3 = &ptr[i * 8]; + u8 *r2 = &src[(7 - i) * 8]; + for (u32 j = 8; j > 0; j--) + { + *r3++ = *r2++; + } + } + + memcpy(src, ptr, 0x40); + } + + FreeToHeap(ptr); + } +} |