Browse Source

Can read TR3 Script

Thomas Buck 10 years ago
parent
commit
a3adea1549
4 changed files with 76 additions and 49 deletions
  1. 1
    0
      ChangeLog.md
  2. 6
    4
      include/Script.h
  3. 62
    45
      src/Script.cpp
  4. 7
    0
      test/Script.cpp

+ 1
- 0
ChangeLog.md View File

4
 
4
 
5
     [ 20140807 ]
5
     [ 20140807 ]
6
     * Script parser successfully loading level scripts
6
     * Script parser successfully loading level scripts
7
+    * Can also read TR3 script now
7
 
8
 
8
     [ 20140806 ]
9
     [ 20140806 ]
9
     * Improved Script reader and its Unit Test
10
     * Improved Script reader and its Unit Test

+ 6
- 4
include/Script.h View File

30
     } ScriptLanguage;
30
     } ScriptLanguage;
31
 
31
 
32
     typedef enum {
32
     typedef enum {
33
-        OP_PICTURE        = 0,  //!< Unused in TR2. Or PSX?
33
+        OP_PICTURE        = 0,  //!< Unused in TR2. Or PSX? Used in TR3.
34
         OP_PSX_TRACK      = 1,  //!< Does not compile. PSX?
34
         OP_PSX_TRACK      = 1,  //!< Does not compile. PSX?
35
         OP_PSX_FMV        = 2,  //!< Does not compile. PSX?
35
         OP_PSX_FMV        = 2,  //!< Does not compile. PSX?
36
         OP_FMV            = 3,  //!< Display FMV
36
         OP_FMV            = 3,  //!< Display FMV
42
         OP_END            = 9,  //!< Closes script sequence
42
         OP_END            = 9,  //!< Closes script sequence
43
         OP_TRACK          = 10, //!< Play soundtrack (precedes level opcode)
43
         OP_TRACK          = 10, //!< Play soundtrack (precedes level opcode)
44
         OP_SUNSET         = 11, //!< Unknown, nothing changes in TR2.
44
         OP_SUNSET         = 11, //!< Unknown, nothing changes in TR2.
45
-        OP_LOAD_PIC       = 12, //!< Does not compile. PSX or TR3?
45
+        OP_LOAD_PIC       = 12, //!< Does not compile. PSX? Used in TR3.
46
         OP_DEADLY_WATER   = 13, //!< Unknown, nothing changes in TR2.
46
         OP_DEADLY_WATER   = 13, //!< Unknown, nothing changes in TR2.
47
         OP_REMOVE_WEAPONS = 14, //!< Start level without weapons
47
         OP_REMOVE_WEAPONS = 14, //!< Start level without weapons
48
-        OP_GAMECOMPLETE   = 15, //!< End of game. Show stats, start credits sequence, music ID 52.
48
+        OP_GAMECOMPLETE   = 15, //!< End of game. Show stats, start credits sequence, music ID 52 in TR2.
49
         OP_CUTANGLE       = 16, //!< Match N-S orientation of Room and animated characters.
49
         OP_CUTANGLE       = 16, //!< Match N-S orientation of Room and animated characters.
50
         OP_NOFLOOR        = 17, //!< Lara dies when her feet reach given depth.
50
         OP_NOFLOOR        = 17, //!< Lara dies when her feet reach given depth.
51
         OP_STARTINV       = 18, //!< Items given to Lara at level start (+1000), or at all secrets found (+0)
51
         OP_STARTINV       = 18, //!< Items given to Lara at level start (+1000), or at all secrets found (+0)
58
 
58
 
59
     // Items for all-secrets-found go from 0 to 26,
59
     // Items for all-secrets-found go from 0 to 26,
60
     // for start-inventory add 1000, so 1000 - 1026
60
     // for start-inventory add 1000, so 1000 - 1026
61
+    // Atleast in TR2
61
     typedef enum {
62
     typedef enum {
62
         OP_WEAPON_PISTOLS     = 0,  //!< Add standard pistols (2)
63
         OP_WEAPON_PISTOLS     = 0,  //!< Add standard pistols (2)
63
         OP_WEAPON_SHOTGUN     = 1,  //!< Add shotgun (1)
64
         OP_WEAPON_SHOTGUN     = 1,  //!< Add shotgun (1)
138
     } ScriptFlag;
139
     } ScriptFlag;
139
 
140
 
140
     void readStringPackage(BinaryFile &f, std::vector<std::string> &v, unsigned int n);
141
     void readStringPackage(BinaryFile &f, std::vector<std::string> &v, unsigned int n);
142
+    void readScriptPackage(BinaryFile &f, std::vector<std::vector<uint16_t>> &v, unsigned int n);
141
 
143
 
142
     const bool opcodeHasOperand[OP_UNKNOWN] {
144
     const bool opcodeHasOperand[OP_UNKNOWN] {
143
         true, true, true, true, true, true,
145
         true, true, true, true, true, true,
180
     std::vector<std::string> cutsceneFilenames; // numCutscenes
182
     std::vector<std::string> cutsceneFilenames; // numCutscenes
181
     std::vector<std::vector<uint16_t>> script; // numLevels + 1
183
     std::vector<std::vector<uint16_t>> script; // numLevels + 1
182
     uint16_t numGameStrings;
184
     uint16_t numGameStrings;
183
-    std::vector<std::string> gameStrings; // numGameStrings, 89
185
+    std::vector<std::string> gameStrings; // numGameStrings
184
     std::vector<std::string> pcStrings; // 41
186
     std::vector<std::string> pcStrings; // 41
185
     std::vector<std::vector<std::string>> puzzles; // 4 * numLevels
187
     std::vector<std::vector<std::string>> puzzles; // 4 * numLevels
186
     std::vector<std::vector<std::string>> pickups; // 2 * numLevels
188
     std::vector<std::vector<std::string>> pickups; // 2 * numLevels

+ 62
- 45
src/Script.cpp View File

35
     titleReplace = f.read32();
35
     titleReplace = f.read32();
36
     onDeathDemoMode = f.readU32();
36
     onDeathDemoMode = f.readU32();
37
     onDeathInGame = f.readU32();
37
     onDeathInGame = f.readU32();
38
-    noInputTime = f.readU32();
38
+    noInputTime = f.readU32(); // Scaled *100 in TR3
39
     onDemoInterrupt = f.readU32();
39
     onDemoInterrupt = f.readU32();
40
     onDemoEnd = f.readU32();
40
     onDemoEnd = f.readU32();
41
 
41
 
61
 
61
 
62
     cypherCode = f.readU8();
62
     cypherCode = f.readU8();
63
     language = f.readU8();
63
     language = f.readU8();
64
-    secretTrack = f.readU16();
64
+    secretTrack = f.readU16(); // Zero in TR3, Part of filler or real number?
65
 
65
 
66
     // Filler 4 (4 bytes)
66
     // Filler 4 (4 bytes)
67
     f.seek(f.tell() + 4);
67
     f.seek(f.tell() + 4);
74
     readStringPackage(f, levelFilenames, numLevels);
74
     readStringPackage(f, levelFilenames, numLevels);
75
     readStringPackage(f, cutsceneFilenames, numCutscenes);
75
     readStringPackage(f, cutsceneFilenames, numCutscenes);
76
 
76
 
77
-    // Script Package
78
-    uint16_t *offset = new uint16_t[numLevels + 1];
79
-    for (unsigned int i = 0; i < (numLevels + 1); i++) {
80
-        offset[i] = f.readU16();
81
-        assertEqual(offset[i] % 2, 0);
82
-    }
83
-
84
-    uint16_t numBytes = f.readU16() + 6; // Offset TR2 specific?!
85
-    assertEqual(numBytes % 2, 0); // 16 bit opcodes and operands
86
-
87
-    uint16_t *list = new uint16_t[numBytes / 2];
88
-    for (uint16_t i = 0; i < (numBytes / 2); i++) {
89
-        list[i] = f.readU16();
90
-    }
91
-
92
-    for (unsigned int i = 0; i < (numLevels + 1); i++) {
93
-        unsigned int end = offset[i] / 2;
94
-
95
-        bool readingOperand = false;
96
-        while (readingOperand || (list[end] != OP_END)) {
97
-            if (readingOperand) {
98
-                readingOperand = false;
99
-                end++;
100
-            } else {
101
-                if (opcodeHasOperand[list[end]]) {
102
-                    readingOperand = true;
103
-                }
104
-                end++;
105
-            }
106
-        }
107
-        end++;
77
+    // Level Scripts
78
+    readScriptPackage(f, script, numLevels + 1);
108
 
79
 
109
-        std::vector<uint16_t> tmp;
110
-        for (unsigned int a = (offset[i] / 2); a < end; a++)
111
-            tmp.push_back(list[a]);
112
-
113
-        script.push_back(tmp);
114
-    }
115
-
116
-    delete [] list;
117
-    delete [] offset;
118
-
119
-    // Engine expects 89 game strings!
120
     numGameStrings = f.readU16();
80
     numGameStrings = f.readU16();
121
-    assertEqual(numGameStrings, 89);
122
 
81
 
123
     // More strings...
82
     // More strings...
124
     readStringPackage(f, gameStrings, numGameStrings);
83
     readStringPackage(f, gameStrings, numGameStrings);
161
     delete [] offset;
120
     delete [] offset;
162
 }
121
 }
163
 
122
 
123
+void Script::readScriptPackage(BinaryFile &f, std::vector<std::vector<uint16_t>> &v, unsigned int n) {
124
+    uint16_t *offset = new uint16_t[n];
125
+    for (unsigned int i = 0; i < n; i++) {
126
+        offset[i] = f.readU16();
127
+        assertEqual(offset[i] % 2, 0);
128
+    }
129
+
130
+    uint16_t numBytes = f.readU16();
131
+    assertEqual(numBytes % 2, 0); // 16 bit opcodes and operands
132
+
133
+    // Only TR2, not TR3, has 6 "filler bytes" hex 13 00 14 00 15 00 here
134
+    // We need to skip these
135
+    uint16_t hack1 = f.readU16();
136
+    uint16_t hack2 = f.readU16();
137
+    uint16_t hack3 = f.readU16();
138
+    uint16_t hackStart = 0;
139
+    uint16_t *list = new uint16_t[(numBytes + 6) / 2];
140
+    if ((hack1 == 19) && (hack2 == 20) && (hack3 == 21)) {
141
+        numBytes += 6;
142
+    } else {
143
+        list[0] = hack1;
144
+        list[1] = hack2;
145
+        list[2] = hack3;
146
+        hackStart = 3;
147
+    }
148
+
149
+    for (uint16_t i = hackStart; i < (numBytes / 2); i++) {
150
+        list[i] = f.readU16();
151
+    }
152
+
153
+    for (unsigned int i = 0; i < n; i++) {
154
+        unsigned int end = offset[i] / 2;
155
+
156
+        bool readingOperand = false;
157
+        while (readingOperand || (list[end] != OP_END)) {
158
+            if (readingOperand) {
159
+                readingOperand = false;
160
+                end++;
161
+            } else {
162
+                if (opcodeHasOperand[list[end]]) {
163
+                    readingOperand = true;
164
+                }
165
+                end++;
166
+            }
167
+        }
168
+        end++;
169
+
170
+        std::vector<uint16_t> tmp;
171
+        for (unsigned int a = (offset[i] / 2); a < end; a++)
172
+            tmp.push_back(list[a]);
173
+
174
+        v.push_back(tmp);
175
+    }
176
+
177
+    delete [] list;
178
+    delete [] offset;
179
+}
180
+
164
 unsigned int Script::levelCount() {
181
 unsigned int Script::levelCount() {
165
     return numLevels;
182
     return numLevels;
166
 }
183
 }

+ 7
- 0
test/Script.cpp View File

106
     int error = test(f, !((argc > 1) && (argv[1][0] == 's')));
106
     int error = test(f, !((argc > 1) && (argv[1][0] == 's')));
107
     delete [] f;
107
     delete [] f;
108
 
108
 
109
+    if (error != 0)
110
+        return error;
111
+
112
+    f = fullPath("~/.OpenRaider/paks/tr3/TOMBPC.DAT", 0);
113
+    error = test(f, !((argc > 1) && (argv[1][0] == 's')));
114
+    delete [] f;
115
+
109
     return error;
116
     return error;
110
 }
117
 }
111
 
118
 

Loading…
Cancel
Save