opcodemgr.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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. return(OpcodeNames[emu_op]);
  113. }
  114. const char *OpcodeManager::EQToName(const uint16 eq_op) {
  115. //first must resolve the eq op to an emu op
  116. EmuOpcode emu_op = EQToEmu(eq_op);
  117. return(OpcodeNames[emu_op]);
  118. }
  119. EmuOpcode OpcodeManager::NameSearch(const char *name) {
  120. EmuOpcode emu_op;
  121. //stupid enum wont let me ++ on it...
  122. for(emu_op = (EmuOpcode)(0); emu_op < _maxEmuOpcode; emu_op=(EmuOpcode)(emu_op+1)) {
  123. //get the name of this emu opcode
  124. const char *op_name = OpcodeNames[emu_op];
  125. if(!strcasecmp(op_name, name)) {
  126. return(emu_op);
  127. }
  128. }
  129. return(OP_Unknown);
  130. }
  131. RegularOpcodeManager::RegularOpcodeManager()
  132. : MutableOpcodeManager()
  133. {
  134. emu_to_eq = NULL;
  135. eq_to_emu = NULL;
  136. EQOpcodeCount = 0;
  137. EmuOpcodeCount = 0;
  138. }
  139. RegularOpcodeManager::~RegularOpcodeManager() {
  140. safe_delete_array(emu_to_eq);
  141. safe_delete_array(eq_to_emu);
  142. }
  143. bool RegularOpcodeManager::LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes) {
  144. NormalMemStrategy s;
  145. s.it = this;
  146. MOpcodes.lock();
  147. loaded = true;
  148. eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE];
  149. emu_to_eq = new uint16[_maxEmuOpcode];
  150. EQOpcodeCount = MAX_EQ_OPCODE;
  151. EmuOpcodeCount = _maxEmuOpcode;
  152. //dont need to set eq_to_emu cause every element should get a value
  153. memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
  154. bool ret = LoadOpcodesMap(eq, &s, missingOpcodes);
  155. MOpcodes.unlock();
  156. return ret;
  157. }
  158. bool RegularOpcodeManager::LoadOpcodes(const char *filename) {
  159. NormalMemStrategy s;
  160. s.it = this;
  161. MOpcodes.lock();
  162. loaded = true;
  163. eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE];
  164. emu_to_eq = new uint16[_maxEmuOpcode];
  165. EQOpcodeCount = MAX_EQ_OPCODE;
  166. EmuOpcodeCount = _maxEmuOpcode;
  167. //dont need to set eq_to_emu cause every element should get a value
  168. memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
  169. bool ret = LoadOpcodesFile(filename, &s);
  170. MOpcodes.unlock();
  171. return ret;
  172. }
  173. bool RegularOpcodeManager::ReloadOpcodes(const char *filename) {
  174. if(!loaded)
  175. return(LoadOpcodes(filename));
  176. NormalMemStrategy s;
  177. s.it = this;
  178. MOpcodes.lock();
  179. memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
  180. bool ret = LoadOpcodesFile(filename, &s);
  181. MOpcodes.unlock();
  182. return(ret);
  183. }
  184. uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
  185. //opcode is checked for validity in GetEQOpcode
  186. uint16 res;
  187. MOpcodes.lock();
  188. res = emu_to_eq[emu_op];
  189. MOpcodes.unlock();
  190. #ifdef _DEBUG_TRANSLATE
  191. fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res);
  192. #endif
  193. return(res);
  194. }
  195. EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) {
  196. //opcode is checked for validity in GetEmuOpcode
  197. //Disabled since current live EQ uses the entire uint16 bitspace for opcodes
  198. // if(eq_op > MAX_EQ_OPCODE)
  199. // return(OP_Unknown);
  200. EmuOpcode res;
  201. MOpcodes.lock();
  202. res = eq_to_emu[eq_op];
  203. MOpcodes.unlock();
  204. #ifdef _DEBUG_TRANSLATE
  205. fprintf(stderr, "M Translate EQ 0x%.4x to Emu %s (%d)\n", eq_op, OpcodeNames[res], res);
  206. #endif
  207. return(res);
  208. }
  209. void RegularOpcodeManager::SetOpcode(EmuOpcode emu_op, uint16 eq_op) {
  210. //clear out old mapping
  211. uint16 oldop = emu_to_eq[emu_op];
  212. if(oldop != 0)
  213. eq_to_emu[oldop] = OP_Unknown;
  214. //use our strategy, since we have it
  215. NormalMemStrategy s;
  216. s.it = this;
  217. s.Set(emu_op, eq_op);
  218. }
  219. void RegularOpcodeManager::NormalMemStrategy::Set(EmuOpcode emu_op, uint16 eq_op) {
  220. if(uint32(emu_op) >= it->EmuOpcodeCount || eq_op >= it->EQOpcodeCount)
  221. return;
  222. it->emu_to_eq[emu_op] = eq_op;
  223. it->eq_to_emu[eq_op] = emu_op;
  224. }
  225. NullOpcodeManager::NullOpcodeManager()
  226. : MutableOpcodeManager() {
  227. }
  228. bool NullOpcodeManager::LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes) {
  229. return(true);
  230. }
  231. bool NullOpcodeManager::LoadOpcodes(const char *filename) {
  232. return(true);
  233. }
  234. bool NullOpcodeManager::ReloadOpcodes(const char *filename) {
  235. return(true);
  236. }
  237. uint16 NullOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
  238. return(0);
  239. }
  240. EmuOpcode NullOpcodeManager::EQToEmu(const uint16 eq_op) {
  241. return(OP_Unknown);
  242. }
  243. EmptyOpcodeManager::EmptyOpcodeManager()
  244. : MutableOpcodeManager() {
  245. }
  246. bool EmptyOpcodeManager::LoadOpcodes(const char *filename) {
  247. return(true);
  248. }
  249. bool EmptyOpcodeManager::LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes) {
  250. return(true);
  251. }
  252. bool EmptyOpcodeManager::ReloadOpcodes(const char *filename) {
  253. return(true);
  254. }
  255. uint16 EmptyOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
  256. map<EmuOpcode, uint16>::iterator f;
  257. f = emu_to_eq.find(emu_op);
  258. return(f == emu_to_eq.end()? 0 : f->second);
  259. }
  260. EmuOpcode EmptyOpcodeManager::EQToEmu(const uint16 eq_op) {
  261. map<uint16, EmuOpcode>::iterator f;
  262. f = eq_to_emu.find(eq_op);
  263. return(f == eq_to_emu.end()?OP_Unknown:f->second);
  264. }
  265. void EmptyOpcodeManager::SetOpcode(EmuOpcode emu_op, uint16 eq_op) {
  266. emu_to_eq[emu_op] = eq_op;
  267. eq_to_emu[eq_op] = emu_op;
  268. }