diff --git a/core/io_ctrl.c b/core/io_ctrl.c index 3800f17..c4803ab 100644 --- a/core/io_ctrl.c +++ b/core/io_ctrl.c @@ -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) { + /* I/O Control register */ if (offset) { - /* I/O Control register */ - if (region_code & REGION_USA) - { - /* + /* Bit Function -------------- 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) D1 : Port A TH pin direction (1=input, 0=output) D0 : Port A TR pin direction (1=input, 0=output) - */ + */ - /* Send TR/TH state to connected peripherals */ - port[0].data_w((data << 1) & 0x60, (~io_reg[0x0F] << 5) & 0x60); - port[1].data_w((data >> 1) & 0x60, (~io_reg[0x0F] << 3) & 0x60); + /* Send TR/TH state to connected peripherals */ + port[0].data_w((data << 1) & 0x60, (~data << 5) & 0x60); + port[1].data_w((data >> 1) & 0x60, (~data << 3) & 0x60); - - /* 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 + /* Japanese model specific */ + if (region_code == REGION_JAPAN_NTSC) { - /* TH output is fixed to 0 & TR is always an input on japanese hardware */ - io_reg[0x0F] = (data | 0x05) & 0x5F; - - /* 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); + /* Reading TH & TR pins always return 0 when set as output */ + data &= 0x0F; } + + /* 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 { - /* Update Memory Control register */ + /* Memory Control register */ io_reg[0x0E] = data; /* Switch cartridge & BIOS ROM */ diff --git a/core/memz80.c b/core/memz80.c index 0165114..c679910 100644 --- a/core/memz80.c +++ b/core/memz80.c @@ -251,9 +251,10 @@ void z80_md_port_w(unsigned int port, unsigned char data) { port &= 0xFF; + /* write FM chip if enabled */ if ((port >= 0xF0) && (config.ym2413 & 1)) { - fm_write(Z80.cycles, port&3, data); + fm_write(Z80.cycles, port, data); return; } @@ -299,7 +300,7 @@ unsigned char z80_md_port_r(unsigned int port) /* read FM chip if enabled */ if ((port >= 0xF0) && (config.ym2413 & 1)) { - return YM2413Read(port & 3); + return YM2413Read(); } return z80_unused_port_r(port); @@ -329,7 +330,7 @@ void z80_gg_port_w(unsigned int port, unsigned char data) return; } - z80_unused_port_w(port & 0xFF, data); + z80_unused_port_w(port, data); return; } @@ -431,13 +432,13 @@ void z80_ms_port_w(unsigned int port, unsigned char data) case 0x01: { /* 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; } - io_z80_write(port & 1, data, Z80.cycles + SMS_CYCLE_OFFSET); + z80_unused_port_w(port & 0xFF, data); return; } @@ -462,9 +463,17 @@ void z80_ms_port_w(unsigned int port, unsigned char data) default: { + /* write FM chip if enabled */ 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; } @@ -506,27 +515,27 @@ unsigned char z80_ms_port_r(unsigned int port) default: { + uint8 data = 0xFF; + /* read FM chip if enabled */ if (!(port & 4) && (config.ym2413 & 1)) { - /* check if I/O ports are disabled */ - if (io_reg[0x0E] & 0x04) + data = YM2413Read(); + + /* 315-5297 I/O chip decodes full address range */ + if (region_code == REGION_JAPAN_NTSC) { - return YM2413Read(port & 3); - } - else - { - return YM2413Read(port & 3) & io_z80_read(port & 1); + return data; } } - /* check if I/O ports are enabled */ + /* read I/O ports if enabled */ 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 0x01: { - z80_unused_port_w(port, data); + z80_unused_port_w(port & 0xFF, data); return; } @@ -568,9 +577,10 @@ void z80_m3_port_w(unsigned int port, unsigned char data) default: { + /* write FM chip if enabled */ if (!(port & 4) && (config.ym2413 & 1)) { - fm_write(Z80.cycles, port & 3, data); + fm_write(Z80.cycles, port, data); return; } @@ -615,8 +625,8 @@ unsigned char z80_m3_port_r(unsigned int port) /* read FM chip if enabled */ if (!(port & 4) && (config.ym2413 & 1)) { - /* I/O ports are automatically disabled */ - return YM2413Read(port & 3); + /* I/O ports are automatically disabled by hardware */ + return YM2413Read(); } /* read I/O ports */ @@ -683,7 +693,7 @@ unsigned char z80_sg_port_r(unsigned int port) default: { - return z80_unused_port_r(port); + return z80_unused_port_r(port & 0xFF); } } } diff --git a/core/sound/sound.c b/core/sound/sound.c index 093b638..06bea1a 100644 --- a/core/sound/sound.c +++ b/core/sound/sound.c @@ -111,6 +111,7 @@ void sound_reset(void) /* reset sound chips */ YM_Reset(); SN76489_Reset(); + SN76489_Config(0, config.psg_preamp, config.psgBoostNoise, 0xff); /* reset FM buffer ouput */ fm_last[0] = fm_last[1] = 0; diff --git a/core/sound/ym2413.c b/core/sound/ym2413.c index b71fbdf..ad453fa 100644 --- a/core/sound/ym2413.c +++ b/core/sound/ym2413.c @@ -1658,14 +1658,14 @@ void YM2413Write(unsigned int a, unsigned int v) } else { - /* latched bit (Master System specific) */ + /* bit 0 enable/disable FM output (Master System / Mark-III FM adapter specific) */ 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; } diff --git a/core/sound/ym2413.h b/core/sound/ym2413.h index 73c8c84..ceb48bf 100644 --- a/core/sound/ym2413.h +++ b/core/sound/ym2413.h @@ -16,7 +16,7 @@ extern void YM2413Init(void); extern void YM2413ResetChip(void); extern void YM2413Update(int *buffer, int length); 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 int YM2413GetContextSize(void);