Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
101b90_len_8f0.c
Go to the documentation of this file.
1#include "common.h"
2#include "sprite.h"
3#include "nu/nusys.h"
4#include "ld_addrs.h"
5#include "sprite/player.h"
6
7#ifdef SHIFT
8#define SPRITE_ROM_START (u32) sprites_ROM_START + 0x10
9#elif VERSION_US || VERSION_IQUE
10#define SPRITE_ROM_START 0x1943000 + 0x10
11#elif VERSION_PAL
12#define SPRITE_ROM_START 0x1DF0000 + 0x10
13#elif VERSION_JP
14#define SPRITE_ROM_START 0x1A40000 + 0x10
15#endif
16
20
22BSS s32 PlayerRasterLoadDescBuffer[101]; //NOTE: maximum rasters supported for a single player sprite is 101
24BSS s32 PlayerRasterLoadDescBeginSpriteIndex[SPR_Peach3]; //TODO size linked to number of player sprites
25BSS s32 PlayerRasterLoadDesc[0x2E0]; // correct length?
26
28BSS s32 PlayerSpriteRasterSets[SPR_Peach3 + 1]; //TODO size linked to number of player sprites
33
34#define ALIGN4(v) (((u32)(v) >> 2) << 2)
35#define SPR_SWIZZLE(base,offset) ((void*)((s32)(offset) + (s32)(base)))
36
37void spr_swizzle_anim_offsets(s32 arg0, s32 base, void* spriteData) {
38 SpriteAnimComponent*** animList;
39 SpriteAnimComponent** compList;
41
42 // required to match, spriteData->animList would be nicer
43 animList = (SpriteAnimComponent***) spriteData;
44 animList += 4;
45
46 while (true) {
47 if (*animList == PTR_LIST_END) {
48 break;
49 }
50 compList = (SpriteAnimComponent**) ((s32)*animList - ALIGN4(base));
51 compList = SPR_SWIZZLE(ALIGN4(spriteData), compList);
52 *animList = compList;
53 while (true) {
54 if (*compList == PTR_LIST_END) {
55 break;
56 }
57 *compList = comp = SPR_SWIZZLE(ALIGN4(spriteData), (s32)*compList - ALIGN4(base));
58 comp->cmdList = SPR_SWIZZLE(ALIGN4(spriteData), (s32)comp->cmdList - ALIGN4(base));
59 compList++;
60 }
61 animList++;
62 }
63}
64
65SpriteAnimData* spr_load_sprite(s32 idx, s32 isPlayerSprite, s32 useTailAlloc) {
66 SpriteAnimData* animData;
67 s32 base;
68 s32 i;
69 s32 compressedSize;
70 s32* ptr1;
71 IMG_PTR image;
72 s32 count;
73 s32** data;
74 s32** palettes;
75
76 if (isPlayerSprite) {
77 base = SpriteDataHeader[1];
78 } else {
79 base = SpriteDataHeader[2];
80 }
81
82 // read current and next sprite offsets, so we can find the difference
83 nuPiReadRom(base + idx * 4, &spr_asset_entry, sizeof(spr_asset_entry));
84
85 compressedSize = ALIGN8(spr_asset_entry[1] - spr_asset_entry[0]);
86 data = general_heap_malloc(compressedSize);
87 nuPiReadRom(base + spr_asset_entry[0], data, compressedSize);
88
89 ptr1 = (s32*)data;
90 // skip 4 bytes: 'YAY0' signature
91 ptr1++;
92
93 if (useTailAlloc) {
94 animData = _heap_malloc_tail(&heap_spriteHead, *ptr1);
95 } else {
96 animData = _heap_malloc(&heap_spriteHead, *ptr1);
97 }
98 ASSERT_MSG(animData, "out of sprite memory");
99 decode_yay0(data, animData);
100 general_heap_free(data);
101
102 // swizzle raster array
103 data = (s32**)animData->rastersOffset;
104 data = SPR_SWIZZLE(ALIGN4(animData), data);
105 animData->rastersOffset = (SpriteRasterCacheEntry**)data;
106
107 while (true) {
108 ptr1 = *data;
109 if (ptr1 == PTR_LIST_END) {
110 break;
111 }
112 // swizzle each raster cache entry
113 ptr1 = SPR_SWIZZLE(ALIGN4(animData), ptr1);
114 *data++ = ptr1;
115 image = ((SpriteRasterCacheEntry*)ptr1)->image;
116
117 if (!isPlayerSprite) {
118 // swizzle image pointer in the cache entry
119 image = SPR_SWIZZLE(ALIGN4(animData), image);
120 *ptr1 = (s32)image;
121 }
122 }
123
124 if (isPlayerSprite) {
126 count = PlayerSpriteRasterSets[idx + 1] - PlayerSpriteRasterSets[idx];
127 // load a range of raster loading desciptors to a buffer and copy contents into PlayerRasterLoadDesc
130 for (i = 0; i < count; i++) {
132 }
133 }
134
135 // swizzle palettes array
136 palettes = SPR_SWIZZLE(ALIGN4(animData), animData->palettesOffset);
137 animData->palettesOffset = (PAL_PTR*)palettes;
138 while (true) {
139 ptr1 = *palettes;
140 if (ptr1 == PTR_LIST_END) {
141 break;
142 }
143 // swizzle each palette pointer
144 ptr1 = SPR_SWIZZLE(ALIGN4(animData), ptr1);
145 *palettes++ = ptr1;
146 }
147
148 spr_swizzle_anim_offsets(0, 0, animData);
149 return animData;
150}
151
152void spr_init_player_raster_cache(s32 cacheSize, s32 maxRasterSize) {
153 void* raster;
154 s32 i;
155
156 nuPiReadRom(SPRITE_ROM_START, &SpriteDataHeader, sizeof(SpriteDataHeader));
157 PlayerRasterCacheSize = cacheSize;
158 PlayerRasterMaxSize = maxRasterSize;
159 SpriteDataHeader[0] += SPRITE_ROM_START;
160 SpriteDataHeader[1] += SPRITE_ROM_START;
161 SpriteDataHeader[2] += SPRITE_ROM_START;
162 raster = _heap_malloc(&heap_spriteHead, maxRasterSize * cacheSize);
163
164 for (i = 0; i < ARRAY_COUNT(PlayerRasterCache); i++) {
165 PlayerRasterCache[i].raster = raster;
166 raster += PlayerRasterMaxSize;
170 }
171
174 }
176 nuPiReadRom(SpriteDataHeader[0], &PlayerRasterHeader, sizeof(PlayerRasterHeader));
178}
179
180IMG_PTR spr_get_player_raster(s32 rasterIndex, s32 playerSpriteID) {
181 PlayerSpriteCacheEntry* cacheEntry;
182 u32 playerRasterInfo;
183 s32 idx = -1;
184 s32 i;
185
186 for (i = 0; i < PlayerRasterCacheSize; i++) {
187 if (PlayerRasterCache[i].lazyDeleteTime != 0) {
188 if (PlayerRasterCache[i].rasterIndex == rasterIndex && PlayerRasterCache[i].spriteIndex == playerSpriteID) {
190 return PlayerRasterCache[i].raster;
191 }
192 } else if (idx == -1) {
193 idx = i;
194 }
195 }
196
197 if (idx == -1) {
198 return nullptr;
199 }
200
201 cacheEntry = &PlayerRasterCache[idx];
202 cacheEntry->rasterIndex = rasterIndex;
203 cacheEntry->spriteIndex = playerSpriteID;
204 cacheEntry->lazyDeleteTime = 2;
205
206 // each player raster load descriptor has image size (in bytes) and relative offset packed into one word
207 // upper three nibbles give size / 16, lower 5 give offset
208 playerRasterInfo = PlayerRasterLoadDesc[PlayerRasterLoadDescBeginSpriteIndex[playerSpriteID] + rasterIndex];
209 nuPiReadRom(SpriteDataHeader[0] + (playerRasterInfo & 0xFFFFF), cacheEntry->raster, (playerRasterInfo >> 0x10) & 0xFFF0);
210 return cacheEntry->raster;
211}
212
214 s32 i;
215
217
218 for (i = 0; i < PlayerRasterCacheSize; i++) {
219 if (PlayerRasterCache[i].lazyDeleteTime != 0) {
221 }
222 }
223}
224
225void spr_load_npc_extra_anims(SpriteAnimData* header, u32* extraAnimList) {
226 u8* src;
227 s32 imgID;
228 s32 rasterSize;
229 s32 remaining;
230 u16 animCmd;
231 u16* cmdList;
232 u32 extraAnimID;
233 u8* dataPos;
234 void* copyEnd;
236 SpriteAnimComponent** compList;
237 void* writePos;
238 SpriteRasterCacheEntry** rasterList;
240 PAL_PTR* oldPalList;
241 // one extra required for 'done' sentinel
242 s32 sawRaster[100 + 1];
243 s32 i;
244
245 for (i = 0; i < ARRAY_COUNT(sawRaster) - 1; i++) {
246 sawRaster[i] = false;
247 }
248
249 while ((extraAnimID = *extraAnimList++) != -1) {
250 compList = header->animListStart[extraAnimID & 0xFF];
251 while ((comp = *compList++) != PTR_LIST_END) {
252 cmdList = comp->cmdList;
253 remaining = (s16) comp->cmdListSize / 2;
254 while (remaining > 0) {
255 animCmd = *cmdList++;
256 remaining--;
257 switch (animCmd & 0xF000) {
258 case 0x1000:
259 i = animCmd; // required to match
260 imgID = i & 0xFF;
261 if (imgID < ARRAY_COUNT(sawRaster) - 1) {
262 sawRaster[imgID] = true;
263 }
264 break;
265 case 0x3000:
266 cmdList++;
267 remaining--;
268 // fallthrough
269 case 0x4000:
270 cmdList++;
271 remaining--;
272 // fallthrough
273 case 0x7000:
274 case 0x5000:
275 cmdList++;
276 remaining--;
277 // fallthrough
278 case 0x0000:
279 case 0x2000:
280 case 0x6000:
281 case 0x8000:
282 break;
283 }
284 }
285 }
286 }
287
288 rasterList = header->rastersOffset;
289 raster = *rasterList;
290 dataPos = raster->image;
291
292 for (i = 0; i < ARRAY_COUNT(sawRaster) - 1; i++) {
293 if ((raster = *rasterList) == PTR_LIST_END) {
294 break;
295 }
296 if (sawRaster[i]) {
297 src = raster->image;
298 rasterSize = (raster->width * raster->height) / 2;
299 copyEnd = &dataPos[rasterSize];
300 rasterSize += 8;
301 if (dataPos != src) {
302 raster->image = dataPos;
303 bcopy(src, dataPos, rasterSize);
304 }
305 *rasterList = copyEnd;
306 dataPos += rasterSize;
307 }
308 rasterList++;
309 }
310 // sentinel value to mark end of valid data
311 sawRaster[i] = true;
312
313 writePos = dataPos;
314
315 // copy raster list
316 rasterList = header->rastersOffset;
317 header->rastersOffset = writePos;
318
319 for (i = 0; i < ARRAY_COUNT(sawRaster) - 1; i++) {
320 raster = *rasterList++;
321 if (sawRaster[i]) {
322 *(SpriteRasterCacheEntry**) writePos = raster;
323 } else {
324 *(SpriteRasterCacheEntry**) writePos = (SpriteRasterCacheEntry*) copyEnd;
325 }
326 writePos += 4;
327 if (raster == PTR_LIST_END) {
328 break;
329 }
330 }
331
332 // copy palette list
333 oldPalList = header->palettesOffset;
334 header->palettesOffset = writePos;
335
336 for (i = 0; i < ARRAY_COUNT(sawRaster) - 1; i++) {
337 raster = (SpriteRasterCacheEntry*)*oldPalList++; // required to match
338 *(u16**)writePos = (u16*)raster;
339 writePos += 4;
340 if (raster == PTR_LIST_END) {
341 break;
342 }
343 }
344
345 _heap_realloc(&heap_spriteHead, header, (s32)writePos - (s32)header);
346}
347
349 s32 listSize;
350 SpriteComponent** listStart;
351 SpriteComponent* component;
352 SpriteComponent** listPos;
353 u32 totalSize;
354 s32 i;
355
356 // data will contain a -1 terminated list, followed by the SpriteComponents
357 // corresponding to that list
358 listSize = (count + 1) * 4;
359 totalSize = (count * sizeof(SpriteComponent)) + listSize;
360
362 listStart = _heap_malloc(&heap_generalHead, totalSize);
363 listPos = listStart;
364 component = (SpriteComponent*) listPos;
365 } else {
366 listStart = _heap_malloc(&heap_spriteHead, totalSize);
367 listPos = listStart;
368 component = (SpriteComponent*) listPos;
369 }
370
371 component = (SpriteComponent*)((s32)(component) + (listSize / 4) * 4);
372
373 // fill list values
374 for (i = 0; i < count; i++) {
375 *listPos++ = component;
376 component++;
377 }
378 *listPos = PTR_LIST_END;
379
380 return listStart;
381}
BSS PlayerRastersHeader PlayerRasterHeader
IMG_PTR spr_get_player_raster(s32 rasterIndex, s32 playerSpriteID)
BSS s32 PlayerRasterCacheSize
BSS s32 spr_asset_entry[2]
#define ALIGN4(v)
void spr_update_player_raster_cache(void)
BSS s32 PlayerRasterMaxSize
SpriteComponent ** spr_allocate_components(s32 count)
void spr_load_npc_extra_anims(SpriteAnimData *header, u32 *extraAnimList)
#define SPR_SWIZZLE(base, offset)
BSS s32 SpriteDataHeader[3]
BSS s32 PlayerRasterLoadDescBuffer[101]
SpriteAnimData * spr_load_sprite(s32 idx, s32 isPlayerSprite, s32 useTailAlloc)
HeapNode heap_generalHead
Definition heaps3.c:3
b32 SpriteUseGeneralHeap
Definition sprite.c:10
HeapNode heap_spriteHead
Definition heaps3.c:4
BSS s32 PlayerRasterLoadDesc[0x2E0]
BSS s32 PlayerSpriteRasterSets[SPR_Peach3+1]
BSS s32 PlayerRasterLoadDescNumLoaded
BSS s32 PlayerRasterLoadDescBeginSpriteIndex[SPR_Peach3]
BSS PlayerSpriteCacheEntry PlayerRasterCache[18]
void spr_init_player_raster_cache(s32 cacheSize, s32 maxRasterSize)
void spr_swizzle_anim_offsets(s32 arg0, s32 base, void *spriteData)
#define PAL_PTR
#define IMG_PTR
s32 b32
#define general_heap_malloc
void * _heap_malloc(HeapNode *head, u32 size)
Definition 43F0.c:77
void * _heap_malloc_tail(HeapNode *head, u32 size)
Definition 43F0.c:151
void * _heap_realloc(HeapNode *heapNodeList, void *addr, u32 newSize)
Definition 43F0.c:284
s32 general_heap_free(void *data)
Definition heap.c:18
void decode_yay0(void *src, void *dst)
void func_8013A4D0(void)
Definition imgfx.c:266
#define BSS
Definition macros.h:6
#define ARRAY_COUNT(arr)
Definition macros.h:39
#define ASSERT_MSG(condition, msg, args...)
Definition macros.h:65
#define PTR_LIST_END
Definition macros.h:41
#define ALIGN8(val)
Definition macros.h:20
SpriteAnimComponent ** animListStart[VLA]
Definition sprite.h:83
SpriteRasterCacheEntry ** rastersOffset
Definition sprite.h:79
PAL_PTR * palettesOffset
Definition sprite.h:80
Sprite data header.
Definition sprite.h:78