Removed ARM9 compression

This commit is contained in:
AnonymousRandomPerson 2023-07-16 00:08:40 -04:00
parent c52c9d4027
commit cb5957ccf5
30 changed files with 4 additions and 1961 deletions

1
.gitignore vendored
View File

@ -62,7 +62,6 @@ files/**/*.c
# Utilities
ntruncompbw
*.elf
*.sbin_LZ
*.diff
*.dSYM

View File

@ -40,23 +40,16 @@ clean: tidy clean-filesystem clean-tools
@$(MAKE) -C lib/syscall clean
@$(MAKE) -C sub clean
SBIN_LZ := $(SBIN)_LZ
.PHONY: main_lz
sdk9 sdk7: sdk
main filesystem: | sdk9
sub: | sdk7
main: $(SBIN) $(ELF)
main_lz: $(SBIN_LZ)
sub: ; @$(MAKE) -C sub
ROMSPEC := rom.rsf
MAKEROM_FLAGS := $(DEFINES)
$(SBIN_LZ): $(BUILD_DIR)/component.files
$(COMPSTATIC) -9 -c -f $<
$(NEF): libsyscall
libsyscall:
@ -66,7 +59,7 @@ $(BUILD_DIR)/component.files: main ;
$(HEADER_TEMPLATE): ;
$(ROM): $(ROMSPEC) tools filesystem main_lz sub $(BANNER)
$(ROM): $(ROMSPEC) tools filesystem main sub $(BANNER)
$(WINE) $(MAKEROM) $(MAKEROM_FLAGS) -DBUILD_DIR=$(BUILD_DIR) -DNITROFS_FILES="$(NITROFS_FILES:files/%=%)" -DTITLE_NAME="$(TITLE_NAME)" -DBNR="$(BANNER)" -DHEADER_TEMPLATE="$(HEADER_TEMPLATE)" $< $@
$(FIXROM) $@ --secure-crc $(SECURE_CRC) --game-code $(GAME_CODE)
ifeq ($(COMPARE),1)

View File

@ -53,9 +53,6 @@ CSV2BIN := $(TOOLSDIR)/csv2bin/csv2bin$(EXE)
MKFXCONST := $(TOOLSDIR)/gen_fx_consts/gen_fx_consts$(EXE)
MOD123ENCRY := $(TOOLSDIR)/mod123encry/mod123encry$(EXE)
# Decompiled NitroSDK tools
COMPSTATIC := $(TOOLSDIR)/compstatic/compstatic$(EXE)
NTRMERGE := $(TOOLSDIR)/ntr_merge_elf/ntr_merge_elf.sh
ASM_PROCESSOR := $(TOOLSDIR)/asm_processor/compile.sh
@ -69,7 +66,6 @@ NATIVE_TOOLS := \
$(ASPATCH) \
$(CSV2BIN) \
$(MKFXCONST) \
$(COMPSTATIC) \
$(MOD123ENCRY)
TOOLDIRS := $(foreach tool,$(NATIVE_TOOLS),$(dir $(tool)))

View File

@ -1,8 +1,8 @@
Arm9
{
Static $(BUILD_DIR)/main.sbin_LZ
OverlayDefs $(BUILD_DIR)/main_defs.sbin_LZ
OverlayTable $(BUILD_DIR)/main_table.sbin_LZ
Static $(BUILD_DIR)/main.sbin
OverlayDefs $(BUILD_DIR)/main_defs.sbin
OverlayTable $(BUILD_DIR)/main_table.sbin
Nef $(BUILD_DIR)/main.nef
}

View File

@ -1 +0,0 @@
compstatic

View File

@ -1,32 +0,0 @@
CC := gcc
CFLAGS := -O3
SRCS = $(wildcard *.c)
OBJS = $(SRCS:%.c=%.o)
prog := compstatic
.PHONY: all clean
DEPDIR := .deps
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
all: $(prog)
@:
clean:
$(RM) -r $(DEPDIR) $(OBJS) $(prog) $(prog).exe
$(prog): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^
$(OBJS): %.o: %.c
$(OBJS): %.o: %.c $(DEPDIR)/%.d | $(DEPDIR)
$(CC) $(CFLAGS) $(DEPFLAGS) -c -o $@ $<
$(DEPDIR): ; @mkdir -p $@
DEPFILES := $(SRCS:%.c=$(DEPDIR)/%.d)
$(DEPFILES):
include $(wildcard $(DEPFILES))

View File

@ -1,187 +0,0 @@
#include <stdbool.h>
#include <string.h>
#include "component.h"
#include "compress.h"
#include "global.h"
#include "overlay_defs.h"
#include "overlay_modules.h"
#include "overlay_table.h"
#include "print.h"
#include "static_module.h"
#include "str.h"
static bool ReadComponent(Component *component, char *staticModule, char *overlayDefs, char *overlayTable);
static bool WriteComponent(Component *component);
static bool ComponentAddSuffix(Component *component, char *suffix);
static void FreeComponent(Component *component);
static void DebugPrintComponent(Component *component);
bool ConvertComponent(Options *options, char *staticModule, char *overlayDefs, char *overlayTable) {
bool finalSuccess = false;
Component component;
memset(&component, 0, sizeof(component));
bool success = ReadComponent(&component, staticModule, overlayDefs, overlayTable);
if (success) {
DebugPrintComponent(&component);
if (!options->overlayModules || CompressOverlayModules(&component)) {
if (!options->overlayDigest || CalculateHMAC_OverlayModules(&component, options->digestType, options->digestKey)) {
if (!options->staticModule || CompressStaticModule(&component, options->headerSize)) {
if (options->outSuffix == NULL || ComponentAddSuffix(&component, options->outSuffix)) {
DebugPrintComponent(&component);
finalSuccess = WriteComponent(&component);
}
}
}
}
}
FreeComponent(&component);
return finalSuccess;
}
static bool ReadComponent(Component *component, char *staticModule, char *overlayDefs, char *overlayTable) {
bool finalSuccess = false;
bool success = ReadOverlayDefs(component, overlayDefs);
if (success) {
success = ReadStaticModule(component, staticModule);
if (success) {
success = ReadOverlayTable(component, overlayTable);
if (success) {
finalSuccess = ReadOverlayModules(component);
}
}
}
return finalSuccess;
}
static bool WriteComponent(Component *component) {
bool finalSuccess = false;
bool success = WriteOverlayDefs(component);
if (success) {
success = WriteStaticModule(component);
if (success) {
success = WriteOverlayTable(component);
if (success) {
finalSuccess = WriteOverlayModules(component);
}
}
}
return finalSuccess;
}
static bool ComponentAddSuffix(Component *component, char *suffix) {
if (suffix == NULL || *suffix == '\0') return true;
bool finalSuccess = false;
bool success = AddSuffixOverlayDefs(component, suffix);
if (success) {
success = AddSuffixStaticModule(component, suffix);
if (success) {
success = AddSuffixOverlayTable(component, suffix);
if (success) {
finalSuccess = AddSuffixOverlayModules(component, suffix);
}
}
}
return finalSuccess;
}
static void FreeComponent(Component *component) {
FreeOverlayDefs(component);
FreeStaticModule(component);
FreeOverlayTable(component);
FreeOverlayModules(component);
component->numOverlays = 0;
}
static void DebugPrintComponent(Component *component) {
int i;
char *filename;
char c;
uint staticParamsOffset = *(uint *)(component->staticModule.footerContent + 4);
StaticParams *staticParams = (StaticParams *)(component->staticModule.fileInfo.content + staticParamsOffset);
DebugPrintf("-------------------------------------------------------------\n");
DebugPrintf("static.buffer.filename = %s\n"
" .ptr = %p\n"
" .size = %p %9d\n"
" .compressed = %p %9d\n"
" .footerSize = %p %9d\n"
" .footer = %p\n"
" .footer.magicNumber = %08x %9s\n"
" .staticParamsOffset = %p %9d\n"
" .digestParamsOffset = %p %9d\n",
component->staticModule.fileInfo.filename,
component->staticModule.fileInfo.content,
component->staticModule.fileInfo.fileSize, component->staticModule.fileInfo.fileSize,
component->staticModule.fileInfo.compressedSize, component->staticModule.fileInfo.compressedSize,
component->staticModule.footerSize, component->staticModule.footerSize,
component->staticModule.footerContent,
*(uint *)(component->staticModule.footerContent + STATIC_FOOTER_MAGIC_OFFSET), (*(uint *)(component->staticModule.footerContent + STATIC_FOOTER_MAGIC_OFFSET) == 0xDEC00621) ? "NITROCODE" : "UNKNOWN!!",
*(uint *)(component->staticModule.footerContent + STATIC_FOOTER_STATIC_PARAM_OFFSET), *(uint *)(component->staticModule.footerContent + STATIC_FOOTER_STATIC_PARAM_OFFSET),
*(uint *)(component->staticModule.footerContent + STATIC_FOOTER_DIGEST_PARAM_OFFSET), *(uint *)(component->staticModule.footerContent + STATIC_FOOTER_DIGEST_PARAM_OFFSET));
DebugPrintf("static.Params = %p\n"
" .Params.autoloadList = %p\n"
" .Params.autoloadListEnd = %p\n"
" .Params.autoloadStart = %p\n"
" .Params.staticBssStart = %p\n"
" .Params.staticBssEnd = %p\n"
" .Params.compressedStatic = %p\n",
component->staticModule.fileInfo.content + staticParamsOffset,
staticParams->autoloadList,
staticParams->autoloadListEnd,
staticParams->autoloadStart,
staticParams->staticBssStart,
staticParams->staticBssEnd,
staticParams->compressedStatic);
DebugPrintf("-------------------------------------------------------------\n");
DebugPrintf("numOverlays = %d\n", component->numOverlays);
DebugPrintf("-------------------------------------------------------------\n");
DebugPrintf("ovdefs.buffer.filename = %s\n"
" .ptr = %p\n"
" .size = %p %9d\n"
" .compressed = %p %9d\n"
" .header = %p\n"
" .header.loadAddress = %p\n"
" .header.entryAddress = %p\n"
" .header.moduleSize = %p %9d\n"
" .header.autoloadDone = %p\n"
" .dirname = %s\n",
component->overlayDefs.fileInfo.filename,
component->overlayDefs.fileInfo.content,
&component->overlayDefs.fileInfo.fileSize, component->overlayDefs.fileInfo.fileSize,
&component->overlayDefs.fileInfo.compressedSize, component->overlayDefs.fileInfo.compressedSize,
component->overlayDefs.header,
*(uint *)(component->overlayDefs.header + OVERLAY_DEFS_HEADER_LOAD_ADDRESS_OFFSET),
*(uint *)(component->overlayDefs.header + OVERLAY_DEFS_HEADER_ENTRY_ADDRESS_OFFSET),
component->overlayDefs.header + OVERLAY_DEFS_HEADER_MODULE_SIZE_OFFSET, *(uint *)(component->overlayDefs.header + OVERLAY_DEFS_HEADER_MODULE_SIZE_OFFSET),
*(uint *)(component->overlayDefs.header + OVERLAY_DEFS_HEADER_AUTOLOAD_DONE_OFFSET),
component->dirName);
filename = component->overlayFilenames;
for (i = 0; i < component->numOverlays; i++) {
DebugPrintf(" .filename[%2d] = %s\n", i, filename);
do {
c = *filename;
filename++;
} while (c != '\0');
}
DebugPrintf("-------------------------------------------------------------\n");
DebugPrintf("-------------------------------------------------------------\n");
}
void ConvertFinal(Options *options) {
options->digestKey = StrDup(options->digestKey, NULL);
options->outSuffix = StrDup(options->outSuffix, NULL);
}

