From 170b6ae5c2d63e941756f1a5fa6929ece92c0cfa Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Wed, 22 Aug 2012 20:16:55 +0000 Subject: [PATCH] (SNES) Rewritten cycle steal code from scratch and nailed it directly in the G65816 CPU core [Angelo Salese, byuu] --- src/emu/cpu/g65816/g65816.c | 19 +++++ src/emu/cpu/g65816/g65816cm.h | 3 + src/emu/cpu/g65816/g65816op.h | 5 ++ src/mame/machine/snes.c | 155 +--------------------------------- 4 files changed, 31 insertions(+), 151 deletions(-) diff --git a/src/emu/cpu/g65816/g65816.c b/src/emu/cpu/g65816/g65816.c index 1f71db8c116..d08f28e545a 100644 --- a/src/emu/cpu/g65816/g65816.c +++ b/src/emu/cpu/g65816/g65816.c @@ -143,6 +143,9 @@ extern void g65816i_set_reg_E(g65816i_cpu_struct *cpustate, int regnum, uint val extern void g65816i_set_line_E(g65816i_cpu_struct *cpustate, int line, int state); extern int g65816i_execute_E(g65816i_cpu_struct *cpustate, int cycles); +extern int bus_5A22_cycle_burst(g65816i_cpu_struct *cpustate, uint addr); + + void (*const *const g65816i_opcodes[5])(g65816i_cpu_struct *cpustate) = { g65816i_opcodes_M0X0, @@ -525,6 +528,22 @@ CPU_GET_INFO( g65816 ) SNES specific, used to handle master cycles */ +int bus_5A22_cycle_burst(g65816i_cpu_struct *cpustate, uint addr) +{ + if(cpustate->cpu_type == CPU_TYPE_G65816) + return 0; + + if(addr & 0x408000) { + if(addr & 0x800000) return (1) ? 6 : 8; // TODO: fastROM setting + return 8; + } + if((addr + 0x6000) & 0x4000) return 8; + if((addr - 0x4000) & 0x7e00) return 6; + + return 12; +} + + static CPU_INIT( 5a22 ) { g65816i_cpu_struct *cpustate = get_safe_token(device); diff --git a/src/emu/cpu/g65816/g65816cm.h b/src/emu/cpu/g65816/g65816cm.h index c9e371046c2..46035817e04 100644 --- a/src/emu/cpu/g65816/g65816cm.h +++ b/src/emu/cpu/g65816/g65816cm.h @@ -103,6 +103,7 @@ struct _g65816i_cpu_struct void (*set_reg)(g65816i_cpu_struct *cpustate, int regnum, uint val); void (*set_line)(g65816i_cpu_struct *cpustate, int line, int state); int (*execute)(g65816i_cpu_struct *cpustate, int cycles); + int bus_5A22_cycle_burst(g65816i_cpu_struct *cpustate, uint addr); uint source; uint destination; int ICount; @@ -114,6 +115,7 @@ extern uint (*const g65816i_get_reg[])(g65816i_cpu_struct *cpustate, int regnum) extern void (*const g65816i_set_reg[])(g65816i_cpu_struct *cpustate, int regnum, uint val); extern void (*const g65816i_set_line[])(g65816i_cpu_struct *cpustate, int line, int state); extern int (*const g65816i_execute[])(g65816i_cpu_struct *cpustate, int cycles); +extern int bus_5A22_cycle_burst(g65816i_cpu_struct *cpustate, uint addr); #define REGISTER_A cpustate->a /* Accumulator */ #define REGISTER_B cpustate->b /* Accumulator hi byte */ @@ -244,6 +246,7 @@ INLINE void g65816i_set_execution_mode(g65816i_cpu_struct *cpustate, uint mode) #define CLK_W_SIY 5 #define CLK(A) CLOCKS -= (cpustate->cpu_type == CPU_TYPE_G65816 ? A : A*6) +#define CLK_BUS(A) CLOCKS -= A #define USE_ALL_CLKS() CLOCKS = 0 diff --git a/src/emu/cpu/g65816/g65816op.h b/src/emu/cpu/g65816/g65816op.h index 9495214205f..fb5c70ab238 100644 --- a/src/emu/cpu/g65816/g65816op.h +++ b/src/emu/cpu/g65816/g65816op.h @@ -59,12 +59,14 @@ INLINE uint g65816i_read_8_normal(g65816i_cpu_struct *cpustate, uint address) { address = ADDRESS_65816(address); + CLOCKS -= (bus_5A22_cycle_burst(cpustate,address)); return g65816_read_8(address); } INLINE uint g65816i_read_8_immediate(g65816i_cpu_struct *cpustate, uint address) { address = ADDRESS_65816(address); + CLOCKS -= (bus_5A22_cycle_burst(cpustate,address)); return g65816_read_8_immediate(address); } @@ -76,6 +78,7 @@ INLINE uint g65816i_read_8_direct(g65816i_cpu_struct *cpustate, uint address) #else address = ADDRESS_65816(address); #endif + CLOCKS -= (bus_5A22_cycle_burst(cpustate,address)); return g65816_read_8(address); } @@ -90,6 +93,7 @@ INLINE uint g65816i_read_8_vector(g65816i_cpu_struct *cpustate, uint address) INLINE void g65816i_write_8_normal(g65816i_cpu_struct *cpustate, uint address, uint value) { address = ADDRESS_65816(address); + CLOCKS -= (bus_5A22_cycle_burst(cpustate,address)); g65816_write_8(address, MAKE_UINT_8(value)); } @@ -101,6 +105,7 @@ INLINE void g65816i_write_8_direct(g65816i_cpu_struct *cpustate, uint address, u #else address = ADDRESS_65816(address); #endif + CLOCKS -= (bus_5A22_cycle_burst(cpustate,address)); g65816_write_8(address, MAKE_UINT_8(value)); } diff --git a/src/mame/machine/snes.c b/src/mame/machine/snes.c index 586a5caeb7c..6541f511386 100644 --- a/src/mame/machine/snes.c +++ b/src/mame/machine/snes.c @@ -13,6 +13,10 @@ Thanks to Anomie for invaluable technical information. Thanks to byuu for invaluable technical information. + TODO: + - DMA takes some Master CPU clock cycles that aren't taken into account + for now. + ***************************************************************************/ #define __MACHINE_SNES_C @@ -55,8 +59,6 @@ struct snes_cart_info snes_cart; #include "machine/snes7110.c" #include "machine/snesbsx.c" -#define USE_CYCLE_STEAL 1 - // ST-010 and ST-011 RAM interface UINT8 st010_read_ram(snes_state *state, UINT16 addr) { @@ -892,70 +894,6 @@ address | | | | | | | */ -#if USE_CYCLE_STEAL -/*FIXME: missing work RAM access steal / we need to do this less "aggressive" otherwise we lose too much CPU horsepower, why? */ -static int snes_bank_0x00_0x3f_cycles(running_machine &machine,UINT32 offset) -{ -/* - $00-$3F | $0000-$1FFF | Slow | Address Bus A + /WRAM (mirror $7E:0000-$1FFF) - | $2000-$20FF | Fast | Address Bus A - | $2100-$21FF | Fast | Address Bus B - | $2200-$3FFF | Fast | Address Bus A - | $4000-$41FF | XSlow | Internal CPU registers (see Note 1 below) - | $4200-$43FF | Fast | Internal CPU registers (see Note 1 below) - | $4400-$5FFF | Fast | Address Bus A - | $6000-$7FFF | Slow | Address Bus A - | $8000-$FFFF | Slow | Address Bus A + /CART - */ - - if(((offset & 0xff00) == 0x4000) || ((offset & 0xff00) == 0x4100)) - return 0; //TODO: 12 - if(((offset & 0xff00) == 0x4200) || ((offset & 0xff00) == 0x4300)) - return 0; //TODO: 6 - - if((offset & 0xff00) <= 0x1f00) - return 0; //TODO: 8 - - if((offset & 0xff00) >= 0x6000) - return 8; - - return 0; //TODO: 6 -} - -static int snes_bank_0x80_0xbf_cycles(running_machine &machine,UINT32 offset) -{ -/* - $80-$BF | $0000-$1FFF | Slow | Address Bus A + /WRAM (mirror $7E:0000-$1FFF) - | $2000-$20FF | Fast | Address Bus A - | $2100-$21FF | Fast | Address Bus B - | $2200-$3FFF | Fast | Address Bus A - | $4000-$41FF | XSlow | Internal CPU registers (see Note 1 below) - | $4200-$43FF | Fast | Internal CPU registers (see Note 1 below) - | $4400-$5FFF | Fast | Address Bus A - | $6000-$7FFF | Slow | Address Bus A - | $8000-$FFFF | Note2 | Address Bus A + /CART -*/ - - - if(((offset & 0xff00) == 0x4000) || ((offset & 0xff00) == 0x4100)) - return 0; //TODO: 12 - - if(((offset & 0xff00) == 0x4200) || ((offset & 0xff00) == 0x4300)) - return 0; //TODO: 6 - - if((offset & 0xff00) <= 0x1f00) - return 0; //TODO: 8 - - if(((offset & 0xff00) >= 0x6000) && ((offset & 0xff00) <= 0x7f00)) - return 0; //TODO: 8 - - if(((offset & 0xff00) >= 0x8000) && ((offset & 0xff00) <= 0xff00)) - return (snes_ram[MEMSEL] & 1) ? 6 : 8; - - return 0; //TODO: 6 -} -#endif - /* 0x000000 - 0x2fffff */ READ8_HANDLER( snes_r_bank1 ) { @@ -1007,11 +945,6 @@ READ8_HANDLER( snes_r_bank1 ) else value = snes_ram[offset]; - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset)); - #endif - return value; } @@ -1074,11 +1007,6 @@ READ8_HANDLER( snes_r_bank2 ) else value = snes_ram[0x300000 + offset]; - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset)); - #endif - return value; } @@ -1117,11 +1045,6 @@ READ8_HANDLER( snes_r_bank3 ) else /* Mode 21 & 25 + SuperFX games */ value = snes_ram[0x400000 + offset]; - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -8); - #endif - return value; } @@ -1166,11 +1089,6 @@ READ8_HANDLER( snes_r_bank4 ) else if (state->m_cart[0].mode & 0x0a) /* Mode 21 & 25 */ value = snes_ram[0x600000 + offset]; - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -8); - #endif - return value; } @@ -1204,11 +1122,6 @@ READ8_HANDLER( snes_r_bank5 ) else value = snes_ram[0x700000 + offset]; - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -8); - #endif - return value; } @@ -1254,11 +1167,6 @@ READ8_HANDLER( snes_r_bank6 ) else value = snes_ram[0x800000 + offset]; - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -snes_bank_0x80_0xbf_cycles(space->machine(), offset)); - #endif - return value; } @@ -1318,11 +1226,6 @@ READ8_HANDLER( snes_r_bank7 ) else /* Mode 21 & 25 + SuperFX Games */ value = snes_ram[0xc00000 + offset]; - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -((snes_ram[MEMSEL] & 1) ? 6 : 8)); - #endif - return value; } @@ -1376,11 +1279,6 @@ WRITE8_HANDLER( snes_w_bank1 ) dsp_set_sr(data); else logerror( "(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset ); - - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset)); - #endif } /* 0x300000 - 0x3fffff */ @@ -1438,11 +1336,6 @@ WRITE8_HANDLER( snes_w_bank2 ) dsp_set_sr(data); else logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x300000); - - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset)); - #endif } /* 0x600000 - 0x6fffff */ @@ -1479,11 +1372,6 @@ WRITE8_HANDLER( snes_w_bank4 ) } else if (state->m_cart[0].mode & 0x0a) logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x600000); - - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -8); - #endif } /* 0x700000 - 0x7dffff */ @@ -1506,11 +1394,6 @@ WRITE8_HANDLER( snes_w_bank5 ) } else if (state->m_cart[0].mode & 0x0a) logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x700000); - - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -8); - #endif } @@ -1562,11 +1445,6 @@ WRITE8_HANDLER( snes_w_bank6 ) dsp_set_sr(data); else logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x800000); - - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -snes_bank_0x80_0xbf_cycles(space->machine(), offset)); - #endif } @@ -1617,11 +1495,6 @@ WRITE8_HANDLER( snes_w_bank7 ) } else if (state->m_cart[0].mode & 0x0a) logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0xc00000); - - #if USE_CYCLE_STEAL - if(!space->debugger_access()) - device_adjust_icount(&space->device(), -((snes_ram[MEMSEL] & 1) ? 6 : 8)); - #endif } @@ -2143,12 +2016,6 @@ INLINE void snes_dma_transfer( address_space *space, UINT8 dma, UINT32 abus, UIN { snes_state *state = space->machine().driver_data(); - #if USE_CYCLE_STEAL - /* every byte transfer takes 8 master cycles */ -// FIXME: this cycle steal makes Final Fantasy VI (III in US) very glitchy! -// device_adjust_icount(&space->device(),-8); - #endif - if (state->m_dma_channel[dma].dmap & 0x80) /* PPU->CPU */ { if (bbus == 0x2180 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) @@ -2355,11 +2222,6 @@ static void snes_dma( address_space *space, UINT8 channels ) /* FIXME: we also need to round to the nearest 8 master cycles */ - #if USE_CYCLE_STEAL - /* overhead steals 8 master cycles, correct? */ - device_adjust_icount(&space->device(),-8); - #endif - /* Assume priority of the 8 DMA channels is 0-7 */ for (i = 0; i < 8; i++) { @@ -2468,18 +2330,9 @@ static void snes_dma( address_space *space, UINT8 channels ) /* We're done, so write the new abus back to the registers */ state->m_dma_channel[i].src_addr = abus; state->m_dma_channel[i].trans_size = 0; - - #if USE_CYCLE_STEAL - /* active channel takes 8 master cycles */ - device_adjust_icount(&space->device(),-8); - #endif } } - /* finally, take yet another 8 master cycles for the aforementioned overhead */ - #if USE_CYCLE_STEAL - device_adjust_icount(&space->device(),-8); - #endif } READ8_HANDLER( superfx_r_bank1 )