opcodemgr.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. EQ2Emulator is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. EQ2Emulator is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "debug.h"
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include "opcodemgr.h"
  20. //#include "debug.h"
  21. #include "emu_opcodes.h"
  22. #include "../common/Log.h"
  23. #if defined(SHARED_OPCODES) && !defined(EQ2)
  24. #include "EMuShareMem.h"
  25. extern LoadEMuShareMemDLL EMuShareMemDLL;
  26. #endif
  27. #include <map>
  28. #include <string>
  29. using namespace std;
  30. //#define DEBUG_TRANSLATE
  31. OpcodeManager::OpcodeManager() {
  32. loaded = false;
  33. }
  34. bool OpcodeManager::LoadOpcodesMap(map<string, uint16>* eq, OpcodeSetStrategy *s, std::string* missingOpcodes){
  35. //do the mapping and store them in the shared memory array
  36. bool ret = true;
  37. EmuOpcode emu_op;
  38. map<string, uint16>::iterator res;
  39. //stupid enum wont let me ++ on it...
  40. for(emu_op = (EmuOpcode)(0); emu_op < _maxEmuOpcode; emu_op=(EmuOpcode)(emu_op+1)) {
  41. //get the name of this emu opcode
  42. const char *op_name = OpcodeNames[emu_op];
  43. if(op_name[0] == '\0') {
  44. break;
  45. }
  46. //find the opcode in the file
  47. res = eq->find(op_name);
  48. if(res == eq->end()) {
  49. if(missingOpcodes) {
  50. if(missingOpcodes->size() < 1) {
  51. missingOpcodes->append(op_name);
  52. }
  53. else {
  54. missingOpcodes->append(", " + std::string(op_name));
  55. }
  56. }
  57. else {
  58. LogWrite(OPCODE__WARNING, 1, "Opcode", "Opcode %s is missing from the opcodes table.", op_name);
  59. }
  60. s->Set(emu_op, 0xFFFF);
  61. continue; //continue to give them a list of all missing opcodes
  62. }
  63. //ship the mapping off to shared mem.
  64. s->Set(emu_op, res->second);
  65. }
  66. return ret;
  67. }
  68. bool OpcodeManager::LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s) {
  69. FILE *opf = fopen(filename, "r");
  70. if(opf == NULL) {
  71. LogWrite(OPCODE__ERROR, 0, "Opcode", "Unable to open opcodes file '%s'. Thats bad.", filename);
  72. return(false);
  73. }
  74. map<string, uint16> eq;
  75. //load the opcode file into eq, could swap in a nice XML parser here
  76. char line[2048];
  77. int lineno = 0;
  78. uint16 curop;
  79. while(!feof(opf)) {
  80. lineno++;
  81. line[0] = '\0'; //for blank line at end of file
  82. if(fgets(line, sizeof(line), opf) == NULL)
  83. break;
  84. //ignore any line that dosent start with OP_
  85. if(line[0] != 'O' || line[1] != 'P' || line[2] != '_')
  86. continue;
  87. char *num = line+3; //skip OP_
  88. //look for the = sign
  89. while(*num != '=' && *num != '\0') {
  90. num++;
  91. }
  92. //make sure we found =
  93. if(*num != '=') {
  94. LogWrite(OPCODE__ERROR, 0, "Opcode", "Malformed opcode line at %s:%d\n", filename, lineno);
  95. continue;
  96. }
  97. *num = '\0'; //null terminate the name
  98. num++; //num should point to the opcode
  99. //read the opcode
  100. if(sscanf(num, "0x%hx", &curop) != 1) {
  101. LogWrite(OPCODE__ERROR, 0, "Opcode", "Malformed opcode at %s:%d\n", filename, lineno);
  102. continue;
  103. }
  104. //we have a name and our opcode... stick it in the map
  105. eq[line] = curop;
  106. }
  107. fclose(opf);
  108. return LoadOpcodesMap(&eq, s);
  109. }
  110. //convenience routines
  111. const char *OpcodeManager::EmuToName(const EmuOpcode emu_op) {
  112. if(emu_op > _maxEmuOpcode)
  113. return "OP_Unknown";
  114. return(OpcodeNames[emu_op]);
  115. }
  116. const char *OpcodeManager::EQToName(const uint16 eq_op) {
  117. //first must resolve the eq op to an emu op
  118. EmuOpcode emu_op = EQToEmu(eq_op);
  119. if(emu_op > _maxEmuOpcode)
  120. return "OP_Unknown";
  121. return(OpcodeNames[emu_op]);
  122. }
  123. EmuOpcode OpcodeManager::NameSearch(const char *name) {
  124. EmuOpcode emu_op;
  125. //stupid enum wont let me ++ on it...
  126. for(emu_op = (EmuOpcode)(0); emu_op < _maxEmuOpcode; emu_op=(EmuOpcode)(emu_op+1)) {
  127. //get the name of this emu opcode
  128. const char *op_name = OpcodeNames[emu_op];
  129. if(!strcasecmp(op_name, name)) {
  130. return(emu_op);
  131. }
  132. }
  133. return(OP_Unknown);
  134. }
  135. RegularOpcodeManager::RegularOpcodeManager()
  136. : MutableOpcodeManager()
  137. {
  138. emu_to_eq = NULL;
  139. eq_to_emu = NULL;
  140. EQOpcodeCount = 0;
  141. EmuOpcodeCount = 0;
  142. }
  143. RegularOpcodeManager::~RegularOpcodeManager() {
  144. safe_delete_array(emu_to_eq);
  145. safe_delete_array(eq_to_emu);
  146. }
  147. bool RegularOpcodeManager::LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes) {
  148. NormalMemStrategy s;
  149. s.it = this;
  150. MOpcodes.lock();
  151. loaded = true;
  152. eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE];
  153. emu_to_eq = new uint16[_maxEmuOpcode];
  154. EQOpcodeCount = MAX_EQ_OPCODE;
  155. EmuOpcodeCount = _maxEmuOpcode;
  156. //dont need to set eq_to_emu cause every element should get a value
  157. memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
  158. memset(emu_to_eq, 0xCD, sizeof(uint16)*_maxEmuOpcode);
  159. bool ret = LoadOpcodesMap(eq, &s, missingOpcodes);
  160. MOpcodes.unlock();
  161. return ret;
  162. }
  163. bool RegularOpcodeManager::LoadOpcodes(const char *filename) {
  164. NormalMemStrategy s;
  165. s.it = this;
  166. MOpcodes.lock();
  167. loaded = true;
  168. eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE];
  169. emu_to_eq = new uint16[_maxEmuOpcode];
  170. EQOpcodeCount = MAX_EQ_OPCODE;
  171. EmuOpcodeCount = _maxEmuOpcode;
  172. //dont need to set eq_to_emu cause every element should get a value
  173. memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
  174. memset(emu_to_eq, 0xCD, sizeof(uint16)*_maxEmuOpcode);
  175. bool ret = LoadOpcodesFile(filename, &s);
  176. MOpcodes.unlock();
  177. return ret;
  178. }
  179. bool RegularOpcodeManager::ReloadOpcodes(const char *filename) {
  180. if(!loaded)
  181. return(LoadOpcodes(filename));
  182. NormalMemStrategy s;
  183. s.it = this;
  184. MOpcodes.lock();
  185. memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
  186. bool ret = LoadOpcodesFile(filename, &s);
  187. MOpcodes.unlock();
  188. return(ret);
  189. }
  190. uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
  191. //opcode is checked for validity in GetEQOpcode
  192. uint16 res;
  193. MOpcodes.lock();
  194. if(emu_op > _maxEmuOpcode)
  195. res = 0;
  196. else
  197. res = emu_to_eq[emu_op];
  198. MOpcodes.unlock();
  199. #ifdef _DEBUG_TRANSLATE
  200. fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res);
  201. #endif
  202. return(res);
  203. }
  204. EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) {
  205. //opcode is checked for validity in GetEmuOpcode
  206. //Disabled since current live EQ uses the entire uint16 bitspace for opcodes
  207. // if(eq_op > MAX_EQ_OPCODE)
  208. // return(OP_Unknown);
  209. EmuOpcode res;
  210. MOpcodes.lock();
  211. if(eq_op >= MAX_EQ_OPCODE)
  212. res = OP_Unknown;
  213. else
  214. res = eq_to_emu[eq_op];
  215. MOpcodes.unlock();
  216. #ifdef _DEBUG_TRANSLATE
  217. fprintf(stderr, "M Translate EQ 0x%.4x to Emu %s (%d)\n", eq_op, OpcodeNames[res], res);
  218. #endif
  219. return(res);
  220. }
  221. void RegularOpcodeManager::SetOpcode(EmuOpcode emu_op, uint16 eq_op) {
  222. //clear out old mapping
  223. uint16 oldop = 0;
  224. if(emu_op <= _maxEmuOpcode)
  225. oldop = emu_to_eq[emu_op];
  226. if(oldop != 0 && oldop < MAX_EQ_OPCODE)
  227. eq_to_emu[oldop] = OP_Unknown;
  228. //use our strategy, since we have it
  229. NormalMemStrategy s;
  230. s.it = this;
  231. s.Set(emu_op, eq_op);
  232. }
  233. void RegularOpcodeManager::NormalMemStrategy::Set(EmuOpcode emu_op, uint16 eq_op) {
  234. if(uint32(emu_op) >= it->EmuOpcodeCount || eq_op >= it->EQOpcodeCount)
  235. return;
  236. it->emu_to_eq[emu_op] = eq_op;
  237. it->eq_to_emu[eq_op] = emu_op;
  238. }
  239. NullOpcodeManager::NullOpcodeManager()
  240. : MutableOpcodeManager() {
  241. }
  242. bool NullOpcodeManager::LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes) {
  243. return(true);
  244. }
  245. bool NullOpcodeManager::LoadOpcodes(const char *filename) {
  246. return(true);
  247. }
  248. bool NullOpcodeManager::ReloadOpcodes(const char *filename) {
  249. return(true);
  250. }
  251. uint16 NullOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
  252. return(0);
  253. }
  254. EmuOpcode NullOpcodeManager::EQToEmu(const uint16 eq_op) {
  255. return(OP_Unknown);
  256. }
  257. EmptyOpcodeManager::EmptyOpcodeManager()
  258. : MutableOpcodeManager() {
  259. }
  260. bool EmptyOpcodeManager::LoadOpcodes(const char *filename) {
  261. return(true);
  262. }
  263. bool EmptyOpcodeManager::LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes) {
  264. return(true);
  265. }
  266. bool EmptyOpcodeManager::ReloadOpcodes(const char *filename) {
  267. return(true);
  268. }
  269. uint16 EmptyOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
  270. map<EmuOpcode, uint16>::iterator f;
  271. f = emu_to_eq.find(emu_op);
  272. return(f == emu_to_eq.end()? 0 : f->second);
  273. }
  274. EmuOpcode EmptyOpcodeManager::EQToEmu(const uint16 eq_op) {
  275. map<uint16, EmuOpcode>::iterator f;
  276. f = eq_to_emu.find(eq_op);
  277. return(f == eq_to_emu.end()?OP_Unknown:f->second);
  278. }
  279. void EmptyOpcodeManager::SetOpcode(EmuOpcode emu_op, uint16 eq_op) {
  280. emu_to_eq[emu_op] = eq_op;
  281. eq_to_emu[eq_op] = emu_op;
  282. }