View File

@ -1,10 +0,0 @@
#ifndef COMPONENT_H
#define COMPONENT_H
#include <stdbool.h>
#include "global.h"
bool ConvertComponent(Options *options, char *staticModule, char *overlayDefs, char *overlayTable);
void ConvertFinal(Options *options);
#endif // COMPONENT_H

View File

@ -1,333 +0,0 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "component.h"
#include "compress.h"
#include "digest.h"
#include "global.h"
#include "misc.h"
#include "overlay_table.h"
#include "print.h"
#include "static_module.h"
static int Compress(char *content, int size);
static int LZCompressRV(char *uncompressed, int uncompressedSize, char *compressed, int compressedSize);
static int FindMatched(char *chunk, int chunkSize, char *remainder, int remainderSize, int *optimalRemainderIdx);
static int HowManyMatched(char *buffer1, char *buffer2, int size);
static int CheckOverwrite(int sourceSize, char *compressed, int compressedSize, int *newSourceSize, int *newCompressedSize);
bool CompressOverlayModules(Component *component) {
OverlayModule *overlayModule = component->overlayModules;
char *overlayTable = component->overlayTable.table;
DebugPrintf("Compressing OverlayModules\n");
if (component->numOverlays == 0 || overlayModule == NULL || overlayTable == NULL) {
DebugPrintf("No overlay to compress\n");
} else {
for (int i = 0; i < component->numOverlays; i++) {
if ((overlayTable[OT_COMPRESSED_FLAGS_OFFSET] & 1) == 0) {
if (overlayModule->fileInfo.fileSize < *(uint *)(overlayTable + OT_FILESIZE_OFFSET)) {
ErrorPrintf("Overlay module file is shorter than the size reported in the overlay table\n"
"FileSize=%d InOverlayTable=%d\n", overlayModule->fileInfo.fileSize, *(uint *)(overlayTable + OT_FILESIZE_OFFSET));
return false;
}
int compressResult = Compress(overlayModule->fileInfo.content, *(int *)(overlayTable + OT_FILESIZE_OFFSET));
if (compressResult < 0) {
if (compressResult == -2 || compressResult != -1) return false;
printf("OverlayModule[%02d]. Not compressed %9d (enlarged or same size as before)\n", i, overlayModule->fileInfo.fileSize);
} else {
if (compressResult > 0x00ffffff) {
ErrorPrintf("Compressed file size too large (over 24bit wide)\n");
}
printf("OverlayModule[%02d]. Compressed ... %9d -> %9d\n", i, overlayModule->fileInfo.fileSize, compressResult);
uint *overlayTableCompressedSize = (uint *)(overlayTable + OT_COMPRESSED_FILESIZE_OFFSET);
*overlayTableCompressedSize = (*overlayTableCompressedSize & 0xff000000) | (compressResult & 0x00ffffff);
overlayModule->fileInfo.compressedSize = compressResult & 0x00ffffff;
overlayModule->fileInfo.compressedSize = compressResult & 0x00ffffff;
overlayTable[OT_COMPRESSED_FLAGS_OFFSET] |= 1;
overlayModule->fileInfo.rewrite = true;
component->overlayTable.fileInfo.rewrite = true;
}
} else {
printf("OverlayModule[%02d]. Already compressed\n", i);
}
overlayModule++;
overlayTable += OVERLAY_ENTRY_SIZE;
}
}
return true;
}
bool CompressStaticModule(Component *component, int headerSize) {
bool success;
int staticParamsOffset = *(int *)(component->staticModule.footerContent + 4);
char *content = component->staticModule.fileInfo.content;
StaticParams *staticParams = (StaticParams *)(content + staticParamsOffset);
if (staticParams->compressedStatic == 0 &&
component->staticModule.fileInfo.compressedSize == 0) {
if (headerSize < 0) {
ErrorPrintf("Specified header size is less than 0 (=%d)\n", headerSize);
success = false;
} else if (component->staticModule.fileInfo.fileSize < headerSize) {
printf("StaticModule ..... Not compressed (Module is smaller than the header [%d bytes])\n", headerSize);
success = true;
} else {
int compressResult =
Compress(component->staticModule.fileInfo.content + headerSize,
component->staticModule.fileInfo.fileSize - headerSize);
if (compressResult < 0) {
if (compressResult == -2 || compressResult != -1) {
success = false;
} else {
printf("StaticModule ..... Not compressed (enlarged or same size as before)\n");
success = true;
}
} else {
component->staticModule.fileInfo.compressedSize = compressResult + headerSize;
printf("StaticModule ..... Compressed ... %9d -> %9d\n",
component->staticModule.fileInfo.fileSize, component->staticModule.fileInfo.compressedSize);
int *header = (int *)component->overlayDefs.header;
header[2] = component->staticModule.fileInfo.compressedSize;
staticParams->compressedStatic = component->staticModule.fileInfo.compressedSize + header[0];
CopyBuffer(component->staticModule.footerContent,
component->staticModule.fileInfo.content + ALIGN_4(component->staticModule.fileInfo.compressedSize),
component->staticModule.footerSize);
component->overlayDefs.fileInfo.rewrite = true;
component->staticModule.fileInfo.rewrite = true;
success = true;
}
}
} else {
printf("StaticModule ..... Already compressed\n");
success = true;
}
return success;
}
bool CalculateHMAC_OverlayModules(Component *component, int digestType, char *digestKey) {
bool success;
OverlayModule *overlayModule = component->overlayModules;
char *overlayTable = component->overlayTable.table;
int numOverlays = component->numOverlays;
if (numOverlays == 0 || overlayModule == NULL || overlayTable == NULL) {
DebugPrintf("No overlay to calculate HMAC\n");
success = true;
} else {
bool initDigestSuccess = Init_Digest(digestType, digestKey);
if (!initDigestSuccess) {
ErrorPrintf("Cannot setup digest library\n");
success = false;
} else {
DebugPrintf("Calculating HMAC for OverlayModules\n");
int digestParamsOffset = *(int *)(component->staticModule.footerContent + STATIC_FOOTER_DIGEST_PARAM_OFFSET);
char *content = component->staticModule.fileInfo.content;
char *digestParams = (char *)(content + digestParamsOffset);
for (int i = 0; i < numOverlays; i++) {
if ((overlayTable[OT_COMPRESSED_FLAGS_OFFSET] & 2U) != 0) {
printf("OverlayModule[%02d]: HMAC already calculated - do it again.\n", i);
}
if ((uint)overlayModule->fileInfo.fileSize < *(uint *)(overlayTable + OT_FILESIZE_OFFSET)) {
ErrorPrintf("Overlay module file is shorter than the size reported in overlay table\n"
" File size=%d InOverlayTabe=%d\n", overlayModule->fileInfo.fileSize, *(uint *)(overlayTable + OT_FILESIZE_OFFSET));
return false;
}
uint overlaySize = *(uint *)(overlayTable + OT_COMPRESSED_FILESIZE_OFFSET) & 0x00ffffff;
if (overlaySize == 0) {
overlaySize = *(uint *)(overlayTable + OT_FILESIZE_OFFSET);
}
printf("OverlayModule[%02d]", i);
Calc_Digest(overlayModule->fileInfo.content, overlaySize, digestParams, false);
overlayTable[OT_COMPRESSED_FLAGS_OFFSET] |= 2;
component->staticModule.fileInfo.rewrite = true;
component->overlayTable.fileInfo.rewrite = true;
digestParams += DIGEST_HASH_SIZE;
overlayModule++;
overlayTable += OVERLAY_ENTRY_SIZE;
}
printf("OverlayTable ");
Calc_Digest(component->overlayTable.table, numOverlays * OVERLAY_ENTRY_SIZE, content + digestParamsOffset - DIGEST_HASH_SIZE, true);
success = true;
}
}
return success;
}
static int Compress(char *content, int size) {
int ret;
int sourceOffset;
int compressedOffset;
char *compressed = malloc(size);
char *compressedCpy = compressed;
if (compressed == NULL) {
ErrorPrintf("Cannot allocate memory size=%d\n", size);
ret = -2;
} else if (((size_t)content % 4) == 0) {
char *contentCpy = content;
int sizeCpy = size;
int compressedSize = size;
int lzResult = LZCompressRV(content, size, compressed, size);
if (lzResult < 0) {
DebugPrintf("Compressed buffer size exceeds original data size.\n");
free(compressedCpy);
ret = -1;
} else {
compressedSize -= lzResult;
compressed += lzResult;
DebugPrintf("1: source size = %d compressed = %d\n", size, compressedSize);
int overwriteResult = CheckOverwrite(sizeCpy, compressed, compressedSize, &sourceOffset, &compressedOffset);
if (overwriteResult == 0) {
contentCpy += sourceOffset;
sizeCpy -= sourceOffset;
compressed += compressedOffset;
compressedSize -= compressedOffset;
DebugPrintf(" !! Shrink back Compressed region to avoid overwriting.\n"
" !! Expand non-compressed region = +%d\n"
"2: source size = %d compressed = %d\n", sourceOffset, sizeCpy, compressedSize);
}
int compressedEnd = compressedSize + sourceOffset;
uint compressedEndAligned = ALIGN_4(compressedEnd);
ret = compressedEndAligned + 8;
if (ret < size) {
CopyBuffer(compressed, contentCpy, compressedSize);
free(compressedCpy);
for (int i = compressedEnd; i < (int)compressedEndAligned; i++) {
content[i] = -1;
}
char *contentEnd = content + compressedEndAligned;
*(uint *)contentEnd = (*(uint *)contentEnd & 0xff000000) | (ret - sourceOffset) & 0xffffff;
char compressedEndU8 = (char)compressedEnd;
char retU8 = (char)ret;
*(contentEnd + 3) = retU8 - compressedEndU8;
*(int *)(contentEnd + 4) = size - ret;
} else {
DebugPrintf("Compressed buffer size exceeds or equals original data size.\n");
free(compressedCpy);
ret = -1;
}
}
} else {
ErrorPrintf("Top of buffer is not aligned by 4.\n");
ret = -2;
}
return ret;
}
static int LZCompressRV(char *uncompressed, int uncompressedSize, char *compressed, int compressedSize) {
int optimalRemainderIdx;
ushort optimalRemainderIdx16;
int bytesLeft = uncompressedSize;
while (true) {
if (bytesLeft < 1) return compressedSize;
if (compressedSize < 1) break;
uint bitVector = 0;
int compressedPtr = compressedSize - 1;
compressedSize = compressedPtr;
for (int i = 0; i < 8; i++) {
bitVector <<= 1;
if (bytesLeft > 0) {
char *remainder = uncompressed + bytesLeft;
int bytesRead = uncompressedSize - bytesLeft;
int chunkSize = MIN(bytesLeft, 0x12);
char *chunk = remainder - chunkSize;
bytesRead = MIN(bytesRead, 0x1002);
int numMatches = FindMatched(chunk, chunkSize, remainder, bytesRead, &optimalRemainderIdx);
if (numMatches < 3) {
if (compressedSize < 1) return -1;
compressedSize--;
bytesLeft--;
compressed[compressedSize] = uncompressed[bytesLeft];
} else {
if (compressedSize < 2) return -1;
bytesLeft -= numMatches;
optimalRemainderIdx -= 2;
optimalRemainderIdx16 = (ushort)optimalRemainderIdx & 0xfff;
compressed[compressedSize - 1] =
(char)((ushort)(((short)numMatches - 3) * 0x1000) >> 8) | (char)(optimalRemainderIdx16 >> 8);
compressedSize -= 2;
compressed[compressedSize] = (char)optimalRemainderIdx16;
bitVector |= 1;
}
}
}
compressed[compressedPtr] = (char)bitVector;
}
return -1;
}
// `chunk` is a pointer to a section of the uncompressed byte array
// of size `chunkSize`. `remainder` is a pointer to the remainder of the
// byte array of size `remainderSize`.
//
// This function iterates over all the bytes after the chunk to find another
// chunk with the most bytes matching `chunk`. It returns the number of
// byte-wise matches found in the optimal chunk.
//
// `optimalRemainderIdx` points to the end of the optimal chunk.
static int FindMatched(char *chunk, int chunkSize, char *remainder, int remainderSize, int *optimalRemainderIdx) {
char lastChar = chunk[chunkSize - 1];
int maxMatches = 0;
for (int i = 0; i < remainderSize; i++) {
if (lastChar == remainder[i]) {
int bufferSize = MIN(i + 1, chunkSize);
int numMatches = HowManyMatched(chunk + chunkSize - 1, remainder + i, bufferSize);
if (numMatches > maxMatches) {
*optimalRemainderIdx = i;
maxMatches = numMatches;
}
}
}
return maxMatches;
}
// Returns the number of consecutive bytes that match in both buffers, starting
// from the end of each buffer.
static int HowManyMatched(char *buffer1, char *buffer2, int size) {
int i = 0;
for (; i < size && *buffer1 == *buffer2; buffer1--) {
buffer2--;
i++;
}
return i;
}
static int CheckOverwrite(int sourceSize, char *compressed, int compressedSize, int *sourceOffset, int *compressedOffset) {
do {
if (sourceSize < 1) {
*sourceOffset = 0;
*compressedOffset = 0;
return 1;
}
compressedSize--;
uint bitVector = compressed[compressedSize];
for (int i = 0; i < 8; i++) {
if (sourceSize > 0) {
if ((bitVector & 0x80) == 0) {
compressedSize--;
sourceSize--;
} else {
int nextCompressedSize = compressedSize - 2;
sourceSize -= ((byte)compressed[compressedSize - 1] >> 4) + 3;
if (sourceSize < 0) {
ErrorPrintf("System error in CheckOverwrite???\n");
exit(-1);
}
compressedSize = nextCompressedSize;
if (sourceSize < nextCompressedSize) {
*sourceOffset = sourceSize;
*compressedOffset = compressedSize;
return 0;
}
}
bitVector <<= 1;
}
}
} while (true);
}

