32x: implement standard/ssf2 mapper
[picodrive.git] / pico / pico_int.h
index 2249148..cb1c21d 100644 (file)
@@ -11,8 +11,8 @@
 #define PICO_INTERNAL_INCLUDED\r
 \r
 #include <stdio.h>\r
-#include <stdlib.h>\r
 #include <string.h>\r
+#include "pico_port.h"\r
 #include "pico.h"\r
 #include "carthw/carthw.h"\r
 \r
@@ -80,7 +80,7 @@ extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k;
 }\r
 #define SekIsStoppedM68k() (PicoCpuFM68k.execinfo&FM68K_HALTED)\r
 #define SekIsStoppedS68k() (PicoCpuFS68k.execinfo&FM68K_HALTED)\r
-#define SekShouldInterrupt() fm68k_would_interrupt()\r
+#define SekShouldInterrupt() fm68k_would_interrupt(&PicoCpuFM68k)\r
 \r
 #define SekNotPolling     PicoCpuFM68k.not_polling\r
 #define SekNotPollingS68k PicoCpuFS68k.not_polling\r
@@ -117,37 +117,25 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k;
 #define SekNotPolling     PicoCpuMM68k.not_polling\r
 #define SekNotPollingS68k PicoCpuMS68k.not_polling\r
 \r
-#define SekInterrupt(irq) { \\r
-       void *oldcontext = m68ki_cpu_p; \\r
-       m68k_set_context(&PicoCpuMM68k); \\r
-       m68k_set_irq(irq); \\r
-       m68k_set_context(oldcontext); \\r
-}\r
-#define SekIrqLevel (PicoCpuMM68k.int_level >> 8)\r
+// avoid m68k_set_irq() for delaying to work\r
+#define SekInterrupt(irq)  PicoCpuMM68k.int_level = (irq) << 8\r
+#define SekIrqLevel        (PicoCpuMM68k.int_level >> 8)\r
 \r
 #endif\r
 #endif // EMU_M68K\r
 \r
-// while running, cnt represents target of current timeslice\r
-// while not in SekRun(), it's actual cycles done\r
-// (but always use SekCyclesDone() if you need current position)\r
-// cnt may change if timeslice is ended prematurely or extended,\r
-// so we use SekCycleAim for the actual target\r
-extern unsigned int SekCycleCnt;\r
-extern unsigned int SekCycleAim;\r
-\r
 // number of cycles done (can be checked anywhere)\r
-#define SekCyclesDone()  (SekCycleCnt - SekCyclesLeft)\r
+#define SekCyclesDone()  (Pico.t.m68c_cnt - SekCyclesLeft)\r
 \r
 // burn cycles while not in SekRun() and while in\r
-#define SekCyclesBurn(c)    SekCycleCnt += c\r
+#define SekCyclesBurn(c)    Pico.t.m68c_cnt += c\r
 #define SekCyclesBurnRun(c) { \\r
   SekCyclesLeft -= c; \\r
 }\r
 \r
 // note: sometimes may extend timeslice to delay an irq\r
 #define SekEndRun(after) { \\r
-  SekCycleCnt -= SekCyclesLeft - (after); \\r
+  Pico.t.m68c_cnt -= SekCyclesLeft - (after); \\r
   SekCyclesLeft = after; \\r
 }\r
 \r
@@ -185,6 +173,7 @@ extern struct DrZ80 drZ80;
 #define z80_nmi()          drZ80.Z80IF |= 8\r
 \r
 #define z80_cyclesLeft     drZ80.cycles\r
+#define z80_subCLeft(c)    drZ80.cycles -= c\r
 #define z80_pc()           (drZ80.Z80PC - drZ80.Z80PC_BASE)\r
 \r
 #elif defined(_USE_CZ80)\r
@@ -196,6 +185,7 @@ extern struct DrZ80 drZ80;
 #define z80_nmi()          Cz80_Set_IRQ(&CZ80, IRQ_LINE_NMI, 0)\r
 \r
 #define z80_cyclesLeft     (CZ80.ICount - CZ80.ExtraCycles)\r
