32x: preliminary PWM implementation. 32x opts in menu
[picodrive.git] / pico / memory.c
index 2eaac2a..d36ac62 100644 (file)
@@ -21,7 +21,7 @@ unsigned long m68k_write8_map [0x1000000 >> M68K_MEM_SHIFT];
 unsigned long m68k_write16_map[0x1000000 >> M68K_MEM_SHIFT];\r
 \r
 static void xmap_set(unsigned long *map, int shift, int start_addr, int end_addr,\r
-    void *func_or_mh, int is_func)\r
+    const void *func_or_mh, int is_func)\r
 {\r
   unsigned long addr = (unsigned long)func_or_mh;\r
   int mask = (1 << shift) - 1;\r
@@ -49,13 +49,13 @@ static void xmap_set(unsigned long *map, int shift, int start_addr, int end_addr
 }\r
 \r
 void z80_map_set(unsigned long *map, int start_addr, int end_addr,\r
-    void *func_or_mh, int is_func)\r
+    const void *func_or_mh, int is_func)\r
 {\r
   xmap_set(map, Z80_MEM_SHIFT, start_addr, end_addr, func_or_mh, is_func);\r
 }\r
 \r
 void cpu68k_map_set(unsigned long *map, int start_addr, int end_addr,\r
-    void *func_or_mh, int is_func)\r
+    const void *func_or_mh, int is_func)\r
 {\r
   xmap_set(map, M68K_MEM_SHIFT, start_addr, end_addr, func_or_mh, is_func);\r
 }\r
@@ -144,6 +144,10 @@ static u32 ym2612_read_local_68k(void);
 static int ym2612_write_local(u32 a, u32 d, int is_from_z80);\r
 static void z80_mem_setup(void);\r
 \r
+#ifdef _ASM_MEMORY_C\r
+u32 PicoRead8_sram(u32 a);\r
+u32 PicoRead16_sram(u32 a);\r
+#endif\r
 \r
 #ifdef EMU_CORE_DEBUG\r
 u32 lastread_a, lastread_d[16]={0,}, lastwrite_cyc_d[16]={0,}, lastwrite_mus_d[16]={0,};\r
@@ -160,61 +164,22 @@ void log_io(unsigned int addr, int bits, int rw);
 #endif\r
 \r
 #if defined(EMU_C68K)\r
-static __inline int PicoMemBase(u32 pc)\r
+void cyclone_crashed(u32 pc, struct Cyclone *context)\r
 {\r
-  int membase=0;\r
-\r
-  if (pc<Pico.romsize+4)\r
-  {\r
-    membase=(int)Pico.rom; // Program Counter in Rom\r
-  }\r
-  else if ((pc&0xe00000)==0xe00000)\r
-  {\r
-    membase=(int)Pico.ram-(pc&0xff0000); // Program Counter in Ram\r
-  }\r
-  else\r
-  {\r
-    // Error - Program Counter is invalid\r
-    membase=(int)Pico.rom;\r
-  }\r
-\r
-  return membase;\r
+    elprintf(EL_STATUS|EL_ANOMALY, "%c68k crash detected @ %06x\n",\r
+      context == &PicoCpuCM68k ? 'm' : 's', pc);\r
+    context->membase = (u32)Pico.rom;\r
+    context->pc = (u32)Pico.rom + Pico.romsize;\r
 }\r
 #endif\r
 \r
-\r
-PICO_INTERNAL u32 PicoCheckPc(u32 pc)\r
-{\r
-  u32 ret=0;\r
-#if defined(EMU_C68K)\r
-  pc-=PicoCpuCM68k.membase; // Get real pc\r
-//  pc&=0xfffffe;\r
-  pc&=~1;\r
-  if ((pc<<8) == 0)\r
-  {\r
-    elprintf(EL_STATUS|EL_ANOMALY, "%i:%03i: game crash detected @ %06x\n",\r
-      Pico.m.frame_count, Pico.m.scanline, SekPc);\r
-    return (int)Pico.rom + Pico.romsize; // common crash condition, may happen with bad ROMs\r
-  }\r
-\r
-  PicoCpuCM68k.membase=PicoMemBase(pc&0x00ffffff);\r
-  PicoCpuCM68k.membase-=pc&0xff000000;\r
-\r
-  ret = PicoCpuCM68k.membase+pc;\r
-#endif\r
-  return ret;\r
-}\r
-\r
-\r
-PICO_INTERNAL void PicoInitPc(u32 pc)\r
-{\r
-  PicoCheckPc(pc);\r
-}\r
-\r
 // -----------------------------------------------------------------\r
 // memmap helpers\r
 \r
