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.1KB

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