Last active
July 26, 2017 22:58
-
-
Save wareya/cecf091068008916345b6a3b3b4c60ea to your computer and use it in GitHub Desktop.
mjo script dumper for sukinarasukitteitte
This file contains 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
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <string> | |
#include <vector> | |
uint8_t key[1024] = { | |
0x00,0x00,0x00,0x00,0x96,0x30,0x07,0x77,0x2c,0x61,0x0e,0xee,0xba,0x51,0x09,0x99, | |
0x19,0xc4,0x6d,0x07,0x8f,0xf4,0x6a,0x70,0x35,0xa5,0x63,0xe9,0xa3,0x95,0x64,0x9e, | |
0x32,0x88,0xdb,0x0e,0xa4,0xb8,0xdc,0x79,0x1e,0xe9,0xd5,0xe0,0x88,0xd9,0xd2,0x97, | |
0x2b,0x4c,0xb6,0x09,0xbd,0x7c,0xb1,0x7e,0x07,0x2d,0xb8,0xe7,0x91,0x1d,0xbf,0x90, | |
0x64,0x10,0xb7,0x1d,0xf2,0x20,0xb0,0x6a,0x48,0x71,0xb9,0xf3,0xde,0x41,0xbe,0x84, | |
0x7d,0xd4,0xda,0x1a,0xeb,0xe4,0xdd,0x6d,0x51,0xb5,0xd4,0xf4,0xc7,0x85,0xd3,0x83, | |
0x56,0x98,0x6c,0x13,0xc0,0xa8,0x6b,0x64,0x7a,0xf9,0x62,0xfd,0xec,0xc9,0x65,0x8a, | |
0x4f,0x5c,0x01,0x14,0xd9,0x6c,0x06,0x63,0x63,0x3d,0x0f,0xfa,0xf5,0x0d,0x08,0x8d, | |
0xc8,0x20,0x6e,0x3b,0x5e,0x10,0x69,0x4c,0xe4,0x41,0x60,0xd5,0x72,0x71,0x67,0xa2, | |
0xd1,0xe4,0x03,0x3c,0x47,0xd4,0x04,0x4b,0xfd,0x85,0x0d,0xd2,0x6b,0xb5,0x0a,0xa5, | |
0xfa,0xa8,0xb5,0x35,0x6c,0x98,0xb2,0x42,0xd6,0xc9,0xbb,0xdb,0x40,0xf9,0xbc,0xac, | |
0xe3,0x6c,0xd8,0x32,0x75,0x5c,0xdf,0x45,0xcf,0x0d,0xd6,0xdc,0x59,0x3d,0xd1,0xab, | |
0xac,0x30,0xd9,0x26,0x3a,0x00,0xde,0x51,0x80,0x51,0xd7,0xc8,0x16,0x61,0xd0,0xbf, | |
0xb5,0xf4,0xb4,0x21,0x23,0xc4,0xb3,0x56,0x99,0x95,0xba,0xcf,0x0f,0xa5,0xbd,0xb8, | |
0x9e,0xb8,0x02,0x28,0x08,0x88,0x05,0x5f,0xb2,0xd9,0x0c,0xc6,0x24,0xe9,0x0b,0xb1, | |
0x87,0x7c,0x6f,0x2f,0x11,0x4c,0x68,0x58,0xab,0x1d,0x61,0xc1,0x3d,0x2d,0x66,0xb6, | |
0x90,0x41,0xdc,0x76,0x06,0x71,0xdb,0x01,0xbc,0x20,0xd2,0x98,0x2a,0x10,0xd5,0xef, | |
0x89,0x85,0xb1,0x71,0x1f,0xb5,0xb6,0x06,0xa5,0xe4,0xbf,0x9f,0x33,0xd4,0xb8,0xe8, | |
0xa2,0xc9,0x07,0x78,0x34,0xf9,0x00,0x0f,0x8e,0xa8,0x09,0x96,0x18,0x98,0x0e,0xe1, | |
0xbb,0x0d,0x6a,0x7f,0x2d,0x3d,0x6d,0x08,0x97,0x6c,0x64,0x91,0x01,0x5c,0x63,0xe6, | |
0xf4,0x51,0x6b,0x6b,0x62,0x61,0x6c,0x1c,0xd8,0x30,0x65,0x85,0x4e,0x00,0x62,0xf2, | |
0xed,0x95,0x06,0x6c,0x7b,0xa5,0x01,0x1b,0xc1,0xf4,0x08,0x82,0x57,0xc4,0x0f,0xf5, | |
0xc6,0xd9,0xb0,0x65,0x50,0xe9,0xb7,0x12,0xea,0xb8,0xbe,0x8b,0x7c,0x88,0xb9,0xfc, | |
0xdf,0x1d,0xdd,0x62,0x49,0x2d,0xda,0x15,0xf3,0x7c,0xd3,0x8c,0x65,0x4c,0xd4,0xfb, | |
0x58,0x61,0xb2,0x4d,0xce,0x51,0xb5,0x3a,0x74,0x00,0xbc,0xa3,0xe2,0x30,0xbb,0xd4, | |
0x41,0xa5,0xdf,0x4a,0xd7,0x95,0xd8,0x3d,0x6d,0xc4,0xd1,0xa4,0xfb,0xf4,0xd6,0xd3, | |
0x6a,0xe9,0x69,0x43,0xfc,0xd9,0x6e,0x34,0x46,0x88,0x67,0xad,0xd0,0xb8,0x60,0xda, | |
0x73,0x2d,0x04,0x44,0xe5,0x1d,0x03,0x33,0x5f,0x4c,0x0a,0xaa,0xc9,0x7c,0x0d,0xdd, | |
0x3c,0x71,0x05,0x50,0xaa,0x41,0x02,0x27,0x10,0x10,0x0b,0xbe,0x86,0x20,0x0c,0xc9, | |
0x25,0xb5,0x68,0x57,0xb3,0x85,0x6f,0x20,0x09,0xd4,0x66,0xb9,0x9f,0xe4,0x61,0xce, | |
0x0e,0xf9,0xde,0x5e,0x98,0xc9,0xd9,0x29,0x22,0x98,0xd0,0xb0,0xb4,0xa8,0xd7,0xc7, | |
0x17,0x3d,0xb3,0x59,0x81,0x0d,0xb4,0x2e,0x3b,0x5c,0xbd,0xb7,0xad,0x6c,0xba,0xc0, | |
0x20,0x83,0xb8,0xed,0xb6,0xb3,0xbf,0x9a,0x0c,0xe2,0xb6,0x03,0x9a,0xd2,0xb1,0x74, | |
0x39,0x47,0xd5,0xea,0xaf,0x77,0xd2,0x9d,0x15,0x26,0xdb,0x04,0x83,0x16,0xdc,0x73, | |
0x12,0x0b,0x63,0xe3,0x84,0x3b,0x64,0x94,0x3e,0x6a,0x6d,0x0d,0xa8,0x5a,0x6a,0x7a, | |
0x0b,0xcf,0x0e,0xe4,0x9d,0xff,0x09,0x93,0x27,0xae,0x00,0x0a,0xb1,0x9e,0x07,0x7d, | |
0x44,0x93,0x0f,0xf0,0xd2,0xa3,0x08,0x87,0x68,0xf2,0x01,0x1e,0xfe,0xc2,0x06,0x69, | |
0x5d,0x57,0x62,0xf7,0xcb,0x67,0x65,0x80,0x71,0x36,0x6c,0x19,0xe7,0x06,0x6b,0x6e, | |
0x76,0x1b,0xd4,0xfe,0xe0,0x2b,0xd3,0x89,0x5a,0x7a,0xda,0x10,0xcc,0x4a,0xdd,0x67, | |
0x6f,0xdf,0xb9,0xf9,0xf9,0xef,0xbe,0x8e,0x43,0xbe,0xb7,0x17,0xd5,0x8e,0xb0,0x60, | |
0xe8,0xa3,0xd6,0xd6,0x7e,0x93,0xd1,0xa1,0xc4,0xc2,0xd8,0x38,0x52,0xf2,0xdf,0x4f, | |
0xf1,0x67,0xbb,0xd1,0x67,0x57,0xbc,0xa6,0xdd,0x06,0xb5,0x3f,0x4b,0x36,0xb2,0x48, | |
0xda,0x2b,0x0d,0xd8,0x4c,0x1b,0x0a,0xaf,0xf6,0x4a,0x03,0x36,0x60,0x7a,0x04,0x41, | |
0xc3,0xef,0x60,0xdf,0x55,0xdf,0x67,0xa8,0xef,0x8e,0x6e,0x31,0x79,0xbe,0x69,0x46, | |
0x8c,0xb3,0x61,0xcb,0x1a,0x83,0x66,0xbc,0xa0,0xd2,0x6f,0x25,0x36,0xe2,0x68,0x52, | |
0x95,0x77,0x0c,0xcc,0x03,0x47,0x0b,0xbb,0xb9,0x16,0x02,0x22,0x2f,0x26,0x05,0x55, | |
0xbe,0x3b,0xba,0xc5,0x28,0x0b,0xbd,0xb2,0x92,0x5a,0xb4,0x2b,0x04,0x6a,0xb3,0x5c, | |
0xa7,0xff,0xd7,0xc2,0x31,0xcf,0xd0,0xb5,0x8b,0x9e,0xd9,0x2c,0x1d,0xae,0xde,0x5b, | |
0xb0,0xc2,0x64,0x9b,0x26,0xf2,0x63,0xec,0x9c,0xa3,0x6a,0x75,0x0a,0x93,0x6d,0x02, | |
0xa9,0x06,0x09,0x9c,0x3f,0x36,0x0e,0xeb,0x85,0x67,0x07,0x72,0x13,0x57,0x00,0x05, | |
0x82,0x4a,0xbf,0x95,0x14,0x7a,0xb8,0xe2,0xae,0x2b,0xb1,0x7b,0x38,0x1b,0xb6,0x0c, | |
0x9b,0x8e,0xd2,0x92,0x0d,0xbe,0xd5,0xe5,0xb7,0xef,0xdc,0x7c,0x21,0xdf,0xdb,0x0b, | |
0xd4,0xd2,0xd3,0x86,0x42,0xe2,0xd4,0xf1,0xf8,0xb3,0xdd,0x68,0x6e,0x83,0xda,0x1f, | |
0xcd,0x16,0xbe,0x81,0x5b,0x26,0xb9,0xf6,0xe1,0x77,0xb0,0x6f,0x77,0x47,0xb7,0x18, | |
0xe6,0x5a,0x08,0x88,0x70,0x6a,0x0f,0xff,0xca,0x3b,0x06,0x66,0x5c,0x0b,0x01,0x11, | |
0xff,0x9e,0x65,0x8f,0x69,0xae,0x62,0xf8,0xd3,0xff,0x6b,0x61,0x45,0xcf,0x6c,0x16, | |
0x78,0xe2,0x0a,0xa0,0xee,0xd2,0x0d,0xd7,0x54,0x83,0x04,0x4e,0xc2,0xb3,0x03,0x39, | |
0x61,0x26,0x67,0xa7,0xf7,0x16,0x60,0xd0,0x4d,0x47,0x69,0x49,0xdb,0x77,0x6e,0x3e, | |
0x4a,0x6a,0xd1,0xae,0xdc,0x5a,0xd6,0xd9,0x66,0x0b,0xdf,0x40,0xf0,0x3b,0xd8,0x37, | |
0x53,0xae,0xbc,0xa9,0xc5,0x9e,0xbb,0xde,0x7f,0xcf,0xb2,0x47,0xe9,0xff,0xb5,0x30, | |
0x1c,0xf2,0xbd,0xbd,0x8a,0xc2,0xba,0xca,0x30,0x93,0xb3,0x53,0xa6,0xa3,0xb4,0x24, | |
0x05,0x36,0xd0,0xba,0x93,0x06,0xd7,0xcd,0x29,0x57,0xde,0x54,0xbf,0x67,0xd9,0x23, | |
0x2e,0x7a,0x66,0xb3,0xb8,0x4a,0x61,0xc4,0x02,0x1b,0x68,0x5d,0x94,0x2b,0x6f,0x2a, | |
0x37,0xbe,0x0b,0xb4,0xa1,0x8e,0x0c,0xc3,0x1b,0xdf,0x05,0x5a,0x8d,0xef,0x02,0x2d}; | |
void fread_or_die(void * a, size_t b, size_t c, FILE * d) | |
{ | |
size_t got = fread(a, b, c, d); | |
if(feof(d)) {puts("feof"); exit(0);} | |
if(ferror(d)) {puts("ferror"); exit(0);} | |
if(got != c) {exit(0);} | |
} | |
bool is_jis_surrogate(uint8_t c) | |
{ | |
if(c >= 0x80 and c <= 0xA0) return true; | |
if(c >= 0xE0) return true; | |
return false; | |
} | |
int main(int argc, char ** argv) | |
{ | |
//16 header | |
//4 ? | |
//4 ? | |
//4 num? | |
//8[num?] ? | |
//4 scriptsize | |
//1 script[scriptsize] | |
if(argc < 2) return puts("usage: unmjo file.mjo"), 0; | |
auto f = fopen(argv[1], "rb"); | |
char magic[16]; | |
fread(magic, 1, 16, f); | |
if(strncmp(magic, "MajiroObjX1.000", 16) != 0) return puts("unsupported file"), puts(argv[1]), 0; | |
uint32_t crap[2]; | |
fread(crap, 4, 2, f); | |
uint32_t numoffsets; | |
fread(&numoffsets, 4, 1, f); | |
for(uint32_t i = 0; i < numoffsets; i++) | |
{ | |
uint32_t offsetdata[2]; | |
fread(offsetdata, 4, 2, f); | |
} | |
uint32_t length; | |
fread(&length, 4, 1, f); | |
unsigned char * data = (unsigned char *)malloc(length); | |
fread(data, 1, length, f); | |
uint32_t i = 0; | |
while(i < length) | |
{ | |
data[i] ^= key[i%1024]; | |
i++; | |
} | |
auto f3 = fopen((std::string(argv[1])+".dec").data(), "wb"); | |
for(uint32_t i = 0; i < length; i++) | |
{ | |
fputc(data[i], f3); | |
} | |
auto f2 = fopen((std::string(argv[1])+".script.txt").data(), "wb"); | |
//auto f2 = fopen((std::string(argv[1])+".dec").data(), "wb"); | |
i = 0; | |
auto fake_fread = [data, &i, length](void * write, int size, int num) | |
{ | |
if(i+size*num > length) exit(0); | |
unsigned char * real_write = (unsigned char *)write; | |
for(int j = 0; j < size*num; j++) | |
{ | |
real_write[j] = data[i]; | |
i++; | |
} | |
}; | |
auto fake_fgetc = [data, &i, length]() | |
{ | |
if(i >= length) exit(0); | |
return data[i++]; | |
}; | |
int furigana_length = 0; | |
std::vector<std::string> internal_text; | |
int debug = 0; | |
while(1) | |
{ | |
uint16_t n; | |
fake_fread(&n, 2, 1); | |
if(debug) fprintf(f2, "\n>%04X:%04X\n", i-2, n); | |
// 083A XXXX: line in original code? | |
// 0840 XXXX: content text of length XXXX | |
// 0801 XXXX: internal text of length XXXX (also used for furigana) | |
// 0841: after content text, always occurs, but sometimes before it too, no idea what it does | |
// 0810: followed by two shorts, seem to dictate what to do with the significance of whatever's on the stack: | |
// - FDF0 812A F0 FD 2A 81 speech file | |
// - FD01 3198 01 FD 98 31 furigana | |
// - EE67 0836 67 EE 36 08 triggers (allows?) a wait for input (also affects auto mode's wait timer) | |
// further followed by three shorts, the first two are blank in the file but modified at runtime. | |
// if, at runtime, you change the 0810 "command" but not the rewritten shorts, it will continue to act like the old command. | |
// example: | |
// F0 FD 2A 81 -> 25 D6 FE 07 | |
// 01 FD 98 31 -> B6 1C FF 07 | |
// 67 EE 36 08 -> D5 0C FF 07 | |
// the last of the three shorts seems to be 0 or 1, sometimes 2. stack usage? | |
// similar to 0810: 080F, 0835 | |
// 0842: text control? | |
// 0842 0002 XXXX (?), where | |
// 006E : new line. waits for input. fucks up the backlog if you use it multiple times in a row | |
// 0070 : wait for input, even twice if you use it multiple times in a row | |
// 0077 : new page, move to upper left | |
// normally 0070 and 0077 are run in that order together | |
// but if you replace the 0070 with 0077 it doesn't seem to change anything. | |
// | |
if(n == 0x0810 or n == 0x080F) | |
{ | |
uint16_t a[5]; | |
fake_fread(a, 2, 5); | |
if(debug) fprintf(f2, "%04X %04X %04X %04X %04X\n", a[0], a[1], a[2], a[3], a[4]); | |
if(a[0] == 0xEE67 and a[1] == 0x0836) | |
fputc('\n', f2); | |
else if(a[0] == 0xFD01 and a[1] == 0x3198) | |
{ | |
// 8171〈 | |
// 8172〉 | |
// 8173《 | |
// 8174》 | |
// 8171234 | |
bool last_char_first_surrogate = false; | |
int chars_printed = 0; | |
for(int i = 0; i < 2; i++) | |
{ | |
if(i == 0) | |
fputs("\x81\x71", f2); | |
else | |
fputs("\x81\x73", f2); | |
for(char c : internal_text[internal_text.size()-1-i]) | |
{ | |
//if(c == '\\' and !is_jis_surrogate(last_c)) | |
//{ | |
// fputc('\\', f2); | |
// fputc('\\', f2); | |
//} | |
//else | |
if(is_jis_surrogate(c) and !last_char_first_surrogate) | |
{ | |
fputc(c, f2); | |
last_char_first_surrogate = true; | |
} | |
else | |
{ | |
if(last_char_first_surrogate or (c != '\n' and c != '\r')) | |
fputc(c, f2); | |
else if(c == '\n') fprintf(f2, "\\n"); | |
else if(c == '\r') fprintf(f2, "\\r"); | |
last_char_first_surrogate = false; | |
chars_printed++; | |
} | |
} | |
if(i == 0) | |
fputs("\x81\x72", f2); | |
else | |
fputs("\x81\x74", f2); | |
} | |
internal_text.clear(); | |
} | |
if(debug) fprintf(f2, "\n"); | |
} | |
else if(n == 0x0842) | |
{ | |
uint16_t a[2]; | |
fake_fread(a, 2, 2); | |
if(debug) fprintf(f2, "%04X %04X\n", a[0], a[1]); | |
//if(a[1] == 0x0077 or a[1] == 0x006E) | |
// fputc('\n', f2); | |
if(a[1] == 0x0077 or a[1] == 0x0070 and !debug) // double newline for new page | |
fputc('\n', f2); | |
} | |
else if(n == 0x0840 or n == 0x0801) | |
{ | |
std::string temp; | |
uint16_t len; | |
fake_fread(&len, 2, 1); | |
bool last_char_first_surrogate = 0; | |
int chars_printed = 0; | |
for(int i = 0; i < len; i++) | |
{ | |
uint8_t c = fake_fgetc(); | |
if(c == 0) | |
{ } | |
else | |
{ | |
if(n == 0x0801) | |
temp += c; | |
if(n != 0x0801 or debug) | |
{ | |
if(last_char_first_surrogate or (c != '\n' and c != '\r')) | |
fputc(c, f2); | |
else if(c == '\n') fprintf(f2, "\\n"); | |
else if(c == '\r') fprintf(f2, "\\r"); | |
} | |
} | |
if(is_jis_surrogate(c) and !last_char_first_surrogate) | |
{ | |
last_char_first_surrogate = true; | |
} | |
else | |
{ | |
last_char_first_surrogate = false; | |
chars_printed++; | |
} | |
} | |
if(n == 0x0801) | |
internal_text.push_back(temp); | |
if(debug) fputs("\n", f2); | |
} | |
// ensure program counter is consistent | |
else if(n == 0x0800 or n == 0x0803) | |
{ | |
uint16_t a[2]; | |
fake_fread(a, 2, 2); | |
} | |
else if(n == 0x083A) | |
{ | |
uint16_t a[1]; | |
fake_fread(a, 2, 1); | |
} | |
else if(n == 0x0829 or n == 0x0836) | |
{ | |
uint16_t a[1]; | |
fake_fread(a, 2, 1); | |
while(a[0]-- > 0) | |
{ | |
uint8_t t; | |
fake_fread(&t, 1, 1); | |
} | |
} | |
else if(n == 0x0835 or n == 0x0834) | |
{ | |
uint16_t a[3]; | |
fake_fread(a, 2, 3); | |
} | |
else if(n == 0x01B0 or n == 0x0802) | |
{ | |
uint16_t a[4]; | |
fake_fread(a, 2, 4); | |
} | |
else if(n == 0x0841 or n == 0x083F or n == 0x082F or n == 0x082B or n == 0x0844) | |
{ | |
//uint16_t a[1]; | |
//fake_fread(a, 2, 1); | |
//if(debug) fprintf(f2, "%04X\n", a[0]); | |
} | |
else if(n == 0x082E or n == 0x082C or n == 0x0830 or n == 0x0831 or n == 0x0847 or n == 0x083B or n == 0x0832 or n == 0x083D) | |
{ | |
uint16_t a[2]; | |
fake_fread(a, 2, 2); | |
} | |
else if(n == 0x01B2) | |
{ | |
uint16_t a[4]; | |
fake_fread(a, 2, 4); | |
} | |
else if(n == 0x0130 or n == 0x0188 or n == 0x0100 | |
or n == 0x0108 or n == 0x0120 or n == 0x0118 | |
or n == 0x0158 or n == 0x0138 or n == 0x0104 | |
or n == 0x0140 or n == 0x0190 or n == 0x011A | |
or n == 0x015A or n == 0x0170 or n == 0x0148 | |
or n == 0x013A) // ??? | |
{ | |
//uint16_t a[1]; | |
//fake_fread(a, 2, 1); | |
//if(debug) fprintf(f2, "%04X\n", a[0]); | |
} | |
else | |
{ | |
puts(argv[1]); | |
printf("Unknown opcode 0x%X at 0x%X\n", n, i-2); | |
return 0; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment