pokeemmo/src/bg.c
2017-09-06 23:53:13 -05:00

1590 lines
36 KiB
C

#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;
void* tilemap;
u32 bg_x;
u32 bg_y;
};
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();
u16 GetBgMetricTextMode(u8 bg, u8 whichMetric);
u16 GetBgMetricAffineMode(u8 bg, u8 whichMetric);
u32 GetBgType(u8 bg);
void SetTextModeAndHideBgs();
bool8 IsInvalidBg(u8 bg);
bool32 IsTileMapOutsideWram(u8 bg);
extern void SetGpuReg(u8 regOffset, u16 value);
extern void SetGpuReg_ForcedBlank(u8 regOffset, u16 value);
extern u16 GetGpuReg(u8 regOffset);
extern int CheckForSpaceForDma3Request(s16 index);
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, s16 dispCenterX, s16 dispCenterY, s16 scaleX, s16 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].tilemap = NULL;
gUnknown_030008F8[bg].bg_x = 0;
gUnknown_030008F8[bg].bg_y = 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].tilemap = NULL;
gUnknown_030008F8[bg].bg_x = 0;
gUnknown_030008F8[bg].bg_y = 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 / 0x20] |= (1 << (cursor % 0x20));
if (gUnneededFireRedVariable == 1)
{
DummiedOutFireRedLeafGreenTileAllocFunc(bg, unk / 0x20, size / 0x20, 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 / 0x20] |= (1 << (cursor % 0x20));
return cursor;
}
u16 Unused_LoadBgPalette(u8 bg, void *src, u16 size, u16 destOffset)
{
u16 unk_1;
s8 cursor;
if (IsInvalidBgDuplicate(bg) == FALSE)
{
unk_1 = (gUnknown_030008F8[bg].unk_2 * 0x20) + (destOffset * 2);
cursor = RequestDma3Copy(src, (void*)(unk_1 + BG_PLTT), size, 0);
if (cursor == -1)
{
return -1;
}
}
else
{
return -1;
}
gUnknown_03000938[cursor / 0x20] |= (1 << (cursor % 0x20));
return (u8)cursor;
}
#ifdef NONMATCHING // Matches everything but r5 and r6 are flipped, rrr
bool8 IsDma3ManagerBusyWithBgCopy(void)
{
u8 mod;
u8 div;
s8 reqSpace;
int i;
for (i = 0; i < 0x80; i++)
{
div = i / 0x20;
mod = i % 0x20;
if ((gUnknown_03000938[div] & (1 << mod)) != FALSE)
{
reqSpace = CheckForSpaceForDma3Request(i);
if (reqSpace == -1)
{
return TRUE;
}
gUnknown_03000938[div] &= ~(1 << mod);
}
}
return FALSE;
}
#else
__attribute__((naked))
bool8 IsDma3ManagerBusyWithBgCopy(void)
{
asm("push {r4-r7,lr}\n\
mov r5, #0\n\
mov r7, #0x1\n\
neg r7, r7\n\
_08001ADC:\n\
add r0, r5, #0\n\
cmp r5, #0\n\
bge _08001AE4\n\
add r0, #0x1F\n\
_08001AE4:\n\
asr r0, #5\n\
lsl r2, r0, #24\n\
lsl r0, #5\n\
sub r0, r5, r0\n\
lsl r0, #24\n\
lsr r0, #24\n\
ldr r1, =gUnknown_03000938\n\
lsr r2, #22\n\
add r4, r2, r1\n\
mov r6, #0x1\n\
lsl r6, r0\n\
ldr r0, [r4]\n\
and r0, r6\n\
cmp r0, #0\n\
beq _08001B22\n\
lsl r0, r5, #16\n\
asr r0, #16\n\
bl CheckForSpaceForDma3Request\n\
lsl r0, #24\n\
asr r0, #24\n\
cmp r0, r7\n\
bne _08001B1C\n\
mov r0, #0x1\n\
b _08001B2A\n\
.pool\n\
_08001B1C:\n\
ldr r0, [r4]\n\
bic r0, r6\n\
str r0, [r4]\n\
_08001B22:\n\
add r5, #0x1\n\
cmp r5, #0x7F\n\
ble _08001ADC\n\
mov r0, #0\n\
_08001B2A:\n\
pop {r4-r7}\n\
pop {r1}\n\
bx r1\n");
}
#endif // NONMATCHING
void ShowBg(u8 bg)
{
ShowBgInternal(bg);
SyncBgVisibilityAndMode();
}
void HideBg(u8 bg)
{
HideBgInternal(bg);
SyncBgVisibilityAndMode();
}
void SetBgAttribute(u8 bg, u8 attributeId, u8 value)
{
switch (attributeId)
{
case 1:
SetBgControlAttributes(bg, value, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
break;
case 2:
SetBgControlAttributes(bg, 0xFF, value, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
break;
case 3:
SetBgControlAttributes(bg, 0xFF, 0xFF, value, 0xFF, 0xFF, 0xFF, 0xFF);
break;
case 4:
SetBgControlAttributes(bg, 0xFF, 0xFF, 0xFF, value, 0xFF, 0xFF, 0xFF);
break;
case 7:
SetBgControlAttributes(bg, 0xFF, 0xFF, 0xFF, 0xFF, value, 0xFF, 0xFF);
break;
case 5:
SetBgControlAttributes(bg, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, value, 0xFF);
break;
case 6:
SetBgControlAttributes(bg, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, value);
break;
}
}
u16 GetBgAttribute(u8 bg, u8 attributeId)
{
switch (attributeId)
{
case 1:
return GetBgControlAttribute(bg, 2);
case 2:
return GetBgControlAttribute(bg, 3);
case 3:
return GetBgControlAttribute(bg, 4);
case 4:
return GetBgControlAttribute(bg, 5);
case 7:
return GetBgControlAttribute(bg, 6);
case 5:
return GetBgControlAttribute(bg, 7);
case 6:
return GetBgControlAttribute(bg, 8);
case 8:
switch (GetBgType(bg))
{
case 0:
return GetBgMetricTextMode(bg, 0) * 0x800;
case 1:
return GetBgMetricAffineMode(bg, 0) * 0x100;
default:
return 0;
}
case 9:
return GetBgType(bg);
case 10:
return gUnknown_030008F8[bg].unk_1;
default:
return -1;
}
}
#ifdef NONMATCHING // Everything that uses temp1 doesn't match
u32 ChangeBgX(u8 bg, u32 value, u8 op)
{
u8 mode;
u32 temp1;
if (IsInvalidBgDuplicate(bg) != FALSE || GetBgControlAttribute(bg, 1) == 0)
{
return -1;
}
switch (op)
{
case 0:
default:
gUnknown_030008F8[bg].bg_x = value;
break;
case 1:
gUnknown_030008F8[bg].bg_x += value;
break;
case 2:
gUnknown_030008F8[bg].bg_x -= value;
break;
}
mode = GetBgMode();
switch (bg)
{
case 0:
SetGpuReg(REG_OFFSET_BG0HOFS, gUnknown_030008F8[0].bg_x >> 0x8);
break;
case 1:
SetGpuReg(REG_OFFSET_BG1HOFS, gUnknown_030008F8[1].bg_x >> 0x8);
break;
case 2:
if (mode == 0)
{
SetGpuReg(REG_OFFSET_BG2HOFS, gUnknown_030008F8[2].bg_x >> 0x8);
}
else
{
temp1 = gUnknown_030008F8[2].bg_x;
SetGpuReg(REG_OFFSET_BG2X_H, (u16)(temp1 >> 0x10));
SetGpuReg(REG_OFFSET_BG2X_L, (u16)(temp1));
}
break;
case 3:
if (mode == 0)
{
SetGpuReg(REG_OFFSET_BG3HOFS, gUnknown_030008F8[3].bg_x >> 0x8);
}
else if (mode == 2)
{
temp1 = gUnknown_030008F8[3].bg_x;
SetGpuReg(REG_OFFSET_BG2X_H, (u16)(temp1 >> 0x10));
SetGpuReg(REG_OFFSET_BG2X_L, (u16)(temp1));
}
break;
}
return gUnknown_030008F8[bg].bg_x;
}
#else
__attribute__((naked))
u32 ChangeBgX(u8 bg, u32 value, u8 op)
{
asm("push {r4-r6,lr}\n\
add r6, r1, #0\n\
lsl r0, #24\n\
lsr r4, r0, #24\n\
lsl r2, #24\n\
lsr r5, r2, #24\n\
add r0, r4, #0\n\
bl IsInvalidBgDuplicate\n\
cmp r0, #0\n\
bne _08001D28\n\
add r0, r4, #0\n\
mov r1, #0x1\n\
bl GetBgControlAttribute\n\
lsl r0, #16\n\
cmp r0, #0\n\
bne _08001D2E\n\
_08001D28:\n\
mov r0, #0x1\n\
neg r0, r0\n\
b _08001E34\n\
_08001D2E:\n\
cmp r5, #0x1\n\
beq _08001D4C\n\
cmp r5, #0x1\n\
ble _08001D3A\n\
cmp r5, #0x2\n\
beq _08001D60\n\
_08001D3A:\n\
ldr r0, =gUnknown_030008F8\n\
lsl r1, r4, #4\n\
add r0, #0x8\n\
add r0, r1, r0\n\
str r6, [r0]\n\
add r5, r1, #0\n\
b _08001D70\n\
.pool\n\
_08001D4C:\n\
ldr r0, =gUnknown_030008F8\n\
lsl r2, r4, #4\n\
add r0, #0x8\n\
add r0, r2, r0\n\
ldr r1, [r0]\n\
add r1, r6\n\
b _08001D6C\n\
.pool\n\
_08001D60:\n\
ldr r0, =gUnknown_030008F8\n\
lsl r2, r4, #4\n\
add r0, #0x8\n\
add r0, r2, r0\n\
ldr r1, [r0]\n\
sub r1, r6\n\
_08001D6C:\n\
str r1, [r0]\n\
add r5, r2, #0\n\
_08001D70:\n\
bl GetBgMode\n\
lsl r0, #24\n\
lsr r0, #24\n\
cmp r4, #0x1\n\
beq _08001DAC\n\
cmp r4, #0x1\n\
bgt _08001D8C\n\
cmp r4, #0\n\
beq _08001D96\n\
b _08001E2C\n\
.pool\n\
_08001D8C:\n\
cmp r4, #0x2\n\
beq _08001DC0\n\
cmp r4, #0x3\n\
beq _08001DF8\n\
b _08001E2C\n\
_08001D96:\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x8]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x10\n\
bl SetGpuReg\n\
b _08001E2C\n\
.pool\n\
_08001DAC:\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x18]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x14\n\
bl SetGpuReg\n\
b _08001E2C\n\
.pool\n\
_08001DC0:\n\
cmp r0, #0\n\
bne _08001DD8\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x28]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x18\n\
bl SetGpuReg\n\
b _08001E2C\n\
.pool\n\
_08001DD8:\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x28]\n\
lsr r1, r0, #16\n\
lsl r0, #16\n\
lsr r4, r0, #16\n\
mov r0, #0x2A\n\
bl SetGpuReg\n\
mov r0, #0x28\n\
add r1, r4, #0\n\
bl SetGpuReg\n\
b _08001E2C\n\
.pool\n\
_08001DF8:\n\
cmp r0, #0\n\
bne _08001E10\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x38]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x1C\n\
bl SetGpuReg\n\
b _08001E2C\n\
.pool\n\
_08001E10:\n\
cmp r0, #0x2\n\
bne _08001E2C\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x38]\n\
lsr r1, r0, #16\n\
lsl r0, #16\n\
lsr r4, r0, #16\n\
mov r0, #0x3A\n\
bl SetGpuReg\n\
mov r0, #0x38\n\
add r1, r4, #0\n\
bl SetGpuReg\n\
_08001E2C:\n\
ldr r0, =gUnknown_030008F8\n\
add r0, #0x8\n\
add r0, r5, r0\n\
ldr r0, [r0]\n\
_08001E34:\n\
pop {r4-r6}\n\
pop {r1}\n\
bx r1\n\
.pool\n");
}
#endif // NONMATCHING
#ifdef NONMATCHING // Probably the stupidest nonmatching ever
u32 GetBgX(u8 bg)
{
if (IsInvalidBgDuplicate(bg) == FALSE && GetBgControlAttribute(bg, 0x1) != 0)
{
return gUnknown_030008F8[bg].bg_x;
}
else
{
return -1;
}
}
#else
__attribute__((naked))
u32 GetBgX(u8 bg)
{
asm("push {r4,lr}\n\
lsl r0, #24\n\
lsr r0, #24\n\
add r4, r0, #0\n\
bl IsInvalidBgDuplicate\n\
cmp r0, #0\n\
bne _08001E70\n\
add r0, r4, #0\n\
mov r1, #0x1\n\
bl GetBgControlAttribute\n\
lsl r0, #16\n\
cmp r0, #0\n\
beq _08001E70\n\
ldr r0, =gUnknown_030008F8\n\
lsl r1, r4, #4\n\
add r0, #0x8\n\
add r1, r0\n\
ldr r0, [r1]\n\
b _08001E74\n\
.pool\n\
_08001E70:\n\
mov r0, #0x1\n\
neg r0, r0\n\
_08001E74:\n\
pop {r4}\n\
pop {r1}\n\
bx r1\n");
}
#endif // NONMATCHING
#ifdef NONMATCHING // Everything that uses temp1 doesn't match
u32 ChangeBgY(u8 bg, u32 value, u8 op)
{
u8 mode;
u32 temp1;
if (IsInvalidBgDuplicate(bg) != FALSE || GetBgControlAttribute(bg, 1) == 0)
{
return -1;
}
switch (op)
{
case 0:
default:
gUnknown_030008F8[bg].bg_y = value;
break;
case 1:
gUnknown_030008F8[bg].bg_y += value;
break;
case 2:
gUnknown_030008F8[bg].bg_y -= value;
break;
}
mode = GetBgMode();
switch (bg)
{
case 0:
SetGpuReg(REG_OFFSET_BG0VOFS, gUnknown_030008F8[0].bg_y >> 0x8);
break;
case 1:
SetGpuReg(REG_OFFSET_BG1VOFS, gUnknown_030008F8[1].bg_y >> 0x8);
break;
case 2:
if (mode == 0)
{
SetGpuReg(REG_OFFSET_BG2VOFS, gUnknown_030008F8[2].bg_y >> 0x8);
}
else
{
temp1 = gUnknown_030008F8[2].bg_y;
SetGpuReg(REG_OFFSET_BG2Y_H, (u16)(temp1 >> 0x10));
SetGpuReg(REG_OFFSET_BG2Y_L, (u16)(temp1));
}
break;
case 3:
if (mode == 0)
{
SetGpuReg(REG_OFFSET_BG3VOFS, gUnknown_030008F8[3].bg_y >> 0x8);
}
else if (mode == 2)
{
temp1 = gUnknown_030008F8[3].bg_y;
SetGpuReg(REG_OFFSET_BG3Y_H, (u16)(temp1 >> 0x10));
SetGpuReg(REG_OFFSET_BG3Y_L, (u16)(temp1));
}
break;
}
return gUnknown_030008F8[bg].bg_y;
}
#else
__attribute__((naked))
u32 ChangeBgY(u8 bg, u32 value, u8 op)
{
asm("push {r4-r6,lr}\n\
add r6, r1, #0\n\
lsl r0, #24\n\
lsr r4, r0, #24\n\
lsl r2, #24\n\
lsr r5, r2, #24\n\
add r0, r4, #0\n\
bl IsInvalidBgDuplicate\n\
cmp r0, #0\n\
bne _08001EA0\n\
add r0, r4, #0\n\
mov r1, #0x1\n\
bl GetBgControlAttribute\n\
lsl r0, #16\n\
cmp r0, #0\n\
bne _08001EA6\n\
_08001EA0:\n\
mov r0, #0x1\n\
neg r0, r0\n\
b _08001FAC\n\
_08001EA6:\n\
cmp r5, #0x1\n\
beq _08001EC4\n\
cmp r5, #0x1\n\
ble _08001EB2\n\
cmp r5, #0x2\n\
beq _08001ED8\n\
_08001EB2:\n\
ldr r0, =gUnknown_030008F8\n\
lsl r1, r4, #4\n\
add r0, #0xC\n\
add r0, r1, r0\n\
str r6, [r0]\n\
add r5, r1, #0\n\
b _08001EE8\n\
.pool\n\
_08001EC4:\n\
ldr r0, =gUnknown_030008F8\n\
lsl r2, r4, #4\n\
add r0, #0xC\n\
add r0, r2, r0\n\
ldr r1, [r0]\n\
add r1, r6\n\
b _08001EE4\n\
.pool\n\
_08001ED8:\n\
ldr r0, =gUnknown_030008F8\n\
lsl r2, r4, #4\n\
add r0, #0xC\n\
add r0, r2, r0\n\
ldr r1, [r0]\n\
sub r1, r6\n\
_08001EE4:\n\
str r1, [r0]\n\
add r5, r2, #0\n\
_08001EE8:\n\
bl GetBgMode\n\
lsl r0, #24\n\
lsr r0, #24\n\
cmp r4, #0x1\n\
beq _08001F24\n\
cmp r4, #0x1\n\
bgt _08001F04\n\
cmp r4, #0\n\
beq _08001F0E\n\
b _08001FA4\n\
.pool\n\
_08001F04:\n\
cmp r4, #0x2\n\
beq _08001F38\n\
cmp r4, #0x3\n\
beq _08001F70\n\
b _08001FA4\n\
_08001F0E:\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0xC]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x12\n\
bl SetGpuReg\n\
b _08001FA4\n\
.pool\n\
_08001F24:\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x1C]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x16\n\
bl SetGpuReg\n\
b _08001FA4\n\
.pool\n\
_08001F38:\n\
cmp r0, #0\n\
bne _08001F50\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x2C]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x1A\n\
bl SetGpuReg\n\
b _08001FA4\n\
.pool\n\
_08001F50:\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x2C]\n\
lsr r1, r0, #16\n\
lsl r0, #16\n\
lsr r4, r0, #16\n\
mov r0, #0x2E\n\
bl SetGpuReg\n\
mov r0, #0x2C\n\
add r1, r4, #0\n\
bl SetGpuReg\n\
b _08001FA4\n\
.pool\n\
_08001F70:\n\
cmp r0, #0\n\
bne _08001F88\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x3C]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x1E\n\
bl SetGpuReg\n\
b _08001FA4\n\
.pool\n\
_08001F88:\n\
cmp r0, #0x2\n\
bne _08001FA4\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x3C]\n\
lsr r1, r0, #16\n\
lsl r0, #16\n\
lsr r4, r0, #16\n\
mov r0, #0x3E\n\
bl SetGpuReg\n\
mov r0, #0x3C\n\
add r1, r4, #0\n\
bl SetGpuReg\n\
_08001FA4:\n\
ldr r0, =gUnknown_030008F8\n\
add r0, #0xC\n\
add r0, r5, r0\n\
ldr r0, [r0]\n\
_08001FAC:\n\
pop {r4-r6}\n\
pop {r1}\n\
bx r1\n\
.pool\n");
}
#endif // NONMATCHING
#ifdef NONMATCHING // Same issue as ChangeBgX and ChangeBgY
u32 ChangeBgY_ScreenOff(u8 bg, u32 value, u8 op)
{
u8 mode;
u16 temp1;
if (IsInvalidBgDuplicate(bg) != FALSE || GetBgControlAttribute(bg, 1) == 0)
{
return -1;
}
switch (op)
{
case 0:
default:
gUnknown_030008F8[bg].bg_y = value;
break;
case 1:
gUnknown_030008F8[bg].bg_y += value;
break;
case 2:
gUnknown_030008F8[bg].bg_y -= value;
break;
}
mode = GetBgMode();
switch (bg)
{
case 0:
SetGpuReg_ForcedBlank(REG_OFFSET_BG0VOFS, gUnknown_030008F8[0].bg_y >> 0x8);
break;
case 1:
SetGpuReg_ForcedBlank(REG_OFFSET_BG1VOFS, gUnknown_030008F8[1].bg_y >> 0x8);
break;
case 2:
if (mode == 0)
{
SetGpuReg_ForcedBlank(REG_OFFSET_BG2VOFS, gUnknown_030008F8[2].bg_y >> 0x8);
}
else
{
temp1 = gUnknown_030008F8[2].bg_y;
SetGpuReg_ForcedBlank(REG_OFFSET_BG2Y_H, (gUnknown_030008F8[2].bg_y >> 0x10));
SetGpuReg_ForcedBlank(REG_OFFSET_BG2Y_L, (temp1));
}
break;
case 3:
if (mode == 0)
{
SetGpuReg_ForcedBlank(REG_OFFSET_BG3VOFS, gUnknown_030008F8[3].bg_y >> 0x8);
}
else if (mode == 2)
{
temp1 = gUnknown_030008F8[3].bg_y;
SetGpuReg_ForcedBlank(REG_OFFSET_BG3Y_H, (gUnknown_030008F8[3].bg_y >> 0x10));
SetGpuReg_ForcedBlank(REG_OFFSET_BG3Y_L, (temp1));
}
break;
}
return gUnknown_030008F8[bg].bg_y;
}
#else
__attribute__((naked))
u32 ChangeBgY_ScreenOff(u8 bg, u32 value, u8 op)
{
asm("push {r4-r6,lr}\n\
add r6, r1, #0\n\
lsl r0, #24\n\
lsr r4, r0, #24\n\
lsl r2, #24\n\
lsr r5, r2, #24\n\
add r0, r4, #0\n\
bl IsInvalidBgDuplicate\n\
cmp r0, #0\n\
bne _08001FDC\n\
add r0, r4, #0\n\
mov r1, #0x1\n\
bl GetBgControlAttribute\n\
lsl r0, #16\n\
cmp r0, #0\n\
bne _08001FE2\n\
_08001FDC:\n\
mov r0, #0x1\n\
neg r0, r0\n\
b _080020E8\n\
_08001FE2:\n\
cmp r5, #0x1\n\
beq _08002000\n\
cmp r5, #0x1\n\
ble _08001FEE\n\
cmp r5, #0x2\n\
beq _08002014\n\
_08001FEE:\n\
ldr r0, =gUnknown_030008F8\n\
lsl r1, r4, #4\n\
add r0, #0xC\n\
add r0, r1, r0\n\
str r6, [r0]\n\
add r5, r1, #0\n\
b _08002024\n\
.pool\n\
_08002000:\n\
ldr r0, =gUnknown_030008F8\n\
lsl r2, r4, #4\n\
add r0, #0xC\n\
add r0, r2, r0\n\
ldr r1, [r0]\n\
add r1, r6\n\
b _08002020\n\
.pool\n\
_08002014:\n\
ldr r0, =gUnknown_030008F8\n\
lsl r2, r4, #4\n\
add r0, #0xC\n\
add r0, r2, r0\n\
ldr r1, [r0]\n\
sub r1, r6\n\
_08002020:\n\
str r1, [r0]\n\
add r5, r2, #0\n\
_08002024:\n\
bl GetBgMode\n\
lsl r0, #24\n\
lsr r0, #24\n\
cmp r4, #0x1\n\
beq _08002060\n\
cmp r4, #0x1\n\
bgt _08002040\n\
cmp r4, #0\n\
beq _0800204A\n\
b _080020E0\n\
.pool\n\
_08002040:\n\
cmp r4, #0x2\n\
beq _08002074\n\
cmp r4, #0x3\n\
beq _080020AC\n\
b _080020E0\n\
_0800204A:\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0xC]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x12\n\
bl SetGpuReg_ForcedBlank\n\
b _080020E0\n\
.pool\n\
_08002060:\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x1C]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x16\n\
bl SetGpuReg_ForcedBlank\n\
b _080020E0\n\
.pool\n\
_08002074:\n\
cmp r0, #0\n\
bne _0800208C\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x2C]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x1A\n\
bl SetGpuReg_ForcedBlank\n\
b _080020E0\n\
.pool\n\
_0800208C:\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x2C]\n\
lsr r1, r0, #16\n\
lsl r0, #16\n\
lsr r4, r0, #16\n\
mov r0, #0x2E\n\
bl SetGpuReg_ForcedBlank\n\
mov r0, #0x2C\n\
add r1, r4, #0\n\
bl SetGpuReg_ForcedBlank\n\
b _080020E0\n\
.pool\n\
_080020AC:\n\
cmp r0, #0\n\
bne _080020C4\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x3C]\n\
lsl r0, #8\n\
lsr r1, r0, #16\n\
mov r0, #0x1E\n\
bl SetGpuReg_ForcedBlank\n\
b _080020E0\n\
.pool\n\
_080020C4:\n\
cmp r0, #0x2\n\
bne _080020E0\n\
ldr r0, =gUnknown_030008F8\n\
ldr r0, [r0, #0x3C]\n\
lsr r1, r0, #16\n\
lsl r0, #16\n\
lsr r4, r0, #16\n\
mov r0, #0x3E\n\
bl SetGpuReg_ForcedBlank\n\
mov r0, #0x3C\n\
add r1, r4, #0\n\
bl SetGpuReg_ForcedBlank\n\
_080020E0:\n\
ldr r0, =gUnknown_030008F8\n\
add r0, #0xC\n\
add r0, r5, r0\n\
ldr r0, [r0]\n\
_080020E8:\n\
pop {r4-r6}\n\
pop {r1}\n\
bx r1\n\
.pool\n");
}
#endif // NONMATCHING
#ifdef NONMATCHING // Probably the stupidest nonmatching ever, electric boogaloo
u32 GetBgY(u8 bg)
{
if (IsInvalidBgDuplicate(bg) != FALSE || GetBgControlAttribute(bg, 0x1) == 0)
{
return gUnknown_030008F8[bg].bg_y;
}
else
{
return -1;
}
}
#else
__attribute__((naked))
u32 GetBgY(u8 bg)
{
asm("push {r4,lr}\n\
lsl r0, #24\n\
lsr r0, #24\n\
add r4, r0, #0\n\
bl IsInvalidBgDuplicate\n\
cmp r0, #0\n\
bne _08002124\n\
add r0, r4, #0\n\
mov r1, #0x1\n\
bl GetBgControlAttribute\n\
lsl r0, #16\n\
cmp r0, #0\n\
beq _08002124\n\
ldr r0, =gUnknown_030008F8\n\
lsl r1, r4, #4\n\
add r0, #0xC\n\
add r1, r0\n\
ldr r0, [r1]\n\
b _08002128\n\
.pool\n\
_08002124:\n\
mov r0, #0x1\n\
neg r0, r0\n\
_08002128:\n\
pop {r4}\n\
pop {r1}\n\
bx r1\n");
}
#endif // NONMATCHING
void SetBgAffine(u8 bg, u32 srcCenterX, u32 srcCenterY, s16 dispCenterX, s16 dispCenterY, s16 scaleX, s16 scaleY, u16 rotationAngle)
{
SetBgAffineInternal(bg, srcCenterX, srcCenterY, dispCenterX, dispCenterY, scaleX, scaleY, rotationAngle);
}
u8 Unused_AdjustBgMosaic(u8 a1, u8 a2)
{
u16 result;
s16 test1;
s16 test2;
result = GetGpuReg(REG_OFFSET_MOSAIC);
test1 = result & 0xF;
test2 = (result >> 4) & 0xF;
result &= 0xFF00;
switch (a2)
{
case 0:
default:
test1 = a1 & 0xF;
test2 = a1 >> 0x4;
break;
case 1:
test1 = a1 & 0xF;
break;
case 2:
if ((test1 + a1) > 0xF)
{
test1 = 0xF;
}
else
{
test1 += a1;
}
break;
case 3:
if ((test1 - a1) < 0)
{
test1 = 0x0;
}
else
{
test1 -= a1;
}
break;
case 4:
test2 = a1 & 0xF;
break;
case 5:
if ((test2 + a1) > 0xF)
{
test2 = 0xF;
}
else
{
test2 += a1;
}
break;
case 6:
if ((test2 - a1) < 0)
{
test2 = 0x0;
}
else
{
test2 -= a1;
}
break;
}
result |= ((test2 << 0x4) & 0xF0);
result |= (test1 & 0xF);
SetGpuReg(REG_OFFSET_MOSAIC, result);
return result;
}
void SetBgTilemapBuffer(u8 bg, void *tilemap)
{
if (IsInvalidBgDuplicate(bg) == FALSE && GetBgControlAttribute(bg, 0x1) != 0x0)
{
gUnknown_030008F8[bg].tilemap = tilemap;
}
}
void UnsetBgTilemapBuffer(u8 bg)
{
if (IsInvalidBgDuplicate(bg) == FALSE && GetBgControlAttribute(bg, 0x1) != 0x0)
{
gUnknown_030008F8[bg].tilemap = NULL;
}
}
#ifdef NONMATCHING // Probably the stupidest nonmatching ever pt 3
void* GetBgTilemapBuffer(u8 bg)
{
if (IsInvalidBgDuplicate(bg) == FALSE && GetBgControlAttribute(bg, 0x1) != 0)
{
return gUnknown_030008F8[bg].tilemap;
}
else
{
return NULL;
}
}
#else
__attribute__((naked))
void* GetBgTilemapBuffer(u8 bg)
{
asm("push {r4,lr}\n\
lsl r0, #24\n\
lsr r0, #24\n\
add r4, r0, #0\n\
bl IsInvalidBgDuplicate\n\
cmp r0, #0\n\
bne _080022E8\n\
add r0, r4, #0\n\
mov r1, #0x1\n\
bl GetBgControlAttribute\n\
lsl r0, #16\n\
cmp r0, #0\n\
beq _080022E8\n\
ldr r0, =gUnknown_030008F8\n\
lsl r1, r4, #4\n\
add r0, #0x4\n\
add r1, r0\n\
ldr r0, [r1]\n\
b _080022EA\n\
.pool\n\
_080022E8:\n\
mov r0, #0\n\
_080022EA:\n\
pop {r4}\n\
pop {r1}\n\
bx r1\n");
}
#endif // NONMATCHING
void CopyToBgTilemapBuffer(u8 bg, void *src, u16 mode, u16 destOffset)
{
if (IsInvalidBgDuplicate(bg) == FALSE && IsTileMapOutsideWram(bg) == FALSE)
{
if (mode != 0)
{
CpuCopy16(src, (void *)(gUnknown_030008F8[bg].tilemap + (destOffset * 2)), mode);
}
else
{
LZ77UnCompWram(src, (void *)(gUnknown_030008F8[bg].tilemap + (destOffset * 2)));
}
}
}
void CopyBgTilemapBufferToVram(u8 bg)
{
u16 sizeToLoad;
if (IsInvalidBgDuplicate(bg) == FALSE && IsTileMapOutsideWram(bg) == FALSE)
{
switch (GetBgType(bg))
{
case 0:
sizeToLoad = GetBgMetricTextMode(bg, 0) * 0x800;
break;
case 1:
sizeToLoad = GetBgMetricAffineMode(bg, 0) * 0x100;
break;
default:
sizeToLoad = 0;
break;
}
LoadBgVram(bg, gUnknown_030008F8[bg].tilemap, sizeToLoad, 0, 2);
}
}
void CopyToBgTilemapBufferRect(u8 bg, void* src, u8 destX, u8 destY, u8 width, u8 height)
{
s16 finalX;
s16 finalY;
u16 test;
u8 destXCopy;
u8 destYCopy;
void* srcBackup;
if (IsInvalidBgDuplicate(bg) == FALSE && IsTileMapOutsideWram(bg) == FALSE)
{
switch (GetBgType(bg))
{
case 0:
srcBackup = src;
destYCopy = destY;
for (finalY = destYCopy + height; destYCopy < finalY; destYCopy++)
{
destXCopy = destX;
for (finalX = destXCopy + width; destXCopy < finalX; destXCopy++)
{
((u16*)gUnknown_030008F8[bg].tilemap)[((destYCopy * 0x20) + destXCopy)] = *((u16*)srcBackup)++;
}
}
break;
case 1:
srcBackup = src;
test = GetBgMetricAffineMode(bg, 0x1);
destYCopy = destY;
for (finalY = destYCopy + height; destYCopy < finalY; destYCopy++)
{
destXCopy = destX;
for (finalX = destXCopy + width; destXCopy < finalX; destXCopy++)
{
((u8*)gUnknown_030008F8[bg].tilemap)[((destYCopy * test) + destXCopy)] = *((u8*)srcBackup)++;
}
}
break;
}
}
}