mirror of
https://github.com/pret/pmd-sky.git
synced 2026-03-21 17:25:15 -05:00
Removed ARM9 compression
This commit is contained in:
parent
c52c9d4027
commit
cb5957ccf5
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -62,7 +62,6 @@ files/**/*.c
|
|||
# Utilities
|
||||
ntruncompbw
|
||||
*.elf
|
||||
*.sbin_LZ
|
||||
*.diff
|
||||
|
||||
*.dSYM
|
||||
|
|
|
|||
9
Makefile
9
Makefile
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
6
rom.rsf
6
rom.rsf
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
1
tools/compstatic/.gitignore
vendored
1
tools/compstatic/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
compstatic
|
||||
|
|
@ -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))
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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, ¶m);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef PRINT_H
|
||||
#define PRINT_H
|
||||
|
||||
void DebugPrintf(const char *format, ...);
|
||||
void ErrorPrintf(const char *format, ...);
|
||||
|
||||
#endif // PRINT_H
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef STR_H
|
||||
#define STR_H
|
||||
|
||||
char *StrCat(int count, ...);
|
||||
char *StrDup(char *prevDest, char *src);
|
||||
|
||||
#endif // STR_H
|
||||
Loading…
Reference in New Issue
Block a user