PCM sound, refactored code940
[picodrive.git] / Pico / cd / Memory.c
index 05299e6..ff787b0 100644 (file)
@@ -17,6 +17,7 @@
 #include "../sound/sn76496.h"\r
 \r
 #include "gfx_cd.h"\r
+#include "pcm.h"\r
 \r
 typedef unsigned char  u8;\r
 typedef unsigned short u16;\r
@@ -161,7 +162,8 @@ static u32 s68k_reg_read16(u32 a)
       goto end;\r
     case 0xC:\r
       dprintf("s68k stopwatch timer read");\r
-      break;\r
+      d = Pico_mcd->m.timer_stopwatch >> 16;\r
+      goto end;\r
     case 0x30:\r
       dprintf("s68k int3 timer read");\r
       break;\r
@@ -212,10 +214,13 @@ static void s68k_reg_write8(u32 a, u32 d)
       dprintf("s68k set CDC dma addr");\r
       break;\r
     case 0xc:\r
+    case 0xd:\r
       dprintf("s68k set stopwatch timer");\r
-      break;\r
+      Pico_mcd->m.timer_stopwatch = 0;\r
+      return;\r
     case 0x31:\r
-      dprintf("s68k set int3 timer");\r
+      dprintf("s68k set int3 timer: %02x", d);\r
+      Pico_mcd->m.timer_int3 = d << 16;\r
       break;\r
     case 0x33: // IRQ mask\r
       dprintf("s68k irq mask: %02x", d);\r
@@ -830,6 +835,21 @@ u8 PicoReadS68k8(u32 a)
     goto end;\r
   }\r
 \r
+  // PCM\r
+  if ((a&0xff8000)==0xff0000) {\r
+    dprintf("s68k_pcm r8: [%06x] @%06x", a, SekPc);\r
+    a &= 0x7fff;\r
+    if (a >= 0x2000)\r
+      d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff];\r
+    else if (a >= 0x20) {\r
+      a &= 0x1e;\r
+      d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;\r
+      if (a & 2) d >>= 8;\r
+    }\r
+    dprintf("ret = %02x", (u8)d);\r
+    goto end;\r
+  }\r
+\r
   // bram\r
   if ((a&0xff0000)==0xfe0000) {\r
     d = Pico_mcd->bram[(a>>1)&0x1fff];\r
@@ -849,7 +869,7 @@ u8 PicoReadS68k8(u32 a)
 \r
 u16 PicoReadS68k16(u32 a)\r
 {\r
-  u16 d=0;\r
+  u32 d=0;\r
 \r
   a&=0xfffffe;\r
 \r
@@ -898,12 +918,27 @@ u16 PicoReadS68k16(u32 a)
   if ((a&0xff0000)==0xfe0000) {\r
     dprintf("s68k_bram r16: [%06x] @%06x", a, SekPc);\r
     a = (a>>1)&0x1fff;\r
-    d = Pico_mcd->bram[a++];           // Gens does little endian here, an so do we..\r
+    d = Pico_mcd->bram[a++];           // Gens does little endian here, and so do we..\r
     d|= Pico_mcd->bram[a++] << 8;\r
     dprintf("ret = %04x", d);\r
     goto end;\r
   }\r
 \r
+  // PCM\r
+  if ((a&0xff8000)==0xff0000) {\r
+    dprintf("s68k_pcm r16: [%06x] @%06x", a, SekPc);\r
+    a &= 0x7fff;\r
+    if (a >= 0x2000)\r
+      d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff];\r
+    else if (a >= 0x20) {\r
+      a &= 0x1e;\r
+      d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;\r
+      if (a & 2) d >>= 8;\r
+    }\r
+    dprintf("ret = %04x", d);\r
+    goto end;\r
+  }\r
+\r
   dprintf("s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
 \r
   end:\r
@@ -964,6 +999,29 @@ u32 PicoReadS68k32(u32 a)
     goto end;\r
   }\r
 \r
+  // PCM\r
+  if ((a&0xff8000)==0xff0000) {\r
+    dprintf("s68k_pcm r32: [%06x] @%06x", a, SekPc);\r
+    a &= 0x7fff;\r
+    if (a >= 0x2000) {\r
+      a >>= 1;\r
+      d  = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][a&0xfff] << 16;\r
+      d |= Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a+1)&0xfff];\r
+    } else if (a >= 0x20) {\r
+      a &= 0x1e;\r
+      if (a & 2) {\r
+        a >>= 2;\r
+        d  = (Pico_mcd->pcm.ch[a].addr >> (PCM_STEP_SHIFT-8)) & 0xff0000;\r
+        d |= (Pico_mcd->pcm.ch[(a+1)&7].addr >> PCM_STEP_SHIFT)   & 0xff;\r
+      } else {\r
+        d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;\r
+        d = ((d<<16)&0xff0000) | ((d>>8)&0xff); // PCM chip is LE\r
+      }\r
+    }\r
+    dprintf("ret = %08x", d);\r
+    goto end;\r
+  }\r
+\r
   // bram\r
   if ((a&0xff0000)==0xfe0000) {\r
     dprintf("s68k_bram r32: [%06x] @%06x", a, SekPc);\r
@@ -1004,9 +1062,6 @@ void PicoWriteS68k8(u32 a,u8 d)
     return;\r
   }\r
 \r
-  if (a != 0xff0011 && (a&0xff8000) == 0xff0000) // PCM hack\r
-    return;\r
-\r
   // regs\r
   if ((a&0xfffe00) == 0xff8000) {\r
     a &= 0x1ff;\r
@@ -1040,6 +1095,16 @@ void PicoWriteS68k8(u32 a,u8 d)
     return;\r
   }\r
 \r
+  // PCM\r
+  if ((a&0xff8000)==0xff0000) {\r
+    a &= 0x7fff;\r
+    if (a >= 0x2000)\r
+      Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d;\r
+    else if (a < 0x12)\r
+      pcm_write(a>>1, d);\r
+    return;\r
+  }\r
+\r
   // bram\r
   if ((a&0xff0000)==0xfe0000) {\r
     Pico_mcd->bram[(a>>1)&0x1fff] = d;\r
@@ -1101,6 +1166,16 @@ void PicoWriteS68k16(u32 a,u16 d)
     return;\r
   }\r
 \r
+  // PCM\r
+  if ((a&0xff8000)==0xff0000) {\r
+    a &= 0x7fff;\r
+    if (a >= 0x2000)\r
+      Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d;\r
+    else if (a < 0x12)\r
+      pcm_write(a>>1, d & 0xff);\r
+    return;\r
+  }\r
+\r
   // bram\r
   if ((a&0xff0000)==0xfe0000) {\r
     dprintf("s68k_bram w16: [%06x] %04x @%06x", a, d, SekPc);\r
@@ -1171,6 +1246,21 @@ void PicoWriteS68k32(u32 a,u32 d)
     return;\r
   }\r
 \r
+  // PCM\r
+  if ((a&0xff8000)==0xff0000) {\r
+    a &= 0x7fff;\r
+    if (a >= 0x2000) {\r
+      a >>= 1;\r
+      Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][a&0xfff] = (d >> 16);\r
+      Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a+1)&0xfff] = d;\r
+    } else if (a < 0x12) {\r
+      a >>= 1;\r
+      pcm_write(a,  (d>>16) & 0xff);\r
+      pcm_write(a+1, d & 0xff);\r
+    }\r
+    return;\r
+  }\r
+\r
   // bram\r
   if ((a&0xff0000)==0xfe0000) {\r
     dprintf("s68k_bram w32: [%06x] %08x @%06x", a, d, SekPc);\r