m68000: implement TAS callback (currently only used by megadrive) in a more sensible and versatile way [Alex Jackson]

This commit is contained in:
Alex W. Jackson 2014-04-22 17:09:12 +00:00
parent 94fc4f582a
commit 69e99a89f2
5 changed files with 23 additions and 23 deletions

View File

@ -171,7 +171,7 @@ public:
void set_reset_callback(write_line_delegate callback);
void set_cmpild_callback(write32_delegate callback);
void set_rte_callback(write_line_delegate callback);
void set_tas_callback(read_line_delegate callback);
void set_tas_write_callback(write8_delegate callback);
UINT16 get_fc();
void set_encrypted_opcode_range(offs_t start, offs_t end);
void set_hmmu_enable(int enable);
@ -252,16 +252,17 @@ public:
const UINT8* cyc_exception;
/* Callbacks to host */
device_irq_acknowledge_callback int_ack_callback; /* Interrupt Acknowledge */
write32_delegate bkpt_ack_callback; /* Breakpoint Acknowledge */
write_line_delegate reset_instr_callback; /* Called when a RESET instruction is encountered */
write32_delegate cmpild_instr_callback; /* Called when a CMPI.L #v, Dn instruction is encountered */
write_line_delegate rte_instr_callback; /* Called when a RTE instruction is encountered */
read_line_delegate tas_instr_callback; /* Called when a TAS instruction is encountered, allows / disallows writeback */
device_irq_acknowledge_callback int_ack_callback; /* Interrupt Acknowledge */
write32_delegate bkpt_ack_callback; /* Breakpoint Acknowledge */
write_line_delegate reset_instr_callback; /* Called when a RESET instruction is encountered */
write32_delegate cmpild_instr_callback; /* Called when a CMPI.L #v, Dn instruction is encountered */
write_line_delegate rte_instr_callback; /* Called when a RTE instruction is encountered */
write8_delegate tas_write_callback; /* Called instead of normal write8 by the TAS instruction,
allowing writeback to be disabled globally or selectively
or other side effects to be implemented */
address_space *program;
/* Redirect memory calls */
typedef delegate<UINT8 (offs_t)> m68k_read8_delegate;

View File

@ -10015,21 +10015,20 @@ M68KMAKE_OP(tas, 8, ., .)
{
UINT32 ea = M68KMAKE_GET_EA_AY_8;
UINT32 dst = m68ki_read_8((mc68kcpu), ea);
UINT32 allow_writeback = TRUE;
(mc68kcpu)->not_z_flag = dst;
(mc68kcpu)->n_flag = NFLAG_8(dst);
(mc68kcpu)->v_flag = VFLAG_CLEAR;
(mc68kcpu)->c_flag = CFLAG_CLEAR;
/* The Genesis/Megadrive games Gargoyles and Ex-Mutants need the TAS writeback
disabled in order to function properly. Some Amiga software may also rely
on this, but only when accessing specific addresses so additional functionality
will be needed. */
if (!(mc68kcpu)->tas_instr_callback.isnull())
allow_writeback = ((mc68kcpu)->tas_instr_callback)();
if (allow_writeback)
/* On the 68000 and 68010, the TAS instruction uses a unique bus cycle that may have
side effects (e.g. delaying DMA) or may fail to write back at all depending on the
bus implementation.
In particular, the Genesis/Megadrive games Gargoyles and Ex-Mutants need the TAS
to fail to write back in order to function properly. */
if (CPU_TYPE_IS_010_LESS((mc68kcpu)->cpu_type) && !(mc68kcpu)->tas_write_callback.isnull())
((mc68kcpu)->tas_write_callback)(*(mc68kcpu)->program, ea, dst | 0x80, 0xff);
else
m68ki_write_8((mc68kcpu), ea, dst | 0x80);
}

View File

@ -1696,9 +1696,9 @@ void m68000_base_device::set_rte_callback(write_line_delegate callback)
rte_instr_callback = callback;
}
void m68000_base_device::set_tas_callback(read_line_delegate callback)
void m68000_base_device::set_tas_write_callback(write8_delegate callback)
{
tas_instr_callback = callback;
tas_write_callback = callback;
}
UINT16 m68000_base_device::get_fc()

View File

@ -123,7 +123,7 @@ public:
UINT32 screen_update_megadriv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void screen_eof_megadriv(screen_device &screen, bool state);
READ_LINE_MEMBER(megadriv_tas_callback);
DECLARE_WRITE8_MEMBER(megadriv_tas_callback);
};

View File

@ -1017,9 +1017,9 @@ MACHINE_CONFIG_FRAGMENT( md_pal )
MACHINE_CONFIG_END
READ_LINE_MEMBER(md_base_state::megadriv_tas_callback)
WRITE8_MEMBER(md_base_state::megadriv_tas_callback)
{
return 0; // writeback not allowed
return; // writeback not allowed
}
void md_base_state::megadriv_init_common()
@ -1034,7 +1034,7 @@ void md_base_state::megadriv_init_common()
m_maincpu->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(md_base_state::genesis_int_callback),this));
m_maincpu->set_tas_callback(read_line_delegate(FUNC(md_base_state::megadriv_tas_callback),this));
m_maincpu->set_tas_write_callback(write8_delegate(FUNC(md_base_state::megadriv_tas_callback),this));
m_megadrive_io_read_data_port_ptr = read8_delegate(FUNC(md_base_state::megadrive_io_read_data_port_3button),this);
m_megadrive_io_write_data_port_ptr = write16_delegate(FUNC(md_base_state::megadrive_io_write_data_port_3button),this);