From 49392b331e781fa6efbdf770a7b5d01e7d8ba277 Mon Sep 17 00:00:00 2001 From: EkeEke Date: Fri, 19 Apr 2013 16:54:26 +0200 Subject: [PATCH 1/5] [MD] added auto-detection of byte-swapped ROM --- source/loadrom.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/source/loadrom.c b/source/loadrom.c index e1d942c..b51381d 100644 --- a/source/loadrom.c +++ b/source/loadrom.c @@ -601,7 +601,7 @@ int load_rom(char *filename) /* Mega Drive hardware (Genesis mode) */ system_hw = SYSTEM_MD; - /* Decode .MDX format */ + /* decode .MDX format */ if (!memcmp("MDX", &extension[0], 3)) { for (i = 4; i < size - 1; i++) @@ -610,6 +610,18 @@ int load_rom(char *filename) } size = size - 5; } + + /* auto-detect byte-swapped dumps */ + if (!memcmp((char *)(cart.rom + 0x100),"ESAGM GE ARDVI E", 16) || + !memcmp((char *)(cart.rom + 0x100),"ESAGG NESESI", 12)) + { + for(i = 0; i < size; i += 2) + { + uint8 temp = cart.rom[i]; + cart.rom[i] = cart.rom[i+1]; + cart.rom[i+1] = temp; + } + } } /* auto-detect 512 byte extra header */ @@ -656,10 +668,10 @@ int load_rom(char *filename) scd.cartridge.boot = 0x00; } +#ifdef LSB_FIRST /* 16-bit ROM specific */ else if (system_hw == SYSTEM_MD) { -#ifdef LSB_FIRST /* Byteswap ROM to optimize 16-bit access */ for (i = 0; i < cart.romsize; i += 2) { @@ -667,20 +679,8 @@ int load_rom(char *filename) cart.rom[i] = cart.rom[i+1]; cart.rom[i+1] = temp; } -#endif - - /* byteswapped RADICA dumps (from Haze) */ - if (((strstr(rominfo.product,"-K0101") != NULL) && (rominfo.checksum == 0xf424)) || - ((strstr(rominfo.product,"-K0109") != NULL) && (rominfo.checksum == 0x4f10))) - { - for(i = 0; i < cart.romsize; i += 2) - { - uint8 temp = cart.rom[i]; - cart.rom[i] = cart.rom[i+1]; - cart.rom[i+1] = temp; - } - } } +#endif /* Save auto-detected system hardware */ romtype = system_hw; From f78f3e605a6188cf193ef6018634830d3743c78b Mon Sep 17 00:00:00 2001 From: EkeEke Date: Fri, 19 Apr 2013 16:54:55 +0200 Subject: [PATCH 2/5] Fixed broken 68k address error emulation --- source/cart_hw/md_cart.c | 5 ---- source/genesis.c | 1 + source/m68k/m68k.h | 60 ++++++++++++++++------------------------ 3 files changed, 25 insertions(+), 41 deletions(-) diff --git a/source/cart_hw/md_cart.c b/source/cart_hw/md_cart.c index 35a9ec8..8889e49 100644 --- a/source/cart_hw/md_cart.c +++ b/source/cart_hw/md_cart.c @@ -520,11 +520,6 @@ void md_cart_init(void) } } -#if M68K_EMULATE_ADDRESS_ERROR - /* default behavior */ - m68k.aerr_enabled = config.addr_error; -#endif - /* detect specific mappers */ if (strstr(rominfo.domestic,"SUPER STREET FIGHTER2") != NULL) { diff --git a/source/genesis.c b/source/genesis.c index 7eec88d..729d59b 100644 --- a/source/genesis.c +++ b/source/genesis.c @@ -67,6 +67,7 @@ void gen_init(void) { /* initialize main 68k */ m68k_init(); + m68k.aerr_enabled = config.addr_error; /* initialize main 68k memory map */ diff --git a/source/m68k/m68k.h b/source/m68k/m68k.h index c85319d..f93b3fc 100644 --- a/source/m68k/m68k.h +++ b/source/m68k/m68k.h @@ -39,9 +39,9 @@ /* ================================ INCLUDES ============================== */ /* ======================================================================== */ +#include #include "macros.h" - /* ======================================================================== */ /* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */ /* ======================================================================== */ @@ -231,30 +231,29 @@ typedef struct { cpu_memory_map memory_map[256]; /* memory mapping */ - cpu_idle_t poll; /* polling detection */ + cpu_idle_t poll; /* polling detection */ - uint cycles; /* current master cycle count */ - uint cycle_end; /* aimed master cycle count for current execution frame */ + uint cycles; /* current master cycle count */ + uint cycle_end; /* aimed master cycle count for current execution frame */ + + uint dar[16]; /* Data and Address Registers */ + uint pc; /* Program Counter */ + uint sp[5]; /* User and Interrupt Stack Pointers */ + uint ir; /* Instruction Register */ + uint t1_flag; /* Trace 1 */ + uint s_flag; /* Supervisor */ + uint x_flag; /* Extend */ + uint n_flag; /* Negative */ + uint not_z_flag; /* Zero, inverted for speedups */ + uint v_flag; /* Overflow */ + uint c_flag; /* Carry */ + uint int_mask; /* I0-I2 */ + uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */ + uint stopped; /* Stopped state */ + + uint pref_addr; /* Last prefetch address */ + uint pref_data; /* Data in the prefetch queue */ - uint dar[16]; /* Data and Address Registers */ - uint pc; /* Program Counter */ - uint sp[5]; /* User and Interrupt Stack Pointers */ - uint ir; /* Instruction Register */ - uint t1_flag; /* Trace 1 */ - uint s_flag; /* Supervisor */ - uint x_flag; /* Extend */ - uint n_flag; /* Negative */ - uint not_z_flag; /* Zero, inverted for speedups */ - uint v_flag; /* Overflow */ - uint c_flag; /* Carry */ - uint int_mask; /* I0-I2 */ - uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */ - uint stopped; /* Stopped state */ -#if M68K_EMULATE_PREFETCH - uint pref_addr; /* Last prefetch address */ - uint pref_data; /* Data in the prefetch queue */ -#endif -#if M68K_EMULATE_ADDRESS_ERROR uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */ uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */ uint aerr_enabled; /* Enables/deisables address error checks at runtime */ @@ -262,27 +261,16 @@ typedef struct uint aerr_address; /* Address error location */ uint aerr_write_mode; /* Address error write mode */ uint aerr_fc; /* Address error FC code */ -#endif -#if M68K_EMULATE_TRACE + uint tracing; /* Tracing enable flag */ -#endif -#if M68K_EMULATE_FC + uint address_space; /* Current FC code */ -#endif /* Callbacks to host */ -#if M68K_EMULATE_INT_ACK == OPT_ON int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */ -#endif -#if M68K_EMULATE_RESET == OPT_ON void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */ -#endif -#if M68K_TAS_HAS_CALLBACK == OPT_ON int (*tas_instr_callback)(void); /* Called when a TAS instruction is encountered, allows / disallows writeback */ -#endif -#if M68K_EMULATE_FC == OPT_ON void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */ -#endif } m68ki_cpu_core; /* CPU cores */ From e78d5a783400966459804f403678aefa8735d52d Mon Sep 17 00:00:00 2001 From: EkeEke Date: Fri, 19 Apr 2013 16:55:15 +0200 Subject: [PATCH 3/5] [Core/VDP] .Minor optimizations to rendering code .Fixed DMA Copy with undocumented code value (Fatal Labyrinth end sequence) --- source/vdp_ctrl.c | 2 +- source/vdp_render.c | 80 ++++++++++++++++++++++----------------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/source/vdp_ctrl.c b/source/vdp_ctrl.c index 675f317..916a94e 100644 --- a/source/vdp_ctrl.c +++ b/source/vdp_ctrl.c @@ -2976,7 +2976,7 @@ static void vdp_dma_68k_io(unsigned int length) static void vdp_dma_copy(unsigned int length) { /* VRAM read/write operation only */ - if ((code & 0x1F) == 0x10) + if ((code & 0x1E) == 0x10) { int name; uint8 data; diff --git a/source/vdp_render.c b/source/vdp_render.c index bbc637b..796b86d 100644 --- a/source/vdp_render.c +++ b/source/vdp_render.c @@ -1521,11 +1521,11 @@ void render_bg_m5(int line, int width) #ifdef LSB_FIRST uint32 shift = (xscroll >> 16) & 0x0F; uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask); - uint32 v_line = (line + ((yscroll >> 16) & 0x3FF)) & pf_row_mask; + uint32 v_line = (line + (yscroll >> 16)) & pf_row_mask; #else uint32 shift = (xscroll & 0x0F); uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); - uint32 v_line = (line + (yscroll & 0x3FF)) & pf_row_mask; + uint32 v_line = (line + yscroll) & pf_row_mask; #endif /* Plane B name table */ @@ -1578,11 +1578,11 @@ void render_bg_m5(int line, int width) #ifdef LSB_FIRST shift = (xscroll & 0x0F); index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask); - v_line = (line + (yscroll & 0x3FF)) & pf_row_mask; + v_line = (line + yscroll) & pf_row_mask; #else shift = (xscroll >> 16) & 0x0F; index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask); - v_line = (line + ((yscroll >> 16) & 0x3FF)) & pf_row_mask; + v_line = (line + (yscroll >> 16)) & pf_row_mask; #endif /* Plane A name table */ @@ -1683,7 +1683,6 @@ void render_bg_m5_vs(int line, int width) if (reg[12] & 1) { yscroll = vs[19] & (vs[19] >> 16); - yscroll &= 0x3FF; } if(shift) @@ -1713,9 +1712,9 @@ void render_bg_m5_vs(int line, int width) { /* Plane B vertical scroll */ #ifdef LSB_FIRST - v_line = (line + ((vs[column] >> 16) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 16)) & pf_row_mask; #else - v_line = (line + (vs[column] & 0x3FF)) & pf_row_mask; + v_line = (line + vs[column]) & pf_row_mask; #endif /* Plane B name table */ @@ -1793,9 +1792,9 @@ void render_bg_m5_vs(int line, int width) { /* Plane A vertical scroll */ #ifdef LSB_FIRST - v_line = (line + (vs[column] & 0x3FF)) & pf_row_mask; + v_line = (line + vs[column]) & pf_row_mask; #else - v_line = (line + ((vs[column] >> 16) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 16)) & pf_row_mask; #endif /* Plane A name table */ @@ -1858,11 +1857,11 @@ void render_bg_m5_im2(int line, int width) #ifdef LSB_FIRST uint32 shift = (xscroll >> 16) & 0x0F; uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask); - uint32 v_line = (line + ((yscroll >> 17) & 0x3FF)) & pf_row_mask; + uint32 v_line = (line + (yscroll >> 17)) & pf_row_mask; #else uint32 shift = (xscroll & 0x0F); uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); - uint32 v_line = (line + ((yscroll >> 1) & 0x3FF)) & pf_row_mask; + uint32 v_line = (line + (yscroll >> 1)) & pf_row_mask; #endif /* Plane B name table */ @@ -1915,11 +1914,11 @@ void render_bg_m5_im2(int line, int width) #ifdef LSB_FIRST shift = (xscroll & 0x0F); index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask); - v_line = (line + ((yscroll >> 1) & 0x3FF)) & pf_row_mask; + v_line = (line + (yscroll >> 1)) & pf_row_mask; #else shift = (xscroll >> 16) & 0x0F; index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask); - v_line = (line + ((yscroll >> 17) & 0x3FF)) & pf_row_mask; + v_line = (line + (yscroll >> 17)) & pf_row_mask; #endif /* Plane A name table */ @@ -2021,7 +2020,6 @@ void render_bg_m5_im2_vs(int line, int width) if (reg[12] & 1) { yscroll = (vs[19] >> 1) & (vs[19] >> 17); - yscroll &= 0x3FF; } if(shift) @@ -2051,9 +2049,9 @@ void render_bg_m5_im2_vs(int line, int width) { /* Plane B vertical scroll */ #ifdef LSB_FIRST - v_line = (line + ((vs[column] >> 17) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 17)) & pf_row_mask; #else - v_line = (line + ((vs[column] >> 1) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 1)) & pf_row_mask; #endif /* Plane B name table */ @@ -2131,9 +2129,9 @@ void render_bg_m5_im2_vs(int line, int width) { /* Plane A vertical scroll */ #ifdef LSB_FIRST - v_line = (line + ((vs[column] >> 1) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 1)) & pf_row_mask; #else - v_line = (line + ((vs[column] >> 17) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 17)) & pf_row_mask; #endif /* Plane A name table */ @@ -2178,6 +2176,7 @@ void render_bg_m5(int line, int width) int column, start, end; uint32 atex, atbuf, *src, *dst; uint32 shift, index, v_line, *nt; + uint8 *lb; /* Scroll Planes common data */ uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)]; @@ -2223,11 +2222,11 @@ void render_bg_m5(int line, int width) #ifdef LSB_FIRST shift = (xscroll & 0x0F); index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask); - v_line = (line + (yscroll & 0x3FF)) & pf_row_mask; + v_line = (line + yscroll) & pf_row_mask; #else shift = (xscroll >> 16) & 0x0F; index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask); - v_line = (line + ((yscroll >> 16) & 0x3FF)) & pf_row_mask; + v_line = (line + (yscroll >> 16)) & pf_row_mask; #endif /* Background line buffer */ @@ -2297,11 +2296,11 @@ void render_bg_m5(int line, int width) #ifdef LSB_FIRST shift = (xscroll >> 16) & 0x0F; index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask); - v_line = (line + ((yscroll >> 16) & 0x3FF)) & pf_row_mask; + v_line = (line + (yscroll >> 16)) & pf_row_mask; #else shift = (xscroll & 0x0F); index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); - v_line = (line + (yscroll & 0x3FF)) & pf_row_mask; + v_line = (line + yscroll) & pf_row_mask; #endif /* Plane B name table */ @@ -2311,7 +2310,7 @@ void render_bg_m5(int line, int width) v_line = (v_line & 7) << 3; /* Background line buffer */ - uint8 *lb = &linebuf[0][0x20]; + lb = &linebuf[0][0x20]; if(shift) { @@ -2334,6 +2333,7 @@ void render_bg_m5_vs(int line, int width) int column, start, end; uint32 atex, atbuf, *src, *dst; uint32 shift, index, v_line, *nt; + uint8 *lb; /* Scroll Planes common data */ uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)]; @@ -2372,7 +2372,6 @@ void render_bg_m5_vs(int line, int width) if (reg[12] & 1) { yscroll = vs[19] & (vs[19] >> 16); - yscroll &= 0x3FF; } /* Number of columns to draw */ @@ -2428,9 +2427,9 @@ void render_bg_m5_vs(int line, int width) { /* Plane A vertical scroll */ #ifdef LSB_FIRST - v_line = (line + (vs[column] & 0x3FF)) & pf_row_mask; + v_line = (line + vs[column]) & pf_row_mask; #else - v_line = (line + ((vs[column] >> 16) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 16)) & pf_row_mask; #endif /* Plane A name table */ @@ -2483,7 +2482,7 @@ void render_bg_m5_vs(int line, int width) #endif /* Background line buffer */ - uint8 *lb = &linebuf[0][0x20]; + lb = &linebuf[0][0x20]; if(shift) { @@ -2507,9 +2506,9 @@ void render_bg_m5_vs(int line, int width) { /* Plane B vertical scroll */ #ifdef LSB_FIRST - v_line = (line + ((vs[column] >> 16) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 16)) & pf_row_mask; #else - v_line = (line + (vs[column] & 0x3FF)) & pf_row_mask; + v_line = (line + vs[column]) & pf_row_mask; #endif /* Plane B name table */ @@ -2528,6 +2527,7 @@ void render_bg_m5_im2(int line, int width) int column, start, end; uint32 atex, atbuf, *src, *dst; uint32 shift, index, v_line, *nt; + uint8 *lb; /* Scroll Planes common data */ int odd = odd_frame; @@ -2574,11 +2574,11 @@ void render_bg_m5_im2(int line, int width) #ifdef LSB_FIRST shift = (xscroll & 0x0F); index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask); - v_line = (line + ((yscroll >> 1) & 0x3FF)) & pf_row_mask; + v_line = (line + (yscroll >> 1)) & pf_row_mask; #else shift = (xscroll >> 16) & 0x0F; index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask); - v_line = (line + ((yscroll >> 17) & 0x3FF)) & pf_row_mask; + v_line = (line + (yscroll >> 17)) & pf_row_mask; #endif /* Background line buffer */ @@ -2648,11 +2648,11 @@ void render_bg_m5_im2(int line, int width) #ifdef LSB_FIRST shift = (xscroll >> 16) & 0x0F; index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask); - v_line = (line + ((yscroll >> 17) & 0x3FF)) & pf_row_mask; + v_line = (line + (yscroll >> 17)) & pf_row_mask; #else shift = (xscroll & 0x0F); index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); - v_line = (line + ((yscroll >> 1) & 0x3FF)) & pf_row_mask; + v_line = (line + (yscroll >> 1)) & pf_row_mask; #endif /* Plane B name table */ @@ -2662,7 +2662,7 @@ void render_bg_m5_im2(int line, int width) v_line = (((v_line & 7) << 1) | odd) << 3; /* Background line buffer */ - uint8 *lb = &linebuf[0][0x20]; + lb = &linebuf[0][0x20]; if(shift) { @@ -2685,6 +2685,7 @@ void render_bg_m5_im2_vs(int line, int width) int column, start, end; uint32 atex, atbuf, *src, *dst; uint32 shift, index, v_line, *nt; + uint8 *lb; /* common data */ int odd = odd_frame; @@ -2725,7 +2726,6 @@ void render_bg_m5_im2_vs(int line, int width) { /* only in 40-cell mode, verified on MD2 */ yscroll = (vs[19] >> 1) & (vs[19] >> 17); - yscroll &= 0x3FF; } /* Number of columns to draw */ @@ -2781,9 +2781,9 @@ void render_bg_m5_im2_vs(int line, int width) { /* Plane A vertical scroll */ #ifdef LSB_FIRST - v_line = (line + ((vs[column] >> 1) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 1)) & pf_row_mask; #else - v_line = (line + ((vs[column] >> 17) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 17)) & pf_row_mask; #endif /* Plane A name table */ @@ -2836,7 +2836,7 @@ void render_bg_m5_im2_vs(int line, int width) #endif /* Background line buffer */ - uint8 *lb = &linebuf[0][0x20]; + lb = &linebuf[0][0x20]; if(shift) { @@ -2860,9 +2860,9 @@ void render_bg_m5_im2_vs(int line, int width) { /* Plane B vertical scroll */ #ifdef LSB_FIRST - v_line = (line + ((vs[column] >> 17) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 17)) & pf_row_mask; #else - v_line = (line + ((vs[column] >> 1) & 0x3FF)) & pf_row_mask; + v_line = (line + (vs[column] >> 1)) & pf_row_mask; #endif /* Plane B name table */ From c9fb127730fb19e0c1b084a94f6d1e558b28321e Mon Sep 17 00:00:00 2001 From: EkeEke Date: Fri, 19 Apr 2013 16:55:34 +0200 Subject: [PATCH 4/5] fixed 68k interrupt behavior (prevents interrupts from being executed multiple time when 68k is halted) --- source/m68k/m68kcpu.c | 25 ++++++++++++++----------- source/m68k/s68kcpu.c | 22 ++++++++++++++-------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/source/m68k/m68kcpu.c b/source/m68k/m68kcpu.c index dd709b1..7c042e1 100644 --- a/source/m68k/m68kcpu.c +++ b/source/m68k/m68kcpu.c @@ -205,9 +205,6 @@ void m68k_update_irq(unsigned int mask) #ifdef LOGVDP error("[%d(%d)][%d(%d)] IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC)); #endif - - /* Check interrupt mask to process IRQ */ - m68ki_check_interrupts(); } void m68k_set_irq(unsigned int int_level) @@ -218,9 +215,6 @@ void m68k_set_irq(unsigned int int_level) #ifdef LOGVDP error("[%d(%d)][%d(%d)] IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC)); #endif - - /* Check interrupt mask to process IRQ */ - m68ki_check_interrupts(); } /* IRQ latency (Fatal Rewind, Sesame's Street Counting Cafe)*/ @@ -261,6 +255,15 @@ void m68k_set_irq_delay(unsigned int int_level) void m68k_run(unsigned int cycles) { + /* Make sure CPU is not already ahead */ + if (m68k.cycles >= cycles) + { + return; + } + + /* Check interrupt mask to process IRQ if needed */ + m68ki_check_interrupts(); + /* Make sure we're not stopped */ if (CPU_STOPPED) { @@ -268,12 +271,12 @@ void m68k_run(unsigned int cycles) return; } - /* Return point for when we have an address error (TODO: use goto) */ - m68ki_set_address_error_trap() /* auto-disable (see m68kcpu.h) */ - /* Save end cycles count for when CPU is stopped */ m68k.cycle_end = cycles; + /* Return point for when we have an address error (TODO: use goto) */ + m68ki_set_address_error_trap() /* auto-disable (see m68kcpu.h) */ + #ifdef LOGVDP error("[%d][%d] m68k run to %d cycles (%x)\n", v_counter, m68k.cycles, cycles, m68k.pc); #endif @@ -290,8 +293,8 @@ void m68k_run(unsigned int cycles) REG_IR = m68ki_read_imm_16(); /* Execute instruction */ - m68ki_instruction_jump_table[REG_IR](); /* TODO: use labels table with goto */ - USE_CYCLES(CYC_INSTRUCTION[REG_IR]); /* TODO: move into instruction handlers */ + m68ki_instruction_jump_table[REG_IR](); + USE_CYCLES(CYC_INSTRUCTION[REG_IR]); /* Trace m68k_exception, if necessary */ m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ diff --git a/source/m68k/s68kcpu.c b/source/m68k/s68kcpu.c index 4fe7312..40ff145 100644 --- a/source/m68k/s68kcpu.c +++ b/source/m68k/s68kcpu.c @@ -215,13 +215,19 @@ void s68k_update_irq(unsigned int mask) #ifdef LOG_SCD error("[%d][%d] IRQ Level = %d(0x%02x) (%x)\n", v_counter, s68k.cycles, CPU_INT_LEVEL>>8,FLAG_INT_MASK,s68k.pc); #endif - - /* Check interrupt mask to process IRQ */ - m68ki_check_interrupts(); } void s68k_run(unsigned int cycles) { + /* Make sure CPU is not already ahead */ + if (s68k.cycles >= cycles) + { + return; + } + + /* Check interrupt mask to process IRQ if needed */ + m68ki_check_interrupts(); + /* Make sure we're not stopped */ if (CPU_STOPPED) { @@ -229,11 +235,12 @@ void s68k_run(unsigned int cycles) return; } + /* Save end cycles count for when CPU is stopped */ + s68k.cycle_end = cycles; + /* Return point for when we have an address error (TODO: use goto) */ m68ki_set_address_error_trap() /* auto-disable (see m68kcpu.h) */ - /* Save end cycles count for when CPU is stopped */ - s68k.cycle_end = cycles; #ifdef LOG_SCD error("[%d][%d] s68k run to %d cycles (%x), irq mask = %x (%x)\n", v_counter, s68k.cycles, cycles, s68k.pc,FLAG_INT_MASK, CPU_INT_LEVEL); #endif @@ -249,10 +256,9 @@ void s68k_run(unsigned int cycles) /* Decode next instruction */ REG_IR = m68ki_read_imm_16(); - /* Execute instruction */ - m68ki_instruction_jump_table[REG_IR](); /* TODO: use labels table with goto */ - USE_CYCLES(CYC_INSTRUCTION[REG_IR]); /* TODO: move into instruction handlers */ + m68ki_instruction_jump_table[REG_IR](); + USE_CYCLES(CYC_INSTRUCTION[REG_IR]); /* Trace m68k_exception, if necessary */ m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ From 325f6dd5a79c2535320e9295ebeecc43f9269880 Mon Sep 17 00:00:00 2001 From: EkeEke Date: Fri, 19 Apr 2013 16:55:52 +0200 Subject: [PATCH 5/5] [Core/CD] .added build-in TOC support for a few games that hang if no audio tracks are found or used .modified CD access/seek time emulation .improved CPU polling detection .improved SUB & MAIN-CPU synchronization (fixes Dracula Unleashed when using Model 2 US BIOS) .added missing reinitialization of MAIN-CPU PRG-RAM bank on reset --- source/cd_hw/cdd.c | 93 +++++++++++++++++++++++++++++++++++++--------- source/cd_hw/scd.c | 20 +++++++--- source/mem68k.c | 20 +++++++++- 3 files changed, 109 insertions(+), 24 deletions(-) diff --git a/source/cd_hw/cdd.c b/source/cd_hw/cdd.c index ab48442..e61b9f3 100644 --- a/source/cd_hw/cdd.c +++ b/source/cd_hw/cdd.c @@ -90,6 +90,26 @@ static const uint32 toc_shadow[15] = 11637, 2547, 2521, 3856, 900 }; +static const uint32 toc_dungeon[13] = +{ + 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100, + 3325, 6825, 25275 +}; + +static const uint32 toc_ffight[26] = +{ + 11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764, + 9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024, + 14562, 10320, 8627, 3795, 3047 +}; + +static const uint32 toc_ffightj[29] = +{ + 11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763, + 9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026, + 14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052 +}; + /* supported WAVE file header (16-bit stereo samples @44.1kHz) */ static const unsigned char waveHeader[32] = { @@ -641,6 +661,45 @@ int cdd_load(char *filename, char *header) } while (cdd.toc.last < 15); } + else if (strstr(header + 0x180,"T-143025") != NULL) + { + /* Dungeon Explorer */ + cdd.toc.last = cdd.toc.end = 0; + do + { + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; + cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last]; + cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; + cdd.toc.last++; + } + while (cdd.toc.last < 13); + } + else if (strstr(header + 0x180,"MK-4410") != NULL) + { + /* Final Fight CD (USA, Europe) */ + cdd.toc.last = cdd.toc.end = 0; + do + { + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; + cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last]; + cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; + cdd.toc.last++; + } + while (cdd.toc.last < 26); + } + else if (strstr(header + 0x180,"G-6013") != NULL) + { + /* Final Fight CD (Japan) */ + cdd.toc.last = cdd.toc.end = 0; + do + { + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; + cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last]; + cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; + cdd.toc.last++; + } + while (cdd.toc.last < 29); + } else { /* default TOC (99 tracks & 2s per audio tracks) */ @@ -1081,11 +1140,24 @@ void cdd_process(void) if (!cdd.latency) { /* Fixes a few games hanging during intro because they expect data to be read with some delay */ - /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */ /* Radical Rex needs at least one interrupt delay */ - /* Jeopardy needs at least 9 interrupts delay */ - /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay */ - cdd.latency = 13; + /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */ + /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 here is OK) */ + /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 7 interrupts delay (+ seek time) seems OK */ + cdd.latency = 7; + } + + /* CD drive seek time */ + /* Some delay is especially needed when playing audio tracks located at the end of the disc (ex: Sonic CD intro) */ + /* max. seek time = 1.5s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc */ + /* Note: this is only a rough approximation, on real hardware, drive seek time is much likely not linear */ + if (lba < cdd.lba) + { + cdd.latency += (((cdd.lba - lba) * 120) / 270000); + } + else + { + cdd.latency += (((lba - cdd.lba) * 120) / 270000); } /* update current track index */ @@ -1110,19 +1182,6 @@ void cdd_process(void) } else if (cdd.toc.tracks[index].fd) { - /* CD drive seek time */ - /* Some delay is also needed when playing AUDIO tracks located at the end of the disc (ex: Sonic CD intro) */ - /* max. seek time = 1.5s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc */ - /* Note: this is only a rough approximation, on real hardware, drive seek time is much likely not linear */ - if (lba < cdd.lba) - { - cdd.latency += (((cdd.lba - lba) * 120) / 270000); - } - else - { - cdd.latency += (((lba - cdd.lba) * 120) / 270000); - } - /* seek AUDIO track */ if (lba < cdd.toc.tracks[index].start) { diff --git a/source/cd_hw/scd.c b/source/cd_hw/scd.c index 91d6085..47ed230 100644 --- a/source/cd_hw/scd.c +++ b/source/cd_hw/scd.c @@ -212,7 +212,7 @@ static void s68k_poll_detect(reg) } /* restart SUB-CPU polling detection */ - s68k.poll.cycle = s68k.cycles + 320; + s68k.poll.cycle = s68k.cycles + 392; s68k.poll.pc = s68k.pc; } @@ -412,7 +412,7 @@ static unsigned int scd_read_word(unsigned int address) /* relative MAIN-CPU cycle counter */ unsigned int cycles = (s68k.cycles * MCYCLES_PER_LINE) / SCYCLES_PER_LINE; - /* sync MAIN-CPU with SUB-CPU */ + /* sync MAIN-CPU with SUB-CPU (Mighty Morphin Power Rangers) */ if (!m68k.stopped && (m68k.cycles < cycles)) { m68k_run(cycles); @@ -1062,7 +1062,7 @@ void scd_init(void) { if (i & 2) { - /* PRG-RAM (first 128KB bank, mirrored) */ + /* $020000-$03FFFF (resp. $420000-$43FFFF): PRG-RAM (first 128KB bank, mirrored each 256KB) */ m68k.memory_map[i].base = scd.prg_ram + ((i & 1) << 16); m68k.memory_map[i].read8 = NULL; m68k.memory_map[i].read16 = NULL; @@ -1074,7 +1074,8 @@ void scd_init(void) } else { - /* internal ROM (128KB mirrored) (Flux expects it to be mapped at $440000-$45FFFF) */ + /* $000000-$01FFFF (resp. $400000-$41FFFF): internal ROM (128KB, mirrored each 256KB) */ + /* NB: Flux expects it to be mapped at $440000-$45FFFF */ m68k.memory_map[i].base = scd.bootrom + ((i & 1) << 16); m68k.memory_map[i].read8 = NULL; m68k.memory_map[i].read16 = NULL; @@ -1116,7 +1117,6 @@ void scd_init(void) /* $080000-$0BFFFF: Word-RAM in 2M mode (256KB)*/ for (i=0x08; i<0x0c; i++) { - /* allow Word-RAM access from both CPU in 2M mode (fixes sync issues in Mortal Kombat) */ s68k.memory_map[i].base = scd.word_ram_2M + ((i & 3) << 16); s68k.memory_map[i].read8 = NULL; s68k.memory_map[i].read16 = NULL; @@ -1167,6 +1167,8 @@ void scd_reset(int hard) /* TODO: figure what exactly is resetted when RESET bit is cleared by SUB-CPU */ if (hard) { + int i; + /* Clear all ASIC registers by default */ memset(scd.regs, 0, sizeof(scd.regs)); @@ -1183,6 +1185,14 @@ void scd_reset(int hard) /* 2M mode */ word_ram_switch(0); + + /* reset PRG-RAM banking on MAIN-CPU side */ + for (i=scd.cartridge.boot+0x02; i>16)&0xff].base, (address) & 0xffff); } @@ -238,6 +238,13 @@ static void m68k_poll_detect(reg) #endif m68k.cycles = m68k.cycle_end; m68k.stopped = 1 << reg; + + /* return to current instruction */ + do + { + m68k.pc -= 2; + } + while (m68k.ir != *(uint16 *)(m68k.memory_map[(m68k.pc>>16)&0xff].base + (m68k.pc & 0xffff))); } return; } @@ -249,7 +256,7 @@ static void m68k_poll_detect(reg) } /* restart MAIN-CPU polling detection */ - m68k.poll.cycle = m68k.cycles + 280; + m68k.poll.cycle = m68k.cycles + 840; m68k.poll.pc = m68k.pc; } @@ -335,6 +342,15 @@ unsigned int ctrl_io_read_byte(unsigned int address) /* SUB-CPU communication flags */ if (index == 0x0f) { + /* relative SUB-CPU cycle counter */ + unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE; + + /* sync SUB-CPU with MAIN-CPU (Dracula Unleashed w/ Sega CD Model 2 OS ROM) */ + if (!s68k.stopped && (s68k.cycles < cycles)) + { + s68k_run(cycles); + } + m68k_poll_detect(0x0f); return scd.regs[0x0f>>1].byte.l; }