mmc1.c 9.7 KB

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