-static int PadRead(int i)\r
+#ifndef _ASM_MEMORY_C\r
+static\r
+#endif\r
+int PadRead(int i)\r
 {\r
   int pad,value,data_reg;\r
   pad=~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU\r
@@ -246,6 +211,8 @@ static int PadRead(int i)
   return value; // will mirror later\r
 }\r
 \r
+#ifndef _ASM_MEMORY_C\r
+\r
 static u32 io_ports_read(u32 a)\r
 {\r
   u32 d;\r
@@ -259,7 +226,7 @@ static u32 io_ports_read(u32 a)
   return d;\r
 }\r
 \r
-static void io_ports_write(u32 a, u32 d)\r
+static void NOINLINE io_ports_write(u32 a, u32 d)\r
 {\r
   a = (a>>1) & 0xf;\r
 \r
@@ -271,11 +238,13 @@ static void io_ports_write(u32 a, u32 d)
       Pico.m.padTHPhase[a - 1]++;\r
   }\r
 \r
-  // cartain IO ports can be used as RAM\r
+  // certain IO ports can be used as RAM\r
   Pico.ioports[a] = d;\r
 }\r
 \r
-static void ctl_write_z80busreq(u32 d)\r
+#endif // _ASM_MEMORY_C\r
+\r
+void NOINLINE ctl_write_z80busreq(u32 d)\r
 {\r
   d&=1; d^=1;\r
   elprintf(EL_BUSREQ, "set_zrun: %i->%i [%i] @%06x", Pico.m.z80Run, d, SekCyclesDone(), SekPc);\r
@@ -295,7 +264,7 @@ static void ctl_write_z80busreq(u32 d)
   }\r
 }\r
 \r
-static void ctl_write_z80reset(u32 d)\r
+void NOINLINE ctl_write_z80reset(u32 d)\r
 {\r
   d&=1; d^=1;\r
   elprintf(EL_BUSREQ, "set_zreset: %i->%i [%i] @%06x", Pico.m.z80_reset, d, SekCyclesDone(), SekPc);\r
@@ -317,95 +286,10 @@ static void ctl_write_z80reset(u32 d)
   }\r
 }\r
 \r
