[Core/MS] improved emulation of Japanese Master System I/O chip (315-5297)

This commit is contained in:
EkeEke 2014-11-23 20:30:27 +01:00
parent 4946d73a47
commit d08b903a11
5 changed files with 59 additions and 53 deletions

View File

@ -412,12 +412,10 @@ unsigned int io_68k_read(unsigned int offset)
void io_z80_write(unsigned int offset, unsigned int data, unsigned int cycles) void io_z80_write(unsigned int offset, unsigned int data, unsigned int cycles)
{ {
/* I/O Control register */
if (offset) if (offset)
{ {
/* I/O Control register */ /*
if (region_code & REGION_USA)
{
/*
Bit Function Bit Function
-------------- --------------
D7 : Port B TH pin output level (1=high, 0=low) D7 : Port B TH pin output level (1=high, 0=low)
@ -428,36 +426,33 @@ void io_z80_write(unsigned int offset, unsigned int data, unsigned int cycles)
D2 : Port B TR pin direction (1=input, 0=output) D2 : Port B TR pin direction (1=input, 0=output)
D1 : Port A TH pin direction (1=input, 0=output) D1 : Port A TH pin direction (1=input, 0=output)
D0 : Port A TR pin direction (1=input, 0=output) D0 : Port A TR pin direction (1=input, 0=output)
*/ */
/* Send TR/TH state to connected peripherals */ /* Send TR/TH state to connected peripherals */
port[0].data_w((data << 1) & 0x60, (~io_reg[0x0F] << 5) & 0x60); port[0].data_w((data << 1) & 0x60, (~data << 5) & 0x60);
port[1].data_w((data >> 1) & 0x60, (~io_reg[0x0F] << 3) & 0x60); port[1].data_w((data >> 1) & 0x60, (~data << 3) & 0x60);
/* Japanese model specific */
/* Check for TH low-to-high transitions on both ports */ if (region_code == REGION_JAPAN_NTSC)
if ((!(io_reg[0x0F] & 0x80) && (data & 0x80)) ||
(!(io_reg[0x0F] & 0x20) && (data & 0x20)))
{
/* Latch new HVC */
hvc_latch = hctab[cycles % MCYCLES_PER_LINE] | 0x10000;
}
/* Update I/O Control register */
io_reg[0x0F] = data;
}
else
{ {
/* TH output is fixed to 0 & TR is always an input on japanese hardware */ /* Reading TH & TR pins always return 0 when set as output */
io_reg[0x0F] = (data | 0x05) & 0x5F; data &= 0x0F;
/* Port $DD bits D4-D5 return D0-D2 (cf. http://www2.odn.ne.jp/~haf09260/Sms/EnrSms.htm) */
io_reg[0x0D] = ((data & 0x01) << 4) | ((data & 0x04) << 3);
} }
/* Check for TH low-to-high transitions on both ports */
if ((!(io_reg[0x0F] & 0x80) && (data & 0x80)) ||
(!(io_reg[0x0F] & 0x20) && (data & 0x20)))
{
/* Latch new HVC */
hvc_latch = hctab[cycles % MCYCLES_PER_LINE] | 0x10000;
}
/* Update I/O Control register */
io_reg[0x0F] = data;
} }
else else
{ {
/* Update Memory Control register */ /* Memory Control register */
io_reg[0x0E] = data; io_reg[0x0E] = data;
/* Switch cartridge & BIOS ROM */ /* Switch cartridge & BIOS ROM */

View File

@ -251,9 +251,10 @@ void z80_md_port_w(unsigned int port, unsigned char data)
{ {
port &= 0xFF; port &= 0xFF;
/* write FM chip if enabled */
if ((port >= 0xF0) && (config.ym2413 & 1)) if ((port >= 0xF0) && (config.ym2413 & 1))
{ {
fm_write(Z80.cycles, port&3, data); fm_write(Z80.cycles, port, data);
return; return;
} }
@ -299,7 +300,7 @@ unsigned char z80_md_port_r(unsigned int port)
/* read FM chip if enabled */ /* read FM chip if enabled */
if ((port >= 0xF0) && (config.ym2413 & 1)) if ((port >= 0xF0) && (config.ym2413 & 1))
{ {
return YM2413Read(port & 3); return YM2413Read();
} }
return z80_unused_port_r(port); return z80_unused_port_r(port);
@ -329,7 +330,7 @@ void z80_gg_port_w(unsigned int port, unsigned char data)
return; return;
} }
z80_unused_port_w(port & 0xFF, data); z80_unused_port_w(port, data);
return; return;
} }
@ -431,13 +432,13 @@ void z80_ms_port_w(unsigned int port, unsigned char data)
case 0x01: case 0x01:
{ {
/* full address range is decoded by 315-5297 I/O chip (fixes Super Tetris / Power Boggle Boggle) */ /* full address range is decoded by 315-5297 I/O chip (fixes Super Tetris / Power Boggle Boggle) */
if ((region_code == REGION_JAPAN_NTSC) && ((port & 0xFE) != 0x3E)) if ((region_code != REGION_JAPAN_NTSC) || ((port & 0xFE) == 0x3E))
{ {
z80_unused_port_w(port & 0xFF, data); io_z80_write(port & 1, data, Z80.cycles + SMS_CYCLE_OFFSET);
return; return;
} }
io_z80_write(port & 1, data, Z80.cycles + SMS_CYCLE_OFFSET); z80_unused_port_w(port & 0xFF, data);
return; return;
} }
@ -462,9 +463,17 @@ void z80_ms_port_w(unsigned int port, unsigned char data)
default: default:
{ {
/* write FM chip if enabled */
if (!(port & 4) && (config.ym2413 & 1)) if (!(port & 4) && (config.ym2413 & 1))
{ {
fm_write(Z80.cycles, port & 3, data); fm_write(Z80.cycles, port, data);
/* 315-5297 I/O chip decodes bit 1 to enable/disable PSG output */
if (region_code == REGION_JAPAN_NTSC)
{
io_reg[6] = (data & 2) ? 0xFF : 0x00;
SN76489_Config(Z80.cycles, config.psg_preamp, config.psgBoostNoise, io_reg[6]);
}
return; return;
} }
@ -506,27 +515,27 @@ unsigned char z80_ms_port_r(unsigned int port)
default: default:
{ {
uint8 data = 0xFF;
/* read FM chip if enabled */ /* read FM chip if enabled */
if (!(port & 4) && (config.ym2413 & 1)) if (!(port & 4) && (config.ym2413 & 1))
{ {
/* check if I/O ports are disabled */ data = YM2413Read();
if (io_reg[0x0E] & 0x04)
/* 315-5297 I/O chip decodes full address range */
if (region_code == REGION_JAPAN_NTSC)
{ {
return YM2413Read(port & 3); return data;
}
else
{
return YM2413Read(port & 3) & io_z80_read(port & 1);
} }
} }
/* check if I/O ports are enabled */ /* read I/O ports if enabled */
if (!(io_reg[0x0E] & 0x04)) if (!(io_reg[0x0E] & 0x04))
{ {
return io_z80_read(port & 1); data &= io_z80_read(port & 1);
} }
return z80_unused_port_r(port & 0xFF); return data;
} }
} }
} }
@ -543,7 +552,7 @@ void z80_m3_port_w(unsigned int port, unsigned char data)
case 0x00: case 0x00:
case 0x01: case 0x01:
{ {
z80_unused_port_w(port, data); z80_unused_port_w(port & 0xFF, data);
return; return;
} }
@ -568,9 +577,10 @@ void z80_m3_port_w(unsigned int port, unsigned char data)
default: default:
{ {
/* write FM chip if enabled */
if (!(port & 4) && (config.ym2413 & 1)) if (!(port & 4) && (config.ym2413 & 1))
{ {
fm_write(Z80.cycles, port & 3, data); fm_write(Z80.cycles, port, data);
return; return;
} }
@ -615,8 +625,8 @@ unsigned char z80_m3_port_r(unsigned int port)
/* read FM chip if enabled */ /* read FM chip if enabled */
if (!(port & 4) && (config.ym2413 & 1)) if (!(port & 4) && (config.ym2413 & 1))
{ {
/* I/O ports are automatically disabled */ /* I/O ports are automatically disabled by hardware */
return YM2413Read(port & 3); return YM2413Read();
} }
/* read I/O ports */ /* read I/O ports */
@ -683,7 +693,7 @@ unsigned char z80_sg_port_r(unsigned int port)
default: default:
{ {
return z80_unused_port_r(port); return z80_unused_port_r(port & 0xFF);
} }
} }
} }

