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.

   1 //「日本語 This file is shift‐jis. I’m sorry, but there’s a reason.」
   2 // This file is shift-jis. I'm sorry, but there's a reason.
   3 // IF THIS FILE IS NOT ENCODED AS SHIFT-JIS, HIRAGANA WILL NOT DUMP CORRECTLY.
   4 
   5 // Dumper for Nanairo Reincarnation's script and maybe others
   6 
   7 #include <stdlib.h>
   8 #include <stdint.h>
   9 #include <stdio.h>
  10 
  11 // For some reason, they use compressed hiragana encodings.
  12 // Not only does this make it impossible to encode ascii text, it's batshit crazy.
  13 const char * array[] = {
  14 /*      X0      X1      X2      X3      X4      X5      X6      X7      X8      X9      XA      XB      XC      XD      XE      XF*/
  15 /*0X*/  "",     "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    
  16 /*1X*/  "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    
  17 /*2X*/  "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    
  18 /*3X*/  "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    
  19 /*4X*/  "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    "",    
  20 /*5X*/  "",    "",    "",    "",    "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     
  21 /*6X*/  "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     
  22 /*7X*/  "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",
  23 /*8X*/  "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",
  24 /*9X*/  "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",
  25 /*AX*/  "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",
  26 /*BX*/  "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",
  27 /*CX*/  "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",
  28 /*DX*/  "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",
  29 /*EX*/  "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",
  30 /*FX*/  "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     "",     ""
  31 };
  32 
  33 bool is_jis_surrogate(uint8_t c)
  34 {
  35     if(c >= 0x80 and c <= 0xA0) return true;
  36     if(c >= 0xE0) return true;
  37     return false;
  38 }
  39 
  40 void output(int c)
  41 {
  42     putc(c, stdout);
  43 }
  44 
  45 int main(int argc, char ** argv)
  46 {
  47     // feed .MES files
  48     for(int i = 1; i < argc; i++)
  49     {
  50         auto f = fopen(argv[i], "rb");
  51         
  52         if(!f) return puts("failed to open"), 0;
  53         
  54         uint32_t numlines;
  55         fread(&numlines, 4, 1, f);
  56         
  57         uint32_t defines;
  58         fread(&defines, 4, 1, f);
  59         
  60         fseek(f, 4*defines, SEEK_CUR);
  61         
  62         uint32_t startpoint = numlines*4 + defines*4 + 8;
  63         
  64         // documentation as code, not used
  65         // address of where to go for various save indexes?
  66         uint32_t * lineaddrs = (uint32_t *)malloc(sizeof(uint32_t)*numlines);
  67         fread(lineaddrs, 4, numlines, f);
  68         
  69         int c = 0;
  70         while(1)
  71         {
  72             c = fgetc(f);
  73             if(c < 0) break;
  74             
  75             // Opcode handling to stay in sync. Not proper reverse engineering, 95% guesswork.
  76             if(c != 0x0A)
  77             {
  78                 switch(c)
  79                 {
  80                 case 0x32: // some kind of load command - variable width?
  81                 case 0x1B: // some kind of jump?
  82                 case 0x14: // some kind of jump?
  83                 case 0x15: // some kind of jump?
  84                 case 0x1A:
  85                     fseek(f, 4, SEEK_CUR);
  86                     continue;
  87                 case 0x19: // related to text, seems to work to interpret it as a page marker
  88                     fseek(f, 4, SEEK_CUR);
  89                     printf("\n");
  90                     continue;
  91                 case 0x18:
  92                 case 0x04:
  93                 case 0x0F:
  94                 case 0x0E:
  95                 case 0x0D:
  96                 case 0x05:
  97                 case 0x3C:
  98                 case 0x42:
  99                 case 0x43:
 100                 case 0x34:
 101                 case 0x17:
 102                 case 0x3A:
 103                 case 0x00: // ????????????????????
 104                 case 0x0C:
 105                 case 0x02:
 106                 case 0x11:
 107                 case 0x3F:
 108                 case 0x41:
 109                 case 0x3B:
 110                 case 0x35:
 111                     continue;
 112                 case 0x1C: // between lines in multi-line messages; line wrap?
 113                     //printf(" ");
 114                     continue;
 115                 case 0x36:
 116                     c = fgetc(f);
 117                     if(c != 0x3D)
 118                     {
 119                         printf("Unexpected pattern byte %02X after 36 at %08X\n", uint8_t(c), ftell(f)-2);
 120                         exit(0);
 121                     }
 122                     continue;
 123                 case 0x33: // e.g. op33: 6E 6E 5F 68 30 30 30 30 2E 6F 67 67 "0x33: nn_h0000.ogg"
 124                     while((c = fgetc(f)) != 0);
 125                     continue;
 126                 }
 127                 if(c < 0)
 128                     continue;
 129                 
 130                 printf("Unknown command %02X at %08X in %s\n", uint8_t(c), ftell(f)-1, argv[i]);
 131                 printf("Next byte is %02X\n", fgetc(f));
 132                 exit(0);
 133             }
 134             // fall-through case command 0x0A: display text
 135             c = fgetc(f);
 136             while(c != 0)
 137             {
 138                 if(is_jis_surrogate(c))
 139                 {
 140                     output(c);
 141                     c = fgetc(f);
 142                     if(c == 0) break;
 143                     output(c);
 144                 }
 145                 else
 146                 {
 147                     if(*(array[c]) == 0)
 148                     {
 149                         printf("Unknown encoded character %02X at %08X\n", uint8_t(c), ftell(f)-1);
 150                         exit(0);
 151                     }
 152                     else if(*(array[c]) != 1)
 153                         printf(array[c]);
 154                 }
 155                 c = fgetc(f);
 156             }
 157         }
 158         free(lineaddrs);
 159         fclose(f);
 160     }
 161 }

Silky (last edited 2017-08-26 23:56:28 by weh)