-\r
-// for nonstandard reads\r
-// TODO: mv to carthw\r
-u32 OtherRead16End(u32 a, int realsize)\r
-{\r
-  u32 d=0;\r
-\r
-  // 32x test\r
-/*\r
-  if      (a == 0xa130ec) { d = 0x4d41; goto end; } // MA\r
-  else if (a == 0xa130ee) { d = 0x5253; goto end; } // RS\r
-  else if (a == 0xa15100) { d = 0x0080; goto end; }\r
-  else\r
-*/\r
-\r
-  // for games with simple protection devices, discovered by Haze\r
-  // some dumb detection is used, but that should be enough to make things work\r
-  if ((a>>22) == 1 && Pico.romsize >= 512*1024) {\r
-    if      (*(int *)(Pico.rom+0x123e4) == 0x00550c39 && *(int *)(Pico.rom+0x123e8) == 0x00000040) { // Super Bubble Bobble (Unl) [!]\r
-      if      (a == 0x400000) { d=0x55<<8; goto end; }\r
-      else if (a == 0x400002) { d=0x0f<<8; goto end; }\r
-    }\r
-    else if (*(int *)(Pico.rom+0x008c4) == 0x66240055 && *(int *)(Pico.rom+0x008c8) == 0x00404df9) { // Smart Mouse (Unl)\r
-      if      (a == 0x400000) { d=0x55<<8; goto end; }\r
-      else if (a == 0x400002) { d=0x0f<<8; goto end; }\r
-      else if (a == 0x400004) { d=0xaa<<8; goto end; }\r
-      else if (a == 0x400006) { d=0xf0<<8; goto end; }\r
-    }\r
-    else if (*(int *)(Pico.rom+0x00404) == 0x00a90600 && *(int *)(Pico.rom+0x00408) == 0x6708b013) { // King of Fighters '98, The (Unl) [!]\r
-      if      (a == 0x480000 || a == 0x4800e0 || a == 0x4824a0 || a == 0x488880) { d=0xaa<<8; goto end; }\r
-      else if (a == 0x4a8820) { d=0x0a<<8; goto end; }\r
-      // there is also a read @ 0x4F8820 which needs 0, but that is returned in default case\r
-    }\r
-    else if (*(int *)(Pico.rom+0x01b24) == 0x004013f9 && *(int *)(Pico.rom+0x01b28) == 0x00ff0000) { // Mahjong Lover (Unl) [!]\r
-      if      (a == 0x400000) { d=0x90<<8; goto end; }\r
-      else if (a == 0x401000) { d=0xd3<<8; goto end; } // this one doesn't seem to be needed, the code does 2 comparisons and only then\r
-                                                       // checks the result, which is of the above one. Left it just in case.\r
-    }\r
-    else if (*(int *)(Pico.rom+0x05254) == 0x0c3962d0 && *(int *)(Pico.rom+0x05258) == 0x00400055) { // Elf Wor (Unl)\r
-      if      (a == 0x400000) { d=0x55<<8; goto end; }\r
-      else if (a == 0x400004) { d=0xc9<<8; goto end; } // this check is done if the above one fails\r
-      else if (a == 0x400002) { d=0x0f<<8; goto end; }\r
-      else if (a == 0x400006) { d=0x18<<8; goto end; } // similar to above\r
-    }\r
-    // our default behaviour is to return whatever was last written a 0x400000-0x7fffff range (used by Squirrel King (R) [!])\r
-    // Lion King II, The (Unl) [!]  writes @ 400000 and wants to get that val @ 400002 and wites another val\r
-    // @ 400004 which is expected @ 400006, so we really remember 2 values here\r
-///    d = Pico.m.prot_bytes[(a>>2)&1]<<8;\r
-  }\r
-  else if (a == 0xa13000 && Pico.romsize >= 1024*1024) {\r
-    if      (*(int *)(Pico.rom+0xc8af0) == 0x30133013 && *(int *)(Pico.rom+0xc8af4) == 0x000f0240) { // Rockman X3 (Unl) [!]\r
-      d=0x0c; goto end;\r
-    }\r
-    else if (*(int *)(Pico.rom+0x28888) == 0x07fc0000 && *(int *)(Pico.rom+0x2888c) == 0x4eb94e75) { // Bug's Life, A (Unl) [!]\r
-      d=0x28; goto end; // does the check from RAM\r
-    }\r
-    else if (*(int *)(Pico.rom+0xc8778) == 0x30133013 && *(int *)(Pico.rom+0xc877c) == 0x000f0240) { // Super Mario Bros. (Unl) [!]\r
-      d=0x0c; goto end; // seems to be the same code as in Rockman X3 (Unl) [!]\r
-    }\r
-    else if (*(int *)(Pico.rom+0xf20ec) == 0x30143013 && *(int *)(Pico.rom+0xf20f0) == 0x000f0200) { // Super Mario 2 1998 (Unl) [!]\r
-      d=0x0a; goto end;\r
-    }\r
-  }\r
-  else if (a == 0xa13002) { // Pocket Monsters (Unl)\r
-    d=0x01; goto end;\r
-  }\r
-  else if (a == 0xa1303E) { // Pocket Monsters (Unl)\r
-    d=0x1f; goto end;\r
-  }\r
-  else if (a == 0x30fe02) {\r
-    // Virtua Racing - just for fun\r
-    // this seems to be some flag that SVP is ready or something similar\r
-    d=1; goto end;\r
-  }\r
-\r
-end:\r
-  elprintf(EL_UIO, "strange r%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);\r
-  return d;\r
-}\r
-\r
-void OtherWrite8End(u32 a,u32 d,int realsize)\r
-{\r
-  // for games with simple protection devices, discovered by Haze\r
-  if ((a>>22) == 1)\r
-;///    Pico.m.prot_bytes[(a>>2)&1] = (u8)d;\r
-}\r
-\r
 // -----------------------------------------------------------------\r
 \r
+#ifndef _ASM_MEMORY_C\r
+\r
 // cart (save) RAM area (usually 0x200000 - ...)\r
 static u32 PicoRead8_sram(u32 a)\r
 {\r
@@ -451,6 +335,8 @@ static u32 PicoRead16_sram(u32 a)
   return m68k_unmapped_read16(a);\r
 }\r
 \r
+#endif // _ASM_MEMORY_C\r
+\r
 static void PicoWrite8_sram(u32 a, u32 d)\r
 {\r
   if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) {\r
@@ -544,7 +430,6 @@ static void PicoWrite8_z80(u32 a, u32 d)
       SN76496Write(d);\r
     return;\r
   }\r
-#if !defined(_ASM_MEMORY_C) || defined(_ASM_MEMORY_C_AMIPS)\r
   if ((a & 0x7f00) == 0x6000) // Z80 BANK register\r
   {\r
     Pico.m.z80_bank68k >>= 1;\r
@@ -553,7 +438,6 @@ static void PicoWrite8_z80(u32 a, u32 d)
     elprintf(EL_Z80BNK, "z80 bank=%06x", Pico.m.z80_bank68k << 15);\r
     return;\r
   }\r
-#endif\r
   elprintf(EL_UIO|EL_ANOMALY, "68k bad write [%06x] %02x @ %06x", a, d&0xff, SekPc);\r
 }\r
 \r
