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
19 // Set and unset contexts (Musashi, StarScream, MZ80)
22 class md
* md::md_musa(0);
24 bool md::md_set_musa(bool set
)
30 md_musa_prev
= md_musa
;
32 md_set_musa_sync(true);
38 if (--md_musa_ref
!= 0)
40 md_set_musa_sync(false);
41 md_musa
= md_musa_prev
;
47 void md::md_set_musa_sync(bool 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
));
63 for (i
= M68K_REG_D0
, j
= 0; (i
<= M68K_REG_D7
); ++i
, ++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
)
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
);
77 class md
* md::md_star(0);
79 bool md::md_set_star(bool set
)
85 md_star_prev
= md_star
;
87 md_set_star_sync(true);
93 if (--md_star_ref
!= 0)
95 md_set_star_sync(false);
96 md_star
= md_star_prev
;
102 void md::md_set_star_sync(bool 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
);
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
);
128 class md
* md::md_cyclone(0);
130 bool md::md_set_cyclone(bool set
)
134 if (md_cyclone
== this)
136 md_cyclone_prev
= md_cyclone
;
138 md_set_cyclone_sync(true);
142 if (md_cyclone
!= this)
144 if (--md_cyclone_ref
!= 0)
146 md_set_cyclone_sync(false);
147 md_cyclone
= md_cyclone_prev
;
153 void md::md_set_cyclone_sync(bool 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
));
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
178 bool md::md_set_cz80(bool set
)
183 md_set_cz80_sync(true);
187 if (md_cz80_ref
== 0)
191 md_set_cz80_sync(false);
196 void md::md_set_cz80_sync(bool 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
);
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
);
238 class md
* md::md_mz80(0);
240 bool md::md_set_mz80(bool set
)
246 md_mz80_prev
= md_mz80
;
248 md_set_mz80_sync(true);
254 if (--md_mz80_ref
!= 0)
256 md_set_mz80_sync(false);
257 md_mz80
= md_mz80_prev
;
263 void md::md_set_mz80_sync(bool 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
);
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
;
307 class md
* md::md_drz80(0);
309 bool md::md_set_drz80(bool set
)
313 if (md_drz80
== this)
315 md_drz80_prev
= md_drz80
;
317 md_set_drz80_sync(true);
321 if (md_drz80
!= this)
323 if (--md_drz80_ref
!= 0)
325 md_set_drz80_sync(false);
326 md_drz80
= md_drz80_prev
;
332 void md::md_set_drz80_sync(bool 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
;
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
;
379 // Set/unset contexts
380 void md::md_set(bool set
)
383 if (cpu_emu
== CPU_EMU_MUSA
)
388 if (cpu_emu
== CPU_EMU_CYCLONE
)
393 if (cpu_emu
== CPU_EMU_STAR
)
399 if (z80_core
== Z80_CORE_CZ80
)
404 if (z80_core
== Z80_CORE_MZ80
)
409 if (z80_core
== Z80_CORE_DRZ80
)
417 unsigned int md::m68k_read_pc()
419 static bool rec
= false;
424 return h2be16(0xdead);
427 if (cpu_emu
== CPU_EMU_MUSA
) {
429 pc
= m68k_get_reg(NULL
, M68K_REG_PC
);
435 if (cpu_emu
== CPU_EMU_CYCLONE
) {
437 pc
= (cyclonecpu
.pc
- cyclonecpu
.membase
);
443 if (cpu_emu
== CPU_EMU_STAR
) {
451 pc
= misc_readword(pc
& 0xffffff);
456 // Return current M68K odometer
459 if (m68k_st_running
) {
461 if (cpu_emu
== CPU_EMU_MUSA
)
462 return (odo
.m68k
+ m68k_cycles_run());
465 if (cpu_emu
== CPU_EMU_CYCLONE
)
467 ((odo
.m68k_max
- odo
.m68k
) -
471 if (cpu_emu
== CPU_EMU_STAR
)
472 return (odo
.m68k
+ s68000readOdometer());
478 // Run M68K to odo.m68k_max
481 int cycles
= (odo
.m68k_max
- odo
.m68k
);
483 int cycles_to_debug
= 0;
494 debug_m68k
= (debug_step_m68k
||
496 debug_instr_count_enabled
||
497 debug_is_m68k_bp_set() ||
498 debug_is_m68k_wp_set());
501 cycles_to_debug
= cycles
;
503 debug_next_instruction
:
504 if (debug_m68k_check_bps())
509 if (cpu_emu
== CPU_EMU_MUSA
)
510 odo
.m68k
+= m68k_execute(cycles
);
514 if (cpu_emu
== CPU_EMU_STAR
) {
515 s68000tripOdometer();
517 odo
.m68k
+= s68000readOdometer();
522 if (cpu_emu
== CPU_EMU_CYCLONE
) {
523 cyclonecpu
.cycles
= cycles
;
524 CycloneRun(&cyclonecpu
);
525 odo
.m68k
+= (cycles
- cyclonecpu
.cycles
);
532 ++debug_m68k_instr_count
;
533 if (debug_m68k_check_wps())
535 cycles_to_debug
-= (odo
.m68k
- prev_odo
);
536 if (cycles_to_debug
> 0) {
538 goto debug_next_instruction
;
547 void md::m68k_busreq_request()
558 void md::m68k_busreq_cancel()
567 void md::m68k_irq(int i
)
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))
576 if (cpu_emu
== CPU_EMU_MUSA
)
581 if (cpu_emu
== CPU_EMU_CYCLONE
)
586 if (cpu_emu
== CPU_EMU_STAR
) {
588 s68000interrupt(i
, -1);
590 s68000GetContext(&cpu
);
591 memset(cpu
.interrupts
, 0, sizeof(cpu
.interrupts
));
592 s68000SetContext(&cpu
);
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))
605 else if ((vdp
.hint_pending
) && (vdp
.reg
[0] & 0x10))
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;
617 if ((vdp
.hint_pending
) && (vdp
.reg
[0] & 0x10))
620 vdp
.hint_pending
= false;
625 vdp
.hint_pending
= false;
630 // Return current Z80 odometer
633 if (z80_st_running
) {
635 if (z80_core
== Z80_CORE_CZ80
)
636 return (odo
.z80
+ Cz80_Get_CycleRemaining(&cz80
));
639 if (z80_core
== Z80_CORE_MZ80
)
640 return (odo
.z80
+ mz80GetElapsedTicks(0));
643 if (z80_core
== Z80_CORE_DRZ80
)
645 ((odo
.z80_max
- odo
.z80
) - drz80
.cycles
));
651 // Run Z80 to odo.z80_max
654 int cycles
= (odo
.z80_max
- odo
.z80
);
656 int cycles_to_debug
= 0;
667 debug_z80
= (debug_step_z80
||
669 debug_instr_count_enabled
||
670 debug_is_z80_bp_set() ||
671 debug_is_z80_wp_set());
674 cycles_to_debug
= cycles
;
676 debug_next_instruction
:
677 if (debug_z80_check_bps())
681 if (z80_st_busreq
| z80_st_reset
)
685 if (z80_core
== Z80_CORE_CZ80
)
686 odo
.z80
+= Cz80_Exec(&cz80
, cycles
);
690 if (z80_core
== Z80_CORE_MZ80
) {
692 odo
.z80
+= mz80GetElapsedTicks(1);
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
);
714 ++debug_z80_instr_count
;
715 if (debug_z80_check_wps())
717 cycles_to_debug
-= (odo
.z80
- prev_odo
);
718 if (cycles_to_debug
> 0) {
720 goto debug_next_instruction
;
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);
733 int cycles_to_debug
= 0;
738 if (cycles
> odo
.z80_max
)
739 cycles
= odo
.z80_max
;
747 debug_z80
= (debug_step_z80
||
749 debug_instr_count_enabled
||
750 debug_is_z80_bp_set() ||
751 debug_is_z80_wp_set());
754 cycles_to_debug
= cycles
;
756 debug_next_instruction
:
757 if (debug_z80_check_bps())
765 if (z80_core
== Z80_CORE_CZ80
)
766 odo
.z80
+= Cz80_Exec(&cz80
, cycles
);
770 if (z80_core
== Z80_CORE_MZ80
) {
772 odo
.z80
+= mz80GetElapsedTicks(1);
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
);
794 ++debug_z80_instr_count
;
795 if (debug_z80_check_wps())
797 cycles_to_debug
-= (odo
.z80
- prev_odo
);
798 if (cycles_to_debug
> 0) {
800 goto debug_next_instruction
;
809 void md::z80_irq(int vector
)
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))
818 z80_irq_vector
= vector
;
820 if (z80_core
== Z80_CORE_CZ80
)
821 Cz80_Set_IRQ(&cz80
, vector
);
825 if (z80_core
== Z80_CORE_MZ80
)
830 if (z80_core
== Z80_CORE_DRZ80
) {
831 drz80
.z80irqvector
= vector
;
840 void md::z80_irq_clear()
845 if (z80_core
== Z80_CORE_CZ80
)
846 Cz80_Clear_IRQ(&cz80
);
850 if (z80_core
== Z80_CORE_MZ80
)
851 mz80ClearPendingInterrupt();
855 if (z80_core
== Z80_CORE_DRZ80
) {
856 drz80
.z80irqvector
= 0x00;
857 drz80
.Z80_IRQ
= 0x00;
864 // Return the number of microseconds spent in current frame
865 unsigned int md::frame_usecs()
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)
891 if (aoo5_six_timeout
> 25)
897 // Generate one frame
898 int md::one_frame(struct bmap
*bm
, unsigned char retpal
[256],
899 struct sndinfo
*sndi
)
902 int m68k_max
, z80_max
;
903 unsigned int vblank
= md::vblank();
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.
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
));
922 memset(&odo
, 0, sizeof(odo
));
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
933 // Clear sprite overflow bit (d6).
935 // Clear sprite collision bit (d5).
937 // Is permanently set
938 hints
= vdp
.reg
[10]; // Set hint counter
939 // Reset sprite overflow line
940 vdp
.sprite_overflow_line
= INT_MIN
;
942 for (ras
= 0; ((unsigned int)ras
< vblank
); ++ras
) {
943 pad_update(); // Update 6-button pads
944 fm_timer_callback(); // Update sound timers
948 vdp
.hint_pending
= true;
949 m68k_vdp_irq_trigger();
950 may_want_to_get_pic(bm
, retpal
, 1);
953 may_want_to_get_pic(bm
, retpal
, 0);
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
;
966 odo
.m68k_max
= m68k_max
;
967 odo
.z80_max
= z80_max
;
971 // Now we're in vblank, more special things happen :)
972 // The following was roughly adapted from Genplus GX
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
;
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
);
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();
1007 fm_timer_callback();
1008 // Run remaining cycles
1012 // Run the course of vblank
1014 fm_timer_callback();
1015 // Usual h-blank stuff
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
;
1024 odo
.m68k_max
= m68k_max
;
1025 odo
.z80_max
= z80_max
;
1028 // Clear Z80 interrupt
1033 while ((unsigned int)ras
< lines
) {
1035 fm_timer_callback();
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
;
1046 odo
.m68k_max
= m68k_max
;
1047 odo
.z80_max
= z80_max
;
1052 // Fill the sound buffers
1054 may_want_to_get_sound(sndi
);
1055 fm_timer_callback();
1063 // Return V counter (Gens/GS style)
1064 uint8_t md::calculate_coo8()
1067 unsigned int hc
, vc
;
1073 Using "(ras - 1)" instead of "ras" here seems to solve horizon
1074 issues in Road Rash and Mickey Mania (Moose Chase level).
1077 id
-= ((ras
- 1) * M68K_CYCLES_PER_LINE
);
1079 if (vdp
.reg
[4] & 0x81) {
1080 hc
= hc_table
[id
][1];
1084 hc
= hc_table
[id
][0];
1103 // Return H counter (Gens/GS style)
1104 uint8_t md::calculate_coo9()
1110 id
-= ((ras
- 1) * M68K_CYCLES_PER_LINE
);
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
);
1131 int md::may_want_to_get_sound(struct sndinfo
*sndi
)
1133 extern intptr_t dgen_volume
;
1134 unsigned int i
, len
= sndi
->len
;
1137 SN76496Update_16_2(0, sndi
->lr
, 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
);
1147 if (index
>= dac_len
)
1148 data
= dac_data
[dac_len
- 1];
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.
1158 memset(dac_data
, 0xff, sizeof(dac_data
));
1162 // Add in the stereo FM buffer
1163 YM2612UpdateOne(0, sndi
->lr
, len
, dgen_volume
, 1);
1165 YM2612UpdateOne(1, sndi
->lr
, len
, dgen_volume
, 0);
1166 YM2612UpdateOne(2, sndi
->lr
, len
, dgen_volume
, 0);