summaryrefslogtreecommitdiff
path: root/src/sprite.c
diff options
context:
space:
mode:
authorDizzyEggg <jajkodizzy@wp.pl>2017-09-02 01:42:44 +0200
committerDizzyEggg <jajkodizzy@wp.pl>2017-09-02 01:42:44 +0200
commitc146c247f23f703f1de48506ecb222d5b72a1200 (patch)
treef454b3d03bdb2de8328a701f059a71da1f5f4661 /src/sprite.c
parent26bf61e06fb4c29e9a297d88dbe42942ba0c96b9 (diff)
decompile more of sprite.s
Diffstat (limited to 'src/sprite.c')
-rw-r--r--src/sprite.c656
1 files changed, 656 insertions, 0 deletions
diff --git a/src/sprite.c b/src/sprite.c
index 245dc2660..8a19358f0 100644
--- a/src/sprite.c
+++ b/src/sprite.c
@@ -2,8 +2,29 @@
#include "sprite.h"
#include "main.h"
+#define MAX_SPRITE_COPY_REQUESTS 64
+
#define OAM_MATRIX_COUNT 32
+#define SET_SPRITE_TILE_RANGE(index, start, count) \
+{ \
+ sSpriteTileRanges[index * 2] = start; \
+ (sSpriteTileRanges + 1)[index * 2] = count; \
+}
+
+#define ALLOC_SPRITE_TILE(n) \
+{ \
+ gSpriteTileAllocBitmap[(n) / 8] |= (1 << ((n) % 8)); \
+}
+
+#define FREE_SPRITE_TILE(n) \
+{ \
+ gSpriteTileAllocBitmap[(n) / 8] &= ~(1 << ((n) % 8)); \
+}
+
+#define SPRITE_TILE_IS_ALLOCATED(n) ((gSpriteTileAllocBitmap[(n) / 8] >> ((n) % 8)) & 1)
+
+
struct SpriteCopyRequest
{
const u8 *src;
@@ -60,6 +81,13 @@ void ResetAffineAnimData(void);
u8 IndexOfSpriteTileTag(u16 tag);
void AllocSpriteTileRange(u16 tag, u16 start, u16 count);
void DoLoadSpritePalette(const u16 *src, u16 paletteOffset);
+void obj_update_pos2(struct Sprite* sprite, s16 arg1, s16 arg2);
+
+typedef void (*AnimFunc)(struct Sprite *);
+typedef void (*AnimCmdFunc)(struct Sprite *);
+typedef void (*AffineAnimCmdFunc)(u8 matrixNum, struct Sprite *);
+
+extern struct AffineAnimState sAffineAnimStates[OAM_MATRIX_COUNT];
EWRAM_DATA struct Sprite gSprites[MAX_SPRITES + 1] = {0};
EWRAM_DATA u16 gSpritePriorities[MAX_SPRITES] = {0};
@@ -75,6 +103,15 @@ EWRAM_DATA s16 gSpriteCoordOffsetY = 0;
EWRAM_DATA struct OamMatrix gOamMatrices[OAM_MATRIX_COUNT] = {0};
EWRAM_DATA bool8 gAffineAnimsDisabled = 0;
+extern const struct OamData gDummyOamData;
+extern const struct SpriteTemplate gDummySpriteTemplate;
+extern const struct Sprite sDummySprite;
+extern const u8 sCenterToCornerVecTable[3][4][2];
+extern const AnimFunc sAnimFuncs[];
+extern const AnimFunc sAffineAnimFuncs[];
+extern const AnimCmdFunc sAnimCmdFuncs[];
+extern const AffineAnimCmdFunc sAffineAnimCmdFuncs[];
+
void ResetSpriteData(void)
{
ResetOamRange(0, 128);
@@ -259,3 +296,622 @@ void CopyMatricesToOamBuffer(void)
}
}
+void AddSpritesToOamBuffer(void)
+{
+ u8 i = 0;
+ u8 oamIndex = 0;
+
+ while (i < MAX_SPRITES)
+ {
+ struct Sprite *sprite = &gSprites[gSpriteOrder[i]];
+ if (sprite->inUse && !sprite->invisible && AddSpriteToOamBuffer(sprite, &oamIndex))
+ return;
+ i++;
+ }
+
+ while (oamIndex < gOamLimit)
+ {
+ gMain.oamBuffer[oamIndex] = gDummyOamData;
+ oamIndex++;
+ }
+}
+
+u8 CreateSprite(const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_SPRITES; i++)
+ if (!gSprites[i].inUse)
+ return CreateSpriteAt(i, template, x, y, subpriority);
+
+ return MAX_SPRITES;
+}
+
+u8 CreateSpriteAtEnd(const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority)
+{
+ s16 i;
+
+ for (i = MAX_SPRITES - 1; i > -1; i--)
+ if (!gSprites[i].inUse)
+ return CreateSpriteAt(i, template, x, y, subpriority);
+
+ return MAX_SPRITES;
+}
+
+u8 CreateInvisibleSprite(void (*callback)(struct Sprite *))
+{
+ u8 index = CreateSprite(&gDummySpriteTemplate, 0, 0, 31);
+
+ if (index == MAX_SPRITES)
+ {
+ return MAX_SPRITES;
+ }
+ else
+ {
+ gSprites[index].invisible = TRUE;
+ gSprites[index].callback = callback;
+ return index;
+ }
+}
+
+u8 CreateSpriteAt(u8 index, const struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority)
+{
+ struct Sprite *sprite = &gSprites[index];
+
+ ResetSprite(sprite);
+
+ sprite->inUse = TRUE;
+ sprite->animBeginning = TRUE;
+ sprite->affineAnimBeginning = TRUE;
+ sprite->usingSheet = TRUE;
+
+ sprite->subpriority = subpriority;
+ sprite->oam = *template->oam;
+ sprite->anims = template->anims;
+ sprite->affineAnims = template->affineAnims;
+ sprite->template = template;
+ sprite->callback = template->callback;
+ sprite->pos1.x = x;
+ sprite->pos1.y = y;
+
+ CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, sprite->oam.affineMode);
+
+ if (template->tileTag == 0xFFFF)
+ {
+ s16 tileNum;
+ sprite->images = template->images;
+ tileNum = AllocSpriteTiles((u8)(sprite->images->size / TILE_SIZE_4BPP));
+ if (tileNum == -1)
+ {
+ ResetSprite(sprite);
+ return MAX_SPRITES;
+ }
+ sprite->oam.tileNum = tileNum;
+ sprite->usingSheet = FALSE;
+ sprite->sheetTileStart = 0;
+ }
+ else
+ {
+ sprite->sheetTileStart = GetSpriteTileStartByTag(template->tileTag);
+ SetSpriteSheetFrameTileNum(sprite);
+ }
+
+ if (sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK)
+ InitSpriteAffineAnim(sprite);
+
+ if (template->paletteTag != 0xFFFF)
+ sprite->oam.paletteNum = IndexOfSpritePaletteTag(template->paletteTag);
+
+ return index;
+}
+
+u8 CreateSpriteAndAnimate(struct SpriteTemplate *template, s16 x, s16 y, u8 subpriority)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_SPRITES; i++)
+ {
+ struct Sprite *sprite = &gSprites[i];
+
+ if (!gSprites[i].inUse)
+ {
+ u8 index = CreateSpriteAt(i, template, x, y, subpriority);
+
+ if (index == MAX_SPRITES)
+ return MAX_SPRITES;
+
+ gSprites[i].callback(sprite);
+
+ if (gSprites[i].inUse)
+ AnimateSprite(sprite);
+
+ return index;
+ }
+ }
+
+ return MAX_SPRITES;
+}
+
+void DestroySprite(struct Sprite *sprite)
+{
+ if (sprite->inUse)
+ {
+ if (!sprite->usingSheet)
+ {
+ u16 i;
+ u16 tileEnd = (sprite->images->size / TILE_SIZE_4BPP) + sprite->oam.tileNum;
+ for (i = sprite->oam.tileNum; i < tileEnd; i++)
+ FREE_SPRITE_TILE(i);
+ }
+ ResetSprite(sprite);
+ }
+}
+
+void ResetOamRange(u8 a, u8 b)
+{
+ u8 i;
+
+ for (i = a; i < b; i++)
+ {
+ struct OamData *oamBuffer = gMain.oamBuffer;
+ oamBuffer[i] = *(struct OamData *)&gDummyOamData;
+ }
+}
+
+void LoadOam(void)
+{
+ if (!gMain.oamLoadDisabled)
+ CpuCopy32(gMain.oamBuffer, (void *)OAM, sizeof(gMain.oamBuffer));
+}
+
+void ClearSpriteCopyRequests(void)
+{
+ u8 i;
+
+ gShouldProcessSpriteCopyRequests = FALSE;
+ gSpriteCopyRequestCount = 0;
+
+ for (i = 0; i < MAX_SPRITE_COPY_REQUESTS; i++)
+ {
+ gSpriteCopyRequests[i].src = 0;
+ gSpriteCopyRequests[i].dest = 0;
+ gSpriteCopyRequests[i].size = 0;
+ }
+}
+
+void ResetOamMatrices(void)
+{
+ u8 i;
+ for (i = 0; i < OAM_MATRIX_COUNT; i++)
+ {
+ // set to identity matrix
+ gOamMatrices[i].a = 0x0100;
+ gOamMatrices[i].b = 0x0000;
+ gOamMatrices[i].c = 0x0000;
+ gOamMatrices[i].d = 0x0100;
+ }
+}
+
+void SetOamMatrix(u8 matrixNum, u16 a, u16 b, u16 c, u16 d)
+{
+ gOamMatrices[matrixNum].a = a;
+ gOamMatrices[matrixNum].b = b;
+ gOamMatrices[matrixNum].c = c;
+ gOamMatrices[matrixNum].d = d;
+}
+
+void ResetSprite(struct Sprite *sprite)
+{
+ *sprite = sDummySprite;
+}
+
+void CalcCenterToCornerVec(struct Sprite *sprite, u8 shape, u8 size, u8 affineMode)
+{
+ u8 x = sCenterToCornerVecTable[shape][size][0];
+ u8 y = sCenterToCornerVecTable[shape][size][1];
+
+ if (affineMode & ST_OAM_AFFINE_DOUBLE_MASK)
+ {
+ x *= 2;
+ y *= 2;
+ }
+
+ sprite->centerToCornerVecX = x;
+ sprite->centerToCornerVecY = y;
+}
+
+s16 AllocSpriteTiles(u16 tileCount)
+{
+ u16 i;
+ s16 start;
+ u16 numTilesFound;
+
+ if (tileCount == 0)
+ {
+ // Free all unreserved tiles if the tile count is 0.
+ for (i = gReservedSpriteTileCount; i < TOTAL_OBJ_TILE_COUNT; i++)
+ FREE_SPRITE_TILE(i);
+
+ return 0;
+ }
+
+ i = gReservedSpriteTileCount;
+
+ for (;;)
+ {
+ while (SPRITE_TILE_IS_ALLOCATED(i))
+ {
+ i++;
+
+ if (i == TOTAL_OBJ_TILE_COUNT)
+ return -1;
+ }
+
+ start = i;
+ numTilesFound = 1;
+
+ while (numTilesFound != tileCount)
+ {
+ i++;
+
+ if (i == TOTAL_OBJ_TILE_COUNT)
+ return -1;
+
+ if (!SPRITE_TILE_IS_ALLOCATED(i))
+ numTilesFound++;
+ else
+ break;
+ }
+
+ if (numTilesFound == tileCount)
+ break;
+ }
+
+ for (i = start; i < tileCount + start; i++)
+ ALLOC_SPRITE_TILE(i);
+
+ return start;
+}
+
+u8 SpriteTileAllocBitmapOp(u16 bit, u8 op)
+{
+ u8 index = bit / 8;
+ u8 shift = bit % 8;
+ u8 val = bit % 8;
+ u8 retVal = 0;
+
+ if (op == 0)
+ {
+ val = ~(1 << val);
+ gSpriteTileAllocBitmap[index] &= val;
+ }
+ else if (op == 1)
+ {
+ val = (1 << val);
+ gSpriteTileAllocBitmap[index] |= val;
+ }
+ else
+ {
+ retVal = 1 << shift;
+ retVal &= gSpriteTileAllocBitmap[index];
+ }
+
+ return retVal;
+}
+
+void SpriteCallbackDummy(struct Sprite *sprite)
+{
+}
+
+void ProcessSpriteCopyRequests(void)
+{
+ if (gShouldProcessSpriteCopyRequests)
+ {
+ u8 i = 0;
+
+ while (gSpriteCopyRequestCount > 0)
+ {
+ CpuCopy16(gSpriteCopyRequests[i].src, gSpriteCopyRequests[i].dest, gSpriteCopyRequests[i].size);
+ gSpriteCopyRequestCount--;
+ i++;
+ }
+
+ gShouldProcessSpriteCopyRequests = FALSE;
+ }
+}
+
+void RequestSpriteFrameImageCopy(u16 index, u16 tileNum, const struct SpriteFrameImage *images)
+{
+ if (gSpriteCopyRequestCount < MAX_SPRITE_COPY_REQUESTS)
+ {
+ gSpriteCopyRequests[gSpriteCopyRequestCount].src = images[index].data;
+ gSpriteCopyRequests[gSpriteCopyRequestCount].dest = (u8 *)OBJ_VRAM0 + TILE_SIZE_4BPP * tileNum;
+ gSpriteCopyRequests[gSpriteCopyRequestCount].size = images[index].size;
+ gSpriteCopyRequestCount++;
+ }
+}
+
+void RequestSpriteCopy(const u8 *src, u8 *dest, u16 size)
+{
+ if (gSpriteCopyRequestCount < MAX_SPRITE_COPY_REQUESTS)
+ {
+ gSpriteCopyRequests[gSpriteCopyRequestCount].src = src;
+ gSpriteCopyRequests[gSpriteCopyRequestCount].dest = dest;
+ gSpriteCopyRequests[gSpriteCopyRequestCount].size = size;
+ gSpriteCopyRequestCount++;
+ }
+}
+
+void CopyFromSprites(u8 *dest)
+{
+ u32 i;
+ u8 *src = (u8 *)gSprites;
+ for (i = 0; i < sizeof(struct Sprite) * MAX_SPRITES; i++)
+ {
+ *dest = *src;
+ dest++;
+ src++;
+ }
+}
+
+void CopyToSprites(u8 *src)
+{
+ u32 i;
+ u8 *dest = (u8 *)gSprites;
+ for (i = 0; i < sizeof(struct Sprite) * MAX_SPRITES; i++)
+ {
+ *dest = *src;
+ src++;
+ dest++;
+ }
+}
+
+void ResetAllSprites(void)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_SPRITES; i++)
+ {
+ ResetSprite(&gSprites[i]);
+ gSpriteOrder[i] = i;
+ }
+
+ ResetSprite(&gSprites[i]);
+}
+
+void FreeSpriteTiles(struct Sprite *sprite)
+{
+ if (sprite->template->tileTag != 0xFFFF)
+ FreeSpriteTilesByTag(sprite->template->tileTag);
+}
+
+void FreeSpritePalette(struct Sprite *sprite)
+{
+ FreeSpritePaletteByTag(sprite->template->paletteTag);
+}
+
+void FreeSpriteOamMatrix(struct Sprite *sprite)
+{
+ if (sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK)
+ {
+ FreeOamMatrix(sprite->oam.matrixNum);
+ sprite->oam.affineMode = ST_OAM_AFFINE_OFF;
+ }
+}
+
+void DestroySpriteAndFreeResources(struct Sprite *sprite)
+{
+ FreeSpriteTiles(sprite);
+ FreeSpritePalette(sprite);
+ FreeSpriteOamMatrix(sprite);
+ DestroySprite(sprite);
+}
+
+void AnimateSprite(struct Sprite *sprite)
+{
+ sAnimFuncs[sprite->animBeginning](sprite);
+
+ if (!gAffineAnimsDisabled)
+ sAffineAnimFuncs[sprite->affineAnimBeginning](sprite);
+}
+
+void BeginAnim(struct Sprite *sprite)
+{
+ s16 imageValue;
+ u8 duration;
+ u8 hFlip;
+ u8 vFlip;
+
+ sprite->animCmdIndex = 0;
+ sprite->animEnded = FALSE;
+ sprite->animLoopCounter = 0;
+ imageValue = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.imageValue;
+
+ if (imageValue != -1)
+ {
+ sprite->animBeginning = FALSE;
+ duration = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.duration;
+ hFlip = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.hFlip;
+ vFlip = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.vFlip;
+
+ if (duration)
+ duration--;
+
+ sprite->animDelayCounter = duration;
+
+ if (!(sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK))
+ SetSpriteOamFlipBits(sprite, hFlip, vFlip);
+
+ if (sprite->usingSheet)
+ sprite->oam.tileNum = sprite->sheetTileStart + imageValue;
+ else
+ RequestSpriteFrameImageCopy(imageValue, sprite->oam.tileNum, sprite->images);
+ }
+}
+
+void ContinueAnim(struct Sprite *sprite)
+{
+ if (sprite->animDelayCounter)
+ {
+ u8 hFlip;
+ u8 vFlip;
+ DecrementAnimDelayCounter(sprite);
+ hFlip = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.hFlip;
+ vFlip = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.vFlip;
+ if (!(sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK))
+ SetSpriteOamFlipBits(sprite, hFlip, vFlip);
+ }
+ else if (!sprite->animPaused)
+ {
+ s16 type;
+ s16 funcIndex;
+ sprite->animCmdIndex++;
+ type = sprite->anims[sprite->animNum][sprite->animCmdIndex].type;
+ funcIndex = 3;
+ if (type < 0)
+ funcIndex = type + 3;
+ sAnimCmdFuncs[funcIndex](sprite);
+ }
+}
+
+void AnimCmd_frame(struct Sprite *sprite)
+{
+ s16 imageValue;
+ u8 duration;
+ u8 hFlip;
+ u8 vFlip;
+
+ imageValue = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.imageValue;
+ duration = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.duration;
+ hFlip = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.hFlip;
+ vFlip = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.vFlip;
+
+ if (duration)
+ duration--;
+
+ sprite->animDelayCounter = duration;
+
+ if (!(sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK))
+ SetSpriteOamFlipBits(sprite, hFlip, vFlip);
+
+ if (sprite->usingSheet)
+ sprite->oam.tileNum = sprite->sheetTileStart + imageValue;
+ else
+ RequestSpriteFrameImageCopy(imageValue, sprite->oam.tileNum, sprite->images);
+}
+
+void AnimCmd_end(struct Sprite *sprite)
+{
+ sprite->animCmdIndex--;
+ sprite->animEnded = TRUE;
+}
+
+void AnimCmd_jump(struct Sprite *sprite)
+{
+ s16 imageValue;
+ u8 duration;
+ u8 hFlip;
+ u8 vFlip;
+
+ sprite->animCmdIndex = sprite->anims[sprite->animNum][sprite->animCmdIndex].jump.target;
+
+ imageValue = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.imageValue;
+ duration = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.duration;
+ hFlip = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.hFlip;
+ vFlip = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.vFlip;
+
+ if (duration)
+ duration--;
+
+ sprite->animDelayCounter = duration;
+
+ if (!(sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK))
+ SetSpriteOamFlipBits(sprite, hFlip, vFlip);
+
+ if (sprite->usingSheet)
+ sprite->oam.tileNum = sprite->sheetTileStart + imageValue;
+ else
+ RequestSpriteFrameImageCopy(imageValue, sprite->oam.tileNum, sprite->images);
+}
+
+void AnimCmd_loop(struct Sprite *sprite)
+{
+ if (sprite->animLoopCounter)
+ ContinueAnimLoop(sprite);
+ else
+ BeginAnimLoop(sprite);
+}
+
+void BeginAnimLoop(struct Sprite *sprite)
+{
+ sprite->animLoopCounter = sprite->anims[sprite->animNum][sprite->animCmdIndex].loop.count;
+ JumpToTopOfAnimLoop(sprite);
+ ContinueAnim(sprite);
+}
+
+void ContinueAnimLoop(struct Sprite *sprite)
+{
+ sprite->animLoopCounter--;
+ JumpToTopOfAnimLoop(sprite);
+ ContinueAnim(sprite);
+}
+
+void JumpToTopOfAnimLoop(struct Sprite *sprite)
+{
+ if (sprite->animLoopCounter)
+ {
+ sprite->animCmdIndex--;
+
+ while (sprite->anims[sprite->animNum][sprite->animCmdIndex - 1].type != -3)
+ {
+ if (sprite->animCmdIndex == 0)
+ break;
+ sprite->animCmdIndex--;
+ }
+
+ sprite->animCmdIndex--;
+ }
+}
+
+void BeginAffineAnim(struct Sprite *sprite)
+{
+ if ((sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK) && sprite->affineAnims[0][0].type != 32767)
+ {
+ struct AffineAnimFrameCmd frameCmd;
+ u8 matrixNum = GetSpriteMatrixNum(sprite);
+ AffineAnimStateRestartAnim(matrixNum);
+ GetAffineAnimFrame(matrixNum, sprite, &frameCmd);
+ sprite->affineAnimBeginning = FALSE;
+ sprite->affineAnimEnded = FALSE;
+ ApplyAffineAnimFrame(matrixNum, &frameCmd);
+ sAffineAnimStates[matrixNum].delayCounter = frameCmd.duration;
+ if (sprite->flags_f)
+ obj_update_pos2(sprite, sprite->data6, sprite->data7);
+ }
+}
+
+void ContinueAffineAnim(struct Sprite *sprite)
+{
+ if (sprite->oam.affineMode & ST_OAM_AFFINE_ON_MASK)
+ {
+ u8 matrixNum = GetSpriteMatrixNum(sprite);
+
+ if (sAffineAnimStates[matrixNum].delayCounter)
+ AffineAnimDelay(matrixNum, sprite);
+ else if (sprite->affineAnimPaused)
+ return;
+ else
+ {
+ s16 type;
+ s16 funcIndex;
+ sAffineAnimStates[matrixNum].animCmdIndex++;
+ type = sprite->affineAnims[sAffineAnimStates[matrixNum].animNum][sAffineAnimStates[matrixNum].animCmdIndex].type;
+ funcIndex = 3;
+ if (type >= 32765)
+ funcIndex = type - 32765;
+ sAffineAnimCmdFuncs[funcIndex](matrixNum, sprite);
+ }
+ if (sprite->flags_f)
+ obj_update_pos2(sprite, sprite->data6, sprite->data7);
+ }
+}