Merge remote-tracking branch 'origin/master' into decomp/pokegear-configure

This commit is contained in:
PikalaxALT 2025-11-25 15:44:31 -05:00
commit 16920eeb9d
21 changed files with 3558 additions and 2056 deletions

View File

@ -1,21 +0,0 @@
#include <nitro/fs/overlay.h>
#pragma once
.public Save_PlayerData_GetProfile
.public PlayerProfile_GetNamePtr
.public PlayerProfile_GetTrainerID
.public PlayerProfile_GetTrainerGender
.public PlayerProfile_GetAvatar
.public Save_WiFiHistory_Get
.public WifiHistory_GetPlayerCountry
.public WiFiHistory_GetPlayerRegion
.public sub_0202D4DC
.public sub_0202D564
.public sub_0202D5DC
.public sub_0202D660
.public Save_FrontierData_Get
.public GetUnionRoomAvatarAttrBySprite
.public sub_02069528
.public MI_CpuFill8
.public MI_CpuCopy8
.public gGameVersion
.public gGameLanguage

View File

@ -1,147 +0,0 @@
.include "asm/macros.inc"
.include "unk_02069528.inc"
.include "global.inc"
.text
thumb_func_start sub_02069528
sub_02069528: ; 0x02069528
push {r4, r5, r6, r7, lr}
sub sp, #0xc
add r6, r0, #0
str r1, [sp]
add r7, r2, #0
bl Save_PlayerData_GetProfile
add r4, r0, #0
add r0, r6, #0
bl Save_WiFiHistory_Get
add r5, r0, #0
add r0, r6, #0
bl Save_FrontierData_Get
str r0, [sp, #4]
add r0, r7, #0
mov r1, #0
mov r2, #0xe4
bl MI_CpuFill8
add r0, r4, #0
bl PlayerProfile_GetNamePtr
add r1, r7, #0
add r1, #0xa8
mov r2, #0x10
bl MI_CpuCopy8
add r0, r4, #0
bl PlayerProfile_GetTrainerID
add r1, r7, #0
add r1, #0xbc
str r0, [r1]
ldr r0, _02069658 ; =gGameVersion
ldrb r1, [r0]
add r0, r7, #0
add r0, #0xb8
strb r1, [r0]
ldr r0, _0206965C ; =gGameLanguage
ldrb r1, [r0]
add r0, r7, #0
add r0, #0xb9
strb r1, [r0]
add r0, r5, #0
bl WifiHistory_GetPlayerCountry
add r1, r7, #0
add r1, #0xba
strb r0, [r1]
add r0, r5, #0
bl WiFiHistory_GetPlayerRegion
add r1, r7, #0
add r1, #0xbb
strb r0, [r1]
add r0, r4, #0
bl PlayerProfile_GetTrainerGender
add r1, r7, #0
add r1, #0xc8
lsl r0, r0, #0x18
lsr r0, r0, #0x18
lsl r0, r0, #0x1f
ldrb r1, [r1]
mov r2, #2
lsr r0, r0, #0x1e
bic r1, r2
orr r1, r0
add r0, r7, #0
add r0, #0xc8
strb r1, [r0]
add r0, r4, #0
bl PlayerProfile_GetAvatar
add r1, r0, #0
add r0, r7, #0
add r0, #0xc8
ldrb r0, [r0]
mov r2, #1
lsl r0, r0, #0x1e
lsr r0, r0, #0x1f
bl GetUnionRoomAvatarAttrBySprite
add r1, r7, #0
add r1, #0xc9
strb r0, [r1]
add r0, r7, #0
mov r4, #0
str r0, [sp, #8]
add r0, #0xca
add r5, r4, #0
str r0, [sp, #8]
_020695E4:
add r0, r6, #0
add r1, r4, #0
bl sub_0202D660
ldr r1, [sp, #8]
mov r2, #8
add r1, r1, r5
bl MI_CpuCopy8
add r4, r4, #1
add r5, #8
cmp r4, #3
blt _020695E4
add r0, r6, #0
mov r1, #3
bl sub_0202D660
add r1, r7, #0
add r1, #0xc0
mov r2, #8
bl MI_CpuCopy8
ldr r0, [sp]
cmp r0, #0
bne _0206963E
ldr r0, [sp, #4]
mov r1, #7
mov r2, #0
bl sub_0202D5DC
add r1, r7, #0
add r1, #0xe2
strh r0, [r1]
add r0, r7, #0
add r0, #0xe2
ldrh r0, [r0]
cmp r0, #0
beq _02069654
ldr r0, [sp, #4]
ldr r1, [sp]
add r2, r7, #0
bl sub_0202D4DC
add sp, #0xc
pop {r4, r5, r6, r7, pc}
_0206963E:
ldr r0, [sp, #4]
bl sub_0202D564
add r1, r7, #0
add r1, #0xe2
strh r0, [r1]
ldr r0, [sp, #4]
ldr r1, [sp]
add r2, r7, #0
bl sub_0202D4DC
_02069654:
add sp, #0xc
pop {r4, r5, r6, r7, pc}
.balign 4, 0
_02069658: .word gGameVersion
_0206965C: .word gGameLanguage
thumb_func_end sub_02069528

View File

@ -4,6 +4,7 @@
#include "frontier_data.h"
#include "pokemon_types_def.h"
#include "save.h"
#include "unk_02069528.h"
void sub_0202D234(u32 a0);
u32 sub_0202D284(u32 a0, u32 a1, void *a2);
@ -14,7 +15,9 @@ void sub_0202D3E4(u32 a0, u32 a1);
u32 sub_0202D450(FRONTIERDATA *a0, u32 a1);
u32 sub_0202D488(FRONTIERDATA *a0, u32 a1);
void sub_0202D4B8(FRONTIERDATA *a0, u32 a1, void *a2);
void sub_0202D4DC(FRONTIERDATA *a0, s32 a1, UnkStruct_02069528 *a2);
void sub_0202D4FC(FRONTIERDATA *a0, u32 a1);
s16 sub_0202D564(FRONTIERDATA *a0);
u32 sub_0202D57C(void *a0, u32 a1, u32 a2);
u32 sub_0202D5C4(FRONTIERDATA *a0, u32 a1, u16 a2);
u32 sub_0202D5DC(FRONTIERDATA *a0, u16 a1, u32 a2);
@ -24,6 +27,6 @@ u32 sub_0202D7B8(u32 a0);
void sub_0202D8D0(u32 a0, u8 *a1);
u32 sub_0202D908(SaveData *saveData);
u32 sub_0202D928(SaveData *saveData);
MailMessage *sub_0202D660(SaveData *saveData, u8 a1);
MailMessage *sub_0202D660(SaveData *saveData, u32 a1);
#endif // POKEHEARTGOLD_UNK_0202D230_H

30
include/unk_02069528.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef POKEHEARTGOLD_UNK_02069528_H
#define POKEHEARTGOLD_UNK_02069528_H
#include "global.h"
#include "frontier_data.h"
#include "pokemon_types_def.h"
#include "save.h"
typedef struct UnkStruct_02069528 {
u8 unk0[0xA8];
u16 *playerName;
u8 unkAC[0xC];
u8 gameVersion;
u8 gameLanguage;
u8 playerCountry;
u8 playerRegion;
u32 trainerId;
u8 unkC0[0x8];
u8 unkC8_0 : 1;
u8 playerGender : 1;
u8 unkC8_2 : 6;
u8 trainerClass;
u8 unkCA[0x18];
u16 unkE2;
} UnkStruct_02069528;
void sub_02069528(SaveData *saveData, s32 a1, UnkStruct_02069528 *a2);
#endif // POKEHEARTGOLD_UNK_02069528_H

View File

@ -244,7 +244,7 @@ Static main
Object src/gymmick_init.o
Object src/unk_02068F84.o
Object asm/unk_02068FC8.o
Object asm/unk_02069528.o
Object src/unk_02069528.o
Object asm/unk_02069660.o
Object asm/unk_0206979C.o
Object src/follow_mon.o

View File

@ -485,7 +485,7 @@ void sub_0203E960(TaskManager *taskman, int a1, UnkStruct_0203E8C8 *a2, u16 *a3,
args = EasyChat_CreateArgs(2, 0, fieldSystem->saveData, &fieldSystem->menuInputState, HEAP_ID_FIELD3);
data->easyChat = args;
sub_02090D40(args);
MailMessage *mailMessage = sub_0202D660(fieldSystem->saveData, a1 - 2);
MailMessage *mailMessage = sub_0202D660(fieldSystem->saveData, (u8)(a1 - 2));
sub_02090D20(data->easyChat, mailMessage);
sub_02090D34(data->easyChat);
}

40
src/unk_02069528.c Normal file
View File

@ -0,0 +1,40 @@
#include "unk_02069528.h"
#include "global.h"
#include "frontier_data.h"
#include "player_data.h"
#include "save_wifi_history.h"
#include "unk_0202D230.h"
#include "unk_0205B3DC.h"
void sub_02069528(SaveData *saveData, s32 a1, UnkStruct_02069528 *a2) {
PlayerProfile *playerProfile = Save_PlayerData_GetProfile(saveData);
SaveWiFiHistory *saveWiFiHistory = Save_WiFiHistory_Get(saveData);
FRONTIERDATA *frontierData = Save_FrontierData_Get(saveData);
MI_CpuFill8(a2, 0, sizeof(UnkStruct_02069528));
MI_CpuCopy8(PlayerProfile_GetNamePtr(playerProfile), &a2->playerName, (PLAYER_NAME_LENGTH + 1) * sizeof(u16));
a2->trainerId = PlayerProfile_GetTrainerID(playerProfile);
a2->gameVersion = gGameVersion;
a2->gameLanguage = gGameLanguage;
a2->playerCountry = WifiHistory_GetPlayerCountry(saveWiFiHistory);
a2->playerRegion = WiFiHistory_GetPlayerRegion(saveWiFiHistory);
a2->playerGender = PlayerProfile_GetTrainerGender(playerProfile);
a2->trainerClass = GetUnionRoomAvatarAttrBySprite(a2->playerGender, PlayerProfile_GetAvatar(playerProfile), 1);
for (s32 index = 0, position = 0; index < 3; index++, position += 8) {
MI_CpuCopy8(sub_0202D660(saveData, index), &a2->unkCA[position], 8);
}
MI_CpuCopy8(sub_0202D660(saveData, 3), &a2->unkC0, sizeof(a2->unkC0));
if (a1 == 0) {
a2->unkE2 = sub_0202D5DC(frontierData, 7, 0);
if (a2->unkE2 != 0) {
sub_0202D4DC(frontierData, a1, a2);
}
} else {
a2->unkE2 = sub_0202D564(frontierData);
sub_0202D4DC(frontierData, a1, a2);
}
}

View File

@ -1,4 +1,4 @@
Copyright (c) 2015 YamaArashi, 2021-2024 red031000
Copyright (c) 2015 YamaArashi, 2021-2025 red031000
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

File diff suppressed because it is too large Load Diff

View File

@ -81,7 +81,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 18
#define CJSON_VERSION_PATCH 19
#include <stddef.h>
@ -286,8 +286,11 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False | cJSON_True))) ? (object)->type = ((object)->type & (~(cJSON_False | cJSON_True))) | ((boolValue) ? cJSON_True : cJSON_False) : cJSON_Invalid)
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)

View File

@ -1,32 +1,29 @@
// Copyright (c) 2015 YamaArashi
#include "font.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "global.h"
#include "font.h"
#include "gfx.h"
#include "options.h"
#include "util.h"
unsigned char gFontPalette[][3] = {
{ 0x90, 0xC8, 0xFF }, // bg (saturated blue that contrasts well with the shadow color)
{ 0x38, 0x38, 0x38 }, // fg (dark grey)
{ 0xD8, 0xD8, 0xD8 }, // shadow (light grey)
{ 0xFF, 0xFF, 0xFF } // box (white)
{0x90, 0xC8, 0xFF}, // bg (saturated blue that contrasts well with the shadow color)
{0x38, 0x38, 0x38}, // fg (dark grey)
{0xD8, 0xD8, 0xD8}, // shadow (light grey)
{0xFF, 0xFF, 0xFF} // box (white)
};
// special palette for DS subscreen font
unsigned char gFontPalette_Subscreen[][3] = {
{ 0x90, 0xC8, 0xFF }, // bg (saturated blue that contrasts well with the shadow color)
{ 0xFF, 0xFF, 0xFF }, // fg (white)
{ 0xD8, 0xD8, 0xD8 }, // shadow (light grey)
{ 0x38, 0x38, 0x38 }, // outline (dark grey)
{0x90, 0xC8, 0xFF}, // bg (saturated blue that contrasts well with the shadow color)
{0xFF, 0xFF, 0xFF}, // fg (white)
{0xD8, 0xD8, 0xD8}, // shadow (light grey)
{0x38, 0x38, 0x38}, // outline (dark grey)
};
static void ConvertFromLatinFont(unsigned char *src, unsigned char *dest, unsigned int numRows)
@ -39,7 +36,7 @@ static void ConvertFromLatinFont(unsigned char *src, unsigned char *dest, unsign
unsigned int pixelsX = (column * 16) + ((glyphTile & 1) * 8);
for (unsigned int i = 0; i < 8; i++) {
unsigned int pixelsY = (row * 16) + ((glyphTile >> 1) * 8) + i;
unsigned int pixelsY = (row * 16) + ((glyphTile >> 1) * 8) + i;
unsigned int destPixelsOffset = (pixelsY * 64) + (pixelsX / 4);
dest[destPixelsOffset] = src[srcPixelsOffset + 1];
@ -88,7 +85,7 @@ static void ConvertFromHalfwidthJapaneseFont(unsigned char *src, unsigned char *
for (unsigned int i = 0; i < 8; i++) {
unsigned int pixelsY = (row * 16) + (glyphTile * 8) + i;
unsigned int destPixelsOffset = (pixelsY * 32) + (pixelsX / 4);
dest[destPixelsOffset] = src[srcPixelsOffset + 1];
dest[destPixelsOffset + 1] = src[srcPixelsOffset];
@ -171,7 +168,8 @@ static void ConvertToFullwidthJapaneseFont(unsigned char *src, unsigned char *de
}
}
static void ConvertFromNitroFont(unsigned char *src, unsigned char *dest, unsigned int numRows, struct NtrFontMetadata *metadata) {
static void ConvertFromNitroFont(unsigned char *src, unsigned char *dest, unsigned int numRows, struct NtrFontMetadata *metadata)
{
unsigned int srcPixelsOffset = 0;
unsigned int curGlyph = 0;
@ -194,7 +192,8 @@ static void ConvertFromNitroFont(unsigned char *src, unsigned char *dest, unsign
}
}
static void ConvertToNitroFont(unsigned char *src, unsigned char *dest, unsigned int numRows, struct NtrFontMetadata *metadata) {
static void ConvertToNitroFont(unsigned char *src, unsigned char *dest, unsigned int numRows, struct NtrFontMetadata *metadata)
{
unsigned int destPixelsOffset = 0;
unsigned int curGlyph = 0;
@ -232,7 +231,8 @@ static void SetFontPalette(struct Image *image)
image->hasTransparency = false;
}
static void SetSubscreenFontPalette(struct Image *image) {
static void SetSubscreenFontPalette(struct Image *image)
{
image->hasPalette = true;
image->palette.numColors = 4;
@ -253,9 +253,8 @@ void ReadLatinFont(char *path, struct Image *image)
int numGlyphs = fileSize / 64;
if (numGlyphs % 16 != 0) {
if (numGlyphs % 16 != 0)
FATAL_ERROR("The number of glyphs (%d) is not a multiple of 16.\n", numGlyphs);
}
int numRows = numGlyphs / 16;
@ -264,9 +263,8 @@ void ReadLatinFont(char *path, struct Image *image)
image->bitDepth = 2;
image->pixels = malloc(fileSize);
if (image->pixels == NULL) {
if (image->pixels == NULL)
FATAL_ERROR("Failed to allocate memory for font.\n");
}
ConvertFromLatinFont(buffer, image->pixels, numRows);
@ -277,21 +275,18 @@ void ReadLatinFont(char *path, struct Image *image)
void WriteLatinFont(char *path, struct Image *image)
{
if (image->width != 256) {
if (image->width != 256)
FATAL_ERROR("The width of the font image (%d) is not 256.\n", image->width);
}
if (image->height % 16 != 0) {
if (image->height % 16 != 0)
FATAL_ERROR("The height of the font image (%d) is not a multiple of 16.\n", image->height);
}
int numRows = image->height / 16;
int bufferSize = numRows * 16 * 64;
unsigned char *buffer = malloc(bufferSize);
if (buffer == NULL) {
if (buffer == NULL)
FATAL_ERROR("Failed to allocate memory for font.\n");
}
ConvertToLatinFont(image->pixels, buffer, numRows);
@ -307,15 +302,13 @@ void ReadHalfwidthJapaneseFont(char *path, struct Image *image)
int glyphSize = 32;
if (fileSize % glyphSize != 0) {
if (fileSize % glyphSize != 0)
FATAL_ERROR("The file size (%d) is not a multiple of %d.\n", fileSize, glyphSize);
}
int numGlyphs = fileSize / glyphSize;
if (numGlyphs % 16 != 0) {
if (numGlyphs % 16 != 0)
FATAL_ERROR("The number of glyphs (%d) is not a multiple of 16.\n", numGlyphs);
}
int numRows = numGlyphs / 16;
@ -324,9 +317,8 @@ void ReadHalfwidthJapaneseFont(char *path, struct Image *image)
image->bitDepth = 2;
image->pixels = malloc(fileSize);
if (image->pixels == NULL) {
if (image->pixels == NULL)
FATAL_ERROR("Failed to allocate memory for font.\n");
}
ConvertFromHalfwidthJapaneseFont(buffer, image->pixels, numRows);
@ -337,21 +329,18 @@ void ReadHalfwidthJapaneseFont(char *path, struct Image *image)
void WriteHalfwidthJapaneseFont(char *path, struct Image *image)
{
if (image->width != 128) {
if (image->width != 128)
FATAL_ERROR("The width of the font image (%d) is not 128.\n", image->width);
}
if (image->height % 16 != 0) {
if (image->height % 16 != 0)
FATAL_ERROR("The height of the font image (%d) is not a multiple of 16.\n", image->height);
}
int numRows = image->height / 16;
int bufferSize = numRows * 16 * 32;
unsigned char *buffer = malloc(bufferSize);
if (buffer == NULL) {
if (buffer == NULL)
FATAL_ERROR("Failed to allocate memory for font.\n");
}
ConvertToHalfwidthJapaneseFont(image->pixels, buffer, numRows);
@ -367,9 +356,8 @@ void ReadFullwidthJapaneseFont(char *path, struct Image *image)
int numGlyphs = fileSize / 64;
if (numGlyphs % 16 != 0) {
if (numGlyphs % 16 != 0)
FATAL_ERROR("The number of glyphs (%d) is not a multiple of 16.\n", numGlyphs);
}
int numRows = numGlyphs / 16;
@ -378,9 +366,8 @@ void ReadFullwidthJapaneseFont(char *path, struct Image *image)
image->bitDepth = 2;
image->pixels = malloc(fileSize);
if (image->pixels == NULL) {
if (image->pixels == NULL)
FATAL_ERROR("Failed to allocate memory for font.\n");
}
ConvertFromFullwidthJapaneseFont(buffer, image->pixels, numRows);
@ -391,21 +378,18 @@ void ReadFullwidthJapaneseFont(char *path, struct Image *image)
void WriteFullwidthJapaneseFont(char *path, struct Image *image)
{
if (image->width != 256) {
if (image->width != 256)
FATAL_ERROR("The width of the font image (%d) is not 256.\n", image->width);
}
if (image->height % 16 != 0) {
if (image->height % 16 != 0)
FATAL_ERROR("The height of the font image (%d) is not a multiple of 16.\n", image->height);
}
int numRows = image->height / 16;
int bufferSize = numRows * 16 * 64;
unsigned char *buffer = malloc(bufferSize);
if (buffer == NULL) {
if (buffer == NULL)
FATAL_ERROR("Failed to allocate memory for font.\n");
}
ConvertToFullwidthJapaneseFont(image->pixels, buffer, numRows);
@ -414,14 +398,16 @@ void WriteFullwidthJapaneseFont(char *path, struct Image *image)
free(buffer);
}
static inline uint32_t ReadLittleEndianWord(unsigned char *buffer, size_t start) {
static inline uint32_t ReadLittleEndianWord(unsigned char *buffer, size_t start)
{
return (buffer[start + 3] << 24)
| (buffer[start + 2] << 16)
| (buffer[start + 1] << 8)
| (buffer[start]);
}
void ReadNtrFont(char *path, struct Image *image, struct NtrFontMetadata *metadata, bool useSubscreenPalette) {
void ReadNtrFont(char *path, struct Image *image, struct NtrFontMetadata *metadata, bool useSubscreenPalette)
{
int filesize;
unsigned char *buffer = ReadWholeFile(path, &filesize);
@ -443,37 +429,33 @@ void ReadNtrFont(char *path, struct Image *image, struct NtrFontMetadata *metada
image->bitDepth = 2;
image->pixels = malloc(filesize);
if (image->pixels == NULL) {
if (image->pixels == NULL)
FATAL_ERROR("Failed to allocate memory for font.\n");
}
ConvertFromNitroFont(buffer + metadata->size, image->pixels, numRows, metadata);
free(buffer);
if (useSubscreenPalette) {
if (useSubscreenPalette)
SetSubscreenFontPalette(image);
} else {
else
SetFontPalette(image);
}
}
void WriteNtrFont(char *path, struct Image *image, struct NtrFontMetadata *metadata) {
if (image->width != 256) {
void WriteNtrFont(char *path, struct Image *image, struct NtrFontMetadata *metadata)
{
if (image->width != 256)
FATAL_ERROR("The width of the font image (%d) is not 256.\n", image->width);
}
if (image->height % 16 != 0) {
if (image->height % 16 != 0)
FATAL_ERROR("The height of the font image (%d) is not a multiple of 16.\n", image->height);
}
int numRows = image->height / 16;
int bufferSize = metadata->widthTableOffset + metadata->numGlyphs;
unsigned char *buffer = malloc(bufferSize);
if (buffer == NULL) {
if (buffer == NULL)
FATAL_ERROR("Failed to allocate memory for font.\n");
}
buffer[0x00] = (metadata->size & 0x000000FF);
buffer[0x01] = (metadata->size & 0x0000FF00) >> 8;
@ -500,7 +482,8 @@ void WriteNtrFont(char *path, struct Image *image, struct NtrFontMetadata *metad
free(buffer);
}
void FreeNtrFontMetadata(struct NtrFontMetadata *metadata) {
void FreeNtrFontMetadata(struct NtrFontMetadata *metadata)
{
free(metadata->glyphWidthTable);
free(metadata);
}

View File

@ -4,7 +4,6 @@
#define FONT_H
#include <stdbool.h>
#include "gfx.h"
#include "options.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// Copyright (c) 2015 YamaArashi, 2021-2024 red031000
// Copyright (c) 2015 YamaArashi, 2021-2025 red031000
#ifndef GFX_H
#define GFX_H
@ -51,16 +51,15 @@ struct Image {
};
void ReadImage(char *path, int tilesWide, int bitDepth, int colsPerChunk, int rowsPerChunk, struct Image *image, bool invertColors);
uint32_t ReadNtrImage(char *path, int tilesWide, int bitDepth, int colsPerChunk, int rowsPerChunk, struct Image *image, bool invertColors, bool scanFrontToBack);
uint32_t ReadNtrImage(char *path, int tilesWide, int bitDepth, int colsPerChunk, int rowsPerChunk, struct Image *image, bool invertColors, uint32_t encodeMode, bool convertTo8Bpp, int palIndex, bool verbose);
void ApplyCellsToImage(char *cellFilePath, struct Image *image, bool toPNG, bool snap);
void WriteImage(char *path, int numTiles, int bitDepth, int colsPerChunk, int rowsPerChunk, struct Image *image, bool invertColors);
void WriteNtrImage(char *path, int numTiles, int bitDepth, int colsPerChunk, int rowsPerChunk, struct Image *image,
bool invertColors, bool clobberSize, bool byteOrder, bool version101, bool sopc, bool vram, uint32_t scanMode,
uint32_t mappingType, uint32_t key, bool wrongSize);
void WriteNtrImage(char *path, int numTiles, int bitDepth, int colsPerChunk, int rowsPerChunk, struct Image *image, bool invertColors, bool clobberSize, bool byteOrder, bool version101, bool sopc, bool vram, bool scan, uint32_t encodeMode, uint32_t mappingType, uint32_t key, bool wrongSize, bool convertTo4Bpp);
void FreeImage(struct Image *image);
void ReadGbaPalette(char *path, struct Palette *palette);
void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIndex, bool inverted);
void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIndex, bool inverted, bool convertTo8Bpp);
void WriteGbaPalette(char *path, struct Palette *palette);
void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, int bitdepth, bool pad, int compNum, bool pcmp, bool inverted);
void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, int bitdepth, bool pad, int compNum, bool pcmp, int pcmpStartIndex, bool inverted, bool convertTo4Bpp);
void ReadNtrCell(char *path, struct JsonToCellOptions *options);
void WriteNtrCell(char *path, struct JsonToCellOptions *options);
void WriteNtrScreen(char *path, struct JsonToScreenOptions *options);

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021-2024 red031000
// Copyright (c) 2021-2025 red031000
#include "global.h"
#include "cJSON.h"
@ -47,13 +47,17 @@ struct JsonToCellOptions *ParseNCERJson(char *path)
}
cJSON *labelBool = cJSON_GetObjectItemCaseSensitive(json, "labelEnabled");
cJSON *dontPadKbecBool = cJSON_GetObjectItemCaseSensitive(json, "dontPadKbec");
cJSON *vramTransferBool = cJSON_GetObjectItemCaseSensitive(json, "vramTransferEnabled");
cJSON *ucatBool = cJSON_GetObjectItemCaseSensitive(json, "ucatEnabled");
cJSON *extended = cJSON_GetObjectItemCaseSensitive(json, "extended");
cJSON *cellCount = cJSON_GetObjectItemCaseSensitive(json, "cellCount");
cJSON *mappingType = cJSON_GetObjectItemCaseSensitive(json, "mappingType");
options->labelEnabled = GetBool(labelBool);
options->dontPadKbec = GetBool(dontPadKbecBool);
options->vramTransferEnabled = GetBool(vramTransferBool);
options->ucatEnabled = GetBool(ucatBool);
options->extended = GetBool(extended);
options->cellCount = GetInt(cellCount);
options->mappingType = GetInt(mappingType);
@ -79,17 +83,19 @@ struct JsonToCellOptions *ParseNCERJson(char *path)
}
}
if (options->vramTransferEnabled) {
if (options->vramTransferEnabled)
{
cJSON *vramTransferMaxSize = cJSON_GetObjectItemCaseSensitive(json, "vramTransferMaxSize");
options->vramTransferMaxSize = GetInt(vramTransferMaxSize);
options->transferData = malloc(sizeof(struct CellVramTransferData *) * options->cellCount);
cJSON *transfers = cJSON_GetObjectItemCaseSensitive(json, "transferData");
cJSON *transfer = NULL;
int j = 0;
cJSON_ArrayForEach(transfer, transfers) {
cJSON_ArrayForEach(transfer, transfers)
{
cJSON *vramTransferOffset = cJSON_GetObjectItemCaseSensitive(transfer, "offset");
cJSON *vramTransferSize = cJSON_GetObjectItemCaseSensitive(transfer, "size");
@ -101,6 +107,16 @@ struct JsonToCellOptions *ParseNCERJson(char *path)
}
}
if (options->ucatEnabled) {
cJSON *ucatCells = cJSON_GetObjectItemCaseSensitive(json, "cellAttributes");
options->ucatCellAttribtes = malloc(sizeof(uint32_t) * options->cellCount);
for (int i = 0; i < options->cellCount; i++) {
options->ucatCellAttribtes[i] = GetInt(cJSON_GetArrayItem(ucatCells, i));
}
}
for (int i = 0; i < options->cellCount; i++)
{
options->cells[i] = malloc(sizeof(struct Cell));
@ -172,7 +188,11 @@ struct JsonToCellOptions *ParseNCERJson(char *path)
cJSON *Colours = cJSON_GetObjectItemCaseSensitive(Attr0, "Colours");
cJSON *Shape = cJSON_GetObjectItemCaseSensitive(Attr0, "Shape");
options->cells[i]->oam[j].attr0.YCoordinate = GetInt(YCoordinate);
int y = GetInt(YCoordinate);
if (y & (1 << 7)) {
y &= 0xFF;
}
options->cells[i]->oam[j].attr0.YCoordinate = y;
options->cells[i]->oam[j].attr0.Rotation = GetBool(Rotation);
options->cells[i]->oam[j].attr0.SizeDisable = GetBool(SizeDisable);
options->cells[i]->oam[j].attr0.Mode = GetInt(Mode);
@ -187,7 +207,11 @@ struct JsonToCellOptions *ParseNCERJson(char *path)
cJSON *RotationScaling = cJSON_GetObjectItemCaseSensitive(Attr1, "RotationScaling");
cJSON *Size = cJSON_GetObjectItemCaseSensitive(Attr1, "Size");
options->cells[i]->oam[j].attr1.XCoordinate = GetInt(XCoordinate);
int x = GetInt(XCoordinate);
if (x & (1 << 8)) {
x &= 0x1FF;
}
options->cells[i]->oam[j].attr1.XCoordinate = x;
options->cells[i]->oam[j].attr1.RotationScaling = GetInt(RotationScaling);
options->cells[i]->oam[j].attr1.Size = GetInt(Size);
@ -218,8 +242,10 @@ char *GetNCERJson(struct JsonToCellOptions *options)
cJSON *ncer = cJSON_CreateObject();
cJSON_AddBoolToObject(ncer, "labelEnabled", options->labelEnabled);
cJSON_AddBoolToObject(ncer, "dontPadKbec", options->dontPadKbec);
cJSON_AddBoolToObject(ncer, "extended", options->extended);
cJSON_AddBoolToObject(ncer, "vramTransferEnabled", options->vramTransferEnabled);
cJSON_AddBoolToObject(ncer, "ucatEnabled", options->ucatEnabled);
cJSON_AddNumberToObject(ncer, "cellCount", options->cellCount);
cJSON_AddNumberToObject(ncer, "mappingType", options->mappingType);
@ -255,7 +281,11 @@ char *GetNCERJson(struct JsonToCellOptions *options)
cJSON *Attr0 = cJSON_AddObjectToObject(OAM, "Attr0");
cJSON_AddNumberToObject(Attr0, "YCoordinate", options->cells[i]->oam[j].attr0.YCoordinate);
int y = options->cells[i]->oam[j].attr0.YCoordinate;
if (y & (1 << 7)) {
y |= ~0xFF;
}
cJSON_AddNumberToObject(Attr0, "YCoordinate", y);
cJSON_AddBoolToObject(Attr0, "Rotation", options->cells[i]->oam[j].attr0.Rotation);
cJSON_AddBoolToObject(Attr0, "SizeDisable", options->cells[i]->oam[j].attr0.SizeDisable);
cJSON_AddNumberToObject(Attr0, "Mode", options->cells[i]->oam[j].attr0.Mode);
@ -265,7 +295,11 @@ char *GetNCERJson(struct JsonToCellOptions *options)
cJSON *Attr1 = cJSON_AddObjectToObject(OAM, "Attr1");
cJSON_AddNumberToObject(Attr1, "XCoordinate", options->cells[i]->oam[j].attr1.XCoordinate);
int x = options->cells[i]->oam[j].attr1.XCoordinate;
if (x & (1 << 8)) {
x |= ~0x1FF;
}
cJSON_AddNumberToObject(Attr1, "XCoordinate", x);
cJSON_AddNumberToObject(Attr1, "RotationScaling", options->cells[i]->oam[j].attr1.RotationScaling);
cJSON_AddNumberToObject(Attr1, "Size", options->cells[i]->oam[j].attr1.Size);
@ -288,11 +322,13 @@ char *GetNCERJson(struct JsonToCellOptions *options)
cJSON_AddNumberToObject(ncer, "labelCount", options->labelCount);
}
if (options->vramTransferEnabled) {
if (options->vramTransferEnabled)
{
cJSON_AddNumberToObject(ncer, "vramTransferMaxSize", options->vramTransferMaxSize);
cJSON *transfers = cJSON_AddArrayToObject(ncer, "transferData");
for (int idx = 0; idx < options->cellCount; idx++) {
for (int idx = 0; idx < options->cellCount; idx++)
{
cJSON *transfer = cJSON_CreateObject();
cJSON_AddNumberToObject(transfer, "offset", options->transferData[idx]->sourceDataOffset);
cJSON_AddNumberToObject(transfer, "size", options->transferData[idx]->size);
@ -300,6 +336,14 @@ char *GetNCERJson(struct JsonToCellOptions *options)
}
}
if (options->ucatEnabled) {
cJSON *ucatCells = cJSON_AddArrayToObject(ncer, "cellAttributes");
for (int i = 0; i < options->cellCount; i++) {
cJSON_AddNumberToObject(ucatCells, "cellAttr", options->ucatCellAttribtes[i]);
}
}
char *jsonString = cJSON_Print(ncer);
cJSON_Delete(ncer);
return jsonString;
@ -473,6 +517,9 @@ struct JsonToAnimationOptions *ParseNANRJson(char *path)
if (i > options->resultCount - 1)
FATAL_ERROR("Frame count is incorrect.\n");
// init padding to false, this is used in gfx.c to control padding, and is therefore checked there
options->animationResults[i]->padded = false;
cJSON *resultType = cJSON_GetObjectItemCaseSensitive(animationResult, "resultType");
options->animationResults[i]->resultType = GetInt(resultType);
switch (options->animationResults[i]->resultType) {
@ -538,6 +585,27 @@ struct JsonToAnimationOptions *ParseNANRJson(char *path)
}
}
cJSON *uaatBool = cJSON_GetObjectItemCaseSensitive(json, "uaatEnabled");
options->uaatEnabled = GetBool(uaatBool);
if (options->uaatEnabled) {
cJSON *uaatData = cJSON_GetObjectItemCaseSensitive(json, "uaatData");
cJSON *uaatSequences = cJSON_GetObjectItemCaseSensitive(uaatData, "sequenceAttributes");
options->uaatData.sequenceAttributes = malloc(sizeof(uint32_t) * options->sequenceCount);
for (int i = 0; i < options->sequenceCount; i++) {
cJSON *uaatSeq = cJSON_GetArrayItem(uaatSequences, i);
options->uaatData.sequenceAttributes[i] = GetInt(uaatSeq);
}
cJSON *uaatFrames = cJSON_GetObjectItemCaseSensitive(uaatData, "frameAttributes");
options->uaatData.frameAttributes = malloc(sizeof(uint32_t) * options->frameCount);
for (int i = 0; i < options->frameCount; i++) {
cJSON *uaatFra = cJSON_GetArrayItem(uaatFrames, i);
options->uaatData.frameAttributes[i] = GetInt(uaatFra);
}
}
cJSON_Delete(json);
free(jsonString);
return options;
@ -548,6 +616,7 @@ char *GetNANRJson(struct JsonToAnimationOptions *options)
cJSON *nanr = cJSON_CreateObject();
cJSON_AddBoolToObject(nanr, "labelEnabled", options->labelEnabled);
cJSON_AddBoolToObject(nanr, "uaatEnabled", options->uaatEnabled);
cJSON_AddNumberToObject(nanr, "sequenceCount", options->sequenceCount);
cJSON_AddNumberToObject(nanr, "frameCount", options->frameCount);
@ -617,6 +686,20 @@ char *GetNANRJson(struct JsonToAnimationOptions *options)
cJSON_AddNumberToObject(nanr, "labelCount", options->labelCount);
}
if (options->uaatEnabled) {
cJSON *uaat = cJSON_AddObjectToObject(nanr, "uaatData");
cJSON *uaatSequences = cJSON_AddArrayToObject(uaat, "sequenceAttributes");
for (int i = 0; i < options->sequenceCount; i++) {
cJSON_AddNumberToObject(uaatSequences, "seqAttr", options->uaatData.sequenceAttributes[i]);
}
cJSON *uaatFrames = cJSON_AddArrayToObject(uaat, "frameAttributes");
for (int i = 0; i < options->frameCount; i++) {
cJSON_AddNumberToObject(uaatFrames, "fraAttr", options->uaatData.frameAttributes[i]);
}
}
char *jsonString = cJSON_Print(nanr);
cJSON_Delete(nanr);
return jsonString;
@ -637,12 +720,17 @@ void FreeNCERCell(struct JsonToCellOptions *options)
}
free(options->labels);
}
if (options->vramTransferEnabled) {
for (int j = 0; j < options->cellCount; j++) {
if (options->vramTransferEnabled)
{
for (int j = 0; j < options->cellCount; j++)
{
free(options->transferData[j]);
}
free(options->transferData);
}
if (options->ucatEnabled) {
free(options->ucatCellAttribtes);
}
free(options->cells);
free(options);
}
@ -669,6 +757,10 @@ void FreeNANRAnimation(struct JsonToAnimationOptions *options)
{
free(options->animationResults[i]);
}
if (options->uaatEnabled) {
free(options->uaatData.sequenceAttributes);
free(options->uaatData.frameAttributes);
}
if (options->labelEnabled)
{
for (int j = 0; j < options->labelCount; j++)
@ -682,14 +774,16 @@ void FreeNANRAnimation(struct JsonToAnimationOptions *options)
free(options);
}
char *GetNtrFontMetadataJson(struct NtrFontMetadata *metadata) {
char *GetNtrFontMetadataJson(struct NtrFontMetadata *metadata)
{
cJSON *json = cJSON_CreateObject();
cJSON_AddNumberToObject(json, "maxGlyphWidth", metadata->maxWidth);
cJSON_AddNumberToObject(json, "maxGlyphHeight", metadata->maxHeight);
cJSON *glyphWidths = cJSON_AddArrayToObject(json, "glyphWidths");
for (int i = 0; i < metadata->numGlyphs; i++) {
for (int i = 0; i < metadata->numGlyphs; i++)
{
cJSON *width = cJSON_CreateNumber(metadata->glyphWidthTable[i]);
cJSON_AddItemToArray(glyphWidths, width);
}
@ -699,18 +793,20 @@ char *GetNtrFontMetadataJson(struct NtrFontMetadata *metadata) {
return jsonString;
}
#define TILE_DIMENSION_PIXELS 8
#define TILE_DIMENSION_PIXELS 8
#define PIXELS_FOR_DIMENSION(dim) ((dim) * TILE_DIMENSION_PIXELS)
#define TILES_FOR_PIXELS(num) (((num) + TILE_DIMENSION_PIXELS - 1) / TILE_DIMENSION_PIXELS)
#define PIXELS_PER_BYTE_2BPP 4
#define NTR_FONT_HEADER_SIZE 16
#define TILES_FOR_PIXELS(num) (((num) + TILE_DIMENSION_PIXELS - 1) / TILE_DIMENSION_PIXELS)
#define PIXELS_PER_BYTE_2BPP 4
#define NTR_FONT_HEADER_SIZE 16
struct NtrFontMetadata *ParseNtrFontMetadataJson(char *path) {
struct NtrFontMetadata *ParseNtrFontMetadataJson(char *path)
{
int fileLength;
unsigned char *jsonString = ReadWholeFile(path, &fileLength);
cJSON *json = cJSON_Parse((const char *)jsonString);
if (json == NULL) {
if (json == NULL)
{
const char *errorPtr = cJSON_GetErrorPtr();
FATAL_ERROR("Error in line \"%s\"\n", errorPtr);
}
@ -737,8 +833,10 @@ struct NtrFontMetadata *ParseNtrFontMetadataJson(char *path) {
uint8_t *glyphWidthCursor = metadata->glyphWidthTable;
cJSON *glyphWidthIter = NULL;
cJSON_ArrayForEach(glyphWidthIter, labelGlyphWidths) {
if (!cJSON_IsNumber(glyphWidthIter)) {
cJSON_ArrayForEach(glyphWidthIter, labelGlyphWidths)
{
if (!cJSON_IsNumber(glyphWidthIter))
{
const char *errorPtr = cJSON_GetErrorPtr();
FATAL_ERROR("Error in line \"%s\"\n", errorPtr);
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021-2024 red031000
// Copyright (c) 2021-2025 red031000
#ifndef JSON_H
#define JSON_H

View File

@ -1,43 +1,37 @@
// Copyright (c) 2015 YamaArashi
#include "lz.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "global.h"
#include "lz.h"
unsigned char *LZDecompress(unsigned char *src, int srcSize, int *uncompressedSize)
{
if (srcSize < 4) {
if (srcSize < 4)
goto fail;
}
int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
unsigned char *dest = malloc(destSize);
if (dest == NULL) {
if (dest == NULL)
goto fail;
}
int srcPos = 4;
int destPos = 0;
for (;;) {
if (srcPos >= srcSize) {
if (srcPos >= srcSize)
goto fail;
}
unsigned char flags = src[srcPos++];
for (int i = 0; i < 8; i++) {
if (flags & 0x80) {
if (srcPos + 1 >= srcSize) {
if (srcPos + 1 >= srcSize)
goto fail;
}
int blockSize = (src[srcPos] >> 4) + 3;
int blockDistance = (((src[srcPos] & 0xF) << 8) | src[srcPos + 1]) + 1;
@ -52,17 +46,14 @@ unsigned char *LZDecompress(unsigned char *src, int srcSize, int *uncompressedSi
fprintf(stderr, "Destination buffer overflow.\n");
}
if (blockPos < 0) {
if (blockPos < 0)
goto fail;
}
for (int j = 0; j < blockSize; j++) {
for (int j = 0; j < blockSize; j++)
dest[destPos++] = dest[blockPos + j];
}
} else {
if (srcPos >= srcSize || destPos >= destSize) {
if (srcPos >= srcSize || destPos >= destSize)
goto fail;
}
dest[destPos++] = src[srcPos++];
}
@ -80,32 +71,32 @@ fail:
FATAL_ERROR("Fatal error while decompressing LZ file.\n");
}
static void FindBestBlockForwards(unsigned char *src, int srcPos, int srcSize, const int minDistance, int *outBestBlockDistance, int *outBestBlockSize) {
static void FindBestBlockForwards(unsigned char *src, int srcPos, int srcSize, const int minDistance, int *outBestBlockDistance, int *outBestBlockSize)
{
int blockStart = srcPos < 0x1000 ? 0 : srcPos - 0x1000;
while (blockStart != srcPos) {
int blockSize = 0;
while (blockSize < 18
&& srcPos + blockSize < srcSize
&& src[blockStart + blockSize] == src[srcPos + blockSize]) {
&& src[blockStart + blockSize] == src[srcPos + blockSize])
blockSize++;
}
if (blockSize > *outBestBlockSize
&& srcPos - blockStart >= minDistance) {
*outBestBlockDistance = srcPos - blockStart;
*outBestBlockSize = blockSize;
if (blockSize == 18) {
if (blockSize == 18)
break;
}
}
blockStart++;
}
}
static void FindBestBlockBackwards(unsigned char *src, int srcPos, int srcSize, const int minDistance, int *outBestBlockDistance, int *outBestBlockSize) {
static void FindBestBlockBackwards(unsigned char *src, int srcPos, int srcSize, const int minDistance, int *outBestBlockDistance, int *outBestBlockSize)
{
int blockDistance = minDistance;
while (blockDistance <= srcPos && blockDistance <= 0x1000) {
@ -114,17 +105,15 @@ static void FindBestBlockBackwards(unsigned char *src, int srcPos, int srcSize,
while (blockSize < 18
&& srcPos + blockSize < srcSize
&& src[blockStart + blockSize] == src[srcPos + blockSize]) {
&& src[blockStart + blockSize] == src[srcPos + blockSize])
blockSize++;
}
if (blockSize > *outBestBlockSize) {
*outBestBlockDistance = blockDistance;
*outBestBlockSize = blockSize;
if (blockSize == 18) {
if (blockSize == 18)
break;
}
}
blockDistance++;
@ -133,10 +122,9 @@ static void FindBestBlockBackwards(unsigned char *src, int srcPos, int srcSize,
typedef void (*FindBestBlockFunc)(unsigned char *src, int srcPos, int srcSize, const int minDistance, int *outBestBlockDistance, int *outBestBlockSize);
unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance, bool forwardIteration) {
if (srcSize <= 0) {
unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance, bool forwardIteration, bool pad) {
if (srcSize <= 0)
goto fail;
}
int worstCaseDestSize = 4 + srcSize + ((srcSize + 7) / 8);
@ -145,9 +133,8 @@ unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize,
unsigned char *dest = malloc(worstCaseDestSize);
if (dest == NULL) {
if (dest == NULL)
goto fail;
}
// header
dest[0] = 0x10; // LZ compression type
@ -181,12 +168,14 @@ unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize,
}
if (srcPos == srcSize) {
// Pad to multiple of 4 bytes.
int remainder = destPos % 4;
if (pad) {
// Pad to multiple of 4 bytes.
int remainder = destPos % 4;
if (remainder != 0) {
for (int i = 0; i < 4 - remainder; i++) {
dest[destPos++] = 0;
if (remainder != 0) {
for (int i = 0; i < 4 - remainder; i++) {
dest[destPos++] = 0;
}
}
}

View File

@ -6,6 +6,6 @@
#include "stdbool.h"
unsigned char *LZDecompress(unsigned char *src, int srcSize, int *uncompressedSize);
unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance, bool forwardIteration);
unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance, bool forwardIteration, bool pad);
#endif // LZ_H

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// Copyright (c) 2018 huderlem, 2021-2024 red031000
// Copyright (c) 2018 huderlem, 2021-2025 red031000
#ifndef OPTIONS_H
#define OPTIONS_H
@ -24,6 +24,8 @@ struct PngToGbaOptions {
};
struct PngToNtrOptions {
char *cellFilePath;
bool cellSnap;
int numTiles;
int bitDepth;
int colsPerChunk;
@ -32,23 +34,29 @@ struct PngToNtrOptions {
bool byteOrder;
bool version101;
bool sopc;
uint32_t scanMode;
bool scan;
bool wrongSize;
bool handleEmpty;
bool vramTransfer;
int mappingType;
uint32_t encodeMode;
bool convertTo4Bpp;
};
struct NtrToPngOptions {
char *paletteFilePath;
char *cellFilePath;
bool cellSnap;
int bitDepth;
bool hasTransparency;
int width;
int colsPerChunk;
int rowsPerChunk;
int palIndex;
bool scanFrontToBack;
bool handleEmpty;
uint32_t encodeMode;
bool convertTo8Bpp;
bool verbose;
};
struct CellVramTransferData {
@ -104,8 +112,10 @@ struct Cell {
struct JsonToCellOptions {
bool labelEnabled;
bool dontPadKbec;
bool extended;
bool vramTransferEnabled;
bool ucatEnabled;
int mappingType;
int cellCount;
struct Cell **cells;
@ -113,6 +123,7 @@ struct JsonToCellOptions {
struct CellVramTransferData **transferData;
char **labels;
int labelCount;
int *ucatCellAttribtes;
};
struct JsonToScreenOptions {
@ -163,6 +174,11 @@ struct AnimationResults {
};
};
struct UaatData {
int *sequenceAttributes;
int *frameAttributes;
};
struct JsonToAnimationOptions {
bool multiCell;
short sequenceCount;
@ -173,6 +189,8 @@ struct JsonToAnimationOptions {
char **labels;
int labelCount;
short resultCount;
bool uaatEnabled;
struct UaatData uaatData;
};
struct NtrFontOptions {

View File

@ -14,29 +14,24 @@ bool ParseNumber(char *s, char **end, int radix, int *intValue)
{
char *localEnd;
if (end == NULL) {
if (end == NULL)
end = &localEnd;
}
errno = 0;
const long longValue = strtol(s, end, radix);
if (*end == s) {
if (*end == s)
return false; // not a number
}
if ((longValue == LONG_MIN || longValue == LONG_MAX) && errno == ERANGE) {
if ((longValue == LONG_MIN || longValue == LONG_MAX) && errno == ERANGE)
return false;
}
if (longValue > INT_MAX) {
if (longValue > INT_MAX)
return false;
}
if (longValue < INT_MIN) {
if (longValue < INT_MIN)
return false;
}
*intValue = (int)longValue;
@ -47,22 +42,29 @@ char *GetFileExtension(char *path)
{
char *extension = path;
while (*extension != 0) {
while (*extension != 0)
extension++;
}
while (extension > path && *extension != '.') {
while (extension > path && *extension != '.')
extension--;
}
if (extension == path) {
if (extension == path)
return NULL;
}
extension++;
if (*extension == 0) {
if (*extension == 0)
return NULL;
if (strcmp(extension, "lz") == 0) {
char *plainName = malloc(strlen(path) + 1);
strcpy(plainName, path);
plainName[strlen(path) - 3] = 0;
char *newExtension = GetFileExtension(plainName);
if (newExtension != NULL) {
extension -= strlen(newExtension) + 1;
}
free(plainName);
}
return extension;
@ -72,9 +74,8 @@ unsigned char *ReadWholeFile(char *path, int *size)
{
FILE *fp = fopen(path, "rb");
if (fp == NULL) {
if (fp == NULL)
FATAL_ERROR("Failed to open \"%s\" for reading.\n", path);
}
fseek(fp, 0, SEEK_END);
@ -82,15 +83,13 @@ unsigned char *ReadWholeFile(char *path, int *size)
unsigned char *buffer = malloc(*size);
if (buffer == NULL) {
if (buffer == NULL)
FATAL_ERROR("Failed to allocate memory for reading \"%s\".\n", path);
}
rewind(fp);
if (fread(buffer, *size, 1, fp) != 1) {
if (fread(buffer, *size, 1, fp) != 1)
FATAL_ERROR("Failed to read \"%s\".\n", path);
}
fclose(fp);
@ -101,9 +100,8 @@ unsigned char *ReadWholeFileZeroPadded(char *path, int *size, int padAmount)
{
FILE *fp = fopen(path, "rb");
if (fp == NULL) {
if (fp == NULL)
FATAL_ERROR("Failed to open \"%s\" for reading.\n", path);
}
fseek(fp, 0, SEEK_END);
@ -111,15 +109,13 @@ unsigned char *ReadWholeFileZeroPadded(char *path, int *size, int padAmount)
unsigned char *buffer = calloc(*size + padAmount, 1);
if (buffer == NULL) {
if (buffer == NULL)
FATAL_ERROR("Failed to allocate memory for reading \"%s\".\n", path);
}
rewind(fp);
if (fread(buffer, *size, 1, fp) != 1) {
if (fread(buffer, *size, 1, fp) != 1)
FATAL_ERROR("Failed to read \"%s\".\n", path);
}
fclose(fp);
@ -130,13 +126,11 @@ void WriteWholeStringToFile(char *path, char *string)
{
FILE *fp = fopen(path, "wb");
if (fp == NULL) {
if (fp == NULL)
FATAL_ERROR("Failed to open \"%s\" for writing.\n", path);
}
if (fputs(string, fp) == EOF) {
if (fputs(string, fp) == EOF)
FATAL_ERROR("Failed to write to \"%s\".\n", path);
}
fclose(fp);
}
@ -145,13 +139,11 @@ void WriteWholeFile(char *path, void *buffer, int bufferSize)
{
FILE *fp = fopen(path, "wb");
if (fp == NULL) {
if (fp == NULL)
FATAL_ERROR("Failed to open \"%s\" for writing.\n", path);
}
if (fwrite(buffer, bufferSize, 1, fp) != 1) {
if (fwrite(buffer, bufferSize, 1, fp) != 1)
FATAL_ERROR("Failed to write to \"%s\".\n", path);
}
fclose(fp);
}