summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/smpc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/smpc.cpp')
-rw-r--r--src/devices/machine/smpc.cpp345
1 files changed, 167 insertions, 178 deletions
diff --git a/src/devices/machine/smpc.cpp b/src/devices/machine/smpc.cpp
index c62e65e1703..e70ab757dc7 100644
--- a/src/devices/machine/smpc.cpp
+++ b/src/devices/machine/smpc.cpp
@@ -160,14 +160,16 @@ SMPC NVRAM contents:
*/
#include "emu.h"
-#include "machine/smpc.h"
+#include "smpc.h"
#include "screen.h"
#include "coreutil.h"
-#define LOG_SMPC 0
-#define LOG_PAD_CMD 0
+#define LOG_PAD_CMD (1U << 1)
+#define VERBOSE (0)
+#include "logmacro.h"
+
//**************************************************************************
// GLOBAL VARIABLES
@@ -180,7 +182,7 @@ DEFINE_DEVICE_TYPE(SMPC_HLE, smpc_hle_device, "smpc_hle", "Sega Saturn SMPC HLE
// "uplift_submaps unhandled case: range straddling slots."
void smpc_hle_device::smpc_regs(address_map &map)
{
-// ADDRESS_MAP_UNMAP_HIGH
+// map.unmap_value_high();
map(0x00, 0x0d).w(FUNC(smpc_hle_device::ireg_w));
map(0x1f, 0x1f).w(FUNC(smpc_hle_device::command_register_w));
map(0x20, 0x5f).r(FUNC(smpc_hle_device::oreg_r));
@@ -203,25 +205,26 @@ void smpc_hle_device::smpc_regs(address_map &map)
//-------------------------------------------------
smpc_hle_device::smpc_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, SMPC_HLE, tag, owner, clock),
- device_memory_interface(mconfig, *this),
- m_space_config("regs", ENDIANNESS_LITTLE, 8, 7, 0, address_map_constructor(FUNC(smpc_hle_device::smpc_regs), this)),
- m_mini_nvram(*this, "smem"),
- m_mshres(*this),
- m_mshnmi(*this),
- m_sshres(*this),
- m_sndres(*this),
- m_sysres(*this),
- m_syshalt(*this),
- m_dotsel(*this),
- m_pdr1_read(*this),
- m_pdr2_read(*this),
- m_pdr1_write(*this),
- m_pdr2_write(*this),
- m_irq_line(*this),
- m_ctrl1(*this, finder_base::DUMMY_TAG),
- m_ctrl2(*this, finder_base::DUMMY_TAG),
- m_screen(*this, finder_base::DUMMY_TAG)
+ : device_t(mconfig, SMPC_HLE, tag, owner, clock)
+ , device_memory_interface(mconfig, *this)
+ , device_rtc_interface(mconfig, *this)
+ , m_space_config("regs", ENDIANNESS_LITTLE, 8, 7, 0, address_map_constructor(FUNC(smpc_hle_device::smpc_regs), this))
+ , m_mini_nvram(*this, "smem")
+ , m_mshres(*this)
+ , m_mshnmi(*this)
+ , m_sshres(*this)
+ , m_sndres(*this)
+ , m_sysres(*this)
+ , m_syshalt(*this)
+ , m_dotsel(*this)
+ , m_pdr1_read(*this, 0xff)
+ , m_pdr2_read(*this, 0xff)
+ , m_pdr1_write(*this)
+ , m_pdr2_write(*this)
+ , m_irq_line(*this)
+ , m_ctrl1(*this, finder_base::DUMMY_TAG)
+ , m_ctrl2(*this, finder_base::DUMMY_TAG)
+ , m_screen(*this, finder_base::DUMMY_TAG)
{
m_has_ctrl_ports = false;
}
@@ -244,27 +247,10 @@ void smpc_hle_device::device_add_mconfig(machine_config &config)
void smpc_hle_device::device_start()
{
- system_time systime;
- machine().base_datetime(systime);
-
// check if SMEM has valid data via byte 4 in the array, if not then simulate a battery backup fail
// (-> call the RTC / Language select menu for Saturn)
m_mini_nvram->set_base(&m_smem, 5);
- m_mshres.resolve_safe();
- m_mshnmi.resolve_safe();
- m_sshres.resolve_safe();
- m_sndres.resolve_safe();
- m_sysres.resolve_safe();
- m_syshalt.resolve_safe();
- m_dotsel.resolve_safe();
- m_irq_line.resolve_safe();
-
- m_pdr1_read.resolve_safe(0xff);
- m_pdr2_read.resolve_safe(0xff);
- m_pdr1_write.resolve_safe();
- m_pdr2_write.resolve_safe();
-
save_item(NAME(m_sf));
save_item(NAME(m_sr));
save_item(NAME(m_ddr1));
@@ -285,18 +271,10 @@ void smpc_hle_device::device_start()
save_item(NAME(m_rtc_data));
save_item(NAME(m_smem));
- m_cmd_timer = timer_alloc(COMMAND_ID);
- m_rtc_timer = timer_alloc(RTC_ID);
- m_intback_timer = timer_alloc(INTBACK_ID);
- m_sndres_timer = timer_alloc(SNDRES_ID);
-
- m_rtc_data[0] = DectoBCD(systime.local_time.year / 100);
- m_rtc_data[1] = DectoBCD(systime.local_time.year % 100);
- m_rtc_data[2] = (systime.local_time.weekday << 4) | (systime.local_time.month+1);
- m_rtc_data[3] = DectoBCD(systime.local_time.mday);
- m_rtc_data[4] = DectoBCD(systime.local_time.hour);
- m_rtc_data[5] = DectoBCD(systime.local_time.minute);
- m_rtc_data[6] = DectoBCD(systime.local_time.second);
+ m_cmd_timer = timer_alloc(FUNC(smpc_hle_device::handle_command), this);
+ m_rtc_timer = timer_alloc(FUNC(smpc_hle_device::handle_rtc_increment), this);
+ m_intback_timer = timer_alloc(FUNC(smpc_hle_device::intback_continue_request), this);
+ m_sndres_timer = timer_alloc(FUNC(smpc_hle_device::sound_reset), this);
}
@@ -328,6 +306,22 @@ void smpc_hle_device::device_reset()
m_rtc_timer->adjust(attotime::zero, 0, attotime::from_seconds(1));
}
+
+//-------------------------------------------------
+// rtc_clock_updated - update clock with real time
+//-------------------------------------------------
+
+void smpc_hle_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+ m_rtc_data[0] = DectoBCD(year / 100);
+ m_rtc_data[1] = DectoBCD(year % 100);
+ m_rtc_data[2] = ((day_of_week - 1) << 4) | month;
+ m_rtc_data[3] = DectoBCD(day);
+ m_rtc_data[4] = DectoBCD(hour);
+ m_rtc_data[5] = DectoBCD(minute);
+ m_rtc_data[6] = DectoBCD(second);
+}
+
device_memory_interface::space_config_vector smpc_hle_device::memory_space_config() const
{
return space_config_vector {
@@ -340,7 +334,7 @@ device_memory_interface::space_config_vector smpc_hle_device::memory_space_confi
// READ/WRITE HANDLERS
//**************************************************************************
-WRITE8_MEMBER( smpc_hle_device::ireg_w )
+void smpc_hle_device::ireg_w(offs_t offset, uint8_t data)
{
if (!(offset & 1)) // avoid writing to even bytes
return;
@@ -353,13 +347,13 @@ WRITE8_MEMBER( smpc_hle_device::ireg_w )
{
if(data & 0x40)
{
- if(LOG_PAD_CMD) printf("SMPC: BREAK request\n");
+ LOGMASKED(LOG_PAD_CMD, "SMPC: BREAK request\n");
sr_ack();
m_intback_stage = 0;
}
else if(data & 0x80)
{
- if(LOG_PAD_CMD) printf("SMPC: CONTINUE request\n");
+ LOGMASKED(LOG_PAD_CMD, "SMPC: CONTINUE request\n");
m_intback_timer->adjust(attotime::from_usec(700)); // TODO: is timing correct?
@@ -371,7 +365,7 @@ WRITE8_MEMBER( smpc_hle_device::ireg_w )
}
}
-READ8_MEMBER( smpc_hle_device::oreg_r )
+uint8_t smpc_hle_device::oreg_r(offs_t offset)
{
if (!(offset & 1)) // avoid reading to even bytes (TODO: is it 0s or 1s?)
return 0x00;
@@ -379,38 +373,38 @@ READ8_MEMBER( smpc_hle_device::oreg_r )
return m_oreg[offset >> 1];
}
-READ8_MEMBER( smpc_hle_device::status_register_r )
+uint8_t smpc_hle_device::status_register_r()
{
return m_sr;
}
-READ8_MEMBER( smpc_hle_device::status_flag_r )
+uint8_t smpc_hle_device::status_flag_r()
{
// bit 3: CD enable related?
return (m_sf<<0) | (m_cd_sf<<3);
}
-WRITE8_MEMBER( smpc_hle_device::status_flag_w )
+void smpc_hle_device::status_flag_w(uint8_t data)
{
m_sf = BIT(data,0);
m_cd_sf = false;
}
-READ8_MEMBER( smpc_hle_device::pdr1_r )
+uint8_t smpc_hle_device::pdr1_r()
{
uint8_t res = (m_pdr1_read() & ~m_ddr1) | m_pdr1_readback;
return res;
}
-READ8_MEMBER( smpc_hle_device::pdr2_r )
+uint8_t smpc_hle_device::pdr2_r()
{
uint8_t res = (m_pdr2_read() & ~m_ddr2) | m_pdr2_readback;
return res;
}
-WRITE8_MEMBER( smpc_hle_device::pdr1_w )
+void smpc_hle_device::pdr1_w(uint8_t data)
{
// pins defined as output returns in input
m_pdr1_readback = (data & m_ddr1);
@@ -420,7 +414,7 @@ WRITE8_MEMBER( smpc_hle_device::pdr1_w )
m_pdr1_readback |= data & 0x80;
}
-WRITE8_MEMBER( smpc_hle_device::pdr2_w )
+void smpc_hle_device::pdr2_w(uint8_t data)
{
// pins defined as output returns in input
m_pdr2_readback = (data & m_ddr2);
@@ -430,23 +424,23 @@ WRITE8_MEMBER( smpc_hle_device::pdr2_w )
m_pdr2_readback |= data & 0x80;
}
-WRITE8_MEMBER( smpc_hle_device::ddr1_w )
+void smpc_hle_device::ddr1_w(uint8_t data)
{
m_ddr1 = data & 0x7f;
}
-WRITE8_MEMBER( smpc_hle_device::ddr2_w )
+void smpc_hle_device::ddr2_w(uint8_t data)
{
m_ddr2 = data & 0x7f;
}
-WRITE8_MEMBER( smpc_hle_device::iosel_w )
+void smpc_hle_device::iosel_w(uint8_t data)
{
m_iosel1 = BIT(data,0);
m_iosel2 = BIT(data,1);
}
-WRITE8_MEMBER( smpc_hle_device::exle_w )
+void smpc_hle_device::exle_w(uint8_t data)
{
m_exle1 = BIT(data,0);
m_exle2 = BIT(data,1);
@@ -499,12 +493,12 @@ inline void smpc_hle_device::irq_request()
// TODO: trampolines that needs to go away
-READ8_MEMBER( smpc_hle_device::read )
+uint8_t smpc_hle_device::read(offs_t offset)
{
return this->space().read_byte(offset);
}
-WRITE8_MEMBER( smpc_hle_device::write )
+void smpc_hle_device::write(offs_t offset, uint8_t data)
{
this->space().write_byte(offset,data);
}
@@ -513,7 +507,7 @@ WRITE8_MEMBER( smpc_hle_device::write )
// Command simulation
//**************************************************************************
-WRITE8_MEMBER( smpc_hle_device::command_register_w )
+void smpc_hle_device::command_register_w(uint8_t data)
{
// don't send a command if previous one is still in progress
// ST-V tries to send a sysres command if OREG31 doesn't return the ack command
@@ -564,124 +558,119 @@ WRITE8_MEMBER( smpc_hle_device::command_register_w )
}
-void smpc_hle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(smpc_hle_device::handle_command)
{
- switch(id)
+ switch(m_comreg)
{
- case COMMAND_ID:
- {
- switch(m_comreg)
- {
- case 0x00: // MSHON
- // enable Master SH2
- m_mshres(m_comreg & 1);
- break;
-
- case 0x02: // SSHON
- case 0x03: // SSHOFF
- // enable or disable Slave SH2
- m_sshres(m_comreg & 1);
- break;
-
- case 0x06: // SNDON
- case 0x07: // SNDOFF
- // enable or disable 68k
- m_sndres(m_comreg & 1);
- break;
-
- case 0x08: // CDON
- case 0x09: // CDOFF
- // ...
- m_command_in_progress = false;
- m_oreg[31] = m_comreg;
- sf_ack(true); //clear hand-shake flag (TODO: diagnostic wants this to have bit 3 high)
- return;
-
-// case 0x0a: // NETLINKON
-// case 0x0b: // NETLINKOFF
-
- case 0x0d: // SYSRES
- // send a 1 -> 0 to device reset lines
- m_sysres(1);
- m_sysres(0);
-
- // send a 1 -> 0 transition to reset line (was PULSE_LINE)
- m_mshres(1);
- m_mshres(0);
- break;
-
- case 0x0e: // CKCHG352
- case 0x0f: // CKCHG320
- m_dotsel(m_comreg & 1);
-
- // send a NMI to Master SH2 if enabled
- if(m_NMI_reset == false)
- master_sh2_nmi();
-
- // assert Slave SH2 line
- m_sshres(1);
- // clear PLL system halt
- m_syshalt(0);
-
- // setup the new dot select
- m_cur_dotsel = (m_comreg & 1) ^ 1;
- break;
-
- case 0x10: // INTBACK
- resolve_intback();
- return;
-
- case 0x16: // SETTIME
- {
- for(int i=0;i<7;i++)
- m_rtc_data[i] = m_ireg[i];
- break;
- }
-
- case 0x17: // SETSMEM
- {
- for(int i=0;i<4;i++)
- m_smem[i] = m_ireg[i];
-
- // clear the SETIME variable, simulate a cr2032 battery alive in the system
- m_smem[4] = 0xff;
- break;
- }
-
- case 0x18: // NMIREQ
- // NMI is unconditionally requested
- master_sh2_nmi();
- break;
-
- case 0x19: // RESENAB
- case 0x1a: // RESDISA
- m_NMI_reset = m_comreg & 1;
- break;
-
- default:
- logerror("%s unemulated %02x command\n",this->tag(),m_comreg);
- return;
- }
+ case 0x00: // MSHON
+ // enable Master SH2
+ m_mshres(m_comreg & 1);
+ break;
+
+ case 0x02: // SSHON
+ case 0x03: // SSHOFF
+ // enable or disable Slave SH2
+ m_sshres(m_comreg & 1);
+ break;
+ case 0x06: // SNDON
+ case 0x07: // SNDOFF
+ // enable or disable 68k
+ m_sndres(m_comreg & 1);
+ break;
+
+ case 0x08: // CDON
+ case 0x09: // CDOFF
+ // ...
m_command_in_progress = false;
m_oreg[31] = m_comreg;
- sf_ack(false);
+ // TODO: diagnostic also wants this to have bit 3 high
+ sf_ack(true); //set hand-shake flag
+ return;
+
+ case 0x0a: // NETLINKON
+ // TODO: understand where NetLink actually lies and implement delegation accordingly
+ // (is it really an SH1 device like suggested by the space access or it overlays on CS2 bus?)
+ popmessage("%s: NetLink enabled", this->tag());
+ [[fallthrough]];
+ case 0x0b: // NETLINKOFF
+ break;
+
+ case 0x0d: // SYSRES
+ // send a 1 -> 0 to device reset lines
+ m_sysres(1);
+ m_sysres(0);
+
+ // send a 1 -> 0 transition to reset line (was PULSE_LINE)
+ m_mshres(1);
+ m_mshres(0);
+ break;
+
+ case 0x0e: // CKCHG352
+ case 0x0f: // CKCHG320
+ m_dotsel(m_comreg & 1);
+
+ // assert Slave SH2 line
+ m_sshres(1);
+ // clear PLL system halt
+ m_syshalt(0);
+
+ // setup the new dot select
+ m_cur_dotsel = (m_comreg & 1) ^ 1;
+
+ // send a NMI to Master SH2 if enabled
+ // it is unconditionally requested:
+ // bigichig, capgen1, capgen4 and capgen5 triggers a SLEEP opcode from BIOS call and expects this to wake them up.
+ //if(m_NMI_reset == false)
+ master_sh2_nmi();
+ break;
+
+ case 0x10: // INTBACK
+ resolve_intback();
+ return;
+
+ case 0x16: // SETTIME
+ {
+ for(int i=0;i<7;i++)
+ m_rtc_data[i] = m_ireg[i];
+ break;
+ }
+
+ case 0x17: // SETSMEM
+ {
+ for(int i=0;i<4;i++)
+ m_smem[i] = m_ireg[i];
+
+ // clear the SETIME variable, simulate a cr2032 battery alive in the system
+ m_smem[4] = 0xff;
break;
}
- case INTBACK_ID: intback_continue_request(); break;
- case RTC_ID: handle_rtc_increment(); break;
+ case 0x18: // NMIREQ
+ // NMI is unconditionally requested
+ master_sh2_nmi();
+ break;
- // from m68k reset opcode trigger
- case SNDRES_ID:
- m_sndres(1);
- m_sndres(0);
+ case 0x19: // RESENAB
+ case 0x1a: // RESDISA
+ m_NMI_reset = m_comreg & 1;
break;
default:
- printf("%d\n",id);
- break;
+ logerror("%s: unemulated %02x command\n",this->tag(),m_comreg);
+ return;
}
+
+ m_command_in_progress = false;
+ m_oreg[31] = m_comreg;
+ sf_ack(false);
+}
+
+TIMER_CALLBACK_MEMBER(smpc_hle_device::sound_reset)
+{
+ // from m68k reset opcode trigger
+ m_sndres(1);
+ m_sndres(0);
}
void smpc_hle_device::resolve_intback()
@@ -741,7 +730,7 @@ void smpc_hle_device::resolve_intback()
m_intback_stage = (m_intback_buf[1] & 8) >> 3; // first peripheral
sr_set(0x40);
m_oreg[31] = 0x10;
- intback_continue_request();
+ intback_continue_request(0);
}
else
{
@@ -751,7 +740,7 @@ void smpc_hle_device::resolve_intback()
}
}
-void smpc_hle_device::intback_continue_request()
+TIMER_CALLBACK_MEMBER(smpc_hle_device::intback_continue_request)
{
if( m_has_ctrl_ports == true )
read_saturn_ports();
@@ -793,7 +782,7 @@ int smpc_hle_device::DectoBCD(int num)
// RTC handling
//**************************************************************************
-void smpc_hle_device::handle_rtc_increment()
+TIMER_CALLBACK_MEMBER(smpc_hle_device::handle_rtc_increment)
{
const uint8_t dpm[12] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 };
int year_num, year_count;