+#define z80_subCLeft(c)    CZ80.ICount -= c\r
 #define z80_pc()           Cz80_Get_Reg(&CZ80, CZ80_PC)\r
 \r
 #else\r
@@ -209,20 +199,13 @@ extern struct DrZ80 drZ80;
 \r
 #define Z80_STATE_SIZE 0x60\r
 \r
-extern unsigned int last_z80_sync;\r
-extern int z80_cycle_cnt;        /* 'done' z80 cycles before z80_run() */\r
-extern int z80_cycle_aim;\r
-extern int z80_scanline;\r
-extern int z80_scanline_cycles;  /* cycles done until z80_scanline */\r
-\r
 #define z80_resetCycles() \\r
-  last_z80_sync = SekCyclesDone(); \\r
-  z80_cycle_cnt = z80_cycle_aim = z80_scanline = z80_scanline_cycles = 0;\r
+  Pico.t.z80c_cnt = Pico.t.z80c_aim = Pico.t.z80_scanline = 0\r
 \r
 #define z80_cyclesDone() \\r
-  (z80_cycle_aim - z80_cyclesLeft)\r
+  (Pico.t.z80c_aim - z80_cyclesLeft)\r
 \r
-#define cycles_68k_to_z80(x) ((x)*957 >> 11)\r
+#define cycles_68k_to_z80(x) ((x) * 3823 >> 13)\r
 \r
 // ----------------------- SH2 CPU -----------------------\r
 \r
@@ -281,6 +264,7 @@ extern SH2 sh2s[2];
 #define OSC_NTSC 53693100\r
 #define OSC_PAL  53203424\r
 \r
+// PicoVideo.debug_p\r
 #define PVD_KILL_A    (1 << 0)\r
 #define PVD_KILL_B    (1 << 1)\r
 #define PVD_KILL_S_LO (1 << 2)\r
@@ -290,6 +274,21 @@ extern SH2 sh2s[2];
 #define PVD_FORCE_B   (1 << 6)\r
 #define PVD_FORCE_S   (1 << 7)\r
 \r
+// PicoVideo.status, not part of real SR\r
+#define SR_PAL        (1 << 0)\r
+#define SR_DMA        (1 << 1)\r
+#define SR_HB         (1 << 2)\r
+#define SR_VB         (1 << 3)\r
+#define SR_ODD        (1 << 4)\r
+#define SR_C          (1 << 5)\r
+#define SR_SOVR       (1 << 6)\r
+#define SR_F          (1 << 7)\r
+#define SR_FULL       (1 << 8)\r
+#define SR_EMPT       (1 << 9)\r
+// not part of real SR\r
+#define PVS_ACTIVE    (1 << 16)\r
+#define PVS_VB2       (1 << 17) // ignores forced blanking\r
+\r
 struct PicoVideo\r
 {\r
   unsigned char reg[0x20];\r
@@ -297,14 +296,15 @@ struct PicoVideo
   unsigned char pending;      // 1 if waiting for second half of 32-bit command\r
   unsigned char type;         // Command type (v/c/vsram read/write)\r
   unsigned short addr;        // Read/Write address\r
-  int status;                 // Status bits\r
+  unsigned int status;        // Status bits (SR) and extra flags\r
   unsigned char pending_ints; // pending interrupts: ??VH????\r
   signed char lwrite_cnt;     // VDP write count during active display line\r
   unsigned short v_counter;   // V-counter\r
   unsigned short debug;       // raw debug register\r
   unsigned char debug_p;      // ... parsed: PVD_*\r
-  unsigned char addr_u;\r
-  unsigned char pad[0x0c];\r
+  unsigned char addr_u;       // bit16 of .addr\r
+  unsigned char hint_cnt;\r
+  unsigned char pad[0x0b];\r
 };\r
 \r
 struct PicoMisc\r
@@ -326,7 +326,7 @@ struct PicoMisc
   unsigned char  eeprom_cycle; // EEPROM cycle number\r
   unsigned char  eeprom_slave; // EEPROM slave word for X24C02 and better SRAMs\r
   unsigned char  eeprom_status;\r
