mirror of
https://github.com/holub/mame
synced 2025-05-02 20:46:41 +03:00
Port from MESS, nw
This commit is contained in:
parent
5257d55866
commit
d05d998ea5
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
717
src/mame/machine/smpc.c
Normal file
717
src/mame/machine/smpc.c
Normal file
@ -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...*/
|
||||
}
|
||||
}
|
4
src/mame/machine/smpc.h
Normal file
4
src/mame/machine/smpc.h
Normal file
@ -0,0 +1,4 @@
|
||||
WRITE8_HANDLER( stv_SMPC_w );
|
||||
READ8_HANDLER( stv_SMPC_r );
|
||||
WRITE8_HANDLER( saturn_SMPC_w );
|
||||
READ8_HANDLER( saturn_SMPC_r );
|
@ -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 \
|
||||
|
Loading…
Reference in New Issue
Block a user