diff options
author | DizzyEggg <jajkodizzy@wp.pl> | 2017-09-02 01:42:44 +0200 |
---|---|---|
committer | DizzyEggg <jajkodizzy@wp.pl> | 2017-09-02 01:42:44 +0200 |
commit | c146c247f23f703f1de48506ecb222d5b72a1200 (patch) | |
tree | f454b3d03bdb2de8328a701f059a71da1f5f4661 /src/sprite.c | |
parent | 26bf61e06fb4c29e9a297d88dbe42942ba0c96b9 (diff) |
decompile more of sprite.s
Diffstat (limited to 'src/sprite.c')
-rw-r--r-- | src/sprite.c | 656 |
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); + } +} |