Size: 4755
Comment:
|
Size: 4753
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 }