-
Notifications
You must be signed in to change notification settings - Fork 1
/
md.h
781 lines (700 loc) · 21 KB
/
md.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
// DGen
#ifndef __MD_H__
#define __MD_H__
#define VER VERSION
#include <stdint.h>
#ifdef WITH_STAR
#ifndef __STARCPU_H__
#include "star/starcpu.h"
#endif
#endif
#ifdef WITH_MUSA
#ifndef M68K__HEADER
extern "C"
{
#include "musa/m68k.h"
}
#endif
#endif
#ifdef WITH_CYCLONE
#include "cyclone/Cyclone.h"
#endif
#ifdef WITH_MZ80
#ifndef _MZ80_H_
#include "mz80/mz80.h"
#endif
#endif
#ifdef WITH_CZ80
#include "cz80/cz80.h"
#endif
#ifdef WITH_DRZ80
#include "drz80/drz80.h"
#endif
#ifdef WITH_DZ80
#include "dz80/types.h"
#include "dz80/dissz80.h"
#endif
//#define BUILD_YM2612
extern "C" {
#include "fm.h"
}
#include "sn76496.h"
#include "system.h"
// Debugging macros and support functions. They look like this because C++98
// lacks support for variadic macros. Not my fault.
#ifndef NDEBUG
#include <stdarg.h>
#include <stdio.h>
static inline const char *debug_basename_(const char *name)
{
const char *tmp;
for (tmp = name; (*tmp != '\0'); ++tmp)
if (*tmp == '/')
name = (tmp + 1);
return name;
}
static inline void debug_printf__()
{
fputc('\n', stderr);
}
static inline void (*debug_printf_(const char *s, ...))()
{
va_list vl;
va_start(vl, s);
vfprintf(stderr, s, vl);
va_end(vl);
return debug_printf__;
}
static inline void (*(*debug_(const char *file, unsigned int line,
const char *func))(const char *, ...))()
{
fprintf(stderr, "%s:%u: %s: ", debug_basename_(file), line, func);
return debug_printf_;
}
#define DEBUG(s) (((debug_(__FILE__, __LINE__, __func__))s)(), (void)0)
#else
#define DEBUG(s) (void)0
#endif
/* ROM is always byteswapped when StarScream or Cyclone are enabled. */
#if defined(WITH_STAR) || defined(WITH_CYCLONE)
#define ROM_BYTESWAP
#define ROM_ADDR(a) ((a) ^ 1)
#else
#undef ROM_BYTESWAP
#define ROM_ADDR(a) (a)
#endif
#ifdef WITH_DEBUGGER
#include "debug.h"
#endif
extern "C" int test_ctv(unsigned char *dest, int len);
extern "C" int blur_bitmap_16(unsigned char *dest, int len);
extern "C" int blur_bitmap_15(unsigned char *dest, int len);
struct bmap { unsigned char *data; int w,h; int pitch; int bpp; };
// New struct, happily encapsulates all the sound info
struct sndinfo {
int16_t *lr;
unsigned int len; /* number of stereo samples */
};
int get_md_palette(unsigned char pal[256],unsigned char *cram);
class md;
class md_vdp
{
public:
// Next three lines are the state of the VDP
// They have to be public so we can save and load states
// and draw the screen.
uint8_t mem[(0x10100 + 0x35)]; //0x20+0x10+0x4+1 for dirt
uint8_t *vram, *cram, *vsram;
uint8_t reg[0x20];
int rw_mode,rw_addr,rw_dma;
bool hint_pending;
bool vint_pending;
bool cmd_pending; // set when first half of command arrives
int sprite_overflow_line;
private:
int poke_vram (int addr,unsigned char d);
int poke_cram (int addr,unsigned char d);
int poke_vsram(int addr,unsigned char d);
int dma_len();
int dma_addr();
unsigned char dma_mem_read(int addr);
int putword(unsigned short d);
int putbyte(unsigned char d);
// Used by draw_scanline to render the different display components
void draw_tile1(int which, int line, unsigned char *where);
void draw_tile1_solid(int which, int line, unsigned char *where);
void draw_tile2(int which, int line, unsigned char *where);
void draw_tile2_solid(int which, int line, unsigned char *where);
void draw_tile3(int which, int line, unsigned char *where);
void draw_tile3_solid(int which, int line, unsigned char *where);
void draw_tile4(int which, int line, unsigned char *where);
void draw_tile4_solid(int which, int line, unsigned char *where);
void draw_window(int line, int front);
void draw_sprites(int line, bool front);
void draw_plane_back0(int line);
void draw_plane_back1(int line);
void draw_plane_front0(int line);
void draw_plane_front1(int line);
struct sprite_info {
uint8_t* sprite; // sprite location
uint32_t* tile; // array of tiles (th * tw)
int x; // X position in pixels
int y; // Y position in pixels
int tw; // width in tiles
int th; // height in tiles
int w; // width in pixels
int h; // height in pixels
unsigned int prio:1; // high priority bit
unsigned int inter:1; // interlaced mode (8x16 tiles)
unsigned int xflip:1; // X-flipped
unsigned int yflip:1; // Y-flipped
};
inline void get_sprite_info(struct sprite_info&, int);
inline void sprite_mask_add(uint8_t*, int, struct sprite_info&, int);
// Working variables for the above
unsigned char sprite_order[0x101], *sprite_base;
uint8_t sprite_mask[512][512];
int sprite_count;
int masking_sprite_index_cache;
int dots_cache;
unsigned int Bpp;
unsigned int Bpp_times8;
struct bmap *bmap;
unsigned char *dest;
md& belongs;
public:
md_vdp(md&);
~md_vdp();
// These are called by MEM.CPP
int command(uint16_t cmd);
unsigned short readword();
unsigned char readbyte();
int writeword(unsigned short d);
int writebyte(unsigned char d);
unsigned char *dirt; // Bitfield: what has changed VRAM/CRAM/VSRAM/Reg
void reset();
uint32_t highpal[64];
// Draw a scanline
void sprite_masking_overflow(int line);
void sprite_mask_generate();
void draw_scanline(struct bmap *bits, int line);
void draw_pixel(struct bmap *bits, int x, int y, uint32_t rgb);
void write_reg(uint8_t addr, uint8_t data);
};
/* Generic structures for dumping and restoring M68K and Z80 states. */
typedef struct {
/* Stored MSB first (big endian) */
uint32_t d[8]; /* D0-D7 */
uint32_t a[8]; /* A0-A7 */
uint32_t pc;
uint16_t sr;
} m68k_state_t;
typedef struct {
/* Stored LSB first (little endian) */
struct {
uint16_t fa;
uint16_t cb;
uint16_t ed;
uint16_t lh;
} alt[2]; /* [1] = alternate registers */
uint16_t ix;
uint16_t iy;
uint16_t sp;
uint16_t pc;
uint8_t r;
uint8_t i;
uint8_t iff; /* x x x x x x IFF2 IFF1 */
uint8_t im; /* interrupt mode */
uint8_t irq_asserted; /* IRQ asserted */
uint8_t irq_vector; /* IRQ vector */
} z80_state_t;
#define MCLK_CYCLES_PER_LINE 3416 /* XXX ideally 3415.597 */
#define M68K_CYCLES_PER_LINE (MCLK_CYCLES_PER_LINE / 7)
#define M68K_CYCLES_HBLANK ((M68K_CYCLES_PER_LINE * 36) / 209)
#define M68K_CYCLES_VDELAY ((M68K_CYCLES_PER_LINE * 36) / 156)
#define Z80_CYCLES_PER_LINE (MCLK_CYCLES_PER_LINE / 15)
#define Z80_CYCLES_HBLANK ((Z80_CYCLES_PER_LINE * 36) / 209)
#define Z80_CYCLES_VDELAY ((Z80_CYCLES_PER_LINE * 36) / 156)
#define NTSC_LINES 262
#define NTSC_VBLANK 224
#define NTSC_HZ 60
#define NTSC_MCLK (MCLK_CYCLES_PER_LINE * NTSC_LINES * NTSC_HZ)
#define PAL_LINES 312
#define PAL_VBLANK 240
#define PAL_HZ 50
#define PAL_MCLK (MCLK_CYCLES_PER_LINE * PAL_LINES * PAL_HZ)
#define MD_UP_MASK (1) // 0x00001
#define MD_DOWN_MASK (1 << 1) // 0x00002
#define MD_LEFT_MASK (1 << 2) // 0x00004
#define MD_RIGHT_MASK (1 << 3) // 0x00008
#define MD_B_MASK (1 << 4) // 0x00010
#define MD_C_MASK (1 << 5) // 0x00020
#define MD_A_MASK (1 << 12) // 0x01000
#define MD_START_MASK (1 << 13) // 0x02000
#define MD_Z_MASK (1 << 16) // 0x10000
#define MD_Y_MASK (1 << 17) // 0x20000
#define MD_X_MASK (1 << 18) // 0x40000
#define MD_MODE_MASK (1 << 19) // 0x80000
#define MD_PAD_UNTOUCHED 0xf303f
#ifdef WITH_PICO
#define MD_PICO_PENBTN_MASK (1 << 7) // 0x00080
#endif
class md {
public:
// ROM placeholder.
static const uint8_t no_rom[];
static const size_t no_rom_size;
// Get default NTSC/PAL, Hz, VBLANK, lines number and memory byte
// for region, which is identified by a single character (J, X, U, E).
static void region_info(uint8_t region, int* pal, int* hz,
int* vblank, int* lines, uint8_t* mem)
{
// Make region code uppercase and replace space with 0.
region &= ~0x20;
switch (region) {
case 'X':
// Japan (PAL). This region code isn't found in ROMs
// but I wanted to label it somehow.
if (mem)
*mem = (0x00 | 0x40); // local + PAL
mem = 0;
case 'E':
// Europe (PAL).
if (pal)
*pal = 1;
if (hz)
*hz = PAL_HZ;
if (vblank)
*vblank = PAL_VBLANK;
if (lines)
*lines = PAL_LINES;
if (mem)
*mem = (0x80 | 0x40); // overseas + PAL
break;
case 'J':
default:
// Japan (NTSC).
if (mem)
*mem = 0x00; // local
mem = 0;
case 'U':
// America (NTSC).
if (pal)
*pal = 0;
if (hz)
*hz = NTSC_HZ;
if (vblank)
*vblank = NTSC_VBLANK;
if (lines)
*lines = NTSC_LINES;
if (mem)
*mem = 0x80; // overseas
break;
}
}
#ifdef WITH_MUSA
static class md* md_musa;
unsigned int md_musa_ref;
class md* md_musa_prev;
bool md_set_musa(bool set);
void md_set_musa_sync(bool push);
#endif
#ifdef WITH_CYCLONE
static class md* md_cyclone;
unsigned int md_cyclone_ref;
class md* md_cyclone_prev;
bool md_set_cyclone(bool set);
void md_set_cyclone_sync(bool push);
uintptr_t checkpc(uintptr_t pc);
#endif
#ifdef WITH_STAR
static class md* md_star;
unsigned int md_star_ref;
class md* md_star_prev;
bool md_set_star(bool set);
void md_set_star_sync(bool push);
#endif
#ifdef WITH_CZ80
unsigned int md_cz80_ref;
bool md_set_cz80(bool set);
void md_set_cz80_sync(bool push);
#endif
#ifdef WITH_MZ80
static class md* md_mz80;
unsigned int md_mz80_ref;
class md* md_mz80_prev;
bool md_set_mz80(bool set);
void md_set_mz80_sync(bool push);
#endif
#ifdef WITH_DRZ80
static class md* md_drz80;
unsigned int md_drz80_ref;
class md* md_drz80_prev;
bool md_set_drz80(bool set);
void md_set_drz80_sync(bool push);
#endif
void md_set(bool set);
unsigned int mclk; // Master clock
unsigned int clk0; // MCLK/15 for Z80, SN76489
unsigned int clk1; // MCLK/7 for M68K, YM2612
unsigned int lines;
unsigned int vhz;
unsigned int pal: 1;
unsigned int vblank(); // Return first vblank line
private:
static bool lock; // Prevent other MD objects
unsigned int ok: 1;
unsigned int ok_ym2612: 1; // YM2612
unsigned int ok_sn76496: 1; // SN76496
unsigned int romlen;
unsigned char *mem,*rom,*ram,*z80ram;
// Saveram stuff:
unsigned char *saveram; // The actual saveram buffer
unsigned save_start, save_len; // Start address and length
int save_prot, save_active; // Flags set from $A130F1
public:
md_vdp vdp;
m68k_state_t m68k_state;
z80_state_t z80_state;
void m68k_state_dump();
void m68k_state_restore();
void z80_state_dump();
void z80_state_restore();
private:
#ifdef WITH_MZ80
struct mz80context z80;
#endif
#ifdef WITH_CZ80
cz80_struc cz80;
#endif
#ifdef WITH_DRZ80
struct DrZ80 drz80 __attribute__((packed)); // See drz80.h and drz80.s.
friend uintptr_t drz80_rebaseSP(uint16_t new_sp);
uintptr_t drz80_rebase_pc(uint16_t address);
friend uintptr_t drz80_rebasePC(uint16_t new_pc);
uintptr_t drz80_rebase_sp(uint16_t address);
friend void drz80_irq_callback();
void drz80_irq_cb();
#endif
#ifdef WITH_STAR
struct S68000CONTEXT cpu;
STARSCREAM_PROGRAMREGION *fetch;
STARSCREAM_DATAREGION *readbyte,*readword,*writebyte,*writeword;
int memory_map();
friend void star_irq_callback(void);
#endif
#ifdef WITH_MUSA
void *ctx_musa;
void musa_memory_map();
m68k_mem_t musa_memory[3];
friend int musa_irq_callback(int);
#endif
#ifdef WITH_CYCLONE
struct Cyclone cyclonecpu;
friend int cyclone_irq_callback(int);
#endif
uint32_t z80_bank68k;
unsigned int z80_st_busreq: 1; // in BUSREQ state
unsigned int z80_st_reset: 1; // in RESET state
unsigned int z80_st_running: 1; // Z80 is running
unsigned int z80_st_irq: 1; // Z80 IRQ asserted
unsigned int m68k_st_running: 1; // M68K is running
int z80_irq_vector; // Z80 IRQ vector
struct {
int m68k;
int m68k_max;
int z80;
int z80_max;
} odo;
int ras;
// Note order is (0) Vblank end -------- Vblank Start -- (HIGH)
// So int6 happens in the middle of the count
int aoo3_toggle,aoo5_toggle,aoo3_six,aoo5_six;
int aoo3_six_timeout, aoo5_six_timeout;
unsigned char calculate_coo8();
unsigned char calculate_coo9();
int may_want_to_get_pic(struct bmap *bm,unsigned char retpal[256],int mark);
int may_want_to_get_sound(struct sndinfo *sndi);
// Horizontal counter table
uint8_t hc_table[512][2];
unsigned int m68k_read_pc(); // PC data
int m68k_odo(); // M68K odometer
void m68k_run(); // Run M68K to odo.m68k_max
void m68k_busreq_request(); // Issue BUSREQ
void m68k_busreq_cancel(); // Cancel BUSREQ
void m68k_irq(int i); // Trigger M68K IRQ
void m68k_vdp_irq_trigger(); // Trigger IRQ from VDP status
void m68k_vdp_irq_handler(); // Called when interrupts are acknowledged
int z80_odo(); // Z80 odometer
void z80_run(); // Run Z80 to odo.z80_max
void z80_sync(int fake); // Synchronize Z80 with M68K
void z80_irq(int vector); // Trigger Z80 IRQ
void z80_irq_clear(); // Clear Z80 IRQ
// Number of microseconds spent in current frame
unsigned int frame_usecs();
int fm_timer_callback();
int myfm_read(int a);
int mysn_write(int v);
void fm_reset();
uint8_t fm_sel[2];
uint8_t fm_tover;
int fm_ticker[4];
signed short fm_reg[2][0x100]; // All of them (-1 = not def'd yet)
uint8_t dac_data[0x400];
unsigned int dac_len;
bool dac_enabled;
void dac_init();
void dac_submit(uint8_t d);
void dac_enable(uint8_t d);
uint8_t m68k_ROM_read(uint32_t a);
uint8_t m68k_IO_read(uint32_t a);
uint8_t m68k_VDP_read(uint32_t a);
void m68k_ROM_write(uint32_t, uint8_t);
void m68k_IO_write(uint32_t, uint8_t);
public:
int myfm_write(int a,int v,int md);
#ifdef WITH_VGMDUMP
FILE *vgm_dump_file;
uint32_t vgm_dump_samples_total;
uint32_t vgm_dump_dac_wait;
unsigned int vgm_dump_dac_samples;
bool vgm_dump;
void vgm_dump_ym2612(uint8_t a1, uint8_t reg, uint8_t data);
void vgm_dump_sn76496(uint8_t data);
int vgm_dump_start(const char *name);
void vgm_dump_stop();
void vgm_dump_frame();
#endif
// public struct, full with data from the cartridge header
struct _carthead_ {
char system_name[0x10]; // "SEGA GENESIS ", "SEGA MEGA DRIVE "
char copyright[0x10]; // "(C)SEGA 1988.JUL"
char domestic_name[0x30]; // Domestic game name
char overseas_name[0x30]; // Overseas game name
char product_no[0xe]; // "GM XXXXXXXX-XX" or "GM MK-XXXX -00"
unsigned short checksum; // ROM checksum
char control_data[0x10]; // I/O use data (usually only joystick)
unsigned rom_start, rom_end; // ROM start & end addresses
unsigned ram_start, ram_end; // RAM start & end addresses
unsigned short save_magic; // 0x5241("RA") if saveram, else 0x2020
unsigned short save_flags; // Misc saveram info
unsigned save_start, save_end; // Saveram start & end
unsigned short modem_magic; // 0x4d4f("MO") if uses modem, else 0x2020
char modem_firm[4]; // Modem firm name (should be same as (c))
char modem_ver[4]; // yy.z, yy=ID number, z=version
char memo[0x28]; // Extra data
char countries[0x10]; // Country code
} cart_head;
char region; // Emulator region.
uint8_t region_guess();
int one_frame(struct bmap *bm,unsigned char retpal[256],struct sndinfo *sndi);
void pad_update();
int pad[2];
uint8_t pad_com[2];
#ifdef WITH_PICO
bool pico_enabled;
uint16_t pico_pen_coords[2];
#endif
// c000004 bit 1 write fifo empty, bit 0 write fifo full (???)
// c000005 vint happened, (sprover, coll, oddinint)
// invblank, inhblank, dma busy, pal
unsigned char coo4,coo5;
int okay() {return ok;}
bool plugged;
md(bool pal, char region);
~md();
void init_pal();
bool init_sound();
int plug_in(unsigned char *cart,int len);
int unplug();
int load(const char *name);
int reset();
uint8_t misc_readbyte(uint32_t a);
void misc_writebyte(uint32_t a, uint8_t d);
uint16_t misc_readword(uint32_t a);
void misc_writeword(uint32_t a, uint16_t d);
void z80_init();
void z80_reset();
uint8_t z80_read(uint16_t a);
void z80_write(uint16_t a, uint8_t d);
uint8_t z80_port_read(uint16_t a);
void z80_port_write(uint16_t a, uint8_t d);
enum z80_core {
Z80_CORE_NONE,
#ifdef WITH_MZ80
Z80_CORE_MZ80,
#endif
#ifdef WITH_CZ80
Z80_CORE_CZ80,
#endif
#ifdef WITH_DRZ80
Z80_CORE_DRZ80,
#endif
Z80_CORE_TOTAL
} z80_core;
void cycle_z80();
enum cpu_emu {
CPU_EMU_NONE,
#ifdef WITH_STAR
CPU_EMU_STAR,
#endif
#ifdef WITH_MUSA
CPU_EMU_MUSA,
#endif
#ifdef WITH_CYCLONE
CPU_EMU_CYCLONE,
#endif
CPU_EMU_TOTAL
} cpu_emu; // OK to read it but call cycle_cpu() to change it
void cycle_cpu();
#ifdef WITH_MZ80
mz80context& z80_context() {return z80;}
#endif
int import_gst(FILE *hand);
int export_gst(FILE *hand);
char romname[256];
int z80dump();
// Fix ROM checksum
void fix_rom_checksum();
// List of patches currently applied.
struct patch_elem {
struct patch_elem *next;
uint32_t addr;
uint16_t data;
} *patch_elem;
// Added by Joe Groff:
// Patch the ROM code, using Game Genie/Hex codes
int patch(const char *list, unsigned int *errors,
unsigned int *applied, unsigned int *reverted);
// Get/put the battery save RAM
int has_save_ram();
int get_save_ram(FILE *from);
int put_save_ram(FILE *into);
#ifdef WITH_JOYSTICK
// Added by Phillip K. Hornung <redx@pknet.com>
void init_joysticks();
void deinit_joysticks();
#endif
// Debugger stuff
#ifdef WITH_DEBUGGER
private:
// M68K FLAGS
// user byte
#define M68K_SR_CARRY (1<<0)
#define M68K_SR_OVERFLOW (1<<1)
#define M68K_SR_ZERO (1<<2)
#define M68K_SR_NEGATIVE (1<<3)
#define M68K_SR_EXTEND (1<<4)
// system byte
#define M68K_SR_IP_MASK1 (1<<8)
#define M68K_SR_IP_MASK2 (1<<9)
#define M68K_SR_IP_MASK3 (1<<10)
#define M68K_SR_MI_STATE (1<<12)
#define M68K_SR_SUP_STATE (1<<13)
#define M68K_SR_TRACE_EN1 (1<<14)
#define M68K_SR_TRACE_EN2 (1<<15)
// Z80 FLAGS
#define Z80_SR_CARRY (1<<0)
#define Z80_SR_ADD_SUB (1<<1)
#define Z80_SR_PARITY_OVERFLOW (1<<2)
#define Z80_SR_HALF_CARRY (1<<4)
#define Z80_SR_ZERO (1<<6)
#define Z80_SR_SIGN (1<<7)
struct dgen_bp debug_bp_m68k[MAX_BREAKPOINTS];
struct dgen_wp debug_wp_m68k[MAX_WATCHPOINTS];
unsigned int debug_step_m68k;
unsigned int debug_trace_m68k;
struct dgen_bp debug_bp_z80[MAX_BREAKPOINTS];
struct dgen_wp debug_wp_z80[MAX_WATCHPOINTS];
unsigned int debug_step_z80;
unsigned int debug_trace_z80;
int debug_context;
unsigned long debug_m68k_instr_count;
unsigned long debug_z80_instr_count;
bool debug_instr_count_enabled;
#ifdef WITH_DZ80
DISZ80 disz80;
#endif
bool debug_is_m68k_bp_set();
bool debug_is_m68k_wp_set();
int debug_next_free_wp_m68k();
int debug_next_free_bp_m68k();
bool debug_is_z80_bp_set();
bool debug_is_z80_wp_set();
int debug_next_free_wp_z80();
int debug_next_free_bp_z80();
void debug_init();
int debug_find_bp_m68k(uint32_t);
int debug_find_wp_m68k(uint32_t);
void debug_print_m68k_wp(int);
int debug_should_m68k_wp_fire(struct dgen_wp *w);
int debug_find_bp_z80(uint16_t);
int debug_find_wp_z80(uint16_t);
void debug_print_z80_wp(int);
int debug_should_z80_wp_fire(struct dgen_wp *w);
uint32_t m68k_get_pc();
uint16_t z80_get_pc();
bool debug_m68k_check_bps();
bool debug_m68k_check_wps();
bool debug_z80_check_bps();
bool debug_z80_check_wps();
void debug_rm_bp_m68k(int);
void debug_rm_wp_m68k(int);
void debug_rm_bp_z80(int);
void debug_rm_wp_z80(int);
void debug_list_bps_m68k();
void debug_list_wps_m68k();
void debug_list_bps_z80();
void debug_list_wps_z80();
int debug_set_bp_m68k(uint32_t);
int debug_set_bp_z80(uint16_t);
public:
struct dgen_debugger_cmd {
char *cmd;
int n_args;
int (md::*handler)(int, char **);
};
const static struct md::dgen_debugger_cmd debug_cmd_list[];
bool debug_trap;
// commands
int debug_despatch_cmd(int n_toks, char **args);
int debug_cmd_cont(int n_args, char **args);
int debug_cmd_reg(int n_args, char **args);
int debug_cmd_help(int n_args, char **args);
int debug_cmd_break(int n_args, char **args);
int debug_cmd_quit(int n_args, char **args);
int debug_cmd_step(int n_args, char **args);
int debug_cmd_trace(int n_args, char **args);
int debug_cmd_minus_break(int n_args, char **args);
int debug_cmd_cpu(int n_args, char **args);
int debug_cmd_dis(int n_args, char **args);
int debug_cmd_mem(int n_args, char **args);
int debug_cmd_setbwlr(int n_args, char **args, unsigned int type);
int debug_cmd_setb(int n_args, char **args);
int debug_cmd_setw(int n_args, char **args);
int debug_cmd_setl(int n_args, char **args);
int debug_cmd_setr(int n_args, char **args);
int debug_cmd_count(int n_args, char **args);
int debug_cmd_watch(int n_args, char **args);
int debug_cmd_minus_watch(int n_args, char **args);
// misc
int debug_enter(void);
void debug_leave(void);
void debug_update_m68k_wp_cache(struct dgen_wp *w);
void debug_update_z80_wp_cache(struct dgen_wp *w);
void debug_update_fired_m68k_wps(void);
void debug_update_fired_z80_wps(void);
void debug_set_wp_m68k(uint32_t start_addr, uint32_t end_addr);
void debug_set_wp_z80(uint16_t start_addr, uint16_t end_addr);
void debug_print_m68k_disassemble(uint32_t from, int len);
void debug_print_z80_disassemble(uint16_t, unsigned int);
void debug_show_m68k_regs(void);
void debug_show_z80_regs(void);
void debug_dump_mem(uint32_t addr, uint32_t len);
#endif
};
inline int md::has_save_ram()
{
return save_len;
}
#endif // __MD_H__