pico_cmn.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * common code for pico.c and cd/pico.c
  3. * (C) notaz, 2007-2009
  4. *
  5. * This work is licensed under the terms of MAME license.
  6. * See COPYING file in the top-level directory.
  7. */
  8. #define CYCLES_M68K_LINE 488 // suitable for both PAL/NTSC
  9. #define CYCLES_M68K_VINT_LAG 68
  10. #define CYCLES_M68K_ASD 148
  11. #define CYCLES_S68K_LINE 795
  12. #define CYCLES_S68K_VINT_LAG 111
  13. #define CYCLES_S68K_ASD 241
  14. // pad delay (for 6 button pads)
  15. #define PAD_DELAY \
  16. if (PicoOpt&POPT_6BTN_PAD) { \
  17. if(Pico.m.padDelay[0]++ > 25) Pico.m.padTHPhase[0]=0; \
  18. if(Pico.m.padDelay[1]++ > 25) Pico.m.padTHPhase[1]=0; \
  19. }
  20. // CPUS_RUN
  21. #ifndef CPUS_RUN
  22. #define CPUS_RUN(m68k_cycles,s68k_cycles) \
  23. SekRunM68k(m68k_cycles)
  24. #endif
  25. static __inline void SekRunM68k(int cyc)
  26. {
  27. int cyc_do;
  28. pprof_start(m68k);
  29. pevt_log_m68k_o(EVT_RUN_START);
  30. SekCycleAim+=cyc;
  31. if ((cyc_do=SekCycleAim-SekCycleCnt) <= 0)
  32. goto out;
  33. #if defined(EMU_CORE_DEBUG)
  34. // this means we do run-compare
  35. SekCycleCnt+=CM_compareRun(cyc_do, 0);
  36. #elif defined(EMU_C68K)
  37. PicoCpuCM68k.cycles=cyc_do;
  38. CycloneRun(&PicoCpuCM68k);
  39. SekCycleCnt+=cyc_do-PicoCpuCM68k.cycles;
  40. #elif defined(EMU_M68K)
  41. SekCycleCnt+=m68k_execute(cyc_do);
  42. #elif defined(EMU_F68K)
  43. SekCycleCnt+=fm68k_emulate(cyc_do+1, 0, 0);
  44. #endif
  45. out:
  46. SekTrace(0);
  47. pevt_log_m68k_o(EVT_RUN_END);
  48. pprof_end(m68k);
  49. }
  50. static int PicoFrameHints(void)
  51. {
  52. struct PicoVideo *pv=&Pico.video;
  53. int lines, y, lines_vis = 224, line_sample, skip, vcnt_wrap;
  54. int hint; // Hint counter
  55. pevt_log_m68k_o(EVT_FRAME_START);
  56. pv->v_counter = Pico.m.scanline = 0;
  57. if ((PicoOpt&POPT_ALT_RENDERER) && !PicoSkipFrame && (pv->reg[1]&0x40)) { // fast rend., display enabled
  58. // draw a frame just after vblank in alternative render mode
  59. // yes, this will cause 1 frame lag, but this is inaccurate mode anyway.
  60. PicoFrameFull();
  61. #ifdef DRAW_FINISH_FUNC
  62. DRAW_FINISH_FUNC();
  63. #endif
  64. skip = 1;
  65. }
  66. else skip=PicoSkipFrame;
  67. if (Pico.m.pal) {
  68. line_sample = 68;
  69. if (pv->reg[1]&8) lines_vis = 240;
  70. } else {
  71. line_sample = 93;
  72. }
  73. SekCyclesReset();
  74. z80_resetCycles();
  75. #ifdef PICO_CD
  76. SekCyclesResetS68k();
  77. #endif
  78. PsndDacLine = 0;
  79. emustatus &= ~1;
  80. pv->status&=~0x88; // clear V-Int, come out of vblank
  81. hint=pv->reg[10]; // Load H-Int counter
  82. //dprintf("-hint: %i", hint);
  83. // This is to make active scan longer (needed for Double Dragon 2, mainly)
  84. CPUS_RUN(CYCLES_M68K_ASD, CYCLES_S68K_ASD);
  85. for (y = 0; y < lines_vis; y++)
  86. {
  87. pv->v_counter = Pico.m.scanline = y;
  88. if ((pv->reg[12]&6) == 6) { // interlace mode 2
  89. pv->v_counter <<= 1;
  90. pv->v_counter |= pv->v_counter >> 8;
  91. pv->v_counter &= 0xff;
  92. }
  93. // VDP FIFO
  94. pv->lwrite_cnt -= 12;
  95. if (pv->lwrite_cnt <= 0) {
  96. pv->lwrite_cnt=0;
  97. Pico.video.status|=0x200;
  98. }
  99. PAD_DELAY
  100. #ifdef PICO_CD
  101. check_cd_dma();
  102. #endif
  103. // H-Interrupts:
  104. if (--hint < 0) // y <= lines_vis: Comix Zone, Golden Axe
  105. {
  106. hint=pv->reg[10]; // Reload H-Int counter
  107. pv->pending_ints|=0x10;
  108. if (pv->reg[0]&0x10) {
  109. elprintf(EL_INTS, "hint: @ %06x [%i]", SekPc, SekCycleCnt);
  110. SekInterrupt(4);
  111. }
  112. }
  113. // decide if we draw this line
  114. if (!skip && (PicoOpt & POPT_ALT_RENDERER))
  115. {
  116. // find the right moment for frame renderer, when display is no longer blanked
  117. if ((pv->reg[1]&0x40) || y > 100) {
  118. PicoFrameFull();
  119. #ifdef DRAW_FINISH_FUNC
  120. DRAW_FINISH_FUNC();
  121. #endif
  122. skip = 1;
  123. }
  124. }
  125. // get samples from sound chips
  126. if ((y == 224 || y == line_sample) && PsndOut)
  127. {
  128. if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80))
  129. PicoSyncZ80(SekCycleCnt);
  130. if (ym2612.dacen && PsndDacLine <= y)
  131. PsndDoDAC(y);
  132. #ifdef PICO_32X
  133. p32x_sync_sh2s(SekCyclesDoneT2());
  134. #endif
  135. PsndGetSamples(y);
  136. }
  137. // Run scanline:
  138. if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA());
  139. CPUS_RUN(CYCLES_M68K_LINE, CYCLES_S68K_LINE);
  140. #ifdef PICO_CD
  141. update_chips();
  142. #else
  143. if (PicoLineHook) PicoLineHook();
  144. #endif
  145. pevt_log_m68k_o(EVT_NEXT_LINE);
  146. }
  147. if (!skip)
  148. {
  149. if (DrawScanline < y)
  150. PicoDrawSync(y - 1, 0);
  151. #ifdef DRAW_FINISH_FUNC
  152. DRAW_FINISH_FUNC();
  153. #endif
  154. }
  155. // V-int line (224 or 240)
  156. Pico.m.scanline = y;
  157. pv->v_counter = 0xe0; // bad for 240 mode
  158. if ((pv->reg[12]&6) == 6) pv->v_counter = 0xc1;
  159. // VDP FIFO
  160. pv->lwrite_cnt=0;
  161. Pico.video.status|=0x200;
  162. memcpy(PicoPadInt, PicoPad, sizeof(PicoPadInt));
  163. PAD_DELAY
  164. #ifdef PICO_CD
  165. check_cd_dma();
  166. #endif
  167. // Last H-Int:
  168. if (--hint < 0)
  169. {
  170. hint=pv->reg[10]; // Reload H-Int counter
  171. pv->pending_ints|=0x10;
  172. //printf("rhint: %i @ %06x [%i|%i]\n", hint, SekPc, y, SekCycleCnt);
  173. if (pv->reg[0]&0x10) SekInterrupt(4);
  174. }
  175. pv->status|=0x08; // go into vblank
  176. pv->pending_ints|=0x20;
  177. // the following SekRun is there for several reasons:
  178. // there must be a delay after vblank bit is set and irq is asserted (Mazin Saga)
  179. // also delay between F bit (bit 7) is set in SR and IRQ happens (Ex-Mutants)
  180. // also delay between last H-int and V-int (Golden Axe 3)
  181. CPUS_RUN(CYCLES_M68K_VINT_LAG, CYCLES_S68K_VINT_LAG);
  182. if (pv->reg[1]&0x20) {
  183. elprintf(EL_INTS, "vint: @ %06x [%i]", SekPc, SekCycleCnt);
  184. SekInterrupt(6);
  185. }
  186. if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) {
  187. PicoSyncZ80(SekCycleCnt);
  188. elprintf(EL_INTS, "zint");
  189. z80_int();
  190. }
  191. #ifdef PICO_32X
  192. p32x_sync_sh2s(SekCyclesDoneT2());
  193. p32x_start_blank();
  194. #endif
  195. // get samples from sound chips
  196. if (y == 224 && PsndOut)
  197. {
  198. if (ym2612.dacen && PsndDacLine <= y)
  199. PsndDoDAC(y);
  200. PsndGetSamples(y);
  201. }
  202. // Run scanline:
  203. if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA());
  204. CPUS_RUN(CYCLES_M68K_LINE - CYCLES_M68K_VINT_LAG - CYCLES_M68K_ASD,
  205. CYCLES_S68K_LINE - CYCLES_S68K_VINT_LAG - CYCLES_S68K_ASD);
  206. #ifdef PICO_CD
  207. update_chips();
  208. #else
  209. if (PicoLineHook) PicoLineHook();
  210. #endif
  211. pevt_log_m68k_o(EVT_NEXT_LINE);
  212. lines = scanlines_total;
  213. vcnt_wrap = Pico.m.pal ? 0x103 : 0xEB; // based on Gens, TODO: verify
  214. for (y++; y < lines; y++)
  215. {
  216. pv->v_counter = Pico.m.scanline = y;
  217. if (y >= vcnt_wrap)
  218. pv->v_counter -= Pico.m.pal ? 56 : 6;
  219. if ((pv->reg[12]&6) == 6)
  220. pv->v_counter = (pv->v_counter << 1) | 1;
  221. pv->v_counter &= 0xff;
  222. PAD_DELAY
  223. #ifdef PICO_CD
  224. check_cd_dma();
  225. #endif
  226. // Run scanline:
  227. if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA());
  228. CPUS_RUN(CYCLES_M68K_LINE, CYCLES_S68K_LINE);
  229. #ifdef PICO_CD
  230. update_chips();
  231. #else
  232. if (PicoLineHook) PicoLineHook();
  233. #endif
  234. pevt_log_m68k_o(EVT_NEXT_LINE);
  235. }
  236. // sync z80
  237. if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80))
  238. PicoSyncZ80(Pico.m.pal ? 151809 : 127671); // cycles adjusted for converter
  239. if (PsndOut && ym2612.dacen && PsndDacLine <= lines-1)
  240. PsndDoDAC(lines-1);
  241. #ifdef PICO_32X
  242. p32x_sync_sh2s(SekCyclesDoneT2());
  243. #endif
  244. timers_cycle();
  245. return 0;
  246. }
  247. #undef PAD_DELAY
  248. #undef CPUS_RUN