Open Source Tomb Raider Engine
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

Script.cpp 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*!
  2. * \file test/Script.cpp
  3. * \brief Game script loader unit test
  4. *
  5. * \author xythobuz
  6. */
  7. #include <iostream>
  8. #include <cstdlib>
  9. #include <cstring>
  10. #include <zlib.h>
  11. #include "global.h"
  12. #include "Script.h"
  13. #include "ScriptTest.h"
  14. #define printStrings(cnt, acc, name) { \
  15. std::cout << name << " (" << cnt << ")" << std::endl; \
  16. for (unsigned int i = 0; i < cnt; i++) { \
  17. std::cout << " " << acc(i) << std::endl; \
  18. } \
  19. std::cout << std::endl; \
  20. }
  21. #define printStrings2D(c, cnt, acc, name) { \
  22. std::cout << name << " (" << c << "*" << cnt << ")" << std::endl; \
  23. for (unsigned int a = 0; a < cnt; a++) { \
  24. std::cout << " "; \
  25. for (unsigned int i = 0; i < c; i++) { \
  26. std::cout << acc(i, a); \
  27. if (i < (c - 1)) \
  28. std::cout << " | "; \
  29. } \
  30. std::cout << std::endl; \
  31. } \
  32. std::cout << std::endl; \
  33. }
  34. #define registerLambda(x, y) { \
  35. s.registerScriptHandler(x, [](bool hasOperand, uint16_t operand) { \
  36. std::cout << "\t" << y; \
  37. if (hasOperand) \
  38. std::cout << " (" << operand << ")"; \
  39. std::cout << std::endl; \
  40. return 0; \
  41. }); \
  42. }
  43. namespace {
  44. int printDataScript(Script& s, bool strings) {
  45. if (strings) {
  46. printStrings(s.levelCount(), s.getLevelName, "Level Names");
  47. printStrings(s.levelCount(), s.getLevelFilename, "Level Filenames");
  48. printStrings(s.pictureCount(), s.getPictureFilename, "Picture Filenames");
  49. printStrings(s.cutsceneCount(), s.getCutsceneFilename, "Cutscenes");
  50. printStrings(s.titleCount(), s.getTitleFilename, "Titles");
  51. printStrings(s.videoCount(), s.getVideoFilename, "Videos");
  52. printStrings(s.gameStringCount(), s.getGameString, "Game Strings");
  53. printStrings(s.pcStringCount(), s.getPCString, "PC Strings");
  54. printStrings2D(4, s.levelCount(), s.getPuzzleString, "Puzzles");
  55. printStrings2D(2, s.levelCount(), s.getPickupString, "Pickups");
  56. printStrings2D(4, s.levelCount(), s.getKeyString, "Keys");
  57. } else {
  58. registerLambda(Script::OP_PICTURE, "Picture");
  59. registerLambda(Script::OP_PSX_TRACK, "PSX-Track");
  60. registerLambda(Script::OP_PSX_FMV, "PSX-FMV");
  61. registerLambda(Script::OP_FMV, "Show FMV");
  62. registerLambda(Script::OP_GAME, "Load level");
  63. registerLambda(Script::OP_CUT, "Cutscene");
  64. registerLambda(Script::OP_COMPLETE, "Level finished");
  65. registerLambda(Script::OP_DEMO, "Demo sequence");
  66. registerLambda(Script::OP_PSX_DEMO, "PSX-Demo");
  67. registerLambda(Script::OP_END, "End of script");
  68. registerLambda(Script::OP_TRACK, "Sound Track");
  69. registerLambda(Script::OP_SUNSET, "Sunset");
  70. registerLambda(Script::OP_LOAD_PIC, "Load picture");
  71. registerLambda(Script::OP_DEADLY_WATER, "Deadly water");
  72. registerLambda(Script::OP_REMOVE_WEAPONS, "Remove weapons");
  73. registerLambda(Script::OP_GAMECOMPLETE, "End of game!");
  74. registerLambda(Script::OP_CUTANGLE, "Cutscene angle");
  75. registerLambda(Script::OP_NOFLOOR, "No floor, fall death");
  76. registerLambda(Script::OP_STARTINV, "Inventory/Bonus");
  77. registerLambda(Script::OP_STARTANIM, "Start animation");
  78. registerLambda(Script::OP_SECRETS, "Secrets");
  79. registerLambda(Script::OP_KILLTOCOMPLETE, "Kill to complete level");
  80. registerLambda(Script::OP_REMOVE_AMMO, "Remove ammo");
  81. for (unsigned int i = 0; i < (s.levelCount() + 1); i++) {
  82. if (i == 0)
  83. std::cout << "Script for Title:" << std::endl;
  84. else
  85. std::cout << "Script for \"" << s.getLevelName(i - 1) << "\" (" << i - 1 << "):" << std::endl;
  86. int error = s.runScript(i);
  87. if (error != 0) {
  88. std::cout << "Returned " << error << "..." << std::endl;
  89. return error;
  90. }
  91. std::cout << std::endl;
  92. }
  93. }
  94. return 0;
  95. }
  96. int test(const char* file, unsigned int n) {
  97. Script s;
  98. std::cout << "Testing " << testDescription[n] << std::endl;
  99. if (s.load(file) != 0) {
  100. std::cout << "Could not open file " << file << std::endl;
  101. return 1;
  102. }
  103. if (s.gameStringCount() != testExpectedGameStringCount[n]) {
  104. std::cout << "Game String Count " << s.gameStringCount() << " != " << testExpectedGameStringCount[n]
  105. << std::endl;
  106. return 2;
  107. }
  108. if (s.pcStringCount() != testExpectedPlatformStringCount[n]) {
  109. std::cout << "Platform String Count " << s.pcStringCount() << " != " <<
  110. testExpectedPlatformStringCount[n] << std::endl;
  111. return 3;
  112. }
  113. std::cout << "Success!" << std::endl << std::endl;
  114. return 0;
  115. }
  116. int readPayloadChunk(const unsigned char* data, unsigned int size, const char* file) {
  117. static const unsigned int bufferSize = 16384; // 16K should be enough for everybody :)
  118. unsigned char buffer[bufferSize];
  119. // Initialize decompression
  120. z_stream stream;
  121. stream.zalloc = Z_NULL;
  122. stream.zfree = Z_NULL;
  123. stream.opaque = Z_NULL;
  124. int error = inflateInit(&stream);
  125. if (error != Z_OK) {
  126. std::cout << "inflateInit() Error " << error << std::endl;
  127. return 1;
  128. }
  129. // Inflate data in one go
  130. stream.avail_in = size;
  131. stream.next_in = const_cast<unsigned char*>(data);
  132. stream.avail_out = bufferSize;
  133. stream.next_out = buffer;
  134. error = inflate(&stream, Z_FINISH);
  135. if (error != Z_STREAM_END) {
  136. std::cout << "inflate() Error " << error << std::endl;
  137. return 2;
  138. }
  139. inflateEnd(&stream);
  140. // Write buffer to file
  141. std::ofstream s(file, std::ios_base::out | std::ios_base::binary);
  142. s.write(reinterpret_cast<const char*>(buffer), bufferSize - stream.avail_out);
  143. return 0;
  144. }
  145. int runForPayload(unsigned int n, bool print, bool printData) {
  146. assert(n < testPayloadCount);
  147. // Get temp file name
  148. char tmpFile[] = "/tmp/openraider_unit_test_0";
  149. FILE* f;
  150. while ((f = fopen(tmpFile, "r")) != NULL) {
  151. fclose(f);
  152. tmpFile[26]++;
  153. }
  154. std::cout << "Temporary test file: " << tmpFile << std::endl;
  155. int error = readPayloadChunk(testPayloads[n], testSizes[n], tmpFile);
  156. if (error == 0) {
  157. if (print) {
  158. Script s;
  159. error = s.load(tmpFile);
  160. if (error == 0)
  161. error = printDataScript(s, printData);
  162. else
  163. std::cout << "Error loading script!" << std::endl;
  164. } else {
  165. error = test(tmpFile, n);
  166. }
  167. }
  168. remove(tmpFile);
  169. return error;
  170. }
  171. }
  172. int main(int argc, char* argv[]) {
  173. bool printHelp = false;
  174. bool print = false;
  175. bool printData = true;
  176. int whichFile = -1;
  177. if (argc == 3) {
  178. if ((strcmp(argv[1], "--printData") == 0)
  179. || (strcmp(argv[1], "--printScript") == 0)) {
  180. print = true;
  181. if (strcmp(argv[1], "--printScript") == 0) {
  182. printData = false;
  183. }
  184. assert(testPayloadCount < 10);
  185. if ((argv[2][0] >= '0')
  186. && (static_cast<unsigned int>(argv[2][0]) <= (testPayloadCount + '0'))) {
  187. whichFile = argv[2][0] - '0';
  188. }
  189. } else {
  190. printHelp = true;
  191. }
  192. } else if (argc != 1) {
  193. printHelp = true;
  194. }
  195. if (printHelp) {
  196. std::cout << "Usage:" << std::endl;
  197. std::cout << "\t" << argv[0] << " [--printData | --printScript] [N | /path]" << std::endl;
  198. return 1;
  199. }
  200. if (print) {
  201. // Print single script
  202. if (whichFile == -1) {
  203. // From given path
  204. Script s;
  205. assertEqual(s.load(argv[2]), 0);
  206. return printDataScript(s, printData);
  207. } else {
  208. // From payload
  209. return runForPayload(static_cast<unsigned int>(whichFile), true, printData);
  210. }
  211. } else {
  212. // Run test on all scripts in payload
  213. for (unsigned int i = 0; i < testPayloadCount; i++) {
  214. int error = runForPayload(i, false, false);
  215. if (error != 0)
  216. return error;
  217. }
  218. return 0;
  219. }
  220. }