mirror of https://github.com/pret/pokeheartgold
Merge remote-tracking branch 'origin/master' into decomp/pokegear-configure
This commit is contained in:
commit
16920eeb9d
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
2
main.lsf
2
main.lsf
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#define FONT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "gfx.h"
|
||||
#include "options.h"
|
||||
|
||||
|
|
|
|||
1901
tools/nitrogfx/gfx.c
1901
tools/nitrogfx/gfx.c
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2021-2024 red031000
|
||||
// Copyright (c) 2021-2025 red031000
|
||||
|
||||
#ifndef JSON_H
|
||||
#define JSON_H
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue