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
5 
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"
18 
19 // Set and unset contexts (Musashi, StarScream, MZ80)
20 
21 #ifdef WITH_MUSA
22 class md* md::md_musa(0);
23 
md_set_musa(bool set)24 bool md::md_set_musa(bool set)
25 {
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;
34 	}
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;
44 	}
45 }
46 
md_set_musa_sync(bool push)47 void md::md_set_musa_sync(bool push)
48 {
49 	unsigned int i, j;
50 
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));
61 	}
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);
72 	}
73 }
74 #endif // WITH_MUSA
75 
76 #ifdef WITH_STAR
77 class md* md::md_star(0);
78 
md_set_star(bool set)79 bool md::md_set_star(bool set)
80 {
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;
89 	}
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;
99 	}
100 }
101 
md_set_star_sync(bool push)102 void md::md_set_star_sync(bool push)
103 {
104 	unsigned int i;
105 
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]);
110 		}
111 		cpu.pc = le2h32(m68k_state.pc);
112 		cpu.sr = le2h16(m68k_state.sr);
113 		s68000SetContext(&cpu);
114 	}
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]);
120 		}
121 		m68k_state.pc = h2le32(cpu.pc);
122 		m68k_state.sr = h2le16(cpu.sr);
123 	}
124 }
125 #endif // WITH_STAR
126 
127 #ifdef WITH_CYCLONE
128 class md* md::md_cyclone(0);
129 
md_set_cyclone(bool set)130 bool md::md_set_cyclone(bool set)
131 {
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;
140 	}
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;
150 	}
151 }
152 
md_set_cyclone_sync(bool push)153 void md::md_set_cyclone_sync(bool push)
154 {
155 	unsigned int i;
156 
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]);
161 		}
162 		cyclonecpu.membase = 0;
163 		cyclonecpu.pc = cyclonecpu.checkpc(le2h32(m68k_state.pc));
164 		CycloneSetSr(&cyclonecpu, le2h16(m68k_state.sr));
165 	}
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]);
170 		}
171 		m68k_state.pc = h2le32(cyclonecpu.pc-cyclonecpu.membase);
172 		m68k_state.sr = h2le16(CycloneGetSr(&cyclonecpu));
173 	}
174 }
175 #endif // WITH_CYCLONE
176 
177 #ifdef WITH_CZ80
md_set_cz80(bool set)178 bool md::md_set_cz80(bool set)
179 {
180 	if (set) {
181 		if (md_cz80_ref++)
182 			return true;
183 		md_set_cz80_sync(true);
184 		return false;
185 	}
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;
193 	}
194 }
195 
md_set_cz80_sync(bool push)196 void md::md_set_cz80_sync(bool push)
197 {
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);
215 	}
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);
233 	}
234 }
235 #endif // WITH_CZ80
236 
237 #ifdef WITH_MZ80
238 class md* md::md_mz80(0);
239 
md_set_mz80(bool set)240 bool md::md_set_mz80(bool set)
241 {
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;
250 	}
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;
260 	}
261 }
262 
md_set_mz80_sync(bool push)263 void md::md_set_mz80_sync(bool push)
264 {
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);
283 	}
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;
302 	}
303 }
304 #endif // WITH_MZ80
305 
306 #ifdef WITH_DRZ80
307 class md* md::md_drz80(0);
308 
md_set_drz80(bool set)309 bool md::md_set_drz80(bool set)
310 {
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;
319 	}
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;
329 	}
330 }
331 
md_set_drz80_sync(bool push)332 void md::md_set_drz80_sync(bool push)
333 {
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;
355 	}
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;
375 	}
376 }
377 #endif // WITH_DRZ80
378 
379 // Set/unset contexts
md_set(bool set)380 void md::md_set(bool set)
381 {
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;
414 }
415 
416 // Return PC data.
m68k_read_pc()417 unsigned int md::m68k_read_pc()
418 {
419 	static bool rec = false;
420 	unsigned int pc;
421 
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);
431 	}
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);
439 	}
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);
447 	}
448 	else
449 #endif
450 		pc = 0;
451 	pc = misc_readword(pc & 0xffffff);
452 	rec = false;
453 	return pc;
454 }
455 
456 // Return current M68K odometer
m68k_odo()457 int md::m68k_odo()
458 {
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
474 	}
475 	return odo.m68k;
476 }
477 
478 // Run M68K to odo.m68k_max
m68k_run()479 void md::m68k_run()
480 {
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
487 
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;
506 	}
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();
518 	}
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);
526 	}
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;
539 		}
540 	}
541 cpu_stalled:
542 #endif
543 	m68k_st_running = 0;
544 }
545 
546 // Issue BUSREQ
m68k_busreq_request()547 void md::m68k_busreq_request()
548 {
549 	if (z80_st_busreq)
550 		return;
551 	z80_st_busreq = 1;
552 	if (z80_st_reset)
553 		return;
554 	z80_sync(0);
555 }
556 
557 // Cancel BUSREQ
m68k_busreq_cancel()558 void md::m68k_busreq_cancel()
559 {
560 	if (!z80_st_busreq)
561 		return;
562 	z80_st_busreq = 0;
563 	z80_sync(1);
564 }
565 
566 // Trigger M68K IRQ
m68k_irq(int i)567 void md::m68k_irq(int i)
568 {
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);
593 		}
594 	}
595 	else
596 #endif
597 		(void)i;
598 }
599 
600 // Trigger M68K IRQ or disable them according to VDP status.
m68k_vdp_irq_trigger()601 void md::m68k_vdp_irq_trigger()
602 {
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);
609 }
610 
611 // Called whenever M68K acknowledges an interrupt.
m68k_vdp_irq_handler()612 void md::m68k_vdp_irq_handler()
613 {
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);
622 		}
623 	}
624 	else {
625 		vdp.hint_pending = false;
626 		m68k_irq(0);
627 	}
628 }
629 
630 // Return current Z80 odometer
z80_odo()631 int md::z80_odo()
632 {
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
647 	}
648 	return odo.z80;
649 }
650 
651 // Run Z80 to odo.z80_max
z80_run()652 void md::z80_run()
653 {
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
660 
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;
679 	}
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);
693 		}
694 		else
695 #endif
696 #ifdef WITH_DRZ80
697 		if (z80_core == Z80_CORE_DRZ80) {
698 			int rem = DrZ80Run(&drz80, cycles);
699 
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);
707 		}
708 		else
709 #endif
710 			odo.z80 += cycles;
711 	}
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;
721 		}
722 	}
723 cpu_stalled:
724 #endif
725 	z80_st_running = 0;
726 }
727 
728 // Synchronize Z80 with M68K, don't execute code if fake is nonzero
z80_sync(int fake)729 void md::z80_sync(int fake)
730 {
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
737 
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;
759 	}
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);
773 		}
774 		else
775 #endif
776 #ifdef WITH_DRZ80
777 		if (z80_core == Z80_CORE_DRZ80) {
778 			int rem = DrZ80Run(&drz80, cycles);
779 
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);
787 		}
788 		else
789 #endif
790 			odo.z80 += cycles;
791 	}
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;
801 		}
802 	}
803 cpu_stalled:
804 #endif
805 	z80_st_running = 0;
806 }
807 
808 // Trigger Z80 IRQ
z80_irq(int vector)809 void md::z80_irq(int vector)
810 {
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;
833 	}
834 	else
835 #endif
836 		(void)0;
837 }
838 
839 // Clear Z80 IRQ
z80_irq_clear()840 void md::z80_irq_clear()
841 {
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;
858 	}
859 	else
860 #endif
861 		(void)0;
862 }
863 
864 // Return the number of microseconds spent in current frame
frame_usecs()865 unsigned int md::frame_usecs()
866 {
867 	if (z80_st_running)
868 		return ((z80_odo() * 1000) / (clk0 / 1000));
869 	return ((m68k_odo() * 1000) / (clk1 / 1000));
870 }
871 
872 // Return first line of vblank
vblank()873 unsigned int md::vblank()
874 {
875 	return (((pal) && (vdp.reg[1] & 0x08)) ? PAL_VBLANK : NTSC_VBLANK);
876 }
877 
878 // 6-button pad status update. Should be called once per displayed line.
pad_update()879 void md::pad_update()
880 {
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).
885 
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;
895 }
896 
897 // Generate one frame
one_frame(struct bmap * bm,unsigned char retpal[256],struct sndinfo * sndi)898 int md::one_frame(struct bmap *bm, unsigned char retpal[256],
899 		  struct sndinfo *sndi)
900 {
901 	int hints;
902 	int m68k_max, z80_max;
903 	unsigned int vblank = md::vblank();
904 
905 #ifdef WITH_DEBUGGER
906 	if (debug_trap)
907 		return 0;
908 #endif
909 #ifdef WITH_DEBUG_VDP
910 	/*
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.
914 	 */
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);
951 		}
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();
970 	}
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();
979 	}
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;
1051 	}
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;
1061 }
1062 
1063 // Return V counter (Gens/GS style)
calculate_coo8()1064 uint8_t md::calculate_coo8()
1065 {
1066 	unsigned int id;
1067 	unsigned int hc, vc;
1068 	uint8_t bl, bh;
1069 
1070 	id = m68k_odo();
1071 	/*
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).
1075 	*/
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;
1082 	}
1083 	else {
1084 		hc = hc_table[id][0];
1085 		bl = 0x84;
1086 	}
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;
1095 	}
1096 	else {
1097 		if (vc >= 0xeb)
1098 			vc -= 6;
1099 	}
1100 	return vc;
1101 }
1102 
1103 // Return H counter (Gens/GS style)
calculate_coo9()1104 uint8_t md::calculate_coo9()
1105 {
1106 	unsigned int id;
1107 
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];
1115 }
1116 
1117 // *************************************
1118 //       May want to get pic or sound
1119 // *************************************
1120 
may_want_to_get_pic(struct bmap * bm,unsigned char retpal[256],int)1121 inline int md::may_want_to_get_pic(struct bmap *bm,unsigned char retpal[256],int/*mark*/)
1122 {
1123   if (bm==NULL) return 0;
1124 
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;
1129 }
1130 
may_want_to_get_sound(struct sndinfo * sndi)1131 int md::may_want_to_get_sound(struct sndinfo *sndi)
1132 {
1133   extern intptr_t dgen_volume;
1134   unsigned int i, len = sndi->len;
1135 
1136   // Get the PSG
1137   SN76496Update_16_2(0, sndi->lr, len);
1138 
1139 	if (dac_len) {
1140 		unsigned int ratio = ((sndi->len << 10) / elemof(dac_data));
1141 
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;
1146 
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;
1154 		}
1155 		// Clear the DAC for next frame.
1156 		dac_len = 0;
1157 #ifndef NDEBUG
1158 		memset(dac_data, 0xff, sizeof(dac_data));
1159 #endif
1160 	}
1161 
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);
1167   }
1168   return 0;
1169 }
1170 
1171