-  unsigned char  pad2;\r
+  unsigned char  status;       // rapid_ym2612, multi_ym_updates\r
   unsigned short dma_xfers;    // 18\r
   unsigned char  eeprom_wb[2]; // EEPROM latch/write buffer\r
   unsigned int  frame_count;   // 1c for movies and idle det\r
@@ -348,15 +348,15 @@ struct PicoEState
   void *DrawLineDest;          // draw destination\r
   unsigned char *HighCol;\r
   int *HighPreSpr;\r
-  void *Pico_video;\r
-  void *Pico_vram;\r
-  int  *PicoOpt;\r
+  struct Pico *Pico;\r
+  void *PicoMem_vram;\r
+  void *PicoMem_cram;\r
+  unsigned int  *PicoOpt;\r
   unsigned char *Draw2FB;\r
   unsigned short HighPal[0x100];\r
 };\r
 \r
-// some assembly stuff depend on these, do not touch!\r
-struct Pico\r
+struct PicoMem\r
 {\r
   unsigned char ram[0x10000];  // 0x00000 scratch ram\r
   union {                      // vram is byteswapped for easier reads when drawing\r
@@ -365,17 +365,9 @@ struct Pico
   };\r
   unsigned char zram[0x2000];  // 0x20000 Z80 ram\r
   unsigned char ioports[0x10]; // XXX: fix asm and mv\r
-  unsigned char pad[0xf0];     // unused\r
-  unsigned short cram[0x40];   // 0x22100\r
-  unsigned short vsram[0x40];  // 0x22180\r
-\r
-  unsigned char *rom;          // 0x22200\r
-  unsigned int romsize;        // 0x22204 (on 32bits)\r
-\r
-  struct PicoMisc m;\r
-  struct PicoVideo video;\r
-  struct PicoMS ms;\r
-  struct PicoEState est;\r
+  unsigned short cram[0x40];   // 0x22010\r
+  unsigned char pad[0x70];     // 0x22050 DrawStripVSRam reads 0 from here\r
+  unsigned short vsram[0x40];  // 0x22100\r
 };\r
 \r
 // sram\r
@@ -385,7 +377,7 @@ struct Pico
 #define SRF_ENABLED  (1 << 0)\r
 #define SRF_EEPROM   (1 << 1)\r
 \r
-struct PicoSRAM\r
+struct PicoCartSave\r
 {\r
   unsigned char *data;         // actual data\r
   unsigned int start;          // start address in 68k address space\r
@@ -401,6 +393,52 @@ struct PicoSRAM
   unsigned int size;\r
 };\r
 \r
+struct PicoTiming\r
+{\r
+  // while running, cnt represents target of current timeslice\r
+  // while not in SekRun(), it's actual cycles done\r
+  // (but always use SekCyclesDone() if you need current position)\r
+  // _cnt may change if timeslice is ended prematurely or extended,\r
+  // so we use _aim for the actual target\r
+  unsigned int m68c_cnt;\r
+  unsigned int m68c_aim;\r
+  unsigned int m68c_frame_start;        // m68k cycles\r
+  unsigned int m68c_line_start;\r
+\r
+  unsigned int z80c_cnt;                // z80 cycles done (this frame)\r
+  unsigned int z80c_aim;\r
+  int z80_scanline;\r
+\r
+  int timer_a_next_oflow, timer_a_step; // in z80 cycles\r
+  int timer_b_next_oflow, timer_b_step;\r
+};\r
+\r
+struct PicoSound\r
+{\r
+  short len;                            // number of mono samples\r
+  short len_use;                        // adjusted\r
+  int len_e_add;                        // for non-int samples/frame\r
+  int len_e_cnt;\r
+  short dac_line;\r
+  short psg_line;\r
+};\r
+\r
+// run tools/mkoffsets pico/pico_int_o32.h if you change these\r
+// careful with savestate compat\r
+struct Pico\r
+{\r
+  struct PicoVideo video;\r
+  struct PicoMisc m;\r
+  struct PicoTiming t;\r
+  struct PicoCartSave sv;\r
+  struct PicoSound snd;\r
+  struct PicoEState est;\r
+  struct PicoMS ms;\r
+\r
+  unsigned char *rom;\r
+  unsigned int romsize;\r
+};\r
+\r
 // MCD\r
 #define PCM_MIXBUF_LEN ((12500000 / 384) / 50 + 1)\r
 \r