@@ -564,6 +448,8 @@ static void PicoWrite16_z80(u32 a, u32 d)
   PicoWrite8_z80(a, d >> 8);\r
 }\r
 \r
+#ifndef _ASM_MEMORY_C\r
+\r
 // IO/control area (0xa10000 - 0xa1ffff)\r
 u32 PicoRead8_io(u32 a)\r
 {\r
@@ -578,13 +464,20 @@ u32 PicoRead8_io(u32 a)
   d = Pico.m.rotate++;\r
   d ^= d << 6;\r
 \r
-  // bit8 seems to be readable in this range\r
-  if ((a & 0xfc01) == 0x1000)\r
-    d &= ~0x01;\r
+  if ((a & 0xfc00) == 0x1000) {\r
+    // bit8 seems to be readable in this range\r
+    if (!(a & 1))\r
+      d &= ~0x01;\r
 \r
-  if ((a & 0xff01) == 0x1100) { // z80 busreq (verified)\r
-    d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1;\r
-    elprintf(EL_BUSREQ, "get_zrun: %02x [%i] @%06x", d, SekCyclesDone(), SekPc);\r
+    if ((a & 0xff01) == 0x1100) { // z80 busreq (verified)\r
+      d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1;\r
+      elprintf(EL_BUSREQ, "get_zrun: %02x [%i] @%06x", d, SekCyclesDone(), SekPc);\r
+    }\r
+    goto end;\r
+  }\r
+\r
+  if (PicoOpt & POPT_EN_32X) {\r
+    d = PicoRead8_32x(a);\r
     goto end;\r
   }\r
 \r
@@ -599,6 +492,7 @@ u32 PicoRead16_io(u32 a)
 \r
   if ((a & 0xffe0) == 0x0000) { // I/O ports\r
     d = io_ports_read(a);\r
+    d |= d << 8;\r
     goto end;\r
   }\r
 \r
@@ -607,12 +501,18 @@ u32 PicoRead16_io(u32 a)
   d ^= (d << 5) ^ (d << 8);\r
 \r
   // bit8 seems to be readable in this range\r
-  if ((a & 0xfc00) == 0x1000)\r
+  if ((a & 0xfc00) == 0x1000) {\r
     d &= ~0x0100;\r
 \r
-  if ((a & 0xff00) == 0x1100) { // z80 busreq\r
-    d |= ((Pico.m.z80Run | Pico.m.z80_reset) & 1) << 8;\r
-    elprintf(EL_BUSREQ, "get_zrun: %04x [%i] @%06x", d, SekCyclesDone(), SekPc);\r
+    if ((a & 0xff00) == 0x1100) { // z80 busreq\r
+      d |= ((Pico.m.z80Run | Pico.m.z80_reset) & 1) << 8;\r
+      elprintf(EL_BUSREQ, "get_zrun: %04x [%i] @%06x", d, SekCyclesDone(), SekPc);\r
+    }\r
+    goto end;\r
+  }\r
+\r
+  if (PicoOpt & POPT_EN_32X) {\r
+    d = PicoRead16_32x(a);\r
     goto end;\r
   }\r
 \r
@@ -641,6 +541,11 @@ void PicoWrite8_io(u32 a, u32 d)
     Pico.m.sram_reg |= (u8)(d & 3);\r
     return;\r
   }\r
+  if (PicoOpt & POPT_EN_32X) {\r
+    PicoWrite8_32x(a, d);\r
+    return;\r
+  }\r
+\r
   m68k_unmapped_write8(a, d);\r
 }\r
 \r
@@ -664,9 +569,15 @@ void PicoWrite16_io(u32 a, u32 d)
     Pico.m.sram_reg |= (u8)(d & 3);\r
     return;\r
   }\r