View File

@ -1,11 +0,0 @@
#ifndef COMPRESS_H
#define COMPRESS_H
#include <stdbool.h>
#include "component.h"
bool CompressOverlayModules(Component *component);
bool CompressStaticModule(Component *component, int headerSize);
bool CalculateHMAC_OverlayModules(Component *component, int digestType, char *digestKey);
#endif // COMPRESS_H

View File

@ -1,370 +0,0 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "digest.h"
#include "files.h"
#include "global.h"
#include "misc.h"
#include "print.h"
typedef struct {
uint intermediateHash[5];
uint lengthLow;
uint lengthHigh;
int messageBlockIdx;
byte messageBlock[64];
bool computed;
uint corrupted;
} DGTHash2Context;
typedef bool (*Hash2ResetCb)(DGTHash2Context *hashCtx);
typedef uint (*Hash2SetSourceCb)(DGTHash2Context *hashCtx, char *digestKey, int digestKeySize);
typedef uint (*Hash2GetDigestCb)(DGTHash2Context *hashCtx, char *digestBuffer);
typedef struct {
int unk0;
int blockSize;
DGTHash2Context *hashCtx;
char *unkC;
Hash2ResetCb hash2Reset;
Hash2SetSourceCb hash2SetSource;
Hash2GetDigestCb hash2GetDigest;
} HmacParam;
static void DGT_Hash2CalcHmac(char *hash, char *content, int size, char *digestKey, int digestKeySize);
static bool DGT_SetOverlayTableMode(bool mode);
static bool DGT_Hash2Reset(DGTHash2Context *hashCtx);
static uint DGT_Hash2SetSource(DGTHash2Context *hashCtx, char *digestKey, int digestKeySize);
static uint DGT_Hash2GetDigest(DGTHash2Context *hashCtx, char *digestBuffer);
static void DGT_Hash2SetPadding(DGTHash2Context *hashCtx);
static void DGT_Hash2DoProcess(DGTHash2Context *hashCtx);
static void HmacCalc(char *hash, char *content, int size, char *digestKey, int digestKeySize, HmacParam *param);
// Set default DigestFunc
static DigestFunc sDigestFunc = DGT_Hash2CalcHmac;
static DigestFunc sDigestFuncs[] = { NULL, DGT_Hash2CalcHmac };
static char sDefaultDigestKey[] = {
0x21, 0x06, 0xc0, 0xde, 0xba, 0x98, 0xce, 0x3f, 0xa6, 0x92, 0xe3, 0x9d,
0x46, 0xf2, 0xed, 0x01, 0x76, 0xe3, 0xcc, 0x08, 0x56, 0x23, 0x63, 0xfa,
0xca, 0xd4, 0xec, 0xdf, 0x9a, 0x62, 0x78, 0x34, 0x8f, 0x6d, 0x63, 0x3c,
0xfe, 0x22, 0xca, 0x92, 0x20, 0x88, 0x97, 0x23, 0xd2, 0xcf, 0xae, 0xc2,
0x32, 0x67, 0x8d, 0xfe, 0xca, 0x83, 0x64, 0x98, 0xac, 0xfd, 0x3e, 0x37,
0x87, 0x46, 0x58, 0x24,
};
static char *sDigestKey;
static int sDigestKeySize;
static bool sOverlayTableMode;
bool Init_Digest(uint digestType, char *digestKey) {
bool success;
if (digestType < 1 || digestType > 2) {
ErrorPrintf("Unknown digest type\n");
success = false;
} else {
DigestFunc digestFunc = sDigestFuncs[digestType - 1];
if (digestFunc == NULL) {
ErrorPrintf("Unsupported digest\n");
success = false;
} else {
sDigestFunc = digestFunc;
if (sDigestKey != NULL) {
free(sDigestKey);
sDigestKey = NULL;
}
if (digestKey == NULL) {
sDigestKey = calloc(1, DIGEST_KEY_SIZE);
if (sDigestKey == NULL) {
ErrorPrintf("Cannot allocate memory.\n");
return false;
}
memcpy(sDigestKey, sDefaultDigestKey, DIGEST_KEY_SIZE);
sDigestKeySize = DIGEST_KEY_SIZE;
} else {
sDigestKeySize = ReadFile(digestKey, &sDigestKey);
if (sDigestKeySize < 0) {
return false;
}
if (sDigestKeySize < DIGEST_KEY_SIZE) {
ErrorPrintf("Key file size should be >= %d bytes\n", DIGEST_KEY_SIZE);
return false;
}
}
success = true;
}
}
return success;
}
void Calc_Digest(char *content, int size, char *hash, bool overlayTableMode) {
byte hashBuffer[40];
bool oldMode = DGT_SetOverlayTableMode(overlayTableMode);
sDigestFunc((char *)hashBuffer, content, size, sDigestKey, sDigestKeySize);
DGT_SetOverlayTableMode(oldMode);
int iCpy = 0;
for (int i = 0; i < 20; i++) {
hashBuffer[i] = hashBuffer[iCpy + 1] ^ hashBuffer[iCpy];
iCpy++;
}
printf(": Digest ");
for (int i = 0; i < 20; i++) {
printf("%02X", hashBuffer[i]);
}
printf(" %8ld\n", (long int)size);
CopyBuffer((char *)hashBuffer, hash, 20);
}
static void DGT_Hash2CalcHmac(char *hash, char *content, int size, char *digestKey, int digestKeySize) {
DGTHash2Context hashCtx;
char unkBuffer1[0x20];
HmacParam param = {0};
param.unk0 = 20;
param.blockSize = DIGEST_KEY_SIZE;
param.hashCtx = &hashCtx;
param.unkC = unkBuffer1;
param.hash2Reset = DGT_Hash2Reset;
param.hash2SetSource = DGT_Hash2SetSource;
param.hash2GetDigest = DGT_Hash2GetDigest;
HmacCalc(hash, content, size, digestKey, digestKeySize, &param);
}
static bool DGT_SetOverlayTableMode(bool mode) {
bool oldMode = sOverlayTableMode;
sOverlayTableMode = mode;
return oldMode;
}
static bool DGT_Hash2Reset(DGTHash2Context *hashCtx) {
if (hashCtx != NULL) {
hashCtx->intermediateHash[0] = 0x67452301;
hashCtx->intermediateHash[1] = 0xefcdab89;
hashCtx->intermediateHash[2] = 0x98badcfe;
hashCtx->intermediateHash[3] = 0x10325476;
hashCtx->intermediateHash[4] = 0xc3d2e1f0;
hashCtx->lengthLow = 0;
hashCtx->lengthHigh = 0;
hashCtx->messageBlockIdx = 0;
hashCtx->computed = false;
hashCtx->corrupted = 0;
}
return hashCtx == NULL;
}
static uint DGT_Hash2SetSource(DGTHash2Context *hashCtx, char *digestKey, int digestKeySize) {
uint ret;
if (digestKeySize == 0) {
ret = 0;
} else if (hashCtx == NULL || digestKey == NULL) {
ret = 1;
} else if (!hashCtx->computed) {
if (hashCtx->corrupted == 0) {
while (digestKeySize -= 1, digestKeySize != -1 && hashCtx->corrupted == 0) {
hashCtx->messageBlock[hashCtx->messageBlockIdx] = *digestKey;
hashCtx->messageBlockIdx += 1;
hashCtx->lengthLow += 8;
if (hashCtx->messageBlockIdx == 0 && (hashCtx->lengthHigh += 1, hashCtx->lengthHigh == 0)) {
hashCtx->corrupted = 1;
}
if (hashCtx->messageBlockIdx == 0x40) {
DGT_Hash2DoProcess(hashCtx);
}
digestKey++;
}
ret = 0;
} else {
ret = hashCtx->corrupted;
}
} else {
hashCtx->corrupted = 3;
ret = 3;
}
return ret;
}
static uint DGT_Hash2GetDigest(DGTHash2Context *hashCtx, char *digestBuffer) {
uint ret;
if (hashCtx == NULL || digestBuffer == NULL) {
ret = 1;
} else if (hashCtx->corrupted == 0) {
if (!hashCtx->computed) {
DGT_Hash2SetPadding(hashCtx);
for (int i = 0; i < 0x40; i++) {
hashCtx->messageBlock[i] = '\0';
}
hashCtx->lengthLow = 0;
hashCtx->lengthHigh = 0;
hashCtx->computed = true;
}
for (int i = 0; i < 20; i++) {
digestBuffer[i] = (char)(*(uint *)(hashCtx->messageBlock + (i >> 2) * 4 + -0x20) >> ((3u - ((byte)i % 4)) * 8u & 0x1f));
}
ret = 0;
} else {
ret = hashCtx->corrupted;
}
return ret;
}
static void DGT_Hash2SetPadding(DGTHash2Context *hashCtx) {
if (hashCtx->messageBlockIdx < 0x38) {
hashCtx->messageBlock[hashCtx->messageBlockIdx] = -0x80;
hashCtx->messageBlockIdx += 1;
while (hashCtx->messageBlockIdx < 0x38) {
hashCtx->messageBlock[hashCtx->messageBlockIdx] = '\0';
hashCtx->messageBlockIdx += 1;
}
} else {
hashCtx->messageBlock[hashCtx->messageBlockIdx] = -0x80;
hashCtx->messageBlockIdx += 1;
while (hashCtx->messageBlockIdx < 0x40) {
hashCtx->messageBlock[hashCtx->messageBlockIdx] = '\0';
hashCtx->messageBlockIdx += 1;
}
DGT_Hash2DoProcess(hashCtx);
while (hashCtx->messageBlockIdx < 0x38) {
hashCtx->messageBlock[hashCtx->messageBlockIdx] = '\0';
hashCtx->messageBlockIdx += 1;
}
}
hashCtx->messageBlock[0x38] = hashCtx->lengthHigh >> 0x18;
hashCtx->messageBlock[0x39] = (byte)(hashCtx->lengthHigh >> 0x10);
hashCtx->messageBlock[0x3a] = (byte)(hashCtx->lengthHigh >> 8);
hashCtx->messageBlock[0x3b] = (byte)(hashCtx->lengthHigh);
hashCtx->messageBlock[0x3c] = hashCtx->lengthLow >> 0x18;
hashCtx->messageBlock[0x3d] = (byte)(hashCtx->lengthLow >> 0x10);
hashCtx->messageBlock[0x3e] = (byte)(hashCtx->lengthLow >> 8);
hashCtx->messageBlock[0x3f] = (byte)(hashCtx->lengthLow);
DGT_Hash2DoProcess(hashCtx);
}
// SHA hash
static void DGT_Hash2DoProcess(DGTHash2Context *hashCtx) {
uint temp;
int temp2;
uint buffer[99];
int i, idx;
if (sOverlayTableMode) {
buffer[10] = *(uint *)(hashCtx->messageBlock + 0x18);
buffer[9] = *(uint *)(hashCtx->messageBlock + 0x38);
*(uint *)(hashCtx->messageBlock + 0x18) = 0;
*(uint *)(hashCtx->messageBlock + 0x38) = 0;
}
for (i = 0; i < 0x10; i++) {
buffer[i + 0x10] = (uint)(byte)hashCtx->messageBlock[i * 4] << 0x18;
buffer[i + 0x10] = (uint)(byte)hashCtx->messageBlock[i * 4 + 1] << 0x10 | buffer[i + 0x10];
buffer[i + 0x10] = (uint)(byte)hashCtx->messageBlock[i * 4 + 2] << 8 | buffer[i + 0x10];
buffer[i + 0x10] = (uint)(byte)hashCtx->messageBlock[i * 4 + 3] | buffer[i + 0x10];
}
for (i = 0x10; i < 0x50; i++) {
temp = buffer[i + 0xd] ^ buffer[i + 8] ^ buffer[i + 2] ^ buffer[i];
buffer[i + 0x10] = temp << 1 | (uint)((int)temp < 0);
}
buffer[14] = hashCtx->intermediateHash[1];
buffer[13] = hashCtx->intermediateHash[2];
buffer[12] = hashCtx->intermediateHash[3];
buffer[11] = hashCtx->intermediateHash[4];
buffer[15] = hashCtx->intermediateHash[0];
for (i = 0; i < 0x14; i++) {
temp2 = (~buffer[14] & buffer[12] | buffer[14] & buffer[13]) +
(buffer[15] << 5 | buffer[15] >> 0x1b) + buffer[11];
idx = i + 0x10;
buffer[11] = buffer[12];
buffer[12] = buffer[13];
buffer[13] = buffer[14] << 0x1e | buffer[14] >> 2;
buffer[14] = buffer[15];
buffer[15] = buffer[idx] + temp2 + 0x5a827999;
}
for (i = 0x14; i < 0x28; i = i + 1) {
temp2 = (buffer[13] ^ buffer[14] ^ buffer[12]) + (buffer[15] << 5 | buffer[15] >> 0x1b) +
buffer[11];
idx = i + 0x10;
buffer[11] = buffer[12];
buffer[12] = buffer[13];
buffer[13] = buffer[14] << 0x1e | buffer[14] >> 2;
buffer[14] = buffer[15];
buffer[15] = buffer[idx] + temp2 + 0x6ed9eba1;
}
for (i = 0x28; i < 0x3c; i++) {
temp2 = (buffer[12] & buffer[13] | (buffer[12] | buffer[13]) & buffer[14]) +
(buffer[15] << 5 | buffer[15] >> 0x1b) + buffer[11];
idx = i + 0x10;
buffer[11] = buffer[12];
buffer[12] = buffer[13];
buffer[13] = buffer[14] << 0x1e | buffer[14] >> 2;
buffer[14] = buffer[15];
buffer[15] = buffer[idx] + temp2 + 0x8f1bbcdc;
}
for (i = 0x3c; i < 0x50; i++) {
temp2 = (buffer[13] ^ buffer[14] ^ buffer[12]) + (buffer[15] << 5 | buffer[15] >> 0x1b) +
buffer[11];
idx = i + 0x10;
buffer[11] = buffer[12];
buffer[12] = buffer[13];
buffer[13] = buffer[14] << 0x1e | buffer[14] >> 2;
buffer[14] = buffer[15];
buffer[15] = buffer[idx] + temp2 + 0xca62c1d6;
}
hashCtx->intermediateHash[0] += buffer[15];
hashCtx->intermediateHash[1] += buffer[14];
hashCtx->intermediateHash[2] += buffer[13];
hashCtx->intermediateHash[3] += buffer[12];
hashCtx->intermediateHash[4] += buffer[11];
hashCtx->messageBlockIdx = 0;
if (sOverlayTableMode) {
*(uint *)(hashCtx->messageBlock + 0x18) = buffer[10];
*(uint *)(hashCtx->messageBlock + 0x38) = buffer[9];
}
}
static void HmacCalc(char *hash, char *content, int size, char *digestKey, int digestKeySize, HmacParam *param) {
char digestBuffer[0x4C];
char *key;
int keySize;
char innerKey[0x48];
char outerKey[0x40];
int i;
if (hash != NULL && content != NULL && size != 0 && digestKey != NULL &&
digestKeySize != 0 && param != NULL) {
if (param->blockSize < digestKeySize) {
param->hash2Reset(param->hashCtx);
param->hash2SetSource(param->hashCtx, digestKey, digestKeySize);
param->hash2GetDigest(param->hashCtx, digestBuffer);
key = digestBuffer;
keySize = param->unk0;
} else {
key = digestKey;
keySize = digestKeySize;
}
for (i = 0; i < keySize; i++) {
innerKey[i] = key[i] ^ 0x36;
}
for (; i < param->blockSize; i++) {
innerKey[i] = 0x36;
}
param->hash2Reset(param->hashCtx);
param->hash2SetSource(param->hashCtx, innerKey, param->blockSize);
param->hash2SetSource(param->hashCtx, content, size);
param->hash2GetDigest(param->hashCtx, param->unkC);
for (i = 0; i < keySize; i++) {
outerKey[i] = key[i] ^ 0x5c;
}
for (; i < param->blockSize; i++) {
outerKey[i] = 0x5c;
}
param->hash2Reset(param->hashCtx);
param->hash2SetSource(param->hashCtx, outerKey, param->blockSize);
param->hash2SetSource(param->hashCtx, param->unkC, param->unk0);
param->hash2GetDigest(param->hashCtx, hash);
}
}

