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