mirror of
https://github.com/pret/pokeheartgold.git
synced 2024-12-11 22:57:18 +00:00
NANR to json decoding
This commit is contained in:
parent
f0ab32e9c8
commit
c562885aa6
@ -1114,6 +1114,184 @@ void WriteNtrScreen(char *path, struct JsonToScreenOptions *options)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void ReadNtrAnimation(char *path, struct JsonToAnimationOptions *options)
|
||||
{
|
||||
int fileSize;
|
||||
unsigned char *data = ReadWholeFile(path, &fileSize);
|
||||
|
||||
if (memcmp(data, "RNAN", 4) != 0 && memcmp(data, "RAMN", 4) != 0) //NANR/NMAR
|
||||
{
|
||||
FATAL_ERROR("Not a valid NANR/NMAR animation file.\n");
|
||||
}
|
||||
|
||||
options->labelEnabled = data[0xE] != 1;
|
||||
|
||||
if (memcmp(data + 0x10, "KNBA", 4) != 0 ) //ABNK
|
||||
{
|
||||
FATAL_ERROR("Not a valid ABNK animation file.\n");
|
||||
}
|
||||
|
||||
options->sequenceCount = data[0x18] | (data[0x19] << 8);
|
||||
options->frameCount = data[0x1A] | (data[0x1B] << 8);
|
||||
|
||||
options->sequenceData = malloc(sizeof(struct SequenceData *) * options->sequenceCount);
|
||||
|
||||
for (int i = 0; i < options->sequenceCount; i++)
|
||||
{
|
||||
options->sequenceData[i] = malloc(sizeof(struct SequenceData));
|
||||
}
|
||||
|
||||
int offset = 0x30;
|
||||
|
||||
unsigned int *frameOffsets = malloc(sizeof(unsigned int) * options->sequenceCount);
|
||||
|
||||
for (int i = 0; i < options->sequenceCount; i++, offset += 0x10)
|
||||
{
|
||||
options->sequenceData[i]->frameCount = data[offset] | (data[offset + 1] << 8);
|
||||
options->sequenceData[i]->loopStartFrame = data[offset + 2] | (data[offset + 3] << 8);
|
||||
options->sequenceData[i]->animationElement = data[offset + 4] | (data[offset + 5] << 8);
|
||||
options->sequenceData[i]->animationType = data[offset + 6] | (data[offset + 7] << 8);
|
||||
options->sequenceData[i]->playbackMode = data[offset + 8] | (data[offset + 9] << 8) | (data[offset + 10] << 16) | (data[offset + 11] << 24);
|
||||
frameOffsets[i] = data[offset + 12] | (data[offset + 13] << 8) | (data[offset + 14] << 16) | (data[offset + 15] << 24);
|
||||
|
||||
options->sequenceData[i]->frameData = malloc(sizeof(struct FrameData *) * options->sequenceData[i]->frameCount);
|
||||
for (int j = 0; j < options->sequenceData[i]->frameCount; j++)
|
||||
{
|
||||
options->sequenceData[i]->frameData[j] = malloc(sizeof(struct FrameData));
|
||||
}
|
||||
}
|
||||
|
||||
int *resultOffsets = malloc(sizeof(int) * options->frameCount);
|
||||
memset(resultOffsets, -1, sizeof(int) * options->frameCount);
|
||||
|
||||
for (int i = 0; i < options->sequenceCount; i++)
|
||||
{
|
||||
for (int j = 0; j < options->sequenceData[i]->frameCount; j++)
|
||||
{
|
||||
int frameOffset = offset + frameOffsets[i] + j * 0x8;
|
||||
options->sequenceData[i]->frameData[j]->resultOffset = data[frameOffset] | (data[frameOffset + 1] << 8) | (data[frameOffset + 2] << 16) | (data[frameOffset + 3] << 24);
|
||||
options->sequenceData[i]->frameData[j]->frameDelay = data[frameOffset + 4] | (data[frameOffset + 5] << 8);
|
||||
//0xBEEF
|
||||
|
||||
//the following is messy
|
||||
bool present = false;
|
||||
//check for offset in array
|
||||
for (int k = 0; k < options->frameCount; k++)
|
||||
{
|
||||
if (resultOffsets[k] == options->sequenceData[i]->frameData[j]->resultOffset)
|
||||
{
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//add data if not present
|
||||
if (!present)
|
||||
{
|
||||
for (int k = 0; i < options->frameCount; k++)
|
||||
{
|
||||
if (resultOffsets[k] == -1)
|
||||
{
|
||||
resultOffsets[k] = options->sequenceData[i]->frameData[j]->resultOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(frameOffsets);
|
||||
|
||||
offset = 0x18 + (data[0x24] | (data[0x25] << 8) | (data[0x26] << 16) | (data[0x27] << 24)); //start of animation results
|
||||
|
||||
int k;
|
||||
|
||||
for (k = 0; k < options->frameCount; k++)
|
||||
{
|
||||
if (resultOffsets[k] == -1)
|
||||
break;
|
||||
}
|
||||
options->resultCount = k;
|
||||
|
||||
free(resultOffsets);
|
||||
|
||||
options->animationResults = malloc(sizeof(struct AnimationResults *) * options->resultCount);
|
||||
|
||||
for (int i = 0; i < options->resultCount; i++)
|
||||
{
|
||||
options->animationResults[i] = malloc(sizeof(struct AnimationResults));
|
||||
}
|
||||
|
||||
int resultOffset = 0;
|
||||
for (int i = 0; i < options->resultCount; i++)
|
||||
{
|
||||
if (data[offset + 2] == 0xCC && data[offset + 3] == 0xCC)
|
||||
{
|
||||
options->animationResults[i]->resultType = 0;
|
||||
}
|
||||
else if (data[offset + 2] == 0xEF && data[offset + 3] == 0xBE)
|
||||
{
|
||||
options->animationResults[i]->resultType = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
options->animationResults[i]->resultType = 1;
|
||||
}
|
||||
for (int j = 0; j < options->sequenceCount; j++)
|
||||
{
|
||||
for (int k = 0; k < options->sequenceData[j]->frameCount; k++)
|
||||
{
|
||||
if (options->sequenceData[j]->frameData[k]->resultOffset == resultOffset)
|
||||
{
|
||||
options->sequenceData[j]->frameData[k]->resultId = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (options->animationResults[i]->resultType)
|
||||
{
|
||||
case 0: //index
|
||||
options->animationResults[i]->index = data[offset] | (data[offset + 1] << 8);
|
||||
resultOffset += 0x4;
|
||||
offset += 0x4;
|
||||
break;
|
||||
|
||||
case 1: //SRT
|
||||
options->animationResults[i]->dataSrt.index = data[offset] | (data[offset + 1] << 8);
|
||||
options->animationResults[i]->dataSrt.rotation = data[offset + 2] | (data[offset + 3] << 8);
|
||||
options->animationResults[i]->dataSrt.scaleX = data[offset + 4] | (data[offset + 5] << 8) | (data[offset + 6] << 16) | (data[offset + 7] << 24);
|
||||
options->animationResults[i]->dataSrt.scaleY = data[offset + 8] | (data[offset + 9] << 8) | (data[offset + 10] << 16) | (data[offset + 11] << 24);
|
||||
options->animationResults[i]->dataSrt.positionX = data[offset + 12] | (data[offset + 13] << 8);
|
||||
options->animationResults[i]->dataSrt.positionY = data[offset + 14] | (data[offset + 15] << 8);
|
||||
resultOffset += 0x10;
|
||||
offset += 0x10;
|
||||
break;
|
||||
|
||||
case 2: //T
|
||||
options->animationResults[i]->dataT.index = data[offset] | (data[offset + 1] << 8);
|
||||
options->animationResults[i]->dataT.positionX = data[offset + 4] | (data[offset + 5] << 8);
|
||||
options->animationResults[i]->dataT.positionY = data[offset + 6] | (data[offset + 7] << 8);
|
||||
resultOffset += 0x8;
|
||||
offset += 0x8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (options->labelEnabled)
|
||||
{
|
||||
options->labelCount = options->sequenceCount; //*should* be the same
|
||||
options->labels = malloc(sizeof(char *) * options->labelCount);
|
||||
offset += 0x8 + options->labelCount * 0x4; //skip to label data
|
||||
for (int i = 0; i < options->labelCount; i++)
|
||||
{
|
||||
options->labels[i] = malloc(strlen((char *)data + offset) + 1);
|
||||
strcpy(options->labels[i], (char *)data + offset);
|
||||
offset += strlen((char *)data + offset) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
void WriteNtrAnimation(char *path, struct JsonToAnimationOptions *options)
|
||||
{
|
||||
FILE *fp = fopen(path, "wb");
|
||||
@ -1269,8 +1447,6 @@ void WriteNtrAnimation(char *path, struct JsonToAnimationOptions *options)
|
||||
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 + 2] = 0xEF;
|
||||
KBNAContents[resPtrCounter + 3] = 0xBE;
|
||||
KBNAContents[resPtrCounter + 4] = options->animationResults[k]->dataT.positionX & 0xff;
|
||||
|
@ -43,6 +43,7 @@ void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, in
|
||||
void ReadNtrCell(char *path, struct JsonToCellOptions *options);
|
||||
void WriteNtrCell(char *path, struct JsonToCellOptions *options);
|
||||
void WriteNtrScreen(char *path, struct JsonToScreenOptions *options);
|
||||
void ReadNtrAnimation(char *path, struct JsonToAnimationOptions *options);
|
||||
void WriteNtrAnimation(char *path, struct JsonToAnimationOptions *options);
|
||||
|
||||
#endif // GFX_H
|
||||
|
@ -481,6 +481,85 @@ struct JsonToAnimationOptions *ParseNANRJson(char *path)
|
||||
return options;
|
||||
}
|
||||
|
||||
char *GetNANRJson(struct JsonToAnimationOptions *options)
|
||||
{
|
||||
cJSON *nanr = cJSON_CreateObject();
|
||||
|
||||
cJSON_AddBoolToObject(nanr, "labelEnabled", options->labelEnabled);
|
||||
cJSON_AddNumberToObject(nanr, "sequenceCount", options->sequenceCount);
|
||||
cJSON_AddNumberToObject(nanr, "frameCount", options->frameCount);
|
||||
|
||||
cJSON *sequences = cJSON_AddArrayToObject(nanr, "sequences");
|
||||
|
||||
for (int i = 0; i < options->sequenceCount; i++)
|
||||
{
|
||||
cJSON *sequence = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(sequence, "frameCount", options->sequenceData[i]->frameCount);
|
||||
cJSON_AddNumberToObject(sequence, "loopStartFrame", options->sequenceData[i]->loopStartFrame);
|
||||
cJSON_AddNumberToObject(sequence, "animationElement", options->sequenceData[i]->animationElement);
|
||||
cJSON_AddNumberToObject(sequence, "animationType", options->sequenceData[i]->animationType);
|
||||
cJSON_AddNumberToObject(sequence, "playbackMode", options->sequenceData[i]->playbackMode);
|
||||
|
||||
cJSON *frameData = cJSON_AddArrayToObject(sequence, "frameData");
|
||||
|
||||
for (int j = 0; j < options->sequenceData[i]->frameCount; j++)
|
||||
{
|
||||
cJSON *frame = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(frame, "frameDelay", options->sequenceData[i]->frameData[j]->frameDelay);
|
||||
cJSON_AddNumberToObject(frame, "resultId", options->sequenceData[i]->frameData[j]->resultId);
|
||||
cJSON_AddItemToArray(frameData, frame);
|
||||
}
|
||||
|
||||
cJSON_AddItemToArray(sequences, sequence);
|
||||
}
|
||||
|
||||
cJSON *animationResults = cJSON_AddArrayToObject(nanr, "animationResults");
|
||||
|
||||
for (int i = 0; i < options->resultCount; i++)
|
||||
{
|
||||
cJSON *animationResult = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(animationResult, "resultType", options->animationResults[i]->resultType);
|
||||
|
||||
switch (options->animationResults[i]->resultType)
|
||||
{
|
||||
case 0: //index
|
||||
cJSON_AddNumberToObject(animationResult, "index", options->animationResults[i]->index);
|
||||
break;
|
||||
|
||||
case 1: //SRT
|
||||
cJSON_AddNumberToObject(animationResult, "index", options->animationResults[i]->dataSrt.index);
|
||||
cJSON_AddNumberToObject(animationResult, "rotation", options->animationResults[i]->dataSrt.rotation);
|
||||
cJSON_AddNumberToObject(animationResult, "scaleX", options->animationResults[i]->dataSrt.scaleX);
|
||||
cJSON_AddNumberToObject(animationResult, "scaleY", options->animationResults[i]->dataSrt.scaleY);
|
||||
cJSON_AddNumberToObject(animationResult, "positionX", options->animationResults[i]->dataSrt.positionX);
|
||||
cJSON_AddNumberToObject(animationResult, "positionY", options->animationResults[i]->dataSrt.positionY);
|
||||
break;
|
||||
|
||||
case 2: //T
|
||||
cJSON_AddNumberToObject(animationResult, "index", options->animationResults[i]->dataT.index);
|
||||
cJSON_AddNumberToObject(animationResult, "positionX", options->animationResults[i]->dataT.positionX);
|
||||
cJSON_AddNumberToObject(animationResult, "positionY", options->animationResults[i]->dataT.positionY);
|
||||
break;
|
||||
}
|
||||
|
||||
cJSON_AddItemToArray(animationResults, animationResult);
|
||||
}
|
||||
|
||||
cJSON_AddNumberToObject(nanr, "resultCount", options->resultCount);
|
||||
|
||||
if (options->labelEnabled)
|
||||
{
|
||||
cJSON *labels = cJSON_CreateStringArray((const char * const*)options->labels, options->labelCount);
|
||||
cJSON_AddItemToObject(nanr, "labels", labels);
|
||||
|
||||
cJSON_AddNumberToObject(nanr, "labelCount", options->labelCount);
|
||||
}
|
||||
|
||||
char *jsonString = cJSON_Print(nanr);
|
||||
cJSON_Delete(nanr);
|
||||
return jsonString;
|
||||
}
|
||||
|
||||
void FreeNCERCell(struct JsonToCellOptions *options)
|
||||
{
|
||||
for (int i = 0; i < options->cellCount; i++)
|
||||
|
@ -9,6 +9,7 @@ struct JsonToCellOptions *ParseNCERJson(char *path);
|
||||
char *GetNCERJson(struct JsonToCellOptions *options);
|
||||
struct JsonToScreenOptions *ParseNSCRJson(char *path);
|
||||
struct JsonToAnimationOptions *ParseNANRJson(char *path);
|
||||
char *GetNANRJson(struct JsonToAnimationOptions *options);
|
||||
void FreeNCERCell(struct JsonToCellOptions *options);
|
||||
void FreeNSCRScreen(struct JsonToScreenOptions *options);
|
||||
void FreeNANRAnimation(struct JsonToAnimationOptions *options);
|
||||
|
@ -832,6 +832,19 @@ void HandleJsonToNtrAnimationCommand(char *inputPath, char *outputPath, int argc
|
||||
FreeNANRAnimation(options);
|
||||
}
|
||||
|
||||
void HandleNtrAnimationToJsonCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
|
||||
{
|
||||
struct JsonToAnimationOptions *options = malloc(sizeof(struct JsonToAnimationOptions));
|
||||
|
||||
ReadNtrAnimation(inputPath, options);
|
||||
|
||||
char *json = GetNANRJson(options);
|
||||
|
||||
WriteWholeStringToFile(outputPath, json);
|
||||
|
||||
FreeNANRAnimation(options);
|
||||
}
|
||||
|
||||
void HandleJsonToNtrMulticellAnimationCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
|
||||
{
|
||||
struct JsonToAnimationOptions *options;
|
||||
@ -1110,7 +1123,9 @@ int main(int argc, char **argv)
|
||||
{ "NCER", "json", HandleNtrCellToJsonCommand },
|
||||
{ "json", "NSCR", HandleJsonToNtrScreenCommand },
|
||||
{ "json", "NANR", HandleJsonToNtrAnimationCommand },
|
||||
{ "NANR", "json", HandleNtrAnimationToJsonCommand },
|
||||
{ "json", "NMAR", HandleJsonToNtrMulticellAnimationCommand },
|
||||
{ "NMAR", "json", HandleNtrAnimationToJsonCommand },
|
||||
{ NULL, "huff", HandleHuffCompressCommand },
|
||||
{ NULL, "lz", HandleLZCompressCommand },
|
||||
{ "huff", NULL, HandleHuffDecompressCommand },
|
||||
|
@ -114,6 +114,7 @@ struct JsonToScreenOptions {
|
||||
struct FrameData {
|
||||
int resultId;
|
||||
short frameDelay;
|
||||
int resultOffset;
|
||||
};
|
||||
|
||||
struct SequenceData {
|
||||
|
Loading…
Reference in New Issue
Block a user