pokeemerald/src/digit_obj_util.c
aaaaaa123456789 7dc95a0103 Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.

Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 06:30:55 -03:00

451 lines
11 KiB
C

#include "global.h"
#include "digit_obj_util.h"
#include "malloc.h"
#include "decompress.h"
#include "main.h"
#include "battle_main.h"
struct DigitPrinter
{
bool8 isActive;
u8 firstOamId;
u8 strConvMode;
u8 oamCount;
u8 palTagIndex;
u8 size;
u8 shape;
u8 priority;
u8 xDelta;
u8 tilesPerImage;
u16 tileStart;
s16 x;
s16 y;
u16 tileTag;
u16 palTag;
u32 pow10;
s32 lastPrinted;
};
struct DigitPrinterAlloc
{
u32 count;
struct DigitPrinter *array;
};
// this file's functions
static u8 GetFirstOamId(u8 oamCount);;
static void CopyWorkToOam(struct DigitPrinter *objWork);
static void DrawNumObjsLeadingZeros(struct DigitPrinter *objWork, s32 num, bool32 sign);
static void DrawNumObjsMinusInFront(struct DigitPrinter *objWork, s32 num, bool32 sign);
static void DrawNumObjsMinusInBack(struct DigitPrinter *objWork, s32 num, bool32 sign);
static bool32 SharesTileWithAnyActive(u32 id);
static bool32 SharesPalWithAnyActive(u32 id);
// ewram
static EWRAM_DATA struct DigitPrinterAlloc *sOamWork = {0};
// const rom data
static const u8 sTilesPerImage[4][4] =
{
[ST_OAM_SQUARE] = {
[ST_OAM_SIZE_0] = 0x01, // SPRITE_SIZE_8x8
[ST_OAM_SIZE_1] = 0x04, // SPRITE_SIZE_16x16
[ST_OAM_SIZE_2] = 0x10, // SPRITE_SIZE_32x32
[ST_OAM_SIZE_3] = 0x40 // SPRITE_SIZE_64x64
},
[ST_OAM_H_RECTANGLE] = {
[ST_OAM_SIZE_0] = 0x02, // SPRITE_SIZE_16x8
[ST_OAM_SIZE_1] = 0x04, // SPRITE_SIZE_32x8
[ST_OAM_SIZE_2] = 0x08, // SPRITE_SIZE_32x16
[ST_OAM_SIZE_3] = 0x20 // SPRITE_SIZE_64x32
},
[ST_OAM_V_RECTANGLE] = {
[ST_OAM_SIZE_0] = 0x02, // SPRITE_SIZE_8x16
[ST_OAM_SIZE_1] = 0x04, // SPRITE_SIZE_8x32
[ST_OAM_SIZE_2] = 0x08, // SPRITE_SIZE_16x32
[ST_OAM_SIZE_3] = 0x20 // SPRITE_SIZE_32x64
}
};
// code
bool32 DigitObjUtil_Init(u32 count)
{
u32 i;
if (sOamWork != NULL)
DigitObjUtil_Free();
sOamWork = Alloc(sizeof(*sOamWork));
if (sOamWork == NULL)
return FALSE;
sOamWork->array = Alloc(sizeof(struct DigitPrinter) * count);
if (sOamWork->array == NULL)
{
Free(sOamWork);
return FALSE;
}
sOamWork->count = count;
for (i = 0; i < count; i++)
{
sOamWork->array[i].isActive = FALSE;
sOamWork->array[i].firstOamId = 0xFF;
}
return TRUE;
}
void DigitObjUtil_Free(void)
{
if (sOamWork != NULL)
{
if (sOamWork->array != NULL)
{
u32 i;
for (i = 0; i < sOamWork->count; i++)
DigitObjUtil_DeletePrinter(i);
Free(sOamWork->array);
}
FREE_AND_SET_NULL(sOamWork);
}
}
bool32 DigitObjUtil_CreatePrinter(u32 id, s32 num, const struct DigitObjUtilTemplate *template)
{
u32 i;
if (sOamWork == NULL)
return FALSE;
if (sOamWork->array[id].isActive)
return FALSE;
sOamWork->array[id].firstOamId = GetFirstOamId(template->oamCount);
if (sOamWork->array[id].firstOamId == 0xFF)
return FALSE;
sOamWork->array[id].tileStart = GetSpriteTileStartByTag(template->spriteSheet->tag);
if (sOamWork->array[id].tileStart == 0xFFFF)
{
if (template->spriteSheet->size != 0)
{
sOamWork->array[id].tileStart = LoadSpriteSheet(template->spriteSheet);
}
else
{
struct CompressedSpriteSheet compSpriteSheet;
compSpriteSheet = *(struct CompressedSpriteSheet*)(template->spriteSheet);
compSpriteSheet.size = GetDecompressedDataSize(template->spriteSheet->data);
sOamWork->array[id].tileStart = LoadCompressedSpriteSheet(&compSpriteSheet);
}
if (sOamWork->array[id].tileStart == 0xFFFF)
return FALSE;
}
sOamWork->array[id].palTagIndex = IndexOfSpritePaletteTag(template->spritePal->tag);
if (sOamWork->array[id].palTagIndex == 0xFF)
sOamWork->array[id].palTagIndex = LoadSpritePalette(template->spritePal);
sOamWork->array[id].strConvMode = template->strConvMode;
sOamWork->array[id].oamCount = template->oamCount;
sOamWork->array[id].x = template->x;
sOamWork->array[id].y = template->y;
sOamWork->array[id].shape = template->shape;
sOamWork->array[id].size = template->size;
sOamWork->array[id].priority = template->priority;
sOamWork->array[id].xDelta = template->xDelta;
sOamWork->array[id].tilesPerImage = GetTilesPerImage(template->shape, template->size);
sOamWork->array[id].tileTag = template->spriteSheet->tag;
sOamWork->array[id].palTag = template->spritePal->tag;
sOamWork->array[id].isActive = TRUE;
// Decimal left shift
sOamWork->array[id].pow10 = 1;
for (i = 1; i < template->oamCount; i++)
sOamWork->array[id].pow10 *= 10;
CopyWorkToOam(&sOamWork->array[id]);
DigitObjUtil_PrintNumOn(id, num);
return TRUE;
}
static void CopyWorkToOam(struct DigitPrinter *objWork)
{
u32 i;
u32 oamId = objWork->firstOamId;
u32 x = objWork->x;
u32 oamCount = objWork->oamCount + 1;
CpuFill16(0, &gMain.oamBuffer[oamId], sizeof(struct OamData) * oamCount);
for (i = 0, oamId = objWork->firstOamId; i < oamCount; i++, oamId++)
{
gMain.oamBuffer[oamId].y = objWork->y;
gMain.oamBuffer[oamId].x = x;
gMain.oamBuffer[oamId].shape = objWork->shape;
gMain.oamBuffer[oamId].size = objWork->size;
gMain.oamBuffer[oamId].tileNum = objWork->tileStart;
gMain.oamBuffer[oamId].priority = objWork->priority;
gMain.oamBuffer[oamId].paletteNum = objWork->palTagIndex;
x += objWork->xDelta;
}
oamId--;
gMain.oamBuffer[oamId].x = objWork->x - objWork->xDelta;
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_ERASE;
gMain.oamBuffer[oamId].tileNum = objWork->tileStart + (objWork->tilesPerImage * 10);
}
void DigitObjUtil_PrintNumOn(u32 id, s32 num)
{
bool32 sign;
if (sOamWork == NULL)
return;
if (!sOamWork->array[id].isActive)
return;
sOamWork->array[id].lastPrinted = num;
if (num < 0)
{
sign = TRUE;
num *= -1;
}
else
{
sign = FALSE;
}
switch (sOamWork->array[id].strConvMode)
{
case 0:
default:
DrawNumObjsLeadingZeros(&sOamWork->array[id], num, sign);
break;
case 1:
DrawNumObjsMinusInFront(&sOamWork->array[id], num, sign);
break;
case 2:
DrawNumObjsMinusInBack(&sOamWork->array[id], num, sign);
break;
}
}
static void DrawNumObjsLeadingZeros(struct DigitPrinter *objWork, s32 num, bool32 sign)
{
u32 pow10 = objWork->pow10;
u32 oamId = objWork->firstOamId;
while (pow10 != 0)
{
u32 digit = num / pow10;
num -= (digit * pow10);
pow10 /= 10;
gMain.oamBuffer[oamId].tileNum = (digit * objWork->tilesPerImage) + objWork->tileStart;
oamId++;
}
if (sign)
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_OFF;
else
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_ERASE;
}
static void DrawNumObjsMinusInFront(struct DigitPrinter *objWork, s32 num, bool32 sign)
{
u32 pow10 = objWork->pow10;
static int oamId;
static int curDigit;
static int firstDigit;
oamId = objWork->firstOamId;
curDigit = 0;
firstDigit = -1;
while (pow10 != 0)
{
u32 digit = num / pow10;
num -= (digit * pow10);
pow10 /= 10;
if (digit != 0 || firstDigit != -1 || pow10 == 0)
{
gMain.oamBuffer[oamId].tileNum = (digit * objWork->tilesPerImage) + objWork->tileStart;
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_OFF;
if (firstDigit == -1)
firstDigit = curDigit;
}
else
{
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_ERASE;
}
oamId++;
curDigit++;
}
if (sign)
{
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_OFF;
gMain.oamBuffer[oamId].x = objWork->x + ((firstDigit - 1) * objWork->xDelta);
}
else
{
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_ERASE;
}
}
static void DrawNumObjsMinusInBack(struct DigitPrinter *objWork, s32 num, bool32 sign)
{
u32 pow10 = objWork->pow10;
u32 oamId = objWork->firstOamId;
bool32 printingDigits = FALSE;
s32 nsprites = 0;
while (pow10 != 0)
{
u32 digit = num / pow10;
num -= (digit * pow10);
pow10 /= 10;
if (digit != 0 || printingDigits || pow10 == 0)
{
printingDigits = TRUE;
gMain.oamBuffer[oamId].tileNum = (digit * objWork->tilesPerImage) + objWork->tileStart;
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_OFF;
oamId++;
nsprites++;
}
}
while (nsprites < objWork->oamCount)
{
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_ERASE;
oamId++;
nsprites++;
}
if (sign)
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_OFF;
else
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_ERASE;
}
void DigitObjUtil_DeletePrinter(u32 id)
{
s32 oamId, oamCount, i;
if (sOamWork == NULL)
return;
if (!sOamWork->array[id].isActive)
return;
oamCount = sOamWork->array[id].oamCount + 1;
oamId = sOamWork->array[id].firstOamId;
for (i = 0; i < oamCount; i++, oamId++)
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_ERASE;
if (!SharesTileWithAnyActive(id))
FreeSpriteTilesByTag(sOamWork->array[id].tileTag);
if (!SharesPalWithAnyActive(id))
FreeSpritePaletteByTag(sOamWork->array[id].palTag);
sOamWork->array[id].isActive = FALSE;
}
void DigitObjUtil_HideOrShow(u32 id, bool32 hide)
{
s32 oamId, oamCount, i;
if (sOamWork == NULL)
return;
if (!sOamWork->array[id].isActive)
return;
oamCount = sOamWork->array[id].oamCount + 1;
oamId = sOamWork->array[id].firstOamId;
if (hide)
{
for (i = 0; i < oamCount; i++, oamId++)
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_ERASE;
}
else
{
for (i = 0; i < oamCount; i++, oamId++)
gMain.oamBuffer[oamId].affineMode = ST_OAM_AFFINE_OFF;
DigitObjUtil_PrintNumOn(id, sOamWork->array[id].lastPrinted);
}
}
static u8 GetFirstOamId(u8 oamCount)
{
u32 i;
u16 firstOamId = 64;
for (i = 0; i < sOamWork->count; i++)
{
if (!sOamWork->array[i].isActive)
{
if (sOamWork->array[i].firstOamId != 0xFF && sOamWork->array[i].oamCount <= oamCount)
return sOamWork->array[i].firstOamId;
}
else
{
firstOamId += 1 + sOamWork->array[i].oamCount;
}
}
if (firstOamId + oamCount + 1 > 128)
return 0xFF;
else
return firstOamId;
}
static bool32 SharesTileWithAnyActive(u32 id)
{
u32 i;
for (i = 0; i < sOamWork->count; i++)
{
if (sOamWork->array[i].isActive && i != id
&& sOamWork->array[i].tileTag == sOamWork->array[id].tileTag)
{
return TRUE;
}
}
return FALSE;
}
static bool32 SharesPalWithAnyActive(u32 id)
{
u32 i;
for (i = 0; i < sOamWork->count; i++)
{
if (sOamWork->array[i].isActive && i != id
&& sOamWork->array[i].palTag == sOamWork->array[id].palTag)
{
return TRUE;
}
}
return FALSE;
}
u8 GetTilesPerImage(u32 shape, u32 size)
{
return sTilesPerImage[shape][size];
}