mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
- Changed S14001A emulator to allow setting the clock frequency instead of the clock multiplier. This is how the real chip works
- Changed the Berzerk driver to set the S14001A clock as per the schematics. This proves that the schematics are correct and the comment suggesting the contrary can be removed.
This commit is contained in:
parent
587c293ee0
commit
4ab04517cb
@ -13,6 +13,8 @@
|
||||
1.01 fixed clipping problem - LN (0.111u5)
|
||||
1.1 add VSU-1000 features, fully fixed stream update by fixing word latching - LN (0.111u6)
|
||||
1.11 fix signedness of output, pre-multiply, fixes clicking on VSU-1000 volume change - LN (0.111u7)
|
||||
1.20 supports setting the clock freq directly - reset is done by external hardware,
|
||||
the chip has no reset line ZV (0.122)
|
||||
|
||||
TODO:
|
||||
* increase accuracy of internal S14001A 'filter' for both driven and undriven cycles (its not terribly inaccurate for undriven cycles, but the dc sliding of driven cycles is not emulated)
|
||||
@ -156,9 +158,7 @@ typedef struct
|
||||
UINT8 audioout; // filtered audio output
|
||||
UINT8 *SpeechRom; // array to hold rom contents, mame will not need this, will use a pointer
|
||||
UINT8 filtervals[8];
|
||||
UINT8 VSU1000_amp; // amplitude setting on VSU-1000 board
|
||||
UINT16 VSU1000_freq; // frequency setting on VSU-1000 board
|
||||
UINT16 VSU1000_counter; // counter for freq divider
|
||||
UINT8 VSU1000_amp; // amplitude setting on VSU-1000 board
|
||||
} S14001AChip;
|
||||
|
||||
//#define DEBUGSTATE
|
||||
@ -437,11 +437,7 @@ static void s14001a_pcm_update(void *param, stream_sample_t **inputs, stream_sam
|
||||
mixp = &mix[0];
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
if (--chip->VSU1000_counter==0)
|
||||
{
|
||||
s14001a_clock(chip);
|
||||
chip->VSU1000_counter = chip->VSU1000_freq;
|
||||
}
|
||||
s14001a_clock(chip);
|
||||
outputs[0][i] = ((((INT16)chip->audioout)-128)<<6)*chip->VSU1000_amp;
|
||||
}
|
||||
}
|
||||
@ -459,9 +455,6 @@ static void *s14001a_start(int sndindex, int clock, const void *config)
|
||||
chip->GlobalSilenceState = 1;
|
||||
chip->OldDelta = 0x02;
|
||||
chip->DACOutput = SILENCE;
|
||||
chip->VSU1000_amp = 0; /* reset by /reset line */
|
||||
chip->VSU1000_freq = 1; /* base-1; reset by /reset line */
|
||||
chip->VSU1000_counter = 1; /* base-1; not reset by /reset line but this is the best place to reset it */
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
@ -472,7 +465,7 @@ static void *s14001a_start(int sndindex, int clock, const void *config)
|
||||
|
||||
chip->SpeechRom = memory_region(intf->region);
|
||||
|
||||
chip->stream = stream_create(0, 1, clock, chip, s14001a_pcm_update);
|
||||
chip->stream = stream_create(0, 1, Machine->sample_rate, chip, s14001a_pcm_update);
|
||||
|
||||
return chip;
|
||||
}
|
||||
@ -488,7 +481,7 @@ static void s14001a_set_info(void *token, UINT32 state, sndinfo *info)
|
||||
int S14001A_bsy_0_r(void)
|
||||
{
|
||||
S14001AChip *chip = sndti_token(SOUND_S14001A, 0);
|
||||
stream_update(chip->stream);
|
||||
stream_update(chip->stream);
|
||||
#ifdef DEBUGSTATE
|
||||
fprintf(stderr,"busy state checked: %d\n",(chip->machineState != 0) );
|
||||
#endif
|
||||
@ -506,43 +499,37 @@ void S14001A_rst_0_w(int data)
|
||||
{
|
||||
S14001AChip *chip = sndti_token(SOUND_S14001A, 0);
|
||||
stream_update(chip->stream);
|
||||
chip->LatchedWord = chip->WordInput;
|
||||
chip->LatchedWord = chip->WordInput;
|
||||
chip->resetState = (data==1);
|
||||
chip->machineState = chip->resetState ? 1 : chip->machineState;
|
||||
}
|
||||
|
||||
void S14001A_set_rate(int newrate)
|
||||
void S14001A_set_clock(int clock)
|
||||
{
|
||||
S14001AChip *chip = sndti_token(SOUND_S14001A, 0);
|
||||
stream_update(chip->stream);
|
||||
chip->VSU1000_freq = newrate;
|
||||
S14001AChip *chip = sndti_token(SOUND_S14001A, 0);
|
||||
stream_set_sample_rate(chip->stream, clock);
|
||||
}
|
||||
|
||||
void S14001A_set_volume(int volume)
|
||||
{
|
||||
S14001AChip *chip = sndti_token(SOUND_S14001A, 0);
|
||||
stream_update(chip->stream);
|
||||
chip->VSU1000_amp = volume;
|
||||
stream_update(chip->stream);
|
||||
chip->VSU1000_amp = volume;
|
||||
}
|
||||
|
||||
void s14001a_get_info(void *token, UINT32 state, sndinfo *info)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
/* --- the following bits of info are returned as 64-bit signed integers --- */
|
||||
|
||||
/* --- the following bits of info are returned as pointers to data or functions --- */
|
||||
case SNDINFO_PTR_SET_INFO: info->set_info = s14001a_set_info; break;
|
||||
case SNDINFO_PTR_START: info->start = s14001a_start; break;
|
||||
case SNDINFO_PTR_STOP: /* Nothing */ break;
|
||||
case SNDINFO_PTR_RESET: /* Nothing */ break;
|
||||
|
||||
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||
case SNDINFO_STR_NAME: info->s = "S14001A"; break;
|
||||
case SNDINFO_STR_CORE_FAMILY: info->s = "TSI S14001A"; break;
|
||||
case SNDINFO_STR_CORE_VERSION: info->s = "1.11"; break;
|
||||
case SNDINFO_STR_NAME: info->s = "S14001A"; break;
|
||||
case SNDINFO_STR_CORE_FAMILY: info->s = "TSI S14001A"; break;
|
||||
case SNDINFO_STR_CORE_VERSION: info->s = "1.20"; break;
|
||||
case SNDINFO_STR_CORE_FILE: info->s = __FILE__; break;
|
||||
case SNDINFO_STR_CORE_CREDITS: info->s = "Copyright Jonathan Gevaryahu"; break;
|
||||
case SNDINFO_STR_CORE_CREDITS: info->s = "Copyright Jonathan Gevaryahu"; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ struct S14001A_interface
|
||||
int S14001A_bsy_0_r(void); /* read BUSY pin */
|
||||
void S14001A_reg_0_w(int data); /* write to input latch */
|
||||
void S14001A_rst_0_w(int data); /* write to RESET pin */
|
||||
void S14001A_set_rate(int newrate); /* set VSU-1000 clock divider */
|
||||
void S14001A_set_clock(int clock); /* set VSU-1000 clock */
|
||||
void S14001A_set_volume(int volume); /* set VSU-1000 volume control */
|
||||
|
||||
#endif
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define MASTER_CLOCK (XTAL_10MHz)
|
||||
#define MAIN_CPU_CLOCK (MASTER_CLOCK / 4)
|
||||
#define PIXEL_CLOCK (MASTER_CLOCK / 2)
|
||||
#define S14001A_CLOCK (MASTER_CLOCK / 2)
|
||||
#define S14001_CLOCK (MASTER_CLOCK / 4)
|
||||
#define HTOTAL (0x140)
|
||||
#define HBEND (0x000)
|
||||
#define HBSTART (0x100)
|
||||
@ -481,41 +481,49 @@ static const struct CustomSound_interface berzerk_custom_interface =
|
||||
|
||||
static WRITE8_HANDLER( berzerk_audio_w )
|
||||
{
|
||||
int clock_divisor;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
/* offset 4 writes to the S14001A */
|
||||
case 4:
|
||||
switch (data >> 6)
|
||||
{
|
||||
/* write data to the S14001 */
|
||||
case 0:
|
||||
/* only if not busy */
|
||||
if (!S14001A_bsy_0_r())
|
||||
{
|
||||
S14001A_reg_0_w(data & 0x3f);
|
||||
|
||||
/* clock the chip -- via a 555 timer */
|
||||
S14001A_rst_0_w(1);
|
||||
S14001A_rst_0_w(0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* volume */
|
||||
S14001A_set_volume(((data & 0x38) >> 3) + 1);
|
||||
|
||||
/* clock control - the first LS161 divides the clock by 9 to 16, the 2nd by 8,
|
||||
giving a final clock from 19.5kHz to 34.7kHz */
|
||||
clock_divisor = 16 - (data & 0x07);
|
||||
|
||||
S14001A_set_clock(S14001_CLOCK / clock_divisor / 8);
|
||||
break;
|
||||
|
||||
default: break; /* 2 and 3 are not connected */
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* offset 6 writes to the sfxcontrol latch */
|
||||
case 6:
|
||||
exidy_sfxctrl_w(data >> 6, data);
|
||||
break;
|
||||
|
||||
/* offset 4 writes to the S14001A */
|
||||
case 4:
|
||||
if ((data & 0xc0) == 0x40) /* VSU-1000 control write */
|
||||
{
|
||||
/* volume and frequency control goes here */
|
||||
/* mame_printf_debug("TODO: VSU-1000 Control write (ignored for now)\n");*/
|
||||
S14001A_set_volume(((data & 0x38) >> 3) + 1);
|
||||
S14001A_set_rate((16 - (data & 0x07)) * 16); /* second LS161 has load triggered by its own TC(when it equals 16) long before the first ls161 will TC and fire again, so effectively it only divides by 15 and not 16. If the clock, as opposed to the E enable, had been tied to the first LS161's TC instead, it would divide by 16 as expected */
|
||||
}
|
||||
else if ((data & 0xc0) != 0x00)
|
||||
/* vsu-1000 ignores these writes entirely */
|
||||
mame_printf_debug("bogus write ignored\n");
|
||||
else
|
||||
{
|
||||
/* select word input */
|
||||
if (S14001A_bsy_0_r()) /* skip if busy... */
|
||||
{
|
||||
mame_printf_debug("S14001A busy, ignoring write\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* write to the register */
|
||||
S14001A_reg_0_w(data & 0x3f);
|
||||
S14001A_rst_0_w(1);
|
||||
S14001A_rst_0_w(0);
|
||||
}
|
||||
break;
|
||||
|
||||
/* everything else writes to the 6840 */
|
||||
default:
|
||||
exidy_sh6840_w(offset, data);
|
||||
@ -532,6 +540,14 @@ static READ8_HANDLER( berzerk_audio_r )
|
||||
|
||||
|
||||
|
||||
static SOUND_RESET(berzerk)
|
||||
{
|
||||
/* clears the flip-flop controlling the volume and freq on the speech chip */
|
||||
berzerk_audio_w(4, 0x40);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Memory handlers
|
||||
@ -866,7 +882,9 @@ static MACHINE_DRIVER_START( berzerk )
|
||||
/* audio hardware */
|
||||
MDRV_SPEAKER_STANDARD_MONO("mono")
|
||||
|
||||
MDRV_SOUND_ADD(S14001A, S14001A_CLOCK) /* CPU clock divided by 16 divided by a programmable TTL setup */
|
||||
MDRV_SOUND_RESET(berzerk)
|
||||
|
||||
MDRV_SOUND_ADD(S14001A, 0) /* placeholder - the clock is software controllable */
|
||||
MDRV_SOUND_CONFIG(berzerk_s14001a_interface)
|
||||
MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user