mmc1.h 10.0 KB

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