503 lines
19 KiB
C
503 lines
19 KiB
C
// tileBankHost.c - Host-cc gate for the baked tile-bank loaders,
|
|
// jlTileBankLoad and jlTileBankLoadToSurface (src/core/assetLoad.c).
|
|
//
|
|
// Built by scripts/check-tilebank.sh as a whole BLANK-port program (core +
|
|
// generics + src/blank/blank.c + this file), so the REAL loader feeds the
|
|
// REAL generic tile paste and every pixel is read back through the public
|
|
// jlSamplePixel. BLANK draws chunky 4bpp like DOS and assetLoad.c expects the
|
|
// DOS target byte there, so the script stages tests/host/tileBank.png with
|
|
// tests/host/tileBankStage.py for target dos: the DOS bake is the bank that
|
|
// must load, and every other assetbake target's bake must be refused.
|
|
//
|
|
// Runs in the script's temp directory, whose DATA/ holds (the staging
|
|
// script's names and layout, shared with examples/tilebank):
|
|
// own.tbk the DOS bake of tileBank.png
|
|
// refuse<n>.tbk one bake per other target; their names arrive as argv[1..]
|
|
// expect.bin the PNG decoded by PIL, independent of assetbake's
|
|
// encoders: tileCount LE16, palette[16] LE16 $0RGB, then
|
|
// tileCount * 64 colour indices (tiles in bank order, each
|
|
// row-major)
|
|
// The malformed banks (bad magic, short header, truncated payload, no
|
|
// palette, more tiles than a surface holds) are cut from own.tbk here, so
|
|
// their parameters live beside the checks that depend on them.
|
|
//
|
|
// Prints one line per check and a final tally; exits nonzero on any failure.
|
|
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "joey/joey.h"
|
|
#include "joey/file.h"
|
|
|
|
// ----- Constants -----
|
|
|
|
#define BAD_MAGIC_BANK "badmagic.tbk"
|
|
#define BIG_BANK "big.tbk"
|
|
#define EXPECTED_FILE "expect.bin"
|
|
#define GOOD_BANK "own.tbk"
|
|
#define MISSING_BANK "missing.tbk"
|
|
#define NO_PALETTE_BANK "nopal.tbk"
|
|
#define SHORT_HEADER_BANK "shorthdr.tbk"
|
|
#define TRUNCATED_BANK "trunc.tbk"
|
|
|
|
// .tbk header fields (the format is documented in tools/assetbake/assetbake.py).
|
|
#define TBK_HEADER_BYTES 44
|
|
#define TBK_OFF_MAGIC 0
|
|
#define TBK_OFF_HAS_PALETTE 5
|
|
#define TBK_OFF_TILE_COUNT 6
|
|
|
|
#define LE16_BYTES 2
|
|
#define PALETTE_COLORS SURFACE_COLORS_PER_PALETTE
|
|
#define TILE_PIXELS (TILE_PIXELS_PER_SIDE * TILE_PIXELS_PER_SIDE)
|
|
#define SURFACE_TILE_BLOCKS (TILE_BLOCKS_PER_ROW * TILE_BLOCKS_PER_COL)
|
|
|
|
// expect.bin layout (see the header comment).
|
|
#define EXPECTED_OFF_PALETTE LE16_BYTES
|
|
#define EXPECTED_OFF_PIXELS (EXPECTED_OFF_PALETTE + PALETTE_COLORS * LE16_BYTES)
|
|
#define EXPECTED_MAX_TILES SURFACE_TILE_BLOCKS
|
|
|
|
// One tile more than a surface holds, so jlTileBankLoadToSurface's 40x25
|
|
// cap is exercised. Also the capacity of the jlTileT buffer every load uses.
|
|
#define BIG_BANK_TILES (SURFACE_TILE_BLOCKS + 1)
|
|
#define TILE_CAPACITY BIG_BANK_TILES
|
|
|
|
#define BAD_MAGIC_BYTE 'X'
|
|
#define FILL_COLOR 9u // pre-paste colour; blocks past a bank must keep it (examples/tilebank clears to the same, so its hash can match ours)
|
|
#define PALETTE_SENTINEL 0xBEEFu
|
|
#define SHORT_HEADER_BYTES (TBK_HEADER_BYTES / 2)
|
|
#define SMALL_MAX_TILES 5u
|
|
#define TILE_SENTINEL 0xA5u
|
|
#define TRUNCATED_EXTRA_BYTES (TILE_BYTES / 2) // half a tile after the last whole one
|
|
#define TRUNCATED_TILES 10u
|
|
|
|
// ----- Prototypes -----
|
|
|
|
static void check(const char *bank, const char *what, bool ok);
|
|
static bool craftBanks(void);
|
|
static bool loadExpected(void);
|
|
static bool paletteIsExpected(void);
|
|
static bool paletteUntouched(void);
|
|
static void pasteLoadedTiles(uint16_t count);
|
|
static uint16_t readLe16(const uint8_t *bytes);
|
|
static void resetBuffers(void);
|
|
static bool surfaceMatches(uint16_t tilesPasted);
|
|
static void testArgumentGuards(void);
|
|
static void testBigBank(void);
|
|
static void testGoodBank(void);
|
|
static void testMaxTiles(void);
|
|
static void testNoPalette(void);
|
|
static void testRefused(const char *bank);
|
|
static void testToSurface(void);
|
|
static void testTruncated(void);
|
|
static bool tilesUntouched(uint16_t first, uint16_t end);
|
|
static bool validRangeIs(uint16_t first, uint16_t end, bool want);
|
|
static bool writeBank(const char *name, uint32_t length);
|
|
static void writeLe16(uint8_t *bytes, uint16_t value);
|
|
|
|
// ----- State -----
|
|
|
|
static uint16_t gExpectedCount;
|
|
static uint16_t gExpectedPalette[PALETTE_COLORS];
|
|
static uint8_t gExpectedPixels[EXPECTED_MAX_TILES * TILE_PIXELS];
|
|
static uint16_t gFail = 0u;
|
|
static uint8_t gFile[TBK_HEADER_BYTES + BIG_BANK_TILES * TILE_BYTES];
|
|
static uint16_t gPalette[PALETTE_COLORS];
|
|
static uint16_t gPass = 0u;
|
|
static jlSurfaceT *gSurface = NULL;
|
|
static jlTileT gTiles[TILE_CAPACITY];
|
|
static bool gValid[TILE_CAPACITY];
|
|
|
|
|
|
static void check(const char *bank, const char *what, bool ok) {
|
|
if (ok) {
|
|
gPass++;
|
|
printf(" ok %s: %s\n", bank, what);
|
|
} else {
|
|
gFail++;
|
|
printf(" FAIL %s: %s\n", bank, what);
|
|
}
|
|
}
|
|
|
|
|
|
// Cut the malformed banks from own.tbk (see the header comment). The big
|
|
// bank goes last because it rewrites gFile's count and extends its payload.
|
|
static bool craftBanks(void) {
|
|
FILE *fp;
|
|
uint32_t goodLength;
|
|
uint16_t i;
|
|
uint8_t saved;
|
|
bool ok;
|
|
|
|
fp = jlDataOpen(GOOD_BANK, "rb");
|
|
if (fp == NULL) {
|
|
return false;
|
|
}
|
|
goodLength = (uint32_t)fread(gFile, 1, sizeof(gFile), fp);
|
|
fclose(fp);
|
|
if (goodLength != TBK_HEADER_BYTES + (uint32_t)gExpectedCount * TILE_BYTES) {
|
|
return false;
|
|
}
|
|
if (!writeBank(SHORT_HEADER_BANK, SHORT_HEADER_BYTES)) {
|
|
return false;
|
|
}
|
|
if (!writeBank(TRUNCATED_BANK, TBK_HEADER_BYTES + TRUNCATED_TILES * TILE_BYTES + TRUNCATED_EXTRA_BYTES)) {
|
|
return false;
|
|
}
|
|
|
|
saved = gFile[TBK_OFF_MAGIC];
|
|
gFile[TBK_OFF_MAGIC] = BAD_MAGIC_BYTE;
|
|
ok = writeBank(BAD_MAGIC_BANK, goodLength);
|
|
gFile[TBK_OFF_MAGIC] = saved;
|
|
if (!ok) {
|
|
return false;
|
|
}
|
|
|
|
saved = gFile[TBK_OFF_HAS_PALETTE];
|
|
gFile[TBK_OFF_HAS_PALETTE] = 0u;
|
|
ok = writeBank(NO_PALETTE_BANK, goodLength);
|
|
gFile[TBK_OFF_HAS_PALETTE] = saved;
|
|
if (!ok) {
|
|
return false;
|
|
}
|
|
|
|
// Tile i of the big bank repeats tile (i % tileCount) of the good one.
|
|
for (i = gExpectedCount; i < BIG_BANK_TILES; i++) {
|
|
memcpy(&gFile[TBK_HEADER_BYTES + (uint32_t)i * TILE_BYTES], &gFile[TBK_HEADER_BYTES + (uint32_t)(i % gExpectedCount) * TILE_BYTES], TILE_BYTES);
|
|
}
|
|
writeLe16(&gFile[TBK_OFF_TILE_COUNT], BIG_BANK_TILES);
|
|
return writeBank(BIG_BANK, TBK_HEADER_BYTES + (uint32_t)BIG_BANK_TILES * TILE_BYTES);
|
|
}
|
|
|
|
|
|
// Read expect.bin. The fixture must span more than one block row (so the
|
|
// 40-block wrap is exercised) and fewer blocks than a surface (so blocks past
|
|
// the bank can be seen keeping their prior content).
|
|
static bool loadExpected(void) {
|
|
FILE *fp;
|
|
uint8_t head[EXPECTED_OFF_PIXELS];
|
|
uint32_t pixelBytes;
|
|
uint16_t i;
|
|
bool ok;
|
|
|
|
fp = jlDataOpen(EXPECTED_FILE, "rb");
|
|
if (fp == NULL) {
|
|
return false;
|
|
}
|
|
ok = fread(head, 1, sizeof(head), fp) == sizeof(head);
|
|
if (ok) {
|
|
gExpectedCount = readLe16(head);
|
|
ok = gExpectedCount > TILE_BLOCKS_PER_ROW && gExpectedCount < SURFACE_TILE_BLOCKS;
|
|
}
|
|
if (ok) {
|
|
for (i = 0; i < PALETTE_COLORS; i++) {
|
|
gExpectedPalette[i] = readLe16(&head[EXPECTED_OFF_PALETTE + i * LE16_BYTES]);
|
|
}
|
|
pixelBytes = (uint32_t)gExpectedCount * TILE_PIXELS;
|
|
ok = fread(gExpectedPixels, 1, pixelBytes, fp) == pixelBytes && fgetc(fp) == EOF;
|
|
}
|
|
fclose(fp);
|
|
return ok;
|
|
}
|
|
|
|
|
|
static bool paletteIsExpected(void) {
|
|
return memcmp(gPalette, gExpectedPalette, sizeof(gPalette)) == 0;
|
|
}
|
|
|
|
|
|
static bool paletteUntouched(void) {
|
|
uint16_t i;
|
|
|
|
for (i = 0; i < PALETTE_COLORS; i++) {
|
|
if (gPalette[i] != PALETTE_SENTINEL) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
// Clear the surface to FILL_COLOR, then paste gTiles[0..count) in the same
|
|
// row-major block order jlTileBankLoadToSurface uses.
|
|
static void pasteLoadedTiles(uint16_t count) {
|
|
uint16_t i;
|
|
|
|
jlSurfaceClear(gSurface, FILL_COLOR);
|
|
for (i = 0; i < count; i++) {
|
|
jlTilePaste(gSurface, (uint8_t)(i % TILE_BLOCKS_PER_ROW), (uint8_t)(i / TILE_BLOCKS_PER_ROW), &gTiles[i]);
|
|
}
|
|
}
|
|
|
|
|
|
static uint16_t readLe16(const uint8_t *bytes) {
|
|
return (uint16_t)(bytes[0] | (bytes[1] << CHAR_BIT));
|
|
}
|
|
|
|
|
|
// Poison every output so a check can tell written slots from untouched ones:
|
|
// tiles and palette get sentinels, and outValid is preset TRUE so a loader
|
|
// that fails to clear it is caught.
|
|
static void resetBuffers(void) {
|
|
uint16_t i;
|
|
|
|
memset(gTiles, TILE_SENTINEL, sizeof(gTiles));
|
|
for (i = 0; i < TILE_CAPACITY; i++) {
|
|
gValid[i] = true;
|
|
}
|
|
for (i = 0; i < PALETTE_COLORS; i++) {
|
|
gPalette[i] = PALETTE_SENTINEL;
|
|
}
|
|
}
|
|
|
|
|
|
// Every pixel of gSurface: blocks below tilesPasted must show the PNG's tile
|
|
// (block % tileCount), every other block FILL_COLOR.
|
|
static bool surfaceMatches(uint16_t tilesPasted) {
|
|
int16_t x;
|
|
int16_t y;
|
|
uint16_t block;
|
|
uint8_t want;
|
|
uint8_t got;
|
|
|
|
for (y = 0; y < SURFACE_HEIGHT; y++) {
|
|
for (x = 0; x < SURFACE_WIDTH; x++) {
|
|
block = (uint16_t)((y / TILE_PIXELS_PER_SIDE) * TILE_BLOCKS_PER_ROW + x / TILE_PIXELS_PER_SIDE);
|
|
want = FILL_COLOR;
|
|
if (block < tilesPasted) {
|
|
want = gExpectedPixels[(uint32_t)(block % gExpectedCount) * TILE_PIXELS + (y % TILE_PIXELS_PER_SIDE) * TILE_PIXELS_PER_SIDE + x % TILE_PIXELS_PER_SIDE];
|
|
}
|
|
got = jlSamplePixel(gSurface, x, y);
|
|
if (got != want) {
|
|
printf(" first mismatch at (%d,%d): got %u, want %u\n", x, y, got, want);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
static void testArgumentGuards(void) {
|
|
resetBuffers();
|
|
check("args", "NULL path loads nothing", jlTileBankLoad(NULL, gTiles, TILE_CAPACITY, gValid, gPalette) == 0u);
|
|
check("args", "NULL tile buffer loads nothing", jlTileBankLoad(GOOD_BANK, NULL, TILE_CAPACITY, gValid, gPalette) == 0u);
|
|
check("args", "maxTiles 0 loads nothing", jlTileBankLoad(GOOD_BANK, gTiles, 0u, gValid, gPalette) == 0u);
|
|
check("args", "no tile written by any of those", tilesUntouched(0u, TILE_CAPACITY));
|
|
check("args", "to-surface NULL path pastes nothing", jlTileBankLoadToSurface(NULL, gSurface, gPalette) == 0u);
|
|
check("args", "to-surface NULL surface pastes nothing", jlTileBankLoadToSurface(GOOD_BANK, NULL, gPalette) == 0u);
|
|
}
|
|
|
|
|
|
static void testBigBank(void) {
|
|
uint16_t loaded;
|
|
uint16_t last;
|
|
|
|
resetBuffers();
|
|
loaded = jlTileBankLoad(BIG_BANK, gTiles, TILE_CAPACITY, gValid, gPalette);
|
|
check(BIG_BANK, "loads more tiles than a surface holds", loaded == BIG_BANK_TILES);
|
|
check(BIG_BANK, "valid true for every tile", validRangeIs(0u, BIG_BANK_TILES, true));
|
|
pasteLoadedTiles(SURFACE_TILE_BLOCKS);
|
|
check(BIG_BANK, "a surface-full of loaded tiles matches the PNG", surfaceMatches(SURFACE_TILE_BLOCKS));
|
|
last = BIG_BANK_TILES - 1u;
|
|
check(BIG_BANK, "the tile past a surface-full matches the PNG", memcmp(&gTiles[last], &gTiles[last % gExpectedCount], sizeof(jlTileT)) == 0);
|
|
|
|
jlSurfaceClear(gSurface, FILL_COLOR);
|
|
loaded = jlTileBankLoadToSurface(BIG_BANK, gSurface, gPalette);
|
|
check(BIG_BANK, "to-surface stops at a full surface", loaded == SURFACE_TILE_BLOCKS);
|
|
check(BIG_BANK, "to-surface fills the surface from the PNG", surfaceMatches(SURFACE_TILE_BLOCKS));
|
|
}
|
|
|
|
|
|
static void testGoodBank(void) {
|
|
uint16_t loaded;
|
|
|
|
resetBuffers();
|
|
loaded = jlTileBankLoad(GOOD_BANK, gTiles, TILE_CAPACITY, gValid, gPalette);
|
|
check(GOOD_BANK, "loads every tile", loaded == gExpectedCount);
|
|
check(GOOD_BANK, "valid true for the loaded slots", validRangeIs(0u, gExpectedCount, true));
|
|
check(GOOD_BANK, "valid false past the bank", validRangeIs(gExpectedCount, TILE_CAPACITY, false));
|
|
check(GOOD_BANK, "slots past the bank untouched", tilesUntouched(gExpectedCount, TILE_CAPACITY));
|
|
check(GOOD_BANK, "palette matches the PNG", paletteIsExpected());
|
|
pasteLoadedTiles(gExpectedCount);
|
|
check(GOOD_BANK, "pasted tiles match the PNG", surfaceMatches(gExpectedCount));
|
|
|
|
resetBuffers();
|
|
loaded = jlTileBankLoad(GOOD_BANK, gTiles, TILE_CAPACITY, NULL, NULL);
|
|
check(GOOD_BANK, "loads with NULL outValid and outPalette", loaded == gExpectedCount);
|
|
}
|
|
|
|
|
|
static void testMaxTiles(void) {
|
|
uint16_t loaded;
|
|
|
|
resetBuffers();
|
|
loaded = jlTileBankLoad(GOOD_BANK, gTiles, SMALL_MAX_TILES, gValid, gPalette);
|
|
check(GOOD_BANK, "a small maxTiles stops the load there", loaded == SMALL_MAX_TILES);
|
|
check(GOOD_BANK, "valid true up to maxTiles", validRangeIs(0u, SMALL_MAX_TILES, true));
|
|
check(GOOD_BANK, "valid past maxTiles untouched", validRangeIs(SMALL_MAX_TILES, TILE_CAPACITY, true));
|
|
check(GOOD_BANK, "tiles past maxTiles untouched", tilesUntouched(SMALL_MAX_TILES, TILE_CAPACITY));
|
|
pasteLoadedTiles(SMALL_MAX_TILES);
|
|
check(GOOD_BANK, "the maxTiles tiles match the PNG", surfaceMatches(SMALL_MAX_TILES));
|
|
}
|
|
|
|
|
|
static void testNoPalette(void) {
|
|
uint16_t loaded;
|
|
|
|
resetBuffers();
|
|
loaded = jlTileBankLoad(NO_PALETTE_BANK, gTiles, TILE_CAPACITY, gValid, gPalette);
|
|
check(NO_PALETTE_BANK, "loads every tile", loaded == gExpectedCount);
|
|
check(NO_PALETTE_BANK, "palette untouched", paletteUntouched());
|
|
|
|
jlSurfaceClear(gSurface, FILL_COLOR);
|
|
loaded = jlTileBankLoadToSurface(NO_PALETTE_BANK, gSurface, gPalette);
|
|
check(NO_PALETTE_BANK, "to-surface pastes every tile", loaded == gExpectedCount);
|
|
check(NO_PALETTE_BANK, "to-surface palette untouched", paletteUntouched());
|
|
}
|
|
|
|
|
|
// A refused bank loads nothing, clears outValid, and leaves the tiles, the
|
|
// palette and the surface alone.
|
|
static void testRefused(const char *bank) {
|
|
uint16_t loaded;
|
|
|
|
resetBuffers();
|
|
loaded = jlTileBankLoad(bank, gTiles, TILE_CAPACITY, gValid, gPalette);
|
|
check(bank, "refused (loads nothing)", loaded == 0u);
|
|
check(bank, "valid false everywhere", validRangeIs(0u, TILE_CAPACITY, false));
|
|
check(bank, "tiles untouched", tilesUntouched(0u, TILE_CAPACITY));
|
|
check(bank, "palette untouched", paletteUntouched());
|
|
|
|
jlSurfaceClear(gSurface, FILL_COLOR);
|
|
loaded = jlTileBankLoadToSurface(bank, gSurface, gPalette);
|
|
check(bank, "to-surface refused (pastes nothing)", loaded == 0u);
|
|
check(bank, "to-surface surface untouched", surfaceMatches(0u));
|
|
check(bank, "to-surface palette untouched", paletteUntouched());
|
|
}
|
|
|
|
|
|
static void testToSurface(void) {
|
|
uint16_t loaded;
|
|
|
|
resetBuffers();
|
|
jlSurfaceClear(gSurface, FILL_COLOR);
|
|
loaded = jlTileBankLoadToSurface(GOOD_BANK, gSurface, gPalette);
|
|
check(GOOD_BANK, "to-surface pastes every tile", loaded == gExpectedCount);
|
|
check(GOOD_BANK, "to-surface palette matches the PNG", paletteIsExpected());
|
|
check(GOOD_BANK, "to-surface pixels match the PNG, later blocks keep theirs", surfaceMatches(gExpectedCount));
|
|
// scripts/verify-<port>-tilebank.sh read this line: each port's own bake,
|
|
// drawn by examples/tilebank, must hash the same.
|
|
printf(" info %s: to-surface hash %08lX (a port loading its own bake must match)\n", GOOD_BANK, (unsigned long)jlSurfaceHash(gSurface));
|
|
|
|
jlSurfaceClear(gSurface, FILL_COLOR);
|
|
loaded = jlTileBankLoadToSurface(GOOD_BANK, gSurface, NULL);
|
|
check(GOOD_BANK, "to-surface pastes with NULL outPalette", loaded == gExpectedCount);
|
|
}
|
|
|
|
|
|
static void testTruncated(void) {
|
|
uint16_t loaded;
|
|
|
|
resetBuffers();
|
|
loaded = jlTileBankLoad(TRUNCATED_BANK, gTiles, TILE_CAPACITY, gValid, gPalette);
|
|
check(TRUNCATED_BANK, "loads only the whole tiles", loaded == TRUNCATED_TILES);
|
|
check(TRUNCATED_BANK, "valid true for the whole tiles", validRangeIs(0u, TRUNCATED_TILES, true));
|
|
check(TRUNCATED_BANK, "valid false from the cut on", validRangeIs(TRUNCATED_TILES, TILE_CAPACITY, false));
|
|
pasteLoadedTiles(TRUNCATED_TILES);
|
|
check(TRUNCATED_BANK, "the whole tiles match the PNG", surfaceMatches(TRUNCATED_TILES));
|
|
|
|
jlSurfaceClear(gSurface, FILL_COLOR);
|
|
loaded = jlTileBankLoadToSurface(TRUNCATED_BANK, gSurface, gPalette);
|
|
check(TRUNCATED_BANK, "to-surface pastes only the whole tiles", loaded == TRUNCATED_TILES);
|
|
check(TRUNCATED_BANK, "to-surface leaves the cut tile's block alone", surfaceMatches(TRUNCATED_TILES));
|
|
}
|
|
|
|
|
|
static bool tilesUntouched(uint16_t first, uint16_t end) {
|
|
uint16_t i;
|
|
uint16_t b;
|
|
|
|
for (i = first; i < end; i++) {
|
|
for (b = 0; b < TILE_BYTES; b++) {
|
|
if (gTiles[i].pixels[b] != TILE_SENTINEL) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool validRangeIs(uint16_t first, uint16_t end, bool want) {
|
|
uint16_t i;
|
|
|
|
for (i = first; i < end; i++) {
|
|
if (gValid[i] != want) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool writeBank(const char *name, uint32_t length) {
|
|
FILE *fp;
|
|
bool ok;
|
|
|
|
fp = jlDataOpen(name, "wb");
|
|
if (fp == NULL) {
|
|
return false;
|
|
}
|
|
ok = fwrite(gFile, 1, length, fp) == length;
|
|
return (fclose(fp) == 0) && ok;
|
|
}
|
|
|
|
|
|
static void writeLe16(uint8_t *bytes, uint16_t value) {
|
|
bytes[0] = (uint8_t)value;
|
|
bytes[1] = (uint8_t)(value >> CHAR_BIT);
|
|
}
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
jlConfigT config;
|
|
int i;
|
|
bool ready;
|
|
|
|
printf("tilebank-host: jlTileBankLoad + jlTileBankLoadToSurface on the BLANK port (real files)\n");
|
|
memset(&config, 0, sizeof(config));
|
|
if (!jlInit(&config)) {
|
|
printf("tilebank-host: jlInit failed\n");
|
|
return 1;
|
|
}
|
|
gSurface = jlSurfaceCreate();
|
|
ready = gSurface != NULL;
|
|
check("setup", "jlSurfaceCreate", ready);
|
|
ready = ready && loadExpected();
|
|
check("setup", EXPECTED_FILE " read (fixture spans more than a block row, less than a surface)", ready);
|
|
ready = ready && craftBanks();
|
|
check("setup", "malformed banks cut from " GOOD_BANK, ready);
|
|
check("setup", "other targets' bakes to refuse were passed in", argc > 1);
|
|
|
|
if (ready) {
|
|
testArgumentGuards();
|
|
testGoodBank();
|
|
testMaxTiles();
|
|
testToSurface();
|
|
testTruncated();
|
|
testNoPalette();
|
|
testBigBank();
|
|
for (i = 1; i < argc; i++) {
|
|
testRefused(argv[i]);
|
|
}
|
|
testRefused(BAD_MAGIC_BANK);
|
|
testRefused(SHORT_HEADER_BANK);
|
|
testRefused(MISSING_BANK);
|
|
}
|
|
|
|
jlSurfaceDestroy(gSurface);
|
|
jlShutdown();
|
|
printf("tilebank-host: %u passed, %u failed\n", (unsigned)gPass, (unsigned)gFail);
|
|
return (gFail == 0u) ? 0 : 1;
|
|
}
|