9
3

opcodemgr.cpp 8.0 KB

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