Add VCS links
[debian-dgen.git] / mdfr.cpp
blobdc2005f72e34b0e4a6e3cd9a6e5fa84e59213bb7
1 // DGen/SDL v1.29+
2 // Megadrive 1 Frame module
3 // Many, many thanks to John Stiles for the new structure of this module! :)
4 // And kudos to Gens (Gens/GS) and Genplus (GX) authors -- zamaz
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <string.h>
10 #include <limits.h>
11 #include <assert.h>
12 #ifdef HAVE_MEMCPY_H
13 #include "memcpy.h"
14 #endif
15 #include "md.h"
16 #include "debug.h"
17 #include "rc-vars.h"
19 // Set and unset contexts (Musashi, StarScream, MZ80)
21 #ifdef WITH_MUSA
22 class md* md::md_musa(0);
24 bool md::md_set_musa(bool set)
26 if (set) {
27 ++md_musa_ref;
28 if (md_musa == this)
29 return true;
30 md_musa_prev = md_musa;
31 md_musa = this;
32 md_set_musa_sync(true);
33 return false;
35 else {
36 if (md_musa != this)
37 abort();
38 if (--md_musa_ref != 0)
39 return true;
40 md_set_musa_sync(false);
41 md_musa = md_musa_prev;
42 md_musa_prev = 0;
43 return true;
47 void md::md_set_musa_sync(bool push)
49 unsigned int i, j;
51 if (push) {
52 m68k_set_context(ctx_musa);
53 for (i = M68K_REG_D0, j = 0; (i <= M68K_REG_D7); ++i, ++j)
54 m68k_set_reg((m68k_register_t)i,
55 le2h32(m68k_state.d[j]));
56 for (i = M68K_REG_A0, j = 0; (i <= M68K_REG_A7); ++i, ++j)
57 m68k_set_reg((m68k_register_t)i,
58 le2h32(m68k_state.a[j]));
59 m68k_set_reg(M68K_REG_PC, le2h32(m68k_state.pc));
60 m68k_set_reg(M68K_REG_SR, le2h16(m68k_state.sr));
62 else {
63 for (i = M68K_REG_D0, j = 0; (i <= M68K_REG_D7); ++i, ++j)
64 m68k_state.d[j] =
65 h2le32(m68k_get_reg(NULL, (m68k_register_t)i));
66 for (i = M68K_REG_A0, j = 0; (i <= M68K_REG_A7); ++i, ++j)
67 m68k_state.a[j] =
68 h2le32(m68k_get_reg(NULL, (m68k_register_t)i));
69 m68k_state.pc = h2le32(m68k_get_reg(NULL, M68K_REG_PC));
70 m68k_state.sr = h2le16(m68k_get_reg(NULL, M68K_REG_SR));
71 m68k_get_context(ctx_musa);
74 #endif // WITH_MUSA
76 #ifdef WITH_STAR
77 class md* md::md_star(0);
79 bool md::md_set_star(bool set)
81 if (set) {
82 ++md_star_ref;
83 if (md_star == this)
84 return true;
85 md_star_prev = md_star;
86 md_star = this;
87 md_set_star_sync(true);
88 return false;
90 else {
91 if (md_star != this)
92 abort();
93 if (--md_star_ref != 0)
94 return true;
95 md_set_star_sync(false);
96 md_star = md_star_prev;
97 md_star_prev = 0;
98 return true;
102 void md::md_set_star_sync(bool push)
104 unsigned int i;
106 if (push) {
107 for (i = 0; (i < 8); ++i) {
108 cpu.dreg[i] = le2h32(m68k_state.d[i]);
109 cpu.areg[i] = le2h32(m68k_state.a[i]);
111 cpu.pc = le2h32(m68k_state.pc);
112 cpu.sr = le2h16(m68k_state.sr);
113 s68000SetContext(&cpu);
115 else {
116 s68000GetContext(&cpu);
117 for (i = 0; (i < 8); ++i) {
118 m68k_state.d[i] = h2le32(cpu.dreg[i]);
119 m68k_state.a[i] = h2le32(cpu.areg[i]);
121 m68k_state.pc = h2le32(cpu.pc);
122 m68k_state.sr = h2le16(cpu.sr);
125 #endif // WITH_STAR
127 #ifdef WITH_CYCLONE
128 class md* md::md_cyclone(0);
130 bool md::md_set_cyclone(bool set)
132 if (set) {
133 ++md_cyclone_ref;
134 if (md_cyclone == this)
135 return true;
136 md_cyclone_prev = md_cyclone;
137 md_cyclone = this;
138 md_set_cyclone_sync(true);
139 return false;
141 else {
142 if (md_cyclone != this)
143 abort();
144 if (--md_cyclone_ref != 0)
145 return true;
146 md_set_cyclone_sync(false);
147 md_cyclone = md_cyclone_prev;
148 md_cyclone_prev = 0;
149 return true;
153 void md::md_set_cyclone_sync(bool push)
155 unsigned int i;
157 if (push) {
158 for (i = 0; (i < 8); ++i) {
159 cyclonecpu.d[i] = le2h32(m68k_state.d[i]);
160 cyclonecpu.a[i] = le2h32(m68k_state.a[i]);
162 cyclonecpu.membase = 0;
163 cyclonecpu.pc = cyclonecpu.checkpc(le2h32(m68k_state.pc));
164 CycloneSetSr(&cyclonecpu, le2h16(m68k_state.sr));
166 else {
167 for (i = 0; (i < 8); ++i) {
168 m68k_state.d[i] = h2le32(cyclonecpu.d[i]);
169 m68k_state.a[i] = h2le32(cyclonecpu.a[i]);
171 m68k_state.pc = h2le32(cyclonecpu.pc-cyclonecpu.membase);
172 m68k_state.sr = h2le16(CycloneGetSr(&cyclonecpu));
175 #endif // WITH_CYCLONE
177 #ifdef WITH_CZ80
178 bool md::md_set_cz80(bool set)
180 if (set) {
181 if (md_cz80_ref++)
182 return true;
183 md_set_cz80_sync(true);
184 return false;
186 else {
187 if (md_cz80_ref == 0)
188 abort();
189 if (--md_cz80_ref)
190 return true;
191 md_set_cz80_sync(false);
192 return true;
196 void md::md_set_cz80_sync(bool push)
198 if (push) {
199 Cz80_Set_AF(&cz80, le2h16(z80_state.alt[0].fa));
200 Cz80_Set_BC(&cz80, le2h16(z80_state.alt[0].cb));
201 Cz80_Set_DE(&cz80, le2h16(z80_state.alt[0].ed));
202 Cz80_Set_HL(&cz80, le2h16(z80_state.alt[0].lh));
203 Cz80_Set_AF2(&cz80, le2h16(z80_state.alt[1].fa));
204 Cz80_Set_BC2(&cz80, le2h16(z80_state.alt[1].cb));
205 Cz80_Set_DE2(&cz80, le2h16(z80_state.alt[1].ed));
206 Cz80_Set_HL2(&cz80, le2h16(z80_state.alt[1].lh));
207 Cz80_Set_IX(&cz80, le2h16(z80_state.ix));
208 Cz80_Set_IY(&cz80, le2h16(z80_state.iy));
209 Cz80_Set_SP(&cz80, le2h16(z80_state.sp));
210 Cz80_Set_PC(&cz80, le2h16(z80_state.pc));
211 Cz80_Set_R(&cz80, z80_state.r);
212 Cz80_Set_I(&cz80, z80_state.i);
213 Cz80_Set_IFF(&cz80, z80_state.iff);
214 Cz80_Set_IM(&cz80, z80_state.im);
216 else {
217 z80_state.alt[0].fa = h2le16(Cz80_Get_AF(&cz80));
218 z80_state.alt[0].cb = h2le16(Cz80_Get_BC(&cz80));
219 z80_state.alt[0].ed = h2le16(Cz80_Get_DE(&cz80));
220 z80_state.alt[0].lh = h2le16(Cz80_Get_HL(&cz80));
221 z80_state.alt[1].fa = h2le16(Cz80_Get_AF2(&cz80));
222 z80_state.alt[1].cb = h2le16(Cz80_Get_BC2(&cz80));
223 z80_state.alt[1].ed = h2le16(Cz80_Get_DE2(&cz80));
224 z80_state.alt[1].lh = h2le16(Cz80_Get_HL2(&cz80));
225 z80_state.ix = h2le16(Cz80_Get_IX(&cz80));
226 z80_state.iy = h2le16(Cz80_Get_IY(&cz80));
227 z80_state.sp = h2le16(Cz80_Get_SP(&cz80));
228 z80_state.pc = h2le16(Cz80_Get_PC(&cz80));
229 z80_state.r = Cz80_Get_R(&cz80);
230 z80_state.i = Cz80_Get_I(&cz80);
231 z80_state.iff = Cz80_Get_IFF(&cz80);
232 z80_state.im = Cz80_Get_IM(&cz80);
235 #endif // WITH_CZ80
237 #ifdef WITH_MZ80
238 class md* md::md_mz80(0);
240 bool md::md_set_mz80(bool set)
242 if (set) {
243 ++md_mz80_ref;
244 if (md_mz80 == this)
245 return true;
246 md_mz80_prev = md_mz80;
247 md_mz80 = this;
248 md_set_mz80_sync(true);
249 return false;
251 else {
252 if (md_mz80 != this)
253 abort();
254 if (--md_mz80_ref != 0)
255 return true;
256 md_set_mz80_sync(false);
257 md_mz80 = md_mz80_prev;
258 md_mz80_prev = 0;
259 return true;
263 void md::md_set_mz80_sync(bool push)
265 if (push) {
266 z80.z80AF = le2h16(z80_state.alt[0].fa);
267 z80.z80BC = le2h16(z80_state.alt[0].cb);
268 z80.z80DE = le2h16(z80_state.alt[0].ed);
269 z80.z80HL = le2h16(z80_state.alt[0].lh);
270 z80.z80afprime = le2h16(z80_state.alt[1].fa);
271 z80.z80bcprime = le2h16(z80_state.alt[1].cb);
272 z80.z80deprime = le2h16(z80_state.alt[1].ed);
273 z80.z80hlprime = le2h16(z80_state.alt[1].lh);
274 z80.z80IX = le2h16(z80_state.ix);
275 z80.z80IY = le2h16(z80_state.iy);
276 z80.z80sp = le2h16(z80_state.sp);
277 z80.z80pc = le2h16(z80_state.pc);
278 z80.z80r = z80_state.r;
279 z80.z80i = z80_state.i;
280 z80.z80iff = z80_state.iff;
281 z80.z80interruptMode = z80_state.im;
282 mz80SetContext(&z80);
284 else {
285 mz80GetContext(&z80);
286 z80_state.alt[0].fa = h2le16(z80.z80AF);
287 z80_state.alt[0].cb = h2le16(z80.z80BC);
288 z80_state.alt[0].ed = h2le16(z80.z80DE);
289 z80_state.alt[0].lh = h2le16(z80.z80HL);
290 z80_state.alt[1].fa = h2le16(z80.z80afprime);
291 z80_state.alt[1].cb = h2le16(z80.z80bcprime);
292 z80_state.alt[1].ed = h2le16(z80.z80deprime);
293 z80_state.alt[1].lh = h2le16(z80.z80hlprime);
294 z80_state.ix = h2le16(z80.z80IX);
295 z80_state.iy = h2le16(z80.z80IY);
296 z80_state.sp = h2le16(z80.z80sp);
297 z80_state.pc = h2le16(z80.z80pc);
298 z80_state.r = z80.z80r;
299 z80_state.i = z80.z80i;
300 z80_state.iff = z80.z80iff;
301 z80_state.im = z80.z80interruptMode;
304 #endif // WITH_MZ80
306 #ifdef WITH_DRZ80
307 class md* md::md_drz80(0);
309 bool md::md_set_drz80(bool set)
311 if (set) {
312 ++md_drz80_ref;
313 if (md_drz80 == this)
314 return true;
315 md_drz80_prev = md_drz80;
316 md_drz80 = this;
317 md_set_drz80_sync(true);
318 return false;
320 else {
321 if (md_drz80 != this)
322 abort();
323 if (--md_drz80_ref != 0)
324 return true;
325 md_set_drz80_sync(false);
326 md_drz80 = md_drz80_prev;
327 md_drz80_prev = 0;
328 return true;
332 void md::md_set_drz80_sync(bool push)
334 if (push) {
335 drz80.Z80A = ((le2h16(z80_state.alt[0].fa) & 0xff00) << 16);
336 drz80.Z80F = (le2h16(z80_state.alt[0].fa) & 0x00ff);
337 drz80.Z80BC = (le2h16(z80_state.alt[0].cb) << 16);
338 drz80.Z80DE = (le2h16(z80_state.alt[0].ed) << 16);
339 drz80.Z80HL = (le2h16(z80_state.alt[0].lh) << 16);
340 drz80.Z80A2 = ((le2h16(z80_state.alt[1].fa) & 0xff00) << 16);
341 drz80.Z80F2 = ((le2h16(z80_state.alt[1].fa) & 0x00ff) << 24);
342 drz80.Z80BC2 = (le2h16(z80_state.alt[1].cb) << 16);
343 drz80.Z80DE2 = (le2h16(z80_state.alt[1].ed) << 16);
344 drz80.Z80HL2 = (le2h16(z80_state.alt[1].lh) << 16);
345 drz80.Z80IX = (le2h16(z80_state.ix) << 16);
346 drz80.Z80IY = (le2h16(z80_state.iy) << 16);
347 drz80.Z80SP_BASE = (uintptr_t)z80ram;
348 drz80.Z80PC_BASE = (uintptr_t)z80ram;
349 drz80.Z80SP = (drz80.Z80SP_BASE + le2h16(z80_state.sp));
350 drz80.Z80PC = (drz80.Z80PC_BASE + le2h16(z80_state.pc));
351 drz80.Z80R = z80_state.r;
352 drz80.Z80I = z80_state.i;
353 drz80.Z80IF = z80_state.iff;
354 drz80.Z80IM = z80_state.im;
356 else {
357 z80_state.alt[0].fa = h2le16(((drz80.Z80A >> 16) & 0xff00) |
358 (drz80.Z80F & 0x00ff));
359 z80_state.alt[0].cb = h2le16(drz80.Z80BC >> 16);
360 z80_state.alt[0].ed = h2le16(drz80.Z80DE >> 16);
361 z80_state.alt[0].lh = h2le16(drz80.Z80HL >> 16);
362 z80_state.alt[1].fa = h2le16(((drz80.Z80A2 >> 16) & 0xff00) |
363 ((drz80.Z80F2 >> 24) & 0x00ff));
364 z80_state.alt[1].cb = h2le16(drz80.Z80BC2 >> 16);
365 z80_state.alt[1].ed = h2le16(drz80.Z80DE2 >> 16);
366 z80_state.alt[1].lh = h2le16(drz80.Z80HL2 >> 16);
367 z80_state.ix = h2le16(drz80.Z80IX >> 16);
368 z80_state.iy = h2le16(drz80.Z80IY >> 16);
369 z80_state.sp = h2le16(drz80.Z80SP - drz80.Z80SP_BASE);
370 z80_state.pc = h2le16(drz80.Z80PC - drz80.Z80PC_BASE);
371 z80_state.r = drz80.Z80R;
372 z80_state.i = drz80.Z80I;
373 z80_state.iff = drz80.Z80IF;
374 z80_state.im = drz80.Z80IM;
377 #endif // WITH_DRZ80
379 // Set/unset contexts
380 void md::md_set(bool set)
382 #ifdef WITH_MUSA
383 if (cpu_emu == CPU_EMU_MUSA)
384 md_set_musa(set);
385 else
386 #endif
387 #ifdef WITH_CYCLONE
388 if (cpu_emu == CPU_EMU_CYCLONE)
389 md_set_cyclone(set);
390 else
391 #endif
392 #ifdef WITH_STAR
393 if (cpu_emu == CPU_EMU_STAR)
394 md_set_star(set);
395 else
396 #endif
397 (void)0;
398 #ifdef WITH_CZ80
399 if (z80_core == Z80_CORE_CZ80)
400 md_set_cz80(set);
401 else
402 #endif
403 #ifdef WITH_MZ80
404 if (z80_core == Z80_CORE_MZ80)
405 md_set_mz80(set);
406 else
407 #endif
408 #ifdef WITH_DRZ80
409 if (z80_core == Z80_CORE_DRZ80)
410 md_set_drz80(set);
411 else
412 #endif
413 (void)0;
416 // Return PC data.
417 unsigned int md::m68k_read_pc()
419 static bool rec = false;
420 unsigned int pc;
422 // Forbid recursion.
423 if (rec)
424 return h2be16(0xdead);
425 rec = true;
426 #ifdef WITH_MUSA
427 if (cpu_emu == CPU_EMU_MUSA) {
428 md_set_musa(1);
429 pc = m68k_get_reg(NULL, M68K_REG_PC);
430 md_set_musa(0);
432 else
433 #endif
434 #ifdef WITH_CYCLONE
435 if (cpu_emu == CPU_EMU_CYCLONE) {
436 md_set_cyclone(1);
437 pc = (cyclonecpu.pc - cyclonecpu.membase);
438 md_set_cyclone(0);
440 else
441 #endif
442 #ifdef WITH_STAR
443 if (cpu_emu == CPU_EMU_STAR) {
444 md_set_star(1);
445 pc = cpu.pc;
446 md_set_star(0);
448 else
449 #endif
450 pc = 0;
451 pc = misc_readword(pc & 0xffffff);
452 rec = false;
453 return pc;
456 // Return current M68K odometer
457 int md::m68k_odo()
459 if (m68k_st_running) {
460 #ifdef WITH_MUSA
461 if (cpu_emu == CPU_EMU_MUSA)
462 return (odo.m68k + m68k_cycles_run());
463 #endif
464 #ifdef WITH_CYCLONE
465 if (cpu_emu == CPU_EMU_CYCLONE)
466 return (odo.m68k +
467 ((odo.m68k_max - odo.m68k) -
468 cyclonecpu.cycles));
469 #endif
470 #ifdef WITH_STAR
471 if (cpu_emu == CPU_EMU_STAR)
472 return (odo.m68k + s68000readOdometer());
473 #endif
475 return odo.m68k;
478 // Run M68K to odo.m68k_max
479 void md::m68k_run()
481 int cycles = (odo.m68k_max - odo.m68k);
482 #ifdef WITH_DEBUGGER
483 int cycles_to_debug = 0;
484 int prev_odo = 0;
485 bool debug_m68k;
486 #endif
488 if (cycles <= 0)
489 return;
490 m68k_st_running = 1;
491 #ifdef WITH_DEBUGGER
492 if (debug_trap)
493 goto cpu_stalled;
494 debug_m68k = (debug_step_m68k ||
495 debug_trace_m68k ||
496 debug_instr_count_enabled ||
497 debug_is_m68k_bp_set() ||
498 debug_is_m68k_wp_set());
499 if (debug_m68k) {
500 prev_odo = odo.m68k;
501 cycles_to_debug = cycles;
502 cycles = 1;
503 debug_next_instruction:
504 if (debug_m68k_check_bps())
505 goto cpu_stalled;
507 #endif
508 #ifdef WITH_MUSA
509 if (cpu_emu == CPU_EMU_MUSA)
510 odo.m68k += m68k_execute(cycles);
511 else
512 #endif
513 #ifdef WITH_STAR
514 if (cpu_emu == CPU_EMU_STAR) {
515 s68000tripOdometer();
516 s68000exec(cycles);
517 odo.m68k += s68000readOdometer();
519 else
520 #endif
521 #ifdef WITH_CYCLONE
522 if (cpu_emu == CPU_EMU_CYCLONE) {
523 cyclonecpu.cycles = cycles;
524 CycloneRun(&cyclonecpu);
525 odo.m68k += (cycles - cyclonecpu.cycles);
527 else
528 #endif
529 odo.m68k += cycles;
530 #ifdef WITH_DEBUGGER
531 if (debug_m68k) {
532 ++debug_m68k_instr_count;
533 if (debug_m68k_check_wps())
534 goto cpu_stalled;
535 cycles_to_debug -= (odo.m68k - prev_odo);
536 if (cycles_to_debug > 0) {
537 prev_odo = odo.m68k;
538 goto debug_next_instruction;
541 cpu_stalled:
542 #endif
543 m68k_st_running = 0;
546 // Issue BUSREQ
547 void md::m68k_busreq_request()
549 if (z80_st_busreq)
550 return;
551 z80_st_busreq = 1;
552 if (z80_st_reset)
553 return;
554 z80_sync(0);
557 // Cancel BUSREQ
558 void md::m68k_busreq_cancel()
560 if (!z80_st_busreq)
561 return;
562 z80_st_busreq = 0;
563 z80_sync(1);
566 // Trigger M68K IRQ
567 void md::m68k_irq(int i)
569 #ifdef WITH_DEBUGGER
570 // Ignore interrupts while debugger is active or stepping by a
571 // small amount (XXX should be configurable).
572 if (debug_trap || (debug_step_m68k && debug_step_m68k < 10000))
573 return;
574 #endif
575 #ifdef WITH_MUSA
576 if (cpu_emu == CPU_EMU_MUSA)
577 m68k_set_irq(i);
578 else
579 #endif
580 #ifdef WITH_CYCLONE
581 if (cpu_emu == CPU_EMU_CYCLONE)
582 cyclonecpu.irq = i;
583 else
584 #endif
585 #ifdef WITH_STAR
586 if (cpu_emu == CPU_EMU_STAR) {
587 if (i)
588 s68000interrupt(i, -1);
589 else {
590 s68000GetContext(&cpu);
591 memset(cpu.interrupts, 0, sizeof(cpu.interrupts));
592 s68000SetContext(&cpu);
595 else
596 #endif
597 (void)i;
600 // Trigger M68K IRQ or disable them according to VDP status.
601 void md::m68k_vdp_irq_trigger()
603 if ((vdp.vint_pending) && (vdp.reg[1] & 0x20))
604 m68k_irq(6);
605 else if ((vdp.hint_pending) && (vdp.reg[0] & 0x10))
606 m68k_irq(4);
607 else
608 m68k_irq(0);
611 // Called whenever M68K acknowledges an interrupt.
612 void md::m68k_vdp_irq_handler()
614 if ((vdp.vint_pending) && (vdp.reg[1] & 0x20)) {
615 vdp.vint_pending = false;
616 coo5 &= ~0x80;
617 if ((vdp.hint_pending) && (vdp.reg[0] & 0x10))
618 m68k_irq(4);
619 else {
620 vdp.hint_pending = false;
621 m68k_irq(0);
624 else {
625 vdp.hint_pending = false;
626 m68k_irq(0);
630 // Return current Z80 odometer
631 int md::z80_odo()
633 if (z80_st_running) {
634 #ifdef WITH_CZ80
635 if (z80_core == Z80_CORE_CZ80)
636 return (odo.z80 + Cz80_Get_CycleRemaining(&cz80));
637 #endif
638 #ifdef WITH_MZ80
639 if (z80_core == Z80_CORE_MZ80)
640 return (odo.z80 + mz80GetElapsedTicks(0));
641 #endif
642 #ifdef WITH_DRZ80
643 if (z80_core == Z80_CORE_DRZ80)
644 return (odo.z80 +
645 ((odo.z80_max - odo.z80) - drz80.cycles));
646 #endif
648 return odo.z80;
651 // Run Z80 to odo.z80_max
652 void md::z80_run()
654 int cycles = (odo.z80_max - odo.z80);
655 #ifdef WITH_DEBUGGER
656 int cycles_to_debug = 0;
657 int prev_odo = 0;
658 bool debug_z80;
659 #endif
661 if (cycles <= 0)
662 return;
663 z80_st_running = 1;
664 #ifdef WITH_DEBUGGER
665 if (debug_trap)
666 goto cpu_stalled;
667 debug_z80 = (debug_step_z80 ||
668 debug_trace_z80 ||
669 debug_instr_count_enabled ||
670 debug_is_z80_bp_set() ||
671 debug_is_z80_wp_set());
672 if (debug_z80) {
673 prev_odo = odo.z80;
674 cycles_to_debug = cycles;
675 cycles = 1;
676 debug_next_instruction:
677 if (debug_z80_check_bps())
678 goto cpu_stalled;
680 #endif
681 if (z80_st_busreq | z80_st_reset)
682 odo.z80 += cycles;
683 else {
684 #ifdef WITH_CZ80
685 if (z80_core == Z80_CORE_CZ80)
686 odo.z80 += Cz80_Exec(&cz80, cycles);
687 else
688 #endif
689 #ifdef WITH_MZ80
690 if (z80_core == Z80_CORE_MZ80) {
691 mz80exec(cycles);
692 odo.z80 += mz80GetElapsedTicks(1);
694 else
695 #endif
696 #ifdef WITH_DRZ80
697 if (z80_core == Z80_CORE_DRZ80) {
698 int rem = DrZ80Run(&drz80, cycles);
700 // drz80.cycles is the number of cycles remaining,
701 // so it must be either 0 or a negative value.
702 // z80_odo() relies on this.
703 // This value is also returned by DrZ80Run().
704 assert(drz80.cycles <= 0);
705 assert(drz80.cycles == rem);
706 odo.z80 += (cycles - rem);
708 else
709 #endif
710 odo.z80 += cycles;
712 #ifdef WITH_DEBUGGER
713 if (debug_z80) {
714 ++debug_z80_instr_count;
715 if (debug_z80_check_wps())
716 goto cpu_stalled;
717 cycles_to_debug -= (odo.z80 - prev_odo);
718 if (cycles_to_debug > 0) {
719 prev_odo = odo.z80;
720 goto debug_next_instruction;
723 cpu_stalled:
724 #endif
725 z80_st_running = 0;
728 // Synchronize Z80 with M68K, don't execute code if fake is nonzero
729 void md::z80_sync(int fake)
731 int cycles = (m68k_odo() >> 1);
732 #ifdef WITH_DEBUGGER
733 int cycles_to_debug = 0;
734 int prev_odo = 0;
735 bool debug_z80;
736 #endif
738 if (cycles > odo.z80_max)
739 cycles = odo.z80_max;
740 cycles -= odo.z80;
741 if (cycles <= 0)
742 return;
743 z80_st_running = 1;
744 #ifdef WITH_DEBUGGER
745 if (debug_trap)
746 goto cpu_stalled;
747 debug_z80 = (debug_step_z80 ||
748 debug_trace_z80 ||
749 debug_instr_count_enabled ||
750 debug_is_z80_bp_set() ||
751 debug_is_z80_wp_set());
752 if (debug_z80) {
753 prev_odo = odo.z80;
754 cycles_to_debug = cycles;
755 cycles = 1;
756 debug_next_instruction:
757 if (debug_z80_check_bps())
758 goto cpu_stalled;
760 #endif
761 if (fake)
762 odo.z80 += cycles;
763 else {
764 #ifdef WITH_CZ80
765 if (z80_core == Z80_CORE_CZ80)
766 odo.z80 += Cz80_Exec(&cz80, cycles);
767 else
768 #endif
769 #ifdef WITH_MZ80
770 if (z80_core == Z80_CORE_MZ80) {
771 mz80exec(cycles);
772 odo.z80 += mz80GetElapsedTicks(1);
774 else
775 #endif
776 #ifdef WITH_DRZ80
777 if (z80_core == Z80_CORE_DRZ80) {
778 int rem = DrZ80Run(&drz80, cycles);
780 // drz80.cycles is the number of cycles remaining,
781 // so it must be either 0 or a negative value.
782 // z80_odo() relies on this.
783 // This value is also returned by DrZ80Run().
784 assert(drz80.cycles <= 0);
785 assert(drz80.cycles == rem);
786 odo.z80 += (cycles - rem);
788 else
789 #endif
790 odo.z80 += cycles;
792 #ifdef WITH_DEBUGGER
793 if (debug_z80) {
794 ++debug_z80_instr_count;
795 if (debug_z80_check_wps())
796 goto cpu_stalled;
797 cycles_to_debug -= (odo.z80 - prev_odo);
798 if (cycles_to_debug > 0) {
799 prev_odo = odo.z80;
800 goto debug_next_instruction;
803 cpu_stalled:
804 #endif
805 z80_st_running = 0;
808 // Trigger Z80 IRQ
809 void md::z80_irq(int vector)
811 #ifdef WITH_DEBUGGER
812 // Ignore interrupts while debugger is active or stepping by a
813 // small amount (XXX should be configurable).
814 if (debug_trap || (debug_step_z80 && debug_step_z80 < 1000))
815 return;
816 #endif
817 z80_st_irq = 1;
818 z80_irq_vector = vector;
819 #ifdef WITH_CZ80
820 if (z80_core == Z80_CORE_CZ80)
821 Cz80_Set_IRQ(&cz80, vector);
822 else
823 #endif
824 #ifdef WITH_MZ80
825 if (z80_core == Z80_CORE_MZ80)
826 mz80int(vector);
827 else
828 #endif
829 #ifdef WITH_DRZ80
830 if (z80_core == Z80_CORE_DRZ80) {
831 drz80.z80irqvector = vector;
832 drz80.Z80_IRQ = 1;
834 else
835 #endif
836 (void)0;
839 // Clear Z80 IRQ
840 void md::z80_irq_clear()
842 z80_st_irq = 0;
843 z80_irq_vector = 0;
844 #ifdef WITH_CZ80
845 if (z80_core == Z80_CORE_CZ80)
846 Cz80_Clear_IRQ(&cz80);
847 else
848 #endif
849 #ifdef WITH_MZ80
850 if (z80_core == Z80_CORE_MZ80)
851 mz80ClearPendingInterrupt();
852 else
853 #endif
854 #ifdef WITH_DRZ80
855 if (z80_core == Z80_CORE_DRZ80) {
856 drz80.z80irqvector = 0x00;
857 drz80.Z80_IRQ = 0x00;
859 else
860 #endif
861 (void)0;
864 // Return the number of microseconds spent in current frame
865 unsigned int md::frame_usecs()
867 if (z80_st_running)
868 return ((z80_odo() * 1000) / (clk0 / 1000));
869 return ((m68k_odo() * 1000) / (clk1 / 1000));
872 // Return first line of vblank
873 unsigned int md::vblank()
875 return (((pal) && (vdp.reg[1] & 0x08)) ? PAL_VBLANK : NTSC_VBLANK);
878 // 6-button pad status update. Should be called once per displayed line.
879 void md::pad_update()
881 // The following code was originally in DGen until at least DGen v1.21
882 // (Win32 version) but wasn't in DGen/SDL v1.23, preventing 6-button
883 // emulation from working at all until now (v1.31 included).
884 // This broke some games (no input at all).
886 // Reset 6-button pad toggle after 26? lines
887 if (aoo3_six_timeout > 25)
888 aoo3_six = 0;
889 else
890 ++aoo3_six_timeout;
891 if (aoo5_six_timeout > 25)
892 aoo5_six = 0;
893 else
894 ++aoo5_six_timeout;
897 // Generate one frame
898 int md::one_frame(struct bmap *bm, unsigned char retpal[256],
899 struct sndinfo *sndi)
901 int hints;
902 int m68k_max, z80_max;
903 unsigned int vblank = md::vblank();
905 #ifdef WITH_DEBUGGER
906 if (debug_trap)
907 return 0;
908 #endif
909 #ifdef WITH_DEBUG_VDP
911 * If the user is disabling planes for debugging, then we
912 * paint the screen black before blitting a new frame. This
913 * stops crap from earlier frames from junking up the display.
915 if ((bm != NULL) &&
916 (dgen_vdp_hide_plane_b | dgen_vdp_hide_plane_a |
917 dgen_vdp_hide_plane_w | dgen_vdp_hide_sprites))
918 memset(bm->data, 0, (bm->pitch * bm->h));
919 #endif
920 md_set(1);
921 // Reset odometers
922 memset(&odo, 0, sizeof(odo));
923 // Reset FM tickers
924 fm_ticker[1] = 0;
925 fm_ticker[3] = 0;
926 // Raster zero causes special things to happen :)
927 // Init status register with fifo always empty (FIXME)
928 coo4 = (0x34 | 0x02); // 00110100b | 00000010b
929 if (vdp.reg[12] & 0x2)
930 coo5 ^= 0x10; // Toggle odd/even for interlace
931 coo5 &= ~0x08; // Clear vblank
932 coo5 |= !!pal;
933 // Clear sprite overflow bit (d6).
934 coo5 &= ~0x40;
935 // Clear sprite collision bit (d5).
936 coo5 &= ~0x20;
937 // Is permanently set
938 hints = vdp.reg[10]; // Set hint counter
939 // Reset sprite overflow line
940 vdp.sprite_overflow_line = INT_MIN;
941 // Video display! :D
942 for (ras = 0; ((unsigned int)ras < vblank); ++ras) {
943 pad_update(); // Update 6-button pads
944 fm_timer_callback(); // Update sound timers
945 if (--hints < 0) {
946 // Trigger hint
947 hints = vdp.reg[10];
948 vdp.hint_pending = true;
949 m68k_vdp_irq_trigger();
950 may_want_to_get_pic(bm, retpal, 1);
952 else
953 may_want_to_get_pic(bm, retpal, 0);
954 // Enable h-blank
955 coo5 |= 0x04;
956 // H-blank comes before, about 36/209 of the whole scanline
957 m68k_max = (odo.m68k_max + M68K_CYCLES_PER_LINE);
958 odo.m68k_max += M68K_CYCLES_HBLANK;
959 z80_max = (odo.z80_max + Z80_CYCLES_PER_LINE);
960 odo.z80_max += Z80_CYCLES_HBLANK;
961 m68k_run();
962 z80_run();
963 // Disable h-blank
964 coo5 &= ~0x04;
965 // Do hdisplay now
966 odo.m68k_max = m68k_max;
967 odo.z80_max = z80_max;
968 m68k_run();
969 z80_run();
971 // Now we're in vblank, more special things happen :)
972 // The following was roughly adapted from Genplus GX
973 // Enable v-blank
974 coo5 |= 0x08;
975 if (--hints < 0) {
976 // Trigger hint
977 vdp.hint_pending = true;
978 m68k_vdp_irq_trigger();
980 // Save m68k_max and z80_max
981 m68k_max = (odo.m68k_max + M68K_CYCLES_PER_LINE);
982 z80_max = (odo.z80_max + Z80_CYCLES_PER_LINE);
983 // Delay between vint and vint flag
984 odo.m68k_max += M68K_CYCLES_HBLANK;
985 odo.z80_max += Z80_CYCLES_HBLANK;
986 // Enable h-blank
987 coo5 |= 0x04;
988 m68k_run();
989 z80_run();
990 // Disable h-blank
991 coo5 &= ~0x04;
992 // Toggle vint flag
993 coo5 |= 0x80;
994 // Delay between v-blank and vint
995 odo.m68k_max += (M68K_CYCLES_VDELAY - M68K_CYCLES_HBLANK);
996 odo.z80_max += (Z80_CYCLES_VDELAY - Z80_CYCLES_HBLANK);
997 m68k_run();
998 z80_run();
999 // Restore m68k_max and z80_max
1000 odo.m68k_max = m68k_max;
1001 odo.z80_max = z80_max;
1002 // Blank everything and trigger vint
1003 vdp.vint_pending = true;
1004 m68k_vdp_irq_trigger();
1005 if (!z80_st_reset)
1006 z80_irq(0);
1007 fm_timer_callback();
1008 // Run remaining cycles
1009 m68k_run();
1010 z80_run();
1011 ++ras;
1012 // Run the course of vblank
1013 pad_update();
1014 fm_timer_callback();
1015 // Usual h-blank stuff
1016 coo5 |= 0x04;
1017 m68k_max = (odo.m68k_max + M68K_CYCLES_PER_LINE);
1018 odo.m68k_max += M68K_CYCLES_HBLANK;
1019 z80_max = (odo.z80_max + Z80_CYCLES_PER_LINE);
1020 odo.z80_max += Z80_CYCLES_HBLANK;
1021 m68k_run();
1022 z80_run();
1023 coo5 &= ~0x04;
1024 odo.m68k_max = m68k_max;
1025 odo.z80_max = z80_max;
1026 m68k_run();
1027 z80_run();
1028 // Clear Z80 interrupt
1029 if (z80_st_irq)
1030 z80_irq_clear();
1031 ++ras;
1032 // Remaining lines
1033 while ((unsigned int)ras < lines) {
1034 pad_update();
1035 fm_timer_callback();
1036 // Enable h-blank
1037 coo5 |= 0x04;
1038 m68k_max = (odo.m68k_max + M68K_CYCLES_PER_LINE);
1039 odo.m68k_max += M68K_CYCLES_HBLANK;
1040 z80_max = (odo.z80_max + Z80_CYCLES_PER_LINE);
1041 odo.z80_max += Z80_CYCLES_HBLANK;
1042 m68k_run();
1043 z80_run();
1044 // Disable h-blank
1045 coo5 &= ~0x04;
1046 odo.m68k_max = m68k_max;
1047 odo.z80_max = z80_max;
1048 m68k_run();
1049 z80_run();
1050 ++ras;
1052 // Fill the sound buffers
1053 if (sndi)
1054 may_want_to_get_sound(sndi);
1055 fm_timer_callback();
1056 md_set(0);
1057 #ifdef WITH_VGMDUMP
1058 vgm_dump_frame();
1059 #endif
1060 return 0;
1063 // Return V counter (Gens/GS style)
1064 uint8_t md::calculate_coo8()
1066 unsigned int id;
1067 unsigned int hc, vc;
1068 uint8_t bl, bh;
1070 id = m68k_odo();
1072 FIXME
1073 Using "(ras - 1)" instead of "ras" here seems to solve horizon
1074 issues in Road Rash and Mickey Mania (Moose Chase level).
1076 if (ras)
1077 id -= ((ras - 1) * M68K_CYCLES_PER_LINE);
1078 id &= 0x1ff;
1079 if (vdp.reg[4] & 0x81) {
1080 hc = hc_table[id][1];
1081 bl = 0xa4;
1083 else {
1084 hc = hc_table[id][0];
1085 bl = 0x84;
1087 bh = (hc <= 0xe0);
1088 bl = (hc >= bl);
1089 bl &= bh;
1090 vc = ras;
1091 vc += (bl != 0);
1092 if (pal) {
1093 if (vc >= 0x103)
1094 vc -= 56;
1096 else {
1097 if (vc >= 0xeb)
1098 vc -= 6;
1100 return vc;
1103 // Return H counter (Gens/GS style)
1104 uint8_t md::calculate_coo9()
1106 unsigned int id;
1108 id = m68k_odo();
1109 if (ras)
1110 id -= ((ras - 1) * M68K_CYCLES_PER_LINE);
1111 id &= 0x1ff;
1112 if (vdp.reg[4] & 0x81)
1113 return hc_table[id][1];
1114 return hc_table[id][0];
1117 // *************************************
1118 // May want to get pic or sound
1119 // *************************************
1121 inline int md::may_want_to_get_pic(struct bmap *bm,unsigned char retpal[256],int/*mark*/)
1123 if (bm==NULL) return 0;
1125 if (ras>=0 && (unsigned int)ras<vblank())
1126 vdp.draw_scanline(bm, ras);
1127 if(retpal && ras == 100) get_md_palette(retpal, vdp.cram);
1128 return 0;
1131 int md::may_want_to_get_sound(struct sndinfo *sndi)
1133 extern intptr_t dgen_volume;
1134 unsigned int i, len = sndi->len;
1136 // Get the PSG
1137 SN76496Update_16_2(0, sndi->lr, len);
1139 if (dac_len) {
1140 unsigned int ratio = ((sndi->len << 10) / elemof(dac_data));
1142 // Stretch the DAC to fit the real length.
1143 for (i = 0; (i != sndi->len); ++i) {
1144 unsigned int index = ((i << 10) / ratio);
1145 uint16_t data;
1147 if (index >= dac_len)
1148 data = dac_data[dac_len - 1];
1149 else
1150 data = dac_data[index];
1151 data = ((data - 0x80) << 6);
1152 sndi->lr[i << 1] += data;
1153 sndi->lr[(i << 1) ^ 1] += data;
1155 // Clear the DAC for next frame.
1156 dac_len = 0;
1157 #ifndef NDEBUG
1158 memset(dac_data, 0xff, sizeof(dac_data));
1159 #endif
1162 // Add in the stereo FM buffer
1163 YM2612UpdateOne(0, sndi->lr, len, dgen_volume, 1);
1164 if (dgen_mjazz) {
1165 YM2612UpdateOne(1, sndi->lr, len, dgen_volume, 0);
1166 YM2612UpdateOne(2, sndi->lr, len, dgen_volume, 0);
1168 return 0;