+  if (PicoOpt & POPT_EN_32X) {\r
+    PicoWrite16_32x(a, d);\r
+    return;\r
+  }\r
   m68k_unmapped_write16(a, d);\r
 }\r
 \r
+#endif // _ASM_MEMORY_C\r
+\r
 // VDP area (0xc00000 - 0xdfffff)\r
 // TODO: verify if lower byte goes to PSG on word writes\r
 static u32 PicoRead8_vdp(u32 a)\r
@@ -785,13 +696,16 @@ PICO_INTERNAL void PicoMemSetup(void)
 \r
   // Setup memory callbacks:\r
 #ifdef EMU_C68K\r
-  PicoCpuCM68k.checkpc = PicoCheckPc;\r
-  PicoCpuCM68k.fetch8  = PicoCpuCM68k.read8  = m68k_read8;\r
-  PicoCpuCM68k.fetch16 = PicoCpuCM68k.read16 = m68k_read16;\r
-  PicoCpuCM68k.fetch32 = PicoCpuCM68k.read32 = m68k_read32;\r
-  PicoCpuCM68k.write8  = m68k_write8;\r
-  PicoCpuCM68k.write16 = m68k_write16;\r
-  PicoCpuCM68k.write32 = m68k_write32;\r
+  PicoCpuCM68k.read8  = (void *)m68k_read8_map;\r
+  PicoCpuCM68k.read16 = (void *)m68k_read16_map;\r
+  PicoCpuCM68k.read32 = (void *)m68k_read16_map;\r
+  PicoCpuCM68k.write8  = (void *)m68k_write8_map;\r
+  PicoCpuCM68k.write16 = (void *)m68k_write16_map;\r
+  PicoCpuCM68k.write32 = (void *)m68k_write16_map;\r
+  PicoCpuCM68k.checkpc = NULL; /* unused */\r
+  PicoCpuCM68k.fetch8  = NULL;\r
+  PicoCpuCM68k.fetch16 = NULL;\r
+  PicoCpuCM68k.fetch32 = NULL;\r
 #endif\r
 #ifdef EMU_F68K\r
   PicoCpuFM68k.read_byte  = m68k_read8;\r
@@ -1150,7 +1064,6 @@ static unsigned char MEMH_FUNC z80_md_vdp_read(unsigned short a)
 \r
 static unsigned char MEMH_FUNC z80_md_bank_read(unsigned short a)\r
 {\r
-  extern unsigned int PicoReadM68k8(unsigned int a);\r
   unsigned int addr68k;\r
   unsigned char ret;\r
 \r
@@ -1192,7 +1105,6 @@ static void MEMH_FUNC z80_md_vdp_br_write(unsigned int a, unsigned char data)
 \r
 static void MEMH_FUNC z80_md_bank_write(unsigned int a, unsigned char data)\r
 {\r
-  extern void PicoWriteM68k8(unsigned int a, unsigned char d);\r
   unsigned int addr68k;\r
 \r
   addr68k = Pico.m.z80_bank68k << 15;\r