bus/snes/sa1.cpp: Flesh out some SA1 features, Fix SNES timing, interrupt (#8673)

This commit is contained in:
cam900 2021-11-20 09:35:56 +09:00 committed by GitHub
parent 6229ca9544
commit db40a44d00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 774 additions and 545 deletions

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@
#include "snes_slot.h"
#include "cpu/g65816/g65816.h"
#include <algorithm>
// ======================> sns_sa1_device
@ -16,108 +17,169 @@ class sns_sa1_device : public device_t,
{
public:
// construction/destruction
sns_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
sns_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
static const device_timer_id TIMER_SA1 = 0; // SA-1 internal timer (18 bit linear timer or HV timer)
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
// reading and writing
virtual uint8_t read_l(offs_t offset) override;
virtual uint8_t read_h(offs_t offset) override;
virtual void write_l(offs_t offset, uint8_t data) override;
virtual void write_h(offs_t offset, uint8_t data) override;
virtual u8 read_l(offs_t offset) override;
virtual u8 read_h(offs_t offset) override;
virtual void write_l(offs_t offset, u8 data) override;
virtual void write_h(offs_t offset, u8 data) override;
// additional reading and writing
virtual uint8_t chip_read(offs_t offset) override;
virtual void chip_write(offs_t offset, uint8_t data) override;
virtual u8 chip_read(offs_t offset) override;
virtual void chip_write(offs_t offset, u8 data) override;
private:
template<bool SA1Read> uint8_t var_length_read(uint32_t offset);
u8 var_length_read(offs_t offset);
void dma_transfer();
void dma_cctype1_transfer();
void dma_cctype2_transfer();
template<bool SA1Read> uint8_t read_regs(uint32_t offset);
uint8_t read_iram(uint32_t offset);
template<bool SA1Read> uint8_t read_bwram(uint32_t offset, bool bitmap = false);
uint8_t read_cconv1_dma(uint32_t offset);
void write_regs(uint32_t offset, uint8_t data);
void write_iram(uint32_t offset, uint8_t data);
void write_bwram(uint32_t offset, uint8_t data, bool bitmap = false);
u8 host_r(offs_t offset);
void host_w(offs_t offset, u8 data);
void shared_regs_w(offs_t offset, u8 data);
u8 read_regs(offs_t offset);
u8 read_iram(offs_t offset);
template<bool SA1Read> u8 read_bwram(offs_t offset, bool bitmap = false);
u8 read_cconv1_dma(offs_t offset);
void write_regs(offs_t offset, u8 data);
void write_iram(offs_t offset, u8 data);
void write_bwram(offs_t offset, u8 data, bool bitmap = false);
void recalc_irqs();
required_device<g65816_device> m_sa1;
u8 rom_r(offs_t offset);
u8 sa1_rom_r(offs_t offset);
uint8_t m_internal_ram[0x800];
u8 sa1_iram_r(offs_t offset);
void sa1_iram_w(offs_t offset, u8 data);
u8 sa1_bwram_r(offs_t offset, bool bitmap = false);
void sa1_bwram_w(offs_t offset, u8 data, bool bitmap = false);
required_device<g65816_device> m_sa1;
emu_timer *m_sa1_timer;
std::unique_ptr<u8[]> m_internal_ram;
// bus conflict related:
// ROM: [00-3f][8000-ffff], [80-bf][8000-ffff], [c0-ff][0000-ffff]
// IRAM: [00-3f][3000-38ff], [80-bf][3000-38ff]
// BWRAM: [00-3f][6000-7fff], [40-4f][0000-ffff], [80-bf][6000-7fff]
inline const bool bus_conflict_rom() { return ((address_r() & 0x408000) == 0x008000) || ((address_r() & 0xc00000) == 0xc00000); }
inline const bool bus_conflict_iram() { return ((address_r() & 0x40f800) == 0x003000); }
inline const bool bus_conflict_bwram() { return ((address_r() & 0x40e000) == 0x006000) || ((address_r() & 0xf00000) == 0x400000); }
// register related
// $2200
uint8_t m_sa1_ctrl;
u8 m_sa1_ctrl;
bool m_sa1_reset_flag;
// SA-1 CPU Control (CCNT)
inline const bool CCNT_SA1_CPU_IRQ() { return BIT(m_sa1_ctrl, 7); } // SA-1 CPU IRQ (from SNES CPU)
inline const bool CCNT_SA1_CPU_RDYB() { return BIT(m_sa1_ctrl, 6); } // SA-1 CPU ready
inline const bool CCNT_SA1_CPU_RESB() { return BIT(m_sa1_ctrl, 5); } // SA-1 CPU reset
inline const bool CCNT_SA1_CPU_NMI() { return BIT(m_sa1_ctrl, 4); } // SA-1 CPU NMI (from SNES CPU)
inline const u8 CCNT_SMEG() { return BIT(m_sa1_ctrl, 0, 4); } // Message from SNES CPU to SA-1 CPU
inline const bool sa1_halted() { return (CCNT_SA1_CPU_RDYB() || CCNT_SA1_CPU_RESB()); } // SA-1 is halted?
// $2201
uint8_t m_scpu_sie;
u8 m_scpu_sie;
// $2203-$2208
uint16_t m_sa1_reset, m_sa1_nmi, m_sa1_irq;
u16 m_sa1_reset_vector, m_sa1_nmi_vector, m_sa1_irq_vector;
// $2209
uint8_t m_scpu_ctrl;
u8 m_scpu_ctrl;
// SNES CPU Control (SCNT)
inline const bool SCNT_SNESCPU_IRQ() { return BIT(m_scpu_ctrl, 7); } // IRQ from SA-1 CPU to SNES CPU
inline const bool SCNT_SNESCPU_IVSW() { return BIT(m_scpu_ctrl, 6); } // SNES CPU IRQ vector selection (ROM, IRQ vector register)
inline const bool SCNT_SNESCPU_NVSW() { return BIT(m_scpu_ctrl, 4); } // SNES CPU NMI vector selection (ROM, NMI vector register)
inline const u8 SCNT_CMEG() { return BIT(m_scpu_ctrl, 0, 4); } // Message from SA-1 CPU to SNES CPU
// $220a
uint8_t m_sa1_sie;
// $200c-$200d - S-CPU vectors
uint16_t m_irq_vector, m_nmi_vector;
// $2012-$2015
uint16_t m_hcount, m_vcount;
u8 m_sa1_sie;
// $220c-$220d - S-CPU vectors
u16 m_irq_vector, m_nmi_vector;
// $2210-$2211
u8 m_timer_ctrl;
// H/V Timer control (TMC)
inline const bool TMC_HVSELB() { return BIT(m_timer_ctrl, 7); } // Select HV timer (HV timer, Linear timer)
inline const bool TMC_VEN() { return BIT(m_timer_ctrl, 1); } // V count enable
inline const bool TMC_HEN() { return BIT(m_timer_ctrl, 0); } // H count enable
// H/V Timer position
u16 m_hpos, m_vpos;
// $2212-$2215
u16 m_hcount, m_vcount;
// $2220-$2223
int m_bank_c_hi, m_bank_c_rom;
int m_bank_d_hi, m_bank_d_rom;
int m_bank_e_hi, m_bank_e_rom;
int m_bank_f_hi, m_bank_f_rom;
/*
enum super_mmc_t
{
CXB = 0,
DXB = 1,
EXB = 2,
FXB = 3
};
*/
bool m_bank_hi[4];
u8 m_bank_rom[4];
// $2224-$2225 & $223f
uint8_t m_bwram_snes, m_bwram_sa1;
int m_bwram_sa1_source, m_bwram_sa1_format;
u8 m_bwram_snes, m_bwram_sa1;
bool m_bwram_sa1_source, m_bwram_sa1_format;
// $2226-$2227
int m_bwram_write_snes, m_bwram_write_sa1;
bool m_bwram_write_snes, m_bwram_write_sa1;
// $2228
uint32_t m_bwpa_sa1;
u32 m_bwpa_sa1;
// $2229-$222a
uint8_t m_iram_write_snes, m_iram_write_sa1;
u8 m_iram_write_snes, m_iram_write_sa1;
// $2230-$2231
uint8_t m_dma_ctrl, m_dma_ccparam;
bool m_dma_cconv_end;
uint8_t m_dma_cconv_size;
uint8_t m_dma_cconv_bits;
u8 m_dma_ctrl, m_dma_ccparam;
u8 m_dma_cconv_size;
u8 m_dma_cconv_bits;
// DMA Control (DCNT)
inline const bool DCNT_DMAEN() { return BIT(m_dma_ctrl, 7); } // DMA Enable control
//inline const bool DCNT_DPRIO() { return BIT(m_dma_ctrl, 6); } // Processing priority between SA-1 CPU and DMA; Not emulated currently
inline const bool DCNT_CDEN() { return BIT(m_dma_ctrl, 5); } // DMA mode selection (Normal/Character conversion)
inline const bool DCNT_CDSEL() { return BIT(m_dma_ctrl, 4); } // Character conversion DMA type
inline const bool DCNT_DD() { return BIT(m_dma_ctrl, 2); } // Destination device (IRAM, BWRAM)
inline const u8 DCNT_SD() { return BIT(m_dma_ctrl, 0, 1); } // Source device (ROM, IRAM, BWRAM)
// Character conversion DMA parameters (CDMA)
inline const bool CDMA_CHDEND() { return BIT(m_dma_ccparam, 7); } // End character conversion 1
inline const u8 CDMA_SIZE() { return std::min<u8>(5, BIT(m_dma_ccparam, 2, 3)); } // Number of virtual VRAM horizontal characters (1 << SIZE)
inline const u8 CDMA_CB() { return std::min<u8>(2, BIT(m_dma_ccparam, 0, 2)); } // Character conversion DMA color mode (8bpp, 4bpp, 2bpp)
// $2232-$2237
uint32_t m_src_addr, m_dst_addr;
u32 m_src_addr, m_dst_addr;
// $2238-$2239
uint16_t m_dma_cnt;
u16 m_dma_cnt;
// $2240-$224f
uint8_t m_brf_reg[0x10];
u8 m_brf_reg[0x10];
// $2250-$2254
uint8_t m_math_ctlr, m_math_overflow;
uint16_t m_math_a, m_math_b;
uint64_t m_math_res;
u8 m_math_ctlr, m_math_overflow;
u16 m_math_a, m_math_b;
u64 m_math_res;
// $2258-$225b
uint32_t m_vda;
uint8_t m_vbit, m_vlen;
int m_drm;
u32 m_vda;
u8 m_vbit, m_vlen;
bool m_drm;
// $2300-$2301
uint8_t m_scpu_flags, m_sa1_flags;
u8 m_scpu_flags, m_sa1_flags;
// $2302-$2305
uint16_t m_hcr, m_vcr;
u16 m_hcr, m_vcr;
bool m_cconv1_dma_active;
uint32_t m_cconv_bits;
u8 m_cconv2_line;
uint8_t sa1_lo_r(offs_t offset);
uint8_t sa1_hi_r(offs_t offset);
void sa1_lo_w(offs_t offset, uint8_t data);
void sa1_hi_w(offs_t offset, uint8_t data);
u8 sa1_lo_r(offs_t offset);
u8 sa1_hi_r(offs_t offset);
void sa1_lo_w(offs_t offset, u8 data);
void sa1_hi_w(offs_t offset, u8 data);
void sa1_map(address_map &map);
uint8_t dma_cctype1_read(offs_t offset);
};

View File

@ -188,6 +188,30 @@ uint8_t device_sns_cart_interface::read_open_bus()
return 0xff;
}
//-------------------------------------------------
// scanlines_r - get motherboard scanline count
//-------------------------------------------------
int device_sns_cart_interface::scanlines_r()
{
if (m_slot != nullptr)
return m_slot->scanlines_r();
return 0xff;
}
//-------------------------------------------------
// address_r - get address pin from S-CPU
//-------------------------------------------------
offs_t device_sns_cart_interface::address_r()
{
if (m_slot != nullptr)
return m_slot->address_r();
return 0xff;
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************

View File

@ -145,6 +145,8 @@ protected:
DECLARE_WRITE_LINE_MEMBER(write_irq);
uint8_t read_open_bus();
int scanlines_r();
offs_t address_r();
// internal state
uint8_t *m_rom;
@ -172,6 +174,8 @@ public:
// configuration
auto irq_callback() { return m_irq_callback.bind(); }
auto open_bus_callback() { return m_open_bus_callback.bind(); }
void set_scanlines(int scanlines) { m_scanlines = scanlines; }
void set_address(offs_t address) { m_address = address; }
// image-level overrides
virtual image_init_result call_load() override;
@ -194,8 +198,14 @@ public:
void setup_nvram();
void internal_header_logging(uint8_t *ROM, uint32_t len);
void save_ram() { if (m_cart && m_cart->get_nvram_size()) m_cart->save_nvram();
if (m_cart && m_cart->get_rtc_ram_size()) m_cart->save_rtc_ram(); }
void save_ram()
{
save_item(NAME(m_address));
if (m_cart && m_cart->get_nvram_size())
m_cart->save_nvram();
if (m_cart && m_cart->get_rtc_ram_size())
m_cart->save_rtc_ram();
}
// reading and writing
uint8_t read_l(offs_t offset);
@ -209,6 +219,8 @@ public:
DECLARE_WRITE_LINE_MEMBER(write_irq) { m_irq_callback(state); }
uint8_t read_open_bus() { return m_open_bus_callback(); }
int scanlines_r() { return m_scanlines; }
offs_t address_r() { return m_address; }
// in order to support legacy dumps + add-on CPU dump appended at the end of the file, we
// check if the required data is present and update bank map accordingly
@ -238,6 +250,8 @@ protected:
private:
devcb_write_line m_irq_callback;
devcb_read8 m_open_bus_callback;
int m_scanlines;
offs_t m_address;
};
// ======================> sns_cart_slot_device