View File

@ -1,15 +0,0 @@
#ifndef DIGEST_H
#define DIGEST_H
#include <stdbool.h>
#include "global.h"
#define DIGEST_KEY_SIZE (0x40)
#define DIGEST_HASH_SIZE (0x14)
typedef void (*DigestFunc)(char *hash, char *content, int size, char *digestKey, int digestKeySize);
bool Init_Digest(uint digestType, char *digestKey);
void Calc_Digest(char *content, int size, char *hash, bool overlayTableMode);
#endif // DIGEST_H

View File

@ -1,149 +0,0 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "files.h"
#include "global.h"
#include "print.h"
#include "str.h"
char *GetDirName(char *filename) {
char *dirName;
int i = strlen(filename);
while (true) {
i--;
if (i < 0) {
dirName = strdup(".");
return dirName;
}
if (filename[i] == '/' || filename[i] == '\\') break;
if (filename[i] == ':') {
dirName = malloc(i + 3);
if (dirName != NULL) {
strncpy(dirName, filename, i);
strcpy(dirName + i, ":.");
}
return dirName;
}
}
// Same size as filename, but has null-character after directory name.
dirName = strdup(filename);
if (dirName == NULL) {
return NULL;
}
dirName[i] = '\0';
return dirName;
}
bool GetFiles(char *responseFile, SourceFiles *sourceFiles) {
char *filename;
bool success;
int numWords;
int wordStart;
char *content;
char *dirName = GetDirName(responseFile);
int bytesRead = ReadFile(responseFile, &content);
if (bytesRead < 0) {
success = false;
} else {
numWords = 0;
wordStart = 0;
for (int i = 0; i < bytesRead; i++) {
if (content[i] == '\0') {
filename = StrCat(3, dirName, "/", &content[wordStart]);
sourceFiles->filenames[numWords] = filename;
wordStart = i + 1;
numWords++;
if (numWords == NUM_SOURCE_FILES) break;
}
}
free(content);
free(dirName);
if (numWords == NUM_SOURCE_FILES) {
success = true;
} else {
while (numWords > 0) {
numWords--;
free(sourceFiles->filenames[numWords]);
}
ErrorPrintf("%s wrong format", responseFile);
success = false;
}
}
return success;
}
// Returns size of file.
int ReadFile(char *filename, char **content) {
int bytesRead;
struct stat fileInfo;
FILE *fp = NULL;
*content = NULL;
if (filename == NULL) {
ErrorPrintf("Not specified filename\n");
} else {
int error = stat(filename, &fileInfo);
if ((error == 0) && (fp = fopen(filename, "rb"), fp != NULL)) {
*content = malloc(fileInfo.st_size);
if (*content == NULL) {
ErrorPrintf("Cannot allocate memory size=%d\n", fileInfo.st_size);
} else {
bytesRead = fread(*content, 1, fileInfo.st_size, fp);
if (bytesRead == fileInfo.st_size) {
DebugPrintf("%p %8d bytes ReadFile \'%s\'\n", *content, fileInfo.st_size, filename);
fclose(fp);
return fileInfo.st_size;
}
ErrorPrintf("Cannot read file \'%s\'\n", filename);
}
}
ErrorPrintf("Cannot read file \'%s\'\n", filename);
}
if (*content != NULL) {
free(content);
}
if (fp != NULL) {
fclose(fp);
}
return -1;
}
// Returns number of bytes written.
int WriteFile(char *filename, char *content, int size) {
FILE *fp = NULL;
int ret;
DebugPrintf("%p %8d bytes WriteFile \'%s\'\n", content, size, filename);
fp = fopen(filename, "wb");
if (fp == NULL) {
ErrorPrintf("Cannot open file \'%s\'\n", filename);
ret = -1;
} else {
int sizeWritten = fwrite(content, 1, size, fp);
if (size == sizeWritten) {
int closeResult = fclose(fp);
if (closeResult < 0) {
ErrorPrintf("Cannot close file \'%s\'\n", filename);
unlink(filename);
ret = -1;
} else {
ret = sizeWritten;
}
} else {
ErrorPrintf("Cannot write file \'%s\'\n", filename);
fclose(fp);
unlink(filename);
ret = -1;
}
}
return ret;
}

