ram.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /**********************************
  2. Copyright (C) Rick Wong (Lick)
  3. Credits: Amadeus, Chishm, Cory1492, Lazy1, Pepsiman, Viruseb
  4. Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
  5. and GPLv2 (http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt) licenses.
  6. ***********************************/
  7. #include "ram.h"
  8. #include "../../src/compat.h"
  9. // Disable annoying GCC warnings.
  10. #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
  11. //===================================//
  12. // //
  13. // Device Ram Drivers ! //
  14. // //
  15. //===================================//
  16. //========================
  17. static vu16 *_sc_unlock (void)
  18. //========================
  19. {
  20. *(vu16*)0x9FFFFFE = 0xA55A;
  21. *(vu16*)0x9FFFFFE = 0xA55A;
  22. *(vu16*)0x9FFFFFE = 0x5; // RAM_RW
  23. *(vu16*)0x9FFFFFE = 0x5;
  24. return (vu16*)0x8000000;
  25. }
  26. //========================
  27. static void _sc_lock (void)
  28. //========================
  29. {
  30. *(vu16*)0x9FFFFFE = 0xA55A;
  31. *(vu16*)0x9FFFFFE = 0xA55A;
  32. *(vu16*)0x9FFFFFE = 0x3; // MEDIA
  33. *(vu16*)0x9FFFFFE = 0x3;
  34. }
  35. //========================
  36. static vu16 *_m3_unlock (void)
  37. //========================
  38. {
  39. u32 mode = 0x00400006; // RAM_RW
  40. vu16 tmp;
  41. tmp = *(vu16*)0x08E00002;
  42. tmp = *(vu16*)0x0800000E;
  43. tmp = *(vu16*)0x08801FFC;
  44. tmp = *(vu16*)0x0800104A;
  45. tmp = *(vu16*)0x08800612;
  46. tmp = *(vu16*)0x08000000;
  47. tmp = *(vu16*)0x08801B66;
  48. tmp = *(vu16*)(0x08000000 + (mode << 1));
  49. tmp = *(vu16*)0x0800080E;
  50. tmp = *(vu16*)0x08000000;
  51. tmp = *(vu16*)0x080001E4;
  52. tmp = *(vu16*)0x080001E4;
  53. tmp = *(vu16*)0x08000188;
  54. tmp = *(vu16*)0x08000188;
  55. return (vu16*)0x8000000;
  56. }
  57. //========================
  58. static void _m3_lock (void)
  59. //========================
  60. {
  61. u32 mode = 0x00400003; // MEDIA
  62. vu16 tmp;
  63. tmp = *(vu16*)0x08E00002;
  64. tmp = *(vu16*)0x0800000E;
  65. tmp = *(vu16*)0x08801FFC;
  66. tmp = *(vu16*)0x0800104A;
  67. tmp = *(vu16*)0x08800612;
  68. tmp = *(vu16*)0x08000000;
  69. tmp = *(vu16*)0x08801B66;
  70. tmp = *(vu16*)(0x08000000 + (mode << 1));
  71. tmp = *(vu16*)0x0800080E;
  72. tmp = *(vu16*)0x08000000;
  73. tmp = *(vu16*)0x080001E4;
  74. tmp = *(vu16*)0x080001E4;
  75. tmp = *(vu16*)0x08000188;
  76. tmp = *(vu16*)0x08000188;
  77. }
  78. //========================
  79. static vu16 *_opera_unlock (void)
  80. //========================
  81. {
  82. *(vu16*)0x8240000 = 1;
  83. return (vu16*)0x9000000;
  84. }
  85. //========================
  86. static void _opera_lock (void)
  87. //========================
  88. {
  89. *(vu16*)0x8240000 = 0;
  90. }
  91. //========================
  92. static vu16 *_g6_unlock (void)
  93. //========================
  94. {
  95. u32 mode = 6; // RAM_RW
  96. vu16 tmp;
  97. tmp = *(vu16*)0x09000000;
  98. tmp = *(vu16*)0x09FFFFE0;
  99. tmp = *(vu16*)0x09FFFFEC;
  100. tmp = *(vu16*)0x09FFFFEC;
  101. tmp = *(vu16*)0x09FFFFEC;
  102. tmp = *(vu16*)0x09FFFFFC;
  103. tmp = *(vu16*)0x09FFFFFC;
  104. tmp = *(vu16*)0x09FFFFFC;
  105. tmp = *(vu16*)0x09FFFF4A;
  106. tmp = *(vu16*)0x09FFFF4A;
  107. tmp = *(vu16*)0x09FFFF4A;
  108. tmp = *(vu16*)(0x09200000 + (mode << 1));
  109. tmp = *(vu16*)0x09FFFFF0;
  110. tmp = *(vu16*)0x09FFFFE8;
  111. return (vu16*)0x8000000;
  112. }
  113. //========================
  114. static void _g6_lock (void)
  115. //========================
  116. {
  117. u32 mode = 3; // MEDIA
  118. vu16 tmp;
  119. tmp = *(vu16*)0x09000000;
  120. tmp = *(vu16*)0x09FFFFE0;
  121. tmp = *(vu16*)0x09FFFFEC;
  122. tmp = *(vu16*)0x09FFFFEC;
  123. tmp = *(vu16*)0x09FFFFEC;
  124. tmp = *(vu16*)0x09FFFFFC;
  125. tmp = *(vu16*)0x09FFFFFC;
  126. tmp = *(vu16*)0x09FFFFFC;
  127. tmp = *(vu16*)0x09FFFF4A;
  128. tmp = *(vu16*)0x09FFFF4A;
  129. tmp = *(vu16*)0x09FFFF4A;
  130. tmp = *(vu16*)(0x09200000 + (mode << 1));
  131. tmp = *(vu16*)0x09FFFFF0;
  132. tmp = *(vu16*)0x09FFFFE8;
  133. }
  134. //========================
  135. static vu16 *_ez_unlock (void)
  136. //========================
  137. {
  138. *(vu16*)0x9FE0000 = 0xD200; // SD_Disable
  139. *(vu16*)0x8000000 = 0x1500;
  140. *(vu16*)0x8020000 = 0xD200;
  141. *(vu16*)0x8040000 = 0x1500;
  142. *(vu16*)0x9400000 = 0;
  143. *(vu16*)0x9C40000 = 0xD200;
  144. *(vu16*)0x9FC0000 = 0x1500;
  145. *(vu16*)0x9FE0000 = 0xD200; // SetRompage (OS mode)
  146. *(vu16*)0x8000000 = 0x1500;
  147. *(vu16*)0x8020000 = 0xD200;
  148. *(vu16*)0x8040000 = 0x1500;
  149. *(vu16*)0x9880000 = 0x8000;
  150. *(vu16*)0x9FC0000 = 0x1500;
  151. *(vu16*)0x9FE0000 = 0xD200; // OpenNorWrite
  152. *(vu16*)0x8000000 = 0x1500;
  153. *(vu16*)0x8020000 = 0xD200;
  154. *(vu16*)0x8040000 = 0x1500;
  155. *(vu16*)0x9C40000 = 0x1500;
  156. *(vu16*)0x9FC0000 = 0x1500;
  157. return (vu16*)0x8400000;
  158. }
  159. //========================
  160. static void _ez_lock (void)
  161. //========================
  162. {
  163. *(vu16*)0x9FE0000 = 0xD200; // CloseNorWrite
  164. *(vu16*)0x8000000 = 0x1500;
  165. *(vu16*)0x8020000 = 0xD200;
  166. *(vu16*)0x8040000 = 0x1500;
  167. *(vu16*)0x9C40000 = 0xD200;
  168. *(vu16*)0x9FC0000 = 0x1500;
  169. *(vu16*)0x9FE0000 = 0xD200; // SetRompage (game mode)
  170. *(vu16*)0x8000000 = 0x1500;
  171. *(vu16*)0x8020000 = 0xD200;
  172. *(vu16*)0x8040000 = 0x1500;
  173. *(vu16*)0x9880000 = 0x0000;
  174. *(vu16*)0x9FC0000 = 0x1500;
  175. *(vu16*)0x9FE0000 = 0xD200; // SD_Enable
  176. *(vu16*)0x8000000 = 0x1500;
  177. *(vu16*)0x8020000 = 0xD200;
  178. *(vu16*)0x8040000 = 0x1500;
  179. *(vu16*)0x9400000 = 1;
  180. *(vu16*)0x9C40000 = 0x1500;
  181. *(vu16*)0x9FC0000 = 0x1500;
  182. }
  183. //===================================//
  184. // //
  185. // Ram API ! //
  186. // //
  187. //===================================//
  188. static vu16* (*_unlock) (void) = 0;
  189. static void (*_lock) (void) = 0;
  190. static u32 _size = 0;
  191. static RAM_TYPE _type = DETECT_RAM;
  192. const char *_types[] = {"Unknown", "Supercard", "M3", "Opera", "G6", "EZ"};
  193. //==========================================================
  194. static bool _ram_test (void)
  195. //==========================================================
  196. {
  197. vu16 *ram = _unlock();
  198. ram[0] = 0x1234;
  199. if(ram[0] == 0x1234) // test writability
  200. {
  201. _lock();
  202. ram[0] = 0x4321;
  203. if(ram[0] != 0x4321) // test non-writability
  204. {
  205. return true;
  206. }
  207. }
  208. return false;
  209. }
  210. //==========================================================
  211. static void _ram_precalc_size (void)
  212. //==========================================================
  213. {
  214. vu16 *ram;
  215. if(_unlock == 0 || _lock == 0)
  216. return;
  217. ram = _unlock();
  218. _size = 0;
  219. ram[0] = 0x2468;
  220. while(ram[_size] == 0x2468)
  221. {
  222. ram[_size] = 0;
  223. _size += 512;
  224. ram[_size] = 0x2468;
  225. }
  226. _size<<=1;
  227. _lock();
  228. }
  229. //==========================================================
  230. bool ram_init (RAM_TYPE type)
  231. //==========================================================
  232. {
  233. sysSetBusOwners(BUS_OWNER_ARM9, BUS_OWNER_ARM9);
  234. switch(type)
  235. {
  236. case SC_RAM:
  237. {
  238. _unlock = _sc_unlock;
  239. _lock = _sc_lock;
  240. _type = SC_RAM;
  241. }
  242. break;
  243. case M3_RAM:
  244. {
  245. _unlock = _m3_unlock;
  246. _lock = _m3_lock;
  247. _type = M3_RAM;
  248. }
  249. break;
  250. case OPERA_RAM:
  251. {
  252. _unlock = _opera_unlock;
  253. _lock = _opera_lock;
  254. _type = OPERA_RAM;
  255. }
  256. break;
  257. case G6_RAM:
  258. {
  259. _unlock = _g6_unlock;
  260. _lock = _g6_lock;
  261. _type = G6_RAM;
  262. }
  263. break;
  264. case EZ_RAM:
  265. {
  266. _unlock = _ez_unlock;
  267. _lock = _ez_lock;
  268. _type = EZ_RAM;
  269. }
  270. break;
  271. case DETECT_RAM:
  272. default:
  273. {
  274. // try ez
  275. _unlock = _ez_unlock;
  276. _lock = _ez_lock;
  277. _type = EZ_RAM;
  278. if(_ram_test())
  279. {
  280. break;
  281. }
  282. // try supercard
  283. _unlock = _sc_unlock;
  284. _lock = _sc_lock;
  285. _type = SC_RAM;
  286. if(_ram_test())
  287. {
  288. break;
  289. }
  290. // try m3
  291. _unlock = _m3_unlock;
  292. _lock = _m3_lock;
  293. _type = M3_RAM;
  294. if(_ram_test())
  295. {
  296. break;
  297. }
  298. // try opera
  299. _unlock = _opera_unlock;
  300. _lock = _opera_lock;
  301. _type = OPERA_RAM;
  302. if(_ram_test())
  303. {
  304. break;
  305. }
  306. // try g6
  307. _unlock = _g6_unlock;
  308. _lock = _g6_lock;
  309. _type = G6_RAM;
  310. if(_ram_test())
  311. {
  312. break;
  313. }
  314. // fail
  315. _unlock = 0;
  316. _lock = 0;
  317. _type = DETECT_RAM;
  318. return false;
  319. }
  320. break;
  321. }
  322. _ram_precalc_size();
  323. return true;
  324. }
  325. //==========================================================
  326. RAM_TYPE ram_type (void)
  327. //==========================================================
  328. {
  329. return _type;
  330. }
  331. //==========================================================
  332. const char* ram_type_string (void)
  333. //==========================================================
  334. {
  335. return _types[(int)_type];
  336. }
  337. //==========================================================
  338. u32 ram_size (void)
  339. //==========================================================
  340. {
  341. return _size;
  342. }
  343. //==========================================================
  344. vu16* ram_unlock (void)
  345. //==========================================================
  346. {
  347. sysSetBusOwners(BUS_OWNER_ARM9, BUS_OWNER_ARM9);
  348. if(_unlock)
  349. return _unlock();
  350. return 0;
  351. }
  352. //==========================================================
  353. void ram_lock (void)
  354. //==========================================================
  355. {
  356. sysSetBusOwners(BUS_OWNER_ARM9, BUS_OWNER_ARM9);
  357. if(_lock)
  358. _lock();
  359. }
  360. //==========================================================
  361. void ram_turbo (bool enable)
  362. //==========================================================
  363. {
  364. if(enable)
  365. REG_EXMEMCNT |= 0x001A;
  366. else
  367. REG_EXMEMCNT &= ~0x001A;
  368. }