mirror of
https://github.com/pmret/papermario.git
synced 2024-11-08 12:02:30 +01:00
a37f30dc94
* wip changes for modern gcc * more * wip * blah * Define explicit size for symbol * Clean up evt_handle_exec1 * wip * . * fixes & VLA macro * VLA innit * wipz * Fix potential UB * meowp * meowp2 * fixies * git subrepo pull --force tools/splat subrepo: subdir: "tools/splat" merged: "e1f0b17917" upstream: origin: "https://github.com/ethteck/splat.git" branch: "master" commit: "e1f0b17917" git-subrepo: version: "0.4.5" origin: "https://github.com/ingydotnet/git-subrepo" commit: "aa416e4" * fixules * git subrepo pull --force tools/splat subrepo: subdir: "tools/splat" merged: "3ba3277e57" upstream: origin: "https://github.com/ethteck/splat.git" branch: "master" commit: "3ba3277e57" git-subrepo: version: "0.4.5" origin: "https://github.com/ingydotnet/git-subrepo" commit: "aa416e4" * more shiftability + symbols work * git subrepo pull --force tools/splat subrepo: subdir: "tools/splat" merged: "02879e52a7" upstream: origin: "https://github.com/ethteck/splat.git" branch: "master" commit: "02879e52a7" git-subrepo: version: "0.4.5" origin: "https://github.com/ingydotnet/git-subrepo" commit: "aa416e4" * more * revert bss changes for now, new heaps overlay for aligning stuff to 0x1000 (not sure how necessary that is, so maybe will revert later on) * 'fixing' jp shift build * more * more syms * more progress * more * ididid * git subrepo pull --force tools/splat subrepo: subdir: "tools/splat" merged: "de54da38f5" upstream: origin: "https://github.com/ethteck/splat.git" branch: "master" commit: "de54da38f5" git-subrepo: version: "0.4.5" origin: "https://github.com/ingydotnet/git-subrepo" commit: "aa416e4" * git subrepo pull --force tools/splat subrepo: subdir: "tools/splat" merged: "a27dc436a6" upstream: origin: "https://github.com/ethteck/splat.git" branch: "master" commit: "a27dc436a6" git-subrepo: version: "0.4.5" origin: "https://github.com/ingydotnet/git-subrepo" commit: "aa416e4" * blah * stuff's broken, but at least it's maybe cleaner * modern gcc back * revert * shifting all overlays - works so far * progs * another * modern gcc flag, re-enabled all ifdef shift stuff * fixies * progress * fixes, matching build * heaps3 overlay and some symbol names * changies * PR comments & cleanup
379 lines
11 KiB
C
379 lines
11 KiB
C
#include "common.h"
|
|
#include "sprite.h"
|
|
#include "nu/nusys.h"
|
|
#include "ld_addrs.h"
|
|
|
|
#ifdef SHIFT
|
|
#define SPRITE_ROM_START _1943000_ROM_START + 0x10
|
|
#else
|
|
#define SPRITE_ROM_START 0x1943000 + 0x10
|
|
#endif
|
|
|
|
extern s32 spr_allocateBtlComponentsOnWorldHeap;
|
|
extern HeapNode heap_generalHead;
|
|
extern HeapNode heap_spriteHead;
|
|
|
|
BSS s32 spr_asset_entry[2];
|
|
BSS s32 D_802DFEB8[101];
|
|
BSS s32 PlayerRasterSetsLoaded;
|
|
BSS s32 PlayerRasterBufferSetOffsets[13];
|
|
BSS s32 D_802D0084[3]; // unused?
|
|
BSS s32 D_802E0090[0x2E0]; // correct length?
|
|
|
|
BSS s32 PlayerRasterHeader[3];
|
|
BSS s32 D_802E0C1C;
|
|
BSS s32 D_802E0C20[14];
|
|
BSS s32 PlayerRasterCacheSize;
|
|
BSS s32 PlayerRasterMaxSize;
|
|
BSS s32 SpriteDataHeader[3];
|
|
BSS s32 D_802E0C6C; // unused?
|
|
BSS PlayerSpriteCacheEntry PlayerRasterCache[18];
|
|
|
|
#define ALIGN4(v) (((u32)(v) >> 2) << 2)
|
|
#define SPR_SWIZZLE(base,offset) ((void*)((s32)(offset) + (s32)(base)))
|
|
|
|
void spr_swizzle_anim_offsets(s32 arg0, s32 base, void* spriteData) {
|
|
u8* buffer;
|
|
SpriteAnimComponent*** animList;
|
|
SpriteAnimComponent** compList;
|
|
SpriteAnimComponent* comp;
|
|
s32 animOffset;
|
|
s32 compOffset;
|
|
s32 temp;
|
|
|
|
// required to match, spriteData->animList would be nicer
|
|
animList = (SpriteAnimComponent***) spriteData;
|
|
animList += 4;
|
|
|
|
while (TRUE) {
|
|
if (*animList == PTR_LIST_END) {
|
|
break;
|
|
}
|
|
compList = (SpriteAnimComponent**) ((s32)*animList - ALIGN4(base));
|
|
compList = SPR_SWIZZLE(ALIGN4(spriteData), compList);
|
|
*animList = compList;
|
|
while (TRUE) {
|
|
if (*compList == PTR_LIST_END) {
|
|
break;
|
|
}
|
|
*compList = comp = SPR_SWIZZLE(ALIGN4(spriteData), (s32)*compList - ALIGN4(base));
|
|
comp->cmdList = SPR_SWIZZLE(ALIGN4(spriteData), (s32)comp->cmdList - ALIGN4(base));
|
|
compList++;
|
|
}
|
|
animList++;
|
|
}
|
|
}
|
|
|
|
SpriteAnimData* spr_load_sprite(s32 idx, s32 isPlayerSprite, s32 useTailAlloc) {
|
|
SpriteAnimData* animData;
|
|
s32 base;
|
|
s32 i;
|
|
s32 compressedSize;
|
|
s32* ptr1;
|
|
IMG_PTR image;
|
|
s32 count;
|
|
s32** data;
|
|
s32** palettes;
|
|
|
|
if (isPlayerSprite) {
|
|
base = SpriteDataHeader[1];
|
|
} else {
|
|
base = SpriteDataHeader[2];
|
|
}
|
|
|
|
// read current and next sprite offsets, so we can find the difference
|
|
nuPiReadRom(base + idx * 4, &spr_asset_entry, sizeof(spr_asset_entry));
|
|
|
|
compressedSize = ALIGN8(spr_asset_entry[1] - spr_asset_entry[0]);
|
|
data = general_heap_malloc(compressedSize);
|
|
nuPiReadRom(base + spr_asset_entry[0], data, compressedSize);
|
|
|
|
ptr1 = (s32*)data;
|
|
// skip 4 bytes: 'YAY0' signature
|
|
ptr1++;
|
|
|
|
if (useTailAlloc) {
|
|
animData = _heap_malloc_tail(&heap_spriteHead, *ptr1);
|
|
} else {
|
|
animData = _heap_malloc(&heap_spriteHead, *ptr1);
|
|
}
|
|
decode_yay0(data, animData);
|
|
general_heap_free(data);
|
|
|
|
// swizzle raster array
|
|
data = (s32**)animData->rastersOffset;
|
|
data = SPR_SWIZZLE(ALIGN4(animData), data);
|
|
animData->rastersOffset = (SpriteRasterCacheEntry**)data;
|
|
|
|
while (TRUE) {
|
|
ptr1 = *data;
|
|
if (ptr1 == PTR_LIST_END) {
|
|
break;
|
|
}
|
|
// swizzle each raster cache entry
|
|
ptr1 = SPR_SWIZZLE(ALIGN4(animData), ptr1);
|
|
*data++ = ptr1;
|
|
image = ((SpriteRasterCacheEntry*)ptr1)->image;
|
|
|
|
if (!isPlayerSprite) {
|
|
// swizzle image pointer in the cache entry
|
|
image = SPR_SWIZZLE(ALIGN4(animData), image);
|
|
*ptr1 = (s32)image;
|
|
}
|
|
}
|
|
|
|
if (isPlayerSprite) {
|
|
PlayerRasterBufferSetOffsets[idx] = PlayerRasterSetsLoaded;
|
|
count = D_802E0C20[idx + 1] - D_802E0C20[idx];
|
|
nuPiReadRom(SpriteDataHeader[0] + PlayerRasterHeader[1] + sizeof(u32) * D_802E0C20[idx], D_802DFEB8, sizeof(D_802DFEB8));
|
|
for (i = 0; i < count; i++) {
|
|
D_802E0090[PlayerRasterSetsLoaded++] = D_802DFEB8[i];
|
|
}
|
|
}
|
|
|
|
// swizzle palettes array
|
|
palettes = SPR_SWIZZLE(ALIGN4(animData), animData->palettesOffset);
|
|
animData->palettesOffset = (PAL_PTR*)palettes;
|
|
while (TRUE) {
|
|
ptr1 = *palettes;
|
|
if (ptr1 == PTR_LIST_END) {
|
|
break;
|
|
}
|
|
// swizzle each palette pointer
|
|
ptr1 = SPR_SWIZZLE(ALIGN4(animData), ptr1);
|
|
*palettes++ = ptr1;
|
|
}
|
|
|
|
spr_swizzle_anim_offsets(0, 0, animData);
|
|
return animData;
|
|
}
|
|
|
|
void spr_init_player_raster_cache(s32 cacheSize, s32 maxRasterSize) {
|
|
void* raster;
|
|
s32 i;
|
|
|
|
nuPiReadRom(SPRITE_ROM_START, &SpriteDataHeader, sizeof(SpriteDataHeader));
|
|
PlayerRasterCacheSize = cacheSize;
|
|
PlayerRasterMaxSize = maxRasterSize;
|
|
SpriteDataHeader[0] += SPRITE_ROM_START;
|
|
SpriteDataHeader[1] += SPRITE_ROM_START;
|
|
SpriteDataHeader[2] += SPRITE_ROM_START;
|
|
raster = _heap_malloc(&heap_spriteHead, maxRasterSize * cacheSize);
|
|
|
|
for (i = 0; i < ARRAY_COUNT(PlayerRasterCache); i++) {
|
|
PlayerRasterCache[i].raster = raster;
|
|
raster += PlayerRasterMaxSize;
|
|
PlayerRasterCache[i].lazyDeleteTime = 0;
|
|
PlayerRasterCache[i].rasterIndex = 0;
|
|
PlayerRasterCache[i].spriteIndex = 0xFF;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(PlayerRasterBufferSetOffsets); i++) {
|
|
PlayerRasterBufferSetOffsets[i] = 0;
|
|
}
|
|
PlayerRasterSetsLoaded = 0;
|
|
nuPiReadRom(SpriteDataHeader[0], &PlayerRasterHeader, sizeof(PlayerRasterHeader));
|
|
nuPiReadRom(SpriteDataHeader[0] + PlayerRasterHeader[0], D_802E0C20, sizeof(D_802E0C20));
|
|
}
|
|
|
|
IMG_PTR spr_get_player_raster(s32 rasterIndex, s32 playerSpriteID) {
|
|
PlayerSpriteCacheEntry* temp_s0;
|
|
u32 temp_a2;
|
|
s32 idx = -1;
|
|
s32 i;
|
|
|
|
for (i = 0; i < PlayerRasterCacheSize; i++) {
|
|
if (PlayerRasterCache[i].lazyDeleteTime != 0) {
|
|
if (PlayerRasterCache[i].rasterIndex == rasterIndex && PlayerRasterCache[i].spriteIndex == playerSpriteID) {
|
|
PlayerRasterCache[i].lazyDeleteTime = 2;
|
|
return PlayerRasterCache[i].raster;
|
|
}
|
|
} else if (idx == -1) {
|
|
idx = i;
|
|
}
|
|
}
|
|
|
|
if (idx == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
temp_s0 = &PlayerRasterCache[idx];
|
|
temp_s0->rasterIndex = rasterIndex;
|
|
temp_s0->spriteIndex = playerSpriteID;
|
|
temp_s0->lazyDeleteTime = 2;
|
|
temp_a2 = D_802E0090[PlayerRasterBufferSetOffsets[playerSpriteID] + rasterIndex];
|
|
nuPiReadRom(SpriteDataHeader[0] + (temp_a2 & 0xFFFFF), temp_s0->raster, (temp_a2 >> 0x10) & 0xFFF0);
|
|
return temp_s0->raster;
|
|
}
|
|
|
|
void spr_update_player_raster_cache(void) {
|
|
s32 i;
|
|
|
|
func_8013A4D0();
|
|
|
|
for (i = 0; i < PlayerRasterCacheSize; i++) {
|
|
if (PlayerRasterCache[i].lazyDeleteTime != 0) {
|
|
PlayerRasterCache[i].lazyDeleteTime--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void spr_load_npc_extra_anims(SpriteAnimData* header, u32* extraAnimList) {
|
|
u8* src;
|
|
s32 imgID;
|
|
s32 rasterSize;
|
|
s32 remaining;
|
|
u16 animCmd;
|
|
u16* cmdList;
|
|
u32 extraAnimID;
|
|
u8* dataPos;
|
|
void* copyEnd;
|
|
SpriteAnimComponent* comp;
|
|
SpriteAnimComponent** compList;
|
|
void* writePos;
|
|
SpriteRasterCacheEntry** rasterList;
|
|
SpriteRasterCacheEntry* raster;
|
|
u16** oldPalList;
|
|
u16* palette;
|
|
// one extra required for 'done' sentinel
|
|
s32 sawRaster[100 + 1];
|
|
s32 i;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(sawRaster) - 1; i++) {
|
|
sawRaster[i] = FALSE;
|
|
}
|
|
|
|
while ((extraAnimID = *extraAnimList++) != -1) {
|
|
compList = header->animListStart[extraAnimID & 0xFF];
|
|
while ((comp = *compList++) != PTR_LIST_END) {
|
|
cmdList = comp->cmdList;
|
|
remaining = (s16) comp->cmdListSize / 2;
|
|
while (remaining > 0) {
|
|
animCmd = *cmdList++;
|
|
remaining--;
|
|
switch (animCmd & 0xF000) {
|
|
case 0x1000:
|
|
i = animCmd; // required to match
|
|
imgID = i & 0xFF;
|
|
if (imgID < ARRAY_COUNT(sawRaster) - 1) {
|
|
sawRaster[imgID] = TRUE;
|
|
}
|
|
break;
|
|
case 0x3000:
|
|
cmdList++;
|
|
remaining--;
|
|
// fallthrough
|
|
case 0x4000:
|
|
cmdList++;
|
|
remaining--;
|
|
// fallthrough
|
|
case 0x7000:
|
|
case 0x5000:
|
|
cmdList++;
|
|
remaining--;
|
|
// fallthrough
|
|
case 0x0000:
|
|
case 0x2000:
|
|
case 0x6000:
|
|
case 0x8000:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
rasterList = header->rastersOffset;
|
|
raster = *rasterList;
|
|
dataPos = raster->image;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(sawRaster) - 1; i++) {
|
|
if ((raster = *rasterList) == PTR_LIST_END) {
|
|
break;
|
|
}
|
|
if (sawRaster[i]) {
|
|
src = raster->image;
|
|
rasterSize = (raster->width * raster->height) / 2;
|
|
copyEnd = &dataPos[rasterSize];
|
|
rasterSize += 8;
|
|
if (dataPos != src) {
|
|
raster->image = dataPos;
|
|
bcopy(src, dataPos, rasterSize);
|
|
}
|
|
*rasterList = copyEnd;
|
|
dataPos += rasterSize;
|
|
}
|
|
rasterList++;
|
|
}
|
|
// sentinel value to mark end of valid data
|
|
sawRaster[i] = TRUE;
|
|
|
|
writePos = dataPos;
|
|
|
|
// copy raster list
|
|
rasterList = header->rastersOffset;
|
|
header->rastersOffset = writePos;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(sawRaster) - 1; i++) {
|
|
raster = *rasterList++;
|
|
if (sawRaster[i]) {
|
|
*(SpriteRasterCacheEntry**) writePos = raster;
|
|
} else {
|
|
*(SpriteRasterCacheEntry**) writePos = (SpriteRasterCacheEntry*) copyEnd;
|
|
}
|
|
writePos += 4;
|
|
if (raster == PTR_LIST_END) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// copy palette list
|
|
oldPalList = header->palettesOffset;
|
|
header->palettesOffset = writePos;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(sawRaster) - 1; i++) {
|
|
raster = (SpriteRasterCacheEntry*)*oldPalList++; // required to match
|
|
*(u16**)writePos = (u16*)raster;
|
|
writePos += 4;
|
|
if (raster == PTR_LIST_END) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
_heap_realloc(&heap_spriteHead, header, (s32)writePos - (s32)header);
|
|
}
|
|
|
|
SpriteComponent** spr_allocate_components(s32 count) {
|
|
s32 listSize;
|
|
SpriteComponent** listStart;
|
|
SpriteComponent* component;
|
|
SpriteComponent** listPos;
|
|
u32 totalSize;
|
|
s32 i;
|
|
|
|
// data will contain a -1 terminated list, followed by the SpriteComponents
|
|
// corresponding to that list
|
|
listSize = (count + 1) * 4;
|
|
totalSize = (count * sizeof(SpriteComponent)) + listSize;
|
|
|
|
if (spr_allocateBtlComponentsOnWorldHeap) {
|
|
listStart = _heap_malloc(&heap_generalHead, totalSize);
|
|
listPos = listStart;
|
|
component = (SpriteComponent*) listPos;
|
|
} else {
|
|
listStart = _heap_malloc(&heap_spriteHead, totalSize);
|
|
listPos = listStart;
|
|
component = (SpriteComponent*) listPos;
|
|
}
|
|
|
|
component = (SpriteComponent*)((s32)(component) + (listSize / 4) * 4);
|
|
|
|
// fill list values
|
|
for (i = 0; i < count; i++) {
|
|
*listPos++ = component;
|
|
component++;
|
|
}
|
|
*listPos = PTR_LIST_END;
|
|
|
|
return listStart;
|
|
}
|