diff --git a/build.sh b/build.sh index 4b428e2..c1dd036 100755 --- a/build.sh +++ b/build.sh @@ -2,4 +2,4 @@ # TEMP BUILD SCRIPT -gcc src/getdata/getdata.c src/setdata/optheaders.c src/setdata/populateheaders.c src/setdata/pagedescriptors.c src/placer/placer.c src/write/writexex.c src/write/headerhash.c src/main.c -o synthxex -lnettle -Wno-multichar -g -fsanitize=address +gcc src/common/common.c src/getdata/getdata.c src/setdata/optheaders.c src/setdata/populateheaders.c src/setdata/pagedescriptors.c src/placer/placer.c src/write/writexex.c src/write/headerhash.c src/main.c -o synthxex -lnettle -Wno-multichar -g -fsanitize=address diff --git a/src/common/common.c b/src/common/common.c new file mode 100644 index 0000000..63e23c6 --- /dev/null +++ b/src/common/common.c @@ -0,0 +1,24 @@ +// This file is part of SynthXEX, one component of the +// FreeChainXenon development toolchain +// +// Copyright (c) 2024 Aiden Isik +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "common.h" + +void infoPrint(char *str) +{ + printf("SynthXEX> %s\n", str); +} diff --git a/src/common/common.h b/src/common/common.h index dc49447..1f7cd33 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -29,9 +29,6 @@ #define COPYRIGHT "2024" #define VERSION_STRING "SynthXEX v0.0.1" -// Print constants -#define PRINT_STEM "SynthXEX>" - // Return values #define SUCCESS 0 diff --git a/src/getdata/getdata.c b/src/getdata/getdata.c index 133c16a..3daac83 100644 --- a/src/getdata/getdata.c +++ b/src/getdata/getdata.c @@ -152,15 +152,15 @@ int getSectionRwxFlags(FILE *pe, struct sections *sections) int getHdrData(FILE *pe, struct peData *peData, uint8_t flags) { // Get header data required for ANY XEX - + // PE size + struct stat peStat; + fstat(fileno(pe), &peStat); + peData->size = peStat.st_size; + // Getting PE header offset before we go any further.. fseek(pe, 0x3C, SEEK_SET); uint32_t peOffset = get32BitFromPE(pe); - // PE size - fseek(pe, peOffset + 0x50, SEEK_SET); - peData->size = get32BitFromPE(pe); - // Base address fseek(pe, peOffset + 0x34, SEEK_SET); peData->baseAddr = get32BitFromPE(pe); diff --git a/src/main.c b/src/main.c index 38fd46f..f22be2a 100644 --- a/src/main.c +++ b/src/main.c @@ -102,7 +102,7 @@ int main(int argc, char **argv) free(xexfilePath); } - printf("%s ERROR: Basefile input expected but not found. Aborting.", PRINT_STEM); + infoPrint("ERROR: Basefile input expected but not found. Aborting."); return -1; } else if(!gotOutput) @@ -112,7 +112,7 @@ int main(int argc, char **argv) free(basefilePath); } - printf("%s ERROR: Xexfile output expected but not found. Aborting.", PRINT_STEM); + infoPrint("ERROR: Xexfile output expected but not found. Aborting."); return -1; } @@ -132,7 +132,7 @@ int main(int argc, char **argv) if(!validatePE(pe)) { - printf("%s ERROR: Basefile is not Xbox 360 PE. Aborting.", PRINT_STEM); + infoPrint("ERROR: Basefile is not Xbox 360 PE. Aborting."); fclose(pe); fclose(xex); return -1; @@ -140,31 +140,31 @@ int main(int argc, char **argv) if(getHdrData(pe, &peData, 0) != 0) { - printf("%s ERROR: Unknown error in data retrieval from basefile. Aborting.", PRINT_STEM); + infoPrint("ERROR: Unknown error in data retrieval from basefile. Aborting."); fclose(pe); fclose(xex); return -1; } // TEMPORARY: READ IN IMPORT HEADER DATA -// FILE *importData = fopen("./import.bin", "r"); -// -// struct stat importStat; -// fstat(fileno(importData), &importStat); -// uint32_t importLen = importStat.st_size; -// -// fread(&(optHeaders.importLibraries.size), sizeof(uint8_t), 4, importData); -// -//#ifdef LITTLE_ENDIAN_SYSTEM -// optHeaders.importLibraries.size = ntohl(optHeaders.importLibraries.size); -//#endif + FILE *importData = fopen("./import.bin", "r"); + + struct stat importStat; + fstat(fileno(importData), &importStat); + uint32_t importLen = importStat.st_size; + + fread(&(optHeaders.importLibraries.size), sizeof(uint8_t), 4, importData); + +#ifdef LITTLE_ENDIAN_SYSTEM + optHeaders.importLibraries.size = ntohl(optHeaders.importLibraries.size); +#endif - //optHeaders.importLibraries.data = malloc(importLen - 0x4 * sizeof(uint8_t)); - //fread(optHeaders.importLibraries.data, sizeof(uint8_t), importLen - 0x4, importData); + optHeaders.importLibraries.data = malloc(importLen - 0x4 * sizeof(uint8_t)); + fread(optHeaders.importLibraries.data, sizeof(uint8_t), importLen - 0x4, importData); // Setting final XEX data structs setXEXHeader(&xexHeader); - setSecInfoHeader(&secInfoHeader, &peData); + setSecInfoHeader(&secInfoHeader, &peData, 0x823DFC64); // TEMP EXPORT TABLE ADDR setPageDescriptors(pe, &peData, &secInfoHeader); setOptHeaders(&secInfoHeader, &peData, &optHeaderEntries, &optHeaders); @@ -174,19 +174,19 @@ int main(int argc, char **argv) // Write out all of the XEX data to file if(writeXEX(&xexHeader, &optHeaderEntries, &secInfoHeader, &optHeaders, &offsets, pe, xex) != 0) { - printf("%s ERROR: Unknown error in XEX write routine. Aborting.", PRINT_STEM); + infoPrint("ERROR: Unknown error in XEX write routine. Aborting."); fclose(pe); fclose(xex); return -1; } - //free(optHeaders.importLibraries.data); + free(optHeaders.importLibraries.data); // Final pass (sets & writes header hash) setHeaderSha1(xex); // TEMPORARY: Hashing will be moved to earlier on when imports are implemented - //setImportsSha1(xex); + setImportsSha1(xex); fclose(pe); fclose(xex); diff --git a/src/placer/placer.c b/src/placer/placer.c index 4d1685b..e235ef7 100644 --- a/src/placer/placer.c +++ b/src/placer/placer.c @@ -91,7 +91,7 @@ void placeStructs(struct offsets *offsets, struct xexHeader *xexHeader, struct o struct importLibIdcs importLibIdcs; uint32_t importLibsIdx; // Entry in opt header entries of import libs setOptHeaderOffsets(offsets, optHeaderEntries, optHeaders, ¤tOffset, &importLibIdcs); - //currentOffset += optHeaders->importLibraries.size; // Reserving bytes for imports + currentOffset += optHeaders->importLibraries.size; // Reserving bytes for imports // PE basefile currentOffset = getNextAligned(currentOffset, 0x1000); // 4KiB alignment for basefile @@ -99,6 +99,6 @@ void placeStructs(struct offsets *offsets, struct xexHeader *xexHeader, struct o xexHeader->peOffset = currentOffset; // Imports, the end of this header is aligned to the start of the basefile, so they are a special case - //offsets->optHeaders[importLibIdcs.header] = offsets->basefile - optHeaders->importLibraries.size; - //optHeaderEntries->optHeaderEntry[importLibIdcs.entry].dataOrOffset = offsets->optHeaders[importLibIdcs.header]; + offsets->optHeaders[importLibIdcs.header] = offsets->basefile - optHeaders->importLibraries.size; + optHeaderEntries->optHeaderEntry[importLibIdcs.entry].dataOrOffset = offsets->optHeaders[importLibIdcs.header]; } diff --git a/src/setdata/optheaders.c b/src/setdata/optheaders.c index 6011d9f..d19db6f 100644 --- a/src/setdata/optheaders.c +++ b/src/setdata/optheaders.c @@ -49,7 +49,7 @@ void setSysFlags(uint32_t *flags) void setOptHeaders(struct secInfoHeader *secInfoHeader, struct peData *peData, struct optHeaderEntries *optHeaderEntries, struct optHeaders *optHeaders) { // TODO: Dynamically select optional headers to use, instead of hard-coding - optHeaderEntries->count = 4; + optHeaderEntries->count = 5; optHeaderEntries->optHeaderEntry = calloc(5, sizeof(struct optHeaderEntry)); // First optional header (basefile format) @@ -61,13 +61,13 @@ void setOptHeaders(struct secInfoHeader *secInfoHeader, struct peData *peData, s optHeaderEntries->optHeaderEntry[1].dataOrOffset = secInfoHeader->baseAddr + peData->entryPoint; // Third optional header (import libs) - //optHeaderEntries->optHeaderEntry[2].id = XEX_OPT_ID_IMPORT_LIBS; + optHeaderEntries->optHeaderEntry[2].id = XEX_OPT_ID_IMPORT_LIBS; // Fourth optional header (tls info) - optHeaderEntries->optHeaderEntry[2].id = XEX_OPT_ID_TLS_INFO; + optHeaderEntries->optHeaderEntry[3].id = XEX_OPT_ID_TLS_INFO; setTLSInfo(&(optHeaders->tlsInfo)); // Fifth optional header (system flags) - optHeaderEntries->optHeaderEntry[3].id = XEX_OPT_ID_SYS_FLAGS; - setSysFlags(&(optHeaderEntries->optHeaderEntry[3].dataOrOffset)); + optHeaderEntries->optHeaderEntry[4].id = XEX_OPT_ID_SYS_FLAGS; + setSysFlags(&(optHeaderEntries->optHeaderEntry[4].dataOrOffset)); } diff --git a/src/setdata/populateheaders.c b/src/setdata/populateheaders.c index 9956f3e..5cedbda 100644 --- a/src/setdata/populateheaders.c +++ b/src/setdata/populateheaders.c @@ -23,10 +23,10 @@ void setXEXHeader(struct xexHeader *xexHeader) // Writing data into XEX header. strcpy(xexHeader->magic, "XEX2"); // Magic xexHeader->moduleFlags = XEX_MOD_FLAG_TITLE; // Hard-coding until more options supported - xexHeader->optHeaderCount = 0x4; // Hard-coding until more optional headers supported, then maybe it can be determined dynamically. + xexHeader->optHeaderCount = 0x5; // Hard-coding until more optional headers supported, then maybe it can be determined dynamically. } -void setSecInfoHeader(struct secInfoHeader *secInfoHeader, struct peData *peData) +void setSecInfoHeader(struct secInfoHeader *secInfoHeader, struct peData *peData, uint32_t TEMPEXPORTADDR) { // Getting page size, if base address is >= 0x90000000 4KiB pages are used, else 64KiB. bool smallPages = peData->baseAddr < 0x90000000 ? false : true; @@ -43,8 +43,7 @@ void setSecInfoHeader(struct secInfoHeader *secInfoHeader, struct peData *peData secInfoHeader->baseAddr = peData->baseAddr; memset(secInfoHeader->mediaID, 0, sizeof(secInfoHeader->mediaID)); // Null media ID memset(secInfoHeader->aesKey, 0, sizeof(secInfoHeader->aesKey)); // No encryption, null AES key - //secInfoHeader->exportTableAddr = TEMPEXPORTADDR; - secInfoHeader->exportTableAddr = 0; + secInfoHeader->exportTableAddr = TEMPEXPORTADDR; secInfoHeader->gameRegion = XEX_REG_FLAG_REGION_FREE; secInfoHeader->mediaTypes = 0xFFFFFFFF; // All flags set, can load from any type. secInfoHeader->pageDescCount = secInfoHeader->peSize / ((smallPages ? 4 : 64) * 1024); // Number of page descriptors following security info (same number of pages) diff --git a/src/setdata/populateheaders.h b/src/setdata/populateheaders.h index 2996e0b..4fab65c 100644 --- a/src/setdata/populateheaders.h +++ b/src/setdata/populateheaders.h @@ -22,4 +22,4 @@ #include "../common/datastorage.h" void setXEXHeader(struct xexHeader *xexHeader); -void setSecInfoHeader(struct secInfoHeader *secInfoHeader, struct peData *peData); +void setSecInfoHeader(struct secInfoHeader *secInfoHeader, struct peData *peData, uint32_t TEMPEXPORTADDR);