32x: mode2 draw, debug, poll detection
[picodrive.git] / pico / 32x / memory.c
1 #include "../pico_int.h"
2 #include "../memory.h"
3
4 static const char str_mars[] = "MARS";
5
6 struct Pico32xMem *Pico32xMem;
7
8 static void bank_switch(int b);
9
10 #define MSB8(x) ((x) >> 8)
11
12 // poll detection
13 struct poll_det {
14         int addr, pc, cnt;
15 };
16 static struct poll_det m68k_poll;
17 static struct poll_det msh2_poll;
18
19 #define POLL_THRESHOLD 6
20
21 static int poll_detect(struct poll_det *pd, u32 a, u32 pc, int flag)
22 {
23   int ret = 0;
24
25   if (a - 2 <= pd->addr && pd->addr <= a + 2 && pd->pc == pc) {
26     pd->cnt++;
27     if (pd->cnt > POLL_THRESHOLD) {
28       if (!(Pico32x.emu_flags & flag)) {
29         elprintf(EL_32X, "%s poll addr %08x @ %06x",
30           flag == P32XF_68KPOLL ? "m68k" : (flag == P32XF_MSH2POLL ? "msh2" : "ssh2"), a, pc);
31         ret = 1;
32       }
33       Pico32x.emu_flags |= flag;
34     }
35   }
36   else
37     pd->cnt = 0;
38   pd->addr = a;
39   pd->pc = pc;
40
41   return ret;
42 }
43
44 static int poll_undetect(struct poll_det *pd, int flag)
45 {
46   int ret = 0;
47   if (pd->cnt > POLL_THRESHOLD)
48     ret = 1;
49   pd->addr = pd->cnt = 0;
50   Pico32x.emu_flags &= ~flag;
51   return ret;
52 }
53
54 // SH2 faking
55 //#define FAKE_SH2
56 int p32x_csum_faked;
57 #ifdef FAKE_SH2
58 static const u16 comm_fakevals[] = {
59   0x4d5f, 0x4f4b, // M_OK
60   0x535f, 0x4f4b, // S_OK
61   0x4D41, 0x5346, // MASF - Brutal Unleashed
62   0x5331, 0x4d31, // Darxide
63   0x5332, 0x4d32,
64   0x5333, 0x4d33,
65   0x0000, 0x0000, // eq for doom
66   0x0002, // Mortal Kombat
67 //  0, // pad
68 };
69
70 static u32 sh2_comm_faker(u32 a)
71 {
72   static int f = 0;
73   if (a == 0x28 && !p32x_csum_faked) {
74     p32x_csum_faked = 1;
75     return *(unsigned short *)(Pico.rom + 0x18e);
76   }
77   if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0]))
78     f = 0;
79   return comm_fakevals[f++];
80 }
81 #endif
82
83 static u32 p32x_reg_read16(u32 a)
84 {
85   a &= 0x3e;
86
87 #ifdef FAKE_SH2
88   if ((a & 0x30) == 0x20)
89     return sh2_comm_faker(a);
90 #else
91   if (poll_detect(&m68k_poll, a, SekPc, P32XF_68KPOLL)) {
92     SekSetStop(1);
93     SekEndRun(16);
94   }
95 #endif
96
97   return Pico32x.regs[a / 2];
98 }
99
100 static void p32x_reg_write8(u32 a, u32 d)
101 {
102   u16 *r = Pico32x.regs;
103   a &= 0x3f;
104
105   if (a == 1 && !(r[0] & 1)) {
106     r[0] |= 1;
107     Pico32xStartup();
108     return;
109   }
110
111   if (!(r[0] & 1))
112     return;
113
114   switch (a) {
115     case 0:
116       r[0] = (r[0] & 0x83) | ((d << 8) & P32XS_FM);
117       break;
118     case 5:
119       d &= 7;
120       if (r[4/2] != d) {
121         r[4/2] = d;
122         bank_switch(d);
123       }
124       break;
125   }
126 }
127
128 static void p32x_reg_write16(u32 a, u32 d)
129 {
130   u16 *r = Pico32x.regs;
131   a &= 0x3e;
132
133   switch (a) {
134     case 0:
135       r[0] = (r[0] & 0x83) | (d & P32XS_FM);
136       return;
137   }
138
139   if ((a & 0x30) == 0x20) {
140     r[a / 2] = d;
141     poll_undetect(&msh2_poll, P32XF_MSH2POLL);
142     return;
143   }
144
145   p32x_reg_write8(a + 1, d);
146 }
147
148 // VDP regs
149 static u32 p32x_vdp_read16(u32 a)
150 {
151   a &= 0x0e;
152
153   return Pico32x.vdp_regs[a / 2];
154 }
155
156 static void p32x_vdp_write8(u32 a, u32 d)
157 {
158   u16 *r = Pico32x.vdp_regs;
159   a &= 0x0f;
160
161   // TODO: verify what's writeable
162   switch (a) {
163     case 0x01:
164       if (((r[0] & 3) == 0) != ((d & 3) == 0)) { // forced blanking changed
165         if (Pico.video.status & 8)
166           r[0x0a/2] |=  P32XV_VBLK;
167         else
168           r[0x0a/2] &= ~P32XV_VBLK;
169       }
170       // priority inversion is handled in palette
171       if ((r[0] ^ d) & P32XV_PRI)
172         Pico32x.dirty_pal = 1;
173       r[0] = (r[0] & P32XV_nPAL) | (d & 0xff);
174       break;
175     case 0x0b:
176       d &= 1;
177       Pico32x.pending_fb = d;
178       // if we are blanking and FS bit is changing
179       if ((r[0x0a/2] & P32XV_VBLK) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
180         r[0x0a/2] ^= 1;
181         Pico32xSwapDRAM(d ^ 1);
182         elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS);
183       }
184       break;
185   }
186 }
187
188 static void p32x_vdp_write16(u32 a, u32 d)
189 {
190   p32x_vdp_write8(a | 1, d);
191 }
192
193 // SH2 regs
194 static u32 p32x_sh2reg_read16(u32 a)
195 {
196   a &= 0xff; // ?
197
198   if (poll_detect(&msh2_poll, a, ash2_pc(), P32XF_MSH2POLL))
199     ash2_end_run(8);
200
201   if (a == 0) {
202     return (Pico32x.regs[0] & P32XS_FM) | P32XS2_ADEN;
203   }
204   if ((a & 0x30) == 0x20)
205     return Pico32x.regs[a / 2];
206
207   return 0;
208 }
209
210 static void p32x_sh2reg_write8(u32 a, u32 d)
211 {
212 }
213
214 static void p32x_sh2reg_write16(u32 a, u32 d)
215 {
216   a &= 0xff;
217
218   if ((a & 0x30) == 0x20) {
219     Pico32x.regs[a/2] = d;
220     if (poll_undetect(&m68k_poll, P32XF_68KPOLL))
221       // dangerous, but let's just assume 68k program
222       // didn't issue STOP itself.
223       SekSetStop(0);
224     return;
225   }
226
227   p32x_sh2reg_write8(a | 1, d);
228 }
229
230 // default 32x handlers
231 u32 PicoRead8_32x(u32 a)
232 {
233   u32 d = 0;
234   if ((a & 0xffc0) == 0x5100) { // a15100
235     d = p32x_reg_read16(a);
236     goto out_16to8;
237   }
238
239   if (!(Pico32x.regs[0] & 1))
240     goto no_vdp;
241
242   if ((a & 0xfff0) == 0x5180) { // a15180
243     d = p32x_vdp_read16(a);
244     goto out_16to8;
245   }
246
247   if ((a & 0xfe00) == 0x5200) { // a15200
248     d = Pico32xMem->pal[(a & 0x1ff) / 2];
249     goto out_16to8;
250   }
251
252 no_vdp:
253   if ((a & 0xfffc) == 0x30ec) { // a130ec
254     d = str_mars[a & 3];
255     goto out;
256   }
257
258   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
259   return d;
260
261 out_16to8:
262   if (a & 1)
263     d &= 0xff;
264   else
265     d >>= 8;
266
267 out:
268   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
269   return d;
270 }
271
272 u32 PicoRead16_32x(u32 a)
273 {
274   u32 d = 0;
275   if ((a & 0xffc0) == 0x5100) { // a15100
276     d = p32x_reg_read16(a);
277     goto out;
278   }
279
280   if (!(Pico32x.regs[0] & 1))
281     goto no_vdp;
282
283   if ((a & 0xfff0) == 0x5180) { // a15180
284     d = p32x_vdp_read16(a);
285     goto out;
286   }
287
288   if ((a & 0xfe00) == 0x5200) { // a15200
289     d = Pico32xMem->pal[(a & 0x1ff) / 2];
290     goto out;
291   }
292
293 no_vdp:
294   if ((a & 0xfffc) == 0x30ec) { // a130ec
295     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
296     goto out;
297   }
298
299   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
300   return d;
301
302 out:
303   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
304   return d;
305 }
306
307 void PicoWrite8_32x(u32 a, u32 d)
308 {
309   if ((a & 0xfc00) == 0x5000)
310     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
311
312   if ((a & 0xffc0) == 0x5100) { // a15100
313     p32x_reg_write8(a, d);
314     return;
315   }
316
317   if (!(Pico32x.regs[0] & 1))
318     goto no_vdp;
319
320   if ((a & 0xfff0) == 0x5180) { // a15180
321     p32x_vdp_write8(a, d);
322     return;
323   }
324
325   // TODO: verify
326   if ((a & 0xfe00) == 0x5200) { // a15200
327     elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
328     ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
329     Pico32x.dirty_pal = 1;
330     return;
331   }
332
333 no_vdp:
334   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
335 }
336
337 void PicoWrite16_32x(u32 a, u32 d)
338 {
339   if ((a & 0xfc00) == 0x5000)
340     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
341
342   if ((a & 0xffc0) == 0x5100) { // a15100
343     p32x_reg_write16(a, d);
344     return;
345   }
346
347   if (!(Pico32x.regs[0] & 1))
348     goto no_vdp;
349
350   if ((a & 0xfff0) == 0x5180) { // a15180
351     p32x_vdp_write16(a, d);
352     return;
353   }
354
355   if ((a & 0xfe00) == 0x5200) { // a15200
356     Pico32xMem->pal[(a & 0x1ff) / 2] = d;
357     Pico32x.dirty_pal = 1;
358     return;
359   }
360
361 no_vdp:
362   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
363 }
364
365 // hint vector is writeable
366 static void PicoWrite8_hint(u32 a, u32 d)
367 {
368   if ((a & 0xfffc) == 0x0070) {
369     Pico32xMem->m68k_rom[a ^ 1] = d;
370     return;
371   }
372
373   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
374 }
375
376 static void PicoWrite16_hint(u32 a, u32 d)
377 {
378   if ((a & 0xfffc) == 0x0070) {
379     ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
380     return;
381   }
382
383   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
384 }
385
386 void Pico32xSwapDRAM(int b)
387 {
388   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
389   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
390   cpu68k_map_set(m68k_write8_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
391   cpu68k_map_set(m68k_write16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
392 }
393
394 static void bank_switch(int b)
395 {
396   unsigned int rs, bank;
397
398   bank = b << 20;
399   if (bank >= Pico.romsize) {
400     elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
401     return;
402   }
403
404   // 32X ROM (unbanked, XXX: consider mirroring?)
405   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
406   rs -= bank;
407   if (rs > 0x100000)
408     rs = 0x100000;
409   cpu68k_map_set(m68k_read8_map,   0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
410   cpu68k_map_set(m68k_read16_map,  0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
411
412   elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
413 }
414
415 // -----------------------------------------------------------------
416 //                              SH2  
417 // -----------------------------------------------------------------
418
419 u32 pico32x_read8(u32 a)
420 {
421   u32 d = 0;
422   if (a < sizeof(Pico32xMem->sh2_rom_m))
423     return Pico32xMem->sh2_rom_m[a ^ 1];
424
425   if ((a & 0x0ffc0000) == 0x06000000)
426     return Pico32xMem->sdram[(a & 0x3ffff) ^ 1];
427
428   if ((a & 0x0fc00000) == 0x02000000)
429     if ((a & 0x003fffff) < Pico.romsize)
430       return Pico.rom[(a & 0x3fffff) ^ 1];
431
432   if ((a & 0x0fffff00) == 0x4000) {
433     d = p32x_sh2reg_read16(a);
434     goto out_16to8;
435   }
436
437   if ((a & 0x0fffff00) == 0x4100) {
438     d = p32x_vdp_read16(a);
439     goto out_16to8;
440   }
441
442   if ((a & 0x0fffff00) == 0x4200) {
443     d = Pico32xMem->pal[(a & 0x1ff) / 2];
444     goto out_16to8;
445   }
446
447   elprintf(EL_UIO, "sh2 unmapped r8  [%08x]       %02x @%06x", a, d, ash2_pc());
448   return d;
449
450 out_16to8:
451   if (a & 1)
452     d &= 0xff;
453   else
454     d >>= 8;
455
456   elprintf(EL_32X, "sh2 r8  [%08x]       %02x @%06x", a, d, ash2_pc());
457   return d;
458 }
459
460 u32 pico32x_read16(u32 a)
461 {
462   u32 d = 0;
463   if (a < sizeof(Pico32xMem->sh2_rom_m))
464     return *(u16 *)(Pico32xMem->sh2_rom_m + a);
465
466   if ((a & 0x0ffc0000) == 0x06000000)
467     return ((u16 *)Pico32xMem->sdram)[(a & 0x3ffff) / 2];
468
469   if ((a & 0x0fc00000) == 0x02000000)
470     if ((a & 0x003fffff) < Pico.romsize)
471       return ((u16 *)Pico.rom)[(a & 0x3fffff) / 2];
472
473   if ((a & 0x0fffff00) == 0x4000) {
474     d = p32x_sh2reg_read16(a);
475     goto out;
476   }
477
478   if ((a & 0x0fffff00) == 0x4100) {
479     d = p32x_vdp_read16(a);
480     goto out;
481   }
482
483   if ((a & 0x0fffff00) == 0x4200) {
484     d = Pico32xMem->pal[(a & 0x1ff) / 2];
485     goto out;
486   }
487
488   elprintf(EL_UIO, "sh2 unmapped r16 [%08x]     %04x @%06x", a, d, ash2_pc());
489   return d;
490
491 out:
492   elprintf(EL_32X, "sh2 r16 [%08x]     %04x @%06x", a, d, ash2_pc());
493   return d;
494 }
495
496 u32 pico32x_read32(u32 a)
497 {
498 //  elprintf(EL_UIO, "sh2 r32 [%08x] %08x @%06x", a, d, ash2_pc());
499   return (pico32x_read16(a) << 16) | pico32x_read16(a + 2);
500 }
501
502 void pico32x_write8(u32 a, u32 d)
503 {
504   if ((a & 0x0ffffc00) == 0x4000)
505     elprintf(EL_32X, "sh2 w8  [%08x]       %02x @%06x", a, d & 0xff, ash2_pc());
506
507   if ((a & 0x0ffc0000) == 0x06000000) {
508     Pico32xMem->sdram[(a & 0x3ffff) ^ 1] = d;
509     return;
510   }
511
512   if ((a & 0x0ffe0000) == 0x04000000) {
513     u8 *dram = (u8 *)Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
514     dram[(a & 0x1ffff) ^ 1] = d;
515     return;
516   }
517
518   if ((a & 0x0fffff00) == 0x4100) {
519     p32x_vdp_write8(a, d);
520     return;
521   }
522
523   if ((a & 0x0fffff00) == 0x4000) {
524     p32x_sh2reg_write8(a, d);
525     return;
526   }
527
528   elprintf(EL_UIO, "sh2 unmapped w8  [%08x]       %02x @%06x", a, d & 0xff, ash2_pc());
529 }
530
531 void pico32x_write16(u32 a, u32 d)
532 {
533   if ((a & 0x0ffffc00) == 0x4000)
534     elprintf(EL_32X, "sh2 w16 [%08x]     %04x @%06x", a, d & 0xffff, ash2_pc());
535
536   if ((a & 0x0ffc0000) == 0x06000000) {
537     ((u16 *)Pico32xMem->sdram)[(a & 0x3ffff) / 2] = d;
538     return;
539   }
540
541   if ((a & 0x0ffe0000) == 0x04000000) {
542     Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1][(a & 0x1ffff) / 2] = d;
543     return;
544   }
545
546   if ((a & 0x0fffff00) == 0x4100) {
547     p32x_vdp_write16(a, d);
548     return;
549   }
550
551   if ((a & 0x0ffffe00) == 0x4200) {
552     Pico32xMem->pal[(a & 0x1ff) / 2] = d;
553     Pico32x.dirty_pal = 1;
554     return;
555   }
556
557   if ((a & 0x0fffff00) == 0x4000) {
558     p32x_sh2reg_write16(a, d);
559     return;
560   }
561
562   elprintf(EL_UIO, "sh2 unmapped w16 [%08x]     %04x @%06x", a, d & 0xffff, ash2_pc());
563 }
564
565 void pico32x_write32(u32 a, u32 d)
566 {
567 //  elprintf(EL_UIO, "sh2 w32 [%08x] %08x @%06x", a, d, ash2_pc());
568   pico32x_write16(a, d >> 16);
569   pico32x_write16(a + 2, d);
570 }
571
572 #define HWSWAP(x) (((x) << 16) | ((x) >> 16))
573 void PicoMemSetup32x(void)
574 {
575   unsigned short *ps;
576   unsigned int *pl;
577   unsigned int rs;
578   int i;
579
580   Pico32xMem = calloc(1, sizeof(*Pico32xMem));
581   if (Pico32xMem == NULL) {
582     elprintf(EL_STATUS, "OOM");
583     return;
584   }
585
586   // generate 68k ROM
587   ps = (unsigned short *)Pico32xMem->m68k_rom;
588   pl = (unsigned int *)Pico32xMem->m68k_rom;
589   for (i = 1; i < 0xc0/4; i++)
590     pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
591
592   // fill with nops
593   for (i = 0xc0/2; i < 0x100/2; i++)
594     ps[i] = 0x4e71;
595
596 #if 0
597   ps[0xc0/2] = 0x46fc;
598   ps[0xc2/2] = 0x2700; // move #0x2700,sr
599   ps[0xfe/2] = 0x60fe; // jump to self
600 #else
601   ps[0xfe/2] = 0x4e75; // rts
602 #endif
603
604   // fill remaining mem with ROM
605   memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, sizeof(Pico32xMem->m68k_rom) - 0x100);
606
607   // 32X ROM
608   // TODO: move
609   {
610     FILE *f = fopen("32X_M_BIOS.BIN", "rb");
611     int i;
612     if (f == NULL) {
613       printf("missing BIOS\n");
614       exit(1);
615     }
616     fread(Pico32xMem->sh2_rom_m, 1, sizeof(Pico32xMem->sh2_rom_m), f);
617     fclose(f);
618     for (i = 0; i < sizeof(Pico32xMem->sh2_rom_m); i += 2) {
619       int t = Pico32xMem->sh2_rom_m[i];
620       Pico32xMem->sh2_rom_m[i] = Pico32xMem->sh2_rom_m[i + 1];
621       Pico32xMem->sh2_rom_m[i + 1] = t;
622     }
623   }
624
625   // cartridge area becomes unmapped
626   // XXX: we take the easy way and don't unmap ROM,
627   // so that we can avoid handling the RV bit.
628   // m68k_map_unmap(0x000000, 0x3fffff);
629
630   // MD ROM area
631   rs = sizeof(Pico32xMem->m68k_rom);
632   cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
633   cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
634   cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
635   cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
636
637   // DRAM area
638   Pico32xSwapDRAM(1);
639
640   // 32X ROM (unbanked, XXX: consider mirroring?)
641   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
642   if (rs > 0x80000)
643     rs = 0x80000;
644   cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
645   cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
646
647   // 32X ROM (banked)
648   bank_switch(0);
649 }
650