@@ -508,6 +546,7 @@ typedef struct
 #define P32XF_68KCPOLL   (1 << 0)\r
 #define P32XF_68KVPOLL   (1 << 1)\r
 #define P32XF_Z80_32X_IO (1 << 7) // z80 does 32x io\r
+#define P32XF_DRC_ROM_C  (1 << 8) // cached code from ROM\r
 \r
 #define P32XI_VRES (1 << 14/2) // IRL/2\r
 #define P32XI_VINT (1 << 12/2)\r
@@ -543,8 +582,8 @@ struct Pico32x
   unsigned int dmac0_fifo_ptr;\r
   unsigned short vdp_fbcr_fake;\r
   unsigned short pad2;\r
-  unsigned char comm_dirty_68k;\r
-  unsigned char comm_dirty_sh2;\r
+  unsigned char comm_dirty;\r
+  unsigned char pad3;            // was comm_dirty_sh2\r
   unsigned char pwm_irq_cnt;\r
   unsigned char pad1;\r
   unsigned short pwm_p[2];       // pwm pos in fifo\r
@@ -679,10 +718,7 @@ void pcd_state_loaded_mem(void);
 \r
 // pico.c\r
 extern struct Pico Pico;\r
-extern struct PicoSRAM SRam;\r
-extern int PicoPadInt[2];\r
-extern int emustatus;\r
-extern int scanlines_total;\r
+extern struct PicoMem PicoMem;\r
 extern void (*PicoResetHook)(void);\r
 extern void (*PicoLineHook)(void);\r
 PICO_INTERNAL int  CheckDMA(void);\r
@@ -759,10 +795,6 @@ void SekInterruptClearS68k(int irq);
 \r
 // sound/sound.c\r
 extern short cdda_out_buffer[2*1152];\r
-extern int PsndLen_exc_cnt;\r
-extern int PsndLen_exc_add;\r
-extern int timer_a_next_oflow, timer_a_step; // in z80 cycles\r
-extern int timer_b_next_oflow, timer_b_step;\r
 \r
 void cdda_start_play(int lba_base, int lba_offset, int lb_len);\r
 \r
@@ -777,29 +809,31 @@ void ym2612_unpack_state(void);
 #define TIMER_B_TICK_ZCYCLES 262800 // 275251 broken, see Dai Makaimura\r
 \r
 #define timers_cycle() \\r
-  if (timer_a_next_oflow > 0 && timer_a_next_oflow < TIMER_NO_OFLOW) \\r
-    timer_a_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256; \\r
-  if (timer_b_next_oflow > 0 && timer_b_next_oflow < TIMER_NO_OFLOW) \\r
-    timer_b_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256; \\r
+  if (Pico.t.timer_a_next_oflow > 0 && Pico.t.timer_a_next_oflow < TIMER_NO_OFLOW) \\r
+    Pico.t.timer_a_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256; \\r
+  if (Pico.t.timer_b_next_oflow > 0 && Pico.t.timer_b_next_oflow < TIMER_NO_OFLOW) \\r
+    Pico.t.timer_b_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256; \\r
   ym2612_sync_timers(0, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode);\r
 \r
 #define timers_reset() \\r
-  timer_a_next_oflow = timer_b_next_oflow = TIMER_NO_OFLOW; \\r
-  timer_a_step = TIMER_A_TICK_ZCYCLES * 1024; \\r
-  timer_b_step = TIMER_B_TICK_ZCYCLES * 256;\r
+  Pico.t.timer_a_next_oflow = Pico.t.timer_b_next_oflow = TIMER_NO_OFLOW; \\r
+  Pico.t.timer_a_step = TIMER_A_TICK_ZCYCLES * 1024; \\r
+  Pico.t.timer_b_step = TIMER_B_TICK_ZCYCLES * 256;\r
 \r
 \r
 // videoport.c\r
-extern int line_base_cycles;\r
 PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d);\r
 PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a);\r
