瀏覽代碼

Improved Script reader and its Unit Test

Thomas Buck 10 年之前
父節點
當前提交
7cff58d7cd
共有 9 個文件被更改,包括 142 次插入23 次删除
  1. 3
    0
      ChangeLog.md
  2. 4
    0
      include/Script.h
  3. 2
    1
      include/utils/binary.h
  4. 42
    8
      src/Script.cpp
  5. 22
    4
      src/utils/binary.cpp
  6. 1
    1
      test/CMakeLists.txt
  7. 45
    2
      test/Script.cpp
  8. 3
    7
      test/binary.cpp
  9. 20
    0
      test/test.h

+ 3
- 0
ChangeLog.md 查看文件

@@ -2,6 +2,9 @@
2 2
 
3 3
 ## OpenRaider (0.1.3) xythobuz <xythobuz@xythobuz.de>
4 4
 
5
+    [ 20140806 ]
6
+    * Improved Script reader and its Unit Test
7
+
5 8
     [ 20140804 ]
6 9
     * Added preliminary Tomb Raider Script parser
7 10
     * Moved Unit Test folder

+ 4
- 0
include/Script.h 查看文件

@@ -52,6 +52,10 @@ public:
52 52
     unsigned int pcStringCount();
53 53
     std::string getPCString(unsigned int i);
54 54
 
55
+    std::string getPuzzleString(unsigned int i, unsigned int j);
56
+    std::string getPickupString(unsigned int i, unsigned int j);
57
+    std::string getKeyString(unsigned int i, unsigned int j);
58
+
55 59
 private:
56 60
 
57 61
     void readStringPackage(BinaryFile &f, std::vector<std::string> &v, unsigned int n);

+ 2
- 1
include/utils/binary.h 查看文件

