Size: 4755
Comment:
|
Size: 4953
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 3: | Line 3: |
{{{#!highlighter c++ | 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. {{{#!highlight c++ |
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 }