summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Angelo Salese <angelosa@users.noreply.github.com>2011-06-30 13:43:46 +0000
committer Angelo Salese <angelosa@users.noreply.github.com>2011-06-30 13:43:46 +0000
commitd05d998ea5dbdf9e501b469e4d0f38a356aeb46b (patch)
treefc2011bad62416e28dc3595ed4ebbca07f95507c
parent5257d558665579e7f880610688072749a31dab71 (diff)
Port from MESS, nw
-rw-r--r--.gitattributes2
-rw-r--r--src/mame/drivers/saturn.c869
-rw-r--r--src/mame/includes/stv.h16
-rw-r--r--src/mame/machine/smpc.c717
-rw-r--r--src/mame/machine/smpc.h4
-rw-r--r--src/mame/mame.mak2
6 files changed, 816 insertions, 794 deletions
diff --git a/.gitattributes b/.gitattributes
index 5f38b16bf0a..42e348b2295 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -3929,6 +3929,8 @@ src/mame/machine/simpsons.c svneol=native#text/plain
src/mame/machine/slapfght.c svneol=native#text/plain
src/mame/machine/slapstic.c svneol=native#text/plain
src/mame/machine/slikshot.c svneol=native#text/plain
+src/mame/machine/smpc.c svneol=native#text/plain
+src/mame/machine/smpc.h svneol=native#text/plain
src/mame/machine/snes.c svneol=native#text/plain
src/mame/machine/snes7110.c svneol=native#text/plain
src/mame/machine/snesbsx.c svneol=native#text/plain
diff --git a/src/mame/drivers/saturn.c b/src/mame/drivers/saturn.c
index 351349eca67..4575071b16e 100644
--- a/src/mame/drivers/saturn.c
+++ b/src/mame/drivers/saturn.c
@@ -106,6 +106,7 @@ also has a DSP;
#include "sound/scsp.h"
#include "sound/cdda.h"
#include "machine/stvprot.h"
+#include "machine/smpc.h"
#include "includes/stv.h"
#include "imagedev/chd_cd.h"
#include "imagedev/cartslot.h"
@@ -114,11 +115,27 @@ also has a DSP;
/* TODO: do this in a verboselog style */
#define LOG_CDB 0
-#define LOG_SMPC 0
#define LOG_SCU 0
#define LOG_IRQ 0
#define LOG_IOGA 0
+static int DectoBCD(int num)
+{
+ int i, cnt = 0, tmp, res = 0;
+
+ while (num > 0) {
+ tmp = num;
+ while (tmp >= 10) tmp %= 10;
+ for (i=0; i<cnt; i++)
+ tmp *= 16;
+ res += tmp;
+ cnt++;
+ num /= 10;
+ }
+
+ return res;
+}
+
/**************************************************************************************/
/*to be added into a stv Header file,remember to remove all the static...*/
@@ -129,24 +146,6 @@ also has a DSP;
/*SMPC stuff*/
/*SCU stuff*/
-
-static struct
-{
- UINT8 vblank_out;
- UINT8 vblank_in;
- UINT8 hblank_in;
- UINT8 timer_0;
- UINT8 timer_1;
- UINT8 dsp_end;
- UINT8 sound_req;
- UINT8 smpc;
- UINT8 pad;
- UINT8 dma_end[3];
- UINT8 dma_ill;
- UINT8 vdp1_end;
- UINT8 abus;
-}stv_irq;
-
static void scu_do_transfer(running_machine &machine,UINT8 event);
static void scu_dma_direct(address_space *space, UINT8 dma_ch); /*DMA level 0 direct transfer function*/
static void scu_dma_indirect(address_space *space, UINT8 dma_ch); /*DMA level 0 indirect transfer function*/
@@ -182,722 +181,6 @@ if(state->m_scu_regs[42] & 1)//IRQ ACK
/**************************************************************************************/
-static int DectoBCD(int num)
-{
- int i, cnt = 0, tmp, res = 0;
-
- while (num > 0) {
- tmp = num;
- while (tmp >= 10) tmp %= 10;
- for (i=0; i<cnt; i++)
- tmp *= 16;
- res += tmp;
- cnt++;
- num /= 10;
- }
-
- return res;
-}
-
-
-/* SMPC
- System Manager and Peripheral Control
-
-*/
-/* SMPC Addresses
-
-00
-01 -w Input Register 0 (IREG)
-02
-03 -w Input Register 1
-04
-05 -w Input Register 2
-06
-07 -w Input Register 3
-08
-09 -w Input Register 4
-0a
-0b -w Input Register 5
-0c
-0d -w Input Register 6
-0e
-0f
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-1a
-1b
-1c
-1d
-1e
-1f -w Command Register (COMREG)
-20
-21 r- Output Register 0 (OREG)
-22
-23 r- Output Register 1
-24
-25 r- Output Register 2
-26
-27 r- Output Register 3
-28
-29 r- Output Register 4
-2a
-2b r- Output Register 5
-2c
-2d r- Output Register 6
-2e
-2f r- Output Register 7
-30
-31 r- Output Register 8
-32
-33 r- Output Register 9
-34
-35 r- Output Register 10
-36
-37 r- Output Register 11
-38
-39 r- Output Register 12
-3a
-3b r- Output Register 13
-3c
-3d r- Output Register 14
-3e
-3f r- Output Register 15
-40
-41 r- Output Register 16
-42
-43 r- Output Register 17
-44
-45 r- Output Register 18
-46
-47 r- Output Register 19
-48
-49 r- Output Register 20
-4a
-4b r- Output Register 21
-4c
-4d r- Output Register 22
-4e
-4f r- Output Register 23
-50
-51 r- Output Register 24
-52
-53 r- Output Register 25
-54
-55 r- Output Register 26
-56
-57 r- Output Register 27
-58
-59 r- Output Register 28
-5a
-5b r- Output Register 29
-5c
-5d r- Output Register 30
-5e
-5f r- Output Register 31
-60
-61 r- SR
-62
-63 rw SF
-64
-65
-66
-67
-68
-69
-6a
-6b
-6c
-6d
-6e
-6f
-70
-71
-72
-73
-74
-75 rw PDR1
-76
-77 rw PDR2
-78
-79 -w DDR1
-7a
-7b -w DDR2
-7c
-7d -w IOSEL2/1
-7e
-7f -w EXLE2/1
-*/
-
-static READ8_HANDLER( stv_SMPC_r8 )
-{
- saturn_state *state = space->machine().driver_data<saturn_state>();
- int return_data;
-
- return_data = state->m_smpc_ram[offset];
-
- if (offset == 0x61) // ?? many games need this or the controls don't work
- return_data = 0x20 ^ 0xff;
-
- if (offset == 0x75)//PDR1 read
- return_data = input_port_read(space->machine(), "DSW1");
-
- if (offset == 0x77)//PDR2 read
- return_data= (0xfe | space->machine().device<eeprom_device>("eeprom")->read_bit());
-
-// if (offset == 0x33) //country code
-// return_data = input_port_read(machine, "FAKE");
-
- //if(LOG_SMPC) logerror ("cpu %s (PC=%08X) SMPC: Read from Byte Offset %02x Returns %02x\n", space->device().tag(), cpu_get_pc(&space->device()), offset, return_data);
-
-
- return return_data;
-}
-
-static TIMER_CALLBACK( stv_bankswitch_state )
-{
- saturn_state *state = machine.driver_data<saturn_state>();
- static const char *const banknames[] = { "game0", "game1", "game2", "game3" };
- UINT8* game_region;
-
- if(state->m_prev_bankswitch != param)
- {
- game_region = machine.region(banknames[param])->base();
-
- if (game_region)
- memcpy(machine.region("abus")->base(), game_region, 0x3000000);
- else
- memset(machine.region("abus")->base(), 0x00, 0x3000000);
-
- state->m_prev_bankswitch = param;
- }
-}
-
-static void stv_select_game(running_machine &machine, int gameno)
-{
- machine.scheduler().timer_set(attotime::zero, FUNC(stv_bankswitch_state), gameno);
-}
-
-static void smpc_master_on(running_machine &machine)
-{
- saturn_state *state = machine.driver_data<saturn_state>();
-
- device_set_input_line(state->m_maincpu, INPUT_LINE_RESET, CLEAR_LINE);
-}
-
-static void smpc_slave_enable(running_machine &machine,UINT8 cmd)
-{
- saturn_state *state = machine.driver_data<saturn_state>();
-
- device_set_input_line(state->m_slave, INPUT_LINE_RESET, cmd ? ASSERT_LINE : CLEAR_LINE);
-}
-
-static void smpc_sound_enable(running_machine &machine,UINT8 cmd)
-{
- saturn_state *state = machine.driver_data<saturn_state>();
-
- device_set_input_line(state->m_audiocpu, INPUT_LINE_RESET, cmd ? ASSERT_LINE : CLEAR_LINE);
- state->m_en_68k = cmd ^ 1;
-}
-
-static void smpc_system_reset(running_machine &machine)
-{
- saturn_state *state = machine.driver_data<saturn_state>();
-
- /*Only backup ram and SMPC ram are retained after that this command is issued.*/
- memset(state->m_scu_regs ,0x00,0x000100);
- memset(state->m_scsp_regs,0x00,0x001000);
- memset(state->m_sound_ram,0x00,0x080000);
- memset(state->m_workram_h,0x00,0x100000);
- memset(state->m_workram_l,0x00,0x100000);
- memset(state->m_vdp2_regs,0x00,0x040000);
- memset(state->m_vdp2_vram,0x00,0x100000);
- memset(state->m_vdp2_cram,0x00,0x080000);
- memset(state->m_vdp1_vram,0x00,0x100000);
- //A-Bus
-
- device_set_input_line(state->m_maincpu, INPUT_LINE_RESET, PULSE_LINE);
-}
-
-static void smpc_change_clock(running_machine &machine, UINT8 cmd)
-{
- saturn_state *state = machine.driver_data<saturn_state>();
- UINT32 xtal;
-
- xtal = cmd ? MASTER_CLOCK_320 : MASTER_CLOCK_352;
-
- machine.device("maincpu")->set_unscaled_clock(xtal/2);
- machine.device("slave")->set_unscaled_clock(xtal/2);
-
- state->m_vdp2.dotsel = cmd ^ 1;
- stv_vdp2_dynamic_res_change(machine);
-
- device_set_input_line(state->m_maincpu, INPUT_LINE_NMI, PULSE_LINE); // ff said this causes nmi, should we set a timer then nmi?
- smpc_slave_enable(machine,1);
- /* TODO: VDP1 / VDP2 / SCU / SCSP default power ON values */
-}
-
-static void smpc_intbackhelper(running_machine &machine)
-{
- saturn_state *state = machine.driver_data<saturn_state>();
- int pad,i;
- static const char *const padnames[] = { "JOY1", "JOY2" };
-
- if (state->m_smpc.intback_stage == 1)
- {
- state->m_smpc.intback_stage++;
- return;
- }
-
-// if (LOG_SMPC) logerror("SMPC: providing PAD data for intback, pad %d\n", intback_stage-2);
- for(i=0;i<2;i++)
- {
- pad = input_port_read(machine, padnames[i]);
- state->m_smpc_ram[0x21+i*8] = 0xf1; // no tap, direct connect
- state->m_smpc_ram[0x23+i*8] = 0x02; // saturn pad
- state->m_smpc_ram[0x25+i*8] = pad>>8;
- state->m_smpc_ram[0x27+i*8] = pad & 0xff;
- }
-
- if (state->m_smpc.intback_stage == 3)
- {
- state->m_smpc.smpcSR = (0x80 | state->m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback
- }
- else
- {
- state->m_smpc.smpcSR = (0xe0 | state->m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback
- }
-
- state->m_smpc.intback_stage++;
-}
-
-/* sys_type 1 == STV, 0 == SATURN */
-static TIMER_CALLBACK( smpc_intback )
-{
- saturn_state *state = machine.driver_data<saturn_state>();
- system_time systime;
- machine.base_datetime(systime);
- UINT8 sys_type = param;
-
- state->m_smpc_ram[0x21] = (0x80) | ((state->m_NMI_reset & 1) << 6);
-
- if(sys_type == 0)
- {
- state->m_smpc_ram[0x23] = dec_2_bcd(systime.local_time.year / 100);
- state->m_smpc_ram[0x25] = dec_2_bcd(systime.local_time.year % 100);
- state->m_smpc_ram[0x27] = (systime.local_time.weekday << 4) | (systime.local_time.month + 1);
- state->m_smpc_ram[0x29] = dec_2_bcd(systime.local_time.mday);
- state->m_smpc_ram[0x2b] = dec_2_bcd(systime.local_time.hour);
- state->m_smpc_ram[0x2d] = dec_2_bcd(systime.local_time.minute);
- state->m_smpc_ram[0x2f] = dec_2_bcd(systime.local_time.second);
- }
-
- state->m_smpc_ram[0x31]=0x00; //?
-
- //state->m_smpc_ram[0x33]=input_port_read(space->machine(), "FAKE");
-
- state->m_smpc_ram[0x35]= 0 << 7 |
- state->m_vdp2.dotsel << 6 |
- 1 << 5 |
- 1 << 4 |
- 0 << 3 | //MSHNMI
- 1 << 2 |
- 0 << 1 | //SYSRES
- 0 << 0; //SOUNDRES
- state->m_smpc_ram[0x37]= 0 << 6; //CDRES
-
- state->m_smpc_ram[0x39]=sys_type ? 0xff : state->m_smpc.SMEM[0];
- state->m_smpc_ram[0x3b]=sys_type ? 0xff : state->m_smpc.SMEM[1];
- state->m_smpc_ram[0x3d]=sys_type ? 0xff : state->m_smpc.SMEM[2];
- state->m_smpc_ram[0x3f]=sys_type ? 0xff : state->m_smpc.SMEM[3];
-
- state->m_smpc_ram[0x41]=0xff;
- state->m_smpc_ram[0x43]=0xff;
- state->m_smpc_ram[0x45]=0xff;
- state->m_smpc_ram[0x47]=0xff;
- state->m_smpc_ram[0x49]=0xff;
- state->m_smpc_ram[0x4b]=0xff;
- state->m_smpc_ram[0x4d]=0xff;
- state->m_smpc_ram[0x4f]=0xff;
- state->m_smpc_ram[0x51]=0xff;
- state->m_smpc_ram[0x53]=0xff;
- state->m_smpc_ram[0x55]=0xff;
- state->m_smpc_ram[0x57]=0xff;
- state->m_smpc_ram[0x59]=0xff;
- state->m_smpc_ram[0x5b]=0xff;
- state->m_smpc_ram[0x5d]=0xff;
-
- if(sys_type == 0)
- {
- state->m_smpc.smpcSR = 0x60; // peripheral data ready, no reset, etc.
- state->m_smpc.pmode = state->m_smpc_ram[1]>>4;
-
- state->m_smpc.intback_stage = 2;
-
- smpc_intbackhelper(machine);
- }
-
- // /*This is for RTC,cartridge code and similar stuff...*/
- //if(LOG_SMPC) logerror ("Interrupt: System Manager (SMPC) at scanline %04x, Vector 0x47 Level 0x08\n",scanline);
- if(stv_irq.smpc)
- device_set_input_line_and_vector(state->m_maincpu, 8, HOLD_LINE, 0x47);
-}
-
-static void smpc_rtc_write(running_machine &machine)
-{
- saturn_state *state = machine.driver_data<saturn_state>();
- state->m_smpc_ram[0x2f] = state->m_smpc_ram[0x0d];
- state->m_smpc_ram[0x2d] = state->m_smpc_ram[0x0b];
- state->m_smpc_ram[0x2b] = state->m_smpc_ram[0x09];
- state->m_smpc_ram[0x29] = state->m_smpc_ram[0x07];
- state->m_smpc_ram[0x27] = state->m_smpc_ram[0x05];
- state->m_smpc_ram[0x25] = state->m_smpc_ram[0x03];
- state->m_smpc_ram[0x23] = state->m_smpc_ram[0x01];
-}
-
-static void smpc_memory_setting(running_machine &machine)
-{
- saturn_state *state = machine.driver_data<saturn_state>();
- state->m_smpc.SMEM[0] = state->m_smpc_ram[1];
- state->m_smpc.SMEM[1] = state->m_smpc_ram[3];
- state->m_smpc.SMEM[2] = state->m_smpc_ram[5];
- state->m_smpc.SMEM[3] = state->m_smpc_ram[7];
-}
-
-static void smpc_nmi_req(running_machine &machine)
-{
- saturn_state *state = machine.driver_data<saturn_state>();
-
- /*NMI is unconditionally requested?*/
- device_set_input_line(state->m_maincpu, INPUT_LINE_NMI, PULSE_LINE);
-}
-
-static void smpc_nmi_set(running_machine &machine,UINT8 cmd)
-{
- saturn_state *state = machine.driver_data<saturn_state>();
-
- state->m_NMI_reset = cmd ^ 1;
- state->m_smpc_ram[0x21] = (0x80) | ((state->m_NMI_reset & 1) << 6);
-}
-
-static WRITE8_HANDLER( stv_SMPC_w8 )
-{
- saturn_state *state = space->machine().driver_data<saturn_state>();
- system_time systime;
- space->machine().base_datetime(systime);
-
-// if(LOG_SMPC) logerror ("8-bit SMPC Write to Offset %02x with Data %02x\n", offset, data);
- state->m_smpc_ram[offset] = data;
-
- if(offset == 0x75)
- {
- /*
- -xx- ---- PDR1
- ---x ---- EEPROM write bit
- ---- x--- EEPROM CLOCK line
- ---- -x-- EEPROM CS line
- ---- --xx A-Bus bank bits
- */
- eeprom_device *eeprom = space->machine().device<eeprom_device>("eeprom");
- eeprom->set_clock_line((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
- eeprom->write_bit(data & 0x10);
- eeprom->set_cs_line((data & 0x04) ? CLEAR_LINE : ASSERT_LINE);
- state->m_stv_multi_bank = data & 3;
-
- stv_select_game(space->machine(), state->m_stv_multi_bank);
-
- state->m_smpc.PDR1 = (data & 0x60);
- }
-
- if(offset == 0x77)
- {
- /*
- -xx- ---- PDR2
- ---x ---- Enable Sound System (ACTIVE LOW)
- */
- //popmessage("PDR2 = %02x",state->m_smpc_ram[0x77]);
-
- if(LOG_SMPC) logerror("SMPC: M68k %s\n",(state->m_smpc_ram[0x77] & 0x10) ? "off" : "on");
- cputag_set_input_line(space->machine(), "audiocpu", INPUT_LINE_RESET, (state->m_smpc_ram[0x77] & 0x10) ? ASSERT_LINE : CLEAR_LINE);
- state->m_en_68k = ((state->m_smpc_ram[0x77] & 0x10) >> 4) ^ 1;
-
- //if(LOG_SMPC) logerror("SMPC: ram [0x77] = %02x\n",state->m_smpc_ram[0x77]);
- state->m_smpc.PDR2 = (data & 0x60);
- }
-
- if(offset == 0x7d)
- {
- /*
- ---- --x- IOSEL2 direct (1) / control mode (0) port select
- ---- ---x IOSEL1 direct (1) / control mode (0) port select
- */
- state->m_smpc.IOSEL1 = (state->m_smpc_ram[0x7d] & 1) >> 0;
- state->m_smpc.IOSEL2 = (state->m_smpc_ram[0x7d] & 2) >> 1;
- }
-
- if(offset == 0x7f)
- {
- //enable PAD irq & VDP2 external latch for port 1/2
- state->m_smpc.EXLE1 = (state->m_smpc_ram[0x7f] & 1) >> 0;
- state->m_smpc.EXLE2 = (state->m_smpc_ram[0x7f] & 2) >> 1;
- if(state->m_smpc.EXLE1 || state->m_smpc.EXLE2)
- {
- //if(LOG_SMPC) logerror ("Interrupt: PAD irq at scanline %04x, Vector 0x48 Level 0x08\n",scanline);
- //cputag_set_input_line_and_vector(space->machine(), "maincpu", 8, (stv_irq.pad) ? HOLD_LINE : CLEAR_LINE, 0x48);
- }
- }
-
- if (offset == 0x1f) // COMREG
- {
- switch (data)
- {
- case 0x00:
- if(LOG_SMPC) logerror ("SMPC: Master ON\n");
- smpc_master_on(space->machine());
- break;
- //in theory 0x01 is for Master OFF,but obviously is not used.
- case 0x02:
- case 0x03:
- if(LOG_SMPC) logerror ("SMPC: Slave %s\n",(data & 1) ? "off" : "on");
- smpc_slave_enable(space->machine(),(data & 1));
- break;
- case 0x06:
- case 0x07:
- if(LOG_SMPC) logerror ("SMPC: Sound %s, ignored\n",(data & 1) ? "off" : "on");
- break;
- /*CD (SH-1) ON/OFF,guess that this is needed for Sports Fishing games...*/
- //case 0x08:
- //case 0x09:
- case 0x0d:
- if(LOG_SMPC) logerror ("SMPC: System Reset\n");
- smpc_system_reset(space->machine());
- break;
- case 0x0e:
- case 0x0f:
- if(LOG_SMPC) logerror ("SMPC: Change Clock to %s\n",data & 1 ? "320" : "352");
- smpc_change_clock(space->machine(),data & 1);
- break;
- /*"Interrupt Back"*/
- case 0x10:
- if(LOG_SMPC) logerror ("SMPC: Status Acquire\n");
- space->machine().scheduler().timer_set(attotime::from_msec(16), FUNC(smpc_intback),1); //TODO: variable time
- break;
- /* RTC write*/
- case 0x16:
- if(LOG_SMPC) logerror("SMPC: RTC write\n");
- smpc_rtc_write(space->machine());
- break;
- /* SMPC memory setting*/
- case 0x17:
- if(LOG_SMPC) logerror ("SMPC: memory setting\n");
- //smpc_memory_setting(space->machine());
- break;
- case 0x18:
- if(LOG_SMPC) logerror ("SMPC: NMI request\n");
- smpc_nmi_req(space->machine());
- break;
- case 0x19:
- case 0x1a:
- if(LOG_SMPC) logerror ("SMPC: NMI %sable\n",data & 1 ? "Dis" : "En");
- smpc_nmi_set(space->machine(),data & 1);
- break;
- default:
- printf ("cpu '%s' (PC=%08X) SMPC: undocumented Command %02x\n", space->device().tag(), cpu_get_pc(&space->device()), data);
- }
-
- // we've processed the command, clear status flag
- state->m_smpc_ram[0x5f] = data; //read-back command
- state->m_smpc_ram[0x63] = 0x00;
- /*TODO:emulate the timing of each command...*/
- }
-}
-
-static READ8_HANDLER( saturn_SMPC_r8 )
-{
- saturn_state *state = space->machine().driver_data<saturn_state>();
- int return_data;
-
- return_data = state->m_smpc_ram[offset];
-
- if ((offset == 0x61))
- return_data = state->m_smpc.smpcSR;
-
- if (offset == 0x75 || offset == 0x77)//PDR1/2 read
- {
-/*
- PORT_START("JOY1")
- PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
- PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
- PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
- PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
- PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) // START
- PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 A") PORT_PLAYER(1) // A
- PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 B") PORT_PLAYER(1) // B
- PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P1 C") PORT_PLAYER(1) // C
- PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("P1 R") PORT_PLAYER(1) // R
- PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P1 X") PORT_PLAYER(1) // X
- PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P1 Y") PORT_PLAYER(1) // Y
- PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P1 Z") PORT_PLAYER(1) // Z
- PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("P1 L") PORT_PLAYER(1) // L
-*/
- if ((state->m_smpc.IOSEL1 && offset == 0x75) || (state->m_smpc.IOSEL2 && offset == 0x77))
- {
- int hshake;
- const int shift_bit[4] = { 4, 12, 8, 0 };
- const char *const padnames[] = { "JOY1", "JOY2" };
-
- if(offset == 0x75)
- hshake = (state->m_smpc.PDR1>>5) & 3;
- else
- hshake = (state->m_smpc.PDR2>>5) & 3;
-
- if (LOG_SMPC) logerror("SMPC: SH-2 direct mode, returning data for phase %d\n", hshake);
-
- return_data = 0x80 | 0x10 | ((input_port_read(space->machine(), padnames[offset == 0x77])>>shift_bit[hshake]) & 0xf);
- }
- }
-
- if (offset == 0x33) return_data = state->m_saturn_region;
-
- if (LOG_SMPC) logerror ("cpu %s (PC=%08X) SMPC: Read from Byte Offset %02x (%d) Returns %02x\n", space->device().tag(), cpu_get_pc(&space->device()), offset, offset>>1, return_data);
-
-
- return return_data;
-}
-
-static WRITE8_HANDLER( saturn_SMPC_w8 )
-{
- saturn_state *state = space->machine().driver_data<saturn_state>();
- system_time systime;
- UINT8 last;
- running_machine &machine = space->machine();
-
- /* get the current date/time from the core */
- machine.current_datetime(systime);
-
- if (LOG_SMPC) logerror ("8-bit SMPC Write to Offset %02x (reg %d) with Data %02x (prev %02x)\n", offset, offset>>1, data, state->m_smpc_ram[offset]);
-
-// if (offset == 0x7d) printf("IOSEL2 %d IOSEL1 %d\n", (data>>1)&1, data&1);
-
- last = state->m_smpc_ram[offset];
-
- if ((state->m_smpc.intback_stage > 0) && (offset == 1) && (((data ^ 0x80)&0x80) == (last&0x80)))
- {
- if (LOG_SMPC) logerror("SMPC: CONTINUE request, stage %d\n", state->m_smpc.intback_stage);
- if (state->m_smpc.intback_stage != 3)
- {
- state->m_smpc.intback_stage = 2;
- }
- smpc_intbackhelper(machine);
- device_set_input_line_and_vector(state->m_maincpu, 8, HOLD_LINE, 0x47);
- }
-
- if ((offset == 1) && (data & 0x40))
- {
- if (LOG_SMPC) logerror("SMPC: BREAK request\n");
- state->m_smpc.intback_stage = 0;
- }
-
- state->m_smpc_ram[offset] = data;
-
- if (offset == 0x75) // PDR1
- {
- state->m_smpc.PDR1 = (data & state->m_smpc_ram[0x79]);
- }
-
- if (offset == 0x77) // PDR2
- {
- state->m_smpc.PDR2 = (data & state->m_smpc_ram[0x7b]);
- }
-
- if(offset == 0x7d)
- {
- state->m_smpc.IOSEL1 = state->m_smpc_ram[0x7d] & 1;
- state->m_smpc.IOSEL2 = (state->m_smpc_ram[0x7d] & 2) >> 1;
- }
-
- if(offset == 0x7f)
- {
- //enable PAD irq & VDP2 external latch for port 1/2
- state->m_smpc.EXLE1 = (state->m_smpc_ram[0x7f] & 1) >> 0;
- state->m_smpc.EXLE2 = (state->m_smpc_ram[0x7f] & 2) >> 1;
- //if(state->m_smpc.EXLE1 || state->m_smpc.EXLE2)
- // cputag_set_input_line_and_vector(space->machine(), "maincpu", 8, (stv_irq.pad) ? HOLD_LINE : CLEAR_LINE, 0x48);
- }
-
- if (offset == 0x1f)
- {
- switch (data)
- {
- case 0x00:
- if(LOG_SMPC) logerror ("SMPC: Master ON\n");
- smpc_master_on(space->machine());
- break;
- //in theory 0x01 is for Master OFF
- case 0x02:
- case 0x03:
- if(LOG_SMPC) logerror ("SMPC: Slave %s\n",(data & 1) ? "off" : "on");
- smpc_slave_enable(space->machine(),data & 1);
- break;
- case 0x06:
- case 0x07:
- if(LOG_SMPC) logerror ("SMPC: Sound %s\n",(data & 1) ? "off" : "on");
- smpc_sound_enable(space->machine(),data & 1);
- break;
- /*CD (SH-1) ON/OFF,guess that this is needed for Sports Fishing games...*/
- //case 0x08:
- //case 0x09:
- case 0x0d:
- if(LOG_SMPC) logerror ("SMPC: System Reset\n");
- smpc_system_reset(space->machine());
- break;
- case 0x0e:
- case 0x0f:
- if(LOG_SMPC) logerror ("SMPC: Change Clock to %s\n",data & 1 ? "320" : "352");
- smpc_change_clock(space->machine(),data & 1);
- break;
- /*"Interrupt Back"*/
- case 0x10:
- if(LOG_SMPC) logerror ("SMPC: Status Acquire (IntBack)\n");
- space->machine().scheduler().timer_set(attotime::from_msec(16), FUNC(smpc_intback),0); //TODO: variable time
- break;
- /* RTC write*/
- case 0x16:
- if(LOG_SMPC) logerror("SMPC: RTC write\n");
- smpc_rtc_write(space->machine());
- break;
- /* SMPC memory setting*/
- case 0x17:
- if(LOG_SMPC) logerror ("SMPC: memory setting\n");
- smpc_memory_setting(space->machine());
- break;
- case 0x18:
- if(LOG_SMPC) logerror ("SMPC: NMI request\n");
- smpc_nmi_req(space->machine());
- break;
- case 0x19:
- case 0x1a:
- if(LOG_SMPC) logerror ("SMPC: NMI %sable\n",data & 1 ? "Dis" : "En");
- smpc_nmi_set(space->machine(),data & 1);
- break;
- default:
- printf ("cpu %s (PC=%08X) SMPC: undocumented Command %02x\n", space->device().tag(), cpu_get_pc(&space->device()), data);
- }
-
- // we've processed the command, clear status flag
- state->m_smpc_ram[0x5f] = data; //read-back for last command issued
- state->m_smpc_ram[0x63] = 0x00;
- /*TODO:emulate the timing of each command...*/
- }
-}
-
/*
I/O overview:
PORT-A 1st player inputs
@@ -1258,21 +541,21 @@ static READ32_HANDLER( saturn_scu_r )
{
if(LOG_SCU) logerror("(PC=%08x) IRQ status reg read %08x\n",cpu_get_pc(&space->device()),mem_mask);
- state->m_scu_regs[41] = (stv_irq.vblank_in & 1)<<0;
- state->m_scu_regs[41]|= (stv_irq.vblank_out & 1)<<1;
- state->m_scu_regs[41]|= (stv_irq.hblank_in & 1)<<2;
- state->m_scu_regs[41]|= (stv_irq.timer_0 & 1)<<3;
- state->m_scu_regs[41]|= (stv_irq.timer_1 & 1)<<4;
- state->m_scu_regs[41]|= (stv_irq.dsp_end & 1)<<5;
- state->m_scu_regs[41]|= (stv_irq.sound_req & 1)<<6;
- state->m_scu_regs[41]|= (stv_irq.smpc & 1)<<7;
- state->m_scu_regs[41]|= (stv_irq.pad & 1)<<8;
- state->m_scu_regs[41]|= (stv_irq.dma_end[0] & 1)<<9;
- state->m_scu_regs[41]|= (stv_irq.dma_end[1] & 1)<<10;
- state->m_scu_regs[41]|= (stv_irq.dma_end[2] & 1)<<11;
- state->m_scu_regs[41]|= (stv_irq.dma_ill & 1)<<12;
- state->m_scu_regs[41]|= (stv_irq.vdp1_end & 1)<<13;
- state->m_scu_regs[41]|= (stv_irq.abus & 1)<<15;
+ state->m_scu_regs[41] = (state->m_scu_irq.vblank_in & 1)<<0;
+ state->m_scu_regs[41]|= (state->m_scu_irq.vblank_out & 1)<<1;
+ state->m_scu_regs[41]|= (state->m_scu_irq.hblank_in & 1)<<2;
+ state->m_scu_regs[41]|= (state->m_scu_irq.timer_0 & 1)<<3;
+ state->m_scu_regs[41]|= (state->m_scu_irq.timer_1 & 1)<<4;
+ state->m_scu_regs[41]|= (state->m_scu_irq.dsp_end & 1)<<5;
+ state->m_scu_regs[41]|= (state->m_scu_irq.sound_req & 1)<<6;
+ state->m_scu_regs[41]|= (state->m_scu_irq.smpc & 1)<<7;
+ state->m_scu_regs[41]|= (state->m_scu_irq.pad & 1)<<8;
+ state->m_scu_regs[41]|= (state->m_scu_irq.dma_end[0] & 1)<<9;
+ state->m_scu_regs[41]|= (state->m_scu_irq.dma_end[1] & 1)<<10;
+ state->m_scu_regs[41]|= (state->m_scu_irq.dma_end[2] & 1)<<11;
+ state->m_scu_regs[41]|= (state->m_scu_irq.dma_ill & 1)<<12;
+ state->m_scu_regs[41]|= (state->m_scu_irq.vdp1_end & 1)<<13;
+ state->m_scu_regs[41]|= (state->m_scu_irq.abus & 1)<<15;
return state->m_scu_regs[41] ^ 0xffffffff; //TODO: this is WRONG (Choice Cuts is a good test case)
}
@@ -1367,21 +650,21 @@ static WRITE32_HANDLER( saturn_scu_w )
/*An interrupt is masked when his specific bit is 1.*/
/*Are bit 16-bit 31 for External A-Bus irq mask like the status register?*/
- stv_irq.vblank_in = (((state->m_scu_regs[40] & 0x0001)>>0) ^ 1);
- stv_irq.vblank_out = (((state->m_scu_regs[40] & 0x0002)>>1) ^ 1);
- stv_irq.hblank_in = (((state->m_scu_regs[40] & 0x0004)>>2) ^ 1);
- stv_irq.timer_0 = (((state->m_scu_regs[40] & 0x0008)>>3) ^ 1);
- stv_irq.timer_1 = (((state->m_scu_regs[40] & 0x0010)>>4) ^ 1);
- stv_irq.dsp_end = (((state->m_scu_regs[40] & 0x0020)>>5) ^ 1);
- stv_irq.sound_req = (((state->m_scu_regs[40] & 0x0040)>>6) ^ 1);
- stv_irq.smpc = (((state->m_scu_regs[40] & 0x0080)>>7) ^ 1); //NOTE: SCU bug
- stv_irq.pad = (((state->m_scu_regs[40] & 0x0100)>>8) ^ 1);
- stv_irq.dma_end[2] = (((state->m_scu_regs[40] & 0x0200)>>9) ^ 1);
- stv_irq.dma_end[1] = (((state->m_scu_regs[40] & 0x0400)>>10) ^ 1);
- stv_irq.dma_end[0] = (((state->m_scu_regs[40] & 0x0800)>>11) ^ 1);
- stv_irq.dma_ill = (((state->m_scu_regs[40] & 0x1000)>>12) ^ 1);
- stv_irq.vdp1_end = (((state->m_scu_regs[40] & 0x2000)>>13) ^ 1);
- stv_irq.abus = (((state->m_scu_regs[40] & 0x8000)>>15) ^ 1);
+ state->m_scu_irq.vblank_in = (((state->m_scu_regs[40] & 0x0001)>>0) ^ 1);
+ state->m_scu_irq.vblank_out = (((state->m_scu_regs[40] & 0x0002)>>1) ^ 1);
+ state->m_scu_irq.hblank_in = (((state->m_scu_regs[40] & 0x0004)>>2) ^ 1);
+ state->m_scu_irq.timer_0 = (((state->m_scu_regs[40] & 0x0008)>>3) ^ 1);
+ state->m_scu_irq.timer_1 = (((state->m_scu_regs[40] & 0x0010)>>4) ^ 1);
+ state->m_scu_irq.dsp_end = (((state->m_scu_regs[40] & 0x0020)>>5) ^ 1);
+ state->m_scu_irq.sound_req = (((state->m_scu_regs[40] & 0x0040)>>6) ^ 1);
+ state->m_scu_irq.smpc = (((state->m_scu_regs[40] & 0x0080)>>7) ^ 1); //NOTE: SCU bug
+ state->m_scu_irq.pad = (((state->m_scu_regs[40] & 0x0100)>>8) ^ 1);
+ state->m_scu_irq.dma_end[2] = (((state->m_scu_regs[40] & 0x0200)>>9) ^ 1);
+ state->m_scu_irq.dma_end[1] = (((state->m_scu_regs[40] & 0x0400)>>10) ^ 1);
+ state->m_scu_irq.dma_end[0] = (((state->m_scu_regs[40] & 0x0800)>>11) ^ 1);
+ state->m_scu_irq.dma_ill = (((state->m_scu_regs[40] & 0x1000)>>12) ^ 1);
+ state->m_scu_irq.vdp1_end = (((state->m_scu_regs[40] & 0x2000)>>13) ^ 1);
+ state->m_scu_irq.abus = (((state->m_scu_regs[40] & 0x8000)>>15) ^ 1);
/*Take out the common settings to keep logging quiet.*/
if(state->m_scu_regs[40] != 0xfffffffe &&
@@ -1414,21 +697,21 @@ static WRITE32_HANDLER( saturn_scu_w )
/*This is r/w by introdon...*/
if(LOG_SCU) logerror("IRQ status reg set:%08x %08x\n",state->m_scu_regs[41],mem_mask);
- stv_irq.vblank_in = ((state->m_scu_regs[41] & 0x0001)>>0);
- stv_irq.vblank_out = ((state->m_scu_regs[41] & 0x0002)>>1);
- stv_irq.hblank_in = ((state->m_scu_regs[41] & 0x0004)>>2);
- stv_irq.timer_0 = ((state->m_scu_regs[41] & 0x0008)>>3);
- stv_irq.timer_1 = ((state->m_scu_regs[41] & 0x0010)>>4);
- stv_irq.dsp_end = ((state->m_scu_regs[41] & 0x0020)>>5);
- stv_irq.sound_req = ((state->m_scu_regs[41] & 0x0040)>>6);
- stv_irq.smpc = ((state->m_scu_regs[41] & 0x0080)>>7);
- stv_irq.pad = ((state->m_scu_regs[41] & 0x0100)>>8);
- stv_irq.dma_end[2] = ((state->m_scu_regs[41] & 0x0200)>>9);
- stv_irq.dma_end[1] = ((state->m_scu_regs[41] & 0x0400)>>10);
- stv_irq.dma_end[0] = ((state->m_scu_regs[41] & 0x0800)>>11);
- stv_irq.dma_ill = ((state->m_scu_regs[41] & 0x1000)>>12);
- stv_irq.vdp1_end = ((state->m_scu_regs[41] & 0x2000)>>13);
- stv_irq.abus = ((state->m_scu_regs[41] & 0x8000)>>15);
+ state->m_scu_irq.vblank_in = ((state->m_scu_regs[41] & 0x0001)>>0);
+ state->m_scu_irq.vblank_out = ((state->m_scu_regs[41] & 0x0002)>>1);
+ state->m_scu_irq.hblank_in = ((state->m_scu_regs[41] & 0x0004)>>2);
+ state->m_scu_irq.timer_0 = ((state->m_scu_regs[41] & 0x0008)>>3);
+ state->m_scu_irq.timer_1 = ((state->m_scu_regs[41] & 0x0010)>>4);
+ state->m_scu_irq.dsp_end = ((state->m_scu_regs[41] & 0x0020)>>5);
+ state->m_scu_irq.sound_req = ((state->m_scu_regs[41] & 0x0040)>>6);
+ state->m_scu_irq.smpc = ((state->m_scu_regs[41] & 0x0080)>>7);
+ state->m_scu_irq.pad = ((state->m_scu_regs[41] & 0x0100)>>8);
+ state->m_scu_irq.dma_end[2] = ((state->m_scu_regs[41] & 0x0200)>>9);
+ state->m_scu_irq.dma_end[1] = ((state->m_scu_regs[41] & 0x0400)>>10);
+ state->m_scu_irq.dma_end[0] = ((state->m_scu_regs[41] & 0x0800)>>11);
+ state->m_scu_irq.dma_ill = ((state->m_scu_regs[41] & 0x1000)>>12);
+ state->m_scu_irq.vdp1_end = ((state->m_scu_regs[41] & 0x2000)>>13);
+ state->m_scu_irq.abus = ((state->m_scu_regs[41] & 0x8000)>>15);
break;
case 42: if(LOG_SCU) logerror("A-Bus IRQ ACK %08x\n",state->m_scu_regs[42]); break;
@@ -1442,7 +725,7 @@ static TIMER_CALLBACK( dma_lv0_ended )
{
saturn_state *state = machine.driver_data<saturn_state>();
- if(stv_irq.dma_end[0]) device_set_input_line_and_vector(state->m_maincpu, 5, HOLD_LINE, 0x4b);
+ if(state->m_scu_irq.dma_end[0]) device_set_input_line_and_vector(state->m_maincpu, 5, HOLD_LINE, 0x4b);
DnMV_0(0);
}
@@ -1452,7 +735,7 @@ static TIMER_CALLBACK( dma_lv1_ended )
{
saturn_state *state = machine.driver_data<saturn_state>();
- if(stv_irq.dma_end[1]) device_set_input_line_and_vector(state->m_maincpu, 6, HOLD_LINE, 0x4a);
+ if(state->m_scu_irq.dma_end[1]) device_set_input_line_and_vector(state->m_maincpu, 6, HOLD_LINE, 0x4a);
DnMV_0(1);
}
@@ -1462,7 +745,7 @@ static TIMER_CALLBACK( dma_lv2_ended )
{
saturn_state *state = machine.driver_data<saturn_state>();
- if(stv_irq.dma_end[2]) device_set_input_line_and_vector(state->m_maincpu, 6, HOLD_LINE, 0x49);
+ if(state->m_scu_irq.dma_end[2]) device_set_input_line_and_vector(state->m_maincpu, 6, HOLD_LINE, 0x49);
DnMV_0(2);
}
@@ -1752,7 +1035,7 @@ static READ8_HANDLER( saturn_cart_type_r )
static ADDRESS_MAP_START( saturn_mem, AS_PROGRAM, 32 )
AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE("share6") // bios
- AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8(saturn_SMPC_r8, saturn_SMPC_w8,0xffffffff)
+ AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8(saturn_SMPC_r, saturn_SMPC_w,0xffffffff)
AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE(saturn_backupram_r, saturn_backupram_w) AM_SHARE("share1") AM_BASE_MEMBER(saturn_state,m_backupram)
AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x100000) AM_SHARE("share2") AM_BASE_MEMBER(saturn_state,m_workram_l)
// AM_RANGE(0x01000000, 0x01000003) AM_MIRROR(0x7ffffc) AM_WRITE(minit_w)
@@ -1781,7 +1064,7 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( stv_mem, AS_PROGRAM, 32 )
AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE("share6") // bios
- AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8(stv_SMPC_r8, stv_SMPC_w8,0xffffffff)
+ AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE8(stv_SMPC_r, stv_SMPC_w,0xffffffff)
AM_RANGE(0x00180000, 0x0018ffff) AM_READWRITE(saturn_backupram_r,saturn_backupram_w) AM_SHARE("share1") AM_BASE_MEMBER(saturn_state,m_backupram)
AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x100000) AM_SHARE("share2") AM_BASE_MEMBER(saturn_state,m_workram_l)
AM_RANGE(0x00400000, 0x0040001f) AM_READWRITE(stv_io_r32, stv_io_w32) AM_BASE_MEMBER(saturn_state,m_ioga) AM_SHARE("share4") AM_MIRROR(0x20)
@@ -2380,7 +1663,7 @@ static WRITE_LINE_DEVICE_HANDLER( scsp_to_main_irq )
{
saturn_state *drvstate = device->machine().driver_data<saturn_state>();
- if(stv_irq.sound_req)
+ if(drvstate->m_scu_irq.sound_req)
{
device_set_input_line_and_vector(drvstate->m_maincpu, 9, HOLD_LINE, 0x46);
scu_do_transfer(device->machine(),5);
@@ -2585,21 +1868,21 @@ static TIMER_DEVICE_CALLBACK( saturn_scanline )
if(scanline == 0*y_step)
{
- if(stv_irq.vblank_out)
+ if(state->m_scu_irq.vblank_out)
{
- device_set_input_line_and_vector(state->m_maincpu, 0xe, (stv_irq.vblank_out) ? HOLD_LINE : CLEAR_LINE , 0x41);
+ device_set_input_line_and_vector(state->m_maincpu, 0xe, (state->m_scu_irq.vblank_out) ? HOLD_LINE : CLEAR_LINE , 0x41);
scu_do_transfer(timer.machine(),1);
}
}
else if(scanline == vblank_line*y_step)
{
- if(stv_irq.vblank_in)
+ if(state->m_scu_irq.vblank_in)
{
device_set_input_line_and_vector(state->m_maincpu, 0xf, HOLD_LINE ,0x40);
scu_do_transfer(timer.machine(),0);
}
- if(stv_irq.vdp1_end)
+ if(state->m_scu_irq.vdp1_end)
{
device_set_input_line_and_vector(state->m_maincpu, 0x2, HOLD_LINE, 0x4d);
scu_do_transfer(timer.machine(),6);
@@ -2608,7 +1891,7 @@ static TIMER_DEVICE_CALLBACK( saturn_scanline )
}
else if((scanline % y_step) == 0 && scanline < vblank_line*y_step)
{
- if(stv_irq.hblank_in)
+ if(state->m_scu_irq.hblank_in)
{
device_set_input_line_and_vector(state->m_maincpu, 0xd, HOLD_LINE, 0x42);
scu_do_transfer(timer.machine(),2);
@@ -2617,7 +1900,7 @@ static TIMER_DEVICE_CALLBACK( saturn_scanline )
if(scanline == (state->m_scu_regs[36] & 0x3ff)*y_step)
{
- if(stv_irq.timer_0)
+ if(state->m_scu_irq.timer_0)
{
device_set_input_line_and_vector(state->m_maincpu, 0xc, HOLD_LINE, 0x43 );
scu_do_transfer(timer.machine(),3);
@@ -2627,7 +1910,7 @@ static TIMER_DEVICE_CALLBACK( saturn_scanline )
/* TODO: this isn't completely correct */
if((state->m_scu_regs[38] & 0x81) == 0x01 && ((scanline % y_step) == 0))
{
- if(stv_irq.timer_1)
+ if(state->m_scu_irq.timer_1)
{
device_set_input_line_and_vector(state->m_maincpu, 0xb, HOLD_LINE, 0x44 );
scu_do_transfer(timer.machine(),4);
diff --git a/src/mame/includes/stv.h b/src/mame/includes/stv.h
index 861cf6789ce..45a220ea8a3 100644
--- a/src/mame/includes/stv.h
+++ b/src/mame/includes/stv.h
@@ -81,6 +81,22 @@ public:
UINT8 intback;
}m_smpc;
+ struct {
+ UINT8 vblank_out;
+ UINT8 vblank_in;
+ UINT8 hblank_in;
+ UINT8 timer_0;
+ UINT8 timer_1;
+ UINT8 dsp_end;
+ UINT8 sound_req;
+ UINT8 smpc;
+ UINT8 pad;
+ UINT8 dma_end[3];
+ UINT8 dma_ill;
+ UINT8 vdp1_end;
+ UINT8 abus;
+ }m_scu_irq;
+
/* Saturn specific*/
int m_saturn_region;
UINT8 m_cart_type;
diff --git a/src/mame/machine/smpc.c b/src/mame/machine/smpc.c
new file mode 100644
index 00000000000..a433507052d
--- /dev/null
+++ b/src/mame/machine/smpc.c
@@ -0,0 +1,717 @@
+/************************************************************************************
+
+Sega Saturn SMPC - System Manager and Peripheral Control MCU simulation
+
+The SMPC is actually a 4-bit Hitachi HD404920FS MCU, labeled with a Sega custom
+315-5744 (that needs decapping)
+
+MCU simulation by Angelo Salese & R. Belmont
+
+TODO:
+- timings;
+- fix intback issue with inputs;
+- better arrangement of variables;
+- clean-ups;
+
+*************************************************************************************/
+/* SMPC Addresses
+
+00
+01 -w Input Register 0 (IREG)
+02
+03 -w Input Register 1
+04
+05 -w Input Register 2
+06
+07 -w Input Register 3
+08
+09 -w Input Register 4
+0a
+0b -w Input Register 5
+0c
+0d -w Input Register 6
+0e
+0f
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+1a
+1b
+1c
+1d
+1e
+1f -w Command Register (COMREG)
+20
+21 r- Output Register 0 (OREG)
+22
+23 r- Output Register 1
+24
+25 r- Output Register 2
+26
+27 r- Output Register 3
+28
+29 r- Output Register 4
+2a
+2b r- Output Register 5
+2c
+2d r- Output Register 6
+2e
+2f r- Output Register 7
+30
+31 r- Output Register 8
+32
+33 r- Output Register 9
+34
+35 r- Output Register 10
+36
+37 r- Output Register 11
+38
+39 r- Output Register 12
+3a
+3b r- Output Register 13
+3c
+3d r- Output Register 14
+3e
+3f r- Output Register 15
+40
+41 r- Output Register 16
+42
+43 r- Output Register 17
+44
+45 r- Output Register 18
+46
+47 r- Output Register 19
+48
+49 r- Output Register 20
+4a
+4b r- Output Register 21
+4c
+4d r- Output Register 22
+4e
+4f r- Output Register 23
+50
+51 r- Output Register 24
+52
+53 r- Output Register 25
+54
+55 r- Output Register 26
+56
+57 r- Output Register 27
+58
+59 r- Output Register 28
+5a
+5b r- Output Register 29
+5c
+5d r- Output Register 30
+5e
+5f r- Output Register 31
+60
+61 r- SR
+62
+63 rw SF
+64
+65
+66
+67
+68
+69
+6a
+6b
+6c
+6d
+6e
+6f
+70
+71
+72
+73
+74
+75 rw PDR1
+76
+77 rw PDR2
+78
+79 -w DDR1
+7a
+7b -w DDR2
+7c
+7d -w IOSEL2/1
+7e
+7f -w EXLE2/1
+*/
+
+#include "emu.h"
+#include "coreutil.h"
+#include "includes/stv.h"
+#include "machine/smpc.h"
+#include "machine/eeprom.h"
+
+#define LOG_SMPC 0
+
+READ8_HANDLER( stv_SMPC_r )
+{
+ saturn_state *state = space->machine().driver_data<saturn_state>();
+ int return_data;
+
+ return_data = state->m_smpc_ram[offset];
+
+ if (offset == 0x61) // ?? many games need this or the controls don't work
+ return_data = 0x20 ^ 0xff;
+
+ if (offset == 0x75)//PDR1 read
+ return_data = input_port_read(space->machine(), "DSW1");
+
+ if (offset == 0x77)//PDR2 read
+ return_data= (0xfe | space->machine().device<eeprom_device>("eeprom")->read_bit());
+
+// if (offset == 0x33) //country code
+// return_data = input_port_read(machine, "FAKE");
+
+ //if(LOG_SMPC) logerror ("cpu %s (PC=%08X) SMPC: Read from Byte Offset %02x Returns %02x\n", space->device().tag(), cpu_get_pc(&space->device()), offset, return_data);
+
+
+ return return_data;
+}
+
+static TIMER_CALLBACK( stv_bankswitch_state )
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+ static const char *const banknames[] = { "game0", "game1", "game2", "game3" };
+ UINT8* game_region;
+
+ if(state->m_prev_bankswitch != param)
+ {
+ game_region = machine.region(banknames[param])->base();
+
+ if (game_region)
+ memcpy(machine.region("abus")->base(), game_region, 0x3000000);
+ else
+ memset(machine.region("abus")->base(), 0x00, 0x3000000);
+
+ state->m_prev_bankswitch = param;
+ }
+}
+
+static void stv_select_game(running_machine &machine, int gameno)
+{
+ machine.scheduler().timer_set(attotime::zero, FUNC(stv_bankswitch_state), gameno);
+}
+
+static void smpc_master_on(running_machine &machine)
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+
+ device_set_input_line(state->m_maincpu, INPUT_LINE_RESET, CLEAR_LINE);
+}
+
+static void smpc_slave_enable(running_machine &machine,UINT8 cmd)
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+
+ device_set_input_line(state->m_slave, INPUT_LINE_RESET, cmd ? ASSERT_LINE : CLEAR_LINE);
+}
+
+static void smpc_sound_enable(running_machine &machine,UINT8 cmd)
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+
+ device_set_input_line(state->m_audiocpu, INPUT_LINE_RESET, cmd ? ASSERT_LINE : CLEAR_LINE);
+ state->m_en_68k = cmd ^ 1;
+}
+
+static void smpc_system_reset(running_machine &machine)
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+
+ /*Only backup ram and SMPC ram are retained after that this command is issued.*/
+ memset(state->m_scu_regs ,0x00,0x000100);
+ memset(state->m_scsp_regs,0x00,0x001000);
+ memset(state->m_sound_ram,0x00,0x080000);
+ memset(state->m_workram_h,0x00,0x100000);
+ memset(state->m_workram_l,0x00,0x100000);
+ memset(state->m_vdp2_regs,0x00,0x040000);
+ memset(state->m_vdp2_vram,0x00,0x100000);
+ memset(state->m_vdp2_cram,0x00,0x080000);
+ memset(state->m_vdp1_vram,0x00,0x100000);
+ //A-Bus
+
+ device_set_input_line(state->m_maincpu, INPUT_LINE_RESET, PULSE_LINE);
+}
+
+static void smpc_change_clock(running_machine &machine, UINT8 cmd)
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+ UINT32 xtal;
+
+ xtal = cmd ? MASTER_CLOCK_320 : MASTER_CLOCK_352;
+
+ machine.device("maincpu")->set_unscaled_clock(xtal/2);
+ machine.device("slave")->set_unscaled_clock(xtal/2);
+
+ state->m_vdp2.dotsel = cmd ^ 1;
+ stv_vdp2_dynamic_res_change(machine);
+
+ device_set_input_line(state->m_maincpu, INPUT_LINE_NMI, PULSE_LINE); // ff said this causes nmi, should we set a timer then nmi?
+ smpc_slave_enable(machine,1);
+ /* TODO: VDP1 / VDP2 / SCU / SCSP default power ON values */
+}
+
+static void smpc_intbackhelper(running_machine &machine)
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+ int pad,i;
+ static const char *const padnames[] = { "JOY1", "JOY2" };
+
+ if (state->m_smpc.intback_stage == 1)
+ {
+ state->m_smpc.intback_stage++;
+ return;
+ }
+
+// if (LOG_SMPC) logerror("SMPC: providing PAD data for intback, pad %d\n", intback_stage-2);
+ for(i=0;i<2;i++)
+ {
+ pad = input_port_read(machine, padnames[i]);
+ state->m_smpc_ram[0x21+i*8] = 0xf1; // no tap, direct connect
+ state->m_smpc_ram[0x23+i*8] = 0x02; // saturn pad
+ state->m_smpc_ram[0x25+i*8] = pad>>8;
+ state->m_smpc_ram[0x27+i*8] = pad & 0xff;
+ }
+
+ if (state->m_smpc.intback_stage == 3)
+ {
+ state->m_smpc.smpcSR = (0x80 | state->m_smpc.pmode); // pad 2, no more data, echo back pad mode set by intback
+ }
+ else
+ {
+ state->m_smpc.smpcSR = (0xe0 | state->m_smpc.pmode); // pad 1, more data, echo back pad mode set by intback
+ }
+
+ state->m_smpc.intback_stage++;
+}
+
+/* sys_type 1 == STV, 0 == SATURN */
+static TIMER_CALLBACK( smpc_intback )
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+ system_time systime;
+ machine.base_datetime(systime);
+ UINT8 sys_type = param;
+
+ state->m_smpc_ram[0x21] = (0x80) | ((state->m_NMI_reset & 1) << 6);
+
+ if(sys_type == 0)
+ {
+ state->m_smpc_ram[0x23] = dec_2_bcd(systime.local_time.year / 100);
+ state->m_smpc_ram[0x25] = dec_2_bcd(systime.local_time.year % 100);
+ state->m_smpc_ram[0x27] = (systime.local_time.weekday << 4) | (systime.local_time.month + 1);
+ state->m_smpc_ram[0x29] = dec_2_bcd(systime.local_time.mday);
+ state->m_smpc_ram[0x2b] = dec_2_bcd(systime.local_time.hour);
+ state->m_smpc_ram[0x2d] = dec_2_bcd(systime.local_time.minute);
+ state->m_smpc_ram[0x2f] = dec_2_bcd(systime.local_time.second);
+ }
+
+ state->m_smpc_ram[0x31]=0x00; //?
+
+ //state->m_smpc_ram[0x33]=input_port_read(space->machine(), "FAKE");
+
+ state->m_smpc_ram[0x35]= 0 << 7 |
+ state->m_vdp2.dotsel << 6 |
+ 1 << 5 |
+ 1 << 4 |
+ 0 << 3 | //MSHNMI
+ 1 << 2 |
+ 0 << 1 | //SYSRES
+ 0 << 0; //SOUNDRES
+ state->m_smpc_ram[0x37]= 0 << 6; //CDRES
+
+ state->m_smpc_ram[0x39]=sys_type ? 0xff : state->m_smpc.SMEM[0];
+ state->m_smpc_ram[0x3b]=sys_type ? 0xff : state->m_smpc.SMEM[1];
+ state->m_smpc_ram[0x3d]=sys_type ? 0xff : state->m_smpc.SMEM[2];
+ state->m_smpc_ram[0x3f]=sys_type ? 0xff : state->m_smpc.SMEM[3];
+
+ state->m_smpc_ram[0x41]=0xff;
+ state->m_smpc_ram[0x43]=0xff;
+ state->m_smpc_ram[0x45]=0xff;
+ state->m_smpc_ram[0x47]=0xff;
+ state->m_smpc_ram[0x49]=0xff;
+ state->m_smpc_ram[0x4b]=0xff;
+ state->m_smpc_ram[0x4d]=0xff;
+ state->m_smpc_ram[0x4f]=0xff;
+ state->m_smpc_ram[0x51]=0xff;
+ state->m_smpc_ram[0x53]=0xff;
+ state->m_smpc_ram[0x55]=0xff;
+ state->m_smpc_ram[0x57]=0xff;
+ state->m_smpc_ram[0x59]=0xff;
+ state->m_smpc_ram[0x5b]=0xff;
+ state->m_smpc_ram[0x5d]=0xff;
+
+ if(sys_type == 0)
+ {
+ state->m_smpc.smpcSR = 0x60; // peripheral data ready, no reset, etc.
+ state->m_smpc.pmode = state->m_smpc_ram[1]>>4;
+
+ state->m_smpc.intback_stage = 2;
+
+ smpc_intbackhelper(machine);
+ }
+
+ // /*This is for RTC,cartridge code and similar stuff...*/
+ //if(LOG_SMPC) logerror ("Interrupt: System Manager (SMPC) at scanline %04x, Vector 0x47 Level 0x08\n",scanline);
+ if(state->m_scu_irq.smpc)
+ device_set_input_line_and_vector(state->m_maincpu, 8, HOLD_LINE, 0x47);
+}
+
+static void smpc_rtc_write(running_machine &machine)
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+ state->m_smpc_ram[0x2f] = state->m_smpc_ram[0x0d];
+ state->m_smpc_ram[0x2d] = state->m_smpc_ram[0x0b];
+ state->m_smpc_ram[0x2b] = state->m_smpc_ram[0x09];
+ state->m_smpc_ram[0x29] = state->m_smpc_ram[0x07];
+ state->m_smpc_ram[0x27] = state->m_smpc_ram[0x05];
+ state->m_smpc_ram[0x25] = state->m_smpc_ram[0x03];
+ state->m_smpc_ram[0x23] = state->m_smpc_ram[0x01];
+}
+
+static void smpc_memory_setting(running_machine &machine)
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+ state->m_smpc.SMEM[0] = state->m_smpc_ram[1];
+ state->m_smpc.SMEM[1] = state->m_smpc_ram[3];
+ state->m_smpc.SMEM[2] = state->m_smpc_ram[5];
+ state->m_smpc.SMEM[3] = state->m_smpc_ram[7];
+}
+
+static void smpc_nmi_req(running_machine &machine)
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+
+ /*NMI is unconditionally requested?*/
+ device_set_input_line(state->m_maincpu, INPUT_LINE_NMI, PULSE_LINE);
+}
+
+static void smpc_nmi_set(running_machine &machine,UINT8 cmd)
+{
+ saturn_state *state = machine.driver_data<saturn_state>();
+
+ state->m_NMI_reset = cmd ^ 1;
+ state->m_smpc_ram[0x21] = (0x80) | ((state->m_NMI_reset & 1) << 6);
+}
+
+WRITE8_HANDLER( stv_SMPC_w )
+{
+ saturn_state *state = space->machine().driver_data<saturn_state>();
+ system_time systime;
+ space->machine().base_datetime(systime);
+
+// if(LOG_SMPC) logerror ("8-bit SMPC Write to Offset %02x with Data %02x\n", offset, data);
+ state->m_smpc_ram[offset] = data;
+
+ if(offset == 0x75)
+ {
+ /*
+ -xx- ---- PDR1
+ ---x ---- EEPROM write bit
+ ---- x--- EEPROM CLOCK line
+ ---- -x-- EEPROM CS line
+ ---- --xx A-Bus bank bits
+ */
+ eeprom_device *eeprom = space->machine().device<eeprom_device>("eeprom");
+ eeprom->set_clock_line((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
+ eeprom->write_bit(data & 0x10);
+ eeprom->set_cs_line((data & 0x04) ? CLEAR_LINE : ASSERT_LINE);
+ state->m_stv_multi_bank = data & 3;
+
+ stv_select_game(space->machine(), state->m_stv_multi_bank);
+
+ state->m_smpc.PDR1 = (data & 0x60);
+ }
+
+ if(offset == 0x77)
+ {
+ /*
+ -xx- ---- PDR2
+ ---x ---- Enable Sound System (ACTIVE LOW)
+ */
+ //popmessage("PDR2 = %02x",state->m_smpc_ram[0x77]);
+
+ if(LOG_SMPC) logerror("SMPC: M68k %s\n",(state->m_smpc_ram[0x77] & 0x10) ? "off" : "on");
+ cputag_set_input_line(space->machine(), "audiocpu", INPUT_LINE_RESET, (state->m_smpc_ram[0x77] & 0x10) ? ASSERT_LINE : CLEAR_LINE);
+ state->m_en_68k = ((state->m_smpc_ram[0x77] & 0x10) >> 4) ^ 1;
+
+ //if(LOG_SMPC) logerror("SMPC: ram [0x77] = %02x\n",state->m_smpc_ram[0x77]);
+ state->m_smpc.PDR2 = (data & 0x60);
+ }
+
+ if(offset == 0x7d)
+ {
+ /*
+ ---- --x- IOSEL2 direct (1) / control mode (0) port select
+ ---- ---x IOSEL1 direct (1) / control mode (0) port select
+ */
+ state->m_smpc.IOSEL1 = (state->m_smpc_ram[0x7d] & 1) >> 0;
+ state->m_smpc.IOSEL2 = (state->m_smpc_ram[0x7d] & 2) >> 1;
+ }
+
+ if(offset == 0x7f)
+ {
+ //enable PAD irq & VDP2 external latch for port 1/2
+ state->m_smpc.EXLE1 = (state->m_smpc_ram[0x7f] & 1) >> 0;
+ state->m_smpc.EXLE2 = (state->m_smpc_ram[0x7f] & 2) >> 1;
+ if(state->m_smpc.EXLE1 || state->m_smpc.EXLE2)
+ {
+ //if(LOG_SMPC) logerror ("Interrupt: PAD irq at scanline %04x, Vector 0x48 Level 0x08\n",scanline);
+ //cputag_set_input_line_and_vector(space->machine(), "maincpu", 8, (state->m_scu_irq.pad) ? HOLD_LINE : CLEAR_LINE, 0x48);
+ }
+ }
+
+ if (offset == 0x1f) // COMREG
+ {
+ switch (data)
+ {
+ case 0x00:
+ if(LOG_SMPC) logerror ("SMPC: Master ON\n");
+ smpc_master_on(space->machine());
+ break;
+ //in theory 0x01 is for Master OFF,but obviously is not used.
+ case 0x02:
+ case 0x03:
+ if(LOG_SMPC) logerror ("SMPC: Slave %s\n",(data & 1) ? "off" : "on");
+ smpc_slave_enable(space->machine(),(data & 1));
+ break;
+ case 0x06:
+ case 0x07:
+ if(LOG_SMPC) logerror ("SMPC: Sound %s, ignored\n",(data & 1) ? "off" : "on");
+ break;
+ /*CD (SH-1) ON/OFF,guess that this is needed for Sports Fishing games...*/
+ //case 0x08:
+ //case 0x09:
+ case 0x0d:
+ if(LOG_SMPC) logerror ("SMPC: System Reset\n");
+ smpc_system_reset(space->machine());
+ break;
+ case 0x0e:
+ case 0x0f:
+ if(LOG_SMPC) logerror ("SMPC: Change Clock to %s\n",data & 1 ? "320" : "352");
+ smpc_change_clock(space->machine(),data & 1);
+ break;
+ /*"Interrupt Back"*/
+ case 0x10:
+ if(LOG_SMPC) logerror ("SMPC: Status Acquire\n");
+ space->machine().scheduler().timer_set(attotime::from_msec(16), FUNC(smpc_intback),1); //TODO: variable time
+ break;
+ /* RTC write*/
+ case 0x16:
+ if(LOG_SMPC) logerror("SMPC: RTC write\n");
+ smpc_rtc_write(space->machine());
+ break;
+ /* SMPC memory setting*/
+ case 0x17:
+ if(LOG_SMPC) logerror ("SMPC: memory setting\n");
+ //smpc_memory_setting(space->machine());
+ break;
+ case 0x18:
+ if(LOG_SMPC) logerror ("SMPC: NMI request\n");
+ smpc_nmi_req(space->machine());
+ break;
+ case 0x19:
+ case 0x1a:
+ if(LOG_SMPC) logerror ("SMPC: NMI %sable\n",data & 1 ? "Dis" : "En");
+ smpc_nmi_set(space->machine(),data & 1);
+ break;
+ default:
+ printf ("cpu '%s' (PC=%08X) SMPC: undocumented Command %02x\n", space->device().tag(), cpu_get_pc(&space->device()), data);
+ }
+
+ // we've processed the command, clear status flag
+ state->m_smpc_ram[0x5f] = data; //read-back command
+ state->m_smpc_ram[0x63] = 0x00;
+ /*TODO:emulate the timing of each command...*/
+ }
+}
+
+READ8_HANDLER( saturn_SMPC_r )
+{
+ saturn_state *state = space->machine().driver_data<saturn_state>();
+ int return_data;
+
+ return_data = state->m_smpc_ram[offset];
+
+ if ((offset == 0x61))
+ return_data = state->m_smpc.smpcSR;
+
+ if (offset == 0x75 || offset == 0x77)//PDR1/2 read
+ {
+/*
+ PORT_START("JOY1")
+ PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
+ PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
+ PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
+ PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
+ PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) // START
+ PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 A") PORT_PLAYER(1) // A
+ PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 B") PORT_PLAYER(1) // B
+ PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P1 C") PORT_PLAYER(1) // C
+ PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("P1 R") PORT_PLAYER(1) // R
+ PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P1 X") PORT_PLAYER(1) // X
+ PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P1 Y") PORT_PLAYER(1) // Y
+ PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P1 Z") PORT_PLAYER(1) // Z
+ PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("P1 L") PORT_PLAYER(1) // L
+*/
+ if ((state->m_smpc.IOSEL1 && offset == 0x75) || (state->m_smpc.IOSEL2 && offset == 0x77))
+ {
+ int hshake;
+ const int shift_bit[4] = { 4, 12, 8, 0 };
+ const char *const padnames[] = { "JOY1", "JOY2" };
+
+ if(offset == 0x75)
+ hshake = (state->m_smpc.PDR1>>5) & 3;
+ else
+ hshake = (state->m_smpc.PDR2>>5) & 3;
+
+ if (LOG_SMPC) logerror("SMPC: SH-2 direct mode, returning data for phase %d\n", hshake);
+
+ return_data = 0x80 | 0x10 | ((input_port_read(space->machine(), padnames[offset == 0x77])>>shift_bit[hshake]) & 0xf);
+ }
+ }
+
+ if (offset == 0x33) return_data = state->m_saturn_region;
+
+ if (LOG_SMPC) logerror ("cpu %s (PC=%08X) SMPC: Read from Byte Offset %02x (%d) Returns %02x\n", space->device().tag(), cpu_get_pc(&space->device()), offset, offset>>1, return_data);
+
+
+ return return_data;
+}
+
+WRITE8_HANDLER( saturn_SMPC_w )
+{
+ saturn_state *state = space->machine().driver_data<saturn_state>();
+ system_time systime;
+ UINT8 last;
+ running_machine &machine = space->machine();
+
+ /* get the current date/time from the core */
+ machine.current_datetime(systime);
+
+ if (LOG_SMPC) logerror ("8-bit SMPC Write to Offset %02x (reg %d) with Data %02x (prev %02x)\n", offset, offset>>1, data, state->m_smpc_ram[offset]);
+
+// if (offset == 0x7d) printf("IOSEL2 %d IOSEL1 %d\n", (data>>1)&1, data&1);
+
+ last = state->m_smpc_ram[offset];
+
+ if ((state->m_smpc.intback_stage > 0) && (offset == 1) && (((data ^ 0x80)&0x80) == (last&0x80)))
+ {
+ if (LOG_SMPC) logerror("SMPC: CONTINUE request, stage %d\n", state->m_smpc.intback_stage);
+ if (state->m_smpc.intback_stage != 3)
+ {
+ state->m_smpc.intback_stage = 2;
+ }
+ smpc_intbackhelper(machine);
+ device_set_input_line_and_vector(state->m_maincpu, 8, HOLD_LINE, 0x47);
+ }
+
+ if ((offset == 1) && (data & 0x40))
+ {
+ if (LOG_SMPC) logerror("SMPC: BREAK request\n");
+ state->m_smpc.intback_stage = 0;
+ }
+
+ state->m_smpc_ram[offset] = data;
+
+ if (offset == 0x75) // PDR1
+ {
+ state->m_smpc.PDR1 = (data & state->m_smpc_ram[0x79]);
+ }
+
+ if (offset == 0x77) // PDR2
+ {
+ state->m_smpc.PDR2 = (data & state->m_smpc_ram[0x7b]);
+ }
+
+ if(offset == 0x7d)
+ {
+ state->m_smpc.IOSEL1 = state->m_smpc_ram[0x7d] & 1;
+ state->m_smpc.IOSEL2 = (state->m_smpc_ram[0x7d] & 2) >> 1;
+ }
+
+ if(offset == 0x7f)
+ {
+ //enable PAD irq & VDP2 external latch for port 1/2
+ state->m_smpc.EXLE1 = (state->m_smpc_ram[0x7f] & 1) >> 0;
+ state->m_smpc.EXLE2 = (state->m_smpc_ram[0x7f] & 2) >> 1;
+ //if(state->m_smpc.EXLE1 || state->m_smpc.EXLE2)
+ // cputag_set_input_line_and_vector(space->machine(), "maincpu", 8, (state->m_scu_irq.pad) ? HOLD_LINE : CLEAR_LINE, 0x48);
+ }
+
+ if (offset == 0x1f)
+ {
+ switch (data)
+ {
+ case 0x00:
+ if(LOG_SMPC) logerror ("SMPC: Master ON\n");
+ smpc_master_on(space->machine());
+ break;
+ //in theory 0x01 is for Master OFF
+ case 0x02:
+ case 0x03:
+ if(LOG_SMPC) logerror ("SMPC: Slave %s\n",(data & 1) ? "off" : "on");
+ smpc_slave_enable(space->machine(),data & 1);
+ break;
+ case 0x06:
+ case 0x07:
+ if(LOG_SMPC) logerror ("SMPC: Sound %s\n",(data & 1) ? "off" : "on");
+ smpc_sound_enable(space->machine(),data & 1);
+ break;
+ /*CD (SH-1) ON/OFF,guess that this is needed for Sports Fishing games...*/
+ //case 0x08:
+ //case 0x09:
+ case 0x0d:
+ if(LOG_SMPC) logerror ("SMPC: System Reset\n");
+ smpc_system_reset(space->machine());
+ break;
+ case 0x0e:
+ case 0x0f:
+ if(LOG_SMPC) logerror ("SMPC: Change Clock to %s\n",data & 1 ? "320" : "352");
+ smpc_change_clock(space->machine(),data & 1);
+ break;
+ /*"Interrupt Back"*/
+ case 0x10:
+ if(LOG_SMPC) logerror ("SMPC: Status Acquire (IntBack)\n");
+ space->machine().scheduler().timer_set(attotime::from_msec(16), FUNC(smpc_intback),0); //TODO: variable time
+ break;
+ /* RTC write*/
+ case 0x16:
+ if(LOG_SMPC) logerror("SMPC: RTC write\n");
+ smpc_rtc_write(space->machine());
+ break;
+ /* SMPC memory setting*/
+ case 0x17:
+ if(LOG_SMPC) logerror ("SMPC: memory setting\n");
+ smpc_memory_setting(space->machine());
+ break;
+ case 0x18:
+ if(LOG_SMPC) logerror ("SMPC: NMI request\n");
+ smpc_nmi_req(space->machine());
+ break;
+ case 0x19:
+ case 0x1a:
+ if(LOG_SMPC) logerror ("SMPC: NMI %sable\n",data & 1 ? "Dis" : "En");
+ smpc_nmi_set(space->machine(),data & 1);
+ break;
+ default:
+ printf ("cpu %s (PC=%08X) SMPC: undocumented Command %02x\n", space->device().tag(), cpu_get_pc(&space->device()), data);
+ }
+
+ // we've processed the command, clear status flag
+ state->m_smpc_ram[0x5f] = data; //read-back for last command issued
+ state->m_smpc_ram[0x63] = 0x00;
+ /*TODO:emulate the timing of each command...*/
+ }
+}
diff --git a/src/mame/machine/smpc.h b/src/mame/machine/smpc.h
new file mode 100644
index 00000000000..2462f6a53c4
--- /dev/null
+++ b/src/mame/machine/smpc.h
@@ -0,0 +1,4 @@
+WRITE8_HANDLER( stv_SMPC_w );
+READ8_HANDLER( stv_SMPC_r );
+WRITE8_HANDLER( saturn_SMPC_w );
+READ8_HANDLER( saturn_SMPC_r );
diff --git a/src/mame/mame.mak b/src/mame/mame.mak
index 2167d091540..d32bd2a27b3 100644
--- a/src/mame/mame.mak
+++ b/src/mame/mame.mak
@@ -1196,7 +1196,7 @@ $(MAMEOBJ)/sega.a: \
$(DRIVERS)/segaybd.o $(VIDEO)/segaybd.o \
$(DRIVERS)/sg1000a.o \
$(DRIVERS)/stactics.o $(VIDEO)/stactics.o \
- $(DRIVERS)/saturn.o $(DRIVERS)/stvinit.o $(MACHINE)/stvprot.o $(MACHINE)/stvcd.o $(VIDEO)/stvvdp1.o $(VIDEO)/stvvdp2.o \
+ $(DRIVERS)/saturn.o $(DRIVERS)/stvinit.o $(MACHINE)/stvprot.o $(MACHINE)/stvcd.o $(MACHINE)/smpc.o $(VIDEO)/stvvdp1.o $(VIDEO)/stvvdp2.o \
$(DRIVERS)/suprloco.o $(VIDEO)/suprloco.o \
$(DRIVERS)/system1.o $(VIDEO)/system1.o \
$(DRIVERS)/system16.o $(VIDEO)/system16.o \