opcodemgr.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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){
  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. LogWrite(OPCODE__WARNING, 1, "Opcode", "Opcode %s is missing from the opcodes table.", op_name);
  50. s->Set(emu_op, 0);
  51. continue; //continue to give them a list of all missing opcodes
  52. }
  53. //ship the mapping off to shared mem.
  54. s->Set(emu_op, res->second);
  55. }
  56. return ret;
  57. }
  58. bool OpcodeManager::LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s) {
  59. FILE *opf = fopen(filename, "r");
  60. if(opf == NULL) {
  61. LogWrite(OPCODE__ERROR, 0, "Opcode", "Unable to open opcodes file '%s'. Thats bad.", filename);
  62. return(false);
  63. }
  64. map<string, uint16> eq;
  65. //load the opcode file into eq, could swap in a nice XML parser here
  66. char line[2048];
  67. int lineno = 0;
  68. uint16 curop;
  69. while(!feof(opf)) {
  70. lineno++;
  71. line[0] = '\0'; //for blank line at end of file
  72. if(fgets(line, sizeof(line), opf) == NULL)
  73. break;
  74. //ignore any line that dosent start with OP_
  75. if(line[0] != 'O' || line[1] != 'P' || line[2] != '_')
  76. continue;
  77. char *num = line+3; //skip OP_
  78. //look for the = sign
  79. while(*num != '=' && *num != '\0') {
  80. num++;
  81. }
  82. //make sure we found =
  83. if(*num != '=') {
  84. LogWrite(OPCODE__ERROR, 0, "Opcode", "Malformed opcode line at %s:%d\n", filename, lineno);
  85. continue;
  86. }
  87. *num = '\0'; //null terminate the name
  88. num++; //num should point to the opcode
  89. //read the opcode
  90. if(sscanf(num, "0x%hx", &curop) != 1) {
  91. LogWrite(OPCODE__ERROR, 0, "Opcode", "Malformed opcode at %s:%d\n", filename, lineno);
  92. continue;
  93. }
  94. //we have a name and our opcode... stick it in the map
  95. eq[line] = curop;
  96. }
  97. fclose(opf);
  98. return LoadOpcodesMap(&eq, s);
  99. }
  100. //convenience routines
  101. const char *OpcodeManager::EmuToName(const EmuOpcode emu_op) {
  102. return(OpcodeNames[emu_op]);
  103. }
  104. const char *OpcodeManager::EQToName(const uint16 eq_op) {
  105. //first must resolve the eq op to an emu op
  106. EmuOpcode emu_op = EQToEmu(eq_op);
  107. return(OpcodeNames[emu_op]);
  108. }
  109. EmuOpcode OpcodeManager::NameSearch(const char *name) {
  110. EmuOpcode emu_op;
  111. //stupid enum wont let me ++ on it...
  112. for(emu_op = (EmuOpcode)(0); emu_op < _maxEmuOpcode; emu_op=(EmuOpcode)(emu_op+1)) {
  113. //get the name of this emu opcode
  114. const char *op_name = OpcodeNames[emu_op];
  115. if(!strcasecmp(op_name, name)) {
  116. return(emu_op);
  117. }
  118. }
  119. return(OP_Unknown);
  120. }
  121. RegularOpcodeManager::RegularOpcodeManager()
  122. : MutableOpcodeManager()
  123. {
  124. emu_to_eq = NULL;
  125. eq_to_emu = NULL;
  126. EQOpcodeCount = 0;
  127. EmuOpcodeCount = 0;
  128. }
  129. RegularOpcodeManager::~RegularOpcodeManager() {
  130. safe_delete_array(emu_to_eq);
  131. safe_delete_array(eq_to_emu);
  132. }
  133. bool RegularOpcodeManager::LoadOpcodes(map<string, uint16>* eq) {
  134. NormalMemStrategy s;
  135. s.it = this;
  136. MOpcodes.lock();
  137. loaded = true;
  138. eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE];
  139. emu_to_eq = new uint16[_maxEmuOpcode];
  140. EQOpcodeCount = MAX_EQ_OPCODE;
  141. EmuOpcodeCount = _maxEmuOpcode;
  142. //dont need to set eq_to_emu cause every element should get a value
  143. memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
  144. bool ret = LoadOpcodesMap(eq, &s);
  145. MOpcodes.unlock();
  146. return ret;
  147. }
  148. bool RegularOpcodeManager::LoadOpcodes(const char *filename) {
  149. NormalMemStrategy s;
  150. s.it = this;
  151. MOpcodes.lock();
  152. loaded = true;
  153. eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE];
  154. emu_to_eq = new uint16[_maxEmuOpcode];
  155. EQOpcodeCount = MAX_EQ_OPCODE;
  156. EmuOpcodeCount = _maxEmuOpcode;
  157. //dont need to set eq_to_emu cause every element should get a value
  158. memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
  159. bool ret = LoadOpcodesFile(filename, &s);
  160. MOpcodes.unlock();
  161. return ret;
  162. }
  163. bool RegularOpcodeManager::ReloadOpcodes(const char *filename) {
  164. if(!loaded)
  165. return(LoadOpcodes(filename));
  166. NormalMemStrategy s;
  167. s.it = this;
  168. MOpcodes.lock();
  169. memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
  170. bool ret = LoadOpcodesFile(filename, &s);
  171. MOpcodes.unlock();
  172. return(ret);
  173. }
  174. uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
  175. //opcode is checked for validity in GetEQOpcode
  176. uint16 res;
  177. MOpcodes.lock();
  178. res = emu_to_eq[emu_op];
  179. MOpcodes.unlock();
  180. #ifdef _DEBUG_TRANSLATE
  181. fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res);
  182. #endif
  183. return(res);
  184. }
  185. EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) {
  186. //opcode is checked for validity in GetEmuOpcode
  187. //Disabled since current live EQ uses the entire uint16 bitspace for opcodes
  188. // if(eq_op > MAX_EQ_OPCODE)
  189. // return(OP_Unknown);
  190. EmuOpcode res;
  191. MOpcodes.lock();
  192. res = eq_to_emu[eq_op];
  193. MOpcodes.unlock();
  194. #ifdef _DEBUG_TRANSLATE
  195. fprintf(stderr, "M Translate EQ 0x%.4x to Emu %s (%d)\n", eq_op, OpcodeNames[res], res);
  196. #endif
  197. return(res);
  198. }
  199. void RegularOpcodeManager::SetOpcode(EmuOpcode emu_op, uint16 eq_op) {
  200. //clear out old mapping
  201. uint16 oldop = emu_to_eq[emu_op];
  202. if(oldop != 0)
  203. eq_to_emu[oldop] = OP_Unknown;
  204. //use our strategy, since we have it
  205. NormalMemStrategy s;
  206. s.it = this;
  207. s.Set(emu_op, eq_op);
  208. }
  209. void RegularOpcodeManager::NormalMemStrategy::Set(EmuOpcode emu_op, uint16 eq_op) {
  210. if(uint32(emu_op) >= it->EmuOpcodeCount || eq_op >= it->EQOpcodeCount)
  211. return;
  212. it->emu_to_eq[emu_op] = eq_op;
  213. it->eq_to_emu[eq_op] = emu_op;
  214. }
  215. NullOpcodeManager::NullOpcodeManager()
  216. : MutableOpcodeManager() {
  217. }
  218. bool NullOpcodeManager::LoadOpcodes(map<string, uint16>* eq) {
  219. return(true);
  220. }
  221. bool NullOpcodeManager::LoadOpcodes(const char *filename) {
  222. return(true);
  223. }
  224. bool NullOpcodeManager::ReloadOpcodes(const char *filename) {
  225. return(true);
  226. }
  227. uint16 NullOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
  228. return(0);
  229. }
  230. EmuOpcode NullOpcodeManager::EQToEmu(const uint16 eq_op) {
  231. return(OP_Unknown);
  232. }
  233. EmptyOpcodeManager::EmptyOpcodeManager()
  234. : MutableOpcodeManager() {
  235. }
  236. bool EmptyOpcodeManager::LoadOpcodes(const char *filename) {
  237. return(true);
  238. }
  239. bool EmptyOpcodeManager::LoadOpcodes(map<string, uint16>* eq) {
  240. return(true);
  241. }
  242. bool EmptyOpcodeManager::ReloadOpcodes(const char *filename) {
  243. return(true);
  244. }
  245. uint16 EmptyOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
  246. map<EmuOpcode, uint16>::iterator f;
  247. f = emu_to_eq.find(emu_op);
  248. return(f == emu_to_eq.end()? 0 : f->second);
  249. }
  250. EmuOpcode EmptyOpcodeManager::EQToEmu(const uint16 eq_op) {
  251. map<uint16, EmuOpcode>::iterator f;
  252. f = eq_to_emu.find(eq_op);
  253. return(f == eq_to_emu.end()?OP_Unknown:f->second);
  254. }
  255. void EmptyOpcodeManager::SetOpcode(EmuOpcode emu_op, uint16 eq_op) {
  256. emu_to_eq[emu_op] = eq_op;
  257. eq_to_emu[eq_op] = emu_op;
  258. }