mmc1.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*
  2. * MMC1 Mapper - The peTI-NESulator Project
  3. * mmc1.h
  4. *
  5. * Created by Manoël Trapier.
  6. * Copyright (c) 2002-2019 986-Studio.
  7. *
  8. */
  9. uint8_t MMC1_reg0;
  10. uint8_t MMC1_reg1;
  11. uint8_t MMC1_reg2;
  12. uint8_t MMC1_reg3;
  13. uint8_t mmc1_CurrentBank;
  14. #define MMC1_R0_MIRROR 0x01
  15. #define MMC1_R0_ONESCREEN 0x02
  16. #define MMC1_R0_PRGAREA 0x04
  17. #define MMC1_R0_PRGSIZE 0x08
  18. #define MMC1_R0_VROMSW 0x10
  19. #define MMC1_R0_RESET 0x80
  20. #define MMC1_R1_VROMB1 0x0F
  21. #define MMC1_R1_256KSEL 0x10
  22. #define MMC1_R1_RESET 0x80
  23. #define MMC1_R2_VROMB2 0x0F
  24. #define MMC1_R2_256KSEL 0x10
  25. #define MMC1_R2_RESET 0x80
  26. #define MMC1_R3_VROMB2 0x0F
  27. #define MMC1_R3_SAVECE 0x10
  28. #define MMC1_R3_RESET 0x80
  29. #define MMC1_REG0_DEFAULT MMC1_R0_PRGSIZE | MMC1_R0_PRGAREA
  30. #define MMC1_REG1_DEFAULT 0
  31. #define MMC1_REG2_DEFAULT 0
  32. #define MMC1_REG3_DEFAULT 0
  33. void mmc1_MapperWriteReg0(register uint8_t Addr, register uint8_t Value);
  34. void mmc1_MapperWriteReg1(register uint8_t Addr, register uint8_t Value);
  35. void mmc1_MapperWriteReg2(register uint8_t Addr, register uint8_t Value);
  36. void mmc1_MapperWriteReg3(register uint8_t Addr, register uint8_t Value);
  37. void mmc1_MapperDump(FILE *fp)
  38. {
  39. fprintf(fp, "MMC1: r0:0x%02X r1:0x%02X r2:0x%02X r3:0x%02X\n", MMC1_reg0, MMC1_reg1, MMC1_reg2, MMC1_reg3);
  40. }
  41. int mmc1_InitMapper(NesCart *cart)
  42. {
  43. int i;
  44. MMC1_reg0 = MMC1_REG0_DEFAULT;
  45. MMC1_reg1 = MMC1_REG1_DEFAULT;
  46. MMC1_reg2 = MMC1_REG2_DEFAULT;
  47. MMC1_reg3 = MMC1_REG3_DEFAULT;
  48. set_prom_bank_16k(0x8000, 0);
  49. set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
  50. mmc1_CurrentBank = 0;
  51. if (cart->VROMSize > 0)
  52. {
  53. set_vrom_bank_4k(0x0000, 0);
  54. }
  55. /* Mapper should register itself for write hook */
  56. for (i = 0x80 ; i < 0xA0 ; i++)
  57. {
  58. set_page_wr_hook(i, mmc1_MapperWriteReg0);
  59. set_page_writeable(i, true);
  60. }
  61. for (i = 0xA0 ; i < 0xC0 ; i++)
  62. {
  63. set_page_wr_hook(i, mmc1_MapperWriteReg1);
  64. set_page_writeable(i, true);
  65. }
  66. for (i = 0xC0 ; i < 0xE0 ; i++)
  67. {
  68. set_page_wr_hook(i, mmc1_MapperWriteReg2);
  69. set_page_writeable(i, true);
  70. }
  71. for (i = 0xE0 ; i < 0x100 ; i++)
  72. {
  73. set_page_wr_hook(i, mmc1_MapperWriteReg3);
  74. set_page_writeable(i, true);
  75. }
  76. return 0;
  77. }
  78. /*
  79. * Reg 0
  80. * 8 : 1000
  81. * 9 : 1001
  82. *
  83. * Reg 1
  84. * A : 1010
  85. * B : 1011
  86. *
  87. * Reg 2
  88. * C : 1100
  89. * D : 1101
  90. *
  91. * Reg 3
  92. * E : 1110
  93. * F : 1111
  94. *
  95. * ((Addr & 0x6000) >> 13) <- port number
  96. */
  97. #define MMC1_GetReg(a) ((a & 0x6000) >> 13)
  98. #define MMC1_GetBit(v) (v & 0x01)
  99. #define MMC1_AddBit(b, v) ( ( b & ~(1 << Bit)) | (v << Bit) )
  100. void mmc1_ApplyReg0Mod()
  101. {
  102. static uint8_t OldSwitchArea = MMC1_R0_PRGAREA;
  103. //console_printf(Console_Default, "Change to reg0 done ! (0x%x)\n\tMirror flag : %d\n\tOneScreen Flag : %d\n\tPRG Size : %d\n\tPRG Area : %d\n\tVROM Switch size : %d\n", MMC1_reg0, MMC1_reg0 & MMC1_R0_MIRROR, MMC1_reg0 & MMC1_R0_ONESCREEN, MMC1_reg0 & MMC1_R0_PRGAREA, MMC1_reg0 & MMC1_R0_PRGSIZE, MMC1_reg0 & MMC1_R0_VROMSW);
  104. switch (MMC1_reg0 & 0x03)
  105. {
  106. case 0:
  107. ppu_setScreenMode(PPU_SCMODE_SINGLE);
  108. ppu_setSingleScreen(PPU_SCREEN_000);
  109. break;
  110. case 1:
  111. ppu_setScreenMode(PPU_SCMODE_SINGLE);
  112. ppu_setSingleScreen(PPU_SCREEN_400);
  113. break;
  114. case 2:
  115. ppu_setScreenMode(PPU_SCMODE_NORMAL);
  116. ppu_setMirroring(PPU_MIRROR_VERTICAL);
  117. break;
  118. case 3:
  119. ppu_setScreenMode(PPU_SCMODE_NORMAL);
  120. ppu_setMirroring(PPU_MIRROR_HORIZTAL);
  121. break;
  122. }
  123. if ((OldSwitchArea != (MMC1_reg0 & MMC1_R0_PRGAREA)) && ((MMC1_reg0 & MMC1_R0_PRGSIZE) != 0))
  124. {
  125. if ((MMC1_reg0 & MMC1_R0_PRGAREA) != 0)
  126. {
  127. /* 0x8000 area */
  128. set_prom_bank_16k(0x8000, mmc1_CurrentBank);
  129. set_prom_bank_16k(0xC000, GETLAST16KBANK(Cart));
  130. }
  131. else
  132. {
  133. /* 0xC000 area */
  134. set_prom_bank_16k(0x8000, 0);
  135. set_prom_bank_16k(0xC000, mmc1_CurrentBank);
  136. }
  137. OldSwitchArea = (MMC1_reg0 & MMC1_R0_PRGAREA);
  138. }
  139. }
  140. int VROMBankNb;
  141. uint8_t Bit = 0;
  142. uint8_t BitBuf = 0;
  143. void mmc1_MapperWriteReg0(register uint8_t Addr, register uint8_t Value)
  144. {
  145. if (Value & 0x80)
  146. {
  147. MMC1_reg0 = MMC1_REG0_DEFAULT;
  148. console_printf(Console_Default, "MMC1: Reg0 Reset occurred !\n");
  149. mmc1_ApplyReg0Mod();
  150. }
  151. else
  152. {
  153. if (Bit < 4)
  154. {
  155. /* Haven't written the 5 bits yet */
  156. BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
  157. Bit++;
  158. }
  159. else
  160. {
  161. BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
  162. Bit = 0;
  163. MMC1_reg0 = BitBuf;
  164. mmc1_ApplyReg0Mod();
  165. }
  166. }
  167. }
  168. void mmc1_MapperWriteReg1(register uint8_t Addr, register uint8_t Value)
  169. {
  170. if (Value & 0x80)
  171. {
  172. MMC1_reg1 = MMC1_REG1_DEFAULT;
  173. console_printf(Console_Default, "MMC1: Reg1 Reset occurred !\n");
  174. }
  175. else
  176. {
  177. if (Bit < 4)
  178. {
  179. /* Haven't written the 5 bits yet */
  180. BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
  181. Bit++;
  182. }
  183. else
  184. {
  185. BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
  186. Bit = 0;
  187. MMC1_reg1 = BitBuf;
  188. VROMBankNb = (MMC1_reg1 /* & MMC1_R1_VROMB1 */ );
  189. if (Cart->VROMSize == 0)
  190. {
  191. console_printf(Console_Default, "Try to change VROM but with didn't have any VROM ! [%04X]\n",
  192. VROMBankNb);
  193. return;
  194. }
  195. if ((MMC1_reg0 & MMC1_R0_VROMSW) != 0)
  196. {
  197. /* 4K vram */
  198. //console_printf(Console_Default, "Switching VROM at 0x0000 to 4k bank %d\n", VROMBankNb);
  199. set_vrom_bank_4k(0x0000, VROMBankNb);
  200. }
  201. else
  202. {
  203. /* 8K vram */
  204. //console_printf(Console_Default, "Switching VROM at 0x0000 to 8k bank %d\n", VROMBankNb>>1);
  205. set_vrom_bank_8k(0x0000, VROMBankNb >> 1);
  206. }
  207. }
  208. }
  209. }
  210. void mmc1_MapperWriteReg2(register uint8_t Addr, register uint8_t Value)
  211. {
  212. if (Value & 0x80)
  213. {
  214. MMC1_reg2 = MMC1_REG2_DEFAULT;
  215. console_printf(Console_Default, "MMC1: Reg2 Reset occurred !\n");
  216. }
  217. else
  218. {
  219. if (Bit < 4)
  220. {
  221. /* Haven't written the 5 bits yet */
  222. BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
  223. Bit++;
  224. }
  225. else
  226. {
  227. BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
  228. Bit = 0;
  229. MMC1_reg2 = BitBuf;
  230. VROMBankNb = (MMC1_reg2 /* & MMC1_R2_VROMB2 */ );
  231. //console_printf(Console_Default, "Want to switch VROM at 0x1000 to 4k bank %d\n", VROMBankNb);
  232. if (Cart->VROMSize == 0)
  233. {
  234. //console_printf(Console_Default, ": No\n");
  235. return;
  236. }
  237. if ((MMC1_reg0 & MMC1_R0_VROMSW) != 0)
  238. {
  239. /* 4K vram */
  240. //console_printf(Console_Default, "Switching VROM at 0x1000 to 4k bank %d\n", VROMBankNb);
  241. set_vrom_bank_4k(0x1000, VROMBankNb);
  242. }
  243. else
  244. {
  245. /* 8K vram */
  246. // console_printf(Console_Default, "Switching VROM at 0x1000 to 8k bank %d\n", VROMBankNb>>1);
  247. // set_vrom_bank_8k(0x1000,VROMBankNb>>1);
  248. }
  249. }
  250. }
  251. }
  252. void mmc1_MapperWriteReg3(register uint8_t Addr, register uint8_t Value)
  253. {
  254. if (Value & 0x80)
  255. {
  256. MMC1_reg3 = MMC1_REG3_DEFAULT;
  257. console_printf(Console_Default, "MMC1: Reg3 Reset occurred !\n");
  258. }
  259. else
  260. {
  261. if (Bit < 4)
  262. {
  263. /* Haven't written the 5 bits yet */
  264. BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
  265. Bit++;
  266. }
  267. else
  268. {
  269. BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
  270. Bit = 0;
  271. MMC1_reg3 = BitBuf;
  272. if (MMC1_reg3 << 14 > Cart->PROMSize)
  273. {
  274. return;
  275. }
  276. if ((MMC1_reg0 & MMC1_R0_PRGSIZE) != 0)
  277. {
  278. /* 16K Switch */
  279. if ((MMC1_reg0 & MMC1_R0_PRGAREA) != 0)
  280. {
  281. /* 0x8000 switch */
  282. set_prom_bank_16k(0x8000, MMC1_reg3);
  283. //console_printf(Console_Default, "LowBank is now %d ( 0x%p )\n", MMC1_reg3, mLBank);
  284. }
  285. else
  286. {
  287. /* 0xC000 switch */
  288. set_prom_bank_16k(0xC000, MMC1_reg3);
  289. //console_printf(Console_Default, "HighBank is now %d ( 0x%p )\n", MMC1_reg3, mUBank);
  290. }
  291. }
  292. else
  293. {
  294. /* 32K Switch */
  295. set_prom_bank_32k(0x8000, MMC1_reg3 >> 1);
  296. }
  297. if ((MMC1_reg3 & MMC1_R3_SAVECE) != 0)
  298. {
  299. unmap_sram();
  300. }
  301. else
  302. {
  303. map_sram();
  304. }
  305. }
  306. }
  307. }
  308. //console_printf(Console_Default, "MMC1: Debug (Reg:%d,Val:0x%02X,reg0:0x%02X,reg1:0x%02X,reg2:0x%02X,reg3:0x%02X)\n", MMC1_GetReg(Addr), Value, MMC1_reg0, MMC1_reg1, MMC1_reg2, MMC1_reg3);