Last active
January 8, 2022 17:26
-
-
Save plutooo/97191a7e9345817074fffe32f3a2df32 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Scramble/descramble raw NAND dumps from the NES Classic. | |
plutoo 2016 | |
Cheers to brizzo, derrek. | |
*/ | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdint.h> | |
#include <stddef.h> | |
static const uint16_t g_seed_table[] = | |
{ | |
0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72, | |
0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436, | |
0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d, | |
0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130, | |
0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56, | |
0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55, | |
0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb, | |
0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17, | |
0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62, | |
0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064, | |
0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126, | |
0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e, | |
0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3, | |
0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b, | |
0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d, | |
0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db | |
}; | |
static const uint16_t g_boot0_seed = 0x4a80; | |
#define PAGE_SIZE 0x400 | |
#define NAND_SIZE (512*1024*1024) | |
#define BOOT0_END 0x100000 | |
static void lfsr_scramble(uint16_t seed, uint8_t page[PAGE_SIZE]) | |
{ | |
uint16_t state = seed; | |
size_t i; | |
for (i=0; i<PAGE_SIZE; i++) | |
{ | |
size_t j; | |
for (j=0; j<8; j++) | |
state = (state >> 1) | (((state ^ (state >> 1)) & 1) << 14); | |
page[i] ^= (uint8_t) (state >> 7); | |
} | |
} | |
int main(int argc, char* argv[]) | |
{ | |
int rc = 0; | |
FILE* in = NULL; | |
FILE* out = NULL; | |
if (argc != 3) | |
{ | |
fprintf(stderr, "Usage: %s <in.bin> <out.bin>\n", argv[0]); | |
rc = 1; | |
goto ret; | |
} | |
in = fopen(argv[1], "rb"); | |
out = fopen(argv[2], "wb"); | |
if (in == NULL || out == NULL) | |
{ | |
fprintf(stderr, "Failed to open file.\n"); | |
rc = 1; | |
goto ret; | |
} | |
size_t i; | |
for (i=0; i<NAND_SIZE; i+=PAGE_SIZE) | |
{ | |
uint8_t page[PAGE_SIZE]; | |
if (fread(page, sizeof page, 1, in) != 1) | |
{ | |
fprintf(stderr, "Failed to read page %zu.. incomplete dump?", i); | |
rc = 1; | |
goto ret; | |
} | |
uint16_t seed; | |
// boot0 uses a fixed seed on every other page. | |
if (i < BOOT0_END) | |
seed = ((i % 2) == 0) ? g_boot0_seed : 0; | |
// rest uses half of the seed_table, accidentally reusing same seed | |
// twice in a row. | |
else | |
seed = g_seed_table[(i / (2*PAGE_SIZE)) & 0x3F]; // wat | |
lfsr_scramble(seed, page); | |
if (fwrite(page, sizeof page, 1, out) != 1) | |
{ | |
fprintf(stderr, "Failed to write page %zu..", i); | |
rc = 1; | |
goto ret; | |
} | |
} | |
ret: | |
if (in != NULL) fclose(in); | |
if (out != NULL) fclose(out); | |
return rc; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi plutoo, I have a dump made with the original hakchi. I think it's already unscrambled but I'm not sure as I am currently unable to mount it anyway. How to tell?