return true;
}
+static void renderChunkCel(uint8_t *outData, ASE_SHORT *zBuffer, BZMemoryArenaID arena, BZResourceID handle, ASE_WORD layerIndex, const ASE_Header *header, size_t pixelDataSize, size_t frameIdx, size_t frameStartPositions[]) {
+ bzResourcesSeek(handle, frameStartPositions[frameIdx]);
+
+ ASE_Frame frame;
+ ASE_DWORD numChunks;
+ readASEFrame(&frame, &numChunks, handle);
+
+ for (ASE_DWORD chunkIdx = 0; chunkIdx < numChunks; ++chunkIdx) {
+ size_t chunkStartPosition = bzResourcesTell(handle);
+
+ ASE_Chunk chunk;
+ bzResourcesReadBytes(handle, &chunk, sizeof(chunk));
+
+ if (chunk.type == ASE_ChunkType_CelChunk) {
+ ASE_Chunk_Cel cel;
+ bzResourcesReadBytes(handle, &cel, sizeof(cel));
+
+ if (cel.layerIndex == layerIndex) {
+ if (cel.celType == ASE_Chunk_Cel_CelType_LinkedCel) {
+ ASE_Chunk_Cel_LinkedCel linkedCel;
+ bzResourcesReadBytes(handle, &linkedCel, sizeof(linkedCel));
+ renderChunkCel(outData, zBuffer, arena, handle, layerIndex, header, pixelDataSize, linkedCel.framePosition, frameStartPositions);
+ } else if (cel.celType == ASE_Chunk_Cel_CelType_CompressedImage) {
+ bzMemoryArenaPushWatermark(arena);
+
+ ASE_Chunk_Cel_CompressedImage image;
+ bzResourcesReadBytes(handle, &image, sizeof(image));
+
+ size_t compressedSize = chunk.chunkSize - sizeof(ASE_Chunk_Cel_CompressedImage) - sizeof(ASE_Chunk_Cel) - sizeof(ASE_Chunk);
+ int8_t *compressedData = bzMemoryAlloc(arena, compressedSize); // If we do this on the stack (alloca) the Playdate will explode!
+ bzResourcesReadBytes(handle, compressedData, compressedSize);
+
+ size_t imagePixelDataSize = image.pixelWidth * image.pixelHeight * pixelDataSize;
+ int8_t *imagePixelData = bzMemoryAlloc(arena, imagePixelDataSize);
+ stbi_zlib_decode_buffer(imagePixelData, imagePixelDataSize, compressedData, compressedSize);
+
+ for (size_t y = 0; y < image.pixelHeight; ++y) {
+ for (size_t x = 0; x < image.pixelWidth; ++x) {
+ size_t outX = cel.positionX + x;
+ size_t outY = cel.positionY + y;
+
+ //ASE_SHORT *currentZ = &zBuffer[outY * header->width + outX];
+ //if (*currentZ > layerIndex) {
+ for (size_t i = 0; i < pixelDataSize; ++i) {
+ uint8_t pixelData = imagePixelData[(y * image.pixelWidth + x) * pixelDataSize + i];
+ if (pixelData > 0) { // FIXME, alpha...
+ outData[outY * header->width + outX * pixelDataSize + i] = pixelData;
+ }
+ }
+ //*currentZ = layerIndex;//cel.zIndex;
+ //}
+ }
+ }
+
+ bzMemoryArenaPopWatermark(arena);
+ }
+
+ // Found what we needed to render...
+ break;
+ }
+ }
+
+ bzResourcesSeek(handle, chunkStartPosition + chunk.chunkSize);
+ }
+}
+
+static bool renderCelsForLayer(uint8_t *outData, ASE_SHORT *zBuffer, BZMemoryArenaID arena, BZResourceID handle, ASE_WORD layerIndex, const ASE_Header *header, size_t pixelDataSize) {
+ size_t framesStartPosition = bzResourcesTell(handle);
+
+ // Layers are .. complicated, you only really need to read them for the first frame...
+ ASE_Frame firstFrame;
+ ASE_DWORD firstFrameChunks;
+ readASEFrame(&firstFrame, &firstFrameChunks, handle);
+
+ bool layerExists = false;
+ bool layerVisible = false;
+ for (ASE_DWORD chunkIdx = 0, layerCount = 0; chunkIdx < firstFrameChunks; ++chunkIdx) {
+ size_t chunkStartPosition = bzResourcesTell(handle);
+
+ ASE_Chunk chunk;
+ bzResourcesReadBytes(handle, &chunk, sizeof(chunk));
+
+ if (chunk.type == ASE_ChunkType_LayerChunk) {
+ ASE_Chunk_Layer layer;
+ bzResourcesReadBytes(handle, &layer, sizeof(layer));
+
+ if (layerCount == layerIndex) {
+ layerExists = true;
+ layerVisible = (layer.flags & 1) > 0; // FIXME, named flag
+ break;
+ } else {
+ layerCount++;
+ }
+ }// else {
+ // Skip this chunk...
+ bzResourcesSeek(handle, chunkStartPosition + chunk.chunkSize);
+ //}
+ }
+
+ if (layerExists && layerVisible) {
+ bzResourcesSeek(handle, framesStartPosition);
+
+ size_t *frameStartPositions = alloca(header->frames * sizeof(size_t)); // FIXME, alloca -> tmp
+
+ for (ASE_WORD frameIdx = 0; frameIdx < header->frames; ++frameIdx) {
+ frameStartPositions[frameIdx] = bzResourcesTell(handle);
+
+ ASE_Frame frame;
+ ASE_DWORD numChunks;
+ readASEFrame(&frame, &numChunks, handle);
+
+ for (ASE_DWORD chunkIdx = 0; chunkIdx < numChunks; ++chunkIdx) {
+ size_t chunkStartPosition = bzResourcesTell(handle);
+
+ ASE_Chunk chunk;
+ bzResourcesReadBytes(handle, &chunk, sizeof(chunk));
+
+ if (chunk.type == ASE_ChunkType_CelChunk) {
+ uint8_t *frameOutData = &outData[frameIdx * header->height * header->width * pixelDataSize];
+ ASE_SHORT *frameZBuffer = NULL;//&zBuffer[frameIdx * header->height * header->width * sizeof(ASE_SHORT)];
+ renderChunkCel(frameOutData, frameZBuffer, arena, handle, layerIndex, header, pixelDataSize, frameIdx, frameStartPositions);
+ }
+
+ bzResourcesSeek(handle, chunkStartPosition + chunk.chunkSize);
+ }
+ }
+ }
+
+ return layerExists;
+}
+
void *bzGfxLoadAsepriteImage(BZMemoryArenaID arena, size_t *framesOut, size_t *widthOut, size_t *heightOut, const char *identifierFmt, ...) {
bzMakeIdentifier(identifier, identifierFmt);
BZResourceID handle = bzResourcesOpenResource("sprite", "assets/sprites/%s.aseprite", identifier);
- //PHYSFS_sint64 length = PHYSFS_fileLength(handle);
- //void *data = alloca(length);
- //PHYSFS_readBytes(handle, data, length);
ASE_Header header;
readASEHeader(&header, handle);
break;
default:
- assert(false);//, "Invalid image");
+ bzAssertMessage(false, "Invalid image");
break;
}
- uint8_t *outData = (uint8_t *)bzMemoryAlloc(arena, header.frames * header.width * header.height * pixelDataSize); // Side by side loading needs to happen...
+ uint8_t *outData = (uint8_t *)bzMemoryAlloc(arena, header.frames * header.height * header.width * pixelDataSize); // Side by side loading needs to happen...
*framesOut = (size_t)header.frames;
*widthOut = (size_t)header.width;
*heightOut = (size_t)header.height;
- bzMemoryArenaPushWatermark(arena);
- size_t zBufferSize = header.width * header.height * sizeof(ASE_SHORT);
- ASE_SHORT *zBuffer = (ASE_SHORT *)bzMemoryAlloc(arena, zBufferSize);
+ //bzMemoryArenaPushWatermark(arena);
+ ASE_SHORT *zBuffer = NULL;//(ASE_SHORT *)bzMemoryAlloc(arena, header.frames * header.height * header.width * sizeof(ASE_SHORT));
+ //memset(zBuffer, 0, header.frames * header.height * header.width * sizeof(ASE_SHORT)); // FIXME
- size_t frameImageSize = header.width * header.height * pixelDataSize;
-
- for (ASE_WORD frameIdx = 0; frameIdx < header.frames; ++frameIdx) {
- ASE_Frame frame;
- ASE_DWORD numChunks = 0;
- readASEFrame(&frame, &numChunks, handle);
- bzLog("FRAME %d: %d chunks", frameIdx, numChunks);
+ size_t startPosition = bzResourcesTell(handle);
+ for (ASE_WORD layerIndex = 0; ; ++layerIndex) {
+ // Reset...
+ bzResourcesSeek(handle, startPosition);
- memset(zBuffer, 0, zBufferSize);
-
- bool layerVisible[16];
- size_t nextLayer = 0;
-
- size_t layerStartOffset[16];
-
- for (ASE_DWORD chunk = 0; chunk < numChunks; ++chunk) {
- size_t chunkStartPosition = bzResourcesTell(handle);
-
- ASE_Chunk chunk;
- bzResourcesReadBytes(handle, &chunk, sizeof(chunk));
-
- switch (chunk.type) {
- case ASE_ChunkType_LayerChunk: {
- bzLog("LAYER %d: %d chunks", frameIdx, numChunks);
-
-
- ASE_Chunk_Layer layer;
- bzResourcesReadBytes(handle, &layer, sizeof(layer));
-
- layerVisible[nextLayer] = (layer.flags & 1) > 0;
- ++nextLayer;
-
- bzResourcesSeek(handle, chunkStartPosition + chunk.chunkSize);
- break;
- }
-
- case ASE_ChunkType_CelChunk: {
- bzLog("CELL %d: %d chunks", frameIdx, numChunks);
- ASE_Chunk_Cel cel;
- bzResourcesReadBytes(handle, &cel, sizeof(cel));
-
-///// ASE_Chunk_Cel_CelType_LinkedCel aaaahhh
-
- if (layerVisible[cel.layerIndex] && cel.celType == ASE_Chunk_Cel_CelType_CompressedImage) {
- bzMemoryArenaPushWatermark(arena);
-
- ASE_Chunk_Cel_CompressedImage image;
- bzResourcesReadBytes(handle, &image, sizeof(image));
-
- size_t compressedSize = chunk.chunkSize - sizeof(ASE_Chunk_Cel_CompressedImage) - sizeof(ASE_Chunk_Cel) - sizeof(ASE_Chunk);
- int8_t *compressedData = bzMemoryAlloc(arena, compressedSize); // If we do this on the stack (alloca) the Playdate will explode!
- bzResourcesReadBytes(handle, compressedData, compressedSize);
-
- size_t imagePixelDataSize = image.pixelWidth * image.pixelHeight * pixelDataSize;
- int8_t *imagePixelData = bzMemoryAlloc(arena, imagePixelDataSize);
- stbi_zlib_decode_buffer(imagePixelData, imagePixelDataSize, compressedData, compressedSize);
-
- for (size_t y = 0; y < image.pixelHeight; ++y) {
- for (size_t x = 0; x < image.pixelWidth; ++x) {
- size_t outX = cel.positionX + x;
- size_t outY = cel.positionY + y;
-
- ASE_SHORT *currentZ = &zBuffer[outY * header.width + outX];
-
- if (*currentZ <= cel.zIndex) {
- for (size_t i = 0; i < pixelDataSize; ++i) {
- uint8_t pixelData = imagePixelData[(y * image.pixelWidth + x) * pixelDataSize + i];
- if (pixelData > 0) { // FIXME, alpha...
- outData[frameIdx * frameImageSize + (outY * header.width + outX) * pixelDataSize + i] = pixelData;
- }
- }
- *currentZ = cel.zIndex;
- }
- }
- }
-
- bzMemoryArenaPopWatermark(arena);
- } else {
- // Skip this chunk...
- bzResourcesSeek(handle, chunkStartPosition + chunk.chunkSize);
- }
-
- break;
- }
-
- default:
- // Skip this chunk...
- bzResourcesSeek(handle, chunkStartPosition + chunk.chunkSize);
- break;
- }
+ bool rendered = renderCelsForLayer(outData, zBuffer, arena, handle, layerIndex, &header, pixelDataSize);
+ if (rendered == false) {
+ break;
}
}
-
- bzMemoryArenaPopWatermark(arena);
- bzResourcesCloseResource(handle);
+ //bzMemoryArenaPopWatermark(arena);
return outData;
}
size_t bzGfxLoadAsepritePalette(uint32_t *colorsOut, size_t maxColors, const char *filename) {
- BZResourceID handle = bzResourcesOpenResource("palette", "assets/palettes/%s", filename);
+ BZResourceID handle = bzResourcesOpenResource("palette", "assets/palettes/%s.aseprite", filename);
ASE_Header header;
readASEHeader(&header, handle);
for (ASE_WORD frame = 0; frame < header.frames; ++frame) {
ASE_Frame frame;
- bzResourcesReadBytes(handle, &frame, sizeof(frame));
-
- ASE_DWORD numChunks = frame.___numChunks;
-
- if (numChunks == 0xFFFF) {
- numChunks = frame.numChunks;
- if (numChunks == 0) {
- numChunks = frame.___numChunks; // See docs.
- }
- }
+ ASE_DWORD numChunks;
+ readASEFrame(&frame, &numChunks, handle);
for (ASE_DWORD chunk = 0; chunk < numChunks; ++chunk) {
size_t chunkStartPosition = bzResourcesTell(handle);