diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bg.c | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/src/bg.c b/src/bg.c new file mode 100644 index 000000000..4130e4bab --- /dev/null +++ b/src/bg.c @@ -0,0 +1,533 @@ +#include "global.h" +#include "dma3.h" + +#define DISPCNT_ALL_BG_AND_MODE_BITS 0x0F07 +#define SECONDARY_TILESET_BASE_TILE 0x4000 +#define SECONDARY_TILESET_BASE_BLOCK 0x800 + +struct BgControl { + struct BgConfig { + u16 visible:1; + u16 unknown_1:1; + u16 screenSize:2; + u16 priority:2; + u16 mosaic:1; + u16 wraparound:1; + + u16 tilesBaseBlock:2; + u16 tileMapBaseBlock:5; + u16 paletteMode:1; + + u8 unknown_2; + u8 unknown_3; + } configs[4]; + + u16 bgVisibilityAndMode; +}; + +struct BgTemplate { + u32 bg:2; + u32 tilesBaseBlock:2; + u32 tileMapBaseBlock:5; + u32 screenSize:2; + u32 paletteMode:1; + u32 priority:2; + u32 unk_1:10; +}; + +struct BgConfig2 { + u32 unk_1:10; + u32 unk_2:4; + u32 unk_3:18; + + u32 unk_4; + u32 unk_5; + u32 unk_6; +}; + +extern struct BgControl gUnknown_030008E0; // gGpuBgConfigs +extern struct BgConfig2 gUnknown_030008F8[4]; // gGpuBgConfigs2 +extern u32 gUnknown_03000938[4]; +extern u32 gUnneededFireRedVariable; +extern struct BgConfig gZeroedBgControlStruct; +extern bool32 IsInvalidBgDuplicate(u8 bg); + +void ResetBgControlStructs(); + +extern void SetTextModeAndHideBgs(); +extern bool8 IsInvalidBg(u8 bg); +extern void SetGpuReg(u8 regOffset, u16 value); +extern u16 GetGpuReg(u8 regOffset); + +void ResetBgs(void) +{ + ResetBgControlStructs(); + gUnknown_030008E0.bgVisibilityAndMode = 0; + SetTextModeAndHideBgs(); +} + +void SetBgModeInternal(u8 bgMode) +{ + gUnknown_030008E0.bgVisibilityAndMode &= 0xFFF8; + gUnknown_030008E0.bgVisibilityAndMode |= bgMode; +} + +u8 GetBgMode(void) +{ + return gUnknown_030008E0.bgVisibilityAndMode & 0x7; +} + +void ResetBgControlStructs(void) +{ + struct BgConfig* bgConfigs = &gUnknown_030008E0.configs[0]; + struct BgConfig zeroedConfig = gZeroedBgControlStruct; + int i; + + for (i = 0; i < 4; i++) + { + bgConfigs[i] = zeroedConfig; + } +} + +void Unused_ResetBgControlStruct(u8 bg) +{ + if (IsInvalidBg(bg) == FALSE) + { + gUnknown_030008E0.configs[bg] = gZeroedBgControlStruct; + } +} + +void SetBgControlAttributes(u8 bg, u8 tilesBaseBlock, u8 tileMapBaseBlock, u8 screenSize, u8 paletteMode, u8 priority, u8 mosaic, u8 wraparound) +{ + if (IsInvalidBg(bg) == FALSE) + { + if (tilesBaseBlock != 0xFF) + { + gUnknown_030008E0.configs[bg].tilesBaseBlock = tilesBaseBlock & 0x3; + } + + if (tileMapBaseBlock != 0xFF) + { + gUnknown_030008E0.configs[bg].tileMapBaseBlock = tileMapBaseBlock & 0x1F; + } + + if (screenSize != 0xFF) + { + gUnknown_030008E0.configs[bg].screenSize = screenSize & 0x3; + } + + if (paletteMode != 0xFF) + { + gUnknown_030008E0.configs[bg].paletteMode = paletteMode; + } + + if (priority != 0xFF) + { + gUnknown_030008E0.configs[bg].priority = priority & 0x3; + } + + if (mosaic != 0xFF) + { + gUnknown_030008E0.configs[bg].mosaic = mosaic & 0x1; + } + + if (wraparound != 0xFF) + { + gUnknown_030008E0.configs[bg].wraparound = wraparound; + } + + gUnknown_030008E0.configs[bg].unknown_2 = 0; + gUnknown_030008E0.configs[bg].unknown_3 = 0; + + gUnknown_030008E0.configs[bg].visible = 1; + } +} + +u16 GetBgControlAttribute(u8 bg, u8 attributeId) +{ + if (IsInvalidBg(bg) == FALSE && gUnknown_030008E0.configs[bg].visible != FALSE) + { + switch (attributeId) + { + case 1: + return gUnknown_030008E0.configs[bg].visible; + case 2: + return gUnknown_030008E0.configs[bg].tilesBaseBlock; + case 3: + return gUnknown_030008E0.configs[bg].tileMapBaseBlock; + case 4: + return gUnknown_030008E0.configs[bg].screenSize; + case 5: + return gUnknown_030008E0.configs[bg].paletteMode; + case 6: + return gUnknown_030008E0.configs[bg].priority; + case 7: + return gUnknown_030008E0.configs[bg].mosaic; + case 8: + return gUnknown_030008E0.configs[bg].wraparound; + } + } + + return 0xFF; +} + +u8 LoadBgVram(u8 bg, void *src, u16 size, u16 destOffset, u8 mode) +{ + u16 offset; + s8 cursor; + + if (IsInvalidBg(bg) == FALSE && gUnknown_030008E0.configs[bg].visible != FALSE) + { + switch (mode) + { + case 0x1: + offset = gUnknown_030008E0.configs[bg].tilesBaseBlock * SECONDARY_TILESET_BASE_TILE; + break; + case 0x2: + offset = gUnknown_030008E0.configs[bg].tileMapBaseBlock * SECONDARY_TILESET_BASE_BLOCK; + break; + default: + cursor = -1; + goto end; + } + + offset = destOffset + offset; + + cursor = RequestDma3Copy(src, (void*)(offset + BG_VRAM), size, 0); + + if (cursor == -1) + { + return -1; + } + } + else + { + return -1; + } + +end: + return cursor; +} + +void ShowBgInternal(u8 bg) +{ + u16 value; + if (IsInvalidBg(bg) == FALSE && gUnknown_030008E0.configs[bg].visible != FALSE) + { + value = gUnknown_030008E0.configs[bg].priority | + (gUnknown_030008E0.configs[bg].tilesBaseBlock << 2) | + (gUnknown_030008E0.configs[bg].mosaic << 6) | + (gUnknown_030008E0.configs[bg].paletteMode << 7) | + (gUnknown_030008E0.configs[bg].tileMapBaseBlock << 8) | + (gUnknown_030008E0.configs[bg].wraparound << 13) | + (gUnknown_030008E0.configs[bg].screenSize << 14); + + SetGpuReg((bg << 1) + 0x8, value); + + gUnknown_030008E0.bgVisibilityAndMode |= 1 << (bg + 8); + gUnknown_030008E0.bgVisibilityAndMode &= DISPCNT_ALL_BG_AND_MODE_BITS; + } +} + +void HideBgInternal(u8 bg) +{ + if (IsInvalidBg(bg) == FALSE) + { + gUnknown_030008E0.bgVisibilityAndMode &= ~(1 << (bg + 8)); + gUnknown_030008E0.bgVisibilityAndMode &= DISPCNT_ALL_BG_AND_MODE_BITS; + } +} + +void SyncBgVisibilityAndMode() +{ + SetGpuReg(0, (GetGpuReg(0) & ~DISPCNT_ALL_BG_AND_MODE_BITS) | gUnknown_030008E0.bgVisibilityAndMode); +} + +void SetTextModeAndHideBgs() +{ + SetGpuReg(0, GetGpuReg(0) & ~DISPCNT_ALL_BG_AND_MODE_BITS); +} + +void SetBgAffineInternal(u8 bg, u32 srcCenterX, u32 srcCenterY, u16 dispCenterX, u16 dispCenterY, u16 scaleX, u16 scaleY, u16 rotationAngle) +{ + struct BgAffineSrcData src; + struct BgAffineDstData dest; + + switch (gUnknown_030008E0.bgVisibilityAndMode & 0x7) + { + case 1: + if (bg != 2) + return; + break; + case 2: + if (bg < 2 || bg > 3) + return; + break; + case 0: + default: + return; + } + + src.texX = srcCenterX; + src.texY = srcCenterY; + src.scrX = dispCenterX; + src.scrY = dispCenterY; + src.sx = scaleX; + src.sy = scaleY; + src.alpha = rotationAngle; + + BgAffineSet(&src, &dest, 1); + + SetGpuReg(REG_OFFSET_BG2PA, dest.pa); + SetGpuReg(REG_OFFSET_BG2PB, dest.pb); + SetGpuReg(REG_OFFSET_BG2PC, dest.pc); + SetGpuReg(REG_OFFSET_BG2PD, dest.pd); + SetGpuReg(REG_OFFSET_BG2PA, dest.pa); + SetGpuReg(REG_OFFSET_BG2X_L, (s16)(dest.dx)); + SetGpuReg(REG_OFFSET_BG2X_H, (s16)(dest.dx >> 16)); + SetGpuReg(REG_OFFSET_BG2Y_L, (s16)(dest.dy)); + SetGpuReg(REG_OFFSET_BG2Y_H, (s16)(dest.dy >> 16)); +} + +bool8 IsInvalidBg(u8 bg) +{ + if (bg > 3) + return TRUE; + return FALSE; +} + +int DummiedOutFireRedLeafGreenTileAllocFunc(int a1, int a2, int a3, int a4) +{ + return 0; +} + +void ResetBgsAndClearDma3BusyFlags(u32 leftoverFireRedLeafGreenVariable) +{ + int i; + ResetBgs(); + + for (i = 0; i < 4; i++) + { + gUnknown_03000938[i] = 0; + } + + gUnneededFireRedVariable = leftoverFireRedLeafGreenVariable; +} + +void InitBgsFromTemplates(u8 bgMode, struct BgTemplate *templates, u8 numTemplates) +{ + int i; + u8 bg; + + SetBgModeInternal(bgMode); + ResetBgControlStructs(); + + for (i = 0; i < numTemplates; i++) + { + bg = templates[i].bg; + if (bg < 4) { + SetBgControlAttributes(bg, + templates[i].tilesBaseBlock, + templates[i].tileMapBaseBlock, + templates[i].screenSize, + templates[i].paletteMode, + templates[i].priority, + 0, + 0); + + gUnknown_030008F8[bg].unk_1 = templates[i].unk_1; + gUnknown_030008F8[bg].unk_2 = 0; + gUnknown_030008F8[bg].unk_3 = 0; + + gUnknown_030008F8[bg].unk_4 = 0; + gUnknown_030008F8[bg].unk_5 = 0; + gUnknown_030008F8[bg].unk_6 = 0; + } + } +} + +void InitBgFromTemplate(struct BgTemplate *template) +{ + u8 bg = template->bg; + + if (bg < 4) + { + SetBgControlAttributes(bg, + template->tilesBaseBlock, + template->tileMapBaseBlock, + template->screenSize, + template->paletteMode, + template->priority, + 0, + 0); + + gUnknown_030008F8[bg].unk_1 = template->unk_1; + gUnknown_030008F8[bg].unk_2 = 0; + gUnknown_030008F8[bg].unk_3 = 0; + + gUnknown_030008F8[bg].unk_4 = 0; + gUnknown_030008F8[bg].unk_5 = 0; + gUnknown_030008F8[bg].unk_6 = 0; + } +} + +void SetBgMode(u8 bgMode) +{ + SetBgModeInternal(bgMode); +} + +u16 LoadBgTiles(u8 bg, void *src, u16 size, u16 destOffset) +{ + u16 unk; + u8 cursor; + + if (GetBgControlAttribute(bg, 5) == 0) + { + unk = (gUnknown_030008F8[bg].unk_1 + destOffset) * 0x20; + } + else + { + unk = (gUnknown_030008F8[bg].unk_1 + destOffset) * 0x40; + } + + cursor = LoadBgVram(bg, src, size, unk, DISPCNT_MODE_1); + + if (cursor == 0xFF) + { + return -1; + } + + gUnknown_03000938[cursor >> 5] |= (1 << (cursor & 0x1F)); + + if (gUnneededFireRedVariable == 1) + { + DummiedOutFireRedLeafGreenTileAllocFunc(bg, unk >> 5, size >> 5, 1); + } + + return cursor; +} + +u16 LoadBgTilemap(u8 bg, void *src, u16 size, u16 destOffset) +{ + u8 cursor; + + cursor = LoadBgVram(bg, src, size, destOffset * 2, DISPCNT_MODE_2); + + if (cursor == 0xFF) + { + return -1; + } + + gUnknown_03000938[cursor >> 5] |= (1 << (cursor & 0x1F)); + + return cursor; +} + +#ifdef NONMATCHING +u16 Unused_LoadBgPalette(u8 bg, void *src, u16 size, u16 destOffset) +{ + u16 unk_1; + s8 cursor; + int cursor2; + u32* ptr; + + if (IsInvalidBgDuplicate(bg) == FALSE) + { + unk_1 = (gUnknown_030008F8[bg].unk_2 * 0x20) + (destOffset * 2); + cursor = RequestDma3Copy(src, (void*)(unk_1 + BG_PLTT), size, 0); + cursor2 = cursor; + } + else + { + return -1; + } + + if (cursor == -1) + { + return -1; + } + + ptr = gUnknown_03000938; + + if (cursor < 0) + { + cursor2 += 0x1F; + } + + cursor2 >>= 5; + + ptr[cursor2] |= (1 << (s8)(cursor - (cursor2 << 5))); + + return (u8)cursor; +} +#else +__attribute__((naked)) +u8 Unused_LoadBgPalette(u8 bg, void *src, u16 size, u16 destOffset) +{ + asm("push {r4-r7,lr}\n\ + add r7, r1, #0\n\ + lsl r0, #24\n\ + lsr r4, r0, #24\n\ + lsl r2, #16\n\ + lsr r6, r2, #16\n\ + lsl r3, #16\n\ + lsr r5, r3, #16\n\ + add r0, r4, #0\n\ + bl IsInvalidBgDuplicate\n\ + cmp r0, #0\n\ + bne _08001A98\n\ + ldr r1, =gUnknown_030008F8\n\ + lsl r0, r4, #4\n\ + add r0, r1\n\ + ldrb r1, [r0, #0x1]\n\ + lsl r1, #26\n\ + lsr r1, #28\n\ + lsl r1, #5\n\ + lsl r0, r5, #1\n\ + add r1, r0\n\ + lsl r1, #16\n\ + lsr r1, #16\n\ + mov r0, #0xA0\n\ + lsl r0, #19\n\ + add r1, r0\n\ + add r0, r7, #0\n\ + add r2, r6, #0\n\ + mov r3, #0\n\ + bl RequestDma3Copy\n\ + lsl r3, r0, #24\n\ + asr r1, r3, #24\n\ + mov r0, #0x1\n\ + neg r0, r0\n\ + cmp r1, r0\n\ + bne _08001AA4\n\ +_08001A98:\n\ + ldr r0, =0x0000ffff\n\ + b _08001AC8\n\ + .pool\n\ +_08001AA4:\n\ + ldr r4, =gUnknown_03000938\n\ + add r0, r1, #0\n\ + cmp r1, #0\n\ + bge _08001AAE\n\ + add r0, #0x1F\n\ +_08001AAE:\n\ + asr r0, #5\n\ + lsl r2, r0, #2\n\ + add r2, r4\n\ + lsl r0, #5\n\ + sub r0, r1, r0\n\ + lsl r0, #24\n\ + asr r0, #24\n\ + mov r1, #0x1\n\ + lsl r1, r0\n\ + ldr r0, [r2]\n\ + orr r0, r1\n\ + str r0, [r2]\n\ + lsr r0, r3, #24\n\ +_08001AC8:\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .pool"); +} +#endif // NONMATCHING |