memory.c 40 KB

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