summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author angelosa <salese_corp_ltd@email.it>2017-10-09 22:22:13 +0200
committer angelosa <salese_corp_ltd@email.it>2017-10-09 22:24:14 +0200
commitd4f7cfd631ed2e50452e75d8a20d0e752f51e963 (patch)
tree6020692608d583cb2cc19bc274372ee36793a216
parent358f17ad4c9754694a1b5ea2dafdee2c95522717 (diff)
saturn.cpp: Moved SCU related functions inside a device [Angelo Salese]
-rw-r--r--scripts/src/machine.lua12
-rw-r--r--scripts/target/mame/arcade.lua1
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/machine/sega_scu.cpp776
-rw-r--r--src/devices/machine/sega_scu.h156
-rw-r--r--src/devices/machine/smpc.cpp2
-rw-r--r--src/mame/drivers/saturn.cpp85
-rw-r--r--src/mame/drivers/stv.cpp29
-rw-r--r--src/mame/etc/template_device.h2
-rw-r--r--src/mame/includes/saturn.h72
-rw-r--r--src/mame/includes/stv.h20
-rw-r--r--src/mame/machine/saturn.cpp628
12 files changed, 999 insertions, 785 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index bb4001f84a8..f0bb0db561b 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -2373,6 +2373,18 @@ end
---------------------------------------------------
--
+--@src/devices/machine/sega_scu.h,MACHINES["SEGA_SCU"] = true
+---------------------------------------------------
+
+if (MACHINES["SEGA_SCU"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/sega_scu.cpp",
+ MAME_DIR .. "src/devices/machine/sega_scu.h",
+ }
+end
+
+---------------------------------------------------
+--
--@src/devices/machine/stvcd.h,MACHINES["STVCD"] = true
---------------------------------------------------
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index f0c819f606f..e761a43a67b 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -550,6 +550,7 @@ MACHINES["SCUDSP"] = true
--MACHINES["SECFLASH"] = true
MACHINES["SERFLASH"] = true
MACHINES["SMC91C9X"] = true
+MACHINES["SEGA_SCU"] = true
MACHINES["SMPC"] = true
MACHINES["STVCD"] = true
MACHINES["TC0091LVC"] = true
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 80f974121ba..d0026297337 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -540,6 +540,7 @@ MACHINES["SEIBU_COP"] = true
--MACHINES["SERFLASH"] = true
MACHINES["SMC91C9X"] = true
MACHINES["SMIOC"] = true
+MACHINES["SEGA_SCU"] = true
MACHINES["SMPC"] = true
MACHINES["STVCD"] = true
MACHINES["TC0091LVC"] = true
diff --git a/src/devices/machine/sega_scu.cpp b/src/devices/machine/sega_scu.cpp
new file mode 100644
index 00000000000..91154a9f775
--- /dev/null
+++ b/src/devices/machine/sega_scu.cpp
@@ -0,0 +1,776 @@
+// license:LGPL-2.1+
+// copyright-holders:Angelo Salese
+/***************************************************************************
+
+ Sega System Control Unit (c) 1995 Sega
+
+ TODO:
+ - make a screen_device subclass, add pixel timers & irq callbacks to it;
+ - A-Bus external interrupts;
+ - Pad signal (lightgun I presume);
+ - Improve DMA, use DRQ model and timers, make them subdevices?
+ (old DMA TODO)
+ - Remove CD transfer DMA hack (tied with CD block bug(s)?)
+ - Add timings(but how fast are each DMA?).
+ - Add level priority & DMA status register.
+
+***************************************************************************/
+/**********************************************************************************
+SCU Register Table
+offset,relative address
+Registers are in long words.
+===================================================================================
+0 0000 Level 0 DMA Set Register
+1 0004
+2 0008
+3 000c
+4 0010
+5 0014
+6 0018
+7 001c
+8 0020 Level 1 DMA Set Register
+9 0024
+10 0028
+11 002c
+12 0030
+13 0034
+14 0038
+15 003c
+16 0040 Level 2 DMA Set Register
+17 0044
+18 0048
+19 004c
+20 0050
+21 0054
+22 0058
+23 005c
+24 0060 DMA Forced Stop
+25 0064
+26 0068
+27 006c
+28 0070 <Free>
+29 0074
+30 0078
+31 007c DMA Status Register
+32 0080 DSP Program Control Port
+33 0084 DSP Program RAM Data Port
+34 0088 DSP Data RAM Address Port
+35 008c DSP Data RAM Data Port
+36 0090 Timer 0 Compare Register
+37 0094 Timer 1 Set Data Register
+38 0098 Timer 1 Mode Register
+39 009c <Free>
+40 00a0 Interrupt Mask Register
+41 00a4 Interrupt Status Register
+42 00a8 A-Bus Interrupt Acknowledge
+43 00ac <Free>
+44 00b0 A-Bus Set Register
+45 00b4
+46 00b8 A-Bus Refresh Register
+47 00bc <Free>
+48 00c0
+49 00c4 SCU SDRAM Select Register
+50 00c8 SCU Version Register
+51 00cc <Free>
+52 00cf
+===================================================================================
+DMA Status Register(32-bit):
+xxxx xxxx x--- xx-- xx-- xx-- xx-- xx-- UNUSED
+---- ---- -x-- ---- ---- ---- ---- ---- DMA DSP-Bus access
+---- ---- --x- ---- ---- ---- ---- ---- DMA B-Bus access
+---- ---- ---x ---- ---- ---- ---- ---- DMA A-Bus access
+---- ---- ---- --x- ---- ---- ---- ---- DMA lv 1 interrupt
+---- ---- ---- ---x ---- ---- ---- ---- DMA lv 0 interrupt
+---- ---- ---- ---- --x- ---- ---- ---- DMA lv 2 in stand-by
+---- ---- ---- ---- ---x ---- ---- ---- DMA lv 2 in operation
+---- ---- ---- ---- ---- --x- ---- ---- DMA lv 1 in stand-by
+---- ---- ---- ---- ---- ---x ---- ---- DMA lv 1 in operation
+---- ---- ---- ---- ---- ---- --x- ---- DMA lv 0 in stand-by
+---- ---- ---- ---- ---- ---- ---x ---- DMA lv 0 in operation
+---- ---- ---- ---- ---- ---- ---- --x- DSP side DMA in stand-by
+---- ---- ---- ---- ---- ---- ---- ---x DSP side DMA in operation
+
+**********************************************************************************/
+
+#include "emu.h"
+#include "sega_scu.h"
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(SEGA_SCU, sega_scu_device, "sega_scu", "Sega System Control Unit")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//AM_RANGE(0x0000, 0x0003) src
+//AM_RANGE(0x0004, 0x0007) dst
+//AM_RANGE(0x0008, 0x000b) size
+//AM_RANGE(0x000c, 0x000f) src/dst add values
+//AM_RANGE(0x0010, 0x0013) DMA enable
+//AM_RANGE(0x0014, 0x0017) DMA start factor
+
+DEVICE_ADDRESS_MAP_START( regs_map, 32, sega_scu_device )
+ AM_RANGE(0x0000, 0x0017) AM_READWRITE(dma_lv0_r,dma_lv0_w)
+ AM_RANGE(0x0020, 0x0037) AM_READWRITE(dma_lv1_r,dma_lv1_w)
+ AM_RANGE(0x0040, 0x0057) AM_READWRITE(dma_lv2_r,dma_lv2_w)
+ // Super Major League and Shin Megami Tensei - Akuma Zensho reads from there (undocumented), DMA status mirror?
+ AM_RANGE(0x005c, 0x005f) AM_READ(dma_status_r)
+// AM_RANGE(0x0060, 0x0063) AM_WRITE(dma_force_stop_w)
+ AM_RANGE(0x007c, 0x007f) AM_READ(dma_status_r)
+ AM_RANGE(0x0080, 0x0083) AM_DEVREADWRITE("scudsp",scudsp_cpu_device, program_control_r,program_control_w)
+ AM_RANGE(0x0084, 0x0087) AM_DEVWRITE("scudsp", scudsp_cpu_device, program_w)
+ AM_RANGE(0x0088, 0x008b) AM_DEVWRITE("scudsp", scudsp_cpu_device, ram_address_control_w)
+ AM_RANGE(0x008c, 0x008f) AM_DEVREADWRITE("scudsp", scudsp_cpu_device, ram_address_r, ram_address_w)
+ AM_RANGE(0x0090, 0x0093) AM_WRITE(t0_compare_w)
+ AM_RANGE(0x0094, 0x0097) AM_WRITE(t1_setdata_w)
+ AM_RANGE(0x0098, 0x009b) AM_WRITE16(t1_mode_w,0x0000ffff)
+ AM_RANGE(0x00a0, 0x00a3) AM_READWRITE(irq_mask_r,irq_mask_w)
+ AM_RANGE(0x00a4, 0x00a7) AM_READWRITE(irq_status_r,irq_status_w)
+// AM_RANGE(0x00a8, 0x00ab) AM_WRITE(abus_irqack_w)
+// AM_RANGE(0x00b0, 0x00b7) AM_READWRITE(abus_set_r,abus_set_w)
+// AM_RANGE(0x00b8, 0x00bb) AM_READWRITE(abus_refresh_r,abus_refresh_w)
+// AM_RANGE(0x00c4, 0x00c7) AM_READWRITE(sdram_r,sdram_w)
+ AM_RANGE(0x00c8, 0x00cb) AM_READ(version_r) // returns 4 for stock Saturn
+ADDRESS_MAP_END
+
+//-------------------------------------------------
+// sega_scu_device - constructor
+//-------------------------------------------------
+
+sega_scu_device::sega_scu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SEGA_SCU, tag, owner, clock),
+ m_scudsp(*this, "scudsp")
+{
+}
+
+void sega_scu_device::static_set_hostcpu(device_t &device, const char *cputag)
+{
+ sega_scu_device &dev = downcast<sega_scu_device &>(device);
+ dev.m_hostcpu_tag = cputag;
+}
+
+
+//-------------------------------------------------
+// add_device_mconfig - device-specific machine
+// configuration addiitons
+//-------------------------------------------------
+
+static ADDRESS_MAP_START( scudsp_mem, AS_PROGRAM, 32, sega_scu_device )
+ AM_RANGE(0x00, 0xff) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( scudsp_data, AS_DATA, 32, sega_scu_device )
+ AM_RANGE(0x00, 0xff) AM_RAM
+ADDRESS_MAP_END
+
+READ16_MEMBER(sega_scu_device::scudsp_dma_r)
+{
+ //address_space &program = m_maincpu->space(AS_PROGRAM);
+ offs_t addr = offset;
+
+// printf("%08x\n",addr);
+
+ return m_hostspace->read_word(addr,mem_mask);
+}
+
+
+WRITE16_MEMBER(sega_scu_device::scudsp_dma_w)
+{
+ //address_space &program = m_maincpu->space(AS_PROGRAM);
+ offs_t addr = offset;
+
+// printf("%08x %02x\n",addr,data);
+
+ m_hostspace->write_word(addr, data,mem_mask);
+}
+
+MACHINE_CONFIG_MEMBER(sega_scu_device::device_add_mconfig)
+ MCFG_CPU_ADD("scudsp", SCUDSP, XTAL_57_2727MHz/4) // 14 MHz
+ MCFG_CPU_PROGRAM_MAP(scudsp_mem)
+ MCFG_CPU_DATA_MAP(scudsp_data)
+ MCFG_SCUDSP_OUT_IRQ_CB(DEVWRITELINE(DEVICE_SELF, sega_scu_device, scudsp_end_w))
+ MCFG_SCUDSP_IN_DMA_CB(READ16(sega_scu_device, scudsp_dma_r))
+ MCFG_SCUDSP_OUT_DMA_CB(WRITE16(sega_scu_device, scudsp_dma_w))
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sega_scu_device::device_start()
+{
+ save_item(NAME(m_ist));
+ save_item(NAME(m_ism));
+ save_item(NAME(m_t0c));
+ save_item(NAME(m_t1s));
+ save_item(NAME(m_t1md));
+
+ m_hostcpu = machine().device<sh2_device>(m_hostcpu_tag);//machine().device(m_hostcpu_tag);
+ m_hostspace = &m_hostcpu->space(AS_PROGRAM);
+
+ m_dma_timer[0] = timer_alloc(DMALV0_ID);
+ m_dma_timer[1] = timer_alloc(DMALV1_ID);
+ m_dma_timer[2] = timer_alloc(DMALV2_ID);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void sega_scu_device::device_reset()
+{
+ m_ism = 0xbfff;
+ m_ist = 0;
+
+ for(int i=0;i<3;i++)
+ {
+ m_dma[i].start_factor = 7;
+ m_dma_timer[i]->reset();
+ }
+
+ m_status = 0;
+ m_scudsp->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+
+}
+
+
+void sega_scu_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+
+ switch(id)
+ {
+ case DMALV0_ID:
+ case DMALV1_ID:
+ case DMALV2_ID:
+ {
+ const int irqlevel = id == 0 ? 5 : 6;
+ const int irqvector = 0x4b - id;
+ const uint16_t irqmask = 1 << (11-id);
+
+ if(!(m_ism & irqmask))
+ m_hostcpu->set_input_line_and_vector(irqlevel, HOLD_LINE, irqvector);
+ else
+ m_ist |= (irqmask);
+
+ update_dma_status(id,false);
+ machine().scheduler().synchronize(); // force resync
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+//**************************************************************************
+// DMA
+//**************************************************************************
+
+uint32_t sega_scu_device::dma_common_r(uint8_t offset,uint8_t level)
+{
+ switch(offset)
+ {
+ case 0x00/4: // source
+ return m_dma[level].src;
+ case 0x04/4: // destination
+ return m_dma[level].dst;
+ case 0x08/4: // size
+ return m_dma[level].size;
+ case 0x0c/4:
+ return 0; // DxAD, write only
+ case 0x10/4:
+ return 0; // DxEN / DxGO, write only
+ case 0x14/4:
+ return 0; // DxMOD / DxRUP / DxWUP / DxFT, write only
+ }
+
+ // can't happen anyway
+ return 0;
+}
+
+void sega_scu_device::dma_common_w(uint8_t offset,uint8_t level,uint32_t data)
+{
+ switch(offset)
+ {
+ case 0x00/4: // source
+ m_dma[level].src = data & 0x07ffffff;
+ break;
+ case 0x04/4: // destination
+ m_dma[level].dst = data & 0x07ffffff;
+ break;
+ case 0x08/4: // size, lv0 is bigger than the others
+ m_dma[level].size = data & ((level == 0) ? 0x000fffff : 0xfff);
+ break;
+ case 0x0c/4: // DxAD
+ m_dma[level].src_add = (data & 0x100) ? 4 : 0;
+ m_dma[level].dst_add = 1 << (data & 7);
+ if(m_dma[level].dst_add == 1) { m_dma[level].dst_add = 0; }
+ break;
+ case 0x10/4: // DxEN / DxGO
+ m_dma[level].enable_mask = BIT(data,8);
+
+ // check if DxGO is enabled for start factor = 7
+ if(m_dma[level].enable_mask == true && data & 1 && m_dma[level].start_factor == 7)
+ {
+ if(m_dma[level].indirect_mode == true)
+ handle_dma_indirect(level);
+ else
+ handle_dma_direct(level);
+ }
+ break;
+ case 0x14/4: // DxMOD / DxRUP / DxWUP / DxFT, write only
+ m_dma[level].indirect_mode = BIT(data,24);
+ m_dma[level].rup = BIT(data,16);
+ m_dma[level].wup = BIT(data,8);
+ m_dma[level].start_factor = data & 7;
+ if(m_dma[level].indirect_mode == true)
+ {
+ //if(LOG_SCU) logerror("Indirect Mode DMA lv %d set\n",level);
+ if(m_dma[level].wup == false)
+ m_dma[level].index = m_dma[level].dst;
+ }
+
+ break;
+ }
+}
+
+inline void sega_scu_device::update_dma_status(uint8_t level,bool state)
+{
+ if(state)
+ m_status|=(0x10 << 4 * level);
+ else
+ m_status&=~(0x10 << 4 * level);
+}
+
+void sega_scu_device::handle_dma_direct(uint8_t level)
+{
+ uint32_t tmp_src,tmp_dst,total_size;
+ uint8_t cd_transfer_flag;
+
+ #if 0
+ if(m_dma[level].src_add == 0 || (m_dma[level].dst_add != 2 && m_dma[level].dst_add != 4))
+ {
+ if(LOG_SCU) printf("DMA lv %d transfer START\n"
+ "Start %08x End %08x Size %04x\n",dma_ch,m_scu.src[dma_ch],m_scu.dst[dma_ch],m_scu.size[dma_ch]);
+ if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",m_scu.src_add[dma_ch],m_scu.dst_add[dma_ch]);
+ }
+ #endif
+
+ // Game Basic, World Cup 98 and Batman Forever trips this, according to the docs the SCU can't transfer from BIOS area (can't communicate from/to that bus)
+ if((m_dma[level].src & 0x07f00000) == 0)
+ {
+ //popmessage("Warning: SCU transfer from BIOS area, contact MAMEdev");
+ if(!(m_ism & IRQ_DMAILL))
+ m_hostcpu->set_input_line_and_vector(3, HOLD_LINE, 0x4c);
+ else
+ m_ist |= (IRQ_DMAILL);
+ return;
+ }
+
+ update_dma_status(level,true);
+
+ /* max size */
+ if(m_dma[level].size == 0) { m_dma[level].size = (level == 0) ? 0x00100000 : 0x1000; }
+
+ tmp_src = tmp_dst = 0;
+
+ total_size = m_dma[level].size ;
+ if(m_dma[level].rup == false) tmp_src = m_dma[level].src;
+ if(m_dma[level].wup == false) tmp_dst = m_dma[level].dst;
+
+ cd_transfer_flag = m_dma[level].src_add == 0 && m_dma[level].src == 0x05818000;
+
+ /* TODO: Many games directly accesses CD-ROM register 0x05818000, it must be a dword access with current implementation otherwise it won't work */
+ if(cd_transfer_flag)
+ {
+ int i;
+ if((m_dma[level].dst & 0x07000000) == 0x06000000)
+ m_dma[level].dst_add = 4;
+ else
+ m_dma[level].dst_add <<= 1;
+
+ for (i = 0; i < m_dma[level].size;i+=m_dma[level].dst_add)
+ {
+ m_hostspace->write_dword(m_dma[level].dst,m_hostspace->read_dword(m_dma[level].src));
+ if(m_dma[level].dst_add == 8)
+ m_hostspace->write_dword(m_dma[level].dst+4,m_hostspace->read_dword(m_dma[level].src));
+
+ m_dma[level].src += m_dma[level].src_add;
+ m_dma[level].dst += m_dma[level].dst_add;
+ }
+ }
+ else
+ {
+ int i;
+ uint8_t src_shift;
+
+ src_shift = ((m_dma[level].src & 2) >> 1) ^ 1;
+
+ for (i = 0; i < m_dma[level].size; i+=2)
+ {
+ dma_single_transfer(m_dma[level].src, m_dma[level].dst, &src_shift);
+
+ if(src_shift)
+ m_dma[level].src+= m_dma[level].src_add ;
+
+ /* if target is Work RAM H, the add value is fixed, behaviour confirmed by Final Romance 2, Virtual Mahjong and Burning Rangers */
+ m_dma[level].dst += ((m_dma[level].dst & 0x07000000) == 0x06000000) ? 2 : m_dma[level].dst_add;
+ }
+ }
+
+ /* Burning Rangers doesn't agree with this. */
+// m_scu.size[dma_ch] = 0;
+ if(m_dma[level].rup == false) m_dma[level].src = tmp_src;
+ if(m_dma[level].wup == false) m_dma[level].dst = tmp_dst;
+
+ // TODO: Timing is a guess.
+ m_dma_timer[level]->adjust(m_hostcpu->cycles_to_attotime(total_size/4));
+}
+
+void sega_scu_device::handle_dma_indirect(uint8_t level)
+{
+ /*Helper to get out of the cycle*/
+ uint8_t job_done = 0;
+ /*temporary storage for the transfer data*/
+ uint32_t tmp_src;
+ uint32_t indirect_src,indirect_dst;
+ int32_t indirect_size;
+ uint32_t total_size = 0;
+
+ update_dma_status(level,true);
+
+ m_dma[level].index = m_dma[level].dst;
+
+ do{
+ tmp_src = m_dma[level].index;
+
+ indirect_size = m_hostspace->read_dword(m_dma[level].index);
+ indirect_dst = m_hostspace->read_dword(m_dma[level].index+4);
+ indirect_src = m_hostspace->read_dword(m_dma[level].index+8);
+
+ /*Indirect Mode end factor*/
+ if(indirect_src & 0x80000000)
+ job_done = 1;
+
+ #if 0
+ if(m_dma[level].src_add == 0 || (m_dma[level].dst_add != 2))
+ {
+ if(LOG_SCU) printf("DMA lv %d indirect mode transfer START\n"
+ "Index %08x Start %08x End %08x Size %04x\n",dma_ch,tmp_src,indirect_src,indirect_dst,indirect_size);
+ if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",m_scu.src_add[dma_ch],m_scu.dst_add[dma_ch]);
+ }
+ #endif
+
+ indirect_src &=0x07ffffff;
+ indirect_dst &=0x07ffffff;
+ indirect_size &= ((level == 0) ? 0xfffff : 0x3ffff); //TODO: Guardian Heroes sets up a 0x23000 transfer for the FMV?
+
+ if(indirect_size == 0) { indirect_size = (level == 0) ? 0x00100000 : 0x2000; }
+
+ {
+ int i;
+ uint8_t src_shift;
+
+ src_shift = ((indirect_src & 2) >> 1) ^ 1;
+
+ for (i = 0; i < indirect_size;i+=2)
+ {
+ dma_single_transfer(indirect_src,indirect_dst,&src_shift);
+
+ if(src_shift)
+ indirect_src+=m_dma[level].src_add;
+
+ indirect_dst += ((m_dma[level].dst & 0x07000000) == 0x06000000) ? 2 : m_dma[level].dst_add;
+ }
+ }
+
+ /* Guess: Size + data acquire (1 cycle for src/dst/size) */
+ total_size += indirect_size + 3*4;
+
+ //if(DRUP(0)) space.write_dword(tmp_src+8,m_scu.src[0]|job_done ? 0x80000000 : 0);
+ //if(DWUP(0)) space.write_dword(tmp_src+4,m_scu.dst[0]);
+
+ m_dma[level].index = tmp_src+0xc;
+
+ }while(job_done == 0);
+
+ // TODO: Timing is a guess.
+ m_dma_timer[level]->adjust(m_hostcpu->cycles_to_attotime(total_size/4));
+}
+
+
+inline void sega_scu_device::dma_single_transfer(uint32_t src, uint32_t dst,uint8_t *src_shift)
+{
+ uint32_t src_data;
+
+ if(src & 1)
+ {
+ /* Road Blaster does a work ram h to color ram with offsetted source address, do some data rotation */
+ src_data = ((m_hostspace->read_dword(src & 0x07fffffc) & 0x00ffffff)<<8);
+ src_data |= ((m_hostspace->read_dword((src & 0x07fffffc)+4) & 0xff000000) >> 24);
+ src_data >>= (*src_shift)*16;
+ }
+ else
+ src_data = m_hostspace->read_dword(src & 0x07fffffc) >> (*src_shift)*16;
+
+ m_hostspace->write_word(dst,src_data);
+
+ *src_shift ^= 1;
+}
+
+inline void sega_scu_device::dma_start_factor_ack(uint8_t event)
+{
+ int i;
+
+ for(i=0;i<3;i++)
+ {
+ if(m_dma[i].enable_mask == true && m_dma[i].start_factor == event)
+ {
+ if(m_dma[i].indirect_mode == true) { handle_dma_indirect(i); }
+ else { handle_dma_direct(i); }
+ }
+ }
+}
+
+READ32_MEMBER(sega_scu_device::dma_lv0_r) { return dma_common_r(offset,0); }
+WRITE32_MEMBER(sega_scu_device::dma_lv0_w) { dma_common_w(offset,0,data); }
+READ32_MEMBER(sega_scu_device::dma_lv1_r) { return dma_common_r(offset,1); }
+WRITE32_MEMBER(sega_scu_device::dma_lv1_w) { dma_common_w(offset,1,data); }
+READ32_MEMBER(sega_scu_device::dma_lv2_r) { return dma_common_r(offset,2); }
+WRITE32_MEMBER(sega_scu_device::dma_lv2_w) { dma_common_w(offset,2,data); }
+
+READ32_MEMBER(sega_scu_device::dma_status_r)
+{
+ return m_status;
+}
+
+//**************************************************************************
+// Timers
+//**************************************************************************
+
+WRITE32_MEMBER(sega_scu_device::t0_compare_w )
+{
+ COMBINE_DATA(&m_t0c);
+}
+
+WRITE32_MEMBER(sega_scu_device::t1_setdata_w )
+{
+ COMBINE_DATA(&m_t1s);
+}
+
+/*
+ ---- ---x ---- ---- T1MD Timer 1 mode (0=each line, 1=only at timer 0 lines)
+ ---- ---- ---- ---x TENB Timers enable
+ */
+WRITE16_MEMBER(sega_scu_device::t1_mode_w )
+{
+ m_t1md = BIT(data,8);
+ m_tenb = BIT(data,0);
+}
+
+
+void sega_scu_device::check_scanline_timers(int scanline,int y_step)
+{
+ if(m_tenb == false)
+ return;
+
+ int timer0_compare = (m_t0c & 0x3ff)*y_step;
+
+ // Timer 0
+ if(scanline == timer0_compare)
+ {
+ if(!(m_ism & IRQ_TIMER_0))
+ {
+ m_hostcpu->set_input_line_and_vector(0xc, HOLD_LINE, 0x43 );
+ dma_start_factor_ack(3);
+ }
+ else
+ m_ist |= (IRQ_TIMER_0);
+ }
+
+ // Timer 1
+ // TODO: should happen after some time when hblank-in is received then counts down t1s
+ if(
+ ((m_t1md == false) && ((scanline % y_step) == 0)) ||
+ ((m_t1md == true) && (scanline == timer0_compare)) )
+ {
+ if(!(m_ism & IRQ_TIMER_1))
+ {
+ m_hostcpu->set_input_line_and_vector(0xb, HOLD_LINE, 0x44 );
+ dma_start_factor_ack(4);
+ }
+ else
+ m_ist |= (IRQ_TIMER_1);
+ }
+
+}
+
+
+//**************************************************************************
+// Interrupt
+//**************************************************************************
+
+READ32_MEMBER(sega_scu_device::irq_mask_r)
+{
+ return m_ism;
+}
+
+READ32_MEMBER(sega_scu_device::irq_status_r)
+{
+ return m_ist;
+}
+
+WRITE32_MEMBER(sega_scu_device::irq_mask_w)
+{
+ COMBINE_DATA(&m_ism);
+ test_pending_irqs();
+}
+
+WRITE32_MEMBER(sega_scu_device::irq_status_w)
+{
+ if(mem_mask != 0xffffffff)
+ logerror("%s IST write %08x with %08x\n",this->tag(),data,mem_mask);
+
+ m_ist &= data;
+ test_pending_irqs();
+}
+
+void sega_scu_device::test_pending_irqs()
+{
+ int i;
+ const int irq_level[32] = { 0xf, 0xe, 0xd, 0xc,
+ 0xb, 0xa, 0x9, 0x8,
+ 0x8, 0x6, 0x6, 0x5,
+ 0x3, 0x2, -1, -1,
+ 0x7, 0x7, 0x7, 0x7,
+ 0x4, 0x4, 0x4, 0x4,
+ 0x1, 0x1, 0x1, 0x1,
+ 0x1, 0x1, 0x1, 0x1 };
+
+ for(i=0;i<32;i++)
+ {
+ if((!(m_ism & 1 << i)) && (m_ist & 1 << i))
+ {
+ if(irq_level[i] != -1) /* TODO: cheap check for undefined irqs */
+ {
+ m_hostcpu->set_input_line_and_vector(irq_level[i], HOLD_LINE, 0x40 + i);
+ m_ist &= ~(1 << i);
+ return; /* avoid spurious irqs, correct? */
+ }
+ }
+ }
+}
+
+WRITE_LINE_MEMBER(sega_scu_device::vblank_out_w)
+{
+ if(!state)
+ return;
+
+ if(!(m_ism & IRQ_VBLANK_OUT))
+ {
+ m_hostcpu->set_input_line_and_vector(0xe, HOLD_LINE, 0x41);
+ dma_start_factor_ack(1);
+ }
+ else
+ m_ist |= (IRQ_VBLANK_OUT);
+}
+
+WRITE_LINE_MEMBER(sega_scu_device::vblank_in_w)
+{
+ if(!state)
+ return;
+
+ if(!(m_ism & IRQ_VBLANK_IN))
+ {
+ m_hostcpu->set_input_line_and_vector(0xf, HOLD_LINE ,0x40);
+ dma_start_factor_ack(0);
+ }
+ else
+ m_ist |= (IRQ_VBLANK_IN);
+}
+
+WRITE_LINE_MEMBER(sega_scu_device::hblank_in_w)
+{
+ if(!state)
+ return;
+
+ if(!(m_ism & IRQ_HBLANK_IN))
+ {
+ m_hostcpu->set_input_line_and_vector(0xd, HOLD_LINE, 0x42);
+ dma_start_factor_ack(2);
+ }
+ else
+ m_ist |= (IRQ_HBLANK_IN);
+}
+
+WRITE_LINE_MEMBER(sega_scu_device::vdp1_end_w)
+{
+ if(!state)
+ return;
+
+ if(!(m_ism & IRQ_VDP1_END))
+ {
+ m_hostcpu->set_input_line_and_vector(0x2, HOLD_LINE, 0x4d);
+ dma_start_factor_ack(6);
+ }
+ else
+ m_ist |= (IRQ_VDP1_END);
+}
+
+WRITE_LINE_MEMBER(sega_scu_device::sound_req_w)
+{
+ if(!state)
+ return;
+
+ if(!(m_ism & IRQ_SOUND_REQ))
+ {
+ m_hostcpu->set_input_line_and_vector(9, HOLD_LINE, 0x46);
+ dma_start_factor_ack(5);
+ }
+ else
+ m_ist |= (IRQ_SOUND_REQ);
+}
+
+WRITE_LINE_MEMBER(sega_scu_device::smpc_irq_w)
+{
+ if(!state)
+ return;
+
+ if(!(m_ism & IRQ_SMPC))
+ m_hostcpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
+ else
+ m_ist |= (IRQ_SMPC);
+}
+
+WRITE_LINE_MEMBER(sega_scu_device::scudsp_end_w)
+{
+ if(!state)
+ return;
+
+ if(!(m_ism & IRQ_DSP_END))
+ m_hostcpu->set_input_line_and_vector(0xa, HOLD_LINE, 0x45);
+ else
+ m_ist |= (IRQ_DSP_END);
+
+}
+
+//**************************************************************************
+// Miscellanea
+//**************************************************************************
+
+READ32_MEMBER(sega_scu_device::version_r)
+{
+ return 4; // correct for stock Saturn at least
+}
diff --git a/src/devices/machine/sega_scu.h b/src/devices/machine/sega_scu.h
new file mode 100644
index 00000000000..b9653e97537
--- /dev/null
+++ b/src/devices/machine/sega_scu.h
@@ -0,0 +1,156 @@
+// license:BSD-3-Clause
+// copyright-holders:<author_name>
+/***************************************************************************
+
+Template for squeleton device
+
+***************************************************************************/
+
+#ifndef MAME_MACHINE_SEGA_SCU_H
+#define MAME_MACHINE_SEGA_SCU_H
+
+#pragma once
+
+#include "cpu/sh/sh2.h"
+#include "cpu/scudsp/scudsp.h"
+
+#define IRQ_VBLANK_IN 1 << 0
+#define IRQ_VBLANK_OUT 1 << 1
+#define IRQ_HBLANK_IN 1 << 2
+#define IRQ_TIMER_0 1 << 3
+#define IRQ_TIMER_1 1 << 4
+#define IRQ_DSP_END 1 << 5
+#define IRQ_SOUND_REQ 1 << 6
+#define IRQ_SMPC 1 << 7
+#define IRQ_PAD 1 << 8
+#define IRQ_DMALV2 1 << 9
+#define IRQ_DMALV1 1 << 10
+#define IRQ_DMALV0 1 << 11
+#define IRQ_DMAILL 1 << 12
+#define IRQ_VDP1_END 1 << 13
+#define IRQ_ABUS 1 << 15
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_SEGA_SCU_ADD(tag) \
+ MCFG_DEVICE_ADD((tag), SEGA_SCU, (0))
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sega_scu_device
+
+class sega_scu_device : public device_t
+{
+public:
+ // construction/destruction
+ sega_scu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // I/O operations
+ DECLARE_ADDRESS_MAP(regs_map, 32);
+
+ // DMA
+ DECLARE_READ32_MEMBER(dma_lv0_r);
+ DECLARE_WRITE32_MEMBER(dma_lv0_w);
+ DECLARE_READ32_MEMBER(dma_lv1_r);
+ DECLARE_WRITE32_MEMBER(dma_lv1_w);
+ DECLARE_READ32_MEMBER(dma_lv2_r);
+ DECLARE_WRITE32_MEMBER(dma_lv2_w);
+ DECLARE_READ32_MEMBER(dma_status_r);
+
+ // Timers
+ DECLARE_WRITE32_MEMBER(t0_compare_w);
+ DECLARE_WRITE32_MEMBER(t1_setdata_w);
+ DECLARE_WRITE16_MEMBER(t1_mode_w);
+ // Interrupt
+ DECLARE_READ32_MEMBER(irq_mask_r);
+ DECLARE_READ32_MEMBER(irq_status_r);
+ DECLARE_WRITE32_MEMBER(irq_mask_w);
+ DECLARE_WRITE32_MEMBER(irq_status_w);
+ DECLARE_READ32_MEMBER(version_r);
+
+ DECLARE_WRITE_LINE_MEMBER(vblank_out_w);
+ DECLARE_WRITE_LINE_MEMBER(vblank_in_w);
+ DECLARE_WRITE_LINE_MEMBER(hblank_in_w);
+ DECLARE_WRITE_LINE_MEMBER(vdp1_end_w);
+ void check_scanline_timers(int scanline,int y_step);
+ DECLARE_WRITE_LINE_MEMBER(sound_req_w);
+ DECLARE_WRITE_LINE_MEMBER(smpc_irq_w);
+ DECLARE_WRITE_LINE_MEMBER(scudsp_end_w);
+ DECLARE_READ16_MEMBER(scudsp_dma_r);
+ DECLARE_WRITE16_MEMBER(scudsp_dma_w);
+
+ static void static_set_hostcpu(device_t &device, const char *cputag);
+
+protected:
+ // device-level overrides
+ //virtual void device_validity_check(validity_checker &valid) const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+private:
+ required_device<scudsp_cpu_device> m_scudsp;
+
+ enum {
+ DMALV0_ID = 0,
+ DMALV1_ID,
+ DMALV2_ID
+ };
+
+ emu_timer *m_dma_timer[3];
+ uint32_t m_ism;
+ uint32_t m_ist;
+ uint32_t m_t0c;
+ uint32_t m_t1s;
+ uint32_t m_status;
+ bool m_t1md;
+ bool m_tenb;
+
+ const char *m_hostcpu_tag;
+ sh2_device *m_hostcpu;
+ address_space *m_hostspace;
+ void test_pending_irqs();
+
+ struct {
+ uint32_t src; /* Source DMA lv n address*/
+ uint32_t dst; /* Destination DMA lv n address*/
+ uint32_t src_add; /* Source Addition for DMA lv n*/
+ uint32_t dst_add; /* Destination Addition for DMA lv n*/
+ uint32_t size; /* Transfer DMA size lv n*/
+ uint32_t index;
+ uint8_t start_factor;
+ bool enable_mask;
+ bool indirect_mode;
+ bool rup;
+ bool wup;
+ uint32_t illegal_factor;
+ }m_dma[3];
+
+ uint32_t dma_common_r(uint8_t offset,uint8_t level);
+ void dma_common_w(uint8_t offset,uint8_t level,uint32_t data);
+ void handle_dma_direct(uint8_t level);
+ void handle_dma_indirect(uint8_t level);
+ void update_dma_status(uint8_t level,bool state);
+ void dma_single_transfer(uint32_t src, uint32_t dst,uint8_t *src_shift);
+ void dma_start_factor_ack(uint8_t event);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SEGA_SCU, sega_scu_device)
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+
+#endif // MAME_MACHINE_SEGA_SCU_H
diff --git a/src/devices/machine/smpc.cpp b/src/devices/machine/smpc.cpp
index 85a49c5313b..6b2c9f8a733 100644
--- a/src/devices/machine/smpc.cpp
+++ b/src/devices/machine/smpc.cpp
@@ -231,7 +231,7 @@ void smpc_hle_device::static_set_region_code(device_t &device, uint8_t rgn)
{
smpc_hle_device &dev = downcast<smpc_hle_device &>(device);
dev.m_region_code = rgn;
-}
+}
void smpc_hle_device::static_set_control_port_tags(device_t &device, const char *tag1, const char *tag2)
{
diff --git a/src/mame/drivers/saturn.cpp b/src/mame/drivers/saturn.cpp
index 836e2e5bc26..5eb6fab7469 100644
--- a/src/mame/drivers/saturn.cpp
+++ b/src/mame/drivers/saturn.cpp
@@ -534,7 +534,7 @@ static ADDRESS_MAP_START( saturn_mem, AS_PROGRAM, 32, sat_console_state )
AM_RANGE(0x05e00000, 0x05e7ffff) AM_MIRROR(0x80000) AM_READWRITE(saturn_vdp2_vram_r, saturn_vdp2_vram_w)
AM_RANGE(0x05f00000, 0x05f7ffff) AM_READWRITE(saturn_vdp2_cram_r, saturn_vdp2_cram_w)
AM_RANGE(0x05f80000, 0x05fbffff) AM_READWRITE16(saturn_vdp2_regs_r, saturn_vdp2_regs_w,0xffffffff)
- AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE(saturn_scu_r, saturn_scu_w)
+ AM_RANGE(0x05fe0000, 0x05fe00cf) AM_DEVICE("scu", sega_scu_device, regs_map ) //AM_READWRITE(saturn_scu_r, saturn_scu_w)
AM_RANGE(0x06000000, 0x060fffff) AM_RAM AM_MIRROR(0x21f00000) AM_SHARE("workram_h")
AM_RANGE(0x20000000, 0x2007ffff) AM_ROM AM_SHARE("share6") // bios mirror
// AM_RANGE(0x22000000, 0x24ffffff) AM_ROM // Cartridge area mirror
@@ -548,14 +548,6 @@ static ADDRESS_MAP_START( sound_mem, AS_PROGRAM, 16, sat_console_state )
AM_RANGE(0x100000, 0x100fff) AM_DEVREADWRITE("scsp", scsp_device, read, write)
ADDRESS_MAP_END
-static ADDRESS_MAP_START( scudsp_mem, AS_PROGRAM, 32, sat_console_state )
- AM_RANGE(0x00, 0xff) AM_RAM
-ADDRESS_MAP_END
-
-static ADDRESS_MAP_START( scudsp_data, AS_DATA, 32, sat_console_state )
- AM_RANGE(0x00, 0xff) AM_RAM
-ADDRESS_MAP_END
-
INPUT_CHANGED_MEMBER(sat_console_state::tray_open)
{
@@ -595,63 +587,9 @@ void sat_console_state::nvram_init(nvram_device &nvram, void *data, size_t size)
memcpy(data, init, sizeof(init));
}
-void saturn_state::debug_scuirq_command(int ref, const std::vector<std::string> &params)
-{
- debugger_console con = machine().debugger().console();
- const char *const irqnames[16] = {
- "VBlank-in", "VBlank-out", "HBlank-in", "Timer 0", "Timer 1", "SCU DSP end", "Sound request", "SMPC", "Pad", "DMA lv 2", "DMA lv 1", "DMA lv 0", "DMA illegal", "VDP1 end", "A-Bus" };
-
-
- for(int irq_lv = 0;irq_lv<16;irq_lv++)
- con.printf("%s irq enabled: %s\n",irqnames[irq_lv],(m_scu.ism & (1 << irq_lv)) == 0 ? "1" : "0");
-}
-
-void saturn_state::debug_scudma_command(int ref, const std::vector<std::string> &params)
-{
- debugger_console con = machine().debugger().console();
-
- for(int ch=0;ch<3;ch++)
- {
- con.printf("DMA LV%02d: src = %08x dst = %08x size = %08x\n",ch,m_scu.src[ch],m_scu.dst[ch],m_scu.size[ch]);
- con.printf(" adds: src = %08x dst = %08x\n",m_scu.src_add[ch],m_scu.dst_add[ch]);
- con.printf("indirect: index = %08x\n",m_scu.index[ch]);
- con.printf(" enable: mask = %08x start factor = %08x\n",m_scu.enable_mask[ch],m_scu.start_factor[ch]);
- }
-}
-
-void saturn_state::debug_help_command(int ref, const std::vector<std::string> &params)
-{
- debugger_console con = machine().debugger().console();
-
- con.printf("Available Saturn commands:\n");
- con.printf(" saturn scudma -- pretty prints current state of SCU DMA registers\n");
- con.printf(" saturn scuirq -- pretty prints current state of SCU IRQ registers\n");
- con.printf(" saturn help -- this list\n");
-}
-
-
-void saturn_state::debug_commands(int ref, const std::vector<std::string> &params)
-{
- if (params.size() < 1)
- return;
-
- if (params[0] == "scudma")
- debug_scudma_command(ref, params);
- else if (params[0] == "scuirq")
- debug_scuirq_command(ref, params);
- else if (params[0] == "help")
- debug_help_command(ref, params);
-}
-
MACHINE_START_MEMBER(sat_console_state, saturn)
-{
- if (machine().debug_flags & DEBUG_FLAG_ENABLED)
- {
- using namespace std::placeholders;
- machine().debugger().console().register_command("saturn", CMDFLAG_NONE, 0, 1, 4, std::bind(&saturn_state::debug_commands, this, _1, _2));
- }
-
+{
machine().device<scsp_device>("scsp")->set_ram_base(m_sound_ram);
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x02400000, 0x027fffff, read32_delegate(FUNC(sat_console_state::saturn_null_ram_r),this), write32_delegate(FUNC(sat_console_state::saturn_null_ram_w),this));
@@ -708,7 +646,7 @@ MACHINE_START_MEMBER(sat_console_state, saturn)
}
// save states
- save_pointer(NAME(m_scu_regs.get()), 0x100/4);
+// save_pointer(NAME(m_scu_regs.get()), 0x100/4);
save_item(NAME(m_en_68k));
save_item(NAME(m_scsp_last_line));
save_item(NAME(m_vdp2.odd));
@@ -736,9 +674,6 @@ MACHINE_RESET_MEMBER(sat_console_state,saturn)
// don't let the slave cpu and the 68k go anywhere
m_slave->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
m_audiocpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
- m_scudsp->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
-
- scu_reset();
m_en_68k = 0;
@@ -861,12 +796,8 @@ static MACHINE_CONFIG_START( saturn )
MCFG_CPU_ADD("audiocpu", M68000, 11289600) //256 x 44100 Hz = 11.2896 MHz
MCFG_CPU_PROGRAM_MAP(sound_mem)
- MCFG_CPU_ADD("scudsp", SCUDSP, MASTER_CLOCK_352/4) // 14 MHz
- MCFG_CPU_PROGRAM_MAP(scudsp_mem)
- MCFG_CPU_DATA_MAP(scudsp_data)
- MCFG_SCUDSP_OUT_IRQ_CB(WRITELINE(saturn_state, scudsp_end_w))
- MCFG_SCUDSP_IN_DMA_CB(READ16(saturn_state, scudsp_dma_r))
- MCFG_SCUDSP_OUT_DMA_CB(WRITE16(saturn_state, scudsp_dma_w))
+ MCFG_SEGA_SCU_ADD("scu")
+ sega_scu_device::static_set_hostcpu(*device, "maincpu");
// SH-1
@@ -884,7 +815,7 @@ static MACHINE_CONFIG_START( saturn )
MCFG_SMPC_HLE_SYSTEM_RESET_CB(WRITELINE(saturn_state, system_reset_w))
MCFG_SMPC_HLE_SYSTEM_HALT_CB(WRITELINE(saturn_state, system_halt_w))
MCFG_SMPC_HLE_DOT_SELECT_CB(WRITELINE(saturn_state, dot_select_w))
- MCFG_SMPC_HLE_IRQ_HANDLER_CB(WRITELINE(saturn_state, smpc_irq_w))
+ MCFG_SMPC_HLE_IRQ_HANDLER_CB(DEVWRITELINE("scu", sega_scu_device, smpc_irq_w))
MCFG_MACHINE_START_OVERRIDE(sat_console_state,saturn)
MCFG_MACHINE_RESET_OVERRIDE(sat_console_state,saturn)
@@ -908,7 +839,7 @@ static MACHINE_CONFIG_START( saturn )
MCFG_SOUND_ADD("scsp", SCSP, 0)
MCFG_SCSP_IRQ_CB(WRITE8(saturn_state, scsp_irq))
- MCFG_SCSP_MAIN_IRQ_CB(WRITELINE(saturn_state, scsp_to_main_irq))
+ MCFG_SCSP_MAIN_IRQ_CB(DEVWRITELINE("scu", sega_scu_device, sound_req_w))
MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
@@ -1000,7 +931,7 @@ void sat_console_state::saturn_init_driver(int rgn)
m_minit_boost_timeslice = attotime::zero;
m_sinit_boost_timeslice = attotime::zero;
- m_scu_regs = make_unique_clear<uint32_t[]>(0x100/4);
+// m_scu_regs = make_unique_clear<uint32_t[]>(0x100/4);
m_backupram = make_unique_clear<uint8_t[]>(0x8000);
}
diff --git a/src/mame/drivers/stv.cpp b/src/mame/drivers/stv.cpp
index 2cdeb6b6ab0..c89ec8c6b05 100644
--- a/src/mame/drivers/stv.cpp
+++ b/src/mame/drivers/stv.cpp
@@ -425,7 +425,7 @@ DRIVER_INIT_MEMBER(stv_state,stv)
m_minit_boost_timeslice = attotime::zero;
m_sinit_boost_timeslice = attotime::zero;
- m_scu_regs = std::make_unique<uint32_t[]>(0x100/4);
+// m_scu_regs = std::make_unique<uint32_t[]>(0x100/4);
m_backupram = std::make_unique<uint8_t[]>(0x8000);
memset(m_backupram.get(), 0, sizeof(uint8_t) * 0x8000);
@@ -999,7 +999,7 @@ static ADDRESS_MAP_START( stv_mem, AS_PROGRAM, 32, stv_state )
AM_RANGE(0x05e00000, 0x05e7ffff) AM_MIRROR(0x80000) AM_READWRITE(saturn_vdp2_vram_r, saturn_vdp2_vram_w)
AM_RANGE(0x05f00000, 0x05f7ffff) AM_READWRITE(saturn_vdp2_cram_r, saturn_vdp2_cram_w)
AM_RANGE(0x05f80000, 0x05fbffff) AM_READWRITE16(saturn_vdp2_regs_r, saturn_vdp2_regs_w,0xffffffff)
- AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE(saturn_scu_r, saturn_scu_w)
+ AM_RANGE(0x05fe0000, 0x05fe00cf) AM_DEVICE("scu", sega_scu_device, regs_map ) //AM_READWRITE(saturn_scu_r, saturn_scu_w)
AM_RANGE(0x06000000, 0x060fffff) AM_RAM AM_MIRROR(0x21f00000) AM_SHARE("workram_h")
AM_RANGE(0x20000000, 0x2007ffff) AM_ROM AM_SHARE("share6") // bios mirror
AM_RANGE(0x22000000, 0x24ffffff) AM_ROM AM_SHARE("share7") // cart mirror
@@ -1012,14 +1012,6 @@ static ADDRESS_MAP_START( sound_mem, AS_PROGRAM, 16, stv_state )
AM_RANGE(0x100000, 0x100fff) AM_DEVREADWRITE("scsp", scsp_device, read, write)
ADDRESS_MAP_END
-static ADDRESS_MAP_START( scudsp_mem, AS_PROGRAM, 32, stv_state )
- AM_RANGE(0x00, 0xff) AM_RAM
-ADDRESS_MAP_END
-
-static ADDRESS_MAP_START( scudsp_data, AS_DATA, 32, stv_state )
- AM_RANGE(0x00, 0xff) AM_RAM
-ADDRESS_MAP_END
-
/********************************************
@@ -1088,12 +1080,8 @@ static MACHINE_CONFIG_START( stv )
MCFG_CPU_ADD("audiocpu", M68000, 11289600) //11.2896 MHz
MCFG_CPU_PROGRAM_MAP(sound_mem)
- MCFG_CPU_ADD("scudsp", SCUDSP, MASTER_CLOCK_352/4) // 14 MHz
- MCFG_CPU_PROGRAM_MAP(scudsp_mem)
- MCFG_CPU_DATA_MAP(scudsp_data)
- MCFG_SCUDSP_OUT_IRQ_CB(WRITELINE(saturn_state, scudsp_end_w))
- MCFG_SCUDSP_IN_DMA_CB(READ16(saturn_state, scudsp_dma_r))
- MCFG_SCUDSP_OUT_DMA_CB(WRITE16(saturn_state, scudsp_dma_w))
+ MCFG_SEGA_SCU_ADD("scu")
+ sega_scu_device::static_set_hostcpu(*device, "maincpu");
MCFG_SMPC_HLE_ADD("smpc", XTAL_4MHz)
smpc_hle_device::static_set_region_code(*device, 0);
@@ -1108,7 +1096,7 @@ static MACHINE_CONFIG_START( stv )
MCFG_SMPC_HLE_SYSTEM_RESET_CB(WRITELINE(saturn_state, system_reset_w))
MCFG_SMPC_HLE_SYSTEM_HALT_CB(WRITELINE(saturn_state, system_halt_w))
MCFG_SMPC_HLE_DOT_SELECT_CB(WRITELINE(saturn_state, dot_select_w))
- MCFG_SMPC_HLE_IRQ_HANDLER_CB(WRITELINE(saturn_state, smpc_irq_w))
+ MCFG_SMPC_HLE_IRQ_HANDLER_CB(DEVWRITELINE("scu", sega_scu_device, smpc_irq_w))
MCFG_MACHINE_START_OVERRIDE(stv_state,stv)
MCFG_MACHINE_RESET_OVERRIDE(stv_state,stv)
@@ -1133,7 +1121,7 @@ static MACHINE_CONFIG_START( stv )
MCFG_SOUND_ADD("scsp", SCSP, 0)
MCFG_SCSP_IRQ_CB(WRITE8(saturn_state, scsp_irq))
- MCFG_SCSP_MAIN_IRQ_CB(WRITELINE(saturn_state, scsp_to_main_irq))
+ MCFG_SCSP_MAIN_IRQ_CB(DEVWRITELINE("scu", sega_scu_device, sound_req_w))
MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
@@ -1215,7 +1203,6 @@ MACHINE_RESET_MEMBER(stv_state,stv)
// don't let the slave cpu and the 68k go anywhere
m_slave->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
m_audiocpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
- m_scudsp->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
std::string region_tag;
if (m_cart1)
@@ -1247,8 +1234,6 @@ MACHINE_RESET_MEMBER(stv_state,stv)
m_prev_gamebank_select = 0xff;
- scu_reset();
-
m_vdp2.old_crmd = -1;
m_vdp2.old_tvmd = -1;
}
@@ -1291,7 +1276,7 @@ MACHINE_START_MEMBER(stv_state,stv)
machine().device<scsp_device>("scsp")->set_ram_base(m_sound_ram);
// save states
- save_pointer(NAME(m_scu_regs.get()), 0x100/4);
+// save_pointer(NAME(m_scu_regs.get()), 0x100/4);
save_item(NAME(m_en_68k));
save_item(NAME(m_prev_gamebank_select));
save_item(NAME(m_port_sel));
diff --git a/src/mame/etc/template_device.h b/src/mame/etc/template_device.h
index 8085a8dd9fd..a9942990655 100644
--- a/src/mame/etc/template_device.h
+++ b/src/mame/etc/template_device.h
@@ -40,7 +40,7 @@ public:
protected:
// device-level overrides
//virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_add_mconfig() override;
+ virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual void device_reset() override;
};
diff --git a/src/mame/includes/saturn.h b/src/mame/includes/saturn.h
index 9d55ab78301..0720076c759 100644
--- a/src/mame/includes/saturn.h
+++ b/src/mame/includes/saturn.h
@@ -5,7 +5,7 @@
#include "machine/timer.h"
#include "cpu/m68000/m68000.h"
#include "cpu/adsp2100/adsp2100.h"
-#include "cpu/scudsp/scudsp.h"
+#include "machine/sega_scu.h"
#include "machine/smpc.h"
#include "cpu/sh/sh2.h"
@@ -39,7 +39,7 @@ public:
m_slave(*this, "slave"),
m_audiocpu(*this, "audiocpu"),
m_smpc_hle(*this, "smpc"),
- m_scudsp(*this, "scudsp"),
+ m_scu(*this, "scu"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette")
{
@@ -53,7 +53,7 @@ public:
memory_region *m_cart_reg[4];
std::unique_ptr<uint8_t[]> m_backupram;
- std::unique_ptr<uint32_t[]> m_scu_regs;
+// std::unique_ptr<uint32_t[]> m_scu_regs;
std::unique_ptr<uint16_t[]> m_vdp2_regs;
std::unique_ptr<uint32_t[]> m_vdp2_vram;
std::unique_ptr<uint32_t[]> m_vdp2_cram;
@@ -62,7 +62,7 @@ public:
uint8_t m_en_68k;
-
+ #if 0
struct {
uint32_t src[3]; /* Source DMA lv n address*/
uint32_t dst[3]; /* Destination DMA lv n address*/
@@ -72,13 +72,14 @@ public:
uint32_t index[3];
int start_factor[3];
uint8_t enable_mask[3];
+ uint32_t illegal_factor[3];
uint32_t ist;
uint32_t ism;
- uint32_t illegal_factor[3];
uint32_t status;
}m_scu;
-
- void scu_reset(void);
+ #endif
+
+// void scu_reset(void);
int m_minit_boost;
int m_sinit_boost;
@@ -131,7 +132,7 @@ public:
required_device<sh2_device> m_slave;
required_device<m68000_base_device> m_audiocpu;
required_device<smpc_hle_device> m_smpc_hle;
- required_device<scudsp_cpu_device> m_scudsp;
+ required_device<sega_scu_device> m_scu;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
@@ -141,17 +142,17 @@ public:
TIMER_DEVICE_CALLBACK_MEMBER(saturn_scanline);
TIMER_DEVICE_CALLBACK_MEMBER(saturn_slave_scanline);
- void scu_do_transfer(uint8_t event);
- void scu_test_pending_irq();
- DECLARE_READ32_MEMBER(saturn_scu_r);
- DECLARE_WRITE32_MEMBER(saturn_scu_w);
- TIMER_CALLBACK_MEMBER(dma_lv0_ended);
- TIMER_CALLBACK_MEMBER(dma_lv1_ended);
- TIMER_CALLBACK_MEMBER(dma_lv2_ended);
+// void scu_do_transfer(uint8_t event);
+// void scu_test_pending_irq();
+// DECLARE_READ32_MEMBER(saturn_scu_r);
+// DECLARE_WRITE32_MEMBER(saturn_scu_w);
+// TIMER_CALLBACK_MEMBER(dma_lv0_ended);
+// TIMER_CALLBACK_MEMBER(dma_lv1_ended);
+// TIMER_CALLBACK_MEMBER(dma_lv2_ended);
TIMER_CALLBACK_MEMBER(vdp1_draw_end);
- void scu_single_transfer(address_space &space, uint32_t src, uint32_t dst,uint8_t *src_shift);
- void scu_dma_direct(address_space &space, uint8_t dma_ch);
- void scu_dma_indirect(address_space &space,uint8_t dma_ch);
+// void scu_single_transfer(address_space &space, uint32_t src, uint32_t dst,uint8_t *src_shift);
+// void scu_dma_direct(address_space &space, uint8_t dma_ch);
+// void scu_dma_indirect(address_space &space,uint8_t dma_ch);
DECLARE_WRITE16_MEMBER(saturn_soundram_w);
DECLARE_READ16_MEMBER(saturn_soundram_r);
DECLARE_WRITE32_MEMBER(minit_w);
@@ -160,7 +161,6 @@ public:
DECLARE_WRITE32_MEMBER(saturn_sinit_w);
DECLARE_READ8_MEMBER(saturn_backupram_r);
DECLARE_WRITE8_MEMBER(saturn_backupram_w);
- DECLARE_WRITE_LINE_MEMBER(scsp_to_main_irq);
DECLARE_WRITE8_MEMBER(scsp_irq);
int m_scsp_last_line;
@@ -616,9 +616,9 @@ public:
DECLARE_WRITE_LINE_MEMBER(m68k_reset_callback);
- DECLARE_WRITE_LINE_MEMBER(scudsp_end_w);
- DECLARE_READ16_MEMBER(scudsp_dma_r);
- DECLARE_WRITE16_MEMBER(scudsp_dma_w);
+// DECLARE_WRITE_LINE_MEMBER(scudsp_end_w);
+// DECLARE_READ16_MEMBER(scudsp_dma_r);
+// DECLARE_WRITE16_MEMBER(scudsp_dma_w);
// SMPC HLE delegates
DECLARE_WRITE_LINE_MEMBER(master_sh2_reset_w);
@@ -628,18 +628,17 @@ public:
DECLARE_WRITE_LINE_MEMBER(system_reset_w);
DECLARE_WRITE_LINE_MEMBER(system_halt_w);
DECLARE_WRITE_LINE_MEMBER(dot_select_w);
- DECLARE_WRITE_LINE_MEMBER(smpc_irq_w);
- void debug_scudma_command(int ref, const std::vector<std::string> &params);
- void debug_scuirq_command(int ref, const std::vector<std::string> &params);
- void debug_help_command(int ref, const std::vector<std::string> &params);
- void debug_commands(int ref, const std::vector<std::string> &params);
+// void debug_scudma_command(int ref, const std::vector<std::string> &params);
+// void debug_scuirq_command(int ref, const std::vector<std::string> &params);
+// void debug_help_command(int ref, const std::vector<std::string> &params);
+// void debug_commands(int ref, const std::vector<std::string> &params);
};
-#define MASTER_CLOCK_352 57272720
-#define MASTER_CLOCK_320 53693174
+#define MASTER_CLOCK_352 XTAL_57_2727MHz
+#define MASTER_CLOCK_320 XTAL_53_693175MHz
#define CEF_1 m_vdp1_regs[0x010/2]|=0x0002
#define CEF_0 m_vdp1_regs[0x010/2]&=~0x0002
#define BEF_1 m_vdp1_regs[0x010/2]|=0x0001
@@ -648,20 +647,5 @@ public:
#define STV_VDP1_VBE ((STV_VDP1_TVMR & 0x0008) >> 3)
#define STV_VDP1_TVM ((STV_VDP1_TVMR & 0x0007) >> 0)
-#define IRQ_VBLANK_IN 1 << 0
-#define IRQ_VBLANK_OUT 1 << 1
-#define IRQ_HBLANK_IN 1 << 2
-#define IRQ_TIMER_0 1 << 3
-#define IRQ_TIMER_1 1 << 4
-#define IRQ_DSP_END 1 << 5
-#define IRQ_SOUND_REQ 1 << 6
-#define IRQ_SMPC 1 << 7
-#define IRQ_PAD 1 << 8
-#define IRQ_DMALV2 1 << 9
-#define IRQ_DMALV1 1 << 10
-#define IRQ_DMALV0 1 << 11
-#define IRQ_DMAILL 1 << 12
-#define IRQ_VDP1_END 1 << 13
-#define IRQ_ABUS 1 << 15
GFXDECODE_EXTERN( stv );
diff --git a/src/mame/includes/stv.h b/src/mame/includes/stv.h
index a235c1f5881..3c28545fcb5 100644
--- a/src/mame/includes/stv.h
+++ b/src/mame/includes/stv.h
@@ -143,8 +143,8 @@ public:
};
-#define MASTER_CLOCK_352 57272720
-#define MASTER_CLOCK_320 53693174
+//#define MASTER_CLOCK_352 57272720
+//#define MASTER_CLOCK_320 53693174
#define CEF_1 m_vdp1_regs[0x010/2]|=0x0002
#define CEF_0 m_vdp1_regs[0x010/2]&=~0x0002
#define BEF_1 m_vdp1_regs[0x010/2]|=0x0001
@@ -153,20 +153,4 @@ public:
#define STV_VDP1_VBE ((STV_VDP1_TVMR & 0x0008) >> 3)
#define STV_VDP1_TVM ((STV_VDP1_TVMR & 0x0007) >> 0)
-#define IRQ_VBLANK_IN 1 << 0
-#define IRQ_VBLANK_OUT 1 << 1
-#define IRQ_HBLANK_IN 1 << 2
-#define IRQ_TIMER_0 1 << 3
-#define IRQ_TIMER_1 1 << 4
-#define IRQ_DSP_END 1 << 5
-#define IRQ_SOUND_REQ 1 << 6
-#define IRQ_SMPC 1 << 7
-#define IRQ_PAD 1 << 8
-#define IRQ_DMALV2 1 << 9
-#define IRQ_DMALV1 1 << 10
-#define IRQ_DMALV0 1 << 11
-#define IRQ_DMAILL 1 << 12
-#define IRQ_VDP1_END 1 << 13
-#define IRQ_ABUS 1 << 15
-
GFXDECODE_EXTERN( stv );
diff --git a/src/mame/machine/saturn.cpp b/src/mame/machine/saturn.cpp
index 7907f5bfd21..fcea8b20e19 100644
--- a/src/mame/machine/saturn.cpp
+++ b/src/mame/machine/saturn.cpp
@@ -54,504 +54,6 @@
#define LOG_IRQ 0
#define LOG_IOGA 0
-/**************************************************************************************/
-
-/*
-
-SCU Handling
-
-*/
-
-/**********************************************************************************
-SCU Register Table
-offset,relative address
-Registers are in long words.
-===================================================================================
-0 0000 Level 0 DMA Set Register
-1 0004
-2 0008
-3 000c
-4 0010
-5 0014
-6 0018
-7 001c
-8 0020 Level 1 DMA Set Register
-9 0024
-10 0028
-11 002c
-12 0030
-13 0034
-14 0038
-15 003c
-16 0040 Level 2 DMA Set Register
-17 0044
-18 0048
-19 004c
-20 0050
-21 0054
-22 0058
-23 005c
-24 0060 DMA Forced Stop
-25 0064
-26 0068
-27 006c
-28 0070 <Free>
-29 0074
-30 0078
-31 007c DMA Status Register
-32 0080 DSP Program Control Port
-33 0084 DSP Program RAM Data Port
-34 0088 DSP Data RAM Address Port
-35 008c DSP Data RAM Data Port
-36 0090 Timer 0 Compare Register
-37 0094 Timer 1 Set Data Register
-38 0098 Timer 1 Mode Register
-39 009c <Free>
-40 00a0 Interrupt Mask Register
-41 00a4 Interrupt Status Register
-42 00a8 A-Bus Interrupt Acknowledge
-43 00ac <Free>
-44 00b0 A-Bus Set Register
-45 00b4
-46 00b8 A-Bus Refresh Register
-47 00bc <Free>
-48 00c0
-49 00c4 SCU SDRAM Select Register
-50 00c8 SCU Version Register
-51 00cc <Free>
-52 00cf
-===================================================================================
-DMA Status Register(32-bit):
-xxxx xxxx x--- xx-- xx-- xx-- xx-- xx-- UNUSED
----- ---- -x-- ---- ---- ---- ---- ---- DMA DSP-Bus access
----- ---- --x- ---- ---- ---- ---- ---- DMA B-Bus access
----- ---- ---x ---- ---- ---- ---- ---- DMA A-Bus access
----- ---- ---- --x- ---- ---- ---- ---- DMA lv 1 interrupt
----- ---- ---- ---x ---- ---- ---- ---- DMA lv 0 interrupt
----- ---- ---- ---- --x- ---- ---- ---- DMA lv 2 in stand-by
----- ---- ---- ---- ---x ---- ---- ---- DMA lv 2 in operation
----- ---- ---- ---- ---- --x- ---- ---- DMA lv 1 in stand-by
----- ---- ---- ---- ---- ---x ---- ---- DMA lv 1 in operation
----- ---- ---- ---- ---- ---- --x- ---- DMA lv 0 in stand-by
----- ---- ---- ---- ---- ---- ---x ---- DMA lv 0 in operation
----- ---- ---- ---- ---- ---- ---- --x- DSP side DMA in stand-by
----- ---- ---- ---- ---- ---- ---- ---x DSP side DMA in operation
-
-**********************************************************************************/
-/*
-DMA TODO:
--Remove CD transfer DMA hack (tied with CD block bug(s)?)
--Add timings(but how fast are each DMA?).
--Add level priority & DMA status register.
-*/
-
-#define DIRECT_MODE(_lv_) (!(m_scu_regs[5+(_lv_*8)] & 0x01000000))
-#define INDIRECT_MODE(_lv_) (m_scu_regs[5+(_lv_*8)] & 0x01000000)
-#define DRUP(_lv_) (m_scu_regs[5+(_lv_*8)] & 0x00010000)
-#define DWUP(_lv_) (m_scu_regs[5+(_lv_*8)] & 0x00000100)
-
-/*These macros sets the various DMA status flags.*/
-#define DnMV_1(_ch_) m_scu.status|=(0x10 << 4 * _ch_)
-#define DnMV_0(_ch_) m_scu.status&=~(0x10 << 4 * _ch_)
-
-/*For area checking*/
-#define BIOS_BUS(var) (var & 0x07f00000) == 0
-#define ABUS(_lv_) ((m_scu.src[_lv_] & 0x07000000) >= 0x02000000) && ((m_scu.src[_lv_] & 0x07000000) <= 0x04000000)
-#define BBUS(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x05a00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05ffffff)
-#define VDP1_REGS(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x05d00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05dfffff)
-#define VDP2(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x05e00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05fdffff)
-#define WORK_RAM_L(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x00200000) && ((scu_##_lv_ & 0x07ffffff) <= 0x002fffff)
-#define WORK_RAM_H(var) (var & 0x07000000) == 0x06000000
-#define SOUND_RAM(_lv_) ((scu_##_lv_ & 0x07ffffff) >= 0x05a00000) && ((scu_##_lv_ & 0x07ffffff) <= 0x05afffff)
-
-void saturn_state::scu_do_transfer(uint8_t event)
-{
- address_space &space = machine().device("maincpu")->memory().space(AS_PROGRAM);
- int i;
-
- for(i=0;i<3;i++)
- {
- if(m_scu.enable_mask[i] && m_scu.start_factor[i] == event)
- {
- if(DIRECT_MODE(i)) { scu_dma_direct(space,i); }
- else { scu_dma_indirect(space,i); }
- }
- }
-}
-
-/* test pending irqs */
-void saturn_state::scu_test_pending_irq()
-{
- int i;
- const int irq_level[32] = { 0xf, 0xe, 0xd, 0xc,
- 0xb, 0xa, 0x9, 0x8,
- 0x8, 0x6, 0x6, 0x5,
- 0x3, 0x2, -1, -1,
- 0x7, 0x7, 0x7, 0x7,
- 0x4, 0x4, 0x4, 0x4,
- 0x1, 0x1, 0x1, 0x1,
- 0x1, 0x1, 0x1, 0x1 };
-
- for(i=0;i<32;i++)
- {
- if((!(m_scu.ism & 1 << i)) && (m_scu.ist & 1 << i))
- {
- if(irq_level[i] != -1) /* TODO: cheap check for undefined irqs */
- {
- m_maincpu->set_input_line_and_vector(irq_level[i], HOLD_LINE, 0x40 + i);
- m_scu.ist &= ~(1 << i);
- return; /* avoid spurious irqs, correct? */
- }
- }
- }
-}
-
-READ32_MEMBER(saturn_state::saturn_scu_r)
-{
- uint32_t res;
-
- /*TODO: write only registers must return 0 or open bus */
- switch(offset)
- {
- case 0x5c/4:
- // Super Major League and Shin Megami Tensei - Akuma Zensho reads from there (undocumented), DMA status mirror?
- if(LOG_SCU && !machine().side_effect_disabled()) logerror("(PC=%08x) DMA status reg read\n",space.device().safe_pc());
- res = m_scu.status;
- break;
- case 0x7c/4:
- if(LOG_SCU && !machine().side_effect_disabled()) logerror("(PC=%08x) DMA status reg read\n",space.device().safe_pc());
- res = m_scu.status;
- break;
- case 0x80/4:
- res = m_scudsp->program_control_r(space, 0, mem_mask);
- break;
- case 0x8c/4:
- if(LOG_SCU && !machine().side_effect_disabled()) logerror( "DSP mem read at %08X\n", m_scu_regs[34]);
- res = m_scudsp->ram_address_r(space, 0, mem_mask);
- break;
- case 0xa0/4:
- if(LOG_SCU && !machine().side_effect_disabled()) logerror("(PC=%08x) IRQ mask reg read %08x MASK=%08x\n",space.device().safe_pc(),mem_mask,m_scu_regs[0xa0/4]);
- res = m_scu.ism;
- break;
- case 0xa4/4:
- if(LOG_SCU && !machine().side_effect_disabled()) logerror("(PC=%08x) IRQ status reg read MASK=%08x IST=%08x | ISM=%08x\n",space.device().safe_pc(),mem_mask,m_scu.ist,m_scu.ism);
- /* TODO: Bug! trips an HW fault. Basically, it tries to read the IST bit 1 with that irq enabled.
- Densetsu no Ogre Battle doesn't like this, so it needs investigation ...
- */
-// res = m_scu.ist | ~m_scu.ism;
- res = m_scu.ist;
- break;
- case 0xc8/4:
- if(LOG_SCU && !machine().side_effect_disabled()) logerror("(PC=%08x) SCU version reg read\n",space.device().safe_pc());
- res = 0x00000004;/*SCU Version 4, OK? */
- break;
- default:
- if(LOG_SCU && !machine().side_effect_disabled()) logerror("(PC=%08x) SCU reg read at %d = %08x\n",space.device().safe_pc(),offset,m_scu_regs[offset]);
- res = m_scu_regs[offset];
- break;
- }
-
- return res;
-}
-
-#define DMA_CH ((offset & 0x18) / 8)
-
-WRITE32_MEMBER(saturn_state::saturn_scu_w)
-{
- COMBINE_DATA(&m_scu_regs[offset]);
-
- switch(offset)
- {
- /*LV 0 DMA*/
- case 0x00/4: case 0x20/4: case 0x40/4: m_scu.src[DMA_CH] = ((m_scu_regs[offset] & 0x07ffffff) >> 0); break;
- case 0x04/4: case 0x24/4: case 0x44/4: m_scu.dst[DMA_CH] = ((m_scu_regs[offset] & 0x07ffffff) >> 0); break;
- case 0x08/4: case 0x28/4: case 0x48/4: m_scu.size[DMA_CH] = ((m_scu_regs[offset] & ((offset == 2) ? 0x000fffff : 0xfff)) >> 0); break;
- case 0x0c/4: case 0x2c/4: case 0x4c/4:
- m_scu.src_add[DMA_CH] = (m_scu_regs[offset] & 0x100) ? 4 : 0;
- m_scu.dst_add[DMA_CH] = 1 << (m_scu_regs[offset] & 7);
- if(m_scu.dst_add[DMA_CH] == 1) { m_scu.dst_add[DMA_CH] = 0; }
- break;
- case 0x10/4: case 0x30/4: case 0x50/4:
- m_scu.enable_mask[DMA_CH] = (data & 0x100) >> 8;
- if(m_scu.enable_mask[DMA_CH] && m_scu.start_factor[DMA_CH] == 7 && m_scu_regs[offset] & 1)
- {
- if(DIRECT_MODE(DMA_CH)) { scu_dma_direct(space,DMA_CH); }
- else { scu_dma_indirect(space,DMA_CH); }
- m_scu_regs[offset]&=~1;//disable starting bit.
- }
- break;
- case 0x14/4: case 0x34/4: case 0x54/4:
- if(INDIRECT_MODE(DMA_CH))
- {
- //if(LOG_SCU) logerror("Indirect Mode DMA lv %d set\n",DMA_CH);
- if(!DWUP(DMA_CH)) m_scu.index[DMA_CH] = m_scu.dst[DMA_CH];
- }
-
- m_scu.start_factor[DMA_CH] = m_scu_regs[offset] & 7;
- break;
-
- case 0x60/4:
- if(LOG_SCU) logerror("DMA Forced Stop Register set = %02x\n",m_scu_regs[24]);
- break;
- case 0x7c/4: if(LOG_SCU) logerror("Warning: DMA status WRITE! Offset %02x(%d)\n",offset*4,offset); break;
- /*DSP section*/
- case 0x80/4:
- m_scudsp->program_control_w(space, 0, m_scu_regs[offset], mem_mask);
- if(LOG_SCU) logerror("SCU DSP: Program Control Port Access %08x\n",data);
- break;
- case 0x84/4:
- m_scudsp->program_w(space, 0, m_scu_regs[offset], mem_mask);
- if(LOG_SCU) logerror("SCU DSP: Program RAM Data Port Access %08x\n",data);
- break;
- case 0x88/4:
- m_scudsp->ram_address_control_w(space, 0,m_scu_regs[offset], mem_mask);
- if(LOG_SCU) logerror("SCU DSP: Data RAM Address Port Access %08x\n",data);
- break;
- case 0x8c/4:
- m_scudsp->ram_address_w(space, 0, m_scu_regs[offset], mem_mask);
- if(LOG_SCU) logerror("SCU DSP: Data RAM Data Port Access %08x\n",data);
- break;
- case 0x90/4: /*if(LOG_SCU) logerror("timer 0 compare data = %03x\n",m_scu_regs[36]);*/ break;
- case 0x94/4: /*if(LOG_SCU) logerror("timer 1 set data = %08x\n",m_scu_regs[37]);*/ break;
- case 0x98/4: /*if(LOG_SCU) logerror("timer 1 mode data = %08x\n",m_scu_regs[38]);*/ break;
- case 0xa0/4: /* IRQ mask */
- m_scu.ism = m_scu_regs[0xa0/4];
- scu_test_pending_irq();
- break;
- case 0xa4/4: /* IRQ control */
- if(LOG_SCU) logerror("PC=%08x IRQ status reg set:%08x %08x\n",space.device().safe_pc(),m_scu_regs[41],mem_mask);
- m_scu.ist &= m_scu_regs[offset];
- scu_test_pending_irq();
- break;
- case 0xa8/4:
- /* This sends an irq signal to the extra devices connected to the A-Bus, not really needed for now. */
- //if(LOG_SCU) logerror("A-Bus IRQ ACK %08x\n",m_scu_regs[42]);
- break;
- case 0xc4/4: if(LOG_SCU) logerror("SCU SDRAM set: %02x\n",m_scu_regs[49]); break;
- default: if(LOG_SCU) logerror("Warning: unused SCU reg set %d = %08x\n",offset,data);
- }
-}
-
-/*Lv 0 DMA end irq*/
-TIMER_CALLBACK_MEMBER(saturn_state::dma_lv0_ended )
-{
- if(!(m_scu.ism & IRQ_DMALV0))
- m_maincpu->set_input_line_and_vector(5, HOLD_LINE, 0x4b);
- else
- m_scu.ist |= (IRQ_DMALV0);
-
- DnMV_0(0);
- machine().scheduler().synchronize(); // force resync
-}
-
-/*Lv 1 DMA end irq*/
-TIMER_CALLBACK_MEMBER(saturn_state::dma_lv1_ended)
-{
- if(!(m_scu.ism & IRQ_DMALV1))
- m_maincpu->set_input_line_and_vector(6, HOLD_LINE, 0x4a);
- else
- m_scu.ist |= (IRQ_DMALV1);
-
- DnMV_0(1);
- machine().scheduler().synchronize(); // force resync
-}
-
-/*Lv 2 DMA end irq*/
-TIMER_CALLBACK_MEMBER(saturn_state::dma_lv2_ended)
-{
- if(!(m_scu.ism & IRQ_DMALV2))
- m_maincpu->set_input_line_and_vector(6, HOLD_LINE, 0x49);
- else
- m_scu.ist |= (IRQ_DMALV2);
-
- DnMV_0(2);
- machine().scheduler().synchronize(); // force resync
-}
-
-void saturn_state::scu_single_transfer(address_space &space, uint32_t src, uint32_t dst,uint8_t *src_shift)
-{
- uint32_t src_data;
-
- if(src & 1)
- {
- /* Road Blaster does a work ram h to color ram with offsetted source address, do some data rotation */
- src_data = ((space.read_dword(src & 0x07fffffc) & 0x00ffffff)<<8);
- src_data |= ((space.read_dword((src & 0x07fffffc)+4) & 0xff000000) >> 24);
- src_data >>= (*src_shift)*16;
- }
- else
- src_data = space.read_dword(src & 0x07fffffc) >> (*src_shift)*16;
-
- space.write_word(dst,src_data);
-
- *src_shift ^= 1;
-}
-
-void saturn_state::scu_dma_direct(address_space &space, uint8_t dma_ch)
-{
- uint32_t tmp_src,tmp_dst,total_size;
- uint8_t cd_transfer_flag;
-
- if(m_scu.src_add[dma_ch] == 0 || (m_scu.dst_add[dma_ch] != 2 && m_scu.dst_add[dma_ch] != 4))
- {
- if(LOG_SCU) printf("DMA lv %d transfer START\n"
- "Start %08x End %08x Size %04x\n",dma_ch,m_scu.src[dma_ch],m_scu.dst[dma_ch],m_scu.size[dma_ch]);
- if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",m_scu.src_add[dma_ch],m_scu.dst_add[dma_ch]);
- }
-
- /* Game Basic and World Cup 98 trips this, according to the docs the SCU can't transfer from BIOS area (can't communicate from/to that bus) */
- if(BIOS_BUS(m_scu.src[dma_ch]))
- {
- popmessage("Warning: SCU transfer from BIOS area, contact MAMEdev");
- if(!(m_scu.ism & IRQ_DMAILL))
- m_maincpu->set_input_line_and_vector(3, HOLD_LINE, 0x4c);
- else
- m_scu.ist |= (IRQ_DMAILL);
- return;
- }
-
- DnMV_1(dma_ch);
-
- /* max size */
- if(m_scu.size[dma_ch] == 0) { m_scu.size[dma_ch] = (dma_ch == 0) ? 0x00100000 : 0x1000; }
-
- tmp_src = tmp_dst = 0;
-
- total_size = m_scu.size[dma_ch];
- if(!(DRUP(dma_ch))) tmp_src = m_scu.src[dma_ch];
- if(!(DWUP(dma_ch))) tmp_dst = m_scu.dst[dma_ch];
-
- cd_transfer_flag = m_scu.src_add[dma_ch] == 0 && m_scu.src[dma_ch] == 0x05818000;
-
- /* TODO: Many games directly accesses CD-ROM register 0x05818000, it must be a dword access with current implementation otherwise it won't work */
- if(cd_transfer_flag)
- {
- int i;
- if(WORK_RAM_H(m_scu.dst[dma_ch]))
- m_scu.dst_add[dma_ch] = 4;
- else
- m_scu.dst_add[dma_ch] <<= 1;
-
- for (i = 0; i < m_scu.size[dma_ch];i+=m_scu.dst_add[dma_ch])
- {
- space.write_dword(m_scu.dst[dma_ch],space.read_dword(m_scu.src[dma_ch]));
- if(m_scu.dst_add[dma_ch] == 8)
- space.write_dword(m_scu.dst[dma_ch]+4,space.read_dword(m_scu.src[dma_ch]));
-
- m_scu.src[dma_ch]+=m_scu.src_add[dma_ch];
- m_scu.dst[dma_ch]+=m_scu.dst_add[dma_ch];
- }
- }
- else
- {
- int i;
- uint8_t src_shift;
-
- src_shift = ((m_scu.src[dma_ch] & 2) >> 1) ^ 1;
-
- for (i = 0; i < m_scu.size[dma_ch];i+=2)
- {
- scu_single_transfer(space,m_scu.src[dma_ch],m_scu.dst[dma_ch],&src_shift);
-
- if(src_shift)
- m_scu.src[dma_ch]+=m_scu.src_add[dma_ch];
-
- /* if target is Work RAM H, the add value is fixed, behaviour confirmed by Final Romance 2, Virtual Mahjong and Burning Rangers */
- m_scu.dst[dma_ch]+=(WORK_RAM_H(m_scu.dst[dma_ch])) ? 2 : m_scu.dst_add[dma_ch];
- }
- }
-
- /* Burning Rangers doesn't agree with this. */
-// m_scu.size[dma_ch] = 0;
- if(!(DRUP(dma_ch))) m_scu.src[dma_ch] = tmp_src;
- if(!(DWUP(dma_ch))) m_scu.dst[dma_ch] = tmp_dst;
-
- {
- /*TODO: Timing is a guess. */
- switch(dma_ch)
- {
- case 0: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv0_ended),this)); break;
- case 1: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv1_ended),this)); break;
- case 2: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv2_ended),this)); break;
- }
- }
-}
-
-void saturn_state::scu_dma_indirect(address_space &space,uint8_t dma_ch)
-{
- /*Helper to get out of the cycle*/
- uint8_t job_done = 0;
- /*temporary storage for the transfer data*/
- uint32_t tmp_src;
- uint32_t indirect_src,indirect_dst;
- int32_t indirect_size;
- uint32_t total_size = 0;
-
- DnMV_1(dma_ch);
-
- m_scu.index[dma_ch] = m_scu.dst[dma_ch];
-
- do{
- tmp_src = m_scu.index[dma_ch];
-
- indirect_size = space.read_dword(m_scu.index[dma_ch]);
- indirect_src = space.read_dword(m_scu.index[dma_ch]+8);
- indirect_dst = space.read_dword(m_scu.index[dma_ch]+4);
-
- /*Indirect Mode end factor*/
- if(indirect_src & 0x80000000)
- job_done = 1;
-
- if(m_scu.src_add[dma_ch] == 0 || (m_scu.dst_add[dma_ch] != 2))
- {
- if(LOG_SCU) printf("DMA lv %d indirect mode transfer START\n"
- "Index %08x Start %08x End %08x Size %04x\n",dma_ch,tmp_src,indirect_src,indirect_dst,indirect_size);
- if(LOG_SCU) printf("Start Add %04x Destination Add %04x\n",m_scu.src_add[dma_ch],m_scu.dst_add[dma_ch]);
- }
-
- indirect_src &=0x07ffffff;
- indirect_dst &=0x07ffffff;
- indirect_size &= ((dma_ch == 0) ? 0xfffff : 0x3ffff); //TODO: Guardian Heroes sets up a 0x23000 transfer for the FMV?
-
- if(indirect_size == 0) { indirect_size = (dma_ch == 0) ? 0x00100000 : 0x2000; }
-
- {
- int i;
- uint8_t src_shift;
-
- src_shift = ((indirect_src & 2) >> 1) ^ 1;
-
- for (i = 0; i < indirect_size;i+=2)
- {
- scu_single_transfer(space,indirect_src,indirect_dst,&src_shift);
-
- if(src_shift)
- indirect_src+=m_scu.src_add[dma_ch];
-
- indirect_dst+= (WORK_RAM_H(indirect_dst)) ? 2 : m_scu.dst_add[dma_ch];
- }
- }
-
- /* Guess: Size + data acquire (1 cycle for src/dst/size) */
- total_size += indirect_size + 3*4;
-
- //if(DRUP(0)) space.write_dword(tmp_src+8,m_scu.src[0]|job_done ? 0x80000000 : 0);
- //if(DWUP(0)) space.write_dword(tmp_src+4,m_scu.dst[0]);
-
- m_scu.index[dma_ch] = tmp_src+0xc;
-
- }while(job_done == 0);
-
- {
- /*TODO: change DMA into DRQ model. Timing is a guess. */
- switch(dma_ch)
- {
- case 0: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv0_ended),this)); break;
- case 1: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv1_ended),this)); break;
- case 2: machine().scheduler().timer_set(m_maincpu->cycles_to_attotime(total_size/4), timer_expired_delegate(FUNC(saturn_state::dma_lv2_ended),this)); break;
- }
- }
-}
/**************************************************************************************/
@@ -649,17 +151,6 @@ WRITE8_MEMBER(saturn_state::saturn_backupram_w)
m_backupram[offset >> 1] = data;
}
-void saturn_state::scu_reset(void)
-{
- m_scu.ism = 0xbfff;
- m_scu.ist = 0;
- m_scu.start_factor[0] = 7;
- m_scu.start_factor[1] = 7;
- m_scu.start_factor[2] = 7;
- m_scu.status = 0;
-}
-
-
WRITE_LINE_MEMBER(saturn_state::m68k_reset_callback)
{
@@ -687,21 +178,6 @@ WRITE8_MEMBER(saturn_state::scsp_irq)
}
}
-WRITE_LINE_MEMBER(saturn_state::scsp_to_main_irq)
-{
- if(state)
- {
- if(!(m_scu.ism & IRQ_SOUND_REQ))
- {
- m_maincpu->set_input_line_and_vector(9, HOLD_LINE, 0x46);
- scu_do_transfer(5);
- }
- else
- m_scu.ist |= (IRQ_SOUND_REQ);
- }
-}
-
-
/*
(Preliminary) explanation about this:
@@ -738,24 +214,11 @@ TIMER_DEVICE_CALLBACK_MEMBER(saturn_state::saturn_scanline)
if(scanline == 0*y_step)
{
- if(!(m_scu.ism & IRQ_VBLANK_OUT))
- {
- m_maincpu->set_input_line_and_vector(0xe, HOLD_LINE, 0x41);
- scu_do_transfer(1);
- }
- else
- m_scu.ist |= (IRQ_VBLANK_OUT);
-
+ m_scu->vblank_out_w(1);
}
else if(scanline == vblank_line*y_step)
{
- if(!(m_scu.ism & IRQ_VBLANK_IN))
- {
- m_maincpu->set_input_line_and_vector(0xf, HOLD_LINE ,0x40);
- scu_do_transfer(0);
- }
- else
- m_scu.ist |= (IRQ_VBLANK_IN);
+ m_scu->vblank_in_w(1);
// flip odd bit here
m_vdp2.odd ^= 1;
@@ -764,13 +227,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(saturn_state::saturn_scanline)
}
else if((scanline % y_step) == 0 && scanline < vblank_line*y_step)
{
- if(!(m_scu.ism & IRQ_HBLANK_IN))
- {
- m_maincpu->set_input_line_and_vector(0xd, HOLD_LINE, 0x42);
- scu_do_transfer(2);
- }
- else
- m_scu.ist |= (IRQ_HBLANK_IN);
+ m_scu->hblank_in_w(1);
}
if(scanline == (vblank_line+1)*y_step)
@@ -784,41 +241,10 @@ TIMER_DEVICE_CALLBACK_MEMBER(saturn_state::saturn_scanline)
// VDP1 timing needs some HW work anyway so I'm currently firing VDP1 after 8 scanlines for now, will de-anon the timers in a later stage.
if(scanline == (vblank_line+8)*y_step)
{
- if(!(m_scu.ism & IRQ_VDP1_END))
- {
- m_maincpu->set_input_line_and_vector(0x2, HOLD_LINE, 0x4d);
- scu_do_transfer(6);
- }
- else
- m_scu.ist |= (IRQ_VDP1_END);
+ m_scu->vdp1_end_w(1);
}
- if(scanline == (m_scu_regs[36] & 0x3ff)*y_step)
- {
- if(!(m_scu.ism & IRQ_TIMER_0))
- {
- m_maincpu->set_input_line_and_vector(0xc, HOLD_LINE, 0x43 );
- scu_do_transfer(3);
- }
- else
- m_scu.ist |= (IRQ_TIMER_0);
- }
-
- /* TODO: this isn't completely correct */
- if(m_scu_regs[38] & 0x1)
- {
- if((!(m_scu_regs[38] & 0x100) && (scanline % y_step) == 0) ||
- ((m_scu_regs[38] & 0x100) && (scanline == (m_scu_regs[36] & 0x3ff)*y_step)))
- {
- if(!(m_scu.ism & IRQ_TIMER_1))
- {
- m_maincpu->set_input_line_and_vector(0xb, HOLD_LINE, 0x44 );
- scu_do_transfer(4);
- }
- else
- m_scu.ist |= (IRQ_TIMER_1);
- }
- }
+ m_scu->check_scanline_timers(scanline, y_step);
}
TIMER_DEVICE_CALLBACK_MEMBER(saturn_state::saturn_slave_scanline )
@@ -900,37 +326,6 @@ GFXDECODE_START( stv )
GFXDECODE_ENTRY( nullptr, 0, tiles16x16x8_layout, 0x00, (0x08*(2+1)) )
GFXDECODE_END
-WRITE_LINE_MEMBER(saturn_state::scudsp_end_w)
-{
- if(state)
- {
- if(!(m_scu.ism & IRQ_DSP_END))
- m_maincpu->set_input_line_and_vector(0xa, HOLD_LINE, 0x45);
- else
- m_scu.ist |= (IRQ_DSP_END);
- }
-}
-
-READ16_MEMBER(saturn_state::scudsp_dma_r)
-{
- address_space &program = m_maincpu->space(AS_PROGRAM);
- offs_t addr = offset;
-
-// printf("%08x\n",addr);
-
- return program.read_word(addr,mem_mask);
-}
-
-
-WRITE16_MEMBER(saturn_state::scudsp_dma_w)
-{
- address_space &program = m_maincpu->space(AS_PROGRAM);
- offs_t addr = offset;
-
-// printf("%08x %02x\n",addr,data);
-
- program.write_word(addr, data,mem_mask);
-}
WRITE_LINE_MEMBER( saturn_state::master_sh2_reset_w )
{
@@ -962,7 +357,7 @@ WRITE_LINE_MEMBER( saturn_state::system_reset_w )
// TODO: actually send a device reset signal to the connected devices
/*Only backup ram and SMPC ram are retained after that this command is issued.*/
- memset(m_scu_regs.get() ,0x00,0x000100);
+ m_scu->reset();
memset(m_sound_ram,0x00,0x080000);
memset(m_workram_h,0x00,0x100000);
memset(m_workram_l,0x00,0x100000);
@@ -993,15 +388,4 @@ WRITE_LINE_MEMBER(saturn_state::dot_select_w)
stv_vdp2_dynamic_res_change();
}
-// TODO: to move into SCU device
-WRITE_LINE_MEMBER(saturn_state::smpc_irq_w)
-{
- if(!state)
- return;
-
- if(!(m_scu.ism & IRQ_SMPC))
- m_maincpu->set_input_line_and_vector(8, HOLD_LINE, 0x47);
- else
- m_scu.ist |= (IRQ_SMPC);
-}