View File

@ -1,12 +0,0 @@
#ifndef FILES_H
#define FILES_H
#include <stdbool.h>
#include "global.h"
char *GetDirName(char *filename);
bool GetFiles(char *responseFile, SourceFiles *sourceFiles);
int ReadFile(char *filename, char **content);
int WriteFile(char *filename, char *content, int size);
#endif // FILES_H

View File

@ -1,74 +0,0 @@
#ifndef GLOBAL_H
#define GLOBAL_H
#include <stdbool.h>
typedef unsigned char byte;
typedef unsigned short ushort;
typedef unsigned int uint;
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
#define ALIGN_4(addr) ((addr + 3U) & 0xfffffffc)
typedef struct {
bool staticModule;
int headerSize; // size in bytes
bool overlayModules;
bool overlayDigest;
int digestType;
char *digestKey;
char *outSuffix;
} Options;
#define SOURCE_FILES_STATIC_MODULE 0
#define SOURCE_FILES_OVERLAY_DEFS 1
#define SOURCE_FILES_OVERLAY_TABLE 2
#define NUM_SOURCE_FILES 3
typedef struct {
char *filenames[NUM_SOURCE_FILES];
} SourceFiles;
extern bool gDebugMode;
typedef struct {
char *filename;
char *content;
int fileSize;
int compressedSize;
bool rewrite; // File should be updated after compression
} FileInfo; // win32 sizeof == 0x14
typedef struct {
FileInfo fileInfo;
char *footerContent;
uint footerSize;
} StaticModule; // win32 sizeof == 0x1c
typedef struct {
FileInfo fileInfo;
char *header;
} OverlayDefs; // win32 sizeof == 0x18
typedef struct {
FileInfo fileInfo;
} OverlayModule; // win32 sizeof == 0x14
typedef struct {
FileInfo fileInfo;
char *table; // == fileInfo.content
} OverlayTable; // win32 sizeof == 0x18
typedef struct {
StaticModule staticModule;
int numOverlays;
OverlayDefs overlayDefs;
char *overlayFilenames;
char *dirName;
OverlayTable overlayTable;
OverlayModule *overlayModules;
} Component; // win32 sizeof: 0x5c
#endif // GLOBAL_H

