Differences between revisions 2 and 3
Revision 2 as of 2017-09-29 06:51:35
Size: 4755
Editor: weh
Comment:
Revision 3 as of 2017-09-29 06:52:03
Size: 4753
Editor: weh
Comment:
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
{{{#!highlighter cpp {{{#!highlight c++

.sob files, 32-bit word bytecode packed with a lookup table in the header and a string table at the end. I have NO IDEA what the VN engine actually does to execute its logic, only how to get the text out of the scripts, and I'm not 100% certain it's correct, it just seems to work properly.

   1 #include <stdio.h>
   2 #include <stdlib.h>
   3 #include <stdint.h>
   4 #include <string.h>
   5 
   6 #include <map>
   7 #include <vector>
   8 
   9 std::vector<std::map<uint32_t, uint32_t>> maps;
  10 
  11 std::map<uint32_t, std::string> examples;
  12 
  13 int main(int argc, char ** argv)
  14 {
  15     int strings = 0;
  16     for(int i = 0; i < argc; i++)
  17     {
  18         maps.clear();
  19         
  20         auto f = fopen(argv[i], "rb");
  21         if(!f) continue;
  22         char magic[4];
  23         int n = fread(magic, 1, 4, f);
  24         if(n != 4 or strncmp(magic, "SOB0", 4) != 0) continue;
  25         uint32_t table_size;
  26         fread(&table_size, 4, 1, f);
  27         uint32_t table_end = table_size + 0x8;
  28         int header_count = 0;
  29         while(ftell(f) < table_end)
  30         {
  31             //printf("Header at %08X\n", ftell(f));
  32             uint32_t word_pairs;
  33             fread(&word_pairs, 4, 1, f);
  34             std::map<uint32_t, uint32_t> newmap;
  35             for(int i = 0; i < word_pairs; i++)
  36             {
  37                 uint32_t key;
  38                 uint32_t value;
  39                 fread(&key, 4, 1, f);
  40                 fread(&value, 4, 1, f);
  41                 newmap[key] = value;
  42             }
  43             maps.push_back(newmap);
  44             header_count += 1;
  45         }
  46         if(maps.size() < 5)
  47         {
  48             puts("not enough maps");
  49             exit(0);
  50         }
  51         fseek(f, table_end, SEEK_SET);
  52         uint32_t strings_start;
  53         uint32_t strings_end;
  54         fread(&strings_start, 4, 1, f);
  55         fread(&strings_end, 4, 1, f);
  56         uint32_t header_end = ftell(f);
  57         //printf("String range: %08X~%08X\n", strings_start, strings_end);
  58         
  59         // can't tell if text is content text until a command tries to use it? I think?
  60         std::string text_memory;
  61         
  62         bool justdidtext = false;
  63         
  64         // no idea if commands have proper inline arguments in this bytecode lol
  65         while(ftell(f) < strings_start)
  66         {
  67             uint32_t address = ftell(f)-header_end;
  68             uint32_t command;
  69             fread(&command, 4, 1, f);
  70             if((command & 0xFFF00000) == 0x01800000)
  71             {
  72                 if(maps[4].count(address) and maps[4][address] >= strings_start and maps[4][address] < strings_end)
  73                 {
  74                     //printf("Found command that uses string: ");
  75                     //printf("%08X: %08X (%08X) / ", address, command, maps[4][address], argv[i]);
  76                     //printf("|%08X|:(|%08X|) [%s]\n", address+header_end, maps[4][address]+header_end, argv[i]);
  77                     strings++;
  78                     fseek(f, maps[4][address]+header_end, SEEK_SET);
  79                     int c = fgetc(f);
  80                     
  81                     if(c == 0) // 00 XX XX <string
  82                         fseek(f, 2, SEEK_CUR);
  83                     else // <string>
  84                         fseek(f, -1, SEEK_CUR);
  85                     
  86                     auto start = ftell(f);
  87                     while((c = fgetc(f)) != 0);
  88                     auto end = ftell(f);
  89                     char * text = (char *)malloc(end-start);
  90                     fseek(f, start, SEEK_SET);
  91                     fread(text, 1, end-start, f);
  92                     std::string str = std::string(text);
  93                     if(!examples.count(command))
  94                         examples[command] = str;
  95                     
  96                     //if(str != "")
  97                     //    printf("%08X text %s\n", command, text);
  98                         //printf("%08X: %08X %s\n", address+header_end, command, text);
  99                     
 100                     text_memory = text;
 101                     
 102                     free(text);
 103                     justdidtext = true;
 104                 }
 105             }
 106             else
 107             {
 108                 //printf("%08X\n", command);
 109                 
 110                 // I have NO CERTAINTY that this is correct
 111                 if(command == 0x000001C8 and text_memory != "")
 112                     puts(text_memory.data());
 113                 
 114                 justdidtext = false;
 115             }
 116             fseek(f, address+header_end+4, SEEK_SET);
 117         }
 118         
 119         fclose(f);
 120     }
 121     //printf("Total strings: %d\n", strings);
 122     //for(auto &[k, v] : examples)
 123     //{
 124     //    printf("%08X: %s\n", k, v.data());
 125     //}
 126 }

Lucifen Library (last edited 2017-10-01 11:21:51 by weh)