pico_cmn.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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 int PicoFrameHints(void)
  26. {
  27. struct PicoVideo *pv=&Pico.video;
  28. int lines, y, lines_vis = 224, line_sample, skip, vcnt_wrap;
  29. int hint; // Hint counter
  30. pv->v_counter = Pico.m.scanline = 0;
  31. if ((PicoOpt&POPT_ALT_RENDERER) && !PicoSkipFrame && (pv->reg[1]&0x40)) { // fast rend., display enabled
  32. // draw a frame just after vblank in alternative render mode
  33. // yes, this will cause 1 frame lag, but this is inaccurate mode anyway.
  34. PicoFrameFull();
  35. #ifdef DRAW_FINISH_FUNC
  36. DRAW_FINISH_FUNC();
  37. #endif
  38. skip = 1;
  39. }
  40. else skip=PicoSkipFrame;
  41. if (Pico.m.pal) {
  42. line_sample = 68;
  43. if (pv->reg[1]&8) lines_vis = 240;
  44. } else {
  45. line_sample = 93;
  46. }
  47. SekCyclesReset();
  48. z80_resetCycles();
  49. #ifdef PICO_CD
  50. SekCyclesResetS68k();
  51. #endif
  52. PsndDacLine = 0;
  53. emustatus &= ~1;
  54. pv->status&=~0x88; // clear V-Int, come out of vblank
  55. hint=pv->reg[10]; // Load H-Int counter
  56. //dprintf("-hint: %i", hint);
  57. // This is to make active scan longer (needed for Double Dragon 2, mainly)
  58. CPUS_RUN(CYCLES_M68K_ASD, CYCLES_S68K_ASD);
  59. for (y = 0; y < lines_vis; y++)
  60. {
  61. pv->v_counter = Pico.m.scanline = y;
  62. if ((pv->reg[12]&6) == 6) { // interlace mode 2
  63. pv->v_counter <<= 1;
  64. pv->v_counter |= pv->v_counter >> 8;
  65. pv->v_counter &= 0xff;
  66. }
  67. // VDP FIFO
  68. pv->lwrite_cnt -= 12;
  69. if (pv->lwrite_cnt <= 0) {
  70. pv->lwrite_cnt=0;
  71. Pico.video.status|=0x200;
  72. }
  73. PAD_DELAY
  74. #ifdef PICO_CD
  75. check_cd_dma();
  76. #endif
  77. #ifdef PICO_32X
  78. p32x_timers_do(1);
  79. #endif
  80. // H-Interrupts:
  81. if (--hint < 0) // y <= lines_vis: Comix Zone, Golden Axe
  82. {
  83. hint=pv->reg[10]; // Reload H-Int counter
  84. pv->pending_ints|=0x10;
  85. if (pv->reg[0]&0x10) {
  86. elprintf(EL_INTS, "hint: @ %06x [%i]", SekPc, SekCycleCnt);
  87. SekInterrupt(4);
  88. }
  89. }
  90. // decide if we draw this line
  91. if (!skip && (PicoOpt & POPT_ALT_RENDERER))
  92. {
  93. // find the right moment for frame renderer, when display is no longer blanked
  94. if ((pv->reg[1]&0x40) || y > 100) {
  95. PicoFrameFull();
  96. #ifdef DRAW_FINISH_FUNC
  97. DRAW_FINISH_FUNC();
  98. #endif
  99. skip = 1;
  100. }
  101. }
  102. // get samples from sound chips
  103. if ((y == 224 || y == line_sample) && PsndOut)
  104. {
  105. if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80))
  106. PicoSyncZ80(SekCycleCnt);
  107. if (ym2612.dacen && PsndDacLine <= y)
  108. PsndDoDAC(y);
  109. PsndGetSamples(y);
  110. }
  111. // Run scanline:
  112. if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA());
  113. CPUS_RUN(CYCLES_M68K_LINE, CYCLES_S68K_LINE);
  114. #ifdef PICO_CD
  115. update_chips();
  116. #else
  117. if (PicoLineHook) PicoLineHook();
  118. #endif
  119. }
  120. if (!skip)
  121. {
  122. if (DrawScanline < y)
  123. PicoDrawSync(y - 1, 0);
  124. #ifdef DRAW_FINISH_FUNC
  125. DRAW_FINISH_FUNC();
  126. #endif
  127. }
  128. // V-int line (224 or 240)
  129. Pico.m.scanline = y;
  130. pv->v_counter = 0xe0; // bad for 240 mode
  131. if ((pv->reg[12]&6) == 6) pv->v_counter = 0xc1;
  132. // VDP FIFO
  133. pv->lwrite_cnt=0;
  134. Pico.video.status|=0x200;
  135. memcpy(PicoPadInt, PicoPad, sizeof(PicoPadInt));
  136. PAD_DELAY
  137. #ifdef PICO_CD
  138. check_cd_dma();
  139. #endif
  140. #ifdef PICO_32X
  141. p32x_timers_do(1);
  142. #endif
  143. // Last H-Int:
  144. if (--hint < 0)
  145. {
  146. hint=pv->reg[10]; // Reload H-Int counter
  147. pv->pending_ints|=0x10;
  148. //printf("rhint: %i @ %06x [%i|%i]\n", hint, SekPc, y, SekCycleCnt);
  149. if (pv->reg[0]&0x10) SekInterrupt(4);
  150. }
  151. pv->status|=0x08; // go into vblank
  152. pv->pending_ints|=0x20;
  153. #ifdef PICO_32X
  154. p32x_start_blank();
  155. #endif
  156. // the following SekRun is there for several reasons:
  157. // there must be a delay after vblank bit is set and irq is asserted (Mazin Saga)
  158. // also delay between F bit (bit 7) is set in SR and IRQ happens (Ex-Mutants)
  159. // also delay between last H-int and V-int (Golden Axe 3)
  160. CPUS_RUN(CYCLES_M68K_VINT_LAG, CYCLES_S68K_VINT_LAG);
  161. if (pv->reg[1]&0x20) {
  162. elprintf(EL_INTS, "vint: @ %06x [%i]", SekPc, SekCycleCnt);
  163. SekInterrupt(6);
  164. }
  165. if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) {
  166. PicoSyncZ80(SekCycleCnt);
  167. elprintf(EL_INTS, "zint");
  168. z80_int();
  169. }
  170. // get samples from sound chips
  171. if (y == 224 && PsndOut)
  172. {
  173. if (ym2612.dacen && PsndDacLine <= y)
  174. PsndDoDAC(y);
  175. PsndGetSamples(y);
  176. }
  177. // Run scanline:
  178. if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA());
  179. CPUS_RUN(CYCLES_M68K_LINE - CYCLES_M68K_VINT_LAG - CYCLES_M68K_ASD,
  180. CYCLES_S68K_LINE - CYCLES_S68K_VINT_LAG - CYCLES_S68K_ASD);
  181. #ifdef PICO_CD
  182. update_chips();
  183. #else
  184. if (PicoLineHook) PicoLineHook();
  185. #endif
  186. lines = scanlines_total;
  187. vcnt_wrap = Pico.m.pal ? 0x103 : 0xEB; // based on Gens, TODO: verify
  188. for (y++; y < lines; y++)
  189. {
  190. pv->v_counter = Pico.m.scanline = y;
  191. if (y >= vcnt_wrap)
  192. pv->v_counter -= Pico.m.pal ? 56 : 6;
  193. if ((pv->reg[12]&6) == 6)
  194. pv->v_counter = (pv->v_counter << 1) | 1;
  195. pv->v_counter &= 0xff;
  196. PAD_DELAY
  197. #ifdef PICO_CD
  198. check_cd_dma();
  199. #endif
  200. #ifdef PICO_32X
  201. p32x_timers_do(1);
  202. #endif
  203. // Run scanline:
  204. if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA());
  205. CPUS_RUN(CYCLES_M68K_LINE, CYCLES_S68K_LINE);
  206. #ifdef PICO_CD
  207. update_chips();
  208. #else
  209. if (PicoLineHook) PicoLineHook();
  210. #endif
  211. }
  212. // sync z80
  213. if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80))
  214. PicoSyncZ80(Pico.m.pal ? 151809 : 127671); // cycles adjusted for converter
  215. if (PsndOut && ym2612.dacen && PsndDacLine <= lines-1)
  216. PsndDoDAC(lines-1);
  217. timers_cycle();
  218. return 0;
  219. }
  220. #undef PAD_DELAY
  221. #undef CPUS_RUN