View File

@ -1304,6 +1304,19 @@ void snes_console_state::machine_start()
// m_maincpu->set_5a22_map();
break;
}
// install memory access taps (send address pin to cartridge slot)
m_maincpu->space(AS_PROGRAM).install_readwrite_tap
(
0x000000, 0xffffff, "cartslot_tap",
[this](offs_t offset, u8 &, u8)
{
m_cartslot->set_address(offset);
},
[this](offs_t offset, u8 &, u8)
{
m_cartslot->set_address(offset);
}
);
m_cartslot->save_ram();
}
}
@ -1317,7 +1330,7 @@ void snes_console_state::machine_reset()
void snes_console_state::snes(machine_config &config)
{
/* basic machine hardware */
_5A22(config, m_maincpu, MCLK_NTSC); /* 2.68 MHz, also 3.58 MHz */
_5A22(config, m_maincpu, MCLK_NTSC); // Nintendo S-CPU 5A22-0x, 21.477272MHz / (6, 8, 12) = 1.79 MHz, 2.68 MHz, also 3.58 MHz
m_maincpu->set_addrmap(AS_PROGRAM, &snes_console_state::snes_map);
// runs at 24.576 MHz / 12 = 2.048 MHz
@ -1329,6 +1342,9 @@ void snes_console_state::snes(machine_config &config)
//config.set_maximum_quantum(attotime::from_hz(48000));
config.set_perfect_quantum(m_maincpu);
INPUT_MERGER_ANY_HIGH(config, m_scpu_irq);
m_scpu_irq->output_handler().set_inputline(m_maincpu, G65816_LINE_IRQ);
/* video hardware */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(DOTCLK_NTSC * 2, SNES_HTOTAL * 2, 0, SNES_SCR_WIDTH * 2, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC);
@ -1355,8 +1371,9 @@ void snes_console_state::snes(machine_config &config)
m_s_dsp->add_route(1, "rspeaker", 1.00);
SNS_CART_SLOT(config, m_cartslot, MCLK_NTSC, snes_cart, nullptr);
m_cartslot->irq_callback().set_inputline(m_maincpu, G65816_LINE_IRQ); // FIXME: conflict with video interrupt, it should be ORed
m_cartslot->irq_callback().set(m_scpu_irq, FUNC(input_merger_device::in_w<1>)); // FIXME: conflict with video interrupt, it should be ORed
m_cartslot->open_bus_callback().set(FUNC(snes_console_state::snes_open_bus_r));
m_cartslot->set_scanlines(SNES_VTOTAL_NTSC);
SOFTWARE_LIST(config, "cart_list").set_original("snes");
SOFTWARE_LIST(config, "bsx_list").set_original("snes_bspack");
@ -1372,6 +1389,7 @@ void snes_console_state::snespal(machine_config &config)
m_ppu->set_clock(MCLK_PAL);
m_cartslot->set_clock(MCLK_PAL);
m_cartslot->set_scanlines(SNES_VTOTAL_PAL);
}

