diff options
Diffstat (limited to 'src/devices/machine/smpc.cpp')
-rw-r--r-- | src/devices/machine/smpc.cpp | 345 |
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; |