## page was renamed from Nanarin Binary script with entry points for saves. Ignore the entry points. Bytecode implementation here is hacky. Shift-JIS, except hiragana is encoded in single bytes. {{{#!highlight c++ //「日本語 This file is shift‐jis. I’m sorry, but there’s a reason.」 // This file is shift-jis. I'm sorry, but there's a reason. // IF THIS FILE IS NOT ENCODED AS SHIFT-JIS, HIRAGANA WILL NOT DUMP CORRECTLY. // Dumper for Nanairo Reincarnation's script and maybe others #include #include #include // For some reason, they use compressed hiragana encodings. // Not only does this make it impossible to encode ascii text, it's batshit crazy. const char * array[] = { /* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF*/ /*0X*/ "", "ぁ", "あ", "ぃ", "い", "ぅ", "う", "ぇ", "え", "ぉ", "お", "か", "が", "き", "ぎ", "く", /*1X*/ "ぐ", "け", "げ", "こ", "ご", "さ", "ざ", "し", "じ", "す", "ず", "せ", "ぜ", "そ", "ぞ", "た", /*2X*/ "だ", "ち", "ぢ", "っ", "つ", "づ", "て", "で", "と", "ど", "な", "に", "ぬ", "ね", "の", "は", /*3X*/ "ば", "ぱ", "ひ", "び", "ぴ", "ふ", "ぶ", "ぷ", "へ", "べ", "ぺ", "ほ", "ぼ", "ぽ", "ま", "み", /*4X*/ "む", "め", "も", "ゃ", "や", "ゅ", "ゆ", "ょ", "よ", "ら", "り", "る", "れ", "ろ", "ゎ", "わ", /*5X*/ "ゐ", "ゑ", "を", "ん", "", "", "", "", "", "", "", "", "", "", "", "", /*6X*/ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*7X*/ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*8X*/ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*9X*/ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*AX*/ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*BX*/ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*CX*/ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*DX*/ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*EX*/ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /*FX*/ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }; bool is_jis_surrogate(uint8_t c) { if(c >= 0x80 and c <= 0xA0) return true; if(c >= 0xE0) return true; return false; } void output(int c) { putc(c, stdout); } int main(int argc, char ** argv) { // feed .MES files for(int i = 1; i < argc; i++) { auto f = fopen(argv[i], "rb"); if(!f) return puts("failed to open"), 0; uint32_t numlines; fread(&numlines, 4, 1, f); uint32_t defines; fread(&defines, 4, 1, f); fseek(f, 4*defines, SEEK_CUR); uint32_t startpoint = numlines*4 + defines*4 + 8; // documentation as code, not used // address of where to go for various save indexes? uint32_t * lineaddrs = (uint32_t *)malloc(sizeof(uint32_t)*numlines); fread(lineaddrs, 4, numlines, f); int c = 0; while(1) { c = fgetc(f); if(c < 0) break; // Opcode handling to stay in sync. Not proper reverse engineering, 95% guesswork. if(c != 0x0A) { switch(c) { case 0x32: // some kind of load command - variable width? case 0x1B: // some kind of jump? case 0x14: // some kind of jump? case 0x15: // some kind of jump? case 0x1A: fseek(f, 4, SEEK_CUR); continue; case 0x19: // related to text, seems to work to interpret it as a page marker fseek(f, 4, SEEK_CUR); printf("\n"); continue; case 0x18: case 0x04: case 0x0F: case 0x0E: case 0x0D: case 0x05: case 0x3C: case 0x42: case 0x43: case 0x34: case 0x17: case 0x3A: case 0x00: // ???????????????????? case 0x0C: case 0x02: case 0x11: case 0x3F: case 0x41: case 0x3B: case 0x35: continue; case 0x1C: // between lines in multi-line messages; line wrap? //printf(" "); continue; case 0x36: c = fgetc(f); if(c != 0x3D) { printf("Unexpected pattern byte %02X after 36 at %08X\n", uint8_t(c), ftell(f)-2); exit(0); } continue; case 0x33: // e.g. op33: 6E 6E 5F 68 30 30 30 30 2E 6F 67 67 "0x33: nn_h0000.ogg" while((c = fgetc(f)) != 0); continue; } if(c < 0) continue; printf("Unknown command %02X at %08X in %s\n", uint8_t(c), ftell(f)-1, argv[i]); printf("Next byte is %02X\n", fgetc(f)); exit(0); } // fall-through case command 0x0A: display text c = fgetc(f); while(c != 0) { if(is_jis_surrogate(c)) { output(c); c = fgetc(f); if(c == 0) break; output(c); } else { if(*(array[c]) == 0) { printf("Unknown encoded character %02X at %08X\n", uint8_t(c), ftell(f)-1); exit(0); } else if(*(array[c]) != 1) printf(array[c]); } c = fgetc(f); } } free(lineaddrs); fclose(f); } } }}}