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

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