Memory.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588
  1. // Memory I/O handlers for Sega/Mega CD.
  2. // Loosely based on Gens code.
  3. // (c) Copyright 2007, Grazvydas "notaz" Ignotas
  4. // A68K no longer supported here
  5. //#define __debug_io
  6. #include "../PicoInt.h"
  7. #include "../sound/ym2612.h"
  8. #include "../sound/sn76496.h"
  9. #include "gfx_cd.h"
  10. #include "pcm.h"
  11. #ifndef UTYPES_DEFINED
  12. typedef unsigned char u8;
  13. typedef unsigned short u16;
  14. typedef unsigned int u32;
  15. #define UTYPES_DEFINED
  16. #endif
  17. //#define __debug_io
  18. //#define __debug_io2
  19. #define rdprintf dprintf
  20. //#define rdprintf(...)
  21. //#define wrdprintf dprintf
  22. #define wrdprintf(...)
  23. #define plprintf dprintf
  24. //#define plprintf(...)
  25. // -----------------------------------------------------------------
  26. // poller detection
  27. //#undef USE_POLL_DETECT
  28. #define POLL_LIMIT 16
  29. #define POLL_CYCLES 124
  30. // int m68k_poll_addr, m68k_poll_cnt;
  31. unsigned int s68k_poll_adclk, s68k_poll_cnt;
  32. #ifndef _ASM_CD_MEMORY_C
  33. static u32 m68k_reg_read16(u32 a)
  34. {
  35. u32 d=0;
  36. a &= 0x3e;
  37. // dprintf("m68k_regs r%2i: [%02x] @%06x", realsize&~1, a+(realsize&1), SekPc);
  38. switch (a) {
  39. case 0:
  40. d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens
  41. goto end;
  42. case 2:
  43. d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7);
  44. // the DMNA delay must only be visible on s68k side (Lunar2, Silpheed)
  45. if (Pico_mcd->m.state_flags&2) { d &= ~1; d |= 2; }
  46. //printf("m68k_regs r3: %02x @%06x\n", (u8)d, SekPc);
  47. goto end;
  48. case 4:
  49. d = Pico_mcd->s68k_regs[4]<<8;
  50. goto end;
  51. case 6:
  52. d = *(u16 *)(Pico_mcd->bios + 0x72);
  53. goto end;
  54. case 8:
  55. d = Read_CDC_Host(0);
  56. goto end;
  57. case 0xA:
  58. dprintf("m68k FIXME: reserved read");
  59. goto end;
  60. case 0xC:
  61. d = Pico_mcd->m.timer_stopwatch >> 16;
  62. dprintf("m68k stopwatch timer read (%04x)", d);
  63. goto end;
  64. }
  65. if (a < 0x30) {
  66. // comm flag/cmd/status (0xE-0x2F)
  67. d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];
  68. goto end;
  69. }
  70. dprintf("m68k_regs FIXME invalid read @ %02x", a);
  71. end:
  72. // dprintf("ret = %04x", d);
  73. return d;
  74. }
  75. #endif
  76. #ifndef _ASM_CD_MEMORY_C
  77. static
  78. #endif
  79. void m68k_reg_write8(u32 a, u32 d)
  80. {
  81. a &= 0x3f;
  82. // dprintf("m68k_regs w%2i: [%02x] %02x @%06x", realsize, a, d, SekPc);
  83. switch (a) {
  84. case 0:
  85. d &= 1;
  86. if ((d&1) && (Pico_mcd->s68k_regs[0x33]&(1<<2))) { dprintf("m68k: s68k irq 2"); SekInterruptS68k(2); }
  87. return;
  88. case 1:
  89. d &= 3;
  90. if (!(d&1)) Pico_mcd->m.state_flags |= 1; // reset pending, needed to be sure we fetch the right vectors on reset
  91. if ( (Pico_mcd->m.busreq&1) != (d&1)) dprintf("m68k: s68k reset %i", !(d&1));
  92. if ( (Pico_mcd->m.busreq&2) != (d&2)) dprintf("m68k: s68k brq %i", (d&2)>>1);
  93. if ((Pico_mcd->m.state_flags&1) && (d&3)==1) {
  94. SekResetS68k(); // S68k comes out of RESET or BRQ state
  95. Pico_mcd->m.state_flags&=~1;
  96. dprintf("m68k: resetting s68k, cycles=%i", SekCyclesLeft);
  97. }
  98. Pico_mcd->m.busreq = d;
  99. return;
  100. case 2:
  101. dprintf("m68k: prg wp=%02x", d);
  102. Pico_mcd->s68k_regs[2] = d; // really use s68k side register
  103. return;
  104. case 3: {
  105. u32 dold = Pico_mcd->s68k_regs[3]&0x1f;
  106. //printf("m68k_regs w3: %02x @%06x\n", (u8)d, SekPc);
  107. d &= 0xc2;
  108. if ((dold>>6) != ((d>>6)&3))
  109. dprintf("m68k: prg bank: %i -> %i", (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));
  110. //if ((Pico_mcd->s68k_regs[3]&4) != (d&4)) dprintf("m68k: ram mode %i mbit", (d&4) ? 1 : 2);
  111. //if ((Pico_mcd->s68k_regs[3]&2) != (d&2)) dprintf("m68k: %s", (d&4) ? ((d&2) ? "word swap req" : "noop?") :
  112. // ((d&2) ? "word ram to s68k" : "word ram to m68k"));
  113. if (dold & 4) {
  114. d ^= 2; // writing 0 to DMNA actually sets it, 1 does nothing
  115. } else {
  116. //dold &= ~2; // ??
  117. #if 1
  118. if ((d & 2) && !(dold & 2)) {
  119. Pico_mcd->m.state_flags |= 2; // we must delay setting DMNA bit (needed for Silpheed)
  120. d &= ~2;
  121. }
  122. #else
  123. if (d & 2) dold &= ~1; // return word RAM to s68k in 2M mode
  124. #endif
  125. }
  126. Pico_mcd->s68k_regs[3] = d | dold; // really use s68k side register
  127. #ifdef USE_POLL_DETECT
  128. if ((s68k_poll_adclk&0xfe) == 2 && s68k_poll_cnt > POLL_LIMIT) {
  129. SekSetStopS68k(0); s68k_poll_adclk = 0;
  130. plprintf("s68k poll release, a=%02x\n", a);
  131. }
  132. #endif
  133. return;
  134. }
  135. case 6:
  136. Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer
  137. return;
  138. case 7:
  139. Pico_mcd->bios[0x72] = d;
  140. dprintf("hint vector set to %08x", PicoRead32(0x70));
  141. return;
  142. case 0xf:
  143. d = (d << 1) | ((d >> 7) & 1); // rol8 1 (special case)
  144. case 0xe:
  145. //dprintf("m68k: comm flag: %02x", d);
  146. Pico_mcd->s68k_regs[0xe] = d;
  147. #ifdef USE_POLL_DETECT
  148. if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) {
  149. SekSetStopS68k(0); s68k_poll_adclk = 0;
  150. plprintf("s68k poll release, a=%02x\n", a);
  151. }
  152. #endif
  153. return;
  154. }
  155. if ((a&0xf0) == 0x10) {
  156. Pico_mcd->s68k_regs[a] = d;
  157. #ifdef USE_POLL_DETECT
  158. if ((a&0xfe) == (s68k_poll_adclk&0xfe) && s68k_poll_cnt > POLL_LIMIT) {
  159. SekSetStopS68k(0); s68k_poll_adclk = 0;
  160. plprintf("s68k poll release, a=%02x\n", a);
  161. }
  162. #endif
  163. return;
  164. }
  165. dprintf("m68k FIXME: invalid write? [%02x] %02x", a, d);
  166. }
  167. #ifndef _ASM_CD_MEMORY_C
  168. static
  169. #endif
  170. u32 s68k_poll_detect(u32 a, u32 d)
  171. {
  172. #ifdef USE_POLL_DETECT
  173. // polling detection
  174. if (a == (s68k_poll_adclk&0xff)) {
  175. unsigned int clkdiff = SekCyclesDoneS68k() - (s68k_poll_adclk>>8);
  176. if (clkdiff <= POLL_CYCLES) {
  177. s68k_poll_cnt++;
  178. //printf("-- diff: %u, cnt = %i\n", clkdiff, s68k_poll_cnt);
  179. if (s68k_poll_cnt > POLL_LIMIT) {
  180. SekSetStopS68k(1);
  181. plprintf("s68k poll detected @ %06x, a=%02x\n", SekPcS68k, a);
  182. }
  183. s68k_poll_adclk = (SekCyclesDoneS68k() << 8) | a;
  184. return d;
  185. }
  186. }
  187. s68k_poll_adclk = (SekCyclesDoneS68k() << 8) | a;
  188. s68k_poll_cnt = 0;
  189. #endif
  190. return d;
  191. }
  192. #define READ_FONT_DATA(basemask) \
  193. { \
  194. unsigned int fnt = *(unsigned int *)(Pico_mcd->s68k_regs + 0x4c); \
  195. unsigned int col0 = (fnt >> 8) & 0x0f, col1 = (fnt >> 12) & 0x0f; \
  196. if (fnt & (basemask << 0)) d = col1 ; else d = col0; \
  197. if (fnt & (basemask << 1)) d |= col1 << 4; else d |= col0 << 4; \
  198. if (fnt & (basemask << 2)) d |= col1 << 8; else d |= col0 << 8; \
  199. if (fnt & (basemask << 3)) d |= col1 << 12; else d |= col0 << 12; \
  200. }
  201. #ifndef _ASM_CD_MEMORY_C
  202. static
  203. #endif
  204. u32 s68k_reg_read16(u32 a)
  205. {
  206. u32 d=0;
  207. // dprintf("s68k_regs r%2i: [%02x] @ %06x", realsize&~1, a+(realsize&1), SekPcS68k);
  208. switch (a) {
  209. case 0:
  210. return ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state
  211. case 2:
  212. d = (Pico_mcd->s68k_regs[2]<<8) | (Pico_mcd->s68k_regs[3]&0x1f);
  213. //printf("s68k_regs r3: %02x @%06x\n", (u8)d, SekPcS68k);
  214. return s68k_poll_detect(a, d);
  215. case 6:
  216. return CDC_Read_Reg();
  217. case 8:
  218. return Read_CDC_Host(1); // Gens returns 0 here on byte reads
  219. case 0xC:
  220. d = Pico_mcd->m.timer_stopwatch >> 16;
  221. dprintf("s68k stopwatch timer read (%04x)", d);
  222. return d;
  223. case 0x30:
  224. dprintf("s68k int3 timer read (%02x)", Pico_mcd->s68k_regs[31]);
  225. return Pico_mcd->s68k_regs[31];
  226. case 0x34: // fader
  227. return 0; // no busy bit
  228. case 0x50: // font data (check: Lunar 2, Silpheed)
  229. READ_FONT_DATA(0x00100000);
  230. return d;
  231. case 0x52:
  232. READ_FONT_DATA(0x00010000);
  233. return d;
  234. case 0x54:
  235. READ_FONT_DATA(0x10000000);
  236. return d;
  237. case 0x56:
  238. READ_FONT_DATA(0x01000000);
  239. return d;
  240. }
  241. d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];
  242. if (a >= 0x0e && a < 0x30)
  243. return s68k_poll_detect(a, d);
  244. return d;
  245. }
  246. #ifndef _ASM_CD_MEMORY_C
  247. static
  248. #endif
  249. void s68k_reg_write8(u32 a, u32 d)
  250. {
  251. //dprintf("s68k_regs w%2i: [%02x] %02x @ %06x", realsize, a, d, SekPcS68k);
  252. // TODO: review against Gens
  253. // Warning: d might have upper bits set
  254. switch (a) {
  255. case 2:
  256. return; // only m68k can change WP
  257. case 3: {
  258. int dold = Pico_mcd->s68k_regs[3];
  259. //printf("s68k_regs w3: %02x @%06x\n", (u8)d, SekPcS68k);
  260. d &= 0x1d;
  261. d |= dold&0xc2;
  262. if (d&4) {
  263. if ((d ^ dold) & 5) {
  264. d &= ~2; // in case of mode or bank change we clear DMNA (m68k req) bit
  265. #ifdef _ASM_CD_MEMORY_C
  266. PicoMemResetCD(d);
  267. #endif
  268. }
  269. #ifdef _ASM_CD_MEMORY_C
  270. if ((d ^ dold) & 0x1d)
  271. PicoMemResetCDdecode(d);
  272. #endif
  273. if (!(dold & 4)) {
  274. dprintf("wram mode 2M->1M");
  275. wram_2M_to_1M(Pico_mcd->word_ram2M);
  276. }
  277. } else {
  278. if (dold & 4) {
  279. dprintf("wram mode 1M->2M");
  280. if (!(d&1)) { // it didn't set the ret bit, which means it doesn't want to give WRAM to m68k
  281. d &= ~3;
  282. d |= (dold&1) ? 2 : 1; // then give it to the one which had bank0 in 1M mode
  283. }
  284. wram_1M_to_2M(Pico_mcd->word_ram2M);
  285. #ifdef _ASM_CD_MEMORY_C
  286. PicoMemResetCD(d);
  287. #endif
  288. }
  289. else
  290. d |= dold&1;
  291. if (d&1) d &= ~2; // return word RAM to m68k in 2M mode
  292. }
  293. break;
  294. }
  295. case 4:
  296. dprintf("s68k CDC dest: %x", d&7);
  297. Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode
  298. return;
  299. case 5:
  300. //dprintf("s68k CDC reg addr: %x", d&0xf);
  301. break;
  302. case 7:
  303. CDC_Write_Reg(d);
  304. return;
  305. case 0xa:
  306. dprintf("s68k set CDC dma addr");
  307. break;
  308. case 0xc:
  309. case 0xd:
  310. dprintf("s68k set stopwatch timer");
  311. Pico_mcd->m.timer_stopwatch = 0;
  312. return;
  313. case 0xe:
  314. Pico_mcd->s68k_regs[0xf] = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair
  315. return;
  316. case 0x31:
  317. dprintf("s68k set int3 timer: %02x", d);
  318. Pico_mcd->m.timer_int3 = (d & 0xff) << 16;
  319. break;
  320. case 0x33: // IRQ mask
  321. dprintf("s68k irq mask: %02x", d);
  322. if ((d&(1<<4)) && (Pico_mcd->s68k_regs[0x37]&4) && !(Pico_mcd->s68k_regs[0x33]&(1<<4))) {
  323. CDD_Export_Status();
  324. }
  325. break;
  326. case 0x34: // fader
  327. Pico_mcd->s68k_regs[a] = (u8) d & 0x7f;
  328. return;
  329. case 0x36:
  330. return; // d/m bit is unsetable
  331. case 0x37: {
  332. u32 d_old = Pico_mcd->s68k_regs[0x37];
  333. Pico_mcd->s68k_regs[0x37] = d&7;
  334. if ((d&4) && !(d_old&4)) {
  335. CDD_Export_Status();
  336. }
  337. return;
  338. }
  339. case 0x4b:
  340. Pico_mcd->s68k_regs[a] = (u8) d;
  341. CDD_Import_Command();
  342. return;
  343. }
  344. if ((a&0x1f0) == 0x10 || (a >= 0x38 && a < 0x42))
  345. {
  346. dprintf("s68k FIXME: invalid write @ %02x?", a);
  347. return;
  348. }
  349. Pico_mcd->s68k_regs[a] = (u8) d;
  350. }
  351. #ifndef _ASM_CD_MEMORY_C
  352. static u32 OtherRead16End(u32 a, int realsize)
  353. {
  354. u32 d=0;
  355. if ((a&0xffffc0)==0xa12000) {
  356. d=m68k_reg_read16(a);
  357. goto end;
  358. }
  359. dprintf("m68k FIXME: unusual r%i: %06x @%06x", realsize&~1, (a&0xfffffe)+(realsize&1), SekPc);
  360. end:
  361. return d;
  362. }
  363. static void OtherWrite8End(u32 a, u32 d, int realsize)
  364. {
  365. if ((a&0xffffc0)==0xa12000) { m68k_reg_write8(a, d); return; }
  366. dprintf("m68k FIXME: strange w%i: [%06x], %08x @%06x", realsize, a&0xffffff, d, SekPc);
  367. }
  368. #undef _ASM_MEMORY_C
  369. #include "../MemoryCmn.c"
  370. #include "cell_map.c"
  371. #endif // !def _ASM_CD_MEMORY_C
  372. // -----------------------------------------------------------------
  373. // Read Rom and read Ram
  374. //u8 PicoReadM68k8_(u32 a);
  375. #ifdef _ASM_CD_MEMORY_C
  376. u32 PicoReadM68k8(u32 a);
  377. #else
  378. static u32 PicoReadM68k8(u32 a)
  379. {
  380. u32 d=0;
  381. if ((a&0xe00000)==0xe00000) { d = *(u8 *)(Pico.ram+((a^1)&0xffff)); goto end; } // Ram
  382. a&=0xffffff;
  383. if (a < 0x20000) { d = *(u8 *)(Pico_mcd->bios+(a^1)); goto end; } // bios
  384. // prg RAM
  385. if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
  386. u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
  387. d = *(prg_bank+((a^1)&0x1ffff));
  388. goto end;
  389. }
  390. // word RAM
  391. if ((a&0xfc0000)==0x200000) {
  392. wrdprintf("m68k_wram r8: [%06x] @%06x", a, SekPc);
  393. if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
  394. int bank = Pico_mcd->s68k_regs[3]&1;
  395. if (a >= 0x220000)
  396. a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged
  397. else a &= 0x1ffff;
  398. d = Pico_mcd->word_ram1M[bank][a^1];
  399. } else {
  400. // allow access in any mode, like Gens does
  401. d = Pico_mcd->word_ram2M[(a^1)&0x3ffff];
  402. }
  403. wrdprintf("ret = %02x", (u8)d);
  404. goto end;
  405. }
  406. if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram
  407. if ((a&0xffffc0)==0xa12000)
  408. rdprintf("m68k_regs r8: [%02x] @%06x", a&0x3f, SekPc);
  409. d=OtherRead16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;
  410. if ((a&0xffffc0)==0xa12000)
  411. rdprintf("ret = %02x", (u8)d);
  412. end:
  413. #ifdef __debug_io
  414. dprintf("r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPc);
  415. #endif
  416. return d;
  417. }
  418. #endif
  419. #ifdef _ASM_CD_MEMORY_C
  420. u32 PicoReadM68k16(u32 a);
  421. #else
  422. static u32 PicoReadM68k16(u32 a)
  423. {
  424. u32 d=0;
  425. if ((a&0xe00000)==0xe00000) { d=*(u16 *)(Pico.ram+(a&0xfffe)); goto end; } // Ram
  426. a&=0xfffffe;
  427. if (a < 0x20000) { d = *(u16 *)(Pico_mcd->bios+a); goto end; } // bios
  428. // prg RAM
  429. if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
  430. u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
  431. wrdprintf("m68k_prgram r16: [%i,%06x] @%06x", Pico_mcd->s68k_regs[3]>>6, a, SekPc);
  432. d = *(u16 *)(prg_bank+(a&0x1fffe));
  433. wrdprintf("ret = %04x", d);
  434. goto end;
  435. }
  436. // word RAM
  437. if ((a&0xfc0000)==0x200000) {
  438. wrdprintf("m68k_wram r16: [%06x] @%06x", a, SekPc);
  439. if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
  440. int bank = Pico_mcd->s68k_regs[3]&1;
  441. if (a >= 0x220000)
  442. a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged
  443. else a &= 0x1fffe;
  444. d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);
  445. } else {
  446. // allow access in any mode, like Gens does
  447. d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
  448. }
  449. wrdprintf("ret = %04x", d);
  450. goto end;
  451. }
  452. if ((a&0xffffc0)==0xa12000)
  453. rdprintf("m68k_regs r16: [%02x] @%06x", a&0x3f, SekPc);
  454. d = OtherRead16(a, 16);
  455. if ((a&0xffffc0)==0xa12000)
  456. rdprintf("ret = %04x", d);
  457. end:
  458. #ifdef __debug_io
  459. dprintf("r16: %06x, %04x @%06x", a&0xffffff, d, SekPc);
  460. #endif
  461. return d;
  462. }
  463. #endif
  464. #ifdef _ASM_CD_MEMORY_C
  465. u32 PicoReadM68k32(u32 a);
  466. #else
  467. static u32 PicoReadM68k32(u32 a)
  468. {
  469. u32 d=0;
  470. if ((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); d = (pm[0]<<16)|pm[1]; goto end; } // Ram
  471. a&=0xfffffe;
  472. if (a < 0x20000) { u16 *pm=(u16 *)(Pico_mcd->bios+a); d = (pm[0]<<16)|pm[1]; goto end; } // bios
  473. // prg RAM
  474. if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
  475. u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
  476. u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));
  477. d = (pm[0]<<16)|pm[1];
  478. goto end;
  479. }
  480. // word RAM
  481. if ((a&0xfc0000)==0x200000) {
  482. wrdprintf("m68k_wram r32: [%06x] @%06x", a, SekPc);
  483. if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
  484. int bank = Pico_mcd->s68k_regs[3]&1;
  485. if (a >= 0x220000) { // cell arranged
  486. u32 a1, a2;
  487. a1 = (a&2) | (cell_map(a >> 2) << 2);
  488. if (a&2) a2 = cell_map((a+2) >> 2) << 2;
  489. else a2 = a1 + 2;
  490. d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a1) << 16;
  491. d |= *(u16 *)(Pico_mcd->word_ram1M[bank]+a2);
  492. } else {
  493. u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe)); d = (pm[0]<<16)|pm[1];
  494. }
  495. } else {
  496. // allow access in any mode, like Gens does
  497. u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];
  498. }
  499. wrdprintf("ret = %08x", d);
  500. goto end;
  501. }
  502. if ((a&0xffffc0)==0xa12000)
  503. rdprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);
  504. d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);
  505. if ((a&0xffffc0)==0xa12000)
  506. rdprintf("ret = %08x", d);
  507. end:
  508. #ifdef __debug_io
  509. dprintf("r32: %06x, %08x @%06x", a&0xffffff, d, SekPc);
  510. #endif
  511. return d;
  512. }
  513. #endif
  514. // -----------------------------------------------------------------
  515. #ifdef _ASM_CD_MEMORY_C
  516. void PicoWriteM68k8(u32 a,u8 d);
  517. #else
  518. static void PicoWriteM68k8(u32 a,u8 d)
  519. {
  520. #ifdef __debug_io
  521. dprintf("w8 : %06x, %02x @%06x", a&0xffffff, d, SekPc);
  522. #endif
  523. //if ((a&0xe0ffff)==0xe0a9ba+0x69c)
  524. // dprintf("w8 : %06x, %02x @%06x", a&0xffffff, d, SekPc);
  525. if ((a&0xe00000)==0xe00000) { // Ram
  526. *(u8 *)(Pico.ram+((a^1)&0xffff)) = d;
  527. return;
  528. }
  529. a&=0xffffff;
  530. // prg RAM
  531. if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
  532. u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
  533. *(u8 *)(prg_bank+((a^1)&0x1ffff))=d;
  534. return;
  535. }
  536. // word RAM
  537. if ((a&0xfc0000)==0x200000) {
  538. wrdprintf("m68k_wram w8: [%06x] %02x @%06x", a, d, SekPc);
  539. if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
  540. int bank = Pico_mcd->s68k_regs[3]&1;
  541. if (a >= 0x220000)
  542. a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged
  543. else a &= 0x1ffff;
  544. *(u8 *)(Pico_mcd->word_ram1M[bank]+(a^1))=d;
  545. } else {
  546. // allow access in any mode, like Gens does
  547. *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;
  548. }
  549. return;
  550. }
  551. if ((a&0xffffc0)==0xa12000) {
  552. rdprintf("m68k_regs w8: [%02x] %02x @%06x", a&0x3f, d, SekPc);
  553. m68k_reg_write8(a, d);
  554. return;
  555. }
  556. OtherWrite8(a,d,8);
  557. }
  558. #endif
  559. #ifdef _ASM_CD_MEMORY_C
  560. void PicoWriteM68k16(u32 a,u16 d);
  561. #else
  562. static void PicoWriteM68k16(u32 a,u16 d)
  563. {
  564. #ifdef __debug_io
  565. dprintf("w16: %06x, %04x", a&0xffffff, d);
  566. #endif
  567. // dprintf("w16: %06x, %04x @%06x", a&0xffffff, d, SekPc);
  568. if ((a&0xe00000)==0xe00000) { // Ram
  569. *(u16 *)(Pico.ram+(a&0xfffe))=d;
  570. return;
  571. }
  572. a&=0xfffffe;
  573. // prg RAM
  574. if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
  575. u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
  576. wrdprintf("m68k_prgram w16: [%i,%06x] %04x @%06x", Pico_mcd->s68k_regs[3]>>6, a, d, SekPc);
  577. *(u16 *)(prg_bank+(a&0x1fffe))=d;
  578. return;
  579. }
  580. // word RAM
  581. if ((a&0xfc0000)==0x200000) {
  582. wrdprintf("m68k_wram w16: [%06x] %04x @%06x", a, d, SekPc);
  583. if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
  584. int bank = Pico_mcd->s68k_regs[3]&1;
  585. if (a >= 0x220000)
  586. a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged
  587. else a &= 0x1fffe;
  588. *(u16 *)(Pico_mcd->word_ram1M[bank]+a)=d;
  589. } else {
  590. // allow access in any mode, like Gens does
  591. *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;
  592. }
  593. return;
  594. }
  595. // regs
  596. if ((a&0xffffc0)==0xa12000) {
  597. rdprintf("m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc);
  598. if (a == 0xe) { // special case, 2 byte writes would be handled differently
  599. Pico_mcd->s68k_regs[0xe] = d >> 8;
  600. #ifdef USE_POLL_DETECT
  601. if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) {
  602. SekSetStopS68k(0); s68k_poll_adclk = 0;
  603. plprintf("s68k poll release, a=%02x\n", a);
  604. }
  605. #endif
  606. return;
  607. }
  608. m68k_reg_write8(a, d>>8);
  609. m68k_reg_write8(a+1,d&0xff);
  610. return;
  611. }
  612. OtherWrite16(a,d);
  613. }
  614. #endif
  615. #ifdef _ASM_CD_MEMORY_C
  616. void PicoWriteM68k32(u32 a,u32 d);
  617. #else
  618. static void PicoWriteM68k32(u32 a,u32 d)
  619. {
  620. #ifdef __debug_io
  621. dprintf("w32: %06x, %08x", a&0xffffff, d);
  622. #endif
  623. if ((a&0xe00000)==0xe00000)
  624. {
  625. // Ram:
  626. u16 *pm=(u16 *)(Pico.ram+(a&0xfffe));
  627. pm[0]=(u16)(d>>16); pm[1]=(u16)d;
  628. return;
  629. }
  630. a&=0xfffffe;
  631. // prg RAM
  632. if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
  633. u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
  634. u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));
  635. pm[0]=(u16)(d>>16); pm[1]=(u16)d;
  636. return;
  637. }
  638. // word RAM
  639. if ((a&0xfc0000)==0x200000) {
  640. if (d != 0) // don't log clears
  641. wrdprintf("m68k_wram w32: [%06x] %08x @%06x", a, d, SekPc);
  642. if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
  643. int bank = Pico_mcd->s68k_regs[3]&1;
  644. if (a >= 0x220000) { // cell arranged
  645. u32 a1, a2;
  646. a1 = (a&2) | (cell_map(a >> 2) << 2);
  647. if (a&2) a2 = cell_map((a+2) >> 2) << 2;
  648. else a2 = a1 + 2;
  649. *(u16 *)(Pico_mcd->word_ram1M[bank]+a1) = d >> 16;
  650. *(u16 *)(Pico_mcd->word_ram1M[bank]+a2) = d;
  651. } else {
  652. u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
  653. pm[0]=(u16)(d>>16); pm[1]=(u16)d;
  654. }
  655. } else {
  656. // allow access in any mode, like Gens does
  657. u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
  658. pm[0]=(u16)(d>>16); pm[1]=(u16)d;
  659. }
  660. return;
  661. }
  662. if ((a&0xffffc0)==0xa12000) {
  663. rdprintf("m68k_regs w32: [%02x] %08x @%06x", a&0x3f, d, SekPc);
  664. if ((a&0x3e) == 0xe) dprintf("m68k FIXME: w32 [%02x]", a&0x3f);
  665. }
  666. OtherWrite16(a, (u16)(d>>16));
  667. OtherWrite16(a+2,(u16)d);
  668. }
  669. #endif
  670. // -----------------------------------------------------------------
  671. // S68k
  672. // -----------------------------------------------------------------
  673. #ifdef _ASM_CD_MEMORY_C
  674. u32 PicoReadS68k8(u32 a);
  675. #else
  676. static u32 PicoReadS68k8(u32 a)
  677. {
  678. u32 d=0;
  679. a&=0xffffff;
  680. // prg RAM
  681. if (a < 0x80000) {
  682. d = *(Pico_mcd->prg_ram+(a^1));
  683. goto end;
  684. }
  685. // regs
  686. if ((a&0xfffe00) == 0xff8000) {
  687. a &= 0x1ff;
  688. rdprintf("s68k_regs r8: [%02x] @ %06x", a, SekPcS68k);
  689. if (a >= 0x0e && a < 0x30) {
  690. d = Pico_mcd->s68k_regs[a];
  691. s68k_poll_detect(a, d);
  692. rdprintf("ret = %02x", (u8)d);
  693. goto end;
  694. }
  695. else if (a >= 0x58 && a < 0x68)
  696. d = gfx_cd_read(a&~1);
  697. else d = s68k_reg_read16(a&~1);
  698. if ((a&1)==0) d>>=8;
  699. rdprintf("ret = %02x", (u8)d);
  700. goto end;
  701. }
  702. // word RAM (2M area)
  703. if ((a&0xfc0000)==0x080000) { // 080000-0bffff
  704. // test: batman returns
  705. wrdprintf("s68k_wram2M r8: [%06x] @%06x", a, SekPcS68k);
  706. if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
  707. int bank = !(Pico_mcd->s68k_regs[3]&1);
  708. d = Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff];
  709. if (a&1) d &= 0x0f;
  710. else d >>= 4;
  711. dprintf("FIXME: decode");
  712. } else {
  713. // allow access in any mode, like Gens does
  714. d = Pico_mcd->word_ram2M[(a^1)&0x3ffff];
  715. }
  716. wrdprintf("ret = %02x", (u8)d);
  717. goto end;
  718. }
  719. // word RAM (1M area)
  720. if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff
  721. int bank;
  722. wrdprintf("s68k_wram1M r8: [%06x] @%06x", a, SekPcS68k);
  723. // if (!(Pico_mcd->s68k_regs[3]&4))
  724. // dprintf("s68k_wram1M FIXME: wrong mode");
  725. bank = !(Pico_mcd->s68k_regs[3]&1);
  726. d = Pico_mcd->word_ram1M[bank][(a^1)&0x1ffff];
  727. wrdprintf("ret = %02x", (u8)d);
  728. goto end;
  729. }
  730. // PCM
  731. if ((a&0xff8000)==0xff0000) {
  732. dprintf("s68k_pcm r8: [%06x] @%06x", a, SekPcS68k);
  733. a &= 0x7fff;
  734. if (a >= 0x2000)
  735. d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff];
  736. else if (a >= 0x20) {
  737. a &= 0x1e;
  738. d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;
  739. if (a & 2) d >>= 8;
  740. }
  741. dprintf("ret = %02x", (u8)d);
  742. goto end;
  743. }
  744. // bram
  745. if ((a&0xff0000)==0xfe0000) {
  746. d = Pico_mcd->bram[(a>>1)&0x1fff];
  747. goto end;
  748. }
  749. dprintf("s68k r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);
  750. end:
  751. #ifdef __debug_io2
  752. dprintf("s68k r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);
  753. #endif
  754. return d;
  755. }
  756. #endif
  757. #ifdef _ASM_CD_MEMORY_C
  758. u32 PicoReadS68k16(u32 a);
  759. #else
  760. static u32 PicoReadS68k16(u32 a)
  761. {
  762. u32 d=0;
  763. a&=0xfffffe;
  764. // prg RAM
  765. if (a < 0x80000) {
  766. wrdprintf("s68k_prgram r16: [%06x] @%06x", a, SekPcS68k);
  767. d = *(u16 *)(Pico_mcd->prg_ram+a);
  768. wrdprintf("ret = %04x", d);
  769. goto end;
  770. }
  771. // regs
  772. if ((a&0xfffe00) == 0xff8000) {
  773. a &= 0x1fe;
  774. rdprintf("s68k_regs r16: [%02x] @ %06x", a, SekPcS68k);
  775. if (a >= 0x58 && a < 0x68)
  776. d = gfx_cd_read(a);
  777. else d = s68k_reg_read16(a);
  778. rdprintf("ret = %04x", d);
  779. goto end;
  780. }
  781. // word RAM (2M area)
  782. if ((a&0xfc0000)==0x080000) { // 080000-0bffff
  783. wrdprintf("s68k_wram2M r16: [%06x] @%06x", a, SekPcS68k);
  784. if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
  785. int bank = !(Pico_mcd->s68k_regs[3]&1);
  786. d = Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff];
  787. d |= d << 4; d &= ~0xf0;
  788. dprintf("FIXME: decode");
  789. } else {
  790. // allow access in any mode, like Gens does
  791. d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
  792. }
  793. wrdprintf("ret = %04x", d);
  794. goto end;
  795. }
  796. // word RAM (1M area)
  797. if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff
  798. int bank;
  799. wrdprintf("s68k_wram1M r16: [%06x] @%06x", a, SekPcS68k);
  800. // if (!(Pico_mcd->s68k_regs[3]&4))
  801. // dprintf("s68k_wram1M FIXME: wrong mode");
  802. bank = !(Pico_mcd->s68k_regs[3]&1);
  803. d = *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
  804. wrdprintf("ret = %04x", d);
  805. goto end;
  806. }
  807. // bram
  808. if ((a&0xff0000)==0xfe0000) {
  809. dprintf("FIXME: s68k_bram r16: [%06x] @%06x", a, SekPcS68k);
  810. a = (a>>1)&0x1fff;
  811. d = Pico_mcd->bram[a++]; // Gens does little endian here, and so do we..
  812. d|= Pico_mcd->bram[a++] << 8; // This is most likely wrong
  813. dprintf("ret = %04x", d);
  814. goto end;
  815. }
  816. // PCM
  817. if ((a&0xff8000)==0xff0000) {
  818. dprintf("FIXME: s68k_pcm r16: [%06x] @%06x", a, SekPcS68k);
  819. a &= 0x7fff;
  820. if (a >= 0x2000)
  821. d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff];
  822. else if (a >= 0x20) {
  823. a &= 0x1e;
  824. d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;
  825. if (a & 2) d >>= 8;
  826. }
  827. dprintf("ret = %04x", d);
  828. goto end;
  829. }
  830. dprintf("s68k r16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);
  831. end:
  832. #ifdef __debug_io2
  833. dprintf("s68k r16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);
  834. #endif
  835. return d;
  836. }
  837. #endif
  838. #ifdef _ASM_CD_MEMORY_C
  839. u32 PicoReadS68k32(u32 a);
  840. #else
  841. static u32 PicoReadS68k32(u32 a)
  842. {
  843. u32 d=0;
  844. a&=0xfffffe;
  845. // prg RAM
  846. if (a < 0x80000) {
  847. u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);
  848. d = (pm[0]<<16)|pm[1];
  849. goto end;
  850. }
  851. // regs
  852. if ((a&0xfffe00) == 0xff8000) {
  853. a &= 0x1fe;
  854. rdprintf("s68k_regs r32: [%02x] @ %06x", a, SekPcS68k);
  855. if (a >= 0x58 && a < 0x68)
  856. d = (gfx_cd_read(a)<<16)|gfx_cd_read(a+2);
  857. else d = (s68k_reg_read16(a)<<16)|s68k_reg_read16(a+2);
  858. rdprintf("ret = %08x", d);
  859. goto end;
  860. }
  861. // word RAM (2M area)
  862. if ((a&0xfc0000)==0x080000) { // 080000-0bffff
  863. wrdprintf("s68k_wram2M r32: [%06x] @%06x", a, SekPcS68k);
  864. if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
  865. int bank = !(Pico_mcd->s68k_regs[3]&1);
  866. a >>= 1;
  867. d = Pico_mcd->word_ram1M[bank][((a+0)^1)&0x1ffff] << 16;
  868. d |= Pico_mcd->word_ram1M[bank][((a+1)^1)&0x1ffff];
  869. d |= d << 4; d &= 0x0f0f0f0f;
  870. } else {
  871. // allow access in any mode, like Gens does
  872. u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];
  873. }
  874. wrdprintf("ret = %08x", d);
  875. goto end;
  876. }
  877. // word RAM (1M area)
  878. if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff
  879. int bank;
  880. wrdprintf("s68k_wram1M r32: [%06x] @%06x", a, SekPcS68k);
  881. // if (!(Pico_mcd->s68k_regs[3]&4))
  882. // dprintf("s68k_wram1M FIXME: wrong mode");
  883. bank = !(Pico_mcd->s68k_regs[3]&1);
  884. u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe)); d = (pm[0]<<16)|pm[1];
  885. wrdprintf("ret = %08x", d);
  886. goto end;
  887. }
  888. // PCM
  889. if ((a&0xff8000)==0xff0000) {
  890. dprintf("s68k_pcm r32: [%06x] @%06x", a, SekPcS68k);
  891. a &= 0x7fff;
  892. if (a >= 0x2000) {
  893. a >>= 1;
  894. d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][a&0xfff] << 16;
  895. d |= Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a+1)&0xfff];
  896. } else if (a >= 0x20) {
  897. a &= 0x1e;
  898. if (a & 2) {
  899. a >>= 2;
  900. d = (Pico_mcd->pcm.ch[a].addr >> (PCM_STEP_SHIFT-8)) & 0xff0000;
  901. d |= (Pico_mcd->pcm.ch[(a+1)&7].addr >> PCM_STEP_SHIFT) & 0xff;
  902. } else {
  903. d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;
  904. d = ((d<<16)&0xff0000) | ((d>>8)&0xff); // PCM chip is LE
  905. }
  906. }
  907. dprintf("ret = %08x", d);
  908. goto end;
  909. }
  910. // bram
  911. if ((a&0xff0000)==0xfe0000) {
  912. dprintf("FIXME: s68k_bram r32: [%06x] @%06x", a, SekPcS68k);
  913. a = (a>>1)&0x1fff;
  914. d = Pico_mcd->bram[a++] << 16; // middle endian? TODO: verify against Fusion..
  915. d|= Pico_mcd->bram[a++] << 24;
  916. d|= Pico_mcd->bram[a++];
  917. d|= Pico_mcd->bram[a++] << 8;
  918. dprintf("ret = %08x", d);
  919. goto end;
  920. }
  921. dprintf("s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);
  922. end:
  923. #ifdef __debug_io2
  924. dprintf("s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);
  925. #endif
  926. return d;
  927. }
  928. #endif
  929. #ifndef _ASM_CD_MEMORY_C
  930. /* check: jaguar xj 220 (draws entire world using decode) */
  931. static void decode_write8(u32 a, u8 d, int r3)
  932. {
  933. u8 *pd = Pico_mcd->word_ram1M[!(r3 & 1)] + (((a>>1)^1)&0x1ffff);
  934. u8 oldmask = (a&1) ? 0xf0 : 0x0f;
  935. r3 &= 0x18;
  936. d &= 0x0f;
  937. if (!(a&1)) d <<= 4;
  938. if (r3 == 8) {
  939. if ((!(*pd & (~oldmask))) && d) goto do_it;
  940. } else if (r3 > 8) {
  941. if (d) goto do_it;
  942. } else {
  943. goto do_it;
  944. }
  945. return;
  946. do_it:
  947. *pd = d | (*pd & oldmask);
  948. }
  949. static void decode_write16(u32 a, u16 d, int r3)
  950. {
  951. u8 *pd = Pico_mcd->word_ram1M[!(r3 & 1)] + (((a>>1)^1)&0x1ffff);
  952. //if ((a & 0x3ffff) < 0x28000) return;
  953. r3 &= 0x18;
  954. d &= 0x0f0f;
  955. d |= d >> 4;
  956. if (r3 == 8) {
  957. u8 dold = *pd;
  958. if (!(dold & 0xf0)) dold |= d & 0xf0;
  959. if (!(dold & 0x0f)) dold |= d & 0x0f;
  960. *pd = dold;
  961. } else if (r3 > 8) {
  962. u8 dold = *pd;
  963. if (!(d & 0xf0)) d |= dold & 0xf0;
  964. if (!(d & 0x0f)) d |= dold & 0x0f;
  965. *pd = d;
  966. } else {
  967. *pd = d;
  968. }
  969. }
  970. #endif
  971. // -----------------------------------------------------------------
  972. #ifdef _ASM_CD_MEMORY_C
  973. void PicoWriteS68k8(u32 a,u8 d);
  974. #else
  975. static void PicoWriteS68k8(u32 a,u8 d)
  976. {
  977. #ifdef __debug_io2
  978. dprintf("s68k w8 : %06x, %02x @%06x", a&0xffffff, d, SekPcS68k);
  979. #endif
  980. a&=0xffffff;
  981. // prg RAM
  982. if (a < 0x80000) {
  983. u8 *pm=(u8 *)(Pico_mcd->prg_ram+(a^1));
  984. if (a >= (Pico_mcd->s68k_regs[2]<<8)) *pm=d;
  985. return;
  986. }
  987. // regs
  988. if ((a&0xfffe00) == 0xff8000) {
  989. a &= 0x1ff;
  990. rdprintf("s68k_regs w8: [%02x] %02x @ %06x", a, d, SekPcS68k);
  991. if (a >= 0x58 && a < 0x68)
  992. gfx_cd_write16(a&~1, (d<<8)|d);
  993. else s68k_reg_write8(a,d);
  994. return;
  995. }
  996. // word RAM (2M area)
  997. if ((a&0xfc0000)==0x080000) { // 080000-0bffff
  998. int r3 = Pico_mcd->s68k_regs[3];
  999. wrdprintf("s68k_wram2M w8: [%06x] %02x @%06x", a, d, SekPcS68k);
  1000. if (r3 & 4) { // 1M decode mode?
  1001. decode_write8(a, d, r3);
  1002. } else {
  1003. // allow access in any mode, like Gens does
  1004. *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;
  1005. }
  1006. return;
  1007. }
  1008. // word RAM (1M area)
  1009. if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff
  1010. // Wing Commander tries to write here in wrong mode
  1011. int bank;
  1012. if (d)
  1013. wrdprintf("s68k_wram1M w8: [%06x] %02x @%06x", a, d, SekPcS68k);
  1014. // if (!(Pico_mcd->s68k_regs[3]&4))
  1015. // dprintf("s68k_wram1M FIXME: wrong mode");
  1016. bank = !(Pico_mcd->s68k_regs[3]&1);
  1017. *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff))=d;
  1018. return;
  1019. }
  1020. // PCM
  1021. if ((a&0xff8000)==0xff0000) {
  1022. a &= 0x7fff;
  1023. if (a >= 0x2000)
  1024. Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d;
  1025. else if (a < 0x12)
  1026. pcm_write(a>>1, d);
  1027. return;
  1028. }
  1029. // bram
  1030. if ((a&0xff0000)==0xfe0000) {
  1031. Pico_mcd->bram[(a>>1)&0x1fff] = d;
  1032. SRam.changed = 1;
  1033. return;
  1034. }
  1035. dprintf("s68k w8 : %06x, %02x @%06x", a&0xffffff, d, SekPcS68k);
  1036. }
  1037. #endif
  1038. #ifdef _ASM_CD_MEMORY_C
  1039. void PicoWriteS68k16(u32 a,u16 d);
  1040. #else
  1041. static void PicoWriteS68k16(u32 a,u16 d)
  1042. {
  1043. #ifdef __debug_io2
  1044. dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);
  1045. #endif
  1046. a&=0xfffffe;
  1047. // prg RAM
  1048. if (a < 0x80000) {
  1049. wrdprintf("s68k_prgram w16: [%06x] %04x @%06x", a, d, SekPcS68k);
  1050. if (a >= (Pico_mcd->s68k_regs[2]<<8)) // needed for Dungeon Explorer
  1051. *(u16 *)(Pico_mcd->prg_ram+a)=d;
  1052. return;
  1053. }
  1054. // regs
  1055. if ((a&0xfffe00) == 0xff8000) {
  1056. a &= 0x1fe;
  1057. rdprintf("s68k_regs w16: [%02x] %04x @ %06x", a, d, SekPcS68k);
  1058. if (a >= 0x58 && a < 0x68)
  1059. gfx_cd_write16(a, d);
  1060. else {
  1061. if (a == 0xe) { // special case, 2 byte writes would be handled differently
  1062. Pico_mcd->s68k_regs[0xf] = d;
  1063. return;
  1064. }
  1065. s68k_reg_write8(a, d>>8);
  1066. s68k_reg_write8(a+1,d&0xff);
  1067. }
  1068. return;
  1069. }
  1070. // word RAM (2M area)
  1071. if ((a&0xfc0000)==0x080000) { // 080000-0bffff
  1072. int r3 = Pico_mcd->s68k_regs[3];
  1073. wrdprintf("s68k_wram2M w16: [%06x] %04x @%06x", a, d, SekPcS68k);
  1074. if (r3 & 4) { // 1M decode mode?
  1075. decode_write16(a, d, r3);
  1076. } else {
  1077. // allow access in any mode, like Gens does
  1078. *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;
  1079. }
  1080. return;
  1081. }
  1082. // word RAM (1M area)
  1083. if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff
  1084. int bank;
  1085. if (d)
  1086. wrdprintf("s68k_wram1M w16: [%06x] %04x @%06x", a, d, SekPcS68k);
  1087. // if (!(Pico_mcd->s68k_regs[3]&4))
  1088. // dprintf("s68k_wram1M FIXME: wrong mode");
  1089. bank = !(Pico_mcd->s68k_regs[3]&1);
  1090. *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe))=d;
  1091. return;
  1092. }
  1093. // PCM
  1094. if ((a&0xff8000)==0xff0000) {
  1095. a &= 0x7fff;
  1096. if (a >= 0x2000)
  1097. Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d;
  1098. else if (a < 0x12)
  1099. pcm_write(a>>1, d & 0xff);
  1100. return;
  1101. }
  1102. // bram
  1103. if ((a&0xff0000)==0xfe0000) {
  1104. dprintf("s68k_bram w16: [%06x] %04x @%06x", a, d, SekPcS68k);
  1105. a = (a>>1)&0x1fff;
  1106. Pico_mcd->bram[a++] = d; // Gens does little endian here, an so do we..
  1107. Pico_mcd->bram[a++] = d >> 8;
  1108. SRam.changed = 1;
  1109. return;
  1110. }
  1111. dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);
  1112. }
  1113. #endif
  1114. #ifdef _ASM_CD_MEMORY_C
  1115. void PicoWriteS68k32(u32 a,u32 d);
  1116. #else
  1117. static void PicoWriteS68k32(u32 a,u32 d)
  1118. {
  1119. #ifdef __debug_io2
  1120. dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);
  1121. #endif
  1122. a&=0xfffffe;
  1123. // prg RAM
  1124. if (a < 0x80000) {
  1125. if (a >= (Pico_mcd->s68k_regs[2]<<8)) {
  1126. u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);
  1127. pm[0]=(u16)(d>>16); pm[1]=(u16)d;
  1128. }
  1129. return;
  1130. }
  1131. // regs
  1132. if ((a&0xfffe00) == 0xff8000) {
  1133. a &= 0x1fe;
  1134. rdprintf("s68k_regs w32: [%02x] %08x @ %06x", a, d, SekPcS68k);
  1135. if (a >= 0x58 && a < 0x68) {
  1136. gfx_cd_write16(a, d>>16);
  1137. gfx_cd_write16(a+2, d&0xffff);
  1138. } else {
  1139. if ((a&0x1fe) == 0xe) dprintf("s68k FIXME: w32 [%02x]", a&0x3f);
  1140. s68k_reg_write8(a, d>>24);
  1141. s68k_reg_write8(a+1,(d>>16)&0xff);
  1142. s68k_reg_write8(a+2,(d>>8) &0xff);
  1143. s68k_reg_write8(a+3, d &0xff);
  1144. }
  1145. return;
  1146. }
  1147. // word RAM (2M area)
  1148. if ((a&0xfc0000)==0x080000) { // 080000-0bffff
  1149. int r3 = Pico_mcd->s68k_regs[3];
  1150. wrdprintf("s68k_wram2M w32: [%06x] %08x @%06x", a, d, SekPcS68k);
  1151. if (r3 & 4) { // 1M decode mode?
  1152. decode_write16(a , d >> 16, r3);
  1153. decode_write16(a+2, d , r3);
  1154. } else {
  1155. // allow access in any mode, like Gens does
  1156. u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
  1157. pm[0]=(u16)(d>>16); pm[1]=(u16)d;
  1158. }
  1159. return;
  1160. }
  1161. // word RAM (1M area)
  1162. if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff
  1163. int bank;
  1164. u16 *pm;
  1165. if (d)
  1166. wrdprintf("s68k_wram1M w32: [%06x] %08x @%06x", a, d, SekPcS68k);
  1167. // if (!(Pico_mcd->s68k_regs[3]&4))
  1168. // dprintf("s68k_wram1M FIXME: wrong mode");
  1169. bank = !(Pico_mcd->s68k_regs[3]&1);
  1170. pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
  1171. pm[0]=(u16)(d>>16); pm[1]=(u16)d;
  1172. return;
  1173. }
  1174. // PCM
  1175. if ((a&0xff8000)==0xff0000) {
  1176. a &= 0x7fff;
  1177. if (a >= 0x2000) {
  1178. a >>= 1;
  1179. Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][a&0xfff] = (d >> 16);
  1180. Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a+1)&0xfff] = d;
  1181. } else if (a < 0x12) {
  1182. a >>= 1;
  1183. pcm_write(a, (d>>16) & 0xff);
  1184. pcm_write(a+1, d & 0xff);
  1185. }
  1186. return;
  1187. }
  1188. // bram
  1189. if ((a&0xff0000)==0xfe0000) {
  1190. dprintf("s68k_bram w32: [%06x] %08x @%06x", a, d, SekPcS68k);
  1191. a = (a>>1)&0x1fff;
  1192. Pico_mcd->bram[a++] = d >> 16; // middle endian? verify?
  1193. Pico_mcd->bram[a++] = d >> 24;
  1194. Pico_mcd->bram[a++] = d;
  1195. Pico_mcd->bram[a++] = d >> 8;
  1196. SRam.changed = 1;
  1197. return;
  1198. }
  1199. dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);
  1200. }
  1201. #endif
  1202. // -----------------------------------------------------------------
  1203. #if defined(EMU_C68K)
  1204. static __inline int PicoMemBaseM68k(u32 pc)
  1205. {
  1206. if ((pc&0xe00000)==0xe00000)
  1207. return (int)Pico.ram-(pc&0xff0000); // Program Counter in Ram
  1208. if (pc < 0x20000)
  1209. return (int)Pico_mcd->bios; // Program Counter in BIOS
  1210. if ((pc&0xfc0000)==0x200000)
  1211. {
  1212. if (!(Pico_mcd->s68k_regs[3]&4))
  1213. return (int)Pico_mcd->word_ram2M - 0x200000; // Program Counter in Word Ram
  1214. if (pc < 0x220000) {
  1215. int bank = (Pico_mcd->s68k_regs[3]&1);
  1216. return (int)Pico_mcd->word_ram1M[bank] - 0x200000;
  1217. }
  1218. }
  1219. // Error - Program Counter is invalid
  1220. dprintf("m68k FIXME: unhandled jump to %06x", pc);
  1221. return (int)Pico_mcd->bios;
  1222. }
  1223. static u32 PicoCheckPcM68k(u32 pc)
  1224. {
  1225. pc-=PicoCpu.membase; // Get real pc
  1226. pc&=0xfffffe;
  1227. PicoCpu.membase=PicoMemBaseM68k(pc);
  1228. return PicoCpu.membase+pc;
  1229. }
  1230. static __inline int PicoMemBaseS68k(u32 pc)
  1231. {
  1232. if (pc < 0x80000) // PRG RAM
  1233. return (int)Pico_mcd->prg_ram;
  1234. if ((pc&0xfc0000)==0x080000) // WORD RAM 2M area (assume we are in the right mode..)
  1235. return (int)Pico_mcd->word_ram2M - 0x080000;
  1236. if ((pc&0xfe0000)==0x0c0000) { // word RAM 1M area
  1237. int bank = !(Pico_mcd->s68k_regs[3]&1);
  1238. return (int)Pico_mcd->word_ram1M[bank] - 0x0c0000;
  1239. }
  1240. // Error - Program Counter is invalid
  1241. dprintf("s68k FIXME: unhandled jump to %06x", pc);
  1242. return (int)Pico_mcd->prg_ram;
  1243. }
  1244. static u32 PicoCheckPcS68k(u32 pc)
  1245. {
  1246. pc-=PicoCpuS68k.membase; // Get real pc
  1247. pc&=0xfffffe;
  1248. PicoCpuS68k.membase=PicoMemBaseS68k(pc);
  1249. return PicoCpuS68k.membase+pc;
  1250. }
  1251. #endif
  1252. PICO_INTERNAL void PicoMemSetupCD(void)
  1253. {
  1254. dprintf("PicoMemSetupCD()");
  1255. #ifdef EMU_C68K
  1256. // Setup m68k memory callbacks:
  1257. PicoCpu.checkpc=PicoCheckPcM68k;
  1258. PicoCpu.fetch8 =PicoCpu.read8 =PicoReadM68k8;
  1259. PicoCpu.fetch16=PicoCpu.read16=PicoReadM68k16;
  1260. PicoCpu.fetch32=PicoCpu.read32=PicoReadM68k32;
  1261. PicoCpu.write8 =PicoWriteM68k8;
  1262. PicoCpu.write16=PicoWriteM68k16;
  1263. PicoCpu.write32=PicoWriteM68k32;
  1264. // s68k
  1265. PicoCpuS68k.checkpc=PicoCheckPcS68k;
  1266. PicoCpuS68k.fetch8 =PicoCpuS68k.read8 =PicoReadS68k8;
  1267. PicoCpuS68k.fetch16=PicoCpuS68k.read16=PicoReadS68k16;
  1268. PicoCpuS68k.fetch32=PicoCpuS68k.read32=PicoReadS68k32;
  1269. PicoCpuS68k.write8 =PicoWriteS68k8;
  1270. PicoCpuS68k.write16=PicoWriteS68k16;
  1271. PicoCpuS68k.write32=PicoWriteS68k32;
  1272. #endif
  1273. // m68k_poll_addr = m68k_poll_cnt = 0;
  1274. s68k_poll_adclk = s68k_poll_cnt = 0;
  1275. }
  1276. #ifdef EMU_M68K
  1277. unsigned char PicoReadCD8w (unsigned int a) {
  1278. return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k8(a) : PicoReadM68k8(a);
  1279. }
  1280. unsigned short PicoReadCD16w(unsigned int a) {
  1281. return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k16(a) : PicoReadM68k16(a);
  1282. }
  1283. unsigned int PicoReadCD32w(unsigned int a) {
  1284. return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k32(a) : PicoReadM68k32(a);
  1285. }
  1286. void PicoWriteCD8w (unsigned int a, unsigned char d) {
  1287. if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k8(a, d); else PicoWriteM68k8(a, d);
  1288. }
  1289. void PicoWriteCD16w(unsigned int a, unsigned short d) {
  1290. if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k16(a, d); else PicoWriteM68k16(a, d);
  1291. }
  1292. void PicoWriteCD32w(unsigned int a, unsigned int d) {
  1293. if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k32(a, d); else PicoWriteM68k32(a, d);
  1294. }
  1295. // these are allowed to access RAM
  1296. unsigned int m68k_read_pcrelative_CD8 (unsigned int a) {
  1297. a&=0xffffff;
  1298. if(m68ki_cpu_p == &PicoS68kCPU) {
  1299. if (a < 0x80000) return *(u8 *)(Pico_mcd->prg_ram+(a^1)); // PRG Ram
  1300. if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)
  1301. return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));
  1302. if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)
  1303. int bank = !(Pico_mcd->s68k_regs[3]&1);
  1304. return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));
  1305. }
  1306. dprintf("s68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);
  1307. } else {
  1308. if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram
  1309. if(a<0x20000) return *(u8 *)(Pico.rom+(a^1)); // Bios
  1310. if((a&0xfc0000)==0x200000) { // word RAM
  1311. if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?
  1312. return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));
  1313. else if (a < 0x220000) {
  1314. int bank = Pico_mcd->s68k_regs[3]&1;
  1315. return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));
  1316. }
  1317. }
  1318. dprintf("m68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);
  1319. }
  1320. return 0;//(u8) lastread_d;
  1321. }
  1322. unsigned int m68k_read_pcrelative_CD16(unsigned int a) {
  1323. a&=0xffffff;
  1324. if(m68ki_cpu_p == &PicoS68kCPU) {
  1325. if (a < 0x80000) return *(u16 *)(Pico_mcd->prg_ram+(a&~1)); // PRG Ram
  1326. if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)
  1327. return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
  1328. if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)
  1329. int bank = !(Pico_mcd->s68k_regs[3]&1);
  1330. return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
  1331. }
  1332. dprintf("s68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);
  1333. } else {
  1334. if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram
  1335. if(a<0x20000) return *(u16 *)(Pico.rom+(a&~1)); // Bios
  1336. if((a&0xfc0000)==0x200000) { // word RAM
  1337. if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?
  1338. return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
  1339. else if (a < 0x220000) {
  1340. int bank = Pico_mcd->s68k_regs[3]&1;
  1341. return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
  1342. }
  1343. }
  1344. dprintf("m68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);
  1345. }
  1346. return 0;
  1347. }
  1348. unsigned int m68k_read_pcrelative_CD32(unsigned int a) {
  1349. u16 *pm;
  1350. a&=0xffffff;
  1351. if(m68ki_cpu_p == &PicoS68kCPU) {
  1352. if (a < 0x80000) { u16 *pm=(u16 *)(Pico_mcd->prg_ram+(a&~1)); return (pm[0]<<16)|pm[1]; } // PRG Ram
  1353. if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)
  1354. { pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }
  1355. if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)
  1356. int bank = !(Pico_mcd->s68k_regs[3]&1);
  1357. pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
  1358. return (pm[0]<<16)|pm[1];
  1359. }
  1360. dprintf("s68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);
  1361. } else {
  1362. if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram
  1363. if(a<0x20000) { u16 *pm=(u16 *)(Pico.rom+(a&~1)); return (pm[0]<<16)|pm[1]; }
  1364. if((a&0xfc0000)==0x200000) { // word RAM
  1365. if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?
  1366. { pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }
  1367. else if (a < 0x220000) {
  1368. int bank = Pico_mcd->s68k_regs[3]&1;
  1369. pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));
  1370. return (pm[0]<<16)|pm[1];
  1371. }
  1372. }
  1373. dprintf("m68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);
  1374. }
  1375. return 0;
  1376. }
  1377. #endif // EMU_M68K