Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Script.cpp 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*!
  2. * \file src/Script.cpp
  3. * \brief Game script loader
  4. *
  5. * \author xythobuz
  6. */
  7. #include "global.h"
  8. #include "Script.h"
  9. Script::Script() : puzzles(4), pickups(2), keys(4) {
  10. }
  11. Script::~Script() {
  12. }
  13. int Script::load(const char *file) {
  14. BinaryFile f;
  15. if (f.open(file) != 0)
  16. return 1;
  17. version = f.readU32();
  18. char desc[256];
  19. for (int i = 0; i < 256; i++)
  20. desc[i] = f.read8();
  21. description = desc;
  22. uint16_t gameflowSize = f.readU16();
  23. assertEqual(gameflowSize, 128);
  24. firstOption = f.readU32();
  25. titleReplace = f.read32();
  26. onDeathDemoMode = f.readU32();
  27. onDeathInGame = f.readU32();
  28. noInputTime = f.readU32();
  29. onDemoInterrupt = f.readU32();
  30. onDemoEnd = f.readU32();
  31. // Filler 1 (36 bytes)
  32. f.seek(f.tell() + 36);
  33. numLevels = f.readU16();
  34. numPictures = f.readU16();
  35. numTitles = f.readU16();
  36. numFMVs = f.readU16();
  37. numCutscenes = f.readU16();
  38. numDemos = f.readU16();
  39. titleTrack = f.readU16();
  40. singleLevel = f.read16();
  41. // Filler 2 (32 bytes)
  42. f.seek(f.tell() + 32);
  43. flags = f.readU16();
  44. // Filler 3 (6 bytes)
  45. f.seek(f.tell() + 6);
  46. cypherCode = f.readU8();
  47. language = f.readU8();
  48. secretTrack = f.readU16();
  49. // Filler 4 (4 bytes)
  50. f.seek(f.tell() + 4);
  51. // Strings
  52. readStringPackage(f, levelNames, numLevels);
  53. readStringPackage(f, pictureFilenames, numPictures);
  54. readStringPackage(f, titleFilenames, numTitles);
  55. readStringPackage(f, fmvFilenames, numFMVs);
  56. readStringPackage(f, levelFilenames, numLevels);
  57. readStringPackage(f, cutsceneFilenames, numCutscenes);
  58. // Script Package
  59. uint16_t *offset = new uint16_t[numLevels + 1];
  60. for (unsigned int i = 0; i < (numLevels + 1); i++) {
  61. offset[i] = f.readU16();
  62. assertEqual(offset[i] % 2, 0);
  63. }
  64. uint16_t numBytes = f.readU16() + 6; // Offset TR2 specific?!
  65. assertEqual(numBytes % 2, 0); // 16 bit opcodes and operands
  66. uint16_t *list = new uint16_t[numBytes / 2];
  67. for (uint16_t i = 0; i < (numBytes / 2); i++) {
  68. list[i] = f.readU16();
  69. }
  70. for (unsigned int i = 0; i < (numLevels + 1); i++) {
  71. unsigned int end = offset[i] / 2;
  72. bool readingOperand = false;
  73. while (readingOperand || (list[end] != OP_END)) {
  74. if (readingOperand) {
  75. readingOperand = false;
  76. end++;
  77. } else {
  78. if (opcodeHasOperand[list[end]]) {
  79. readingOperand = true;
  80. }
  81. end++;
  82. }
  83. }
  84. end++;
  85. std::vector<uint16_t> tmp;
  86. for (unsigned int a = (offset[i] / 2); a < end; a++)
  87. tmp.push_back(list[a]);
  88. script.push_back(tmp);
  89. }
  90. delete [] list;
  91. delete [] offset;
  92. // Engine expects 89 game strings!
  93. numGameStrings = f.readU16();
  94. assertEqual(numGameStrings, 89);
  95. // More strings...
  96. readStringPackage(f, gameStrings, numGameStrings);
  97. readStringPackage(f, pcStrings, 41);
  98. readStringPackage(f, puzzles[0], numLevels);
  99. readStringPackage(f, puzzles[1], numLevels);
  100. readStringPackage(f, puzzles[2], numLevels);
  101. readStringPackage(f, puzzles[3], numLevels);
  102. readStringPackage(f, pickups[0], numLevels);
  103. readStringPackage(f, pickups[1], numLevels);
  104. readStringPackage(f, keys[0], numLevels);
  105. readStringPackage(f, keys[1], numLevels);
  106. readStringPackage(f, keys[2], numLevels);
  107. readStringPackage(f, keys[3], numLevels);
  108. return 0;
  109. }
  110. void Script::readStringPackage(BinaryFile &f, std::vector<std::string> &v, unsigned int n) {
  111. uint16_t *offset = new uint16_t[n];
  112. for (unsigned int i = 0; i < n; i++)
  113. offset[i] = f.readU16();
  114. uint16_t numBytes = f.readU16();
  115. char *list = new char[numBytes];
  116. for (uint16_t i = 0; i < numBytes; i++) {
  117. list[i] = f.read8();
  118. if (flags & S_UseSecurityTag) {
  119. list[i] ^= cypherCode;
  120. }
  121. }
  122. for (unsigned int i = 0; i < n; i++) {
  123. std::string tmp(list + offset[i]);
  124. v.push_back(tmp);
  125. }
  126. delete [] list;
  127. delete [] offset;
  128. }
  129. unsigned int Script::levelCount() {
  130. return numLevels;
  131. }
  132. std::string Script::getLevelName(unsigned int i) {
  133. assert(i < numLevels);
  134. return levelNames.at(i);
  135. }
  136. std::string Script::getLevelFilename(unsigned int i) {
  137. assert(i < numLevels);
  138. return levelFilenames.at(i);
  139. }
  140. unsigned int Script::cutsceneCount() {
  141. return numCutscenes;
  142. }
  143. std::string Script::getCutsceneFilename(unsigned int i) {
  144. assert(i < numCutscenes);
  145. return cutsceneFilenames.at(i);
  146. }
  147. unsigned int Script::titleCount() {
  148. return numTitles;
  149. }
  150. std::string Script::getTitleFilename(unsigned int i) {
  151. assert(i < numTitles);
  152. return titleFilenames.at(i);
  153. }
  154. unsigned int Script::videoCount() {
  155. return numFMVs;
  156. }
  157. std::string Script::getVideoFilename(unsigned int i) {
  158. assert(i < numFMVs);
  159. return fmvFilenames.at(i);
  160. }
  161. unsigned int Script::gameStringCount() {
  162. return numGameStrings;
  163. }
  164. std::string Script::getGameString(unsigned int i) {
  165. assert(i < numGameStrings);
  166. return gameStrings.at(i);
  167. }
  168. unsigned int Script::pcStringCount() {
  169. return 41;
  170. }
  171. std::string Script::getPCString(unsigned int i) {
  172. assert(i < 41);
  173. return pcStrings.at(i);
  174. }
  175. std::string Script::getPuzzleString(unsigned int i, unsigned int j) {
  176. assert(i < 4);
  177. assert(j < numLevels);
  178. return puzzles.at(i).at(j);
  179. }
  180. std::string Script::getPickupString(unsigned int i, unsigned int j) {
  181. assert(i < 2);
  182. assert(j < numLevels);
  183. return pickups.at(i).at(j);
  184. }
  185. std::string Script::getKeyString(unsigned int i, unsigned int j) {
  186. assert(i < 4);
  187. assert(j < numLevels);
  188. return keys.at(i).at(j);
  189. }
  190. void Script::registerScriptHandler(ScriptOpCode op, std::function<int (bool, uint16_t)> func) {
  191. assert(op < OP_UNKNOWN);
  192. scriptHandlers[op] = func;
  193. }
  194. int Script::runScript(unsigned int level) {
  195. assert(level < (numLevels + 1));
  196. std::vector<uint16_t> s = script.at(level);
  197. for (unsigned int i = 0; i < s.size(); i++) {
  198. uint16_t opcode = s.at(i);
  199. if (opcode >= OP_UNKNOWN) {
  200. return 1;
  201. }
  202. uint16_t operand = 0;
  203. if (opcodeHasOperand[opcode]) {
  204. if ((i + 1) >= s.size())
  205. return 2; // Can't read operand!
  206. operand = s.at(++i);
  207. }
  208. if (scriptHandlers[opcode]) {
  209. int error = scriptHandlers[opcode](opcodeHasOperand[opcode], operand);
  210. if (error != 0)
  211. return error;
  212. } else {
  213. return 3;
  214. }
  215. }
  216. return 0;
  217. }