diff options
| author | 2011-06-30 13:43:46 +0000 | |
|---|---|---|
| committer | 2011-06-30 13:43:46 +0000 | |
| commit | d05d998ea5dbdf9e501b469e4d0f38a356aeb46b (patch) | |
| tree | fc2011bad62416e28dc3595ed4ebbca07f95507c | |
| parent | 5257d558665579e7f880610688072749a31dab71 (diff) | |
Port from MESS, nw
| -rw-r--r-- | .gitattributes | 2 | ||||
| -rw-r--r-- | src/mame/drivers/saturn.c | 869 | ||||
| -rw-r--r-- | src/mame/includes/stv.h | 16 | ||||
| -rw-r--r-- | src/mame/machine/smpc.c | 717 | ||||
| -rw-r--r-- | src/mame/machine/smpc.h | 4 | ||||
| -rw-r--r-- | src/mame/mame.mak | 2 |
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 \ |
