summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAetias <aetias@outlook.com>2023-10-21 10:36:14 +0200
committerAetias <aetias@outlook.com>2023-10-21 10:36:14 +0200
commitd2f26367743c4393d469809633fa2f3074679e0c (patch)
treef24e6d1d6d9cf41dcc55abb8cd2d4f99b89059d4
parentadd71a74821021e20eeeffc00ec1030224526378 (diff)
Match secure area CRC
-rw-r--r--.gitignore1
-rw-r--r--INSTALL.md28
-rw-r--r--Makefile5
-rw-r--r--README.md2
-rw-r--r--tools/rom/build.c37
5 files changed, 52 insertions, 21 deletions
diff --git a/.gitignore b/.gitignore
index 4497de2f..c8c16468 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ ph_jpn/
ph_usa/
ph_eur/
*.nds
+*bios.bin
diff --git a/INSTALL.md b/INSTALL.md
index fe653525..43b80275 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -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™).
diff --git a/Makefile b/Makefile
index 62f2212c..6af70c03 100644
--- a/Makefile
+++ b/Makefile
@@ -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:
diff --git a/README.md b/README.md
index a0860a16..5ca2ea69 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/tools/rom/build.c b/tools/rom/build.c
index 363d244a..878157e6 100644
--- a/tools/rom/build.c
+++ b/tools/rom/build.c
@@ -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;
- }
- tmp = *a ^ blowfish.subkeys[0x11];
- *a = *b ^ blowfish.subkeys[0x10];
- *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;
+ }
+ *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));