// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. // See LICENSE.md for license information. // SPDX-License-Identifier: MIT // // tileBankExpect.c - the pixels a correct load of the tile-bank fixture // must show, decoded straight from its indexed PNG (independent of // assetbake's encoders), for tests/host/tileBankStage.sh: // tileCount LE16, the first 16 palette entries as LE16 $0RGB, then each // tile's 64 colour indices (tiles row-major across the sheet, each tile // row-major) // // Usage: tileBankExpect PNG OUT #include #include #include #include "toolBuf.h" #include "toolFile.h" #include "toolPng.h" #define TOOL_NAME "tileBankExpect" #define TILE_PX 8u #define COLORS 16u #define NIBBLE_BITS 4u #define RED_SHIFT 8u int main(int argc, char **argv) { ToolImageT img; ToolBufT out; char err[TOOL_PNG_ERROR_BYTES]; uint32_t i; uint32_t tx; uint32_t ty; uint32_t x; uint32_t y; toolFileName(TOOL_NAME); if (argc != 3) { fprintf(stderr, "usage: %s PNG OUT\n", TOOL_NAME); return 2; } if (!toolPngLoad(argv[1], &img, err)) { toolFail("%s: %s", argv[1], err); } if (!img.indexed) { toolFail("%s is not an indexed PNG", argv[1]); } memset(&out, 0, sizeof(out)); toolBufLe16(&out, (img.width / TILE_PX) * (img.height / TILE_PX)); for (i = 0; i < COLORS; i++) { if (i < img.paletteCount) { toolBufLe16(&out, ((uint32_t)(img.palette[i][0] >> NIBBLE_BITS) << RED_SHIFT) | ((uint32_t)(img.palette[i][1] >> NIBBLE_BITS) << NIBBLE_BITS) | (uint32_t)(img.palette[i][2] >> NIBBLE_BITS)); } else { toolBufLe16(&out, 0u); } } for (ty = 0; ty + TILE_PX <= img.height; ty += TILE_PX) { for (tx = 0; tx + TILE_PX <= img.width; tx += TILE_PX) { for (y = 0; y < TILE_PX; y++) { for (x = 0; x < TILE_PX; x++) { toolBufByte(&out, img.pixels[(size_t)(ty + y) * img.width + tx + x]); } } } } if (!toolWriteFile(argv[2], out.data, out.len)) { toolFail("cannot write %s", argv[2]); } toolBufFree(&out); toolImageFree(&img); return 0; }