Match secure area CRC

This commit is contained in:
Aetias
2023-10-21 10:36:14 +02:00
parent add71a7482
commit d2f2636774
5 changed files with 51 additions and 20 deletions
+1
View File
@@ -4,3 +4,4 @@ ph_jpn/
ph_usa/
ph_eur/
*.nds
*bios.bin
+25 -3
View File
@@ -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™).
+5
View File
@@ -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:
+1 -1
View File
@@ -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
View File
@@ -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));