2 // Megadrive C++ module
19 extern FILE *debug_log
;
22 extern "C" unsigned star_readbyte(unsigned a
, unsigned d
);
23 extern "C" unsigned star_readword(unsigned a
, unsigned d
);
24 extern "C" unsigned star_writebyte(unsigned a
, unsigned d
);
25 extern "C" unsigned star_writeword(unsigned a
, unsigned d
);
28 * This sets up an array of memory locations.
29 * This method is StarScream specific.
30 * @return 0 on success
37 if (rommax
>0xa00000) rommax
=0xa00000;
38 if (rommax
<0) rommax
=0;
40 // FETCH: Set up 2 or 3 FETCH sections
43 { fetch
[i
].lowaddr
=0x000000; fetch
[i
].highaddr
=rommax
-1; fetch
[i
].offset
=(unsigned)rom
-0x000000; i
++; }
44 fetch
[i
].lowaddr
=0xff0000; fetch
[i
].highaddr
=0xffffff; fetch
[i
].offset
=(unsigned)ram
- 0xff0000; i
++;
46 fetch
[i
].lowaddr
=0xffff0000; fetch
[i
].highaddr
=0xffffffff; fetch
[i
].offset
=(unsigned)ram
-0xffff0000; i
++;
48 fetch
[i
].lowaddr
=0xff000000; fetch
[i
].highaddr
=0xff000000+rommax
-1; fetch
[i
].offset
=(unsigned)rom
-0xff000000; i
++;
49 fetch
[i
].lowaddr
=fetch
[i
].highaddr
=0xffffffff; fetch
[i
].offset
=0; i
++;
52 fprintf (debug_log
,"StarScream memory_map has %d fetch sections\n",i
);
57 // Simple version ***************
58 readbyte
[i
].lowaddr
= readword
[i
].lowaddr
=
59 writebyte
[j
].lowaddr
= writeword
[j
].lowaddr
= 0;
60 readbyte
[i
].highaddr
= readword
[i
].highaddr
=
61 writebyte
[j
].highaddr
= writeword
[j
].highaddr
= 0xffffffff;
63 readbyte
[i
].memorycall
=(void *)star_readbyte
;
64 readword
[i
].memorycall
=(void *)star_readword
;
65 writebyte
[j
].memorycall
=(void *)star_writebyte
;
66 writeword
[j
].memorycall
=(void *)star_writeword
;
68 readbyte
[i
].userdata
= readword
[i
].userdata
=
69 writebyte
[j
].userdata
= writeword
[j
].userdata
= NULL
;
71 // Simple version end ***************
74 // Faster version ***************
75 // IO: Set up 3/4 read sections, and 2/3 write sections
78 // Cartridge save RAM memory
80 readbyte
[i
].lowaddr
= readword
[i
].lowaddr
=
81 writebyte
[j
].lowaddr
= writeword
[j
].lowaddr
= save_start
;
82 readbyte
[i
].highaddr
= readword
[i
].highaddr
=
83 writebyte
[j
].highaddr
= writeword
[j
].highaddr
= save_start
+save_len
-1;
84 readbyte
[i
].memorycall
= star_readbyte
;
85 readword
[j
].memorycall
= star_readword
;
86 writebyte
[i
].memorycall
= star_writebyte
;
87 writeword
[j
].memorycall
= star_writeword
;
88 readbyte
[i
].userdata
= readword
[i
].userdata
=
89 writebyte
[j
].userdata
= writeword
[j
].userdata
= NULL
;
92 // Cartridge ROM memory (read only)
93 readbyte
[i
].lowaddr
= readword
[i
].lowaddr
= 0x000000;
94 readbyte
[i
].highaddr
= readword
[i
].highaddr
= rommax
-1;
95 readbyte
[i
].memorycall
=readword
[i
].memorycall
=NULL
;
96 readbyte
[i
].userdata
= readword
[i
].userdata
= rom
;
98 // misc memory (e.g. aoo and coo) through star_rw
99 readbyte
[i
].lowaddr
= readword
[i
].lowaddr
=
100 writebyte
[j
].lowaddr
= writeword
[j
].lowaddr
= rommax
;
103 readbyte
[i
].lowaddr
= readword
[i
].lowaddr
=
104 writebyte
[j
].lowaddr
= writeword
[j
].lowaddr
= 0;
106 readbyte
[i
].highaddr
= readword
[i
].highaddr
=
107 writebyte
[j
].highaddr
= writeword
[j
].highaddr
= 0xfeffff;
109 readbyte
[i
].memorycall
= star_readbyte
;
110 readword
[i
].memorycall
= star_readword
;
111 writebyte
[j
].memorycall
= star_writebyte
;
112 writeword
[j
].memorycall
= star_writeword
;
114 readbyte
[i
].userdata
= readword
[i
].userdata
=
115 writebyte
[j
].userdata
= writeword
[j
].userdata
= NULL
;
118 // scratch RAM memory
119 readbyte
[i
].lowaddr
= readword
[i
].lowaddr
=
120 writebyte
[j
].lowaddr
= writeword
[j
].lowaddr
= 0xff0000;
121 readbyte
[i
].highaddr
= readword
[i
].highaddr
=
122 writebyte
[j
].highaddr
= writeword
[j
].highaddr
= 0xffffff;
123 readbyte
[i
].memorycall
= readword
[i
].memorycall
=
124 writebyte
[j
].memorycall
=writeword
[j
].memorycall
= NULL
;
125 readbyte
[i
].userdata
= readword
[i
].userdata
=
126 writebyte
[j
].userdata
= writeword
[j
].userdata
= ram
;
128 // Faster version end ***************
132 readbyte
[i
].lowaddr
= readword
[i
].lowaddr
=
133 writebyte
[j
].lowaddr
= writeword
[j
].lowaddr
=
134 readbyte
[i
].highaddr
= readword
[i
].highaddr
=
135 writebyte
[j
].highaddr
= writeword
[j
].highaddr
= 0xffffffff;
137 readbyte
[i
].memorycall
= 0;
138 readword
[i
].memorycall
= 0;
139 writebyte
[j
].memorycall
= 0;
140 writeword
[j
].memorycall
= 0;
141 readbyte
[i
].userdata
= 0;
142 readword
[i
].userdata
= 0;
143 writebyte
[j
].userdata
= 0;
144 writeword
[j
].userdata
= 0;
149 fprintf (debug_log
,"StarScream memory_map has %d read sections and %d write sections\n",i
,j
);
154 void star_irq_callback(void)
156 assert(md::md_star
!= NULL
);
157 md::md_star
->m68k_vdp_irq_handler();
163 * This sets up an array of memory locations for Musashi.
165 void md::musa_memory_map()
167 unsigned int rom0_len
= romlen
;
168 unsigned int rom1_sta
= 0;
169 unsigned int rom1_len
= 0;
171 m68k_register_memory(NULL
, 0);
173 DEBUG(("[%06x-%06x] ???? (SAVE)",
174 save_start
, (save_start
+ save_len
- 1)));
175 if (save_start
< romlen
) {
176 /* Punch a hole through the ROM area. */
177 rom0_len
= save_start
;
178 /* Add entry for ROM leftovers, if any. */
179 if ((save_start
+ save_len
) < romlen
) {
180 rom1_sta
= (save_start
+ save_len
);
181 rom1_len
= (romlen
- rom1_sta
);
192 const m68k_mem_t mem
[3] = {
193 // r, w, x, swab, addr, size, mask, mem
194 { 1, 0, 1, S
, 0x000000, rom0_len
, 0x7fffff, rom
}, // M68K ROM
195 { 1, 1, 1, 1, 0xe00000, 0x200000, 0x00ffff, ram
}, // M68K RAM
196 { 1, 0, 1, S
, rom1_sta
, rom1_len
, 0x7fffff, &rom
[rom1_sta
] }
201 for (i
= 0; ((i
< elemof(mem
)) && (j
< elemof(musa_memory
))); ++i
) {
202 if (mem
[i
].size
== 0)
204 DEBUG(("[%06x-%06x] %c%c%c%c (%s)",
206 (mem
[i
].addr
+ mem
[i
].size
- 1),
207 (mem
[i
].r
? 'r' : '-'),
208 (mem
[i
].w
? 'w' : '-'),
209 (mem
[i
].x
? 'x' : '-'),
210 (mem
[i
].swab
? 's' : '-'),
211 (mem
[i
].w
? "RAM" : "ROM")));
212 musa_memory
[j
] = mem
[i
];
216 m68k_register_memory(musa_memory
, j
);
218 DEBUG(("no memory region defined"));
221 int musa_irq_callback(int level
)
224 assert(md::md_musa
!= NULL
);
225 md::md_musa
->m68k_vdp_irq_handler();
226 return M68K_INT_ACK_AUTOVECTOR
;
231 extern "C" uint32_t cyclone_read_memory_8(uint32_t address
);
232 extern "C" uint32_t cyclone_read_memory_16(uint32_t address
);
233 extern "C" uint32_t cyclone_read_memory_32(uint32_t address
);
234 extern "C" void cyclone_write_memory_8(uint32_t address
, uint8_t value
);
235 extern "C" void cyclone_write_memory_16(uint32_t address
, uint16_t value
);
236 extern "C" void cyclone_write_memory_32(uint32_t address
, uint32_t value
);
237 extern "C" uintptr_t cyclone_checkpc(uintptr_t pc
);
239 int cyclone_irq_callback(int level
)
242 assert(md::md_cyclone
!= NULL
);
243 md::md_cyclone
->m68k_vdp_irq_handler();
244 return CYCLONE_INT_ACK_AUTOVECTOR
;
249 * Resets everything (Z80, M68K, VDP, etc).
250 * @return 0 on success
255 memset(mem
, 0, 0x20000);
259 memset(&m68k_state
, 0, sizeof(m68k_state
));
260 memset(&z80_state
, 0, sizeof(z80_state
));
261 m68k_state_restore();
275 CycloneReset(&cyclonecpu
);
279 debug_m68k_instr_count
= 0;
280 debug_z80_instr_count
= 0;
282 if (debug_log
) fprintf (debug_log
,"reset()\n");
284 aoo3_toggle
=aoo5_toggle
=aoo3_six
=aoo5_six
285 =aoo3_six_timeout
=aoo5_six_timeout
287 pad
[0] = MD_PAD_UNTOUCHED
;
288 pad
[1] = MD_PAD_UNTOUCHED
;
289 memset(pad_com
, 0, sizeof(pad_com
));
292 // Initialize Pico pen X, Y coordinates
293 pico_pen_coords
[0] = 0x3c;
294 pico_pen_coords
[1] = 0x1fc;
297 // Reset FM registers
301 memset(&odo
, 0, sizeof(odo
));
315 extern "C" UINT8
mz80_read(UINT32 a
, struct MemoryReadByte
*unused
);
316 extern "C" void mz80_write(UINT32 a
, UINT8 d
, struct MemoryWriteByte
*unused
);
317 extern "C" UINT16
mz80_ioread(UINT16 a
, struct z80PortRead
*unused
);
318 extern "C" void mz80_iowrite(UINT16 a
, UINT8 d
, struct z80PortWrite
*unused
);
320 static struct MemoryReadByte mem_read
[] = {
321 { 0x0000, 0xffff, mz80_read
, NULL
},
322 { (UINT32
)-1, (UINT32
)-1, NULL
, NULL
}
325 static struct MemoryWriteByte mem_write
[] = {
326 { 0x0000, 0xffff, mz80_write
, NULL
},
327 { (UINT32
)-1, (UINT32
)-1, NULL
, NULL
}
330 static struct z80PortRead io_read
[] = {
331 { 0x00, 0xff, mz80_ioread
, NULL
},
332 { (UINT16
)-1, (UINT16
)-1, NULL
, NULL
}
335 static struct z80PortWrite io_write
[] = {
336 { 0x00, 0xff, mz80_iowrite
, NULL
},
337 { (UINT16
)-1, (UINT16
)-1, NULL
, NULL
}
344 extern "C" uint8_t cz80_memread(void *ctx
, uint16_t a
);
345 extern "C" void cz80_memwrite(void *ctx
, uint16_t a
, uint8_t d
);
346 extern "C" uint16_t cz80_memread16(void *ctx
, uint16_t a
);
347 extern "C" void cz80_memwrite16(void *ctx
, uint16_t a
, uint16_t d
);
348 extern "C" uint8_t cz80_ioread(void *ctx
, uint16_t a
);
349 extern "C" void cz80_iowrite(void *ctx
, uint16_t a
, uint8_t d
);
355 extern uintptr_t drz80_rebaseSP(uint16_t new_sp
);
356 extern uintptr_t drz80_rebasePC(uint16_t new_pc
);
357 extern uint8_t drz80_read8(uint16_t a
);
358 extern uint16_t drz80_read16(uint16_t a
);
359 extern void drz80_write8(uint8_t d
, uint16_t a
);
360 extern void drz80_write16(uint16_t d
, uint16_t a
);
361 extern uint8_t drz80_in(uint16_t p
);
362 extern void drz80_out(uint16_t p
, uint8_t d
);
364 void drz80_irq_callback()
366 md::md_drz80
->drz80_irq_cb();
369 void md::drz80_irq_cb()
371 drz80
.Z80_IRQ
= 0x00; // lower irq when in accepted
377 * Initialise the Z80.
385 // Erase local context with global context.
386 mz80GetContext(&z80
);
387 // Configure callbacks in local context.
388 z80
.z80Base
= z80ram
;
389 z80
.z80MemRead
= mem_read
;
390 z80
.z80MemWrite
= mem_write
;
391 z80
.z80IoRead
= io_read
;
392 z80
.z80IoWrite
= io_write
;
393 // Erase global context with the above.
394 mz80SetContext(&z80
);
398 Cz80_Set_Ctx(&cz80
, this);
399 Cz80_Set_Fetch(&cz80
, 0x0000, 0xffff, (void *)z80ram
);
400 Cz80_Set_ReadB(&cz80
, cz80_memread
);
401 Cz80_Set_WriteB(&cz80
, cz80_memwrite
);
402 Cz80_Set_ReadW(&cz80
, cz80_memread16
);
403 Cz80_Set_WriteW(&cz80
, cz80_memwrite16
);
404 Cz80_Set_INPort(&cz80
, cz80_ioread
);
405 Cz80_Set_OUTPort(&cz80
, cz80_iowrite
);
409 memset(&drz80
, 0, sizeof(drz80
));
410 drz80
.z80_write8
= drz80_write8
;
411 drz80
.z80_write16
= drz80_write16
;
412 drz80
.z80_in
= drz80_in
;
413 drz80
.z80_out
= drz80_out
;
414 drz80
.z80_read8
= drz80_read8
;
415 drz80
.z80_read16
= drz80_read16
;
416 drz80
.z80_rebasePC
= drz80_rebasePC
;
417 drz80
.z80_rebaseSP
= drz80_rebaseSP
;
418 drz80
.z80_irq_callback
= drz80_irq_callback
;
422 z80_bank68k
= 0xff8000;
430 z80_bank68k
= 0xff8000;
441 drz80
.Z80A
= (1 << 2); // set ZFlag
442 drz80
.Z80F
= (1 << 2); // set ZFlag
448 drz80
.Z80BC2
= 0x0000 << 16;
449 drz80
.Z80DE2
= 0x0000 << 16;
450 drz80
.Z80HL2
= 0x0000 << 16;
451 drz80
.Z80IX
= 0xFFFF << 16;
452 drz80
.Z80IY
= 0xFFFF << 16;
455 drz80
.Z80_IRQ
= 0x00;
460 drz80
.Z80PC
= drz80_rebasePC(0);
461 drz80
.Z80SP
= drz80_rebaseSP(0x2000);
468 * @return True when successful.
470 bool md::init_sound()
482 // Initialize two additional chips when MJazz is enabled.
483 if (YM2612Init((dgen_mjazz
? 3 : 1),
484 (((pal
) ? PAL_MCLK
: NTSC_MCLK
) / 7),
485 dgen_soundrate
, dgen_mjazz
, NULL
, NULL
))
489 (((pal
) ? PAL_MCLK
: NTSC_MCLK
) / 15),
497 * Switch to PAL or NTSC.
498 * This method's name is a bit misleading. This switches to PAL or not
499 * depending on "md::pal".
517 // Initialize horizontal counter table (Gens style)
518 for (hc
= 0; (hc
< 512); ++hc
) {
520 hc_table
[hc
][0] = (((hc
* 170) / M68K_CYCLES_PER_LINE
) - 0x18);
522 hc_table
[hc
][1] = (((hc
* 205) / M68K_CYCLES_PER_LINE
) - 0x1c);
526 bool md::lock
= false;
530 * @param pal True if we are running the MD in PAL mode.
531 * @param region Region to emulate ('J', 'U', or 'E').
533 md::md(bool pal
, char region
):
535 md_musa_ref(0), md_musa_prev(0),
538 md_cyclone_ref(0), md_cyclone_prev(0),
541 md_star_ref(0), md_star_prev(0),
547 md_mz80_ref(0), md_mz80_prev(0),
549 pal(pal
), ok_ym2612(false), ok_sn76496(false),
550 vdp(*this), region(region
), plugged(false)
552 // Only one MD object is allowed to exist at once.
560 // Start up the sound chips.
561 if (init_sound() == false)
564 romlen
= no_rom_size
;
565 rom
= (uint8_t*)no_rom
;
566 mem
=ram
=z80ram
=saveram
=NULL
;
567 save_start
=save_len
=save_prot
=save_active
=0;
572 vgm_dump_file
= NULL
;
573 vgm_dump_samples_total
= 0;
574 vgm_dump_dac_wait
= 0;
575 vgm_dump_dac_samples
= 0;
580 pico_enabled
= false;
583 memset(&m68k_state
, 0, sizeof(m68k_state
));
584 memset(&z80_state
, 0, sizeof(z80_state
));
587 ctx_musa
= calloc(1, m68k_context_size());
588 if (ctx_musa
== NULL
)
592 m68k_set_cpu_type(M68K_CPU_TYPE_68000
);
593 m68k_register_memory(NULL
, 0);
594 m68k_set_int_ack_callback(musa_irq_callback
);
600 readbyte
=readword
=writebyte
=writeword
=NULL
;
601 memset(&cpu
,0,sizeof(cpu
));
605 memset(&cyclonecpu
, 0, sizeof(cyclonecpu
));
606 cyclonecpu
.read8
= cyclone_read_memory_8
;
607 cyclonecpu
.read16
= cyclone_read_memory_16
;
608 cyclonecpu
.read32
= cyclone_read_memory_32
;
609 cyclonecpu
.write8
= cyclone_write_memory_8
;
610 cyclonecpu
.write16
= cyclone_write_memory_16
;
611 cyclonecpu
.write32
= cyclone_write_memory_32
;
612 cyclonecpu
.checkpc
= cyclone_checkpc
;
613 cyclonecpu
.fetch8
= cyclone_read_memory_8
;
614 cyclonecpu
.fetch16
= cyclone_read_memory_16
;
615 cyclonecpu
.fetch32
= cyclone_read_memory_32
;
616 cyclonecpu
.IrqCallback
= cyclone_irq_callback
;
623 memset(&z80
,0,sizeof(z80
));
629 memset(&drz80
, 0, sizeof(drz80
));
631 memset(&cart_head
, 0, sizeof(cart_head
));
633 memset(romname
, 0, sizeof(romname
));
637 // Format of pad is: __SA____ UDLRBC__
639 rom
= (uint8_t*)no_rom
;
640 romlen
= no_rom_size
;
642 mem
=(unsigned char *)malloc(0x20008);
645 memset(mem
,0,0x20000);
648 // Hack for DrZ80 to avoid crashing when PC leaves z80ram.
649 z80ram
[0x10000] = 0x00; // NOP
650 z80ram
[0x10001] = 0x00; // NOP
651 z80ram
[0x10002] = 0x00; // NOP
652 z80ram
[0x10003] = 0x00; // NOP
653 z80ram
[0x10004] = 0x00; // NOP
654 z80ram
[0x10005] = 0xc3; // JP 0x0000
655 z80ram
[0x10006] = 0x00;
656 z80ram
[0x10007] = 0x00;
665 if (s68000init() != 0) {
667 printf ("s68000init failed!\n");
672 // Dave: Rich said doing point star stuff is done after s68000init
673 // in Asgard68000, so just in case...
674 if (((fetch
= new STARSCREAM_PROGRAMREGION
[6]) == NULL
) ||
675 ((readbyte
= new STARSCREAM_DATAREGION
[5]) == NULL
) ||
676 ((readword
= new STARSCREAM_DATAREGION
[5]) == NULL
) ||
677 ((writebyte
= new STARSCREAM_DATAREGION
[5]) == NULL
) ||
678 ((writeword
= new STARSCREAM_DATAREGION
[5]) == NULL
))
684 cpu
.s_fetch
= cpu
.u_fetch
= fetch
;
685 cpu
.s_readbyte
= cpu
.u_readbyte
= readbyte
;
686 cpu
.s_readword
= cpu
.u_readword
= readword
;
687 cpu
.s_writebyte
= cpu
.u_writebyte
= writebyte
;
688 cpu
.s_writeword
= cpu
.u_writeword
= writeword
;
690 cpu
.inthandler
= star_irq_callback
;
696 // M68K: 0 = none, 1 = StarScream, 2 = Musashi, 3 = Cyclone
697 switch (dgen_emu_m68k
) {
700 cpu_emu
= CPU_EMU_STAR
;
705 cpu_emu
= CPU_EMU_MUSA
;
710 cpu_emu
= CPU_EMU_CYCLONE
;
714 cpu_emu
= CPU_EMU_NONE
;
717 // Z80: 0 = none, 1 = CZ80, 2 = MZ80, 3 = DrZ80
718 switch (dgen_emu_z80
) {
721 z80_core
= Z80_CORE_MZ80
;
726 z80_core
= Z80_CORE_CZ80
;
731 z80_core
= Z80_CORE_DRZ80
;
735 z80_core
= Z80_CORE_NONE
;
751 reset(); // reset megadrive
774 memset(this, 0, sizeof(*this));
789 rom
=mem
=ram
=z80ram
=NULL
;
810 memset(this, 0, sizeof(*this));
817 * @param[in] start Byte array of cart memory.
818 * @param len How many bytes to byteswap.
819 * @return 0 on success (always 0).
822 int byteswap_memory(unsigned char *start
,int len
)
823 { int i
; unsigned char tmp
;
825 { tmp
=start
[i
+0]; start
[i
+0]=start
[i
+1]; start
[i
+1]=tmp
; }
831 * Plug a cart into the MD.
832 * @param[in] cart Cart's memory as a byte array.
833 * @param len Length of the cart.
834 * @return 0 on success.
836 int md::plug_in(unsigned char *cart
,int len
)
838 // Plug in the cartridge specified by the uchar *
839 // NB - The megadrive will free() it if unplug() is called, or it exits
840 // So it must be a single piece of malloced data
841 if (cart
==NULL
) return 1; if (len
<=0) return 1;
843 byteswap_memory(cart
,len
); // for starscream
847 // Get saveram start, length (remember byteswapping)
848 // First check magic, if there is saveram
849 if(rom
[ROM_ADDR(0x1b0)] == 'R' && rom
[ROM_ADDR(0x1b1)] == 'A')
851 save_start
= rom
[ROM_ADDR(0x1b4)] << 24 | rom
[ROM_ADDR(0x1b5)] << 16 |
852 rom
[ROM_ADDR(0x1b6)] << 8 | rom
[ROM_ADDR(0x1b7)];
853 save_len
= rom
[ROM_ADDR(0x1b8)] << 24 | rom
[ROM_ADDR(0x1b9)] << 16 |
854 rom
[ROM_ADDR(0x1ba)] << 8 | rom
[ROM_ADDR(0x1bb)];
855 // Make sure start is even, end is odd, for alignment
856 // A ROM that I came across had the start and end bytes of
857 // the save ram the same and wouldn't work. Fix this as seen
858 // fit, I know it could probably use some work. [PKH]
859 if(save_start
!= save_len
) {
860 if(save_start
& 1) --save_start
;
861 if(!(save_len
& 1)) ++save_len
;
862 save_len
-= (save_start
- 1);
863 saveram
= (unsigned char*)calloc(1, save_len
);
864 if (saveram
== NULL
) {
868 // If save RAM does not overlap main ROM, set it active by default since
869 // a few games can't manage to properly switch it on/off.
870 if(save_start
>= (unsigned int)romlen
)
874 save_start
= save_len
= 0;
880 save_start
= save_len
= 0;
890 memory_map(); // Update memory map to include this cartridge
893 reset(); // Reset megadrive
898 * Region to emulate according to dgen_region_order and ROM header.
899 * @return Region identifier ('J', 'U' or 'E').
901 uint8_t md::region_guess()
903 char const* order
= dgen_region_order
.val
;
904 char const* avail
= this->cart_head
.countries
;
908 assert(order
!= NULL
);
909 assert(avail
!= NULL
);
910 for (r
= 0; (order
[r
] != '\0'); ++r
)
911 for (i
= 0; (i
!= sizeof(this->cart_head
.countries
)); ++i
)
912 if ((isprint(order
[r
])) &&
913 (toupper(order
[r
]) == toupper(avail
[i
])))
914 return toupper(order
[r
]);
915 // Use default region.
920 * Unplug a cart from the system.
921 * @return 0 on success.
927 if (rom
== no_rom
) return 1;
929 rom
= (uint8_t*)no_rom
;
930 romlen
= no_rom_size
;
933 save_start
= save_len
= 0;
941 memory_map(); // Update memory map to include no rom
944 memset(romname
, 0, sizeof(romname
));
945 memset(&cart_head
, 0, sizeof(cart_head
));
948 while (patch_elem
!= NULL
) {
949 struct patch_elem
*next
= patch_elem
->next
;
961 * @param[in] name File name of cart to load.
962 * @return 0 on success.
964 int md::load(const char *name
)
970 if ((name
== NULL
) ||
971 ((b_name
= dgen_basename(name
)) == NULL
))
973 temp
= load_rom(&size
, name
);
979 if ((b_name
[0] != '\0')) {
982 snprintf(romname
, sizeof(romname
), "%s", b_name
);
983 for (i
= 0; (romname
[i
] != '\0'); ++i
)
984 if (romname
[i
] == '.') {
985 memset(&(romname
[i
]), 0,
986 (sizeof(romname
) - i
));
990 if (romname
[0] == '\0')
991 snprintf(romname
, sizeof(romname
), "%s", "unknown");
993 // Fill the header with ROM info (god this is ugly)
994 memcpy((void*)cart_head
.system_name
, (void*)(temp
+ 0x100), 0x10);
995 memcpy((void*)cart_head
.copyright
, (void*)(temp
+ 0x110), 0x10);
996 memcpy((void*)cart_head
.domestic_name
,(void*)(temp
+ 0x120), 0x30);
997 memcpy((void*)cart_head
.overseas_name
,(void*)(temp
+ 0x150), 0x30);
998 memcpy((void*)cart_head
.product_no
, (void*)(temp
+ 0x180), 0x0e);
999 cart_head
.checksum
= temp
[0x18e]<<8 | temp
[0x18f]; // ugly, but endian-neutral
1000 memcpy((void*)cart_head
.control_data
, (void*)(temp
+ 0x190), 0x10);
1001 cart_head
.rom_start
= temp
[0x1a0]<<24 | temp
[0x1a1]<<16 | temp
[0x1a2]<<8 | temp
[0x1a3];
1002 cart_head
.rom_end
= temp
[0x1a4]<<24 | temp
[0x1a5]<<16 | temp
[0x1a6]<<8 | temp
[0x1a7];
1003 cart_head
.ram_start
= temp
[0x1a8]<<24 | temp
[0x1a9]<<16 | temp
[0x1aa]<<8 | temp
[0x1ab];
1004 cart_head
.ram_end
= temp
[0x1ac]<<24 | temp
[0x1ad]<<16 | temp
[0x1ae]<<8 | temp
[0x1af];
1005 cart_head
.save_magic
= temp
[0x1b0]<<8 | temp
[0x1b1];
1006 cart_head
.save_flags
= temp
[0x1b2]<<8 | temp
[0x1b3];
1007 cart_head
.save_start
= temp
[0x1b4]<<24 | temp
[0x1b5]<<16 | temp
[0x1b6]<<8 | temp
[0x1b7];
1008 cart_head
.save_end
= temp
[0x1b8]<<24 | temp
[0x1b9]<<16 | temp
[0x1ba]<<8 | temp
[0x1bb];
1009 memcpy((void*)cart_head
.memo
, (void*)(temp
+ 0x1c8), 0x28);
1010 memcpy((void*)cart_head
.countries
, (void*)(temp
+ 0x1f0), 0x10);
1013 // Check if cartridge inserted is intended for Sega Pico.
1014 // If it is, the Sega Pico I/O area will be enabled, and the
1015 // Megadrive I/O area will be disabled.
1016 if ((!strncmp(cart_head
.system_name
, "SEGA PICO", 9)) ||
1017 (!strncmp(cart_head
.system_name
, "SEGATOYS PICO", 13)))
1018 pico_enabled
= true;
1020 pico_enabled
= false;
1022 // Plug it into the memory map
1023 plug_in(temp
, size
); // md then deallocates it when it's done
1029 * Cycle through Z80 CPU implementations.
1031 void md::cycle_z80()
1034 z80_core
= (enum z80_core
)((z80_core
+ 1) % Z80_CORE_TOTAL
);
1035 z80_state_restore();
1039 * Cycle between M68K CPU implementations.
1041 void md::cycle_cpu()
1044 cpu_emu
= (enum cpu_emu
)((cpu_emu
+ 1) % CPU_EMU_TOTAL
);
1045 m68k_state_restore();
1049 * Dump Z80 ram to a file named "dgz80ram".
1050 * @return Always returns 0.
1055 hand
= dgen_fopen(NULL
, "dgz80ram", DGEN_WRITE
);
1057 { fwrite(z80ram
,1,0x10000,hand
); fclose(hand
); }
1062 * This takes a comma or whitespace-separated list of Game Genie and/or hex
1063 * codes to patch the ROM with.
1064 * @param[in] list List of codes separated by '\\t', '\\n', or ','.
1065 * @param[out] errors Number of codes that failed to apply.
1066 * @param[out] applied Number of codes that applied correctly.
1067 * @param[out] reverted Number of codes that were reverted.
1068 * @return 0 on success.
1070 int md::patch(const char *list
, unsigned int *errors
,
1071 unsigned int *applied
, unsigned int *reverted
)
1073 static const char delims
[] = " \t\n,";
1074 char *worklist
, *tok
;
1081 if (applied
!= NULL
)
1083 if (reverted
!= NULL
)
1086 // Copy the given list to a working list so we can strtok it
1087 wl_sz
= strlen(list
) + 1;
1088 worklist
= (char *)malloc(wl_sz
);
1089 if (worklist
== NULL
)
1091 strncpy(worklist
, list
, wl_sz
);
1093 for(tok
= strtok(worklist
, delims
); tok
; tok
= strtok(NULL
, delims
))
1095 struct patch_elem
*elem
= patch_elem
;
1096 struct patch_elem
*prev
= NULL
;
1097 uint8_t *dest
= rom
;
1098 size_t mask
= ~(size_t)0;
1102 // If it's empty, toss it
1103 if(*tok
== '\0') continue;
1106 // Discard it if it was bad code
1107 if (((signed)p
.addr
== -1) || (p
.addr
>= (size_t)(romlen
- 1))) {
1108 if ((p
.addr
< 0xff0000) || (p
.addr
>= 0xffffff)) {
1109 printf("Bad patch \"%s\"\n", tok
);
1115 // This is a RAM patch.
1119 if (dest
== no_rom
) {
1120 printf("Cannot patch this ROM\n");
1123 #ifndef ROM_BYTESWAP
1127 // Put it into dest (remember byteswapping)
1128 while (elem
!= NULL
) {
1129 if (elem
->addr
== p
.addr
) {
1130 // Revert a previous patch.
1131 p
.data
= elem
->data
;
1133 prev
->next
= elem
->next
;
1144 printf("Reverting patch \"%s\" -> %06X\n", tok
, p
.addr
);
1145 if (reverted
!= NULL
)
1149 printf("Patch \"%s\" -> %06X:%04X\n", tok
, p
.addr
, p
.data
);
1150 if (applied
!= NULL
)
1152 if ((elem
= (struct patch_elem
*)malloc(sizeof(*elem
))) != NULL
) {
1153 elem
->next
= patch_elem
;
1154 elem
->addr
= p
.addr
;
1155 elem
->data
= ((dest
[((p
.addr
+ 0) ^ swap
) & mask
] << 8) |
1156 (dest
[((p
.addr
+ 1) ^ swap
) & mask
]));
1160 dest
[((p
.addr
+ 0) ^ swap
) & mask
] = (uint8_t)(p
.data
>> 8);
1161 dest
[((p
.addr
+ 1) ^ swap
) & mask
] = (uint8_t)(p
.data
& 0xff);
1169 * Get saveram from FILE*.
1170 * @param from File to read from.
1171 * @return 0 on success.
1173 int md::get_save_ram(FILE *from
)
1175 return !fread((void*)saveram
, save_len
, 1, from
);
1179 * Write a saveram to FILE*.
1180 * @param into File to write to.
1181 * @return 0 on success.
1183 int md::put_save_ram(FILE *into
)
1185 return !fwrite((void*)saveram
, save_len
, 1, into
);
1189 * Calculates a ROM's checksum.
1190 * @param rom ROM memory area.
1191 * @param len ROM size.
1194 static unsigned short calculate_checksum(unsigned char *rom
,int len
)
1196 unsigned short checksum
=0;
1198 for (i
=512;i
<=(len
-2);i
+=2)
1200 checksum
+=(rom
[ROM_ADDR(i
+0)]<<8);
1201 checksum
+=rom
[ROM_ADDR(i
+1)];
1207 * Replace the in-memory ROM checksum with a calculated checksum.
1209 void md::fix_rom_checksum()
1211 unsigned short cs
; cs
=calculate_checksum(rom
,romlen
);
1212 if (romlen
>=0x190) { rom
[ROM_ADDR(0x18e)]=cs
>>8; rom
[ROM_ADDR(0x18f)]=cs
&255; }
1216 * This is the default ROM, used when nothing is loaded.
1220 const uint8_t md::no_rom
[] = {
1221 // Note: everything is byte swapped.
1222 "\x72\x4e" "\xff\xff" // stop #0xffff
1225 "\xf6\x60" // bra.b 0
1230 const uint8_t md::no_rom
[] = {
1231 "\x4e\x72" "\xff\xff" // stop #0xffff
1234 "\x60\xf6" // bra.b 0
1239 const size_t md::no_rom_size
= sizeof(no_rom
);