memory.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561
  1. /*
  2. * PicoDrive
  3. * (C) notaz, 2009,2010
  4. *
  5. * This work is licensed under the terms of MAME license.
  6. * See COPYING file in the top-level directory.
  7. *
  8. * SH2 addr lines:
  9. * iii. .cc. ..xx * // Internal, Cs, x
  10. *
  11. * Register map:
  12. * a15100 F....... R.....EA F.....AC N...VHMP 4000 // Fm Ren nrEs Aden Cart heN V H cMd Pwm
  13. * a15102 ........ ......SM ? 4002 // intS intM
  14. * a15104 ........ ......10 ........ hhhhhhhh 4004 // bk1 bk0 Hint
  15. * a15106 F....... .....SDR UE...... .....SDR 4006 // Full 68S Dma Rv fUll[fb] Empt[fb]
  16. * a15108 (32bit DREQ src) 4008
  17. * a1510c (32bit DREQ dst) 400c
  18. * a15110 llllllll llllll00 4010 // DREQ Len
  19. * a15112 (16bit FIFO reg) 4012
  20. * a15114 ? (16bit VRES clr) 4014
  21. * a15116 ? (16bit Vint clr) 4016
  22. * a15118 ? (16bit Hint clr) 4018
  23. * a1511a ........ .......C (16bit CMD clr) 401a // Cm
  24. * a1511c ? (16bit PWM clr) 401c
  25. * a1511e ? ? 401e
  26. * a15120 (16 bytes comm) 2020
  27. * a15130 (PWM) 2030
  28. */
  29. #include "../pico_int.h"
  30. #include "../memory.h"
  31. #ifdef DRC_SH2
  32. #include "../../cpu/sh2/compiler.h"
  33. #endif
  34. #if 0
  35. #undef ash2_end_run
  36. #undef SekEndRun
  37. #define ash2_end_run(x)
  38. #define SekEndRun(x)
  39. #endif
  40. static const char str_mars[] = "MARS";
  41. void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
  42. struct Pico32xMem *Pico32xMem;
  43. static void bank_switch(int b);
  44. // poll detection
  45. #define POLL_THRESHOLD 6
  46. struct poll_det {
  47. u32 addr, cycles, cyc_max;
  48. int cnt, flag;
  49. };
  50. static struct poll_det m68k_poll, sh2_poll[2];
  51. static int p32x_poll_detect(struct poll_det *pd, u32 a, u32 cycles, int is_vdp)
  52. {
  53. int ret = 0, flag = pd->flag;
  54. if (is_vdp)
  55. flag <<= 3;
  56. if (a - 2 <= pd->addr && pd->addr <= a + 2 && cycles - pd->cycles <= pd->cyc_max) {
  57. pd->cnt++;
  58. if (pd->cnt > POLL_THRESHOLD) {
  59. if (!(Pico32x.emu_flags & flag)) {
  60. elprintf(EL_32X, "%s poll addr %08x, cyc %u",
  61. flag & (P32XF_68KPOLL|P32XF_68KVPOLL) ? "m68k" :
  62. (flag & (P32XF_MSH2POLL|P32XF_MSH2VPOLL) ? "msh2" : "ssh2"), a, cycles - pd->cycles);
  63. ret = 1;
  64. }
  65. Pico32x.emu_flags |= flag;
  66. }
  67. }
  68. else {
  69. pd->cnt = 0;
  70. pd->addr = a;
  71. }
  72. pd->cycles = cycles;
  73. return ret;
  74. }
  75. static int p32x_poll_undetect(struct poll_det *pd, int is_vdp)
  76. {
  77. int ret = 0, flag = pd->flag;
  78. if (is_vdp)
  79. flag <<= 3; // VDP only
  80. else
  81. flag |= flag << 3; // both
  82. if (Pico32x.emu_flags & flag) {
  83. elprintf(EL_32X, "poll %02x -> %02x", Pico32x.emu_flags, Pico32x.emu_flags & ~flag);
  84. ret = 1;
  85. }
  86. Pico32x.emu_flags &= ~flag;
  87. pd->addr = pd->cnt = 0;
  88. return ret;
  89. }
  90. void p32x_poll_event(int cpu_mask, int is_vdp)
  91. {
  92. if (cpu_mask & 1)
  93. p32x_poll_undetect(&sh2_poll[0], is_vdp);
  94. if (cpu_mask & 2)
  95. p32x_poll_undetect(&sh2_poll[1], is_vdp);
  96. }
  97. // SH2 faking
  98. //#define FAKE_SH2
  99. int p32x_csum_faked;
  100. #ifdef FAKE_SH2
  101. static const u16 comm_fakevals[] = {
  102. 0x4d5f, 0x4f4b, // M_OK
  103. 0x535f, 0x4f4b, // S_OK
  104. 0x4D41, 0x5346, // MASF - Brutal Unleashed
  105. 0x5331, 0x4d31, // Darxide
  106. 0x5332, 0x4d32,
  107. 0x5333, 0x4d33,
  108. 0x0000, 0x0000, // eq for doom
  109. 0x0002, // Mortal Kombat
  110. // 0, // pad
  111. };
  112. static u32 sh2_comm_faker(u32 a)
  113. {
  114. static int f = 0;
  115. if (a == 0x28 && !p32x_csum_faked) {
  116. p32x_csum_faked = 1;
  117. return *(unsigned short *)(Pico.rom + 0x18e);
  118. }
  119. if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0]))
  120. f = 0;
  121. return comm_fakevals[f++];
  122. }
  123. #endif
  124. // DMAC handling
  125. static struct {
  126. unsigned int sar0, dar0, tcr0; // src addr, dst addr, transfer count
  127. unsigned int chcr0; // chan ctl
  128. unsigned int sar1, dar1, tcr1; // same for chan 1
  129. unsigned int chcr1;
  130. int pad[4];
  131. unsigned int dmaor;
  132. } * dmac0;
  133. static void dma_68k2sh2_do(void)
  134. {
  135. unsigned short *dreqlen = &Pico32x.regs[0x10 / 2];
  136. int i;
  137. if (dmac0->tcr0 != *dreqlen)
  138. elprintf(EL_32X|EL_ANOMALY, "tcr0 and dreq len differ: %d != %d", dmac0->tcr0, *dreqlen);
  139. // HACK: assume bus is busy and SH2 is halted
  140. // XXX: use different mechanism for this, not poll det
  141. Pico32x.emu_flags |= P32XF_MSH2POLL; // id ? P32XF_SSH2POLL : P32XF_MSH2POLL;
  142. for (i = 0; i < Pico32x.dmac_ptr && dmac0->tcr0 > 0; i++) {
  143. elprintf(EL_32X, "dmaw [%08x] %04x, left %d", dmac0->dar0, Pico32x.dmac_fifo[i], *dreqlen);
  144. p32x_sh2_write16(dmac0->dar0, Pico32x.dmac_fifo[i], &msh2);
  145. dmac0->dar0 += 2;
  146. dmac0->tcr0--;
  147. (*dreqlen)--;
  148. }
  149. Pico32x.dmac_ptr = 0; // HACK
  150. Pico32x.regs[6 / 2] &= ~P32XS_FULL;
  151. if (*dreqlen == 0)
  152. Pico32x.regs[6 / 2] &= ~P32XS_68S; // transfer complete
  153. if (dmac0->tcr0 == 0) {
  154. dmac0->chcr0 |= 2; // DMA has ended normally
  155. p32x_poll_undetect(&sh2_poll[0], 0);
  156. }
  157. }
  158. // ------------------------------------------------------------------
  159. // 68k regs
  160. static u32 p32x_reg_read16(u32 a)
  161. {
  162. a &= 0x3e;
  163. if (a == 2) // INTM, INTS
  164. return ((Pico32x.sh2irqi[0] & P32XI_CMD) >> 4) | ((Pico32x.sh2irqi[1] & P32XI_CMD) >> 3);
  165. #if 0
  166. if ((a & 0x30) == 0x20)
  167. return sh2_comm_faker(a);
  168. #else
  169. if ((a & 0x30) == 0x20) {
  170. // evil X-Men proto polls in a dbra loop and expects it to expire..
  171. static u32 dr2 = 0;
  172. if (SekDar(2) != dr2)
  173. m68k_poll.cnt = 0;
  174. dr2 = SekDar(2);
  175. if (p32x_poll_detect(&m68k_poll, a, SekCyclesDoneT(), 0)) {
  176. SekSetStop(1);
  177. SekEndTimeslice(16);
  178. }
  179. dr2 = SekDar(2);
  180. }
  181. #endif
  182. if ((a & 0x30) == 0x30)
  183. return p32x_pwm_read16(a);
  184. return Pico32x.regs[a / 2];
  185. }
  186. static void p32x_reg_write8(u32 a, u32 d)
  187. {
  188. u16 *r = Pico32x.regs;
  189. a &= 0x3f;
  190. // for things like bset on comm port
  191. m68k_poll.cnt = 0;
  192. switch (a) {
  193. case 0: // adapter ctl
  194. r[0] = (r[0] & ~P32XS_FM) | ((d << 8) & P32XS_FM);
  195. return;
  196. case 1: // adapter ctl, RES bit writeable
  197. if ((d ^ r[0]) & d & P32XS_nRES)
  198. p32x_reset_sh2s();
  199. r[0] = (r[0] & ~P32XS_nRES) | (d & P32XS_nRES);
  200. return;
  201. case 3: // irq ctl
  202. if ((d & 1) && !(Pico32x.sh2irqi[0] & P32XI_CMD)) {
  203. Pico32x.sh2irqi[0] |= P32XI_CMD;
  204. p32x_update_irls(0);
  205. SekEndRun(16);
  206. }
  207. if ((d & 2) && !(Pico32x.sh2irqi[1] & P32XI_CMD)) {
  208. Pico32x.sh2irqi[1] |= P32XI_CMD;
  209. p32x_update_irls(0);
  210. SekEndRun(16);
  211. }
  212. return;
  213. case 5: // bank
  214. d &= 7;
  215. if (r[4 / 2] != d) {
  216. r[4 / 2] = d;
  217. bank_switch(d);
  218. }
  219. return;
  220. case 7: // DREQ ctl
  221. r[6 / 2] = (r[6 / 2] & P32XS_FULL) | (d & (P32XS_68S|P32XS_DMA|P32XS_RV));
  222. return;
  223. case 0x1b: // TV
  224. r[0x1a / 2] = d;
  225. return;
  226. }
  227. if ((a & 0x30) == 0x20) {
  228. u8 *r8 = (u8 *)r;
  229. r8[a ^ 1] = d;
  230. p32x_poll_undetect(&sh2_poll[0], 0);
  231. p32x_poll_undetect(&sh2_poll[1], 0);
  232. // if some SH2 is busy waiting, it needs to see the result ASAP
  233. if (SekCyclesLeftNoMCD > 32)
  234. SekEndRun(32);
  235. return;
  236. }
  237. }
  238. static void p32x_reg_write16(u32 a, u32 d)
  239. {
  240. u16 *r = Pico32x.regs;
  241. a &= 0x3e;
  242. // for things like bset on comm port
  243. m68k_poll.cnt = 0;
  244. switch (a) {
  245. case 0x00: // adapter ctl
  246. if ((d ^ r[0]) & d & P32XS_nRES)
  247. p32x_reset_sh2s();
  248. r[0] = (r[0] & ~(P32XS_FM|P32XS_nRES)) | (d & (P32XS_FM|P32XS_nRES));
  249. return;
  250. case 0x10: // DREQ len
  251. r[a / 2] = d & ~3;
  252. return;
  253. case 0x12: // FIFO reg
  254. if (!(r[6 / 2] & P32XS_68S)) {
  255. elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?");
  256. return;
  257. }
  258. if (Pico32x.dmac_ptr < DMAC_FIFO_LEN) {
  259. Pico32x.dmac_fifo[Pico32x.dmac_ptr++] = d;
  260. if ((Pico32x.dmac_ptr & 3) == 0 && (dmac0->chcr0 & 3) == 1 && (dmac0->dmaor & 1))
  261. dma_68k2sh2_do();
  262. if (Pico32x.dmac_ptr == DMAC_FIFO_LEN)
  263. r[6 / 2] |= P32XS_FULL;
  264. }
  265. break;
  266. }
  267. // DREQ src, dst
  268. if ((a & 0x38) == 0x08) {
  269. r[a / 2] = d;
  270. return;
  271. }
  272. // comm port
  273. else if ((a & 0x30) == 0x20 && r[a / 2] != d) {
  274. r[a / 2] = d;
  275. p32x_poll_undetect(&sh2_poll[0], 0);
  276. p32x_poll_undetect(&sh2_poll[1], 0);
  277. // same as for w8
  278. if (SekCyclesLeftNoMCD > 32)
  279. SekEndRun(32);
  280. return;
  281. }
  282. // PWM
  283. else if ((a & 0x30) == 0x30) {
  284. p32x_pwm_write16(a, d);
  285. return;
  286. }
  287. p32x_reg_write8(a + 1, d);
  288. }
  289. // ------------------------------------------------------------------
  290. // VDP regs
  291. static u32 p32x_vdp_read16(u32 a)
  292. {
  293. a &= 0x0e;
  294. return Pico32x.vdp_regs[a / 2];
  295. }
  296. static void p32x_vdp_write8(u32 a, u32 d)
  297. {
  298. u16 *r = Pico32x.vdp_regs;
  299. a &= 0x0f;
  300. // for FEN checks between writes
  301. sh2_poll[0].cnt = 0;
  302. // TODO: verify what's writeable
  303. switch (a) {
  304. case 0x01:
  305. // priority inversion is handled in palette
  306. if ((r[0] ^ d) & P32XV_PRI)
  307. Pico32x.dirty_pal = 1;
  308. r[0] = (r[0] & P32XV_nPAL) | (d & 0xff);
  309. break;
  310. case 0x03: // shift (for pp mode)
  311. r[2 / 2] = d & 1;
  312. break;
  313. case 0x05: // fill len
  314. r[4 / 2] = d & 0xff;
  315. break;
  316. case 0x0b:
  317. d &= 1;
  318. Pico32x.pending_fb = d;
  319. // if we are blanking and FS bit is changing
  320. if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
  321. r[0x0a/2] ^= P32XV_FS;
  322. Pico32xSwapDRAM(d ^ 1);
  323. elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS);
  324. }
  325. break;
  326. }
  327. }
  328. static void p32x_vdp_write16(u32 a, u32 d)
  329. {
  330. a &= 0x0e;
  331. if (a == 6) { // fill start
  332. Pico32x.vdp_regs[6 / 2] = d;
  333. return;
  334. }
  335. if (a == 8) { // fill data
  336. u16 *dram = Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
  337. int len = Pico32x.vdp_regs[4 / 2] + 1;
  338. a = Pico32x.vdp_regs[6 / 2];
  339. while (len--) {
  340. dram[a] = d;
  341. a = (a & 0xff00) | ((a + 1) & 0xff);
  342. }
  343. Pico32x.vdp_regs[6 / 2] = a;
  344. Pico32x.vdp_regs[8 / 2] = d;
  345. return;
  346. }
  347. p32x_vdp_write8(a | 1, d);
  348. }
  349. // ------------------------------------------------------------------
  350. // SH2 regs
  351. static u32 p32x_sh2reg_read16(u32 a, int cpuid)
  352. {
  353. u16 *r = Pico32x.regs;
  354. a &= 0xfe; // ?
  355. switch (a) {
  356. case 0x00: // adapter/irq ctl
  357. return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0] | Pico32x.sh2irq_mask[cpuid];
  358. case 0x04: // H count (often as comm too)
  359. if (p32x_poll_detect(&sh2_poll[cpuid], a, ash2_cycles_done(), 0))
  360. ash2_end_run(8);
  361. return Pico32x.sh2_regs[4 / 2];
  362. case 0x10: // DREQ len
  363. return r[a / 2];
  364. }
  365. // DREQ src, dst
  366. if ((a & 0x38) == 0x08)
  367. return r[a / 2];
  368. // comm port
  369. if ((a & 0x30) == 0x20) {
  370. if (p32x_poll_detect(&sh2_poll[cpuid], a, ash2_cycles_done(), 0))
  371. ash2_end_run(8);
  372. return r[a / 2];
  373. }
  374. if ((a & 0x30) == 0x30) {
  375. sh2_poll[cpuid].cnt = 0;
  376. return p32x_pwm_read16(a);
  377. }
  378. return 0;
  379. }
  380. static void p32x_sh2reg_write8(u32 a, u32 d, int cpuid)
  381. {
  382. a &= 0xff;
  383. switch (a) {
  384. case 0: // FM
  385. Pico32x.regs[0] &= ~P32XS_FM;
  386. Pico32x.regs[0] |= (d << 8) & P32XS_FM;
  387. return;
  388. case 1: //
  389. Pico32x.sh2irq_mask[cpuid] = d & 0x8f;
  390. Pico32x.sh2_regs[0] &= ~0x80;
  391. Pico32x.sh2_regs[0] |= d & 0x80;
  392. p32x_update_irls(1);
  393. return;
  394. case 5: // H count
  395. Pico32x.sh2_regs[4 / 2] = d & 0xff;
  396. p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
  397. return;
  398. }
  399. if ((a & 0x30) == 0x20) {
  400. u8 *r8 = (u8 *)Pico32x.regs;
  401. r8[a ^ 1] = d;
  402. if (p32x_poll_undetect(&m68k_poll, 0))
  403. SekSetStop(0);
  404. p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
  405. return;
  406. }
  407. }
  408. static void p32x_sh2reg_write16(u32 a, u32 d, int cpuid)
  409. {
  410. a &= 0xfe;
  411. // comm
  412. if ((a & 0x30) == 0x20 && Pico32x.regs[a/2] != d) {
  413. Pico32x.regs[a / 2] = d;
  414. if (p32x_poll_undetect(&m68k_poll, 0))
  415. SekSetStop(0);
  416. p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
  417. return;
  418. }
  419. // PWM
  420. else if ((a & 0x30) == 0x30) {
  421. p32x_pwm_write16(a, d);
  422. return;
  423. }
  424. switch (a) {
  425. case 0: // FM
  426. Pico32x.regs[0] &= ~P32XS_FM;
  427. Pico32x.regs[0] |= d & P32XS_FM;
  428. break;
  429. case 0x14: Pico32x.sh2irqs &= ~P32XI_VRES; goto irls;
  430. case 0x16: Pico32x.sh2irqs &= ~P32XI_VINT; goto irls;
  431. case 0x18: Pico32x.sh2irqs &= ~P32XI_HINT; goto irls;
  432. case 0x1a: Pico32x.sh2irqi[cpuid] &= ~P32XI_CMD; goto irls;
  433. case 0x1c:
  434. Pico32x.sh2irqs &= ~P32XI_PWM;
  435. p32x_timers_do(0);
  436. goto irls;
  437. }
  438. p32x_sh2reg_write8(a | 1, d, cpuid);
  439. return;
  440. irls:
  441. p32x_update_irls(1);
  442. }
  443. // ------------------------------------------------------------------
  444. // SH2 internal peripherals
  445. // we keep them in little endian format
  446. static u32 sh2_peripheral_read8(u32 a, int id)
  447. {
  448. u8 *r = (void *)Pico32xMem->sh2_peri_regs[id];
  449. u32 d;
  450. a &= 0x1ff;
  451. d = PREG8(r, a);
  452. elprintf(EL_32X, "%csh2 peri r8 [%08x] %02x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
  453. return d;
  454. }
  455. static u32 sh2_peripheral_read16(u32 a, int id)
  456. {
  457. u16 *r = (void *)Pico32xMem->sh2_peri_regs[id];
  458. u32 d;
  459. a &= 0x1ff;
  460. d = r[(a / 2) ^ 1];
  461. elprintf(EL_32X, "%csh2 peri r16 [%08x] %04x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
  462. return d;
  463. }
  464. static u32 sh2_peripheral_read32(u32 a, int id)
  465. {
  466. u32 d;
  467. a &= 0x1fc;
  468. d = Pico32xMem->sh2_peri_regs[id][a / 4];
  469. elprintf(EL_32X, "%csh2 peri r32 [%08x] %08x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
  470. return d;
  471. }
  472. static int REGPARM(3) sh2_peripheral_write8(u32 a, u32 d, int id)
  473. {
  474. u8 *r = (void *)Pico32xMem->sh2_peri_regs[id];
  475. elprintf(EL_32X, "%csh2 peri w8 [%08x] %02x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
  476. a &= 0x1ff;
  477. PREG8(r, a) = d;
  478. // X-men SCI hack
  479. if ((a == 2 && (d & 0x20)) || // transmiter enabled
  480. (a == 4 && !(d & 0x80))) { // valid data in TDR
  481. void *oregs = Pico32xMem->sh2_peri_regs[id ^ 1];
  482. if ((PREG8(oregs, 2) & 0x50) == 0x50) { // receiver + irq enabled
  483. int level = PREG8(oregs, 0x60) >> 4;
  484. int vector = PREG8(oregs, 0x63) & 0x7f;
  485. elprintf(EL_32X, "%csh2 SCI recv irq (%d, %d)", (id ^ 1) ? 's' : 'm', level, vector);
  486. sh2_internal_irq(&sh2s[id ^ 1], level, vector);
  487. return 1;
  488. }
  489. }
  490. return 0;
  491. }
  492. static int REGPARM(3) sh2_peripheral_write16(u32 a, u32 d, int id)
  493. {
  494. u16 *r = (void *)Pico32xMem->sh2_peri_regs[id];
  495. elprintf(EL_32X, "%csh2 peri w16 [%08x] %04x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
  496. a &= 0x1ff;
  497. // evil WDT
  498. if (a == 0x80) {
  499. if ((d & 0xff00) == 0xa500) { // WTCSR
  500. PREG8(r, 0x80) = d;
  501. p32x_timers_recalc();
  502. }
  503. if ((d & 0xff00) == 0x5a00) // WTCNT
  504. PREG8(r, 0x81) = d;
  505. return 0;
  506. }
  507. r[(a / 2) ^ 1] = d;
  508. return 0;
  509. }
  510. static void sh2_peripheral_write32(u32 a, u32 d, int id)
  511. {
  512. u32 *r = Pico32xMem->sh2_peri_regs[id];
  513. elprintf(EL_32X, "%csh2 peri w32 [%08x] %08x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
  514. a &= 0x1fc;
  515. r[a / 4] = d;
  516. switch (a) {
  517. // division unit (TODO: verify):
  518. case 0x104: // DVDNT: divident L, starts divide
  519. elprintf(EL_32X, "%csh2 divide %08x / %08x", id ? 's' : 'm', d, r[0x100 / 4]);
  520. if (r[0x100 / 4]) {
  521. signed int divisor = r[0x100 / 4];
  522. r[0x118 / 4] = r[0x110 / 4] = (signed int)d % divisor;
  523. r[0x104 / 4] = r[0x11c / 4] = r[0x114 / 4] = (signed int)d / divisor;
  524. }
  525. else
  526. r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ?
  527. break;
  528. case 0x114:
  529. elprintf(EL_32X, "%csh2 divide %08x%08x / %08x @%08x",
  530. id ? 's' : 'm', r[0x110 / 4], d, r[0x100 / 4], sh2_pc(id));
  531. if (r[0x100 / 4]) {
  532. signed long long divident = (signed long long)r[0x110 / 4] << 32 | d;
  533. signed int divisor = r[0x100 / 4];
  534. // XXX: undocumented mirroring to 0x118,0x11c?
  535. r[0x118 / 4] = r[0x110 / 4] = divident % divisor;
  536. divident /= divisor;
  537. r[0x11c / 4] = r[0x114 / 4] = divident;
  538. divident >>= 31;
  539. if ((unsigned long long)divident + 1 > 1) {
  540. //elprintf(EL_32X, "%csh2 divide overflow! @%08x", id ? 's' : 'm', sh2_pc(id));
  541. r[0x11c / 4] = r[0x114 / 4] = divident > 0 ? 0x7fffffff : 0x80000000; // overflow
  542. }
  543. }
  544. else
  545. r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ?
  546. break;
  547. }
  548. if ((a == 0x1b0 || a == 0x18c) && (dmac0->chcr0 & 3) == 1 && (dmac0->dmaor & 1)) {
  549. elprintf(EL_32X, "sh2 DMA %08x -> %08x, cnt %d, chcr %04x @%06x",
  550. dmac0->sar0, dmac0->dar0, dmac0->tcr0, dmac0->chcr0, sh2_pc(id));
  551. dmac0->tcr0 &= 0xffffff;
  552. // HACK: assume 68k starts writing soon and end the timeslice
  553. ash2_end_run(16);
  554. // DREQ is only sent after first 4 words are written.
  555. // we do multiple of 4 words to avoid messing up alignment
  556. if (dmac0->sar0 == 0x20004012 && Pico32x.dmac_ptr && (Pico32x.dmac_ptr & 3) == 0) {
  557. elprintf(EL_32X, "68k -> sh2 DMA");
  558. dma_68k2sh2_do();
  559. }
  560. }
  561. }
  562. // ------------------------------------------------------------------
  563. // 32x handlers
  564. // after ADEN
  565. static u32 PicoRead8_32x_on(u32 a)
  566. {
  567. u32 d = 0;
  568. if ((a & 0xffc0) == 0x5100) { // a15100
  569. d = p32x_reg_read16(a);
  570. goto out_16to8;
  571. }
  572. if ((a & 0xfc00) != 0x5000)
  573. return PicoRead8_io(a);
  574. if ((a & 0xfff0) == 0x5180) { // a15180
  575. d = p32x_vdp_read16(a);
  576. goto out_16to8;
  577. }
  578. if ((a & 0xfe00) == 0x5200) { // a15200
  579. d = Pico32xMem->pal[(a & 0x1ff) / 2];
  580. goto out_16to8;
  581. }
  582. if ((a & 0xfffc) == 0x30ec) { // a130ec
  583. d = str_mars[a & 3];
  584. goto out;
  585. }
  586. elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc);
  587. return d;
  588. out_16to8:
  589. if (a & 1)
  590. d &= 0xff;
  591. else
  592. d >>= 8;
  593. out:
  594. elprintf(EL_32X, "m68k 32x r8 [%06x] %02x @%06x", a, d, SekPc);
  595. return d;
  596. }
  597. static u32 PicoRead16_32x_on(u32 a)
  598. {
  599. u32 d = 0;
  600. if ((a & 0xffc0) == 0x5100) { // a15100
  601. d = p32x_reg_read16(a);
  602. goto out;
  603. }
  604. if ((a & 0xfc00) != 0x5000)
  605. return PicoRead16_io(a);
  606. if ((a & 0xfff0) == 0x5180) { // a15180
  607. d = p32x_vdp_read16(a);
  608. goto out;
  609. }
  610. if ((a & 0xfe00) == 0x5200) { // a15200
  611. d = Pico32xMem->pal[(a & 0x1ff) / 2];
  612. goto out;
  613. }
  614. if ((a & 0xfffc) == 0x30ec) { // a130ec
  615. d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
  616. goto out;
  617. }
  618. elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
  619. return d;
  620. out:
  621. elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
  622. return d;
  623. }
  624. static void PicoWrite8_32x_on(u32 a, u32 d)
  625. {
  626. if ((a & 0xfc00) == 0x5000)
  627. elprintf(EL_32X, "m68k 32x w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
  628. if ((a & 0xffc0) == 0x5100) { // a15100
  629. p32x_reg_write8(a, d);
  630. return;
  631. }
  632. if ((a & 0xfc00) != 0x5000) {
  633. PicoWrite8_io(a, d);
  634. return;
  635. }
  636. if ((a & 0xfff0) == 0x5180) { // a15180
  637. p32x_vdp_write8(a, d);
  638. return;
  639. }
  640. // TODO: verify
  641. if ((a & 0xfe00) == 0x5200) { // a15200
  642. elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
  643. ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
  644. Pico32x.dirty_pal = 1;
  645. return;
  646. }
  647. elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
  648. }
  649. static void PicoWrite16_32x_on(u32 a, u32 d)
  650. {
  651. if ((a & 0xfc00) == 0x5000)
  652. elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
  653. if ((a & 0xffc0) == 0x5100) { // a15100
  654. p32x_reg_write16(a, d);
  655. return;
  656. }
  657. if ((a & 0xfc00) != 0x5000) {
  658. PicoWrite16_io(a, d);
  659. return;
  660. }
  661. if ((a & 0xfff0) == 0x5180) { // a15180
  662. p32x_vdp_write16(a, d);
  663. return;
  664. }
  665. if ((a & 0xfe00) == 0x5200) { // a15200
  666. Pico32xMem->pal[(a & 0x1ff) / 2] = d;
  667. Pico32x.dirty_pal = 1;
  668. return;
  669. }
  670. elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
  671. }
  672. // before ADEN
  673. u32 PicoRead8_32x(u32 a)
  674. {
  675. u32 d = 0;
  676. if ((a & 0xffc0) == 0x5100) { // a15100
  677. // regs are always readable
  678. d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1];
  679. goto out;
  680. }
  681. if ((a & 0xfffc) == 0x30ec) { // a130ec
  682. d = str_mars[a & 3];
  683. goto out;
  684. }
  685. elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc);
  686. return d;
  687. out:
  688. elprintf(EL_32X, "m68k 32x r8 [%06x] %02x @%06x", a, d, SekPc);
  689. return d;
  690. }
  691. u32 PicoRead16_32x(u32 a)
  692. {
  693. u32 d = 0;
  694. if ((a & 0xffc0) == 0x5100) { // a15100
  695. d = Pico32x.regs[(a & 0x3f) / 2];
  696. goto out;
  697. }
  698. if ((a & 0xfffc) == 0x30ec) { // a130ec
  699. d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
  700. goto out;
  701. }
  702. elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
  703. return d;
  704. out:
  705. elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
  706. return d;
  707. }
  708. void PicoWrite8_32x(u32 a, u32 d)
  709. {
  710. if ((a & 0xffc0) == 0x5100) { // a15100
  711. u16 *r = Pico32x.regs;
  712. elprintf(EL_32X, "m68k 32x w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
  713. a &= 0x3f;
  714. if (a == 1) {
  715. if ((d ^ r[0]) & d & P32XS_ADEN) {
  716. Pico32xStartup();
  717. r[0] &= ~P32XS_nRES; // causes reset if specified by this write
  718. r[0] |= P32XS_ADEN;
  719. p32x_reg_write8(a, d); // forward for reset processing
  720. }
  721. return;
  722. }
  723. // allow only COMM for now
  724. if ((a & 0x30) == 0x20) {
  725. u8 *r8 = (u8 *)r;
  726. r8[a ^ 1] = d;
  727. }
  728. return;
  729. }
  730. elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
  731. }
  732. void PicoWrite16_32x(u32 a, u32 d)
  733. {
  734. if ((a & 0xffc0) == 0x5100) { // a15100
  735. u16 *r = Pico32x.regs;
  736. elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
  737. a &= 0x3e;
  738. if (a == 0) {
  739. if ((d ^ r[0]) & d & P32XS_ADEN) {
  740. Pico32xStartup();
  741. r[0] &= ~P32XS_nRES; // causes reset if specified by this write
  742. r[0] |= P32XS_ADEN;
  743. p32x_reg_write16(a, d); // forward for reset processing
  744. }
  745. return;
  746. }
  747. // allow only COMM for now
  748. if ((a & 0x30) == 0x20)
  749. r[a / 2] = d;
  750. return;
  751. }
  752. elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
  753. }
  754. // -----------------------------------------------------------------
  755. // hint vector is writeable
  756. static void PicoWrite8_hint(u32 a, u32 d)
  757. {
  758. if ((a & 0xfffc) == 0x0070) {
  759. Pico32xMem->m68k_rom[a ^ 1] = d;
  760. return;
  761. }
  762. elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc);
  763. }
  764. static void PicoWrite16_hint(u32 a, u32 d)
  765. {
  766. if ((a & 0xfffc) == 0x0070) {
  767. ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
  768. return;
  769. }
  770. elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
  771. }
  772. static void bank_switch(int b)
  773. {
  774. unsigned int rs, bank;
  775. bank = b << 20;
  776. if (bank >= Pico.romsize) {
  777. elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
  778. return;
  779. }
  780. // 32X ROM (unbanked, XXX: consider mirroring?)
  781. rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
  782. rs -= bank;
  783. if (rs > 0x100000)
  784. rs = 0x100000;
  785. cpu68k_map_set(m68k_read8_map, 0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
  786. cpu68k_map_set(m68k_read16_map, 0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
  787. elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
  788. #ifdef EMU_F68K
  789. // setup FAME fetchmap
  790. for (rs = 0x90; rs < 0xa0; rs++)
  791. PicoCpuFM68k.Fetch[rs] = (u32)Pico.rom + bank - 0x900000;
  792. #endif
  793. }
  794. // -----------------------------------------------------------------
  795. // SH2
  796. // -----------------------------------------------------------------
  797. // read8
  798. static u32 sh2_read8_unmapped(u32 a, int id)
  799. {
  800. elprintf(EL_UIO, "%csh2 unmapped r8 [%08x] %02x @%06x",
  801. id ? 's' : 'm', a, 0, sh2_pc(id));
  802. return 0;
  803. }
  804. static u32 sh2_read8_cs0(u32 a, int id)
  805. {
  806. u32 d = 0;
  807. // 0x3ff00 is veridied
  808. if ((a & 0x3ff00) == 0x4000) {
  809. d = p32x_sh2reg_read16(a, id);
  810. goto out_16to8;
  811. }
  812. if ((a & 0x3ff00) == 0x4100) {
  813. d = p32x_vdp_read16(a);
  814. if (p32x_poll_detect(&sh2_poll[id], a, ash2_cycles_done(), 1))
  815. ash2_end_run(8);
  816. goto out_16to8;
  817. }
  818. // TODO: mirroring?
  819. if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
  820. return Pico32xMem->sh2_rom_m[a ^ 1];
  821. if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
  822. return Pico32xMem->sh2_rom_s[a ^ 1];
  823. if ((a & 0x3fe00) == 0x4200) {
  824. d = Pico32xMem->pal[(a & 0x1ff) / 2];
  825. goto out_16to8;
  826. }
  827. return sh2_read8_unmapped(a, id);
  828. out_16to8:
  829. if (a & 1)
  830. d &= 0xff;
  831. else
  832. d >>= 8;
  833. elprintf(EL_32X, "%csh2 r8 [%08x] %02x @%06x",
  834. id ? 's' : 'm', a, d, sh2_pc(id));
  835. return d;
  836. }
  837. static u32 sh2_read8_da(u32 a, int id)
  838. {
  839. return Pico32xMem->data_array[id][(a & 0xfff) ^ 1];
  840. }
  841. // read16
  842. static u32 sh2_read16_unmapped(u32 a, int id)
  843. {
  844. elprintf(EL_UIO, "%csh2 unmapped r16 [%08x] %04x @%06x",
  845. id ? 's' : 'm', a, 0, sh2_pc(id));
  846. return 0;
  847. }
  848. static u32 sh2_read16_cs0(u32 a, int id)
  849. {
  850. u32 d = 0;
  851. if ((a & 0x3ff00) == 0x4000) {
  852. d = p32x_sh2reg_read16(a, id);
  853. if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
  854. return d;
  855. goto out;
  856. }
  857. if ((a & 0x3ff00) == 0x4100) {
  858. d = p32x_vdp_read16(a);
  859. if (p32x_poll_detect(&sh2_poll[id], a, ash2_cycles_done(), 1))
  860. ash2_end_run(8);
  861. goto out;
  862. }
  863. if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
  864. return *(u16 *)(Pico32xMem->sh2_rom_m + a);
  865. if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
  866. return *(u16 *)(Pico32xMem->sh2_rom_s + a);
  867. if ((a & 0x3fe00) == 0x4200) {
  868. d = Pico32xMem->pal[(a & 0x1ff) / 2];
  869. goto out;
  870. }
  871. return sh2_read16_unmapped(a, id);
  872. out:
  873. elprintf(EL_32X, "%csh2 r16 [%08x] %04x @%06x",
  874. id ? 's' : 'm', a, d, sh2_pc(id));
  875. return d;
  876. }
  877. static u32 sh2_read16_da(u32 a, int id)
  878. {
  879. return ((u16 *)Pico32xMem->data_array[id])[(a & 0xfff) / 2];
  880. }
  881. static int REGPARM(3) sh2_write_ignore(u32 a, u32 d, int id)
  882. {
  883. return 0;
  884. }
  885. // write8
  886. static int REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, int id)
  887. {
  888. elprintf(EL_UIO, "%csh2 unmapped w8 [%08x] %02x @%06x",
  889. id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
  890. return 0;
  891. }
  892. static int REGPARM(3) sh2_write8_cs0(u32 a, u32 d, int id)
  893. {
  894. elprintf(EL_32X, "%csh2 w8 [%08x] %02x @%06x",
  895. id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
  896. if ((a & 0x3ff00) == 0x4100) {
  897. p32x_vdp_write8(a, d);
  898. return 0;
  899. }
  900. if ((a & 0x3ff00) == 0x4000) {
  901. p32x_sh2reg_write8(a, d, id);
  902. return 1;
  903. }
  904. return sh2_write8_unmapped(a, d, id);
  905. }
  906. /* quirk: in both normal and overwrite areas only nonzero values go through */
  907. #define sh2_write8_dramN(n) \
  908. if ((d & 0xff) != 0) { \
  909. u8 *dram = (u8 *)Pico32xMem->dram[n]; \
  910. dram[(a & 0x1ffff) ^ 1] = d; \
  911. } \
  912. return 0;
  913. static int REGPARM(3) sh2_write8_dram0(u32 a, u32 d, int id)
  914. {
  915. sh2_write8_dramN(0);
  916. }
  917. static int REGPARM(3) sh2_write8_dram1(u32 a, u32 d, int id)
  918. {
  919. sh2_write8_dramN(1);
  920. }
  921. static int REGPARM(3) sh2_write8_sdram(u32 a, u32 d, int id)
  922. {
  923. u32 a1 = a & 0x3ffff;
  924. #ifdef DRC_SH2
  925. int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
  926. if (t)
  927. sh2_drc_wcheck_ram(a, t, id);
  928. #endif
  929. Pico32xMem->sdram[a1 ^ 1] = d;
  930. return 0;
  931. }
  932. static int REGPARM(3) sh2_write8_da(u32 a, u32 d, int id)
  933. {
  934. u32 a1 = a & 0xfff;
  935. #ifdef DRC_SH2
  936. int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
  937. if (t)
  938. sh2_drc_wcheck_da(a, t, id);
  939. #endif
  940. Pico32xMem->data_array[id][a1 ^ 1] = d;
  941. return 0;
  942. }
  943. // write16
  944. static int REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, int id)
  945. {
  946. elprintf(EL_UIO, "%csh2 unmapped w16 [%08x] %04x @%06x",
  947. id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
  948. return 0;
  949. }
  950. static int REGPARM(3) sh2_write16_cs0(u32 a, u32 d, int id)
  951. {
  952. if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
  953. elprintf(EL_32X, "%csh2 w16 [%08x] %04x @%06x",
  954. id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
  955. if ((a & 0x3ff00) == 0x4100) {
  956. sh2_poll[id].cnt = 0; // for poll before VDP accesses
  957. p32x_vdp_write16(a, d);
  958. return 0;
  959. }
  960. if ((a & 0x3fe00) == 0x4200) {
  961. Pico32xMem->pal[(a & 0x1ff) / 2] = d;
  962. Pico32x.dirty_pal = 1;
  963. return 0;
  964. }
  965. if ((a & 0x3ff00) == 0x4000) {
  966. p32x_sh2reg_write16(a, d, id);
  967. return 1;
  968. }
  969. return sh2_write16_unmapped(a, d, id);
  970. }
  971. #define sh2_write16_dramN(n) \
  972. u16 *pd = &Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \
  973. if (!(a & 0x20000)) { \
  974. *pd = d; \
  975. return 0; \
  976. } \
  977. /* overwrite */ \
  978. if (!(d & 0xff00)) d |= *pd & 0xff00; \
  979. if (!(d & 0x00ff)) d |= *pd & 0x00ff; \
  980. *pd = d; \
  981. return 0
  982. static int REGPARM(3) sh2_write16_dram0(u32 a, u32 d, int id)
  983. {
  984. sh2_write16_dramN(0);
  985. }
  986. static int REGPARM(3) sh2_write16_dram1(u32 a, u32 d, int id)
  987. {
  988. sh2_write16_dramN(1);
  989. }
  990. static int REGPARM(3) sh2_write16_sdram(u32 a, u32 d, int id)
  991. {
  992. u32 a1 = a & 0x3ffff;
  993. #ifdef DRC_SH2
  994. int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
  995. if (t)
  996. sh2_drc_wcheck_ram(a, t, id);
  997. #endif
  998. ((u16 *)Pico32xMem->sdram)[a1 / 2] = d;
  999. return 0;
  1000. }
  1001. static int REGPARM(3) sh2_write16_da(u32 a, u32 d, int id)
  1002. {
  1003. u32 a1 = a & 0xfff;
  1004. #ifdef DRC_SH2
  1005. int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
  1006. if (t)
  1007. sh2_drc_wcheck_da(a, t, id);
  1008. #endif
  1009. ((u16 *)Pico32xMem->data_array[id])[a1 / 2] = d;
  1010. return 0;
  1011. }
  1012. typedef struct {
  1013. uptr addr; // stores (membase >> 1) or ((handler >> 1) | (1<<31))
  1014. u32 mask;
  1015. } sh2_memmap;
  1016. typedef u32 (sh2_read_handler)(u32 a, int id);
  1017. typedef int REGPARM(3) (sh2_write_handler)(u32 a, u32 d, int id);
  1018. #define SH2MAP_ADDR2OFFS_R(a) \
  1019. ((((a) >> 25) & 3) | (((a) >> 27) & 0x1c))
  1020. #define SH2MAP_ADDR2OFFS_W(a) \
  1021. ((u32)(a) >> SH2_WRITE_SHIFT)
  1022. u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2)
  1023. {
  1024. const sh2_memmap *sh2_map = sh2->read8_map;
  1025. uptr p;
  1026. sh2_map += SH2MAP_ADDR2OFFS_R(a);
  1027. p = sh2_map->addr;
  1028. if (map_flag_set(p))
  1029. return ((sh2_read_handler *)(p << 1))(a, sh2->is_slave);
  1030. else
  1031. return *(u8 *)((p << 1) + ((a & sh2_map->mask) ^ 1));
  1032. }
  1033. u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
  1034. {
  1035. const sh2_memmap *sh2_map = sh2->read16_map;
  1036. uptr p;
  1037. sh2_map += SH2MAP_ADDR2OFFS_R(a);
  1038. p = sh2_map->addr;
  1039. if (map_flag_set(p))
  1040. return ((sh2_read_handler *)(p << 1))(a, sh2->is_slave);
  1041. else
  1042. return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
  1043. }
  1044. u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
  1045. {
  1046. const sh2_memmap *sh2_map = sh2->read16_map;
  1047. sh2_read_handler *handler;
  1048. u32 offs;
  1049. uptr p;
  1050. offs = SH2MAP_ADDR2OFFS_R(a);
  1051. sh2_map += offs;
  1052. p = sh2_map->addr;
  1053. if (!map_flag_set(p)) {
  1054. // XXX: maybe 32bit access instead with ror?
  1055. u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
  1056. return (pd[0] << 16) | pd[1];
  1057. }
  1058. if (offs == 0x1f)
  1059. return sh2_peripheral_read32(a, sh2->is_slave);
  1060. handler = (sh2_read_handler *)(p << 1);
  1061. return (handler(a, sh2->is_slave) << 16) | handler(a + 2, sh2->is_slave);
  1062. }
  1063. // return nonzero if write potentially causes an interrupt (used by drc)
  1064. int REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
  1065. {
  1066. const void **sh2_wmap = sh2->write8_tab;
  1067. sh2_write_handler *wh;
  1068. wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
  1069. return wh(a, d, sh2->is_slave);
  1070. }
  1071. int REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
  1072. {
  1073. const void **sh2_wmap = sh2->write16_tab;
  1074. sh2_write_handler *wh;
  1075. wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
  1076. return wh(a, d, sh2->is_slave);
  1077. }
  1078. int REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
  1079. {
  1080. const void **sh2_wmap = sh2->write16_tab;
  1081. sh2_write_handler *handler;
  1082. u32 offs;
  1083. offs = SH2MAP_ADDR2OFFS_W(a);
  1084. if (offs == SH2MAP_ADDR2OFFS_W(0xffffc000)) {
  1085. sh2_peripheral_write32(a, d, sh2->is_slave);
  1086. return 0;
  1087. }
  1088. handler = sh2_wmap[offs];
  1089. handler(a, d >> 16, sh2->is_slave);
  1090. handler(a + 2, d, sh2->is_slave);
  1091. return 0;
  1092. }
  1093. // -----------------------------------------------------------------
  1094. static const u16 msh2_code[] = {
  1095. // trap instructions
  1096. 0xaffe, // bra <self>
  1097. 0x0009, // nop
  1098. // have to wait a bit until m68k initial program finishes clearing stuff
  1099. // to avoid races with game SH2 code, like in Tempo
  1100. 0xd004, // mov.l @(_m_ok,pc), r0
  1101. 0xd105, // mov.l @(_cnt,pc), r1
  1102. 0xd205, // mov.l @(_start,pc), r2
  1103. 0x71ff, // add #-1, r1
  1104. 0x4115, // cmp/pl r1
  1105. 0x89fc, // bt -2
  1106. 0xc208, // mov.l r0, @(h'20,gbr)
  1107. 0x6822, // mov.l @r2, r8
  1108. 0x482b, // jmp @r8
  1109. 0x0009, // nop
  1110. ('M'<<8)|'_', ('O'<<8)|'K',
  1111. 0x0001, 0x0000,
  1112. 0x2200, 0x03e0 // master start pointer in ROM
  1113. };
  1114. static const u16 ssh2_code[] = {
  1115. 0xaffe, // bra <self>
  1116. 0x0009, // nop
  1117. // code to wait for master, in case authentic master BIOS is used
  1118. 0xd104, // mov.l @(_m_ok,pc), r1
  1119. 0xd206, // mov.l @(_start,pc), r2
  1120. 0xc608, // mov.l @(h'20,gbr), r0
  1121. 0x3100, // cmp/eq r0, r1
  1122. 0x8bfc, // bf #-2
  1123. 0xd003, // mov.l @(_s_ok,pc), r0
  1124. 0xc209, // mov.l r0, @(h'24,gbr)
  1125. 0x6822, // mov.l @r2, r8
  1126. 0x482b, // jmp @r8
  1127. 0x0009, // nop
  1128. ('M'<<8)|'_', ('O'<<8)|'K',
  1129. ('S'<<8)|'_', ('O'<<8)|'K',
  1130. 0x2200, 0x03e4 // slave start pointer in ROM
  1131. };
  1132. #define HWSWAP(x) (((x) << 16) | ((x) >> 16))
  1133. static void get_bios(void)
  1134. {
  1135. u16 *ps;
  1136. u32 *pl;
  1137. int i;
  1138. // M68K ROM
  1139. if (p32x_bios_g != NULL) {
  1140. elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
  1141. Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, sizeof(Pico32xMem->m68k_rom));
  1142. }
  1143. else {
  1144. // generate 68k ROM
  1145. ps = (u16 *)Pico32xMem->m68k_rom;
  1146. pl = (u32 *)ps;
  1147. for (i = 1; i < 0xc0/4; i++)
  1148. pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
  1149. // fill with nops
  1150. for (i = 0xc0/2; i < 0x100/2; i++)
  1151. ps[i] = 0x4e71;
  1152. #if 0
  1153. ps[0xc0/2] = 0x46fc;
  1154. ps[0xc2/2] = 0x2700; // move #0x2700,sr
  1155. ps[0xfe/2] = 0x60fe; // jump to self
  1156. #else
  1157. ps[0xfe/2] = 0x4e75; // rts
  1158. #endif
  1159. }
  1160. // fill remaining m68k_rom page with game ROM
  1161. memcpy(Pico32xMem->m68k_rom_bank + sizeof(Pico32xMem->m68k_rom),
  1162. Pico.rom + sizeof(Pico32xMem->m68k_rom),
  1163. sizeof(Pico32xMem->m68k_rom_bank) - sizeof(Pico32xMem->m68k_rom));
  1164. // MSH2
  1165. if (p32x_bios_m != NULL) {
  1166. elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
  1167. Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
  1168. }
  1169. else {
  1170. pl = (u32 *)Pico32xMem->sh2_rom_m;
  1171. // fill exception vector table to our trap address
  1172. for (i = 0; i < 128; i++)
  1173. pl[i] = HWSWAP(0x200);
  1174. // startup code
  1175. memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code));
  1176. // reset SP
  1177. pl[1] = pl[3] = HWSWAP(0x6040000);
  1178. // start
  1179. pl[0] = pl[2] = HWSWAP(0x204);
  1180. }
  1181. // SSH2
  1182. if (p32x_bios_s != NULL) {
  1183. elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
  1184. Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
  1185. }
  1186. else {
  1187. pl = (u32 *)Pico32xMem->sh2_rom_s;
  1188. // fill exception vector table to our trap address
  1189. for (i = 0; i < 128; i++)
  1190. pl[i] = HWSWAP(0x200);
  1191. // startup code
  1192. memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
  1193. // reset SP
  1194. pl[1] = pl[3] = HWSWAP(0x603f800);
  1195. // start
  1196. pl[0] = pl[2] = HWSWAP(0x204);
  1197. }
  1198. }
  1199. #define MAP_MEMORY(m) ((uptr)(m) >> 1)
  1200. #define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) )
  1201. static sh2_memmap sh2_read8_map[0x20], sh2_read16_map[0x20];
  1202. // for writes we are using handlers only
  1203. static sh2_write_handler *sh2_write8_map[0x80], *sh2_write16_map[0x80];
  1204. void Pico32xSwapDRAM(int b)
  1205. {
  1206. cpu68k_map_set(m68k_read8_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
  1207. cpu68k_map_set(m68k_read16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
  1208. cpu68k_map_set(m68k_write8_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
  1209. cpu68k_map_set(m68k_write16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
  1210. // SH2
  1211. sh2_read8_map[2].addr = sh2_read8_map[6].addr =
  1212. sh2_read16_map[2].addr = sh2_read16_map[6].addr = MAP_MEMORY(Pico32xMem->dram[b]);
  1213. sh2_write8_map[0x04/2] = sh2_write8_map[0x24/2] = b ? sh2_write8_dram1 : sh2_write8_dram0;
  1214. sh2_write16_map[0x04/2] = sh2_write16_map[0x24/2] = b ? sh2_write16_dram1 : sh2_write16_dram0;
  1215. }
  1216. void PicoMemSetup32x(void)
  1217. {
  1218. unsigned int rs;
  1219. int i;
  1220. Pico32xMem = plat_mmap(0x06000000, sizeof(*Pico32xMem), 0, 0);
  1221. if (Pico32xMem == NULL) {
  1222. elprintf(EL_STATUS, "OOM");
  1223. return;
  1224. }
  1225. dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4];
  1226. get_bios();
  1227. // cartridge area becomes unmapped
  1228. // XXX: we take the easy way and don't unmap ROM,
  1229. // so that we can avoid handling the RV bit.
  1230. // m68k_map_unmap(0x000000, 0x3fffff);
  1231. // MD ROM area
  1232. rs = sizeof(Pico32xMem->m68k_rom_bank);
  1233. cpu68k_map_set(m68k_read8_map, 0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
  1234. cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
  1235. cpu68k_map_set(m68k_write8_map, 0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
  1236. cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
  1237. // 32X ROM (unbanked, XXX: consider mirroring?)
  1238. rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
  1239. if (rs > 0x80000)
  1240. rs = 0x80000;
  1241. cpu68k_map_set(m68k_read8_map, 0x880000, 0x880000 + rs - 1, Pico.rom, 0);
  1242. cpu68k_map_set(m68k_read16_map, 0x880000, 0x880000 + rs - 1, Pico.rom, 0);
  1243. #ifdef EMU_F68K
  1244. // setup FAME fetchmap
  1245. PicoCpuFM68k.Fetch[0] = (u32)Pico32xMem->m68k_rom;
  1246. for (rs = 0x88; rs < 0x90; rs++)
  1247. PicoCpuFM68k.Fetch[rs] = (u32)Pico.rom - 0x880000;
  1248. #endif
  1249. // 32X ROM (banked)
  1250. bank_switch(0);
  1251. // SYS regs
  1252. cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
  1253. cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
  1254. cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
  1255. cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
  1256. // SH2 maps: A31,A30,A29,CS1,CS0
  1257. // all unmapped by default
  1258. for (i = 0; i < ARRAY_SIZE(sh2_read8_map); i++) {
  1259. sh2_read8_map[i].addr = MAP_HANDLER(sh2_read8_unmapped);
  1260. sh2_read16_map[i].addr = MAP_HANDLER(sh2_read16_unmapped);
  1261. }
  1262. for (i = 0; i < ARRAY_SIZE(sh2_write8_map); i++) {
  1263. sh2_write8_map[i] = sh2_write8_unmapped;
  1264. sh2_write16_map[i] = sh2_write16_unmapped;
  1265. }
  1266. // "purge area"
  1267. for (i = 0x40; i <= 0x5f; i++) {
  1268. sh2_write8_map[i >> 1] =
  1269. sh2_write16_map[i >> 1] = sh2_write_ignore;
  1270. }
  1271. // CS0
  1272. sh2_read8_map[0].addr = sh2_read8_map[4].addr = MAP_HANDLER(sh2_read8_cs0);
  1273. sh2_read16_map[0].addr = sh2_read16_map[4].addr = MAP_HANDLER(sh2_read16_cs0);
  1274. sh2_write8_map[0x00/2] = sh2_write8_map[0x20/2] = sh2_write8_cs0;
  1275. sh2_write16_map[0x00/2] = sh2_write16_map[0x20/2] = sh2_write16_cs0;
  1276. // CS1 - ROM
  1277. sh2_read8_map[1].addr = sh2_read8_map[5].addr =
  1278. sh2_read16_map[1].addr = sh2_read16_map[5].addr = MAP_MEMORY(Pico.rom);
  1279. sh2_read8_map[1].mask = sh2_read8_map[5].mask =
  1280. sh2_read16_map[1].mask = sh2_read16_map[5].mask = 0x3fffff; // FIXME
  1281. // CS2 - DRAM - done by Pico32xSwapDRAM()
  1282. sh2_read8_map[2].mask = sh2_read8_map[6].mask =
  1283. sh2_read16_map[2].mask = sh2_read16_map[6].mask = 0x01ffff;
  1284. // CS3 - SDRAM
  1285. sh2_read8_map[3].addr = sh2_read8_map[7].addr =
  1286. sh2_read16_map[3].addr = sh2_read16_map[7].addr = MAP_MEMORY(Pico32xMem->sdram);
  1287. sh2_write8_map[0x06/2] = sh2_write8_map[0x26/2] = sh2_write8_sdram;
  1288. sh2_write16_map[0x06/2] = sh2_write16_map[0x26/2] = sh2_write16_sdram;
  1289. sh2_read8_map[3].mask = sh2_read8_map[7].mask =
  1290. sh2_read16_map[3].mask = sh2_read16_map[7].mask = 0x03ffff;
  1291. // SH2 data array
  1292. sh2_read8_map[0x18].addr = MAP_HANDLER(sh2_read8_da);
  1293. sh2_read16_map[0x18].addr = MAP_HANDLER(sh2_read16_da);
  1294. sh2_write8_map[0xc0/2] = sh2_write8_da;
  1295. sh2_write16_map[0xc0/2] = sh2_write16_da;
  1296. // SH2 IO
  1297. sh2_read8_map[0x1f].addr = MAP_HANDLER(sh2_peripheral_read8);
  1298. sh2_read16_map[0x1f].addr = MAP_HANDLER(sh2_peripheral_read16);
  1299. sh2_write8_map[0xff/2] = sh2_peripheral_write8;
  1300. sh2_write16_map[0xff/2] = sh2_peripheral_write16;
  1301. // map DRAM area, both 68k and SH2
  1302. Pico32xSwapDRAM(1);
  1303. msh2.read8_map = ssh2.read8_map = sh2_read8_map;
  1304. msh2.read16_map = ssh2.read16_map = sh2_read16_map;
  1305. msh2.write8_tab = ssh2.write8_tab = (const void **)(void *)sh2_write8_map;
  1306. msh2.write16_tab = ssh2.write16_tab = (const void **)(void *)sh2_write16_map;
  1307. // setup poll detector
  1308. m68k_poll.flag = P32XF_68KPOLL;
  1309. m68k_poll.cyc_max = 64;
  1310. sh2_poll[0].flag = P32XF_MSH2POLL;
  1311. sh2_poll[0].cyc_max = 21;
  1312. sh2_poll[1].flag = P32XF_SSH2POLL;
  1313. sh2_poll[1].cyc_max = 16;
  1314. #ifdef DRC_SH2
  1315. sh2_drc_mem_setup(&msh2);
  1316. sh2_drc_mem_setup(&ssh2);
  1317. #endif
  1318. }
  1319. void Pico32xStateLoaded(void)
  1320. {
  1321. bank_switch(Pico32x.regs[4 / 2]);
  1322. Pico32xSwapDRAM((Pico32x.vdp_regs[0x0a / 2] & P32XV_FS) ^ P32XV_FS);
  1323. p32x_poll_event(3, 0);
  1324. Pico32x.dirty_pal = 1;
  1325. memset(Pico32xMem->pwm, 0, sizeof(Pico32xMem->pwm));
  1326. #ifdef DRC_SH2
  1327. sh2_drc_flush_all();
  1328. #endif
  1329. }
  1330. // vim:shiftwidth=2:expandtab