-PICO_INTERNAL_ASM unsigned int PicoVideoRead8(unsigned int a);\r
+unsigned char PicoVideoRead8DataH(void);\r
+unsigned char PicoVideoRead8DataL(void);\r
+unsigned char PicoVideoRead8CtlH(void);\r
+unsigned char PicoVideoRead8CtlL(void);\r
+unsigned char PicoVideoRead8HV_H(void);\r
+unsigned char PicoVideoRead8HV_L(void);\r
 extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **base, unsigned int *mask);\r
 \r
 // misc.c\r
-PICO_INTERNAL_ASM void memcpy16(unsigned short *dest, unsigned short *src, int count);\r
 PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count);\r
-PICO_INTERNAL_ASM void memcpy32(void *dest, const void *src, int count); // 32bit word count\r
 PICO_INTERNAL_ASM void memset32(void *dest, int c, int count);\r
 \r
 // eeprom.c\r
@@ -820,11 +854,12 @@ PICO_INTERNAL_ASM void wram_1M_to_2M(unsigned char *m);
 \r
 // sound/sound.c\r
 PICO_INTERNAL void PsndReset(void);\r
+PICO_INTERNAL void PsndStartFrame(void);\r
 PICO_INTERNAL void PsndDoDAC(int line_to);\r
+PICO_INTERNAL void PsndDoPSG(int line_to);\r
 PICO_INTERNAL void PsndClear(void);\r
 PICO_INTERNAL void PsndGetSamples(int y);\r
 PICO_INTERNAL void PsndGetSamplesMS(void);\r
-extern int PsndDacLine;\r
 \r
 // sms.c\r
 #ifndef NO_SMS\r
@@ -872,7 +907,7 @@ void p32x_event_schedule_sh2(SH2 *sh2, enum p32x_event event, int after);
 void p32x_schedule_hint(SH2 *sh2, int m68k_cycles);\r
 \r
 // 32x/memory.c\r
-struct Pico32xMem *Pico32xMem;\r
+extern struct Pico32xMem *Pico32xMem;\r
 unsigned int PicoRead8_32x(unsigned int a);\r
 unsigned int PicoRead16_32x(unsigned int a);\r
 void PicoWrite8_32x(unsigned int a, unsigned int d);\r
@@ -880,6 +915,7 @@ void PicoWrite16_32x(unsigned int a, unsigned int d);
 void PicoMemSetup32x(void);\r
 void Pico32xSwapDRAM(int b);\r
 void Pico32xMemStateLoaded(void);\r
+void p32x_update_banks(void);\r
 void p32x_m68k_poll_event(unsigned int flags);\r
 void p32x_sh2_poll_event(SH2 *sh2, unsigned int flags, unsigned int m68k_cycles);\r
 \r
@@ -948,7 +984,7 @@ static __inline int isspace_(int c)
 // emulation event logging\r
 #ifndef EL_LOGMASK\r
 # ifdef __x86_64__ // HACK\r
-#  define EL_LOGMASK (EL_STATUS|EL_IDLE|EL_ANOMALY)\r
+#  define EL_LOGMASK (EL_STATUS|EL_ANOMALY)\r
 # else\r
 #  define EL_LOGMASK (EL_STATUS)\r
 # endif\r
@@ -1043,28 +1079,10 @@ void pevt_dump(void);
 #define pevt_dump()\r
 #endif\r
 \r
-// misc\r
-#ifdef _MSC_VER\r
-#define cdprintf\r
-#else\r
-#define cdprintf(x...)\r
-#endif\r
-\r
-#if defined(__GNUC__) && defined(__i386__)\r
-#define REGPARM(x) __attribute__((regparm(x)))\r
-#else\r
-#define REGPARM(x)\r
-#endif\r
-\r
-#ifdef __GNUC__\r
-#define NOINLINE __attribute__((noinline))\r
-#else\r
-#define NOINLINE\r
-#endif\r
-\r
 #ifdef __cplusplus\r
 } // End of extern "C"\r
 #endif\r
 \r
 #endif // PICO_INTERNAL_INCLUDED\r
 \r
+// vim:shiftwidth=2:ts=2:expandtab\r