Differences between revisions 3 and 4
Revision 3 as of 2017-09-29 06:52:03
Size: 4753
Editor: weh
Comment:
Revision 4 as of 2017-09-30 01:27:48
Size: 4953
Editor: weh
Comment:
Deletions are marked like this. Additions are marked like this.
Line 2: Line 2:

Oretsuba Prelude and Oretsuba seem to trigger dialogue text with different commands (0x000001C8 vs 0x000001CF). I'm not certain that this is correct, but it seems to work.
Line 114: Line 116:
                if(command == 0x000001C8 and text_memory != "")                 if(command == 0x000001C8 or command == 0x000001CF and text_memory != "")

.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.

Oretsuba Prelude and Oretsuba seem to trigger dialogue text with different commands (0x000001C8 vs 0x000001CF). I'm not certain that this is correct, but it seems to work.

   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 or command == 0x000001CF 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)