modernised TMS5220 [smf]
This commit is contained in:
parent
25cb3c0cda
commit
d700c1f372
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -1402,6 +1402,8 @@ src/emu/machine/smc91c9x.c svneol=native#text/plain
|
||||
src/emu/machine/smc91c9x.h svneol=native#text/plain
|
||||
src/emu/machine/smpc.c svneol=native#text/plain
|
||||
src/emu/machine/smpc.h svneol=native#text/plain
|
||||
src/emu/machine/spchrom.c svneol=native#text/plain
|
||||
src/emu/machine/spchrom.h svneol=native#text/plain
|
||||
src/emu/machine/stvcd.c svneol=native#text/plain
|
||||
src/emu/machine/tc009xlvc.c svneol=native#text/plain
|
||||
src/emu/machine/tc009xlvc.h svneol=native#text/plain
|
||||
@ -5927,8 +5929,6 @@ src/mess/audio/mea8000.c svneol=native#text/plain
|
||||
src/mess/audio/mea8000.h svneol=native#text/plain
|
||||
src/mess/audio/socrates.c svneol=native#text/plain
|
||||
src/mess/audio/socrates.h svneol=native#text/plain
|
||||
src/mess/audio/spchroms.c svneol=native#text/plain
|
||||
src/mess/audio/spchroms.h svneol=native#text/plain
|
||||
src/mess/audio/special.c svneol=native#text/plain
|
||||
src/mess/audio/svision.c svneol=native#text/plain
|
||||
src/mess/audio/tvc.c svneol=native#text/plain
|
||||
|
115
src/emu/machine/spchrom.c
Normal file
115
src/emu/machine/spchrom.c
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
spchroms.c - This is an emulator for "typical" speech ROMs from TI, as used by TI99/4(a).
|
||||
|
||||
In order to support its speech processor, TI designed some ROMs with a 1-bit data bus
|
||||
and 4-bit address bus (multiplexed 5 times to provide a 18-bit address).
|
||||
A fairly complete description of such a ROM (tms6100) is found in the tms5220 datasheet.
|
||||
|
||||
One notable thing is that the address is a byte address (*NOT* a bit address).
|
||||
|
||||
This file is designed to be interfaced with the tms5220 core.
|
||||
Interfacing it with the tms5110 would make sense, too.
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "spchrom.h"
|
||||
|
||||
#define TMS5220_ADDRESS_MASK 0x3FFFFUL /* 18-bit mask for tms5220 address */
|
||||
|
||||
// device type definition
|
||||
const device_type SPEECHROM = &device_creator<speechrom_device>;
|
||||
|
||||
speechrom_device::speechrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, SPEECHROM, "SPEECHROM", tag, owner, clock),
|
||||
m_speechROMaddr(0),
|
||||
m_load_pointer(0),
|
||||
m_ROM_bits_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
Read 'count' bits serially from speech ROM
|
||||
*/
|
||||
int speechrom_device::read(int count)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (m_load_pointer)
|
||||
{ /* first read after load address is ignored */
|
||||
m_load_pointer = 0;
|
||||
count--;
|
||||
}
|
||||
|
||||
if (m_speechROMaddr < m_speechROMlen)
|
||||
if (count < m_ROM_bits_count)
|
||||
{
|
||||
m_ROM_bits_count -= count;
|
||||
val = (m_speechrom_data[m_speechROMaddr] >> m_ROM_bits_count) & (0xFF >> (8 - count));
|
||||
}
|
||||
else
|
||||
{
|
||||
val = ((int) m_speechrom_data[m_speechROMaddr]) << 8;
|
||||
|
||||
m_speechROMaddr = (m_speechROMaddr + 1) & TMS5220_ADDRESS_MASK;
|
||||
|
||||
if (m_speechROMaddr < m_speechROMlen)
|
||||
val |= m_speechrom_data[m_speechROMaddr];
|
||||
|
||||
m_ROM_bits_count += 8 - count;
|
||||
|
||||
val = (val >> m_ROM_bits_count) & (0xFF >> (8 - count));
|
||||
}
|
||||
else
|
||||
val = 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
Write an address nibble to speech ROM
|
||||
*/
|
||||
void speechrom_device::load_address(int data)
|
||||
{
|
||||
/* tms5220 data sheet says that if we load only one 4-bit nibble, it won't work.
|
||||
This code does not care about this. */
|
||||
m_speechROMaddr = ( (m_speechROMaddr & ~(0xf << m_load_pointer))
|
||||
| (((unsigned long) (data & 0xf)) << m_load_pointer) ) & TMS5220_ADDRESS_MASK;
|
||||
m_load_pointer += 4;
|
||||
m_ROM_bits_count = 8;
|
||||
}
|
||||
|
||||
/*
|
||||
Perform a read and branch command
|
||||
*/
|
||||
void speechrom_device::read_and_branch()
|
||||
{
|
||||
/* tms5220 data sheet says that if more than one speech ROM (tms6100) is present,
|
||||
there is a bus contention. This code does not care about this. */
|
||||
if (m_speechROMaddr < m_speechROMlen-1)
|
||||
m_speechROMaddr = (m_speechROMaddr & 0x3c000UL)
|
||||
| (((((unsigned long) m_speechrom_data[m_speechROMaddr]) << 8)
|
||||
| m_speechrom_data[m_speechROMaddr+1]) & 0x3fffUL);
|
||||
else if (m_speechROMaddr == m_speechROMlen-1)
|
||||
m_speechROMaddr = (m_speechROMaddr & 0x3c000UL)
|
||||
| ((((unsigned long) m_speechrom_data[m_speechROMaddr]) << 8) & 0x3fffUL);
|
||||
else
|
||||
m_speechROMaddr = (m_speechROMaddr & 0x3c000UL);
|
||||
|
||||
m_ROM_bits_count = 8;
|
||||
}
|
||||
|
||||
void speechrom_device::device_start()
|
||||
{
|
||||
memory_region *region = memregion(tag());
|
||||
if (region == NULL)
|
||||
{
|
||||
throw emu_fatalerror("No region for device '%s'\n", tag());
|
||||
}
|
||||
|
||||
m_speechrom_data = region->base();
|
||||
m_speechROMlen = region->bytes();
|
||||
|
||||
save_item(NAME(m_speechROMaddr));
|
||||
save_item(NAME(m_load_pointer));
|
||||
save_item(NAME(m_ROM_bits_count));
|
||||
}
|
37
src/emu/machine/spchrom.h
Normal file
37
src/emu/machine/spchrom.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Voice Synthesis Memory
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SPCHROMS_H
|
||||
#define __SPCHROMS_H
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
class speechrom_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
speechrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
/// TODO: implement bus behaviour
|
||||
int read(int count);
|
||||
void load_address(int data);
|
||||
void read_and_branch();
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
|
||||
private:
|
||||
UINT8 *m_speechrom_data; /* pointer to speech ROM data */
|
||||
unsigned long m_speechROMlen; /* length of data pointed by speechrom_data, from 0 to 2^18 */
|
||||
unsigned long m_speechROMaddr; /* 18 bit pointer in ROM */
|
||||
int m_load_pointer; /* which 4-bit nibble will be affected by load address */
|
||||
int m_ROM_bits_count; /* current bit position in ROM */
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type SPEECHROM;
|
||||
|
||||
#endif
|
@ -644,7 +644,7 @@ $(SOUNDOBJ)/tms5110.o: $(SOUNDSRC)/tms5110r.c
|
||||
# Texas Instruments TMS5200-series speech synthesizers
|
||||
#-------------------------------------------------
|
||||
ifneq ($(filter TMS5220,$(SOUNDS)),)
|
||||
SOUNDOBJS += $(SOUNDOBJ)/tms5220.o
|
||||
SOUNDOBJS += $(SOUNDOBJ)/tms5220.o $(EMUMACHINE)/spchrom.o
|
||||
endif
|
||||
|
||||
$(SOUNDOBJ)/tms5220.o: $(SOUNDSRC)/tms5110r.c
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,11 @@
|
||||
#ifndef __TMS5220_H__
|
||||
#define __TMS5220_H__
|
||||
|
||||
#include "devlegcy.h"
|
||||
#include "emu.h"
|
||||
#include "machine/spchrom.h"
|
||||
|
||||
/* HACK: if defined, uses impossibly perfect 'straight line' interpolation */
|
||||
#undef PERFECT_INTERPOLATION_HACK
|
||||
|
||||
#define FIFO_SIZE 16
|
||||
|
||||
@ -11,35 +15,16 @@
|
||||
/* usually 640000 for 8000 Hz sample rate or */
|
||||
/* usually 800000 for 10000 Hz sample rate. */
|
||||
|
||||
struct tms5220_interface
|
||||
{
|
||||
devcb_write_line irq_func; /* IRQ callback function, active low, i.e. state=0 */
|
||||
devcb_write_line readyq_func; /* Ready callback function, active low, i.e. state=0 */
|
||||
/* IRQ callback function, active low, i.e. state=0 */
|
||||
#define MCFG_TMS52XX_IRQ_HANDLER(_devcb) \
|
||||
devcb = &tms5220_device::set_irq_handler(*device, DEVCB2_##_devcb);
|
||||
|
||||
int (*read)(device_t *device, int count); /* speech ROM read callback */
|
||||
void (*load_address)(device_t *device, int data); /* speech ROM load address callback */
|
||||
void (*read_and_branch)(device_t *device); /* speech ROM read and branch callback */
|
||||
};
|
||||
/* Ready callback function, active low, i.e. state=0 */
|
||||
#define MCFG_TMS52XX_READYQ_HANDLER(_devcb) \
|
||||
devcb = &tms5220_device::set_readyq_handler(*device, DEVCB2_##_devcb);
|
||||
|
||||
/* Control lines - once written to will switch interface into
|
||||
* "true" timing behaviour.
|
||||
*/
|
||||
|
||||
/* all lines with suffix q are active low! */
|
||||
|
||||
WRITE_LINE_DEVICE_HANDLER( tms5220_rsq_w );
|
||||
WRITE_LINE_DEVICE_HANDLER( tms5220_wsq_w );
|
||||
|
||||
DECLARE_WRITE8_DEVICE_HANDLER( tms5220_data_w );
|
||||
DECLARE_READ8_DEVICE_HANDLER( tms5220_status_r );
|
||||
|
||||
READ_LINE_DEVICE_HANDLER( tms5220_readyq_r );
|
||||
READ_LINE_DEVICE_HANDLER( tms5220_intq_r );
|
||||
|
||||
|
||||
double tms5220_time_to_ready(device_t *device);
|
||||
|
||||
void tms5220_set_frequency(device_t *device, int frequency);
|
||||
#define MCFG_TMS52XX_SPEECHROM(_tag) \
|
||||
tms5220_device::set_speechrom_tag(*device, _tag);
|
||||
|
||||
class tms5220_device : public device_t,
|
||||
public device_sound_interface
|
||||
@ -47,21 +32,175 @@ class tms5220_device : public device_t,
|
||||
public:
|
||||
tms5220_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
tms5220_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
||||
~tms5220_device() { global_free(m_token); }
|
||||
|
||||
// access to legacy token
|
||||
void *token() const { assert(m_token != NULL); return m_token; }
|
||||
// static configuration helpers
|
||||
template<class _Object> static devcb2_base &set_irq_handler(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_irq_handler.set_callback(object); }
|
||||
template<class _Object> static devcb2_base &set_readyq_handler(device_t &device, _Object object) { return downcast<tms5220_device &>(device).m_readyq_handler.set_callback(object); }
|
||||
static void set_speechrom_tag(device_t &device, const char *_tag) { downcast<tms5220_device &>(device).m_speechrom_tag = _tag; }
|
||||
|
||||
/* Control lines - once written to will switch interface into
|
||||
* "true" timing behaviour.
|
||||
*/
|
||||
|
||||
/* all lines with suffix q are active low! */
|
||||
|
||||
WRITE_LINE_MEMBER( rsq_w );
|
||||
WRITE_LINE_MEMBER( wsq_w );
|
||||
|
||||
DECLARE_WRITE8_MEMBER( data_w );
|
||||
DECLARE_READ8_MEMBER( status_r );
|
||||
|
||||
READ_LINE_MEMBER( readyq_r );
|
||||
READ_LINE_MEMBER( intq_r );
|
||||
|
||||
double time_to_ready();
|
||||
|
||||
void set_frequency(int frequency);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
// sound stream update overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
|
||||
void set_variant(int variant);
|
||||
|
||||
private:
|
||||
void register_for_save_states();
|
||||
void data_write(int data);
|
||||
void update_status_and_ints();
|
||||
int extract_bits(int count);
|
||||
int status_read();
|
||||
int ready_read();
|
||||
int cycles_to_ready();
|
||||
int int_read();
|
||||
void process(INT16 *buffer, unsigned int size);
|
||||
INT32 lattice_filter();
|
||||
void process_command(unsigned char cmd);
|
||||
void parse_frame();
|
||||
void set_interrupt_state(int state);
|
||||
void update_ready_state();
|
||||
|
||||
// internal state
|
||||
void *m_token;
|
||||
|
||||
/* coefficient tables */
|
||||
int m_variant; /* Variant of the 5xxx - see tms5110r.h */
|
||||
|
||||
/* coefficient tables */
|
||||
const struct tms5100_coeffs *m_coeff;
|
||||
|
||||
/* these contain data that describes the 128-bit data FIFO */
|
||||
UINT8 m_fifo[FIFO_SIZE];
|
||||
UINT8 m_fifo_head;
|
||||
UINT8 m_fifo_tail;
|
||||
UINT8 m_fifo_count;
|
||||
UINT8 m_fifo_bits_taken;
|
||||
|
||||
|
||||
/* these contain global status bits */
|
||||
UINT8 m_speaking_now; /* True only if actual speech is being generated right now. Is set when a speak vsm command happens OR when speak external happens and buffer low becomes nontrue; Is cleared when speech halts after the last stop frame or the last frame after talk status is otherwise cleared.*/
|
||||
UINT8 m_speak_external; /* If 1, DDIS is 1, i.e. Speak External command in progress, writes go to FIFO. */
|
||||
UINT8 m_talk_status; /* If 1, TS status bit is 1, i.e. speak or speak external is in progress and we have not encountered a stop frame yet; talk_status differs from speaking_now in that speaking_now is set as soon as a speak or speak external command is started; talk_status does NOT go active until after 8 bytes are written to the fifo on a speak external command, otherwise the two are the same. TS is cleared by 3 things: 1. when a STOP command has just been processed as a new frame in the speech stream; 2. if the fifo runs out in speak external mode; 3. on power-up/during a reset command; When it gets cleared, speak_external is also cleared, an interrupt is generated, and speaking_now will be cleared when the next frame starts. */
|
||||
UINT8 m_buffer_low; /* If 1, FIFO has less than 8 bytes in it */
|
||||
UINT8 m_buffer_empty; /* If 1, FIFO is empty */
|
||||
UINT8 m_irq_pin; /* state of the IRQ pin (output) */
|
||||
UINT8 m_ready_pin; /* state of the READY pin (output) */
|
||||
|
||||
/* these contain data describing the current and previous voice frames */
|
||||
#define OLD_FRAME_SILENCE_FLAG m_OLDE // 1 if E=0, 0 otherwise.
|
||||
#define OLD_FRAME_UNVOICED_FLAG m_OLDP // 1 if P=0 (unvoiced), 0 if voiced
|
||||
UINT8 m_OLDE;
|
||||
UINT8 m_OLDP;
|
||||
|
||||
#define NEW_FRAME_STOP_FLAG (m_new_frame_energy_idx == 0xF) // 1 if this is a stop (Energy = 0xF) frame
|
||||
#define NEW_FRAME_SILENCE_FLAG (m_new_frame_energy_idx == 0) // ditto as above
|
||||
#define NEW_FRAME_UNVOICED_FLAG (m_new_frame_pitch_idx == 0) // ditto as above
|
||||
UINT8 m_new_frame_energy_idx;
|
||||
UINT8 m_new_frame_pitch_idx;
|
||||
UINT8 m_new_frame_k_idx[10];
|
||||
|
||||
|
||||
/* these are all used to contain the current state of the sound generation */
|
||||
#ifndef PERFECT_INTERPOLATION_HACK
|
||||
INT16 m_current_energy;
|
||||
INT16 m_current_pitch;
|
||||
INT16 m_current_k[10];
|
||||
|
||||
INT16 m_target_energy;
|
||||
INT16 m_target_pitch;
|
||||
INT16 m_target_k[10];
|
||||
#else
|
||||
UINT8 m_old_frame_energy_idx;
|
||||
UINT8 m_old_frame_pitch_idx;
|
||||
UINT8 m_old_frame_k_idx[10];
|
||||
|
||||
INT32 m_current_energy;
|
||||
INT32 m_current_pitch;
|
||||
INT32 m_current_k[10];
|
||||
|
||||
INT32 m_target_energy;
|
||||
INT32 m_target_pitch;
|
||||
INT32 m_target_k[10];
|
||||
#endif
|
||||
|
||||
UINT16 m_previous_energy; /* needed for lattice filter to match patent */
|
||||
|
||||
UINT8 m_subcycle; /* contains the current subcycle for a given PC: 0 is A' (only used on SPKSLOW mode on 51xx), 1 is A, 2 is B */
|
||||
UINT8 m_subc_reload; /* contains 1 for normal speech, 0 when SPKSLOW is active */
|
||||
UINT8 m_PC; /* current parameter counter (what param is being interpolated), ranges from 0 to 12 */
|
||||
/* TODO/NOTE: the current interpolation period, counts 1,2,3,4,5,6,7,0 for divide by 8,8,8,4,4,2,2,1 */
|
||||
UINT8 m_IP; /* the current interpolation period */
|
||||
UINT8 m_inhibit; /* If 1, interpolation is inhibited until the DIV1 period */
|
||||
UINT8 m_tms5220c_rate; /* only relevant for tms5220C's multi frame rate feature; is the actual 4 bit value written on a 0x2* or 0x0* command */
|
||||
UINT16 m_pitch_count; /* pitch counter; provides chirp rom address */
|
||||
|
||||
INT32 m_u[11];
|
||||
INT32 m_x[10];
|
||||
|
||||
UINT16 m_RNG; /* the random noise generator configuration is: 1 + x + x^3 + x^4 + x^13 */
|
||||
INT16 m_excitation_data;
|
||||
|
||||
/* R Nabet : These have been added to emulate speech Roms */
|
||||
UINT8 m_schedule_dummy_read; /* set after each load address, so that next read operation is preceded by a dummy read */
|
||||
UINT8 m_data_register; /* data register, used by read command */
|
||||
UINT8 m_RDB_flag; /* whether we should read data register or status register */
|
||||
|
||||
/* io_ready: page 3 of the datasheet specifies that READY will be asserted until
|
||||
* data is available or processed by the system.
|
||||
*/
|
||||
UINT8 m_io_ready;
|
||||
|
||||
/* flag for "true" timing involving rs/ws */
|
||||
UINT8 m_true_timing;
|
||||
|
||||
/* rsws - state, rs bit 1, ws bit 0 */
|
||||
UINT8 m_rs_ws;
|
||||
UINT8 m_read_latch;
|
||||
UINT8 m_write_latch;
|
||||
|
||||
/* The TMS52xx has two different ways of providing output data: the
|
||||
analog speaker pin (which was usually used) and the Digital I/O pin.
|
||||
The internal DAC used to feed the analog pin is only 8 bits, and has the
|
||||
funny clipping/clamping logic, while the digital pin gives full 10 bit
|
||||
resolution of the output data.
|
||||
TODO: add a way to set/reset this other than the FORCE_DIGITAL define
|
||||
*/
|
||||
UINT8 m_digital_select;
|
||||
|
||||
sound_stream *m_stream;
|
||||
int m_clock;
|
||||
emu_timer *m_timer_io_ready;
|
||||
|
||||
/* callbacks */
|
||||
devcb2_write_line m_irq_handler;
|
||||
devcb2_write_line m_readyq_handler;
|
||||
const char *m_speechrom_tag;
|
||||
speechrom_device *m_speechrom;
|
||||
};
|
||||
|
||||
extern const device_type TMS5220;
|
||||
@ -73,9 +212,6 @@ public:
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
|
||||
// sound stream update overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
};
|
||||
|
||||
extern const device_type TMS5220C;
|
||||
@ -87,9 +223,6 @@ public:
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
|
||||
// sound stream update overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
};
|
||||
|
||||
extern const device_type TMC0285;
|
||||
@ -101,213 +234,8 @@ public:
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
|
||||
// sound stream update overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
};
|
||||
|
||||
extern const device_type TMS5200;
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
New class implementation
|
||||
Michael Zapf, June 2012
|
||||
***************************************************************************/
|
||||
|
||||
extern const device_type TMS5220N;
|
||||
extern const device_type TMS5220CN;
|
||||
extern const device_type TMC0285N;
|
||||
extern const device_type TMS5200N;
|
||||
|
||||
|
||||
struct tms52xx_config
|
||||
{
|
||||
devcb_write_line irq_func; // IRQ callback function, active low, i.e. state=0 (TODO: change to ASSERT/CLEAR)
|
||||
devcb_write_line readyq_func; // Ready callback function, active low, i.e. state=0
|
||||
|
||||
devcb_read8 read_mem; // speech ROM read callback
|
||||
devcb_write8 load_address; // speech ROM load address callback
|
||||
devcb_write8 read_and_branch; // speech ROM read and branch callback
|
||||
|
||||
};
|
||||
|
||||
// Change back from 5220n to 5220 when all client drivers will be converted
|
||||
class tms52xx_device : public device_t, public device_sound_interface
|
||||
{
|
||||
public:
|
||||
tms52xx_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, const struct tms5100_coeffs* coeffs, const int var, device_t *owner, UINT32 clock);
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER( rsq_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( wsq_w );
|
||||
DECLARE_WRITE8_MEMBER( write );
|
||||
DECLARE_READ8_MEMBER( read );
|
||||
DECLARE_READ_LINE_MEMBER( readyq );
|
||||
DECLARE_READ_LINE_MEMBER( intq );
|
||||
|
||||
double time_to_ready();
|
||||
|
||||
protected:
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
private:
|
||||
// Methods
|
||||
void set_interrupt_state(int state);
|
||||
void register_for_save_states();
|
||||
void update_ready_state();
|
||||
void set_frequency(int frequency);
|
||||
void process(INT16 *buffer, unsigned int size);
|
||||
void data_write(int data);
|
||||
void update_status_and_ints();
|
||||
void parse_frame();
|
||||
|
||||
int extract_bits(int count);
|
||||
int status_read();
|
||||
int cycles_to_ready();
|
||||
INT32 lattice_filter();
|
||||
void process_command(unsigned char cmd);
|
||||
|
||||
inline bool ready_read();
|
||||
inline int int_read();
|
||||
|
||||
// coefficient tables
|
||||
const int m_variant; // Variant of the 5xxx - see tms5110r.h
|
||||
|
||||
// coefficient tables
|
||||
const struct tms5100_coeffs *m_coeff;
|
||||
|
||||
// callbacks
|
||||
devcb_resolved_write_line m_irq_func;
|
||||
devcb_resolved_write_line m_readyq_func;
|
||||
devcb_resolved_read8 m_read_mem;
|
||||
devcb_resolved_write8 m_load_address;
|
||||
devcb_resolved_write8 m_read_and_branch;
|
||||
|
||||
// these contain data that describes the 128-bit data FIFO
|
||||
UINT8 m_fifo[FIFO_SIZE];
|
||||
UINT8 m_fifo_head;
|
||||
UINT8 m_fifo_tail;
|
||||
int m_fifo_count;
|
||||
int m_fifo_bits_taken;
|
||||
|
||||
// these contain global status bits
|
||||
bool m_speaking_now; // True only if actual speech is being generated right now. Is set when a speak vsm command happens OR when speak external happens and buffer low becomes nontrue; Is cleared when speech halts after the last stop frame or the last frame after talk status is otherwise cleared.
|
||||
bool m_speak_external; // If 1, DDIS is 1, i.e. Speak External command in progress, writes go to FIFO.
|
||||
bool m_talk_status; // If 1, TS status bit is 1, i.e. speak or speak external is in progress and we have not encountered a stop frame yet; talk_status differs from speaking_now in that speaking_now is set as soon as a speak or speak external command is started; talk_status does NOT go active until after 8 bytes are written to the fifo on a speak external command, otherwise the two are the same. TS is cleared by 3 things: 1. when a STOP command has just been processed as a new frame in the speech stream; 2. if the fifo runs out in speak external mode; 3. on power-up/during a reset command; When it gets cleared, speak_external is also cleared, an interrupt is generated, and speaking_now will be cleared when the next frame starts.
|
||||
bool m_buffer_low; // If 1, FIFO has less than 8 bytes in it
|
||||
bool m_buffer_empty; // If 1, FIFO is empty
|
||||
int m_irq_pin; // state of the IRQ pin (output)
|
||||
int m_ready_pin; // state of the READY pin (output)
|
||||
|
||||
// these contain data describing the current and previous voice frames
|
||||
#define M_OLD_FRAME_SILENCE_FLAG m_OLDE // 1 if E=0, 0 otherwise.
|
||||
#define M_OLD_FRAME_UNVOICED_FLAG m_OLDP // 1 if P=0 (unvoiced), 0 if voiced
|
||||
bool m_OLDE;
|
||||
bool m_OLDP;
|
||||
|
||||
#define M_NEW_FRAME_STOP_FLAG (m_new_frame_energy_idx == 0xF) // 1 if this is a stop (Energy = 0xF) frame
|
||||
#define M_NEW_FRAME_SILENCE_FLAG (m_new_frame_energy_idx == 0) // ditto as above
|
||||
#define M_NEW_FRAME_UNVOICED_FLAG (m_new_frame_pitch_idx == 0) // ditto as above
|
||||
int m_new_frame_energy_idx;
|
||||
int m_new_frame_pitch_idx;
|
||||
int m_new_frame_k_idx[10];
|
||||
|
||||
// these are all used to contain the current state of the sound generation
|
||||
#ifndef PERFECT_INTERPOLATION_HACK
|
||||
INT16 m_current_energy;
|
||||
INT16 m_current_pitch;
|
||||
INT16 m_current_k[10];
|
||||
|
||||
INT16 m_target_energy;
|
||||
INT16 m_target_pitch;
|
||||
INT16 m_target_k[10];
|
||||
#else
|
||||
int m_old_frame_energy_idx;
|
||||
int m_old_frame_pitch_idx;
|
||||
int m_old_frame_k_idx[10];
|
||||
|
||||
INT32 m_current_energy;
|
||||
INT32 m_current_pitch;
|
||||
INT32 m_current_k[10];
|
||||
|
||||
INT32 m_target_energy;
|
||||
INT32 m_target_pitch;
|
||||
INT32 m_target_k[10];
|
||||
#endif
|
||||
|
||||
UINT16 m_previous_energy; // needed for lattice filter to match patent
|
||||
int m_subcycle; // contains the current subcycle for a given PC: 0 is A' (only used on SPKSLOW mode on 51xx), 1 is A, 2 is B
|
||||
int m_subc_reload; // contains 1 for normal speech, 0 when SPKSLOW is active
|
||||
int m_PC; // current parameter counter (what param is being interpolated), ranges from 0 to 12
|
||||
|
||||
// TODO/NOTE: the current interpolation period, counts 1,2,3,4,5,6,7,0 for divide by 8,8,8,4,4,2,2,1
|
||||
int m_IP; // the current interpolation period
|
||||
bool m_inhibit; // If 1, interpolation is inhibited until the DIV1 period
|
||||
UINT8 m_tms5220c_rate; // only relevant for tms5220C's multi frame rate feature; is the actual 4 bit value written on a 0x2* or 0x0* command
|
||||
UINT16 m_pitch_count; // pitch counter; provides chirp rom address
|
||||
|
||||
INT32 m_u[11];
|
||||
INT32 m_x[10];
|
||||
|
||||
UINT16 m_RNG; // the random noise generator configuration is: 1 + x + x^3 + x^4 + x^13
|
||||
INT16 m_excitation_data;
|
||||
|
||||
// R Nabet : These have been added to emulate speech Roms
|
||||
bool m_schedule_dummy_read; // set after each load address, so that next read operation is preceded by a dummy read
|
||||
UINT8 m_data_register; // data register, used by read command
|
||||
bool m_RDB_flag; // whether we should read data register or status register
|
||||
|
||||
// io_ready: page 3 of the datasheet specifies that READY will be asserted until
|
||||
// data is available or processed by the system.
|
||||
int m_io_ready;
|
||||
|
||||
// flag for "true" timing involving rs/ws
|
||||
bool m_true_timing;
|
||||
|
||||
// rsws - state, rs bit 1, ws bit 0
|
||||
int m_rs_ws;
|
||||
UINT8 m_read_latch;
|
||||
UINT8 m_write_latch;
|
||||
|
||||
// The TMS52xx has two different ways of providing output data: the
|
||||
// analog speaker pin (which was usually used) and the Digital I/O pin.
|
||||
// The internal DAC used to feed the analog pin is only 8 bits, and has the
|
||||
// funny clipping/clamping logic, while the digital pin gives full 12? bit
|
||||
// resolution of the output data.
|
||||
// TODO: add a way to set/reset this other than the FORCE_DIGITAL define
|
||||
bool m_digital_select;
|
||||
|
||||
sound_stream *m_stream;
|
||||
|
||||
emu_timer *m_ready_timer;
|
||||
};
|
||||
|
||||
class tms5220n_device : public tms52xx_device
|
||||
{
|
||||
public:
|
||||
tms5220n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
};
|
||||
|
||||
class tms5220cn_device : public tms52xx_device
|
||||
{
|
||||
public:
|
||||
tms5220cn_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
};
|
||||
|
||||
class tmc0285n_device : public tms52xx_device
|
||||
{
|
||||
public:
|
||||
tmc0285n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
};
|
||||
|
||||
class tms5200n_device : public tms52xx_device
|
||||
{
|
||||
public:
|
||||
tms5200n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
};
|
||||
|
||||
|
||||
#endif /* __TMS5220_H__ */
|
||||
|
@ -59,7 +59,7 @@ static UINT16 test_mask;
|
||||
|
||||
static pokey_device *pokey;
|
||||
static ym2151_device *ym2151;
|
||||
static device_t *tms5220;
|
||||
static tms5220_device *tms5220;
|
||||
static okim6295_device *oki6295;
|
||||
static okim6295_device *oki6295_l, *oki6295_r;
|
||||
|
||||
@ -138,7 +138,7 @@ void atarijsa_init(running_machine &machine, const char *testport, int testmask)
|
||||
bank_source_data = &rgn[0x10000];
|
||||
|
||||
/* determine which sound hardware is installed */
|
||||
tms5220 = machine.device("tms");
|
||||
tms5220 = machine.device<tms5220_device>("tms");
|
||||
ym2151 = machine.device<ym2151_device>("ymsnd");
|
||||
pokey = machine.device<pokey_device>("pokey");
|
||||
oki6295 = machine.device<okim6295_device>("adpcm");
|
||||
@ -231,7 +231,7 @@ static READ8_HANDLER( jsa1_io_r )
|
||||
if (!(space.machine().root_device().ioport(test_port)->read() & test_mask)) result ^= 0x80;
|
||||
if (atarigen->m_cpu_to_sound_ready) result ^= 0x40;
|
||||
if (atarigen->m_sound_to_cpu_ready) result ^= 0x20;
|
||||
if ((tms5220 != NULL) && (tms5220_readyq_r(tms5220) == 0))
|
||||
if ((tms5220 != NULL) && (tms5220->readyq_r() == 0))
|
||||
result |= 0x10;
|
||||
else
|
||||
result &= ~0x10;
|
||||
@ -269,7 +269,7 @@ static WRITE8_HANDLER( jsa1_io_w )
|
||||
|
||||
case 0x200: /* /VOICE */
|
||||
if (tms5220 != NULL)
|
||||
tms5220_data_w(tms5220, space, 0, data);
|
||||
tms5220->data_w(space, 0, data);
|
||||
break;
|
||||
|
||||
case 0x202: /* /WRP */
|
||||
@ -291,10 +291,10 @@ static WRITE8_HANDLER( jsa1_io_w )
|
||||
if (tms5220 != NULL)
|
||||
{
|
||||
int count;
|
||||
tms5220_wsq_w(tms5220, (data&0x02)>>1);
|
||||
tms5220_rsq_w(tms5220, (data&0x04)>>2);
|
||||
tms5220->wsq_w((data&0x02)>>1);
|
||||
tms5220->rsq_w((data&0x04)>>2);
|
||||
count = 5 | ((data >> 2) & 2);
|
||||
tms5220_set_frequency(tms5220, JSA_MASTER_CLOCK*2 / (16 - count));
|
||||
tms5220->set_frequency(JSA_MASTER_CLOCK*2 / (16 - count));
|
||||
}
|
||||
|
||||
/* reset the YM2151 if needed */
|
||||
|
@ -1410,7 +1410,7 @@ static SOUND_RESET( demon_sound )
|
||||
state->m_last_portb_write = 0xff;
|
||||
|
||||
/* turn off channel A on AY8910 #0 because it is used as a low-pass filter */
|
||||
ay8910_set_volume(machine.device("ay1"), 0, 0);
|
||||
machine.device<ay8910_device>("ay1")->set_volume(0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -103,7 +103,7 @@ struct exidy_sound_state
|
||||
|
||||
/* 5220/CVSD variables */
|
||||
device_t *m_cvsd;
|
||||
device_t *m_tms;
|
||||
tms5220_device *m_tms;
|
||||
pia6821_device *m_pia1;
|
||||
|
||||
/* sound streaming variables */
|
||||
@ -533,7 +533,7 @@ static WRITE8_DEVICE_HANDLER( r6532_porta_w )
|
||||
if (state->m_tms != NULL)
|
||||
{
|
||||
logerror("(%f)%s:TMS5220 data write = %02X\n", space.machine().time().as_double(), space.machine().describe_context(), state->m_riot->porta_out_get());
|
||||
tms5220_data_w(state->m_tms, space, 0, data);
|
||||
state->m_tms->data_w(space, 0, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -542,8 +542,8 @@ static READ8_DEVICE_HANDLER( r6532_porta_r )
|
||||
exidy_sound_state *state = get_safe_token(device);
|
||||
if (state->m_tms != NULL)
|
||||
{
|
||||
logerror("(%f)%s:TMS5220 status read = %02X\n", space.machine().time().as_double(), space.machine().describe_context(), tms5220_status_r(state->m_tms, space, 0));
|
||||
return tms5220_status_r(state->m_tms, space, 0);
|
||||
logerror("(%f)%s:TMS5220 status read = %02X\n", space.machine().time().as_double(), space.machine().describe_context(), state->m_tms->status_r(space, 0));
|
||||
return state->m_tms->status_r(space, 0);
|
||||
}
|
||||
else
|
||||
return 0xff;
|
||||
@ -554,8 +554,8 @@ static WRITE8_DEVICE_HANDLER( r6532_portb_w )
|
||||
exidy_sound_state *state = get_safe_token(device);
|
||||
if (state->m_tms != NULL)
|
||||
{
|
||||
tms5220_rsq_w(state->m_tms, data & 0x01);
|
||||
tms5220_wsq_w(state->m_tms, (data >> 1) & 0x01);
|
||||
state->m_tms->rsq_w(data & 0x01);
|
||||
state->m_tms->wsq_w((data >> 1) & 0x01);
|
||||
}
|
||||
}
|
||||
|
||||
@ -567,8 +567,8 @@ static READ8_DEVICE_HANDLER( r6532_portb_r )
|
||||
if (state->m_tms != NULL)
|
||||
{
|
||||
newdata &= ~0x0c;
|
||||
if (tms5220_readyq_r(state->m_tms)) newdata |= 0x04;
|
||||
if (tms5220_intq_r(state->m_tms)) newdata |= 0x08;
|
||||
if (state->m_tms->readyq_r()) newdata |= 0x04;
|
||||
if (state->m_tms->intq_r()) newdata |= 0x08;
|
||||
}
|
||||
return newdata;
|
||||
}
|
||||
@ -1126,7 +1126,7 @@ static DEVICE_START( victory_sound )
|
||||
device->save_item(NAME(state->m_victory_sound_response_ack_clk));
|
||||
|
||||
DEVICE_START_CALL(venture_common_sh_start);
|
||||
state->m_tms = device->machine().device("tms");
|
||||
state->m_tms = device->machine().device<tms5220_device>("tms");
|
||||
}
|
||||
|
||||
|
||||
|
@ -139,8 +139,8 @@ WRITE8_MEMBER(jedi_state::speech_strobe_w)
|
||||
|
||||
if ((new_speech_strobe_state != m_speech_strobe_state) && new_speech_strobe_state)
|
||||
{
|
||||
device_t *tms = machine().device("tms");
|
||||
tms5220_data_w(tms, space, 0, *m_speech_data);
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
tms5220->data_w(space, 0, *m_speech_data);
|
||||
}
|
||||
m_speech_strobe_state = new_speech_strobe_state;
|
||||
}
|
||||
@ -148,7 +148,8 @@ WRITE8_MEMBER(jedi_state::speech_strobe_w)
|
||||
|
||||
READ8_MEMBER(jedi_state::speech_ready_r)
|
||||
{
|
||||
return (tms5220_readyq_r(machine().device("tms"))) << 7;
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
return (tms5220->readyq_r()) << 7;
|
||||
}
|
||||
|
||||
|
||||
|
@ -372,12 +372,12 @@ WRITE8_MEMBER(midway_ssio_device::portb1_w)
|
||||
|
||||
void midway_ssio_device::update_volumes()
|
||||
{
|
||||
ay8910_set_volume(m_ay0, 0, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[0][0]]);
|
||||
ay8910_set_volume(m_ay0, 1, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[0][1]]);
|
||||
ay8910_set_volume(m_ay0, 2, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[0][2]]);
|
||||
ay8910_set_volume(m_ay1, 0, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[1][0]]);
|
||||
ay8910_set_volume(m_ay1, 1, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[1][1]]);
|
||||
ay8910_set_volume(m_ay1, 2, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[1][2]]);
|
||||
m_ay0->set_volume(0, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[0][0]]);
|
||||
m_ay0->set_volume(1, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[0][1]]);
|
||||
m_ay0->set_volume(2, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[0][2]]);
|
||||
m_ay1->set_volume(0, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[1][0]]);
|
||||
m_ay1->set_volume(1, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[1][1]]);
|
||||
m_ay1->set_volume(2, m_mute ? 0 : m_ayvolume_lookup[m_duty_cycle[1][2]]);
|
||||
}
|
||||
|
||||
|
||||
@ -1198,7 +1198,7 @@ WRITE8_MEMBER(midway_squawk_n_talk_device::portb2_w)
|
||||
// write strobe -- pass the current command to the TMS5200
|
||||
if (((data ^ m_tms_strobes) & 0x02) && !(data & 0x02))
|
||||
{
|
||||
tms5220_data_w(m_tms5200, space, offset, m_tms_command);
|
||||
m_tms5200->data_w(space, offset, m_tms_command);
|
||||
|
||||
// DoT expects the ready line to transition on a command/write here, so we oblige
|
||||
m_pia1->ca2_w(1);
|
||||
@ -1208,7 +1208,7 @@ WRITE8_MEMBER(midway_squawk_n_talk_device::portb2_w)
|
||||
// read strobe -- read the current status from the TMS5200
|
||||
else if (((data ^ m_tms_strobes) & 0x01) && !(data & 0x01))
|
||||
{
|
||||
m_pia1->porta_w(tms5220_status_r(m_tms5200, space, offset));
|
||||
m_pia1->porta_w(m_tms5200->status_r(space, offset));
|
||||
|
||||
// DoT expects the ready line to transition on a command/write here, so we oblige
|
||||
m_pia1->ca2_w(1);
|
||||
|
@ -34,17 +34,18 @@ READ8_MEMBER(starwars_state::r6532_porta_r)
|
||||
/* Note: bit 4 is always set to avoid sound self test */
|
||||
UINT8 olddata = m_riot->porta_in_get();
|
||||
|
||||
return (olddata & 0xc0) | 0x10 | (tms5220_readyq_r(machine().device("tms")) << 2);
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
return (olddata & 0xc0) | 0x10 | (tms5220->readyq_r() << 2);
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(starwars_state::r6532_porta_w)
|
||||
{
|
||||
device_t *device = machine().device("tms");
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
/* handle 5220 read */
|
||||
tms5220_rsq_w(device, (data & 2)>>1);
|
||||
tms5220->rsq_w((data & 2)>>1);
|
||||
/* handle 5220 write */
|
||||
tms5220_wsq_w(device, (data & 1)>>0);
|
||||
tms5220->wsq_w((data & 1)>>0);
|
||||
}
|
||||
|
||||
|
||||
@ -57,9 +58,9 @@ WRITE_LINE_MEMBER(starwars_state::snd_interrupt)
|
||||
const riot6532_interface starwars_riot6532_intf =
|
||||
{
|
||||
DEVCB_DRIVER_MEMBER(starwars_state,r6532_porta_r),
|
||||
DEVCB_DEVICE_HANDLER("tms", tms5220_status_r),
|
||||
DEVCB_DEVICE_MEMBER("tms", tms5220_device, status_r),
|
||||
DEVCB_DRIVER_MEMBER(starwars_state,r6532_porta_w),
|
||||
DEVCB_DEVICE_HANDLER("tms", tms5220_data_w),
|
||||
DEVCB_DEVICE_MEMBER("tms", tms5220_device, data_w),
|
||||
DEVCB_DRIVER_LINE_MEMBER(starwars_state,snd_interrupt)
|
||||
};
|
||||
|
||||
|
@ -394,37 +394,37 @@ READ8_MEMBER(atarisy1_state::switch_6502_r)
|
||||
|
||||
WRITE8_MEMBER(atarisy1_state::via_pa_w)
|
||||
{
|
||||
device_t *device = machine().device("tms");
|
||||
tms5220_data_w(device, space, 0, data);
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
tms5220->data_w(space, 0, data);
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER(atarisy1_state::via_pa_r)
|
||||
{
|
||||
device_t *device = machine().device("tms");
|
||||
return tms5220_status_r(device, space, 0);
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
return tms5220->status_r(space, 0);
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(atarisy1_state::via_pb_w)
|
||||
{
|
||||
device_t *device = machine().device("tms");
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
/* write strobe */
|
||||
tms5220_wsq_w(device, data & 1);
|
||||
tms5220->wsq_w(data & 1);
|
||||
|
||||
/* read strobe */
|
||||
tms5220_rsq_w(device, (data & 2)>>1);
|
||||
tms5220->rsq_w((data & 2)>>1);
|
||||
|
||||
/* bit 4 is connected to an up-counter, clocked by SYCLKB */
|
||||
data = 5 | ((data >> 3) & 2);
|
||||
tms5220_set_frequency(device, ATARI_CLOCK_14MHz/2 / (16 - data));
|
||||
tms5220->set_frequency(ATARI_CLOCK_14MHz/2 / (16 - data));
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER(atarisy1_state::via_pb_r)
|
||||
{
|
||||
device_t *device = machine().device("tms");
|
||||
return (tms5220_readyq_r(device) << 2) | (tms5220_intq_r(device) << 3);
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
return (tms5220->readyq_r() << 2) | (tms5220->intq_r() << 3);
|
||||
}
|
||||
|
||||
|
||||
|
@ -350,7 +350,7 @@ READ8_MEMBER(atarisy2_state::switch_6502_r)
|
||||
|
||||
if (m_cpu_to_sound_ready) result |= 0x01;
|
||||
if (m_sound_to_cpu_ready) result |= 0x02;
|
||||
if ((m_has_tms5220) && (tms5220_readyq_r(machine().device("tms")) == 0))
|
||||
if ((m_has_tms5220) && (machine().device<tms5220_device>("tms")->readyq_r() == 0))
|
||||
result &= ~0x04;
|
||||
if (!(ioport("1801")->read() & 0x80)) result |= 0x10;
|
||||
|
||||
@ -363,7 +363,7 @@ WRITE8_MEMBER(atarisy2_state::switch_6502_w)
|
||||
if (m_has_tms5220)
|
||||
{
|
||||
data = 12 | ((data >> 5) & 1);
|
||||
tms5220_set_frequency(machine().device("tms"), MASTER_CLOCK/4 / (16 - data) / 2);
|
||||
machine().device<tms5220_device>("tms")->set_frequency(MASTER_CLOCK/4 / (16 - data) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -736,7 +736,7 @@ WRITE8_MEMBER(atarisy2_state::tms5220_w)
|
||||
{
|
||||
if (m_has_tms5220)
|
||||
{
|
||||
tms5220_data_w(machine().device("tms"), space, 0, data);
|
||||
machine().device<tms5220_device>("tms")->data_w(space, 0, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,7 +744,7 @@ WRITE8_MEMBER(atarisy2_state::tms5220_strobe_w)
|
||||
{
|
||||
if (m_has_tms5220)
|
||||
{
|
||||
tms5220_wsq_w(machine().device("tms"), 1-(offset & 1));
|
||||
machine().device<tms5220_device>("tms")->wsq_w(1-(offset & 1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3178,7 +3178,7 @@ DRIVER_INIT_MEMBER(atarisy2_state,paperboy)
|
||||
|
||||
m_pedal_count = 0;
|
||||
m_has_tms5220 = 1;
|
||||
tms5220_rsq_w(machine().device("tms"), 1); // /RS is tied high on sys2 hw
|
||||
machine().device<tms5220_device>("tms")->rsq_w(1); // /RS is tied high on sys2 hw
|
||||
}
|
||||
|
||||
|
||||
@ -3191,7 +3191,7 @@ DRIVER_INIT_MEMBER(atarisy2_state,720)
|
||||
|
||||
m_pedal_count = -1;
|
||||
m_has_tms5220 = 1;
|
||||
tms5220_rsq_w(machine().device("tms"), 1); // /RS is tied high on sys2 hw
|
||||
machine().device<tms5220_device>("tms")->rsq_w(1); // /RS is tied high on sys2 hw
|
||||
}
|
||||
|
||||
|
||||
@ -3233,7 +3233,7 @@ DRIVER_INIT_MEMBER(atarisy2_state,apb)
|
||||
|
||||
m_pedal_count = 2;
|
||||
m_has_tms5220 = 1;
|
||||
tms5220_rsq_w(machine().device("tms"), 1); // /RS is tied high on sys2 hw
|
||||
machine().device<tms5220_device>("tms")->rsq_w(1); // /RS is tied high on sys2 hw
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "machine/6840ptm.h"
|
||||
#include "machine/nvram.h"
|
||||
#include "sound/dac.h"
|
||||
#include "sound/tms5220.h"
|
||||
#include "includes/esripsys.h"
|
||||
|
||||
|
||||
@ -521,10 +520,10 @@ READ8_MEMBER(esripsys_state::tms5220_r)
|
||||
if (offset == 0)
|
||||
{
|
||||
/* TMS5220 core returns status bits in D7-D6 */
|
||||
UINT8 status = tms5220_status_r(m_tms, space, 0);
|
||||
UINT8 status = m_tms->status_r(space, 0);
|
||||
|
||||
status = ((status & 0x80) >> 5) | ((status & 0x40) >> 5) | ((status & 0x20) >> 5);
|
||||
return (tms5220_readyq_r(m_tms) << 7) | (tms5220_intq_r(m_tms) << 6) | status;
|
||||
return (m_tms->readyq_r() << 7) | (m_tms->intq_r() << 6) | status;
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
@ -536,12 +535,12 @@ WRITE8_MEMBER(esripsys_state::tms5220_w)
|
||||
if (offset == 0)
|
||||
{
|
||||
m_tms_data = data;
|
||||
tms5220_data_w(m_tms, space, 0, m_tms_data);
|
||||
m_tms->data_w(space, 0, m_tms_data);
|
||||
}
|
||||
#if 0
|
||||
if (offset == 1)
|
||||
{
|
||||
tms5220_data_w(m_tms, space, 0, m_tms_data);
|
||||
m_tms->data_w(space, 0, m_tms_data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -351,7 +351,8 @@ WRITE8_MEMBER(firefox_state::sound_to_main_w)
|
||||
|
||||
READ8_MEMBER(firefox_state::riot_porta_r)
|
||||
{
|
||||
device_t *tms = machine().device("tms");
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
|
||||
/* bit 7 = MAINFLAG */
|
||||
/* bit 6 = SOUNDFLAG */
|
||||
/* bit 5 = PA5 */
|
||||
@ -361,18 +362,18 @@ READ8_MEMBER(firefox_state::riot_porta_r)
|
||||
/* bit 1 = TMS /read */
|
||||
/* bit 0 = TMS /write */
|
||||
|
||||
return (m_main_to_sound_flag << 7) | (m_sound_to_main_flag << 6) | 0x10 | (tms5220_readyq_r(tms) << 2);
|
||||
return (m_main_to_sound_flag << 7) | (m_sound_to_main_flag << 6) | 0x10 | (tms5220->readyq_r() << 2);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(firefox_state::riot_porta_w)
|
||||
{
|
||||
device_t *tms = machine().device("tms");
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
|
||||
/* handle 5220 read */
|
||||
tms5220_rsq_w(tms, (data>>1) & 1);
|
||||
tms5220->rsq_w((data>>1) & 1);
|
||||
|
||||
/* handle 5220 write */
|
||||
tms5220_wsq_w(tms, data & 1);
|
||||
tms5220->wsq_w(data & 1);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(firefox_state::riot_irq)
|
||||
@ -695,9 +696,9 @@ GFXDECODE_END
|
||||
static const riot6532_interface riot_intf =
|
||||
{
|
||||
DEVCB_DRIVER_MEMBER(firefox_state,riot_porta_r),
|
||||
DEVCB_DEVICE_HANDLER("tms", tms5220_status_r),
|
||||
DEVCB_DEVICE_MEMBER("tms", tms5220_device, status_r),
|
||||
DEVCB_DRIVER_MEMBER(firefox_state,riot_porta_w),
|
||||
DEVCB_DEVICE_HANDLER("tms", tms5220_data_w),
|
||||
DEVCB_DEVICE_MEMBER("tms", tms5220_device, data_w),
|
||||
DEVCB_DRIVER_LINE_MEMBER(firefox_state,riot_irq)
|
||||
};
|
||||
|
||||
|
@ -207,8 +207,9 @@ WRITE16_MEMBER(gauntlet_state::sound_reset_w)
|
||||
if (m_sound_reset_val & 1)
|
||||
{
|
||||
machine().device("ymsnd")->reset();
|
||||
machine().device("tms")->reset();
|
||||
tms5220_set_frequency(machine().device("tms"), ATARI_CLOCK_14MHz/2 / 11);
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
tms5220->reset();
|
||||
tms5220->set_frequency(ATARI_CLOCK_14MHz/2 / 11);
|
||||
set_ym2151_volume(0);
|
||||
set_pokey_volume(0);
|
||||
set_tms5220_volume(0);
|
||||
@ -227,11 +228,12 @@ WRITE16_MEMBER(gauntlet_state::sound_reset_w)
|
||||
|
||||
READ8_MEMBER(gauntlet_state::switch_6502_r)
|
||||
{
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
int temp = 0x30;
|
||||
|
||||
if (m_cpu_to_sound_ready) temp ^= 0x80;
|
||||
if (m_sound_to_cpu_ready) temp ^= 0x40;
|
||||
if (!tms5220_readyq_r(machine().device("tms"))) temp ^= 0x20;
|
||||
if (!tms5220->readyq_r()) temp ^= 0x20;
|
||||
if (!(ioport("803008")->read() & 0x0008)) temp ^= 0x10;
|
||||
|
||||
return temp;
|
||||
@ -246,7 +248,7 @@ READ8_MEMBER(gauntlet_state::switch_6502_r)
|
||||
|
||||
WRITE8_MEMBER(gauntlet_state::sound_ctl_w)
|
||||
{
|
||||
device_t *tms = machine().device("tms");
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
switch (offset & 7)
|
||||
{
|
||||
case 0: /* music reset, bit D7, low reset */
|
||||
@ -254,16 +256,16 @@ WRITE8_MEMBER(gauntlet_state::sound_ctl_w)
|
||||
break;
|
||||
|
||||
case 1: /* speech write, bit D7, active low */
|
||||
tms5220_wsq_w(tms, data >> 7);
|
||||
tms5220->wsq_w(data >> 7);
|
||||
break;
|
||||
|
||||
case 2: /* speech reset, bit D7, active low */
|
||||
tms5220_rsq_w(tms, data >> 7);
|
||||
tms5220->rsq_w(data >> 7);
|
||||
break;
|
||||
|
||||
case 3: /* speech squeak, bit D7 */
|
||||
data = 5 | ((data >> 6) & 2);
|
||||
tms5220_set_frequency(tms, ATARI_CLOCK_14MHz/2 / (16 - data));
|
||||
tms5220->set_frequency(ATARI_CLOCK_14MHz/2 / (16 - data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -342,7 +344,7 @@ static ADDRESS_MAP_START( sound_map, AS_PROGRAM, 8, gauntlet_state )
|
||||
AM_RANGE(0x1030, 0x103f) AM_MIRROR(0x27c0) AM_READWRITE(switch_6502_r, sound_ctl_w)
|
||||
AM_RANGE(0x1800, 0x180f) AM_MIRROR(0x27c0) AM_DEVREADWRITE("pokey", pokey_device, read, write)
|
||||
AM_RANGE(0x1810, 0x1811) AM_MIRROR(0x27ce) AM_DEVREADWRITE("ymsnd", ym2151_device, read, write)
|
||||
AM_RANGE(0x1820, 0x182f) AM_MIRROR(0x27c0) AM_DEVWRITE_LEGACY("tms", tms5220_data_w)
|
||||
AM_RANGE(0x1820, 0x182f) AM_MIRROR(0x27c0) AM_DEVWRITE("tms", tms5220_device, data_w)
|
||||
AM_RANGE(0x1830, 0x183f) AM_MIRROR(0x27c0) AM_READWRITE(m6502_irq_ack_r, m6502_irq_ack_w)
|
||||
AM_RANGE(0x4000, 0xffff) AM_ROM
|
||||
ADDRESS_MAP_END
|
||||
|
@ -163,7 +163,7 @@ INPUT_PORTS_END
|
||||
void icecold_state::machine_reset()
|
||||
{
|
||||
// CH-C is used for generate a 30hz clock
|
||||
ay8910_set_volume(m_ay8910_0, 2, 0);
|
||||
m_ay8910_0->set_volume(2, 0);
|
||||
|
||||
m_rmotor = m_lmotor = 10;
|
||||
m_sint = 0;
|
||||
|
@ -552,8 +552,8 @@ static ADDRESS_MAP_START( looping_sound_map, AS_PROGRAM, 8, looping_state )
|
||||
AM_RANGE(0x3c00, 0x3c00) AM_MIRROR(0x00f4) AM_DEVREADWRITE("aysnd", ay8910_device, data_r, address_w)
|
||||
AM_RANGE(0x3c02, 0x3c02) AM_MIRROR(0x00f4) AM_READNOP AM_DEVWRITE("aysnd", ay8910_device, data_w)
|
||||
AM_RANGE(0x3c03, 0x3c03) AM_MIRROR(0x00f6) AM_NOP
|
||||
AM_RANGE(0x3e00, 0x3e00) AM_MIRROR(0x00f4) AM_READNOP AM_DEVWRITE("tms", tms5220n_device, write)
|
||||
AM_RANGE(0x3e02, 0x3e02) AM_MIRROR(0x00f4) AM_DEVREAD("tms", tms5220n_device, read) AM_WRITENOP
|
||||
AM_RANGE(0x3e00, 0x3e00) AM_MIRROR(0x00f4) AM_READNOP AM_DEVWRITE("tms", tms5220_device, data_w)
|
||||
AM_RANGE(0x3e02, 0x3e02) AM_MIRROR(0x00f4) AM_DEVREAD("tms", tms5220_device, status_r) AM_WRITENOP
|
||||
AM_RANGE(0x3e03, 0x3e03) AM_MIRROR(0x00f6) AM_NOP
|
||||
ADDRESS_MAP_END
|
||||
|
||||
@ -612,12 +612,6 @@ GFXDECODE_END
|
||||
*
|
||||
*************************************/
|
||||
|
||||
static const tms52xx_config tms5220interface =
|
||||
{
|
||||
DEVCB_DRIVER_LINE_MEMBER(looping_state,looping_spcint), // IRQ
|
||||
DEVCB_NULL // READYQ
|
||||
};
|
||||
|
||||
static const ay8910_interface ay8910_config =
|
||||
{
|
||||
AY8910_LEGACY_OUTPUT,
|
||||
@ -676,8 +670,8 @@ static MACHINE_CONFIG_START( looping, looping_state )
|
||||
MCFG_SOUND_CONFIG(ay8910_config)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.20)
|
||||
|
||||
MCFG_SOUND_ADD("tms", TMS5220N, TMS_CLOCK)
|
||||
MCFG_SOUND_CONFIG(tms5220interface)
|
||||
MCFG_SOUND_ADD("tms", TMS5220, TMS_CLOCK)
|
||||
MCFG_TMS52XX_IRQ_HANDLER(WRITELINE(looping_state, looping_spcint))
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
||||
|
||||
MCFG_DAC_ADD("dac")
|
||||
|
@ -795,8 +795,8 @@ READ8_MEMBER(maygay1b_state::latch_st_lo)
|
||||
|
||||
READ8_MEMBER(maygay1b_state::m1_meter_r)
|
||||
{
|
||||
device_t *ay8910 = machine().device("aysnd");
|
||||
return ~ay8910_read_ym(ay8910);
|
||||
ay8910_device *ay8910 = machine().device<ay8910_device>("aysnd");
|
||||
return ~ay8910->data_r(space, offset);
|
||||
}
|
||||
|
||||
static ADDRESS_MAP_START( m1_memmap, AS_PROGRAM, 8, maygay1b_state )
|
||||
|
@ -957,11 +957,6 @@ const namco_06xx_config topracern_namco_06xx_intf =
|
||||
"maincpu", "51xx", NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static const tms52xx_config tms_intf =
|
||||
{
|
||||
DEVCB_NULL
|
||||
};
|
||||
|
||||
static MACHINE_CONFIG_START( topracern, polepos_state )
|
||||
|
||||
/* basic machine hardware */
|
||||
@ -1030,10 +1025,9 @@ static MACHINE_CONFIG_DERIVED( polepos2bi, topracern )
|
||||
MCFG_CPU_PROGRAM_MAP(sound_z80_bootleg_map)
|
||||
MCFG_CPU_IO_MAP(sound_z80_bootleg_iomap)
|
||||
|
||||
MCFG_SOUND_ADD("tms", TMS5220N, 600000) /* ? Mhz */
|
||||
MCFG_SOUND_ADD("tms", TMS5220, 600000) /* ? Mhz */
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.80)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.80)
|
||||
MCFG_SOUND_CONFIG(tms_intf)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
|
@ -240,11 +240,6 @@ static GFXDECODE_START( portrait )
|
||||
GFXDECODE_ENTRY( "gfx1", 0x00000, tile_layout, 0, 0x800/8 )
|
||||
GFXDECODE_END
|
||||
|
||||
static const tms52xx_config tms_intf =
|
||||
{
|
||||
DEVCB_NULL
|
||||
};
|
||||
|
||||
|
||||
static MACHINE_CONFIG_START( portrait, portrait_state )
|
||||
MCFG_CPU_ADD("maincpu", Z80, 4000000) /* 4 MHz ? */
|
||||
@ -270,9 +265,8 @@ static MACHINE_CONFIG_START( portrait, portrait_state )
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_ADD("tms", TMS5200N, 640000)
|
||||
MCFG_SOUND_ADD("tms", TMS5200, 640000)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
|
||||
MCFG_SOUND_CONFIG(tms_intf)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_dsp(*this, "dsp") { }
|
||||
|
||||
required_device<tms5220n_device> m_tms;
|
||||
required_device<tms5220_device> m_tms;
|
||||
int m_control_num;
|
||||
required_shared_ptr<UINT16> m_shared_ram;
|
||||
UINT8 m_nvram[0x800];
|
||||
@ -400,11 +400,6 @@ static const riot6532_interface tomcat_riot6532_intf =
|
||||
DEVCB_NULL // connected to IRQ line of 6502
|
||||
};
|
||||
|
||||
static const tms52xx_config tms_intf =
|
||||
{
|
||||
DEVCB_NULL
|
||||
};
|
||||
|
||||
static MACHINE_CONFIG_START( tomcat, tomcat_state )
|
||||
MCFG_CPU_ADD("maincpu", M68010, XTAL_12MHz / 2)
|
||||
MCFG_CPU_PROGRAM_MAP(tomcat_map)
|
||||
@ -444,10 +439,9 @@ static MACHINE_CONFIG_START( tomcat, tomcat_state )
|
||||
MCFG_POKEY_ADD("pokey2", XTAL_14_31818MHz / 8)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.20)
|
||||
|
||||
MCFG_SOUND_ADD("tms", TMS5220N, 325000)
|
||||
MCFG_SOUND_ADD("tms", TMS5220, 325000)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.50)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.50)
|
||||
MCFG_SOUND_CONFIG(tms_intf)
|
||||
|
||||
MCFG_YM2151_ADD("ymsnd", XTAL_14_31818MHz / 4)
|
||||
MCFG_SOUND_ROUTE(0, "lspeaker", 0.60)
|
||||
|
@ -96,7 +96,7 @@ WRITE8_MEMBER(zaccaria_state::ay8910_port0a_w)
|
||||
/* 150 below to scale to volume 100 */
|
||||
v = (150 * table[ba]) / (4700 + table[ba]);
|
||||
//printf("dac1w %02d %04d\n", ba, v);
|
||||
ay8910_set_volume(machine().device("ay2"), 1, v);
|
||||
machine().device<ay8910_device>("ay2")->set_volume(1, v);
|
||||
}
|
||||
|
||||
|
||||
@ -160,12 +160,12 @@ INTERRUPT_GEN_MEMBER(zaccaria_state::zaccaria_cb1_toggle)
|
||||
|
||||
WRITE8_MEMBER(zaccaria_state::zaccaria_port1b_w)
|
||||
{
|
||||
device_t *tms = machine().device("tms");
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
|
||||
// bit 0 = /RS
|
||||
tms5220_rsq_w(tms, (data >> 0) & 0x01);
|
||||
tms5220->rsq_w((data >> 0) & 0x01);
|
||||
// bit 1 = /WS
|
||||
tms5220_wsq_w(tms, (data >> 1) & 0x01);
|
||||
tms5220->wsq_w((data >> 1) & 0x01);
|
||||
|
||||
// bit 3 = "ACS" (goes, inverted, to input port 6 bit 3)
|
||||
m_acs = ~data & 0x08;
|
||||
@ -546,13 +546,13 @@ static const pia6821_interface pia_0_config =
|
||||
|
||||
static const pia6821_interface pia_1_config =
|
||||
{
|
||||
DEVCB_DEVICE_HANDLER("tms", tms5220_status_r), /* port A in */
|
||||
DEVCB_DEVICE_MEMBER("tms", tms5220_device, status_r), /* port A in */
|
||||
DEVCB_NULL, /* port B in */
|
||||
DEVCB_NULL, /* line CA1 in */
|
||||
DEVCB_NULL, /* line CB1 in */ // tms5220_intq_r, handled below in tms5220_config
|
||||
DEVCB_NULL, /* line CA2 in */ // tms5220_readyq_r, "
|
||||
DEVCB_NULL, /* line CB2 in */
|
||||
DEVCB_DEVICE_HANDLER("tms", tms5220_data_w), /* port A out */
|
||||
DEVCB_DEVICE_MEMBER("tms", tms5220_device, data_w), /* port A out */
|
||||
DEVCB_DRIVER_MEMBER(zaccaria_state,zaccaria_port1b_w), /* port B out */
|
||||
DEVCB_NULL, /* line CA2 out */
|
||||
DEVCB_NULL, /* port CB2 out */
|
||||
@ -560,12 +560,6 @@ static const pia6821_interface pia_1_config =
|
||||
DEVCB_NULL /* IRQB */
|
||||
};
|
||||
|
||||
static const tms5220_interface tms5220_config =
|
||||
{
|
||||
DEVCB_DEVICE_LINE_MEMBER("pia1", pia6821_device, cb1_w), /* IRQ handler */
|
||||
DEVCB_DEVICE_LINE_MEMBER("pia1", pia6821_device, ca2_w) /* READYQ handler */
|
||||
};
|
||||
|
||||
INTERRUPT_GEN_MEMBER(zaccaria_state::vblank_irq)
|
||||
{
|
||||
if(m_nmi_mask)
|
||||
@ -622,7 +616,8 @@ static MACHINE_CONFIG_START( zaccaria, zaccaria_state )
|
||||
/* There is no xtal, the clock is obtained from a RC oscillator as shown in the TMS5220 datasheet (R=100kOhm C=22pF) */
|
||||
/* 162kHz measured on pin 3 20 minutesa fter power on. Clock would then be 162*4=648kHz. */
|
||||
MCFG_SOUND_ADD("tms", TMS5200, 649200) /* ROMCLK pin measured at 162.3Khz, OSC is exactly *4 of that) */
|
||||
MCFG_SOUND_CONFIG(tms5220_config)
|
||||
MCFG_TMS52XX_IRQ_HANDLER(DEVWRITELINE("pia1", pia6821_device, cb1_w))
|
||||
MCFG_TMS52XX_READYQ_HANDLER(DEVWRITELINE("pia1", pia6821_device, ca2_w))
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "cpu/esrip/esrip.h"
|
||||
#include "sound/dac.h"
|
||||
#include "sound/tms5220.h"
|
||||
|
||||
/* TODO */
|
||||
#define ESRIPSYS_PIXEL_CLOCK (XTAL_25MHz / 2)
|
||||
@ -48,7 +49,7 @@ public:
|
||||
required_device<esrip_device> m_videocpu;
|
||||
required_device<cpu_device> m_gamecpu;
|
||||
required_device<cpu_device> m_soundcpu;
|
||||
required_device<device_t> m_tms;
|
||||
required_device<tms5220_device> m_tms;
|
||||
|
||||
UINT8 m_g_iodata;
|
||||
UINT8 m_g_ioaddr;
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
m_subcpu(*this, "sub"),
|
||||
m_subcpu2(*this, "sub2") { }
|
||||
|
||||
optional_device<tms5220n_device> m_tms;
|
||||
optional_device<tms5220_device> m_tms;
|
||||
UINT8 m_steer_last;
|
||||
UINT8 m_steer_delta;
|
||||
INT16 m_steer_accum;
|
||||
|
@ -11,7 +11,7 @@ public:
|
||||
m_spriteram(*this, "spriteram"),
|
||||
m_maincpu(*this, "maincpu") { }
|
||||
|
||||
required_device<tms5200n_device> m_tms;
|
||||
required_device<tms5200_device> m_tms;
|
||||
required_shared_ptr<UINT8> m_bgvideoram;
|
||||
required_shared_ptr<UINT8> m_fgvideoram;
|
||||
int m_scroll;
|
||||
|
@ -203,7 +203,8 @@ WRITE8_MEMBER(mhavoc_state::mhavoc_rom_banksel_w)
|
||||
|
||||
CUSTOM_INPUT_MEMBER(mhavoc_state::tms5220_r)
|
||||
{
|
||||
return tms5220_readyq_r(machine().device("tms")) ? 1 : 0;
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
return tms5220->readyq_r() ? 1 : 0;
|
||||
}
|
||||
|
||||
CUSTOM_INPUT_MEMBER(mhavoc_state::mhavoc_bit67_r)
|
||||
@ -308,8 +309,8 @@ WRITE8_MEMBER(mhavoc_state::mhavocrv_speech_data_w)
|
||||
|
||||
WRITE8_MEMBER(mhavoc_state::mhavocrv_speech_strobe_w)
|
||||
{
|
||||
device_t *tms = machine().device("tms");
|
||||
tms5220_data_w(tms, space, 0, m_speech_write_buffer);
|
||||
tms5220_device *tms5220 = machine().device<tms5220_device>("tms");
|
||||
tms5220->data_w(space, 0, m_speech_write_buffer);
|
||||
}
|
||||
|
||||
/*************************************
|
||||
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
spchroms.c - This is an emulator for "typical" speech ROMs from TI, as used by TI99/4(a).
|
||||
|
||||
In order to support its speech processor, TI designed some ROMs with a 1-bit data bus
|
||||
and 4-bit address bus (multiplexed 5 times to provide a 18-bit address).
|
||||
A fairly complete description of such a ROM (tms6100) is found in the tms5220 datasheet.
|
||||
|
||||
One notable thing is that the address is a byte address (*NOT* a bit address).
|
||||
|
||||
This file is designed to be interfaced with the tms5220 core.
|
||||
Interfacing it with the tms5110 would make sense, too.
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "spchroms.h"
|
||||
|
||||
static UINT8 *speechrom_data = NULL; /* pointer to speech ROM data */
|
||||
static unsigned long speechROMlen = 0; /* length of data pointed by speechrom_data, from 0 to 2^18 */
|
||||
static unsigned long speechROMaddr; /* 18 bit pointer in ROM */
|
||||
#define TMS5220_ADDRESS_MASK 0x3FFFFUL /* 18-bit mask for tms5220 address */
|
||||
static int load_pointer = 0; /* which 4-bit nibble will be affected by load address */
|
||||
static int ROM_bits_count; /* current bit position in ROM */
|
||||
|
||||
/*
|
||||
set the speech ROMs
|
||||
*/
|
||||
void spchroms_config(running_machine &machine, const spchroms_interface *intf)
|
||||
{
|
||||
if (intf->memory_region == NULL)
|
||||
{ /* no speech ROM */
|
||||
speechrom_data = NULL;
|
||||
speechROMlen = 0;
|
||||
}
|
||||
else
|
||||
{ /* speech ROM */
|
||||
speechrom_data = machine.root_device().memregion(intf->memory_region)->base();
|
||||
/* take region length */
|
||||
speechROMlen = machine.root_device().memregion(intf->memory_region)->bytes();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Read 'count' bits serially from speech ROM
|
||||
*/
|
||||
int spchroms_read(device_t *device, int count)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (load_pointer)
|
||||
{ /* first read after load address is ignored */
|
||||
load_pointer = 0;
|
||||
count--;
|
||||
}
|
||||
|
||||
if (speechROMaddr < speechROMlen)
|
||||
if (count < ROM_bits_count)
|
||||
{
|
||||
ROM_bits_count -= count;
|
||||
val = (speechrom_data[speechROMaddr] >> ROM_bits_count) & (0xFF >> (8 - count));
|
||||
}
|
||||
else
|
||||
{
|
||||
val = ((int) speechrom_data[speechROMaddr]) << 8;
|
||||
|
||||
speechROMaddr = (speechROMaddr + 1) & TMS5220_ADDRESS_MASK;
|
||||
|
||||
if (speechROMaddr < speechROMlen)
|
||||
val |= speechrom_data[speechROMaddr];
|
||||
|
||||
ROM_bits_count += 8 - count;
|
||||
|
||||
val = (val >> ROM_bits_count) & (0xFF >> (8 - count));
|
||||
}
|
||||
else
|
||||
val = 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
Write an address nibble to speech ROM
|
||||
*/
|
||||
void spchroms_load_address(device_t *device, int data)
|
||||
{
|
||||
/* tms5220 data sheet says that if we load only one 4-bit nibble, it won't work.
|
||||
This code does not care about this. */
|
||||
speechROMaddr = ( (speechROMaddr & ~(0xf << load_pointer))
|
||||
| (((unsigned long) (data & 0xf)) << load_pointer) ) & TMS5220_ADDRESS_MASK;
|
||||
load_pointer += 4;
|
||||
ROM_bits_count = 8;
|
||||
}
|
||||
|
||||
/*
|
||||
Perform a read and branch command
|
||||
*/
|
||||
void spchroms_read_and_branch(device_t *device)
|
||||
{
|
||||
/* tms5220 data sheet says that if more than one speech ROM (tms6100) is present,
|
||||
there is a bus contention. This code does not care about this. */
|
||||
if (speechROMaddr < speechROMlen-1)
|
||||
speechROMaddr = (speechROMaddr & 0x3c000UL)
|
||||
| (((((unsigned long) speechrom_data[speechROMaddr]) << 8)
|
||||
| speechrom_data[speechROMaddr+1]) & 0x3fffUL);
|
||||
else if (speechROMaddr == speechROMlen-1)
|
||||
speechROMaddr = (speechROMaddr & 0x3c000UL)
|
||||
| ((((unsigned long) speechrom_data[speechROMaddr]) << 8) & 0x3fffUL);
|
||||
else
|
||||
speechROMaddr = (speechROMaddr & 0x3c000UL);
|
||||
|
||||
ROM_bits_count = 8;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
#ifndef __SPCHROMS_H
|
||||
#define __SPCHROMS_H
|
||||
|
||||
struct spchroms_interface
|
||||
{
|
||||
const char *memory_region; /* memory region where the speech ROM is. NULL means no speech ROM */
|
||||
};
|
||||
|
||||
void spchroms_config(running_machine &machine, const spchroms_interface *intf);
|
||||
|
||||
int spchroms_read(device_t *device, int count);
|
||||
void spchroms_load_address(device_t *device, int data);
|
||||
void spchroms_read_and_branch(device_t *device);
|
||||
|
||||
#endif
|
@ -54,7 +54,7 @@ TODO:
|
||||
#include "cpu/tms7000/tms7000.h"
|
||||
#include "video/tms3556.h"
|
||||
#include "sound/tms5220.h"
|
||||
#include "audio/spchroms.h"
|
||||
#include "machine/spchrom.h"
|
||||
//#include "imagedev/cartslot.h"
|
||||
//#include "imagedev/cassette.h"
|
||||
|
||||
@ -74,7 +74,6 @@ public:
|
||||
required_device<tms5220c_device> m_tms5220c;
|
||||
|
||||
virtual void machine_start();
|
||||
virtual void machine_reset();
|
||||
|
||||
DECLARE_READ8_MEMBER( mailbox_wx319_r );
|
||||
DECLARE_WRITE8_MEMBER( mailbox_wx318_w );
|
||||
@ -281,9 +280,9 @@ READ8_MEMBER(exelv_state::tms7041_porta_r)
|
||||
logerror("tms7041_porta_r\n");
|
||||
|
||||
data |= (m_tms7020_portb & 0x01 ) ? 0x04 : 0x00;
|
||||
data |= tms5220_intq_r(m_tms5220c) ? 0x08 : 0x00;
|
||||
data |= m_tms5220c->intq_r() ? 0x08 : 0x00;
|
||||
data |= (m_tms7020_portb & 0x02) ? 0x10 : 0x00;
|
||||
data |= tms5220_readyq_r(m_tms5220c) ? 0x80 : 0x00;
|
||||
data |= m_tms5220c->readyq_r() ? 0x80 : 0x00;
|
||||
|
||||
return data;
|
||||
}
|
||||
@ -319,8 +318,8 @@ WRITE8_MEMBER(exelv_state::tms7041_portb_w)
|
||||
{
|
||||
logerror("tms7041_portb_w: data = 0x%02x\n", data);
|
||||
|
||||
tms5220_wsq_w(m_tms5220c, (data & 0x01) ? 1 : 0);
|
||||
tms5220_rsq_w(m_tms5220c, (data & 0x02) ? 1 : 0);
|
||||
m_tms5220c->wsq_w((data & 0x01) ? 1 : 0);
|
||||
m_tms5220c->rsq_w((data & 0x02) ? 1 : 0);
|
||||
|
||||
m_maincpu->set_input_line(TMS7000_IRQ1_LINE, (data & 0x04) ? CLEAR_LINE : ASSERT_LINE);
|
||||
|
||||
@ -381,7 +380,7 @@ WRITE8_MEMBER(exelv_state::tms7041_portd_w)
|
||||
{
|
||||
logerror("tms7041_portd_w: data = 0x%02x\n", data);
|
||||
|
||||
tms5220_data_w(m_tms5220c, space, 0, BITSWAP8(data,0,1,2,3,4,5,6,7));
|
||||
m_tms5220c->data_w(space, 0, BITSWAP8(data,0,1,2,3,4,5,6,7));
|
||||
m_tms7041_portd = data;
|
||||
}
|
||||
|
||||
@ -475,16 +474,6 @@ static INPUT_PORTS_START(exelv)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
static const tms5220_interface exl100_tms5220_interface =
|
||||
{
|
||||
DEVCB_NULL, /* no IRQ callback */
|
||||
DEVCB_NULL, /* no Ready callback */
|
||||
spchroms_read, /* speech ROM read handler */
|
||||
spchroms_load_address, /* speech ROM load address handler */
|
||||
spchroms_read_and_branch /* speech ROM read and branch handler */
|
||||
};
|
||||
|
||||
|
||||
void exelv_state::palette_init()
|
||||
{
|
||||
int i, red, green, blue;
|
||||
@ -519,12 +508,6 @@ void exelv_state::machine_start()
|
||||
save_item(NAME(m_wx319));
|
||||
}
|
||||
|
||||
void exelv_state::machine_reset()
|
||||
{
|
||||
static const spchroms_interface exelv_speech_intf = {"tms5220c"};
|
||||
spchroms_config(machine(), &exelv_speech_intf);
|
||||
}
|
||||
|
||||
static MACHINE_CONFIG_START( exl100, exelv_state )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD("maincpu", TMS7000_EXL, XTAL_4_9152MHz) /* TMS7020 */
|
||||
@ -557,10 +540,12 @@ static MACHINE_CONFIG_START( exl100, exelv_state )
|
||||
MCFG_SCREEN_REFRESH_RATE(50)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
|
||||
|
||||
MCFG_DEVICE_ADD("vsm", SPEECHROM, 0)
|
||||
|
||||
/* sound */
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_ADD("tms5220c", TMS5220C, 640000)
|
||||
MCFG_SOUND_CONFIG(exl100_tms5220_interface)
|
||||
MCFG_TMS52XX_SPEECHROM("vsm")
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
@ -597,10 +582,12 @@ static MACHINE_CONFIG_START( exeltel, exelv_state )
|
||||
MCFG_SCREEN_REFRESH_RATE(50)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
|
||||
|
||||
MCFG_DEVICE_ADD("vsm", SPEECHROM, 0)
|
||||
|
||||
/* sound */
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_ADD("tms5220c", TMS5220C, 640000)
|
||||
MCFG_SOUND_CONFIG(exl100_tms5220_interface)
|
||||
MCFG_TMS52XX_SPEECHROM("vsm")
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
@ -618,7 +605,7 @@ ROM_START(exl100)
|
||||
ROM_REGION(0x10000, "user1", ROMREGION_ERASEFF) /* cartridge area */
|
||||
|
||||
/* is this correct for exl100? */
|
||||
ROM_REGION(0x8000, "tms5220c", 0)
|
||||
ROM_REGION(0x8000, "vsm", 0)
|
||||
ROM_LOAD("cm62312.bin", 0x0000, 0x4000, CRC(93b817de) SHA1(03863087a071b8f22d36a52d18243f1c33e17ff7)) /* system speech ROM */
|
||||
ROM_END
|
||||
|
||||
@ -636,7 +623,7 @@ ROM_START(exeltel)
|
||||
ROM_SYSTEM_BIOS( 1, "spanish", "Spanish" )
|
||||
ROMX_LOAD("amper.bin", 0x0000, 0x10000, CRC(45af256c) SHA1(3bff16542f8ac55b9841084ea38034132459facb), ROM_BIOS(2)) /* Spanish system rom */
|
||||
|
||||
ROM_REGION(0x8000, "tms5220c", 0)
|
||||
ROM_REGION(0x8000, "vsm", 0)
|
||||
ROM_LOAD("cm62312.bin", 0x0000, 0x4000, CRC(93b817de) SHA1(03863087a071b8f22d36a52d18243f1c33e17ff7)) /* system speech ROM */
|
||||
ROM_END
|
||||
|
||||
|
@ -64,7 +64,7 @@ static ADDRESS_MAP_START( mpf1b_io_map, AS_IO, 8, mpf1_state )
|
||||
AM_RANGE(0x00, 0x03) AM_MIRROR(0x3c) AM_DEVREADWRITE(I8255A_TAG, i8255_device, read, write)
|
||||
AM_RANGE(0x40, 0x43) AM_MIRROR(0x3c) AM_DEVREADWRITE(Z80CTC_TAG, z80ctc_device, read, write)
|
||||
AM_RANGE(0x80, 0x83) AM_MIRROR(0x3c) AM_DEVREADWRITE(Z80PIO_TAG, z80pio_device, read, write)
|
||||
AM_RANGE(0xfe, 0xfe) AM_MIRROR(0x01) AM_DEVREADWRITE_LEGACY(TMS5220_TAG, tms5220_status_r, tms5220_data_w)
|
||||
AM_RANGE(0xfe, 0xfe) AM_MIRROR(0x01) AM_DEVREADWRITE(TMS5220_TAG, tms5220_device, status_r, data_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( mpf1p_io_map, AS_IO, 8, mpf1_state )
|
||||
@ -317,19 +317,6 @@ static const cassette_interface mpf1_cassette_interface =
|
||||
NULL
|
||||
};
|
||||
|
||||
/* TMS5220 Interface */
|
||||
|
||||
static const tms5220_interface mpf1_tms5220_intf =
|
||||
{
|
||||
DEVCB_NULL, /* no IRQ callback */
|
||||
DEVCB_NULL, /* no Ready callback */
|
||||
#if 1
|
||||
spchroms_read, /* speech ROM read handler */
|
||||
spchroms_load_address, /* speech ROM load address handler */
|
||||
spchroms_read_and_branch /* speech ROM read and branch handler */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Machine Initialization */
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(mpf1_state::check_halt_callback)
|
||||
@ -404,7 +391,6 @@ static MACHINE_CONFIG_START( mpf1b, mpf1_state )
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
|
||||
|
||||
MCFG_SOUND_ADD(TMS5220_TAG, TMS5220, 680000L)
|
||||
MCFG_SOUND_CONFIG(mpf1_tms5220_intf)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
||||
|
||||
MCFG_TIMER_DRIVER_ADD_PERIODIC("halt_timer", mpf1_state, check_halt_callback, attotime::from_hz(1))
|
||||
|
@ -126,8 +126,8 @@ WRITE8_MEMBER( pes_state::rsws_w )
|
||||
#ifdef DEBUG_PORTS
|
||||
logerror("port0 write: RSWS states updated: /RS: %d, /WS: %d\n", m_rsstate, m_wsstate);
|
||||
#endif
|
||||
tms5220_rsq_w(state->m_speech, m_rsstate);
|
||||
tms5220_wsq_w(state->m_speech, m_wsstate);
|
||||
state->m_speech->rsq_w(m_rsstate);
|
||||
state->m_speech->wsq_w(m_wsstate);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( pes_state::port1_w )
|
||||
@ -136,7 +136,7 @@ WRITE8_MEMBER( pes_state::port1_w )
|
||||
#ifdef DEBUG_PORTS
|
||||
logerror("port1 write: tms5220 data written: %02X\n", data);
|
||||
#endif
|
||||
tms5220_data_w(state->m_speech, space, 0, data);
|
||||
state->m_speech->data_w(space, 0, data);
|
||||
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ READ8_MEMBER( pes_state::port1_r )
|
||||
{
|
||||
UINT8 data = 0xFF;
|
||||
pes_state *state = machine().driver_data<pes_state>();
|
||||
data = tms5220_status_r(state->m_speech, space, 0);
|
||||
data = state->m_speech->status_r(space, 0);
|
||||
#ifdef DEBUG_PORTS
|
||||
logerror("port1 read: tms5220 data read: 0x%02X\n", data);
|
||||
#endif
|
||||
@ -186,8 +186,8 @@ READ8_MEMBER( pes_state::port3_r )
|
||||
{
|
||||
data |= 0x10; // set RTS bit
|
||||
}
|
||||
data |= (tms5220_intq_r(state->m_speech)<<2);
|
||||
data |= (tms5220_readyq_r(state->m_speech)<<3);
|
||||
data |= (state->m_speech->intq_r()<<2);
|
||||
data |= (state->m_speech->readyq_r()<<3);
|
||||
#ifdef DEBUG_PORTS
|
||||
logerror("port3 read: returning 0x%02X: ", data);
|
||||
logerror("RXD: %d; ", BIT(data,0));
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "audio/spchroms.h"
|
||||
#include "machine/spchrom.h"
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "cpu/z80/z80daisy.h"
|
||||
#include "imagedev/cassette.h"
|
||||
|
@ -79,7 +79,7 @@ UINT8 a2bus_echoii_device::read_c0nx(address_space &space, UINT8 offset)
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
return 0x1f | tms5220_status_r(m_tms, space, 0);
|
||||
return 0x1f | m_tms->status_r(space, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -90,7 +90,7 @@ void a2bus_echoii_device::write_c0nx(address_space &space, UINT8 offset, UINT8 d
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
tms5220_data_w(m_tms, space, offset, data);
|
||||
m_tms->data_w(space, offset, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -545,7 +545,7 @@ UINT8 a2bus_echoplus_device::read_c0nx(address_space &space, UINT8 offset)
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
return 0x1f | tms5220_status_r(m_tms, space, 0);
|
||||
return 0x1f | m_tms->status_r(space, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -556,7 +556,7 @@ void a2bus_echoplus_device::write_c0nx(address_space &space, UINT8 offset, UINT8
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
tms5220_data_w(m_tms, space, offset, data);
|
||||
m_tms->data_w(space, offset, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2707,7 +2707,7 @@ void rmnimbus_state::rmni_sound_reset()
|
||||
//device_t *ay8910 = machine().device(AY8910_TAG);
|
||||
device_t *msm5205 = machine().device(MSM5205_TAG);
|
||||
|
||||
//ay8910_reset_ym(ay8910);
|
||||
//ay8910->reset();
|
||||
msm5205_reset_w(msm5205, 1);
|
||||
|
||||
m_last_playmode=MSM5205_S48_4B;
|
||||
|
@ -20,14 +20,13 @@
|
||||
|
||||
#include "spchsyn.h"
|
||||
#include "sound/wave.h"
|
||||
#include "machine/spchrom.h"
|
||||
|
||||
#define TMS5220_ADDRESS_MASK 0x3FFFFUL /* 18-bit mask for tms5220 address */
|
||||
|
||||
#define VERBOSE 1
|
||||
#define LOG logerror
|
||||
|
||||
#define SPEECHROM_TAG "speechrom"
|
||||
|
||||
#define REAL_TIMING 0
|
||||
|
||||
/****************************************************************************/
|
||||
@ -108,7 +107,7 @@ READ8Z_MEMBER( ti_speech_synthesizer_device::readz )
|
||||
if ((offset & m_select_mask)==m_select_value)
|
||||
{
|
||||
machine().device("maincpu")->execute().adjust_icount(-(18+3)); /* this is just a minimum, it can be more */
|
||||
*value = m_vsp->read(space, offset, 0xff) & 0xff;
|
||||
*value = m_vsp->status_r(space, offset, 0xff) & 0xff;
|
||||
if (VERBOSE>4) LOG("spchsyn: read value = %02x\n", *value);
|
||||
}
|
||||
}
|
||||
@ -126,7 +125,7 @@ WRITE8_MEMBER( ti_speech_synthesizer_device::write )
|
||||
/* when there are 15 bytes in FIFO. It should be 16. Of course, if */
|
||||
/* it were the case, we would need to store the value on the bus, */
|
||||
/* which would be more complex. */
|
||||
if (!m_vsp->readyq())
|
||||
if (!m_vsp->readyq_r())
|
||||
{
|
||||
attotime time_to_ready = attotime::from_double(m_vsp->time_to_ready());
|
||||
int cycles_to_ready = machine().device<cpu_device>("maincpu")->attotime_to_cycles(time_to_ready);
|
||||
@ -136,104 +135,11 @@ WRITE8_MEMBER( ti_speech_synthesizer_device::write )
|
||||
machine().scheduler().timer_set(attotime::zero, FUNC_NULL);
|
||||
}
|
||||
if (VERBOSE>4) LOG("spchsyn: write value = %02x\n", data);
|
||||
m_vsp->write(space, offset, data);
|
||||
m_vsp->data_w(space, offset, data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
Callbacks from TMS5220
|
||||
*****************************************************************************/
|
||||
/*
|
||||
Read 'count' bits serially from speech ROM. The offset is used as the count.
|
||||
*/
|
||||
READ8_MEMBER( ti_speech_synthesizer_device::spchrom_read )
|
||||
{
|
||||
int val;
|
||||
int count = offset;
|
||||
|
||||
if (m_load_pointer != 0)
|
||||
{ // first read after load address is ignored
|
||||
m_load_pointer = 0;
|
||||
count--;
|
||||
}
|
||||
|
||||
if (m_sprom_address < m_sprom_length)
|
||||
{
|
||||
if (count < m_rombits_count)
|
||||
{
|
||||
m_rombits_count -= count;
|
||||
val = (m_speechrom[m_sprom_address] >> m_rombits_count) & (0xFF >> (8 - count));
|
||||
}
|
||||
else
|
||||
{
|
||||
val = ((int)m_speechrom[m_sprom_address]) << 8;
|
||||
|
||||
m_sprom_address = (m_sprom_address + 1) & TMS5220_ADDRESS_MASK;
|
||||
|
||||
if (m_sprom_address < m_sprom_length)
|
||||
val |= m_speechrom[m_sprom_address];
|
||||
|
||||
m_rombits_count += 8 - count;
|
||||
|
||||
val = (val >> m_rombits_count) & (0xFF >> (8 - count));
|
||||
}
|
||||
}
|
||||
else
|
||||
val = 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
Write an address nibble to speech ROM. The address nibble is in the data,
|
||||
the offset is ignored.
|
||||
*/
|
||||
WRITE8_MEMBER( ti_speech_synthesizer_device::spchrom_load_address )
|
||||
{
|
||||
// tms5220 data sheet says that if we load only one 4-bit nibble, it won't work.
|
||||
// This code does not care about this.
|
||||
m_sprom_address = ((m_sprom_address & ~(0xf << m_load_pointer))
|
||||
| (((unsigned long) (data & 0xf)) << m_load_pointer) ) & TMS5220_ADDRESS_MASK;
|
||||
m_load_pointer += 4;
|
||||
m_rombits_count = 8;
|
||||
}
|
||||
|
||||
/*
|
||||
Perform a read and branch command. We do not use the offset or data parameter.
|
||||
*/
|
||||
WRITE8_MEMBER( ti_speech_synthesizer_device::spchrom_read_and_branch )
|
||||
{
|
||||
// tms5220 data sheet says that if more than one speech ROM (tms6100) is present,
|
||||
// there is a bus contention. This code does not care about this. */
|
||||
if (m_sprom_address < m_sprom_length-1)
|
||||
m_sprom_address = (m_sprom_address & 0x3c000UL)
|
||||
| (((((unsigned long) m_speechrom[m_sprom_address]) << 8)
|
||||
| m_speechrom[m_sprom_address+1]) & 0x3fffUL);
|
||||
else if (m_sprom_address == m_sprom_length-1)
|
||||
m_sprom_address = (m_sprom_address & 0x3c000UL)
|
||||
| ((((unsigned long) m_speechrom[m_sprom_address]) << 8) & 0x3fffUL);
|
||||
else
|
||||
m_sprom_address = (m_sprom_address & 0x3c000UL);
|
||||
|
||||
m_rombits_count = 8;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
Callback interface instance
|
||||
*/
|
||||
static const tms52xx_config ti99_4x_tms5200interface =
|
||||
{
|
||||
DEVCB_NULL, // no IRQ callback
|
||||
DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, ti_speech_synthesizer_device, speech_ready),
|
||||
|
||||
DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, ti_speech_synthesizer_device, spchrom_read), // speech ROM read handler
|
||||
DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, ti_speech_synthesizer_device, spchrom_load_address), // speech ROM load address handler
|
||||
DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, ti_speech_synthesizer_device, spchrom_read_and_branch) // speech ROM read and branch handler
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
WRITE_LINE_MEMBER( ti_speech_synthesizer_device::speech_ready )
|
||||
@ -260,17 +166,11 @@ void ti_speech_synthesizer_device::device_start()
|
||||
|
||||
void ti_speech_synthesizer_device::device_config_complete()
|
||||
{
|
||||
m_vsp = subdevice<tmc0285n_device>("speechsyn");
|
||||
m_vsp = subdevice<tmc0285_device>("speechsyn");
|
||||
}
|
||||
|
||||
void ti_speech_synthesizer_device::device_reset()
|
||||
{
|
||||
m_speechrom = memregion(SPEECHROM_TAG)->base();
|
||||
m_sprom_length = memregion(SPEECHROM_TAG)->bytes();
|
||||
m_sprom_address = 0;
|
||||
m_load_pointer = 0;
|
||||
m_rombits_count = 0;
|
||||
|
||||
if (m_genmod)
|
||||
{
|
||||
m_select_mask = 0x1ffc01;
|
||||
@ -284,14 +184,17 @@ void ti_speech_synthesizer_device::device_reset()
|
||||
}
|
||||
|
||||
MACHINE_CONFIG_FRAGMENT( ti99_speech )
|
||||
MCFG_DEVICE_ADD("vsm", SPEECHROM, 0)
|
||||
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_ADD("speechsyn", TMC0285N, 640000L)
|
||||
MCFG_SOUND_CONFIG(ti99_4x_tms5200interface)
|
||||
MCFG_SOUND_ADD("speechsyn", TMC0285, 640000L)
|
||||
MCFG_TMS52XX_READYQ_HANDLER(DEVWRITELINE(DEVICE_SELF_OWNER, ti_speech_synthesizer_device, speech_ready))
|
||||
MCFG_TMS52XX_SPEECHROM("vsm")
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START( ti99_speech )
|
||||
ROM_REGION(0x8000, SPEECHROM_TAG, 0)
|
||||
ROM_REGION(0x8000, "vsm", 0)
|
||||
ROM_LOAD_OPTIONAL("spchrom.bin", 0x0000, 0x8000, CRC(58b155f7) SHA1(382292295c00dff348d7e17c5ce4da12a1d87763)) /* system speech ROM */
|
||||
ROM_END
|
||||
|
||||
|
@ -41,13 +41,7 @@ protected:
|
||||
virtual void device_config_complete();
|
||||
|
||||
private:
|
||||
tmc0285n_device *m_vsp;
|
||||
|
||||
UINT8 *m_speechrom; // pointer to speech ROM data
|
||||
int m_load_pointer; // which 4-bit nibble will be affected by load address
|
||||
int m_rombits_count; // current bit position in ROM
|
||||
UINT32 m_sprom_address; // 18 bit pointer in ROM
|
||||
UINT32 m_sprom_length; // length of data pointed by speechrom_data, from 0 to 2^18
|
||||
tmc0285_device *m_vsp;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "speech8.h"
|
||||
#include "sound/wave.h"
|
||||
#include "machine/spchrom.h"
|
||||
|
||||
#define TMS5220_ADDRESS_MASK 0x3FFFFUL /* 18-bit mask for tms5220 address */
|
||||
|
||||
@ -20,7 +21,6 @@
|
||||
#define LOG logerror
|
||||
|
||||
#define SPEECHSYN_TAG "speechsyn"
|
||||
#define SPEECHROM_TAG "speechrom"
|
||||
|
||||
#define REAL_TIMING 0
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
|
||||
ti998_spsyn_device::ti998_spsyn_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: bus8z_device(mconfig, TI99_SPEECH8, "TI-99/8 Speech synthesizer (onboard)", tag, owner, clock, "ti99_speech8", __FILE__)
|
||||
, m_load_pointer(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -73,7 +72,7 @@ READ8Z_MEMBER( ti998_spsyn_device::readz )
|
||||
if ((offset & m_select_mask)==m_select_value)
|
||||
{
|
||||
machine().device("maincpu")->execute().adjust_icount(-(18+3)); /* this is just a minimum, it can be more */
|
||||
*value = m_vsp->read(space, offset, 0xff) & 0xff;
|
||||
*value = m_vsp->status_r(space, offset, 0xff) & 0xff;
|
||||
if (VERBOSE>4) LOG("speech8: read value = %02x\n", *value);
|
||||
}
|
||||
}
|
||||
@ -91,7 +90,7 @@ WRITE8_MEMBER( ti998_spsyn_device::write )
|
||||
/* when there are 15 bytes in FIFO. It should be 16. Of course, if */
|
||||
/* it were the case, we would need to store the value on the bus, */
|
||||
/* which would be more complex. */
|
||||
if (!m_vsp->readyq())
|
||||
if (!m_vsp->readyq_r())
|
||||
{
|
||||
attotime time_to_ready = attotime::from_double(m_vsp->time_to_ready());
|
||||
int cycles_to_ready = machine().device<cpu_device>("maincpu")->attotime_to_cycles(time_to_ready);
|
||||
@ -101,102 +100,11 @@ WRITE8_MEMBER( ti998_spsyn_device::write )
|
||||
machine().scheduler().timer_set(attotime::zero, FUNC_NULL);
|
||||
}
|
||||
if (VERBOSE>4) LOG("speech8: write value = %02x\n", data);
|
||||
m_vsp->write(space, offset, data);
|
||||
m_vsp->data_w(space, offset, data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
Callbacks from TMS5220
|
||||
*****************************************************************************/
|
||||
/*
|
||||
Read 'count' bits serially from speech ROM
|
||||
*/
|
||||
READ8_MEMBER( ti998_spsyn_device::spchrom_read )
|
||||
{
|
||||
int val;
|
||||
int count = offset;
|
||||
|
||||
if (m_load_pointer != 0)
|
||||
{ // first read after load address is ignored
|
||||
m_load_pointer = 0;
|
||||
count--;
|
||||
}
|
||||
|
||||
if (m_sprom_address < m_sprom_length)
|
||||
{
|
||||
if (count < m_rombits_count)
|
||||
{
|
||||
m_rombits_count -= count;
|
||||
val = (m_speechrom[m_sprom_address] >> m_rombits_count) & (0xFF >> (8 - count));
|
||||
}
|
||||
else
|
||||
{
|
||||
val = ((int)m_speechrom[m_sprom_address]) << 8;
|
||||
|
||||
m_sprom_address = (m_sprom_address + 1) & TMS5220_ADDRESS_MASK;
|
||||
|
||||
if (m_sprom_address < m_sprom_length)
|
||||
val |= m_speechrom[m_sprom_address];
|
||||
|
||||
m_rombits_count += 8 - count;
|
||||
|
||||
val = (val >> m_rombits_count) & (0xFF >> (8 - count));
|
||||
}
|
||||
}
|
||||
else
|
||||
val = 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
Write an address nibble to speech ROM
|
||||
*/
|
||||
WRITE8_MEMBER( ti998_spsyn_device::spchrom_load_address )
|
||||
{
|
||||
// tms5220 data sheet says that if we load only one 4-bit nibble, it won't work.
|
||||
// This code does not care about this.
|
||||
m_sprom_address = ((m_sprom_address & ~(0xf << m_load_pointer))
|
||||
| (((unsigned long) (data & 0xf)) << m_load_pointer) ) & TMS5220_ADDRESS_MASK;
|
||||
m_load_pointer += 4;
|
||||
m_rombits_count = 8;
|
||||
}
|
||||
|
||||
/*
|
||||
Perform a read and branch command
|
||||
*/
|
||||
WRITE8_MEMBER( ti998_spsyn_device::spchrom_read_and_branch )
|
||||
{
|
||||
// tms5220 data sheet says that if more than one speech ROM (tms6100) is present,
|
||||
// there is a bus contention. This code does not care about this. */
|
||||
if (m_sprom_address < m_sprom_length-1)
|
||||
m_sprom_address = (m_sprom_address & 0x3c000UL)
|
||||
| (((((unsigned long) m_speechrom[m_sprom_address]) << 8)
|
||||
| m_speechrom[m_sprom_address+1]) & 0x3fffUL);
|
||||
else if (m_sprom_address == m_sprom_length-1)
|
||||
m_sprom_address = (m_sprom_address & 0x3c000UL)
|
||||
| ((((unsigned long) m_speechrom[m_sprom_address]) << 8) & 0x3fffUL);
|
||||
else
|
||||
m_sprom_address = (m_sprom_address & 0x3c000UL);
|
||||
|
||||
m_rombits_count = 8;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
Callback interface instance
|
||||
*/
|
||||
static const tms52xx_config ti99_8_tms5200interface =
|
||||
{
|
||||
DEVCB_NULL, // no IRQ callback
|
||||
DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, ti998_spsyn_device, speech8_ready),
|
||||
|
||||
DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, ti998_spsyn_device, spchrom_read), // speech ROM read handler
|
||||
DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, ti998_spsyn_device, spchrom_load_address), // speech ROM load address handler
|
||||
DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, ti998_spsyn_device, spchrom_read_and_branch) // speech ROM read and branch handler
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
WRITE_LINE_MEMBER( ti998_spsyn_device::speech8_ready )
|
||||
@ -219,17 +127,11 @@ void ti998_spsyn_device::device_start()
|
||||
{
|
||||
const speech8_config *conf = reinterpret_cast<const speech8_config *>(static_config());
|
||||
m_ready.resolve(conf->ready, *this);
|
||||
m_vsp = subdevice<tms5220n_device>(SPEECHSYN_TAG);
|
||||
m_vsp = subdevice<tms5220_device>(SPEECHSYN_TAG);
|
||||
}
|
||||
|
||||
void ti998_spsyn_device::device_reset()
|
||||
{
|
||||
m_speechrom = memregion(SPEECHROM_TAG)->base();
|
||||
m_sprom_length = memregion(SPEECHROM_TAG)->bytes();
|
||||
m_sprom_address = 0;
|
||||
m_load_pointer = 0;
|
||||
m_rombits_count = 0;
|
||||
|
||||
m_select_mask = 0xfc01;
|
||||
m_select_value = 0x9000;
|
||||
if (VERBOSE>4) LOG("speech8: reset\n");
|
||||
@ -237,14 +139,17 @@ void ti998_spsyn_device::device_reset()
|
||||
|
||||
// Unlike the TI-99/4A, the 99/8 uses the TMS5220
|
||||
MACHINE_CONFIG_FRAGMENT( ti998_speech )
|
||||
MCFG_DEVICE_ADD("vsm", SPEECHROM, 0)
|
||||
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_ADD(SPEECHSYN_TAG, TMS5220N, 640000L)
|
||||
MCFG_SOUND_CONFIG(ti99_8_tms5200interface)
|
||||
MCFG_SOUND_ADD(SPEECHSYN_TAG, TMS5220, 640000L)
|
||||
MCFG_TMS52XX_READYQ_HANDLER(DEVWRITELINE(DEVICE_SELF_OWNER, ti998_spsyn_device, speech8_ready))
|
||||
MCFG_TMS52XX_SPEECHROM("vsm")
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START( ti998_speech )
|
||||
ROM_REGION(0x8000, SPEECHROM_TAG, 0)
|
||||
ROM_REGION(0x8000, "vsm", 0)
|
||||
ROM_LOAD_OPTIONAL("spchrom.bin", 0x0000, 0x8000, BAD_DUMP CRC(58b155f7) SHA1(382292295c00dff348d7e17c5ce4da12a1d87763)) /* system speech ROM */
|
||||
ROM_END
|
||||
|
||||
|
@ -53,12 +53,12 @@ protected:
|
||||
virtual machine_config_constructor device_mconfig_additions() const;
|
||||
|
||||
private:
|
||||
tms5220n_device *m_vsp;
|
||||
UINT8 *m_speechrom; // pointer to speech ROM data
|
||||
int m_load_pointer; // which 4-bit nibble will be affected by load address
|
||||
int m_rombits_count; // current bit position in ROM
|
||||
UINT32 m_sprom_address; // 18 bit pointer in ROM
|
||||
UINT32 m_sprom_length; // length of data pointed by speechrom_data, from 0 to 2^18
|
||||
tms5220_device *m_vsp;
|
||||
// UINT8 *m_speechrom; // pointer to speech ROM data
|
||||
// int m_load_pointer; // which 4-bit nibble will be affected by load address
|
||||
// int m_rombits_count; // current bit position in ROM
|
||||
// UINT32 m_sprom_address; // 18 bit pointer in ROM
|
||||
// UINT32 m_sprom_length; // length of data pointed by speechrom_data, from 0 to 2^18
|
||||
|
||||
// Ready line to the CPU
|
||||
devcb_resolved_write_line m_ready;
|
||||
|
@ -509,7 +509,6 @@ $(MESSOBJ)/mame.a: \
|
||||
|
||||
$(MESSOBJ)/shared.a: \
|
||||
$(MESS_AUDIO)/mea8000.o \
|
||||
$(MESS_AUDIO)/spchroms.o \
|
||||
$(MESS_MACHINE)/3c503.o \
|
||||
$(MESS_MACHINE)/68561mpcc.o \
|
||||
$(MESS_MACHINE)/8530scc.o \
|
||||
|
Loading…
Reference in New Issue
Block a user