mirror of
https://github.com/zeldaret/ph
synced 2026-06-16 06:35:36 -04:00
Match secure area CRC
This commit is contained in:
@@ -4,3 +4,4 @@ ph_jpn/
|
||||
ph_usa/
|
||||
ph_eur/
|
||||
*.nds
|
||||
*bios.bin
|
||||
|
||||
+25
-3
@@ -4,6 +4,7 @@ Contents:
|
||||
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Build the ROM](#build-the-rom)
|
||||
- [Matching the base ROM](#matching-the-base-rom)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -19,9 +20,8 @@ python tools/setup.py
|
||||
|
||||
## Build the ROM
|
||||
|
||||
This repository does not include any of the game's assets. You will need an original decrypted ROM for the version(s) you want
|
||||
to build.
|
||||
Put the original ROM in the root directory of this repository. Please verify that your dumped ROM matches one of the versions
|
||||
This repository does not include any of the game's assets, and you will need an original decrypted base ROM.
|
||||
Put the base ROM in the root directory of this repository. Please verify that your dumped ROM matches one of the versions
|
||||
below:
|
||||
|
||||
| Version | File name | SHA1 |
|
||||
@@ -31,3 +31,25 @@ below:
|
||||
Run `make extract` to extract from the base ROM. You only need to do this once.
|
||||
|
||||
Once you have extracted the base ROM, simply run `make` to rebuild it.
|
||||
|
||||
### Matching the base ROM
|
||||
|
||||
**This is optional!** You only need to follow these steps if you want a matching ROM.
|
||||
|
||||
> [!NOTE]
|
||||
> For interested readers:
|
||||
> Retail games are usually "encrypted," which means that the first 0x800 bytes of the secure area is encrypted using a
|
||||
4168-byte key found in the ARM7 BIOS. The secure area is 0x4000 bytes long and lives at the start of the ARM9 program at
|
||||
address 0x2000000.
|
||||
> This encryption is optional, and games will run just fine without it. In fact, this project doesn't even produce an
|
||||
encrypted ROM. However, the ROM header includes a checksum of the secure area **after** encryption, so we must calculate it
|
||||
somehow.
|
||||
|
||||
First, [extract the ARM7 BIOS from your DS device](https://wiki.ds-homebrew.com/ds-index/ds-bios-firmware-dump). Put the
|
||||
ARM7 BIOS in the root directory of this repository, and verify that your dumped BIOS matches the one below:
|
||||
|
||||
| File name | SHA1 |
|
||||
| --------------- | ------------------------------------------ |
|
||||
| `arm7_bios.bin` | `6ee830c7f552c5bf194c20a2c13d5bb44bdb5c03` |
|
||||
|
||||
Now, `make` should automatically detect the ARM7 BIOS and will build a matching ROM (soon™).
|
||||
|
||||
@@ -14,6 +14,7 @@ TOOLS_DIR := $(ROOT)/tools
|
||||
BASE_DIR := $(ROOT)/ph_$(REGION_NAME)
|
||||
LCF_FILE := $(BUILD_DIR)/arm9_linker_script.lcf
|
||||
OBJS_FILE := $(BUILD_DIR)/arm9_objects.txt
|
||||
ARM7_BIOS := $(ROOT)/arm7_bios.bin
|
||||
|
||||
ASM_FILES := $(wildcard asm/*.s)
|
||||
CXX_FILES := $(wildcard src/*.cpp)
|
||||
@@ -49,7 +50,11 @@ tools:
|
||||
|
||||
.PHONY: rom
|
||||
rom: arm9
|
||||
ifneq (,$(wildcard $(ARM7_BIOS)))
|
||||
$(TOOLS_DIR)/rom/buildrom -a $(BASE_DIR) -b $(TARGET_DIR) -r $(REGION_SUFFIX) -o $(NDS_FILE) -7 $(ARM7_BIOS)
|
||||
else
|
||||
$(TOOLS_DIR)/rom/buildrom -a $(BASE_DIR) -b $(TARGET_DIR) -r $(REGION_SUFFIX) -o $(NDS_FILE)
|
||||
endif
|
||||
|
||||
.PHONY: extract
|
||||
extract:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
assembly code by hand. **The repository only contains code.** To build the ROM, you must own an existing copy of the game to
|
||||
extract assets from.
|
||||
|
||||
**Note:** The project can not build a ROM yet. Furthermore, it only targets the European version, and other versions might
|
||||
**Note:** The project can build a ROM, but it doesn't match the original ROM yet. Furthermore, it only targets the European version, and other versions might
|
||||
be supported later.
|
||||
|
||||
## How to install
|
||||
|
||||
+19
-16
@@ -68,24 +68,25 @@ uint32_t BlowfishF(size_t x) {
|
||||
return f;
|
||||
}
|
||||
|
||||
void BlowfishEncrypt(uint32_t *a, uint32_t *b) {
|
||||
void BlowfishEncrypt(uint32_t *pLeft, uint32_t *pRight) {
|
||||
uint32_t tmp;
|
||||
for (size_t i = 0; i < 0x12; ++i) {
|
||||
tmp = *a ^ blowfish.subkeys[i];
|
||||
*a = *b ^ BlowfishF(tmp);
|
||||
*b = tmp;
|
||||
uint32_t x = *pRight;
|
||||
uint32_t y = *pLeft;
|
||||
for (size_t i = 0; i < 0x10; ++i) {
|
||||
tmp = x ^ blowfish.subkeys[i];
|
||||
x = y ^ BlowfishF(tmp);
|
||||
y = tmp;
|
||||
}
|
||||
tmp = *a ^ blowfish.subkeys[0x11];
|
||||
*a = *b ^ blowfish.subkeys[0x10];
|
||||
*b = tmp;
|
||||
*pLeft = x ^ blowfish.subkeys[0x10];
|
||||
*pRight = y ^ blowfish.subkeys[0x11];
|
||||
}
|
||||
|
||||
void BlowfishApplyCode(uint32_t code[3]) {
|
||||
BlowfishEncrypt(&code[1], &code[2]);
|
||||
BlowfishEncrypt(&code[0], &code[1]);
|
||||
for (size_t i = 0; i < 0x12; i += 2) {
|
||||
blowfish.subkeys[i + 0] ^= REVERSE32(code[0]);
|
||||
blowfish.subkeys[i + 1] ^= REVERSE32(code[1]);
|
||||
for (size_t i = 0; i < 0x12; ++i) {
|
||||
uint32_t x = REVERSE32(code[i % 2]);
|
||||
blowfish.subkeys[i] ^= x;
|
||||
}
|
||||
|
||||
uint32_t scratch0 = 0;
|
||||
@@ -109,8 +110,8 @@ bool BlowfishInit(const uint8_t *encKey, const Header *pHeader, size_t level) {
|
||||
|
||||
uint32_t code[3];
|
||||
memcpy(&code[0], pHeader->gamecode, sizeof(code[0]));
|
||||
code[1] = code[0] << 1;
|
||||
code[2] = code[0] >> 1;
|
||||
code[1] = code[0] >> 1;
|
||||
code[2] = code[0] << 1;
|
||||
BlowfishApplyCode(code);
|
||||
if (level >= 2) BlowfishApplyCode(code);
|
||||
if (level >= 3) {
|
||||
@@ -524,13 +525,15 @@ bool FinalizeHeader(FILE *fpRom, Header *pHeader, const char *arm7bios, uint32_t
|
||||
if (fread(&encKey, sizeof(encKey), 1, fp) != 1) FATAL("Failed to read encrypion key\n");
|
||||
fclose(fp);
|
||||
|
||||
if (!BlowfishInit(encKey, pHeader, 2)) return false;
|
||||
BlowfishEncrypt(&secureArea[0], &secureArea[1]);
|
||||
if (!BlowfishInit(encKey, pHeader, 3)) return false;
|
||||
for (size_t i = 2; i < 0x200; i += 2) {
|
||||
BlowfishEncrypt(&secureArea[i], &secureArea[i + 1]);
|
||||
}
|
||||
header.secureAreaCrc = Crc(secureArea, sizeof(secureArea));
|
||||
memcpy(secureArea, "encryObj", 8);
|
||||
BlowfishEncrypt(&secureArea[0], &secureArea[1]);
|
||||
if (!BlowfishInit(encKey, pHeader, 2)) return false;
|
||||
BlowfishEncrypt(&secureArea[0], &secureArea[1]);
|
||||
header.secureAreaCrc = Crc(secureArea, 0x4000);
|
||||
}
|
||||
|
||||
header.headerCrc = Crc(&header, offsetof(Header, headerCrc));
|
||||
|
||||
Reference in New Issue
Block a user