Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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. }