@@ -13,9 +13,10 @@
13 13
 class BinaryFile {
14 14
 public:
15 15
 
16
-    BinaryFile(const char *f);
17 16
     ~BinaryFile();
18 17
 
18
+    int open(const char *f);
19
+
19 20
     long long tell();
20 21
     void seek(long long pos);
21 22
 

+ 42
- 8
src/Script.cpp 查看文件

@@ -8,8 +8,7 @@
8 8
 #include "global.h"
9 9
 #include "Script.h"
10 10
 
11
-Script::Script() {
12
-
11
+Script::Script() : puzzles(4), pickups(2), keys(4) {
13 12
 }
14 13
 
15 14
 Script::~Script() {
@@ -17,7 +16,10 @@ Script::~Script() {
17 16
 }
18 17
 
19 18
 int Script::load(const char *file) {
20
-    BinaryFile f(file);
19
+    BinaryFile f;
20
+
21
+    if (f.open(file) != 0)
22
+        return 1;
21 23
 
22 24
     version = f.readU32();
23 25
 
@@ -74,14 +76,24 @@ int Script::load(const char *file) {
74 76
     readStringPackage(f, script, numLevels + 1);
75 77
 
76 78
     numGameStrings = f.readU16();
79
+    numGameStrings = 89; // Ignored?
80
+
77 81
     readStringPackage(f, gameStrings, numGameStrings);
78 82
 
79 83
     readStringPackage(f, pcStrings, 41);
80 84
 
81
-    //! \todo read puzzle strings
82
-    //std::vector<std::vector<std::string>> puzzles; // 4 * numLevels
83
-    //std::vector<std::vector<std::string>> pickups; // 2 * numLevels
84
-    //std::vector<std::vector<std::string>> keys; // 4 * numLevels
85
+    readStringPackage(f, puzzles[0], numLevels);
86
+    readStringPackage(f, puzzles[1], numLevels);
87
+    readStringPackage(f, puzzles[2], numLevels);
88
+    readStringPackage(f, puzzles[3], numLevels);
89
+
90
+    readStringPackage(f, pickups[0], numLevels);
91
+    readStringPackage(f, pickups[1], numLevels);
92
+
93
+    readStringPackage(f, keys[0], numLevels);
94
+    readStringPackage(f, keys[1], numLevels);
95
+    readStringPackage(f, keys[2], numLevels);
96
+    readStringPackage(f, keys[3], numLevels);
85 97
 
86 98
     return 0;
87 99
 }
@@ -94,8 +106,12 @@ void Script::readStringPackage(BinaryFile &f, std::vector<std::string> &v, unsig
94 106
     uint16_t numBytes = f.readU16();
95 107
 
96 108
     char *list = new char[numBytes];
97
-    for (uint16_t i = 0; i < numBytes; i++)
109
+    for (uint16_t i = 0; i < numBytes; i++) {
98 110
         list[i] = f.read8();
111
+        if (flags & S_UseSecurityTag) {
112
+            list[i] ^= cypherCode;
113
+        }
114
+    }
99 115
 
100 116
     for (unsigned int i = 0; i < n; i++) {
101 117
         std::string tmp(list + offset[i]);
@@ -165,3 +181,21 @@ std::string Script::getPCString(unsigned int i) {
165 181
     return pcStrings.at(i);
166 182
 }
167 183
 
184
+std::string Script::getPuzzleString(unsigned int i, unsigned int j) {
185
+    assert(i < 4);
186
+    assert(j < numLevels);
187
+    return puzzles.at(i).at(j);
188
+}
189
+
190
+std::string Script::getPickupString(unsigned int i, unsigned int j) {
191
+    assert(i < 2);
192
+    assert(j < numLevels);
193
+    return pickups.at(i).at(j);
194
+}
195
+
196
+std::string Script::getKeyString(unsigned int i, unsigned int j) {
197
+    assert(i < 4);
198
+    assert(j < numLevels);
199
+    return keys.at(i).at(j);
200
+}
201
+

+ 22
- 4
src/utils/binary.cpp 查看文件

@@ -5,25 +5,35 @@
5 5
  * \author xythobuz
6 6
  */
7 7
 
8
+#include "global.h"
8 9
 #include "utils/binary.h"
9 10
 
10
-BinaryFile::BinaryFile(const char *f) {
11
-    file.open(f, std::ios_base::in | std::ios_base::binary);
11
+BinaryFile::~BinaryFile() {
12
+    if (file.is_open())
13
+        file.close();
12 14
 }
13 15
 
14
-BinaryFile::~BinaryFile() {
15
-    file.close();
16
+int BinaryFile::open(const char *f) {
17
+    if (file.is_open()) {
18
+        return 1;
19
+    } else {
20
+        file.open(f, std::ios_base::in | std::ios_base::binary);
21
+        return (file ? 0 : 1);
22
+    }
16 23
 }
17 24
 
18 25
 long long BinaryFile::tell() {
26
+    assert(file.is_open());
19 27
     return file.tellg();
20 28
 }
21 29
 
22 30
 void BinaryFile::seek(long long pos) {
31
+    assert(file.is_open());
23 32
     file.seekg(pos);
24 33
 }
25 34
 
26 35
 uint8_t BinaryFile::readU8() {
36
+    assert(file.is_open());
27 37
     uint8_t ret;
28 38
     char *c = reinterpret_cast<char *>(&ret);
29 39
     file.read(c, 1);
@@ -31,24 +41,28 @@ uint8_t BinaryFile::readU8() {
31 41
 }
32 42
 
33 43
 uint16_t BinaryFile::readU16() {
44
+    assert(file.is_open());
34 45
     uint8_t a = readU8();
35 46
     uint8_t b = readU8();
36 47
     return ((uint16_t)a | (uint16_t)(b << 8));
37 48
 }
38 49
 
39 50
 uint32_t BinaryFile::readU32() {
51
+    assert(file.is_open());
40 52
     uint16_t a = readU16();
41 53
     uint16_t b = readU16();
42 54
     return ((uint32_t)a | (uint32_t)(b << 16));
43 55
 }
44 56
 
45 57
 uint64_t BinaryFile::readU64() {
58
+    assert(file.is_open());
46 59
     uint32_t a = readU32();
47 60
     uint32_t b = readU32();
48 61
     return ((uint64_t)a | ((uint64_t)b << 32));
49 62
 }
50 63
 
51 64
 float BinaryFile::readFloat() {
65
+    assert(file.is_open());
52 66
     uint32_t val = readU32();
53 67
     char *a = reinterpret_cast<char *>(&val);
54 68
 
@@ -82,6 +96,7 @@ namespace {
82 96
 }
83 97
 
84 98
 int8_t BinaryFile::read8() {
99
+    assert(file.is_open());
85 100
     int8_t ret;
86 101
     char *p = reinterpret_cast<char *>(&ret);
87 102
     file.read(p, sizeof(ret));
@@ -89,6 +104,7 @@ int8_t BinaryFile::read8() {
89 104
 }
90 105
 
91 106
 int16_t BinaryFile::read16() {
107
+    assert(file.is_open());
92 108
     int16_t ret;
93 109
     char *p = reinterpret_cast<char *>(&ret);
94 110
     file.read(p, sizeof(ret));
@@ -97,6 +113,7 @@ int16_t BinaryFile::read16() {
97 113
 }
98 114
 
99 115
 int32_t BinaryFile::read32() {
116
+    assert(file.is_open());
100 117
     int32_t ret;
101 118
     char *p = reinterpret_cast<char *>(&ret);
102 119
     file.read(p, sizeof(ret));
@@ -105,6 +122,7 @@ int32_t BinaryFile::read32() {
105 122
 }
106 123
 
107 124
 int64_t BinaryFile::read64() {
125
+    assert(file.is_open());
108 126
     int64_t ret;
109 127
     char *p = reinterpret_cast<char *>(&ret);
110 128
     file.read(p, sizeof(ret));

+ 1
- 1
test/CMakeLists.txt 查看文件

@@ -16,7 +16,7 @@ add_test (NAME test_binary COMMAND tester_binary)
16 16
 
17 17
 add_executable (tester_script EXCLUDE_FROM_ALL
18 18
     "Script.cpp" "../src/Script.cpp" "../src/main.cpp"
19
-    "../src/utils/binary.cpp"
19
+    "../src/utils/binary.cpp" "../src/utils/strings.cpp"
20 20
 )
21 21
 add_dependencies (check tester_script)
22 22
 add_test (NAME test_script COMMAND tester_script)

+ 45
- 2
test/Script.cpp 查看文件

@@ -1,14 +1,57 @@
1 1
 /*!
2
- * \file src/Script.cpp
3
- * \brief Game script loader
2
+ * \file test/Script.cpp
3
+ * \brief Game script loader unit test
4 4
  *
5 5
  * \author xythobuz
6 6
  */
7 7
 
8
+#include <iostream>
9
+
8 10
 #include "global.h"
11
+#include "test.h"
12
+#include "utils/strings.h"
9 13
 #include "Script.h"
10 14
 
15
+#define printStrings(cnt, acc, name) { \
16
+    std::cout << name << " (" << cnt << ")" << std::endl; \
17
+    for (unsigned int i = 0; i < cnt; i++) { \
18
+        std::cout << "    " << acc(i) << std::endl; \
19
+    } \
20
+    std::cout << std::endl; \
21
+}
22
+
23
+#define printStrings2D(c, cnt, acc, name) { \
24
+    std::cout << name << " (" << c << "*" << cnt << ")" << std::endl; \
25
+    for (unsigned int a = 0; a < cnt; a++) { \
26
+        std::cout << "    "; \
27
+        for (unsigned int i = 0; i < c; i++) { \
28
+            std::cout << acc(i, a) << " "; \
29
+        } \
30
+        std::cout << std::endl; \
31
+    } \
32
+    std::cout << std::endl; \
33
+}
34
+
11 35
 int main() {
36
+    Script s;
37
+    char *f = fullPath("~/.OpenRaider/paks/tr2/TOMBPC.DAT", 0);
38
+    assertEqual(s.load(f), 0);
39
+    delete [] f;
40
+
41
+    printStrings(s.levelCount(), s.getLevelName, "Level Names");
42
+    printStrings(s.levelCount(), s.getLevelFilename, "Level Filenames");
43
+    printStrings(s.cutsceneCount(), s.getCutsceneFilename, "Cutscenes");
44
+    printStrings(s.titleCount(), s.getTitleFilename, "Titles");
45
+    printStrings(s.videoCount(), s.getVideoFilename, "Videos");
46
+    printStrings(s.gameStringCount(), s.getGameString, "Game Strings");
47
+    printStrings(s.pcStringCount(), s.getPCString, "PC Strings");
48
+
49
+    printStrings2D(4, s.levelCount(), s.getPuzzleString, "Puzzles");
50
+    printStrings2D(2, s.levelCount(), s.getPickupString, "Pickups");
51
+    printStrings2D(4, s.levelCount(), s.getKeyString, "Keys");
52
+
53
+    //std::cout << "This test always fails so you can see its output!" << std::endl;
54
+    //return 1;
12 55
 
13 56
     return 0;
14 57
 }

+ 3
- 7
test/binary.cpp 查看文件

@@ -10,6 +10,7 @@
10 10
 #include <fstream>
11 11
 
12 12
 #include "global.h"
13
+#include "test.h"
13 14
 #include "utils/binary.h"
14 15
 
15 16
 
@@ -38,14 +39,9 @@ namespace {
38 39
         file.write(reinterpret_cast<char *>(&f2), sizeof(f2));
39 40
     }
40 41
 
41
-#define assertEqual(x, y) if (x != y) {\
42
-    std::cout << "Assertion failed:" << std::endl; \
43
-    std::cout << #x << " == " << #y << " (" << x << ", " << y << ")" << std::endl; \
44
-    return 1; \
45
-}
46
-
47 42
     int test(const char *name) {
48
-        BinaryFile file(name);
43
+        BinaryFile file;
44
+        assertEqual(file.open(name), 0);
49 45
 
50 46
         assertEqual(file.readU8(), 255);
51 47
         assertEqual(file.readU16(), 65535);

+ 20
- 0
test/test.h 查看文件

@@ -0,0 +1,20 @@
1
+/*!
2
+ * \file test/test.h
3
+ * \brief Common Unit Test helpers
4
+ *
5
+ * \author xythobuz
6
+ */
7
+
8
+#ifndef _TEST_H
9
+#define _TEST_H
10
+
11
+#include <iostream>
12
+
13
+#define assertEqual(x, y) if (x != y) { \
14
+    std::cout << "Assertion failed:" << std::endl; \
15
+    std::cout << #x << " == " << #y << " (" << x << ", " << y << ")" << std::endl; \
16
+    return 1; \
17
+}
18
+
19
+#endif
20
+

Loading…
取消
儲存