From e9a56255ea70271354ce6daef90554bb62ea5be8 Mon Sep 17 00:00:00 2001 From: red031000 Date: Mon, 3 Jul 2023 07:14:59 +0100 Subject: [PATCH] add NANR support to nitrogfx --- Makefile | 5 +- arm9/src/bg_window.c | 2 +- files/poketool/icongra/poke_icon/.gitignore | 1 + .../poketool/icongra/poke_icon/narc_0001.NANR | Bin 154 -> 0 bytes .../poketool/icongra/poke_icon/narc_0001.json | 32 +++ filesystem.mk | 1 + graphics_rules.mk | 2 + tools/nitrogfx/gfx.c | 214 +++++++++++++++++- tools/nitrogfx/gfx.h | 3 +- tools/nitrogfx/json.c | 186 ++++++++++++++- tools/nitrogfx/json.h | 2 + tools/nitrogfx/main.c | 12 + tools/nitrogfx/options.h | 43 ++++ 13 files changed, 496 insertions(+), 7 deletions(-) delete mode 100644 files/poketool/icongra/poke_icon/narc_0001.NANR create mode 100644 files/poketool/icongra/poke_icon/narc_0001.json diff --git a/Makefile b/Makefile index f608b4b9f..9cec59d86 100644 --- a/Makefile +++ b/Makefile @@ -168,7 +168,7 @@ clean: mostlyclean clean-fs clean-tools clean-fs: $(RM) $(filter %.narc %.arc,$(HOSTFS_FILES)) $(RM) $(patsubst %.narc,%.naix,$(patsubst %.arc,%.naix,$(filter %.narc %.arc,$(HOSTFS_FILES)))) - $(RM) $(NCGR_CLEAN_LIST) $(NCLR_CLEAN_LIST) $(NCER_CLEAN_LIST) $(FS_CLEAN_LIST) + $(RM) $(NCGR_CLEAN_LIST) $(NCLR_CLEAN_LIST) $(NCER_CLEAN_LIST) $(NANR_CLEAN_LIST) $(FS_CLEAN_LIST) find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' \) -exec $(RM) {} + $(RM) files/msgdata/msg/narc_*.bin @@ -283,6 +283,9 @@ $(NCPR_NCLR_FILES): GFX_FLAGS = -ncpr %.NCER: %.json $(GFX) $< $@ +%.NANR: %.json + $(GFX) $< $@ + %.NSCR: %_map.json $(GFX) $< $@ $(GFX_FLAGS) diff --git a/arm9/src/bg_window.c b/arm9/src/bg_window.c index 9e30b4117..91bafa246 100644 --- a/arm9/src/bg_window.c +++ b/arm9/src/bg_window.c @@ -5,7 +5,7 @@ #include "gx.h" #include "heap.h" -const u8 sTilemapWidthByBufferSize[] = { +static const u8 sTilemapWidthByBufferSize[] = { [GF_BG_SCR_SIZE_128x128] = 0x10, [GF_BG_SCR_SIZE_256x256] = 0x20, [GF_BG_SCR_SIZE_256x512] = 0x20, diff --git a/files/poketool/icongra/poke_icon/.gitignore b/files/poketool/icongra/poke_icon/.gitignore index fccab7c87..a7f09e505 100644 --- a/files/poketool/icongra/poke_icon/.gitignore +++ b/files/poketool/icongra/poke_icon/.gitignore @@ -1,4 +1,5 @@ narc_0000.NCLR +narc_0001.NANR *.NCER narc_0007.NCGR narc_0008.NCGR diff --git a/files/poketool/icongra/poke_icon/narc_0001.NANR b/files/poketool/icongra/poke_icon/narc_0001.NANR deleted file mode 100644 index 033b8ba3c498510dea60a017d79f361a9af58645..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154 zcmWIYbM*WFkAZO(0|SEq12coSpOa$*kj(^y5width * options->height * 2 + 0x14; @@ -947,3 +947,211 @@ void WriteNtrScreen(char *outputPath, struct JsonToScreenOptions *options) fclose(fp); } + +void WriteNtrAnimation(char *path, struct JsonToAnimationOptions *options) +{ + FILE *fp = fopen(path, "wb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for writing.\n", path); + + unsigned int totalSize = 0x20 + options->sequenceCount * 0x10 + options->frameCount * 0x8; + + //todo: check these + for (int i = 0; i < options->frameCount; i++) + { + if (options->sequenceData[i]->animationElement == 0) + totalSize += 0x4; + else if (options->sequenceData[i]->animationElement == 1) + totalSize += 0x10; + else if (options->sequenceData[i]->animationElement == 2) + totalSize += 0x8; + } + + unsigned int KNBASize = totalSize; + + if (options->labelEnabled) + { + totalSize += 0x14; + for (int j = 0; j < options->labelCount; j++) + { + totalSize += (unsigned)strlen(options->labels[j]) + 5; //strlen + terminator + pointer + } + } + + WriteGenericNtrHeader(fp, "RNAN", totalSize, true, false, options->labelEnabled ? 3 : 1); + + unsigned char KBNAHeader[0x20] = + { + 0x4B, 0x4E, 0x42, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + KBNAHeader[4] = KNBASize & 0xff; + KBNAHeader[5] = (KNBASize >> 8) & 0xff; + KBNAHeader[6] = (KNBASize >> 16) & 0xff; + KBNAHeader[7] = KNBASize >> 24; + + KBNAHeader[8] = options->sequenceCount & 0xff; + KBNAHeader[9] = options->sequenceCount >> 8; + + KBNAHeader[10] = options->frameCount & 0xff; + KBNAHeader[11] = options->frameCount >> 8; + + unsigned int frameOffset = 0x18 + options->sequenceCount * 0x10; + + KBNAHeader[16] = frameOffset & 0xff; + KBNAHeader[17] = (frameOffset >> 8) & 0xff; + KBNAHeader[18] = (frameOffset >> 16) & 0xff; + KBNAHeader[19] = frameOffset >> 24; + + unsigned int resultsOffset = frameOffset + options->frameCount * 0x8; + + KBNAHeader[20] = resultsOffset & 0xff; + KBNAHeader[21] = (resultsOffset >> 8) & 0xff; + KBNAHeader[22] = (resultsOffset >> 16) & 0xff; + KBNAHeader[23] = resultsOffset >> 24; + + fwrite(KBNAHeader, 1, 0x20, fp); + + int contentsSize = KNBASize - 0x20; + unsigned char *KBNAContents = malloc(contentsSize); + + int i; + for (i = 0; i < options->sequenceCount * 0x10; i += 0x10) + { + KBNAContents[i] = options->sequenceData[i / 0x10]->frameNumber & 0xff; + KBNAContents[i + 1] = options->sequenceData[i / 0x10]->frameNumber >> 8; + KBNAContents[i + 2] = options->sequenceData[i / 0x10]->loopStartFrame & 0xff; + KBNAContents[i + 3] = options->sequenceData[i / 0x10]->loopStartFrame >> 8; + KBNAContents[i + 4] = options->sequenceData[i / 0x10]->animationElement & 0xff; + KBNAContents[i + 5] = options->sequenceData[i / 0x10]->animationElement >> 8; + KBNAContents[i + 6] = options->sequenceData[i / 0x10]->animationType & 0xff; + KBNAContents[i + 7] = options->sequenceData[i / 0x10]->animationType >> 8; + KBNAContents[i + 8] = options->sequenceData[i / 0x10]->playbackMode & 0xff; + KBNAContents[i + 9] = (options->sequenceData[i / 0x10]->playbackMode >> 8) & 0xff; + KBNAContents[i + 10] = (options->sequenceData[i / 0x10]->playbackMode >> 16) & 0xff; + KBNAContents[i + 11] = options->sequenceData[i / 0x10]->playbackMode >> 24; + KBNAContents[i + 12] = (i / 0x10 * 8) & 0xff; + KBNAContents[i + 13] = ((i / 0x10 * 8) >> 8) & 0xff; + KBNAContents[i + 14] = ((i / 0x10 * 8) >> 16) & 0xff; + KBNAContents[i + 15] = (i / 0x10 * 8) >> 24; + } + + int j; + int resPtrCounter = 0; + for (j = i; j < options->frameCount * 8 + i; j += 8) + { + KBNAContents[j] = resPtrCounter & 0xff; + KBNAContents[j + 1] = (resPtrCounter >> 8) & 0xff; + KBNAContents[j + 2] = (resPtrCounter >> 16) & 0xff; + KBNAContents[j + 3] = resPtrCounter >> 24; + if (options->sequenceData[(j - i) / 8]->animationElement == 0) + resPtrCounter += 0x4; + else if (options->sequenceData[(j - i) / 8]->animationElement == 1) + resPtrCounter += 0x10; + else if (options->sequenceData[(j - i) / 8]->animationElement == 2) + resPtrCounter += 0x8; + KBNAContents[j + 4] = options->frameDelay[(j - i) / 8] & 0xff; + KBNAContents[j + 5] = options->frameDelay[(j - i) / 8] >> 8; + KBNAContents[j + 6] = 0xEF; + KBNAContents[j + 7] = 0xBE; + } + + //todo: these are extrapolated, need confirming + resPtrCounter = j; + for (int k = 0; k < options->frameCount; k++) + { + switch (options->sequenceData[k]->animationElement) + { + case 0: + KBNAContents[resPtrCounter] = options->animationResults[k]->index & 0xff; + KBNAContents[resPtrCounter + 1] = options->animationResults[k]->index >> 8; + KBNAContents[resPtrCounter + 2] = 0xCC; + KBNAContents[resPtrCounter + 3] = 0xCC; + resPtrCounter += 0x4; + break; + + case 1: + KBNAContents[resPtrCounter] = options->animationResults[k]->dataSrt.index & 0xff; + KBNAContents[resPtrCounter + 1] = options->animationResults[k]->dataSrt.index >> 8; + KBNAContents[resPtrCounter + 2] = options->animationResults[k]->dataSrt.rotation & 0xff; + KBNAContents[resPtrCounter + 3] = options->animationResults[k]->dataSrt.rotation >> 8; + KBNAContents[resPtrCounter + 4] = options->animationResults[k]->dataSrt.scaleX & 0xff; + KBNAContents[resPtrCounter + 5] = (options->animationResults[k]->dataSrt.scaleX >> 8) & 0xff; + KBNAContents[resPtrCounter + 6] = (options->animationResults[k]->dataSrt.scaleX >> 16) & 0xff; + KBNAContents[resPtrCounter + 7] = options->animationResults[k]->dataSrt.scaleX >> 24; + KBNAContents[resPtrCounter + 8] = options->animationResults[k]->dataSrt.scaleY & 0xff; + KBNAContents[resPtrCounter + 9] = (options->animationResults[k]->dataSrt.scaleY >> 8) & 0xff; + KBNAContents[resPtrCounter + 10] = (options->animationResults[k]->dataSrt.scaleY >> 16) & 0xff; + KBNAContents[resPtrCounter + 11] = options->animationResults[k]->dataSrt.scaleY >> 24; + KBNAContents[resPtrCounter + 12] = options->animationResults[k]->dataSrt.positionX & 0xff; + KBNAContents[resPtrCounter + 13] = options->animationResults[k]->dataSrt.positionX >> 8; + KBNAContents[resPtrCounter + 14] = options->animationResults[k]->dataSrt.positionY & 0xff; + KBNAContents[resPtrCounter + 15] = options->animationResults[k]->dataSrt.positionY >> 8; + resPtrCounter += 0x10; + break; + + case 2: + KBNAContents[resPtrCounter] = options->animationResults[k]->dataT.index & 0xff; + KBNAContents[resPtrCounter + 1] = options->animationResults[k]->dataT.index >> 8; + KBNAContents[resPtrCounter + 2] = options->animationResults[k]->dataT.rotation & 0xff; + KBNAContents[resPtrCounter + 3] = options->animationResults[k]->dataT.rotation >> 8; + KBNAContents[resPtrCounter + 4] = options->animationResults[k]->dataT.positionX & 0xff; + KBNAContents[resPtrCounter + 5] = options->animationResults[k]->dataT.positionX >> 8; + KBNAContents[resPtrCounter + 6] = options->animationResults[k]->dataT.positionY & 0xff; + KBNAContents[resPtrCounter + 7] = options->animationResults[k]->dataT.positionY >> 8; + resPtrCounter += 0x8; + break; + } + } + + fwrite(KBNAContents, 1, contentsSize, fp); + + free(KBNAContents); + + if (options->labelEnabled) + { + unsigned int lablSize = 8; + for (int j = 0; j < options->labelCount; j++) + { + lablSize += (unsigned)strlen(options->labels[j]) + 5; + } + + unsigned char *labl = malloc(lablSize); + + memset(labl, 0, lablSize); + + strcpy((char *) labl, "LBAL"); + labl[4] = lablSize & 0xff; + labl[5] = lablSize >> 8; + + unsigned int position = 0; + + i = 0; + for (int j = 0; j < options->labelCount; j++) + { + labl[i + 8] = position & 0xff; + labl[i + 9] = position >> 8; + + position += (unsigned)strlen(options->labels[j]) + 1; + i += 4; + } + + for (int j = 0; j < options->labelCount; j++) + { + strcpy((char *) (labl + (i + 8)), options->labels[j]); + i += (int)strlen(options->labels[j]) + 1; + } + + fwrite(labl, 1, lablSize, fp); + + free(labl); + + unsigned char texu[0xc] = {0x54, 0x58, 0x45, 0x55, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + fwrite(texu, 1, 0xc, fp); + } + + fclose(fp); +} diff --git a/tools/nitrogfx/gfx.h b/tools/nitrogfx/gfx.h index 389aec413..9a6c58c04 100644 --- a/tools/nitrogfx/gfx.h +++ b/tools/nitrogfx/gfx.h @@ -41,6 +41,7 @@ void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIn void WriteGbaPalette(char *path, struct Palette *palette); void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, int bitdepth, bool pad, int compNum); void WriteNtrCell(char *path, struct JsonToCellOptions *options); -void WriteNtrScreen(char *outputPath, struct JsonToScreenOptions *options); +void WriteNtrScreen(char *path, struct JsonToScreenOptions *options); +void WriteNtrAnimation(char *path, struct JsonToAnimationOptions *options); #endif // GFX_H diff --git a/tools/nitrogfx/json.c b/tools/nitrogfx/json.c index b825c363d..7bbad9519 100644 --- a/tools/nitrogfx/json.c +++ b/tools/nitrogfx/json.c @@ -1,4 +1,4 @@ -// Copyright (c) 2021 red031000 +// Copyright (c) 2023 red031000 #include "global.h" #include "cJSON.h" @@ -230,6 +230,165 @@ struct JsonToScreenOptions *ParseNSCRJson(char *path) return options; } +struct JsonToAnimationOptions *ParseNANRJson(char *path) +{ + int filelength; + unsigned char *jsonString = ReadWholeFile(path, &filelength); + + cJSON *json = cJSON_Parse((const char *)jsonString); + + struct JsonToAnimationOptions *options = malloc(sizeof(struct JsonToAnimationOptions)); + + if (json == NULL) + { + const char *errorPtr = cJSON_GetErrorPtr(); + FATAL_ERROR("Error in line \"%s\"\n", errorPtr); + } + + cJSON *sequenceCount = cJSON_GetObjectItemCaseSensitive(json, "sequenceCount"); + cJSON *frameCount = cJSON_GetObjectItemCaseSensitive(json, "frameCount"); + + options->sequenceCount = GetInt(sequenceCount); + options->frameCount = GetInt(frameCount); + + options->sequenceData = malloc(sizeof(struct SequenceData *) * options->sequenceCount); + + int i; + for (i = 0; i < options->sequenceCount; i++) + { + options->sequenceData[i] = malloc(sizeof(struct SequenceData)); + } + + cJSON *sequence = NULL; + cJSON *sequences = cJSON_GetObjectItemCaseSensitive(json, "sequences"); + + i = 0; + cJSON_ArrayForEach(sequence, sequences) + { + if (i > options->sequenceCount - 1) + FATAL_ERROR("Sequence count is incorrect.\n"); + + cJSON *frameNumber = cJSON_GetObjectItemCaseSensitive(sequence, "frameNumber"); + cJSON *loopStartFrame = cJSON_GetObjectItemCaseSensitive(sequence, "loopStartFrame"); + cJSON *animationElement = cJSON_GetObjectItemCaseSensitive(sequence, "animationElement"); + cJSON *animationType = cJSON_GetObjectItemCaseSensitive(sequence, "animationType"); + cJSON *playbackMode = cJSON_GetObjectItemCaseSensitive(sequence, "playbackMode"); + + options->sequenceData[i]->frameNumber = GetInt(frameNumber); + options->sequenceData[i]->loopStartFrame = GetInt(loopStartFrame); + options->sequenceData[i]->animationElement = GetInt(animationElement); + options->sequenceData[i]->animationType = GetInt(animationType); + options->sequenceData[i]->playbackMode = GetInt(playbackMode); + + //TODO: see if frame data mapping is required + + i++; + } + + i = 0; + + options->frameDelay = malloc(sizeof(short) * options->frameCount); + + cJSON *frameDelay = NULL; + cJSON *frameDelays = cJSON_GetObjectItemCaseSensitive(json, "frameDelays"); + cJSON_ArrayForEach(frameDelay, frameDelays) + { + if (i > options->frameCount - 1) + FATAL_ERROR("Frame count is incorrect.\n"); + + options->frameDelay[i] = GetInt(frameDelay); + + //TODO: see if animation result data mapping is required + + i++; + } + + //todo implement extended attributes + + options->animationResults = malloc(sizeof(struct AnimationResults *) * options->frameCount); + + for (i = 0; i < options->frameCount; i++) + { + options->animationResults[i] = malloc(sizeof(struct AnimationResults)); + } + + i = 0; + + cJSON *animationResult = NULL; + cJSON *animationResults = cJSON_GetObjectItemCaseSensitive(json, "animationResults"); + cJSON_ArrayForEach(animationResult, animationResults) + { + if (i > options->frameCount - 1) + FATAL_ERROR("Frame count is incorrect.\n"); + + switch (options->sequenceData[i]->animationElement) { + case 0: { //index + cJSON *index = cJSON_GetObjectItemCaseSensitive(animationResult, "index"); + options->animationResults[i]->index = GetInt(index); + break; + } + + case 1: { //SRT + cJSON *index = cJSON_GetObjectItemCaseSensitive(animationResult, "index"); + cJSON *rotation = cJSON_GetObjectItemCaseSensitive(animationResult, "rotation"); + cJSON *scaleX = cJSON_GetObjectItemCaseSensitive(animationResult, "scaleX"); + cJSON *scaleY = cJSON_GetObjectItemCaseSensitive(animationResult, "scaleY"); + cJSON *positionX = cJSON_GetObjectItemCaseSensitive(animationResult, "positionX"); + cJSON *positionY = cJSON_GetObjectItemCaseSensitive(animationResult, "positionY"); + + options->animationResults[i]->dataSrt.index = GetInt(index); + options->animationResults[i]->dataSrt.rotation = GetInt(rotation); + options->animationResults[i]->dataSrt.scaleX = GetInt(scaleX); + options->animationResults[i]->dataSrt.scaleY = GetInt(scaleY); + options->animationResults[i]->dataSrt.positionX = GetInt(positionX); + options->animationResults[i]->dataSrt.positionY = GetInt(positionY); + break; + } + + case 2: { //T + cJSON *index = cJSON_GetObjectItemCaseSensitive(animationResult, "index"); + cJSON *rotation = cJSON_GetObjectItemCaseSensitive(animationResult, "rotation"); + cJSON *positionX = cJSON_GetObjectItemCaseSensitive(animationResult, "positionX"); + cJSON *positionY = cJSON_GetObjectItemCaseSensitive(animationResult, "positionY"); + + options->animationResults[i]->dataSrt.index = GetInt(index); + options->animationResults[i]->dataSrt.rotation = GetInt(rotation); + options->animationResults[i]->dataSrt.positionX = GetInt(positionX); + options->animationResults[i]->dataSrt.positionY = GetInt(positionY); + break; + } + } + + i++; + } + + cJSON *labelBool = cJSON_GetObjectItemCaseSensitive(json, "labelEnabled"); + options->labelEnabled = GetBool(labelBool); + + if (options->labelEnabled) + { + cJSON *labelCount = cJSON_GetObjectItemCaseSensitive(json, "labelCount"); + options->labelCount = GetInt(labelCount); + options->labels = malloc(sizeof(char *) * options->labelCount); + + cJSON *labels = cJSON_GetObjectItemCaseSensitive(json, "labels"); + cJSON *label = NULL; + + int j = 0; + cJSON_ArrayForEach(label, labels) + { + char *labelString = GetString(label); + options->labels[j] = malloc(strlen(labelString) + 1); + strcpy(options->labels[j], labelString); + j++; + } + } + + cJSON_Delete(json); + free(jsonString); + return options; +} + void FreeNCERCell(struct JsonToCellOptions *options) { for (int i = 0; i < options->cellCount; i++) @@ -244,6 +403,7 @@ void FreeNCERCell(struct JsonToCellOptions *options) } free(options->labels); } + free(options->cells); free(options); } @@ -253,3 +413,27 @@ void FreeNSCRScreen(struct JsonToScreenOptions *options) free(options); } + +void FreeNANRAnimation(struct JsonToAnimationOptions *options) +{ + for (int i = 0; i < options->sequenceCount; i++) + { + free(options->sequenceData[i]); + } + for (int i = 0; i < options->frameCount; i++) + { + free(options->animationResults[i]); + } + if (options->labelEnabled) + { + for (int j = 0; j < options->labelCount; j++) + { + free(options->labels[j]); + } + free(options->labels); + } + free(options->sequenceData); + free(options->animationResults); + free(options->frameDelay); + free(options); +} diff --git a/tools/nitrogfx/json.h b/tools/nitrogfx/json.h index f297cf08a..cc4e1dde0 100644 --- a/tools/nitrogfx/json.h +++ b/tools/nitrogfx/json.h @@ -7,7 +7,9 @@ struct JsonToCellOptions *ParseNCERJson(char *path); struct JsonToScreenOptions *ParseNSCRJson(char *path); +struct JsonToAnimationOptions *ParseNANRJson(char *path); void FreeNCERCell(struct JsonToCellOptions *options); void FreeNSCRScreen(struct JsonToScreenOptions *options); +void FreeNANRAnimation(struct JsonToAnimationOptions *options); #endif //JSON_H diff --git a/tools/nitrogfx/main.c b/tools/nitrogfx/main.c index 5561e44ef..95e437d89 100644 --- a/tools/nitrogfx/main.c +++ b/tools/nitrogfx/main.c @@ -732,6 +732,17 @@ void HandleJsonToNtrScreenCommand(char *inputPath, char *outputPath, int argc UN FreeNSCRScreen(options); } +void HandleJsonToNtrAnimationCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + struct JsonToAnimationOptions *options; + + options = ParseNANRJson(inputPath); + + WriteNtrAnimation(outputPath, options); + + FreeNANRAnimation(options); +} + void HandleLatinFontToPngCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) { struct Image image; @@ -992,6 +1003,7 @@ int main(int argc, char **argv) { "png", "fwjpnfont", HandlePngToFullwidthJapaneseFontCommand }, { "json", "NCER", HandleJsonToNtrCellCommand }, { "json", "NSCR", HandleJsonToNtrScreenCommand }, + { "json", "NANR", HandleJsonToNtrAnimationCommand }, { NULL, "huff", HandleHuffCompressCommand }, { NULL, "lz", HandleLZCompressCommand }, { "huff", NULL, HandleHuffDecompressCommand }, diff --git a/tools/nitrogfx/options.h b/tools/nitrogfx/options.h index e67217666..3a449e6af 100644 --- a/tools/nitrogfx/options.h +++ b/tools/nitrogfx/options.h @@ -91,4 +91,47 @@ struct JsonToScreenOptions { int bitdepth; }; +struct SequenceData { + short frameNumber; + short loopStartFrame; + short animationElement; + short animationType; + int playbackMode; +}; + +struct AnimationDataSRT { + short index; + unsigned short rotation; + int scaleX; + int scaleY; + short positionX; + short positionY; +}; + +struct AnimationDataT { + short index; + unsigned short rotation; + short positionX; + short positionY; +}; + +struct AnimationResults { + union { + short index; + struct AnimationDataSRT dataSrt; + struct AnimationDataT dataT; + }; +}; + +struct JsonToAnimationOptions { + short sequenceCount; + short frameCount; + struct SequenceData **sequenceData; + short *frameDelay; + struct AnimationResults **animationResults; + bool labelEnabled; + char **labels; + int labelCount; +}; + #endif // OPTIONS_H