View File

@ -1,134 +0,0 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "component.h"
#include "files.h"
#include "global.h"
#include "print.h"
#include "str.h"
bool gDebugMode = false;
void InitializeOptions(Options *options) {
options->staticModule = false;
options->headerSize = 0x4000;
options->overlayModules = false;
options->overlayDigest = false;
options->digestType = 2;
options->digestKey = StrDup(NULL, NULL);
options->outSuffix = StrDup(NULL, "_LZ");
}
void usage(void) {
printf("NDS Development Tool - compstatic - Compress static module\n\n"
"Usage: compstatic [-sHSIZE|-9|-7] [-c] [-a[FILE]]\n"
" [-F] [-eSUFFIX] [-fRESFILE] [-d] [-h]\n"
" [STATICMODULE OVERLAYDEFS [OVERLAYTABLE]]\n\n"
" Compress component modules\n\n"
" -sHSIZE Compress STATICMODULE\n"
" without header region specified by HSIZE(bytes)\n"
" -9 Compress as ARM9 static module (HEADER_SIZE = 16k)\n"
" -7 Compress as ARM7 static module (HEADER_SIZE = 1k)\n"
" -c Compress overlay modules\n"
" -a[FILE] Generate overlay digest code with FILE as key\n"
" -F Overwrite original component files\n"
" -eSUFFIX SUFFIX for output file (default:\"_LZ\")\n"
" -fRESFILE Use response file to specify source files\n"
" -d Show debug messages (for test purpose)\n"
" -h Show this message\n\n");
}
int main(int argc, char *argv[]) {
int opt;
int useResponseFile = false;
int argsLeft;
char **remainingArgs;
char *overlayTable;
bool success;
SourceFiles sourceFiles;
Options options;
InitializeOptions(&options);
while ((opt = getopt(argc, argv, "s:ca::A:97Fe:fdhv")) != -1) {
switch (opt) {
case '7':
options.staticModule = true;
options.headerSize = 0x400;
break;
case '9':
options.staticModule = true;
options.headerSize = 0x4000;
break;
// Not referenced in usage
case 'A':
options.digestType = atoi(optarg);
break;
case 'F':
options.outSuffix = StrDup(options.outSuffix, NULL);
break;
case 'a':
options.overlayDigest = true;
options.digestKey = StrDup(options.digestKey, optarg);
break;
case 'c':
options.overlayModules = true;
break;
case 'd':
gDebugMode = true;
break;
case 'e':
options.outSuffix = strdup(optarg);
break;
case 'f':
useResponseFile = true;
break;
case 's':
options.staticModule = true;
options.headerSize = atoi(optarg);
break;
default:
usage();
break;
}
DebugPrintf("option -%c: %s\n", opt, (optarg == NULL) ? "No ARG" : optarg);
}
argsLeft = argc - optind;
remainingArgs = &argv[optind];
DebugPrintf("argc=%d optind=%d\n", argsLeft, optind);
for (int i = 0; i < argsLeft; i++) {
DebugPrintf("argv[%d] = [%s]\n", i, argv[optind + i]);
}
if (!useResponseFile || argsLeft != 1) {
if (!useResponseFile && (argsLeft == 2 || argsLeft == 3)) {
overlayTable = (argsLeft == 3) ? remainingArgs[2] : NULL;
success = ConvertComponent(&options, remainingArgs[0], remainingArgs[1], overlayTable);
} else {
usage();
}
} else {
success = GetFiles(remainingArgs[0], &sourceFiles);
if (success) {
printf("StaticModule = %s\n", sourceFiles.filenames[SOURCE_FILES_STATIC_MODULE]);
printf("OverlayDefs = %s\n", sourceFiles.filenames[SOURCE_FILES_OVERLAY_DEFS]);
printf("OverlayTable = %s\n", sourceFiles.filenames[SOURCE_FILES_OVERLAY_TABLE]);
success = ConvertComponent(&options, sourceFiles.filenames[SOURCE_FILES_STATIC_MODULE], sourceFiles.filenames[SOURCE_FILES_OVERLAY_DEFS], sourceFiles.filenames[SOURCE_FILES_OVERLAY_TABLE]);
free(sourceFiles.filenames[SOURCE_FILES_STATIC_MODULE]);
free(sourceFiles.filenames[SOURCE_FILES_OVERLAY_DEFS]);
free(sourceFiles.filenames[SOURCE_FILES_OVERLAY_TABLE]);
}
}
ConvertFinal(&options);
if (!success) {
ErrorPrintf("exit...\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

View File

@ -1,55 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "global.h"
#include "misc.h"
#include "print.h"
void CopyBuffer(char *src, char *dest, int size) {
if (dest < src) {
for (int i = 0; i < size; i++) {
dest[i] = src[i];
}
} else {
for (int i = size - 1; i >= 0; i--) {
dest[i] = src[i];
}
}
}
void FreeBuffer(FileInfo *fileInfo) {
if (fileInfo->content != NULL) {
free(fileInfo->content);
fileInfo->content = NULL;
}
if (fileInfo->filename != NULL) {
free(fileInfo->filename);
fileInfo->filename = NULL;
}
fileInfo->compressedSize = 0;
fileInfo->fileSize = 0;
fileInfo->rewrite = false;
}
bool AddSuffixBuffer(FileInfo *fileInfo, char *suffix) {
bool success;
if (fileInfo->fileSize == 0 || fileInfo->filename == NULL || suffix == NULL || *suffix == '\0') {
success = true;
} else {
int filenameLength = strlen(fileInfo->filename);
int suffixLength = strlen(suffix);
char *dest = malloc(filenameLength + suffixLength + 1);
if (dest == NULL) {
ErrorPrintf("Cannot allocate memory.\n");
success = false;
} else {
sprintf(dest, "%s%s", fileInfo->filename, suffix);
free(fileInfo->filename);
fileInfo->filename = dest;
fileInfo->rewrite = true;
success = true;
}
}
return success;
}

View File

@ -1,10 +0,0 @@
#ifndef MISC_H
#define MISC_H
#include "global.h"
void CopyBuffer(char *src, char *dest, int size);
void FreeBuffer(FileInfo *fileInfo);
bool AddSuffixBuffer(FileInfo *fileInfo, char *suffix);
#endif // MISC_H

View File

@ -1,87 +0,0 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "files.h"
#include "global.h"
#include "misc.h"
#include "overlay_defs.h"
#include "print.h"
bool ReadOverlayDefs(Component *component, char *filename) {
int numWords;
int checkPtr;
bool success = false;
DebugPrintf("Reading overlayDefs=%s\n", filename);
int fileSize = ReadFile(filename, &component->overlayDefs.fileInfo.content);
component->overlayDefs.fileInfo.fileSize = fileSize;
component->overlayDefs.fileInfo.compressedSize = 0;
component->overlayDefs.fileInfo.rewrite = false;
component->overlayDefs.fileInfo.filename = strdup(filename);
if (component->overlayDefs.fileInfo.fileSize < 0) {
success = false;
} else if (component->overlayDefs.fileInfo.fileSize < MIN_OVERLAY_DEFS_FILE_SIZE) {
ErrorPrintf("Overlaydefs is too small (size=%d). Must be >= %d\n", component->overlayDefs.fileInfo.fileSize, MIN_OVERLAY_DEFS_FILE_SIZE);
success = false;
} else {
component->overlayDefs.header = component->overlayDefs.fileInfo.content;
component->overlayFilenames = component->overlayDefs.header + OVERLAY_DEFS_FILENAMES_OFFSET;
component->dirName = GetDirName(filename);
if (component->dirName == NULL) {
success = false;
} else {
// Count the number of words in the footer. Once two '\0' chars
// appear back-to-back, stop checking.
numWords = 0;
checkPtr = 0;
for (int i = 0; i < component->overlayDefs.fileInfo.fileSize - OVERLAY_DEFS_FILENAMES_SIZE; i++) {
if (component->overlayFilenames[i] == '\0') {
if (checkPtr == i) break;
numWords++;
checkPtr = i + 1;
}
}
component->numOverlays = numWords;
success = true;
}
}
return success;
}
bool WriteOverlayDefs(Component *component) {
int sizeWritten;
bool success;
OverlayDefs *overlayDefs = &component->overlayDefs;
if (!overlayDefs->fileInfo.rewrite) {
success = true;
} else {
DebugPrintf("Writing overlayDefs=%s\n", overlayDefs->fileInfo.filename);
if (overlayDefs->fileInfo.compressedSize == 0) {
sizeWritten = WriteFile(overlayDefs->fileInfo.filename, overlayDefs->fileInfo.content, overlayDefs->fileInfo.fileSize);
success = sizeWritten >= 0;
} else {
ErrorPrintf("Don\'t support compressed overlaydefs\n");
success = false;
}
}
return success;
}
bool AddSuffixOverlayDefs(Component *component, char *suffix) {
DebugPrintf("Adding suffix overlayDefs=%s\n", suffix);
return AddSuffixBuffer(&component->overlayDefs.fileInfo, suffix);
}
void FreeOverlayDefs(Component *component) {
DebugPrintf("Releasing overlayDefs\n");
FreeBuffer(&component->overlayDefs.fileInfo);
component->overlayDefs.header = NULL;
component->overlayFilenames = NULL;
if (component->dirName != NULL) {
free(component->dirName);
component->dirName = NULL;
}
}

View File

@ -1,22 +0,0 @@
#ifndef OVERLAY_DEFS_H
#define OVERLAY_DEFS_H
#include <stdbool.h>
#include "global.h"
#define MIN_OVERLAY_DEFS_FILE_SIZE 0x10
#define OVERLAY_DEFS_FOOTER_OFFSET 0x8
#define OVERLAY_DEFS_FILENAMES_OFFSET 0x10
#define OVERLAY_DEFS_FILENAMES_SIZE 0x10
#define OVERLAY_DEFS_HEADER_LOAD_ADDRESS_OFFSET 0
#define OVERLAY_DEFS_HEADER_ENTRY_ADDRESS_OFFSET 4
#define OVERLAY_DEFS_HEADER_MODULE_SIZE_OFFSET 8
#define OVERLAY_DEFS_HEADER_AUTOLOAD_DONE_OFFSET 12
bool ReadOverlayDefs(Component *component, char *filename);
bool WriteOverlayDefs(Component *component);
bool AddSuffixOverlayDefs(Component *component, char *suffix);
void FreeOverlayDefs(Component *component);
#endif // OVERLAY_DEFS_H

View File

@ -1,149 +0,0 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "files.h"
#include "global.h"
#include "misc.h"
#include "overlay_modules.h"
#include "print.h"
bool ReadOverlayModules(Component *component) {
bool success;
char c;
OverlayModule *overlayModules;
char *overlayFilenames = component->overlayFilenames;
char *dirName = component->dirName;
int dirNameLength = strlen(dirName);
if (component->numOverlays == 0) {
DebugPrintf("No overlay to read\n");
component->overlayModules = NULL;
success = true;
} else {
overlayModules = calloc(component->numOverlays, sizeof(OverlayModule));
if (overlayModules == NULL) {
ErrorPrintf("Cannot allocate memory.\n");
success = false;
} else {
component->overlayModules = overlayModules;
for (int i = 0; i < component->numOverlays; i++) {
int filenameLength = strlen(overlayFilenames);
overlayModules->fileInfo.filename = malloc(filenameLength + dirNameLength + 2);;
if (overlayModules->fileInfo.filename == NULL) {
ErrorPrintf("Cannot allocate memory\n");
return false;
}
sprintf(overlayModules->fileInfo.filename, "%s/%s", dirName, overlayFilenames);
DebugPrintf("Reading overlay[%d]=%s\n", i, overlayModules->fileInfo.filename);
int fileSize = ReadFile(overlayModules->fileInfo.filename, &overlayModules->fileInfo.content);
overlayModules->fileInfo.fileSize = fileSize;
overlayModules->fileInfo.compressedSize = 0;
overlayModules->fileInfo.rewrite = false;
if (overlayModules->fileInfo.fileSize < 0) return false;
overlayModules++;
do {
c = *overlayFilenames;
overlayFilenames++;
} while (c != '\0');
}
success = true;
}
}
return success;
}
bool WriteOverlayModules(Component *component) {
OverlayModule *overlayModule = component->overlayModules;
int i = 0;
do {
if (i >= component->numOverlays) {
return true;
}
if (overlayModule->fileInfo.rewrite) {
DebugPrintf("Writing overlay[%d]=%s\n", i, overlayModule->fileInfo.filename);
int overlaySize = overlayModule->fileInfo.compressedSize ? overlayModule->fileInfo.compressedSize : overlayModule->fileInfo.fileSize;
int sizeWritten = WriteFile(overlayModule->fileInfo.filename, overlayModule->fileInfo.content, overlaySize);
if (sizeWritten < 0) {
return false;
}
}
overlayModule++;
i++;
} while (true);
}
bool AddSuffixOverlayModules(Component *component, char *suffix) {
bool success;
OverlayModule *overlayModule = component->overlayModules;
if (component->numOverlays == 0 || overlayModule == NULL) {
DebugPrintf("No overlay to add suffix\n");
success = true;
} else if (suffix == NULL || *suffix == '\0') {
success = true;
} else {
int suffixLength = strlen(suffix);
int fileSize = suffixLength * component->numOverlays + component->overlayDefs.fileInfo.fileSize;
char *buffer = malloc(fileSize);
if (buffer == NULL) {
ErrorPrintf("Cannot allocate memory\n");
success = false;
} else {
uint *header32 = (uint *)component->overlayDefs.header;
*(uint *)buffer = header32[0];
*(uint *)(buffer + 4) = header32[1];
*(uint *)(buffer + 8) = header32[2];
*(uint *)(buffer + 0xc) = header32[3];
char *contentPtr = buffer + 0x10;
char *ovFilename = component->overlayFilenames;
for (int i = 0; i < component->numOverlays; i++) {
DebugPrintf("Adding suffix overlay[%d]\n", i);
strcpy(contentPtr, ovFilename);
strcat(contentPtr, suffix);
int length = strlen(ovFilename);
ovFilename += length + 1;
length = strlen(contentPtr);
contentPtr += length + 1;
bool addSuffixSuccess = AddSuffixBuffer(&overlayModule->fileInfo, suffix);
if (!addSuffixSuccess) {
return false;
}
overlayModule++;
}
CopyBuffer(ovFilename, contentPtr, fileSize - ((size_t)contentPtr - (size_t)buffer));
free(component->overlayDefs.fileInfo.content);
component->overlayDefs.fileInfo.content = buffer;
component->overlayDefs.fileInfo.fileSize = fileSize;
component->overlayDefs.fileInfo.rewrite = true;
component->overlayDefs.header = buffer;
component->overlayFilenames = buffer + 0x10;
success = true;
}
}
return success;
}
void FreeOverlayModules(Component *component) {
OverlayModule *overlayModule = component->overlayModules;
if (component->numOverlays == 0 || overlayModule == NULL) {
DebugPrintf("No overlay to release\n");
} else {
for (int i = 0; i < component->numOverlays; i++) {
DebugPrintf("Releasing overlay[%d]\n", i);
FreeBuffer(&overlayModule->fileInfo);
overlayModule++;
}
}
if (component->overlayModules != NULL) {
free(component->overlayModules);
component->overlayModules = NULL;
}
}

View File

@ -1,12 +0,0 @@
#ifndef OVERLAY_MODULE_H
#define OVERLAY_MODULE_H
#include <stdbool.h>
#include "global.h"
bool ReadOverlayModules(Component *component);
bool WriteOverlayModules(Component *component);
bool AddSuffixOverlayModules(Component *component, char *suffix);
void FreeOverlayModules(Component *component);
#endif // OVERLAY_MODULE_H

View File

@ -1,76 +0,0 @@
#include <stdbool.h>
#include <string.h>
#include "files.h"
#include "global.h"
#include "misc.h"
#include "overlay_table.h"
#include "print.h"
bool ReadOverlayTable(Component *component, char *filename) {
OverlayTable *overlayTable = &component->overlayTable;
if (filename == NULL || component->numOverlays < 1) {
DebugPrintf("No overlay table to read\n");
overlayTable->fileInfo.content = NULL;
overlayTable->fileInfo.fileSize = 0;
overlayTable->fileInfo.filename = NULL;
} else {
DebugPrintf("Reading overlayTable=%s\n", filename);
int fileSize = ReadFile(filename, &overlayTable->fileInfo.content);
overlayTable->fileInfo.fileSize = fileSize;
overlayTable->fileInfo.filename = strdup(filename);
}
overlayTable->fileInfo.compressedSize = 0;
overlayTable->fileInfo.rewrite = false;
bool success = overlayTable->fileInfo.fileSize == component->numOverlays * OVERLAY_ENTRY_SIZE;
if (success) {
overlayTable->table = overlayTable->fileInfo.content;
} else {
ErrorPrintf("Not matched number of overlays and size of overlay table\n");
}
return success;
}
bool WriteOverlayTable(Component *component) {
bool success;
OverlayTable *overlayTable = &component->overlayTable;
if (!overlayTable->fileInfo.rewrite) {
success = true;
} else if (overlayTable->fileInfo.filename == NULL) {
ErrorPrintf("No filename specified for overlay table\n");
success = false;
} else {
DebugPrintf("Writing overlayTable=%s\n", overlayTable->fileInfo.filename);
if (overlayTable->fileInfo.compressedSize == 0) {
int sizeWritten = WriteFile(overlayTable->fileInfo.filename, overlayTable->fileInfo.content, overlayTable->fileInfo.fileSize);
success = sizeWritten >= 0;
} else {
ErrorPrintf("Don\'t support compressed overlay table\n");
success = false;
}
}
return success;
}
bool AddSuffixOverlayTable(Component *component, char *suffix) {
bool success;
if (component->overlayTable.fileInfo.content == NULL || component->numOverlays == 0) {
DebugPrintf("No overlaytable to add suffix\n");
success = true;
} else {
DebugPrintf("Adding suffix overlayTable=%s\n", suffix);
success = AddSuffixBuffer(&component->overlayTable.fileInfo, suffix);
}
return success;
}
void FreeOverlayTable(Component *component) {
if (component->overlayTable.fileInfo.content == NULL) {
DebugPrintf("No overlaytable to release\n");
} else {
DebugPrintf("Releasing overlayTable\n");
FreeBuffer(&component->overlayTable.fileInfo);
}
component->overlayTable.table = NULL;
}

View File

@ -1,18 +0,0 @@
#ifndef OVERLAY_TABLE_H
#define OVERLAY_TABLE_H
#include <stdbool.h>
#include "component.h"
#define OVERLAY_ENTRY_SIZE 32
#define OT_FILESIZE_OFFSET 0x8
#define OT_COMPRESSED_FILESIZE_OFFSET 0x1c
#define OT_COMPRESSED_FLAGS_OFFSET 0x1f
bool ReadOverlayTable(Component *component, char *filename);
bool WriteOverlayTable(Component *component);
bool AddSuffixOverlayTable(Component *component, char *suffix);
void FreeOverlayTable(Component *component);
#endif // OVERLAY_TABLE_H

View File

@ -1,22 +0,0 @@
#include <stdarg.h>
#include <stdio.h>
#include "global.h"
#include "print.h"
void DebugPrintf(const char *format, ...) {
if (!gDebugMode) return;
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
void ErrorPrintf(const char *format, ...) {
printf("Error: ");
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}

View File

@ -1,7 +0,0 @@
#ifndef PRINT_H
#define PRINT_H
void DebugPrintf(const char *format, ...);
void ErrorPrintf(const char *format, ...);
#endif // PRINT_H

View File

@ -1,74 +0,0 @@
#include <stdbool.h>
#include <string.h>
#include "files.h"
#include "global.h"
#include "misc.h"
#include "overlay_defs.h"
#include "print.h"
#include "static_module.h"
bool ReadStaticModule(Component *component, char *filename) {
bool success;
StaticModule *staticModule = &component->staticModule;
DebugPrintf("Reading staticModule=%s\n", filename);
int fileSize = ReadFile(filename, &staticModule->fileInfo.content);
staticModule->fileInfo.fileSize = fileSize;
staticModule->fileInfo.compressedSize = 0;
staticModule->fileInfo.rewrite = false;
staticModule->fileInfo.filename = strdup(filename);
if (staticModule->fileInfo.fileSize < 0) {
success = false;
} else if (staticModule->fileInfo.fileSize % 4 == 0) {
int footerOffset = *(int *)(component->overlayDefs.header + OVERLAY_DEFS_FOOTER_OFFSET);
uint footerOffsetAligned = ALIGN_4(footerOffset);
staticModule->footerSize = staticModule->fileInfo.fileSize - footerOffsetAligned;
staticModule->footerContent = staticModule->fileInfo.content + footerOffsetAligned;
staticModule->fileInfo.fileSize = footerOffset;
int staticParamsOffset = *(uint *)(staticModule->footerContent + 4);
if (staticModule->footerSize < 0xc || *(uint *)(staticModule->footerContent + STATIC_FOOTER_MAGIC_OFFSET) != 0xDEC00621) {
ErrorPrintf("Static module is older format (No footer extension).\n");
success = false;
} else if (((staticParamsOffset % 4) == 0) &&
(staticParamsOffset > -1) &&
(staticParamsOffset < footerOffset)) {
success = true;
} else {
ErrorPrintf("Static module is illegal format (Unknown footer format).\n");
success = false;
}
} else {
ErrorPrintf("Static module size is illegal (size=%d). Must be aligned by 4\n");
success = false;
}
return success;
}
bool WriteStaticModule(Component *component) {
bool success;
StaticModule *staticModule = &component->staticModule;
if (!staticModule->fileInfo.rewrite) {
success = true;
} else {
DebugPrintf("Writing staticModule=%s\n", staticModule->fileInfo.filename);
int fileSize = staticModule->fileInfo.compressedSize ? staticModule->fileInfo.compressedSize : staticModule->fileInfo.fileSize;
int sizeWritten = WriteFile(staticModule->fileInfo.filename, staticModule->fileInfo.content, fileSize + staticModule->footerSize);
success = sizeWritten >= 0;
}
return success;
}
bool AddSuffixStaticModule(Component *component, char *suffix) {
DebugPrintf("Adding suffix staticModule=%s\n", suffix);
return AddSuffixBuffer(&component->staticModule.fileInfo, suffix);
}
void FreeStaticModule(Component *component) {
DebugPrintf("Releasing staticModule\n");
FreeBuffer(&component->staticModule.fileInfo);
component->staticModule.footerContent = NULL;
component->staticModule.footerSize = 0;
}

View File

@ -1,25 +0,0 @@
#ifndef STATIC_MODULE_H
#define STATIC_MODULE_H
#include <stdbool.h>
#include "global.h"
#define STATIC_FOOTER_MAGIC_OFFSET (0)
#define STATIC_FOOTER_STATIC_PARAM_OFFSET (4)
#define STATIC_FOOTER_DIGEST_PARAM_OFFSET (8)
typedef struct {
uint autoloadList;
uint autoloadListEnd;
uint autoloadStart;
uint staticBssStart;
uint staticBssEnd;
int compressedStatic;
} StaticParams;
bool ReadStaticModule(Component *component, char *filename);
bool WriteStaticModule(Component *component);
bool AddSuffixStaticModule(Component *component, char *suffix);
void FreeStaticModule(Component *component);
#endif // STATIC_MODULE_H

View File

@ -1,53 +0,0 @@
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "print.h"
#include "str.h"
char *StrCat(int count, ...) {
char *dest;
char *word;
int length;
va_list args;
va_start(args, count);
va_list argsCpy;
va_copy(argsCpy, args);
int totalLength = 0;
for (int i = 0; i < count; i++) {
word = va_arg(args, char *);
length = strlen(word);
totalLength += length;
}
va_end(args);
dest = malloc(totalLength + 1);
if (dest == NULL) {
ErrorPrintf("Cannot allocate memory\n");
exit(1);
}
dest[0] = '\0';
for (int i = 0; i < count; i++) {
word = va_arg(argsCpy, char *);
length = strlen(word);
strcat(dest, word);
}
va_end(argsCpy);
return dest;
}
char *StrDup(char *prevDest, char *src) {
if (prevDest != NULL) {
free(prevDest);
}
if (src != NULL) {
src = strdup(src);
if (src == NULL) {
ErrorPrintf("Cannot allocate memory\n");
exit(1);
}
}
return src;
}

View File

@ -1,7 +0,0 @@
#ifndef STR_H
#define STR_H
char *StrCat(int count, ...);
char *StrDup(char *prevDest, char *src);
#endif // STR_H