mirror of
https://github.com/zeldaret/ph
synced 2026-05-31 09:21:38 -04:00
Write ARM9 module info in buildrom
This commit is contained in:
+10
-6
@@ -911,17 +911,21 @@ func_02000b60: ; 0x02000b60
|
||||
|
||||
.global spAutoloadBlockInfosStart
|
||||
spAutoloadBlockInfosStart: ; 0x02000b64
|
||||
.word 0x02060fc0
|
||||
.word 0x0
|
||||
.global spAutoloadBlockInfosEnd
|
||||
spAutoloadBlockInfosEnd: ; 0x02000b68
|
||||
.word 0x02060fd8
|
||||
.word 0x0
|
||||
.global spAutoloadCode
|
||||
spAutoloadCode: ; 0x02000b6c
|
||||
.word 0x02058e20
|
||||
.word 0x0
|
||||
.global spBssStart
|
||||
spBssStart: ; 0x02000b70
|
||||
.word 0x02058e20
|
||||
.word 0x0
|
||||
.global spBssEnd
|
||||
spBssEnd: ; 0x02000b74
|
||||
.word 0x020773c0
|
||||
.word 0x0
|
||||
sCompressedCodeEnd: ; 0x02000b78
|
||||
.word 0x02041a64
|
||||
.word 0x0
|
||||
sSdkVersion: ; 0x02000b7c
|
||||
.word 0x04007530
|
||||
.word 0xdec00621 ; nitrocode
|
||||
|
||||
@@ -269,9 +269,11 @@ with open(f'{BUILD}arm9_linker_script.lcf', 'w') as file:
|
||||
for obj in ARM9_OBJECTS: file.write(f' {name(obj)}.o(.sinit)\n')
|
||||
file.write(' . = ALIGN(32);\n')
|
||||
for obj in ARM9_OBJECTS: file.write(f' {name(obj)}.o(.data)\n')
|
||||
file.write(' arm9_bss_start = .;\n')
|
||||
for obj in ARM9_OBJECTS: file.write(f' {name(obj)}.o(.bss)\n')
|
||||
for obj in ARM9_OBJECTS: file.write(f' {name(obj)}.o(.sbss)\n')
|
||||
file.write(' . = ALIGN(32);\n')
|
||||
file.write(' arm9_bss_end = .;\n')
|
||||
file.write(' } > ARM9\n')
|
||||
file.write('\n')
|
||||
file.write(' .itcm : {\n')
|
||||
@@ -291,13 +293,18 @@ with open(f'{BUILD}arm9_linker_script.lcf', 'w') as file:
|
||||
for obj in DTCM_OBJECTS: file.write(f' {name(obj)}.o(.data)\n')
|
||||
file.write(' dtcm_end = .;\n')
|
||||
file.write(' dtcm_size = dtcm_end - dtcm_start;\n')
|
||||
file.write(' . = ALIGN(32);\n')
|
||||
file.write(' dtcm_end = .;\n')
|
||||
file.write(' dtcm_aligned_size = dtcm_end - dtcm_start;\n')
|
||||
for obj in DTCM_OBJECTS: file.write(f' {name(obj)}.o(.bss)\n')
|
||||
for obj in DTCM_OBJECTS: file.write(f' {name(obj)}.o(.sbss)\n')
|
||||
file.write(' } > DTCM\n')
|
||||
file.write('\n')
|
||||
file.write(' .autoloads : {\n')
|
||||
file.write(' autoloads_start = arm9_bss_start + itcm_size + dtcm_size;\n')
|
||||
file.write(' WRITEW ADDR(ITCM); WRITEW itcm_size; WRITEW 0;\n')
|
||||
file.write(' WRITEW ADDR(DTCM); WRITEW dtcm_size; WRITEW 0xec0;\n')
|
||||
file.write(' autoloads_end = . + autoloads_start;\n')
|
||||
file.write(' } > AUTOLOADS\n')
|
||||
file.write('\n')
|
||||
file.write(' .footer : {\n')
|
||||
@@ -311,6 +318,11 @@ with open(f'{BUILD}arm9_linker_script.lcf', 'w') as file:
|
||||
file.write(' WRITEW spAutoloadBlockInfosStart - ADDR(ARM9);\n')
|
||||
file.write(' WRITEW Entry;\n')
|
||||
file.write(' WRITEW ADDR(ARM9);\n')
|
||||
file.write(' WRITEW autoloads_start;\n')
|
||||
file.write(' WRITEW autoloads_end;\n')
|
||||
file.write(' WRITEW arm9_bss_start;\n')
|
||||
file.write(' WRITEW arm9_bss_start;\n')
|
||||
file.write(' WRITEW arm9_bss_end;\n')
|
||||
file.write(' } > METADATA\n')
|
||||
file.write('\n')
|
||||
for ov in OVERLAYS:
|
||||
|
||||
+96
-28
@@ -8,7 +8,7 @@
|
||||
#include "util.h"
|
||||
#include "files.h"
|
||||
|
||||
#define VERSION "1.0.1"
|
||||
#define VERSION "1.1"
|
||||
|
||||
#define BUFFER_SIZE 1024 * 1024
|
||||
uint8_t *readBuffer = NULL;
|
||||
@@ -184,6 +184,57 @@ void InitHeader(Header *pHeader, const BuildInfo *info) {
|
||||
memset(&pHeader->reserved7, 0, sizeof(pHeader->reserved7));
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t autoloadBlocksStart;
|
||||
uint32_t autoloadBlocksEnd;
|
||||
uint32_t autoloadCode;
|
||||
uint32_t bssStart;
|
||||
uint32_t bssEnd;
|
||||
} Arm9ModuleInfo;
|
||||
|
||||
typedef struct {
|
||||
uint32_t autoloadCallback;
|
||||
uint32_t autoloadBlockInfos;
|
||||
uint32_t entryAddr;
|
||||
uint32_t baseAddr;
|
||||
Arm9ModuleInfo moduleInfo;
|
||||
} Arm9Metadata;
|
||||
|
||||
bool LoadArm9Metadata(Arm9Metadata *pMetadata) {
|
||||
FILE *fp = fopen(ARM9_METADATA_FILE, "rb");
|
||||
if (fp == NULL) FATAL("Failed to open ARM9 metadata '" ARM9_METADATA_FILE "'\n");
|
||||
if (fread(pMetadata, sizeof(*pMetadata), 1, fp) != 1) FATAL("Failed to read ARM9 metadata '" ARM9_METADATA_FILE "'\n");
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reads an entire file into a newly allocated buffer and writes it to *pBuffer if successful.
|
||||
// If pFileSize != NULL, this function writes the file's size into *pFileSize.
|
||||
// The buffer can be freed with free().
|
||||
bool ReadFile(const char *filePath, uint8_t **pBuffer, uint32_t *pFileSize) {
|
||||
FILE *fp = fopen(filePath, "rb");
|
||||
if (fp == NULL) FATAL("Failed to open file '%s'\n", filePath);
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size_t size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
uint8_t *buffer = malloc(size);
|
||||
if (buffer == NULL) FATAL("Failed to allocate buffer for file '%s'\n", filePath);
|
||||
uint8_t *current = buffer;
|
||||
uint8_t *end = buffer + size;
|
||||
|
||||
while (current < end) {
|
||||
size_t bytesRead = fread(current, 1, BUFFER_SIZE, fp);
|
||||
if (bytesRead == 0) FATAL("Failed to read from file '%s'\n", filePath);
|
||||
current += bytesRead;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
*pBuffer = buffer;
|
||||
if (pFileSize != NULL) *pFileSize = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AppendFile(FILE *fpRom, const char *filePath, size_t *pAddress, uint32_t *pFileSize) {
|
||||
assert(readBuffer != NULL);
|
||||
|
||||
@@ -207,6 +258,37 @@ bool AppendFile(FILE *fpRom, const char *filePath, size_t *pAddress, uint32_t *p
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteArm9Program(FILE *fpRom, size_t *pAddress, uint32_t *pFileSize, uint32_t *pSecureArea, const Arm9Metadata *metadata) {
|
||||
size_t address = *pAddress;
|
||||
|
||||
uint8_t *arm9;
|
||||
uint32_t fileSize;
|
||||
if (!ReadFile(ARM9_PROGRAM_FILE, &arm9, &fileSize)) return false;
|
||||
|
||||
// Write module info, see spAutoloadBlockInfosStart in asm/main.s
|
||||
// This might seem unsafe since the ARM9 program is compressed, but the addresses we're writing to are in the secure area,
|
||||
// which is uncompressed.
|
||||
|
||||
size_t offset = metadata->autoloadBlockInfos;
|
||||
// First five values, from spAutoloadBlockInfosStart to spBssEnd
|
||||
memcpy(&arm9[offset], &metadata->moduleInfo, sizeof(metadata->moduleInfo));
|
||||
offset += sizeof(metadata->moduleInfo);
|
||||
// Last value, sCompressedCodeEnd
|
||||
uint32_t compressedCodeEnd = 0x2000000 + fileSize;
|
||||
memcpy(&arm9[offset], &compressedCodeEnd, sizeof(compressedCodeEnd));
|
||||
offset += compressedCodeEnd;
|
||||
|
||||
if (fwrite(arm9, fileSize, 1, fpRom) != 1) FATAL("Failed to write ARM9 program\n");
|
||||
address += fileSize;
|
||||
|
||||
memcpy(pSecureArea, arm9, SECURE_AREA_SIZE);
|
||||
free(arm9);
|
||||
|
||||
*pAddress = address;
|
||||
*pFileSize = fileSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Align(size_t alignment, FILE *fpRom, size_t *pAddress) {
|
||||
assert((alignment & (alignment - 1)) == 0);
|
||||
|
||||
@@ -661,25 +743,12 @@ bool RewriteFat(FILE *fpRom, size_t fatStart, const FatEntry *entries, size_t nu
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t autoloadCallback;
|
||||
uint32_t autoloadBlockInfos;
|
||||
uint32_t entryAddr;
|
||||
uint32_t baseAddr;
|
||||
} Arm9Metadata;
|
||||
|
||||
bool FinalizeHeader(FILE *fpRom, Header *pHeader, const char *arm7bios) {
|
||||
bool FinalizeHeader(FILE *fpRom, Header *pHeader, const char *arm7bios, uint32_t *secureArea, const Arm9Metadata *metadata) {
|
||||
Header header;
|
||||
memcpy(&header, pHeader, sizeof(header));
|
||||
|
||||
if (arm7bios != NULL) {
|
||||
FILE *fp = fopen(ARM9_PROGRAM_FILE, "rb");
|
||||
if (fp == NULL) FATAL("Failed to open ARM9 program '" ARM9_PROGRAM_FILE "'\n");
|
||||
uint32_t secureArea[0x1000];
|
||||
if (fread(secureArea, sizeof(secureArea), 1, fp) != 1) FATAL("Failed to read secure area\n");
|
||||
fclose(fp);
|
||||
|
||||
fp = fopen(arm7bios, "rb");
|
||||
FILE *fp = fopen(arm7bios, "rb");
|
||||
if (fp == NULL) FATAL("Failed to open ARM7 BIOS '%s'\n", arm7bios);
|
||||
fseek(fp, 0x30, SEEK_SET);
|
||||
uint8_t encKey[sizeof(Blowfish)];
|
||||
@@ -694,18 +763,13 @@ bool FinalizeHeader(FILE *fpRom, Header *pHeader, const char *arm7bios) {
|
||||
BlowfishEncrypt(&secureArea[0], &secureArea[1]);
|
||||
if (!BlowfishInit(encKey, pHeader, 2)) return false;
|
||||
BlowfishEncrypt(&secureArea[0], &secureArea[1]);
|
||||
header.secureAreaCrc = Crc(secureArea, 0x4000);
|
||||
header.secureAreaCrc = Crc(secureArea, SECURE_AREA_SIZE);
|
||||
}
|
||||
|
||||
FILE *fp = fopen(ARM9_METADATA_FILE, "rb");
|
||||
if (fp == NULL) FATAL("Failed to open ARM9 metadata '" ARM9_METADATA_FILE "'\n");
|
||||
Arm9Metadata metadata;
|
||||
if (fread(&metadata, sizeof(metadata), 1, fp) != 1) FATAL("Failed to read ARM9 metadata '" ARM9_METADATA_FILE "'\n");
|
||||
fclose(fp);
|
||||
header.arm9.entry = metadata.entryAddr;
|
||||
header.arm9.baseAddr = metadata.baseAddr;
|
||||
header.arm9AutoloadCallback = metadata.autoloadCallback;
|
||||
header.autoloadBlockInfosOffset = header.arm9.offset + metadata.autoloadBlockInfos;
|
||||
header.arm9.entry = metadata->entryAddr;
|
||||
header.arm9.baseAddr = metadata->baseAddr;
|
||||
header.arm9AutoloadCallback = metadata->autoloadCallback;
|
||||
header.autoloadBlockInfosOffset = header.arm9.offset + metadata->autoloadBlockInfos;
|
||||
|
||||
header.headerCrc = Crc(&header, offsetof(Header, headerCrc));
|
||||
|
||||
@@ -877,7 +941,11 @@ int main(int argc, char **argv) {
|
||||
|
||||
if (!Align(512, fpRom, &address)) return 1;
|
||||
header.arm9.offset = address;
|
||||
if (!AppendFile(fpRom, ARM9_PROGRAM_FILE, &address, &header.arm9.size)) return 1;
|
||||
|
||||
Arm9Metadata metadata;
|
||||
if (!LoadArm9Metadata(&metadata)) return 1;
|
||||
uint32_t secureArea[SECURE_AREA_SIZE / sizeof(uint32_t)];
|
||||
if (!WriteArm9Program(fpRom, &address, &header.arm9.size, secureArea, &metadata)) return 1;
|
||||
if (!AppendFile(fpRom, ARM9_FOOTER_FILE, &address, NULL)) return 1;
|
||||
|
||||
|
||||
@@ -986,7 +1054,7 @@ int main(int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!FinalizeHeader(fpRom, &header, arm7bios)) return false;
|
||||
if (!FinalizeHeader(fpRom, &header, arm7bios, secureArea, &metadata)) return false;
|
||||
FreeFullPath(&arm7bios);
|
||||
|
||||
if (chdir(rootDir) != 0) {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define SECURE_AREA_SIZE 0x4000
|
||||
|
||||
typedef struct {
|
||||
/* 00 */ uint32_t offset;
|
||||
/* 04 */ uint32_t entry;
|
||||
|
||||
Reference in New Issue
Block a user