/Nes/Mappers/Mapper025.cs

http://mynes.codeplex.com · C# · 237 lines · 201 code · 16 blank · 20 comment · 20 complexity · 05867498d34883abd74108ab1256d0c1 MD5 · raw file

  1. /*********************************************************************\
  2. *This file is part of My Nes *
  3. *A Nintendo Entertainment System Emulator. *
  4. * *
  5. *Copyright Š Ala Hadid 2009 - 2011 *
  6. *E-mail: mailto:ahdsoftwares@hotmail.com *
  7. * *
  8. *My Nes is free software: you can redistribute it and/or modify *
  9. *it under the terms of the GNU General Public License as published by *
  10. *the Free Software Foundation, either version 3 of the License, or *
  11. *(at your option) any later version. *
  12. * *
  13. *My Nes is distributed in the hope that it will be useful, *
  14. *but WITHOUT ANY WARRANTY; without even the implied warranty of *
  15. *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  16. *GNU General Public License for more details. *
  17. * *
  18. *You should have received a copy of the GNU General Public License *
  19. *along with this program. If not, see <http://www.gnu.org/licenses/>.*
  20. \*********************************************************************/
  21. namespace MyNes.Nes
  22. {
  23. class Mapper25 : Mapper
  24. {
  25. byte[] reg = new byte[11];
  26. bool SwapMode = false;
  27. int irq_latch = 0;
  28. byte irq_enable = 0;
  29. int irq_counter = 0;
  30. int irq_clock = 0;
  31. public Mapper25(NesSystem nesSystem)
  32. : base(nesSystem) { }
  33. public override void Poke(int address, byte data)
  34. {
  35. switch (address & 0xF000)
  36. {
  37. case 0x8000:
  38. if ((reg[10] & 0x02) == 0x02)
  39. {
  40. reg[9] = data;
  41. cpuMemory.Switch8kPrgRom(data * 2, 2);
  42. }
  43. else
  44. {
  45. reg[8] = data;
  46. cpuMemory.Switch8kPrgRom(data * 2, 0);
  47. }
  48. break;
  49. case 0xA000:
  50. cpuMemory.Switch8kPrgRom(data * 2, 1);
  51. break;
  52. }
  53. switch (address & 0xF00F)
  54. {
  55. case 0x9001:
  56. case 0x9004:
  57. if ((reg[10] & 0x02) != (data & 0x02))
  58. {
  59. byte swap = reg[8];
  60. reg[8] = reg[9];
  61. reg[9] = swap;
  62. cpuMemory.Switch8kPrgRom(reg[8] * 2, 0);
  63. cpuMemory.Switch8kPrgRom(reg[9] * 2, 2);
  64. }
  65. reg[10] = data;
  66. break;
  67. case 0x9000:
  68. data &= 0x03;
  69. if (data == 0)
  70. cartridge.Mirroring = Mirroring.ModeVert;
  71. else if (data == 1)
  72. cartridge.Mirroring = Mirroring.ModeHorz;
  73. else if (data == 2)
  74. cartridge.Mirroring = Mirroring.Mode1ScA;
  75. else
  76. cartridge.Mirroring = Mirroring.Mode1ScB;
  77. break;
  78. case 0xB000:
  79. reg[0] = (byte)((reg[0] & 0xF0) | (data & 0x0F));
  80. cpuMemory.Switch1kChrRom(reg[0], 0);
  81. break;
  82. case 0xB002:
  83. case 0xB008:
  84. reg[0] = (byte)((reg[0] & 0x0F) | ((data & 0x0F) << 4));
  85. cpuMemory.Switch1kChrRom(reg[0], 0);
  86. break;
  87. case 0xB001:
  88. case 0xB004:
  89. reg[1] = (byte)((reg[1] & 0xF0) | (data & 0x0F));
  90. cpuMemory.Switch1kChrRom(reg[1], 1);
  91. break;
  92. case 0xB003:
  93. case 0xB00C:
  94. reg[1] = (byte)((reg[1] & 0x0F) | ((data & 0x0F) << 4));
  95. cpuMemory.Switch1kChrRom(reg[1], 1);
  96. break;
  97. case 0xC000:
  98. reg[2] = (byte)((reg[2] & 0xF0) | (data & 0x0F));
  99. cpuMemory.Switch1kChrRom(reg[2], 2);
  100. break;
  101. case 0xC002:
  102. case 0xC008:
  103. reg[2] = (byte)((reg[2] & 0x0F) | ((data & 0x0F) << 4));
  104. cpuMemory.Switch1kChrRom(reg[2], 2);
  105. break;
  106. case 0xC001:
  107. case 0xC004:
  108. reg[3] = (byte)((reg[3] & 0xF0) | (data & 0x0F));
  109. cpuMemory.Switch1kChrRom(reg[3], 3);
  110. break;
  111. case 0xC003:
  112. case 0xC00C:
  113. reg[3] = (byte)((reg[3] & 0x0F) | ((data & 0x0F) << 4));
  114. cpuMemory.Switch1kChrRom(reg[3], 3);
  115. break;
  116. case 0xD000:
  117. reg[4] = (byte)((reg[4] & 0xF0) | (data & 0x0F));
  118. cpuMemory.Switch1kChrRom(reg[4], 4);
  119. break;
  120. case 0xD002:
  121. case 0xD008:
  122. reg[4] = (byte)((reg[4] & 0x0F) | ((data & 0x0F) << 4));
  123. cpuMemory.Switch1kChrRom(reg[4], 4);
  124. break;
  125. case 0xD001:
  126. case 0xD004:
  127. reg[5] = (byte)((reg[5] & 0xF0) | (data & 0x0F));
  128. cpuMemory.Switch1kChrRom(reg[5], 5);
  129. break;
  130. case 0xD003:
  131. case 0xD00C:
  132. reg[5] = (byte)((reg[5] & 0x0F) | ((data & 0x0F) << 4));
  133. cpuMemory.Switch1kChrRom(reg[5], 5);
  134. break;
  135. case 0xE000:
  136. reg[6] = (byte)((reg[6] & 0xF0) | (data & 0x0F));
  137. cpuMemory.Switch1kChrRom(reg[6], 6);
  138. break;
  139. case 0xE002:
  140. case 0xE008:
  141. reg[6] = (byte)((reg[6] & 0x0F) | ((data & 0x0F) << 4));
  142. cpuMemory.Switch1kChrRom(reg[6], 6);
  143. break;
  144. case 0xE001:
  145. case 0xE004:
  146. reg[7] = (byte)((reg[7] & 0xF0) | (data & 0x0F));
  147. cpuMemory.Switch1kChrRom(reg[7], 7);
  148. break;
  149. case 0xE003:
  150. case 0xE00C:
  151. reg[7] = (byte)((reg[7] & 0x0F) | ((data & 0x0F) << 4));
  152. cpuMemory.Switch1kChrRom(reg[7], 7);
  153. break;
  154. case 0xF000:
  155. irq_latch = (irq_latch & 0xF0) | (data & 0x0F);
  156. cpu.Interrupt(NesCpu.IsrType.External, false);
  157. break;
  158. case 0xF002:
  159. case 0xF008:
  160. irq_latch = (irq_latch & 0x0F) | ((data & 0x0F) << 4);
  161. cpu.Interrupt(NesCpu.IsrType.External, false);
  162. break;
  163. case 0xF001:
  164. case 0xF004:
  165. irq_enable = (byte)(data & 0x03);
  166. irq_counter = irq_latch;
  167. irq_clock = 0;
  168. cpu.Interrupt(NesCpu.IsrType.External, false);
  169. break;
  170. case 0xF003:
  171. case 0xF00C:
  172. irq_enable = (byte)((irq_enable & 0x01) * 3);
  173. break;
  174. }
  175. }
  176. protected override void Initialize(bool initializing)
  177. {
  178. cpuMemory.Switch16kPrgRom(0, 0);
  179. cpuMemory.Switch16kPrgRom((cartridge.PrgPages - 1) * 4, 1);
  180. if (cartridge.HasCharRam)
  181. cpuMemory.FillChr(16);
  182. reg[9] = (byte)((cartridge.PrgPages * 2) - 2);
  183. }
  184. public override void TickCycleTimer(int cycles)
  185. {
  186. if ((irq_enable & 0x02) != 0)
  187. {
  188. irq_clock += cycles * 3;
  189. while (irq_clock >= 341)
  190. {
  191. irq_clock -= 341;
  192. irq_counter++;
  193. if (irq_counter == 0xFF)
  194. {
  195. irq_counter = irq_latch;
  196. cpu.Interrupt(NesCpu.IsrType.External, true);
  197. }
  198. }
  199. }
  200. }
  201. public override void SaveState(StateStream stateStream)
  202. {
  203. stateStream.Write(reg); stateStream.Write(SwapMode);
  204. stateStream.Write(irq_latch);
  205. stateStream.Write(irq_enable);
  206. stateStream.Write(irq_counter);
  207. stateStream.Write(irq_clock);
  208. base.SaveState(stateStream);
  209. }
  210. public override void LoadState(StateStream stateStream)
  211. {
  212. stateStream.Read(reg);
  213. SwapMode = stateStream.ReadBooleans()[0];
  214. irq_latch = stateStream.ReadInt32();
  215. irq_enable = stateStream.ReadByte();
  216. irq_counter = stateStream.ReadInt32();
  217. irq_clock = stateStream.ReadInt32();
  218. base.LoadState(stateStream);
  219. }
  220. }
  221. }