View File

@ -5,6 +5,7 @@
#define MAME_INCLUDES_SNES_H
#include "cpu/g65816/g65816.h"
#include "machine/input_merger.h"
#include "machine/s_smp.h"
#include "sound/s_dsp.h"
#include "video/snes_ppu.h"
@ -306,6 +307,7 @@ public:
m_s_dsp(*this, "s_dsp"),
m_ppu(*this, "ppu"),
m_screen(*this, "screen"),
m_scpu_irq(*this, "scpu_irq"),
m_wram(*this, "wram")
{ }
@ -395,6 +397,7 @@ protected:
required_device<s_dsp_device> m_s_dsp;
required_device<snes_ppu_device> m_ppu;
required_device<screen_device> m_screen;
optional_device<input_merger_device> m_scpu_irq;
required_shared_ptr<u8> m_wram;
@ -440,6 +443,7 @@ protected:
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(load_snes_cart);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(load_sufami_cart);
void snes_init_timers();
void scpu_irq_refresh();
};
/* Special chips, checked at init and used in memory handlers */

View File

@ -43,6 +43,15 @@ uint32_t snes_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
Timers
*************************************/
void snes_state::scpu_irq_refresh()
{
if (m_scpu_irq != nullptr) // multiplexed interrupt?
m_scpu_irq->in_w<0>(SNES_CPU_REG(TIMEUP) & 0x80);
else
m_maincpu->set_input_line(G65816_LINE_IRQ, (SNES_CPU_REG(TIMEUP) & 0x80) ? ASSERT_LINE : CLEAR_LINE);
}
void snes_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
@ -89,7 +98,7 @@ void snes_state::hirq_tick()
// (don't need to switch to the 65816 context, we don't do anything dependant on it)
m_ppu->set_latch_hv(m_ppu->current_x(), m_ppu->current_y());
SNES_CPU_REG(TIMEUP) = 0x80; /* Indicate that irq occurred */
m_maincpu->set_input_line(G65816_LINE_IRQ, ASSERT_LINE);
scpu_irq_refresh();
// don't happen again
m_hirq_timer->adjust(attotime::never);
@ -136,7 +145,7 @@ TIMER_CALLBACK_MEMBER(snes_state::snes_scanline_tick)
SNES_CPU_REG(TIMEUP) = 0x80; /* Indicate that irq occurred */
// IRQ latches the counters, do it now
m_ppu->set_latch_hv(m_ppu->current_x(), m_ppu->current_y());
m_maincpu->set_input_line(G65816_LINE_IRQ, ASSERT_LINE );
scpu_irq_refresh();
}
}
/* Horizontal IRQ timer */
@ -404,8 +413,9 @@ uint8_t snes_state::snes_r_io(offs_t offset)
switch (offset) // offset is from 0x000000
{
case WMDATA: /* Data to read from WRAM */
value = m_wram[m_wram_address++];
m_wram_address &= 0x1ffff;
value = m_wram[m_wram_address];
if (!machine().side_effects_disabled())
m_wram_address = (m_wram_address + 1) & 0x1ffff;
return value;
case OLDJOY1: /* Data for old NES controllers (JOYSER1) */
@ -416,12 +426,16 @@ uint8_t snes_state::snes_r_io(offs_t offset)
case RDNMI: /* NMI flag by v-blank and version number */
value = (SNES_CPU_REG(RDNMI) & 0x80) | (snes_open_bus_r() & 0x70);
SNES_CPU_REG(RDNMI) &= 0x70; /* NMI flag is reset on read */
if (!machine().side_effects_disabled())
SNES_CPU_REG(RDNMI) &= 0x70; /* NMI flag is reset on read */
return value | 2; //CPU version number
case TIMEUP: /* IRQ flag by H/V count timer */
value = (snes_open_bus_r() & 0x7f) | (SNES_CPU_REG(TIMEUP) & 0x80);
m_maincpu->set_input_line(G65816_LINE_IRQ, CLEAR_LINE );
SNES_CPU_REG(TIMEUP) = 0; // flag is cleared on both read and write
if (!machine().side_effects_disabled())
{
SNES_CPU_REG(TIMEUP) = 0; // flag is cleared on both read and write
scpu_irq_refresh();
}
return value;
case HVBJOY: /* H/V blank and joypad controller enable */
// electronics test says hcounter 272 is start of hblank, which is beampos 363
@ -500,16 +514,13 @@ void snes_state::snes_w_io(address_space &space, offs_t offset, uint8_t data)
m_wram_address &= 0x1ffff;
return;
case WMADDL: /* Address to read/write to wram (low) */
m_wram_address = (m_wram_address & 0xffff00) | (data << 0);
m_wram_address &= 0x1ffff;
m_wram_address = (m_wram_address & 0x1ff00) | (data << 0);
return;
case WMADDM: /* Address to read/write to wram (mid) */
m_wram_address = (m_wram_address & 0xff00ff) | (data << 8);
m_wram_address &= 0x1ffff;
m_wram_address = (m_wram_address & 0x100ff) | (data << 8);
return;
case WMADDH: /* Address to read/write to wram (high) */
m_wram_address = (m_wram_address & 0x00ffff) | (data << 16);
m_wram_address &= 0x1ffff;
m_wram_address = (m_wram_address & 0x0ffff) | ((data & 1) << 16);
return;
case OLDJOY1: /* Old NES joystick support */
write_joy_latch(data);
@ -521,8 +532,8 @@ void snes_state::snes_w_io(address_space &space, offs_t offset, uint8_t data)
case NMITIMEN: /* Flag for v-blank, timer int. and joy read */
if ((data & 0x30) == 0x00)
{
m_maincpu->set_input_line(G65816_LINE_IRQ, CLEAR_LINE );
SNES_CPU_REG(TIMEUP) = 0; // clear pending IRQ if irq is disabled here, 3x3 Eyes - Seima Korin Den behaves on this
scpu_irq_refresh();
}
SNES_CPU_REG(NMITIMEN) = data;
return;
@ -531,20 +542,16 @@ void snes_state::snes_w_io(address_space &space, offs_t offset, uint8_t data)
SNES_CPU_REG(WRIO) = data;
return;
case HTIMEL: /* H-Count timer settings (low) */
m_htime = (m_htime & 0xff00) | (data << 0);
m_htime &= 0x1ff;
m_htime = (m_htime & 0x100) | (data << 0);
return;
case HTIMEH: /* H-Count timer settings (high) */
m_htime = (m_htime & 0x00ff) | (data << 8);
m_htime &= 0x1ff;
m_htime = (m_htime & 0x0ff) | ((data & 1) << 8);
return;
case VTIMEL: /* V-Count timer settings (low) */
m_vtime = (m_vtime & 0xff00) | (data << 0);
m_vtime &= 0x1ff;
m_vtime = (m_vtime & 0x100) | (data << 0);
return;
case VTIMEH: /* V-Count timer settings (high) */
m_vtime = (m_vtime & 0x00ff) | (data << 8);
m_vtime &= 0x1ff;
m_vtime = (m_vtime & 0x0ff) | ((data & 1) << 8);
return;
case MDMAEN: /* DMA channel designation and trigger */
dma(space, data);
@ -556,8 +563,8 @@ void snes_state::snes_w_io(address_space &space, offs_t offset, uint8_t data)
SNES_CPU_REG(HDMAEN) = data;
return;
case TIMEUP: // IRQ Flag is cleared on both read and write
m_maincpu->set_input_line(G65816_LINE_IRQ, CLEAR_LINE );
SNES_CPU_REG(TIMEUP) = 0;
scpu_irq_refresh();
return;
/* Following are read-only */
case HVBJOY: /* H/V blank and joypad enable */
@ -1215,6 +1222,7 @@ inline int snes_state::dma_abus_valid( uint32_t address )
inline uint8_t snes_state::abus_read( address_space &space, uint32_t abus )
{
m_maincpu->adjust_icount(-8); // 8 master cycle per memory access
if (!dma_abus_valid(abus))
return 0;
@ -1225,6 +1233,7 @@ inline void snes_state::dma_transfer( address_space &space, uint8_t dma, uint32_
{
if (m_dma_channel[dma].dmap & 0x80) /* PPU->CPU */
{
m_maincpu->adjust_icount(-8); // 8 master cycle per memory access
if (bbus == 0x2180 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000))
{
//illegal WRAM->WRAM transfer (bus conflict)