diff options
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 |
commit | d4f7cfd631ed2e50452e75d8a20d0e752f51e963 (patch) | |
tree | 6020692608d583cb2cc19bc274372ee36793a216 | |
parent | 358f17ad4c9754694a1b5ea2dafdee2c95522717 (diff) |
saturn.cpp: Moved SCU related functions inside a device [Angelo Salese]
-rw-r--r-- | scripts/src/machine.lua | 12 | ||||
-rw-r--r-- | scripts/target/mame/arcade.lua | 1 | ||||
-rw-r--r-- | scripts/target/mame/mess.lua | 1 | ||||
-rw-r--r-- | src/devices/machine/sega_scu.cpp | 776 | ||||
-rw-r--r-- | src/devices/machine/sega_scu.h | 156 | ||||
-rw-r--r-- | src/devices/machine/smpc.cpp | 2 | ||||
-rw-r--r-- | src/mame/drivers/saturn.cpp | 85 | ||||
-rw-r--r-- | src/mame/drivers/stv.cpp | 29 | ||||
-rw-r--r-- | src/mame/etc/template_device.h | 2 | ||||
-rw-r--r-- | src/mame/includes/saturn.h | 72 | ||||
-rw-r--r-- | src/mame/includes/stv.h | 20 | ||||
-rw-r--r-- | src/mame/machine/saturn.cpp | 628 |
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> ¶ms) -{ - 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> ¶ms) -{ - 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> ¶ms) -{ - 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> ¶ms) -{ - 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> ¶ms); - void debug_scuirq_command(int ref, const std::vector<std::string> ¶ms); - void debug_help_command(int ref, const std::vector<std::string> ¶ms); - void debug_commands(int ref, const std::vector<std::string> ¶ms); +// void debug_scudma_command(int ref, const std::vector<std::string> ¶ms); +// void debug_scuirq_command(int ref, const std::vector<std::string> ¶ms); +// void debug_help_command(int ref, const std::vector<std::string> ¶ms); +// void debug_commands(int ref, const std::vector<std::string> ¶ms); }; -#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); -} |