View File

@ -111,6 +111,7 @@ void sound_reset(void)
/* reset sound chips */ /* reset sound chips */
YM_Reset(); YM_Reset();
SN76489_Reset(); SN76489_Reset();
SN76489_Config(0, config.psg_preamp, config.psgBoostNoise, 0xff);
/* reset FM buffer ouput */ /* reset FM buffer ouput */
fm_last[0] = fm_last[1] = 0; fm_last[0] = fm_last[1] = 0;

View File

@ -1658,14 +1658,14 @@ void YM2413Write(unsigned int a, unsigned int v)
} }
else else
{ {
/* latched bit (Master System specific) */ /* bit 0 enable/disable FM output (Master System / Mark-III FM adapter specific) */
ym2413.status = v & 0x01; ym2413.status = v & 0x01;
} }
} }
unsigned int YM2413Read(unsigned int a) unsigned int YM2413Read(void)
{ {
/* D0=latched bit, D1-D2 need to be zero (Master System specific) */ /* bit 0 returns latched FM enable status, bits 1-2 return zero (Master System / Mark-III FM adapter specific) */
return 0xF8 | ym2413.status; return 0xF8 | ym2413.status;
} }

View File

@ -16,7 +16,7 @@ extern void YM2413Init(void);
extern void YM2413ResetChip(void); extern void YM2413ResetChip(void);
extern void YM2413Update(int *buffer, int length); extern void YM2413Update(int *buffer, int length);
extern void YM2413Write(unsigned int a, unsigned int v); extern void YM2413Write(unsigned int a, unsigned int v);
extern unsigned int YM2413Read(unsigned int a); extern unsigned int YM2413Read(void);
extern unsigned char *YM2413GetContextPtr(void); extern unsigned char *YM2413GetContextPtr(void);
extern unsigned int YM2413GetContextSize(void); extern unsigned int YM2413GetContextSize(void);