cx4.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. C4 emulation
  3. Used in Rockman X2/X3 (Megaman X2/X3)
  4. Portions (c) anomie, Overload, zsKnight, Nach, byuu
  5. */
  6. #include <../base.hpp>
  7. #define CX4_CPP
  8. #include "cx4.hpp"
  9. #include "cx4data.cpp"
  10. #include "cx4fn.cpp"
  11. #include "cx4oam.cpp"
  12. #include "cx4ops.cpp"
  13. void Cx4::init() {}
  14. void Cx4::enable() {}
  15. uint32 Cx4::ldr(uint8 r) {
  16. uint16 addr = 0x0080 + (r * 3);
  17. return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
  18. }
  19. void Cx4::str(uint8 r, uint32 data) {
  20. uint16 addr = 0x0080 + (r * 3);
  21. reg[addr ] = (data);
  22. reg[addr + 1] = (data >> 8);
  23. reg[addr + 2] = (data >> 16);
  24. }
  25. void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
  26. int64 rx = x & 0xffffff;
  27. int64 ry = y & 0xffffff;
  28. if(rx & 0x800000)rx |= ~0x7fffff;
  29. if(ry & 0x800000)ry |= ~0x7fffff;
  30. rx *= ry;
  31. rl = (rx) & 0xffffff;
  32. rh = (rx >> 24) & 0xffffff;
  33. }
  34. uint32 Cx4::sin(uint32 rx) {
  35. r0 = rx & 0x1ff;
  36. if(r0 & 0x100)r0 ^= 0x1ff;
  37. if(r0 & 0x080)r0 ^= 0x0ff;
  38. if(rx & 0x100) {
  39. return sin_table[r0 + 0x80];
  40. } else {
  41. return sin_table[r0];
  42. }
  43. }
  44. uint32 Cx4::cos(uint32 rx) {
  45. return sin(rx + 0x080);
  46. }
  47. void Cx4::immediate_reg(uint32 start) {
  48. r0 = ldr(0);
  49. for(uint32 i = start; i < 48; i++) {
  50. if((r0 & 0x0fff) < 0x0c00) {
  51. ram[r0 & 0x0fff] = immediate_data[i];
  52. }
  53. r0++;
  54. }
  55. str(0, r0);
  56. }
  57. void Cx4::transfer_data() {
  58. uint32 src;
  59. uint16 dest, count;
  60. src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
  61. count = (reg[0x43]) | (reg[0x44] << 8);
  62. dest = (reg[0x45]) | (reg[0x46] << 8);
  63. for(uint32 i=0;i<count;i++) {
  64. write(dest++, bus.read(src++));
  65. }
  66. }
  67. void Cx4::write(unsigned addr, uint8 data) {
  68. addr &= 0x1fff;
  69. if(addr < 0x0c00) {
  70. //ram
  71. ram[addr] = data;
  72. return;
  73. }
  74. if(addr < 0x1f00) {
  75. //unmapped
  76. return;
  77. }
  78. //command register
  79. reg[addr & 0xff] = data;
  80. if(addr == 0x1f47) {
  81. //memory transfer
  82. transfer_data();
  83. return;
  84. }
  85. if(addr == 0x1f4f) {
  86. //c4 command
  87. if(reg[0x4d] == 0x0e && !(data & 0xc3)) {
  88. //c4 test command
  89. reg[0x80] = data >> 2;
  90. return;
  91. }
  92. switch(data) {
  93. case 0x00: op00(); break;
  94. case 0x01: op01(); break;
  95. case 0x05: op05(); break;
  96. case 0x0d: op0d(); break;
  97. case 0x10: op10(); break;
  98. case 0x13: op13(); break;
  99. case 0x15: op15(); break;
  100. case 0x1f: op1f(); break;
  101. case 0x22: op22(); break;
  102. case 0x25: op25(); break;
  103. case 0x2d: op2d(); break;
  104. case 0x40: op40(); break;
  105. case 0x54: op54(); break;
  106. case 0x5c: op5c(); break;
  107. case 0x5e: op5e(); break;
  108. case 0x60: op60(); break;
  109. case 0x62: op62(); break;
  110. case 0x64: op64(); break;
  111. case 0x66: op66(); break;
  112. case 0x68: op68(); break;
  113. case 0x6a: op6a(); break;
  114. case 0x6c: op6c(); break;
  115. case 0x6e: op6e(); break;
  116. case 0x70: op70(); break;
  117. case 0x72: op72(); break;
  118. case 0x74: op74(); break;
  119. case 0x76: op76(); break;
  120. case 0x78: op78(); break;
  121. case 0x7a: op7a(); break;
  122. case 0x7c: op7c(); break;
  123. case 0x89: op89(); break;
  124. }
  125. }
  126. }
  127. void Cx4::writeb(uint16 addr, uint8 data) {
  128. write(addr, data);
  129. }
  130. void Cx4::writew(uint16 addr, uint16 data) {
  131. write(addr, data);
  132. write(addr + 1, data >> 8);
  133. }
  134. void Cx4::writel(uint16 addr, uint32 data) {
  135. write(addr, data);
  136. write(addr + 1, data >> 8);
  137. write(addr + 2, data >> 16);
  138. }
  139. uint8 Cx4::read(unsigned addr) {
  140. addr &= 0x1fff;
  141. if(addr < 0x0c00) {
  142. return ram[addr];
  143. }
  144. if(addr >= 0x1f00) {
  145. return reg[addr & 0xff];
  146. }
  147. return cpu.regs.mdr;
  148. }
  149. uint8 Cx4::readb(uint16 addr) {
  150. return read(addr);
  151. }
  152. uint16 Cx4::readw(uint16 addr) {
  153. return read(addr) | (read(addr + 1) << 8);
  154. }
  155. uint32 Cx4::readl(uint16 addr) {
  156. return read(addr) | (read(addr + 1) << 8) + (read(addr + 2) << 16);
  157. }
  158. void Cx4::power() {
  159. reset();
  160. }
  161. void Cx4::reset() {
  162. memset(ram, 0, 0x0c00);
  163. memset(reg, 0, 0x0100);
  164. }