mirror of
https://github.com/holub/mame
synced 2025-04-17 22:13:04 +03:00
casio/ct8000.cpp: Emulated Casiotone 8000 keyboard and related systems. (#13237)
* sound/flt_biquad.cpp: Added Sallen-Key high-pass filters. * sound/bbd.cpp: Added MN3207P variant. * sound/upd931.cpp: Emulated µPD931 synthesis chip. New working systems -------------------- Casio Casiotone 8000 [=CO=Windler, Devin Acker] Casio Casiotone FK-1 [BCM, Devin Acker] New systems marked not working ------------------------ Casio Casiotone MB-1 [=CO=Windler, Devin Acker]
This commit is contained in:
parent
7cc6ac973b
commit
efee42e5e4
@ -1503,6 +1503,18 @@ if (SOUNDS["LC82310"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
-- NEC uPD931
|
||||
--@src/devices/sound/upd931.h,SOUNDS["UPD931"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (SOUNDS["UPD931"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/sound/upd931.cpp",
|
||||
MAME_DIR .. "src/devices/sound/upd931.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
-- NEC uPD933
|
||||
--@src/devices/sound/upd933.h,SOUNDS["UPD933"] = true
|
||||
|
@ -52,7 +52,8 @@ void bbd_device_base<Entries, Outputs>::device_start()
|
||||
template<int Entries, int Outputs>
|
||||
void bbd_device_base<Entries, Outputs>::device_clock_changed()
|
||||
{
|
||||
m_stream->set_sample_rate(sample_rate());
|
||||
if (m_cv_handler.isnull())
|
||||
m_stream->set_sample_rate(sample_rate());
|
||||
}
|
||||
|
||||
|
||||
@ -163,3 +164,16 @@ mn3204p_device::mn3204p_device(const machine_config &mconfig, const char *tag, d
|
||||
bbd_device_base(mconfig, tag, owner, clock, MN3204P)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// MN3207P
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(MN3207, mn3207_device, "mn3207", "MN3207 BBD")
|
||||
|
||||
mn3207_device::mn3207_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
bbd_device_base(mconfig, tag, owner, clock, MN3207)
|
||||
{
|
||||
}
|
||||
|
@ -90,4 +90,15 @@ public:
|
||||
|
||||
DECLARE_DEVICE_TYPE(MN3204P, mn3204p_device)
|
||||
|
||||
|
||||
// ======================> mn3207_device
|
||||
|
||||
class mn3207_device : public bbd_device_base<1024, 2>
|
||||
{
|
||||
public:
|
||||
mn3207_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(MN3207, mn3207_device)
|
||||
|
||||
#endif // MAME_SOUND_BBD_H
|
||||
|
@ -7,18 +7,15 @@
|
||||
|
||||
It has a number of constructor-helpers for automatically generating
|
||||
a biquad filter equivalent to the filter response of a few standard
|
||||
analog second order filter topographies.
|
||||
analog first and second order filter topographies.
|
||||
|
||||
This biquad filter implementation is based on one written by Frank
|
||||
Palazzolo, K. Wilkins, Couriersud, and Derrick Renaud, with some changes:
|
||||
* It uses the Q factor directly in the filter definitions, rather than the damping factor (1/2Q)
|
||||
* It implements every common type of digital biquad filter which I could find documentation for.
|
||||
* The filter is Direct-form II instead of Direct-form I, which results in shorter compiled code.
|
||||
* (There are advantages to Direct-form I if the code used fixed-point math, but it does not.)
|
||||
* Optional direct control of the 5 normalized biquad parameters for a custom/raw parameter filter.
|
||||
|
||||
Possibly useful features which aren't implemented because nothing uses them yet:
|
||||
* More Sallen-Key filter variations (band-pass, high-pass)
|
||||
|
||||
*/
|
||||
#include "emu.h"
|
||||
#include "flt_biquad.h"
|
||||
@ -149,60 +146,106 @@ void filter_biquad_device::modify_raw(double a1, double a2, double b0, double b1
|
||||
|
||||
|
||||
// Sallen-Key filters
|
||||
// (sometimes referred to as KRC or VCVS filter structures)
|
||||
|
||||
/*
|
||||
* The calculation of the cutoff parameter for the Sallen-Key low-pass and
|
||||
* high-pass is identical, the only differences being the biquad filter
|
||||
* type used, and the calculation of the q factor.
|
||||
*/
|
||||
filter_biquad_device::biquad_params filter_biquad_device::opamp_sk_lphp_calc(biquad_type type, double r1, double r2, double r3, double r4, double c1, double c2)
|
||||
{
|
||||
filter_biquad_device::biquad_params r;
|
||||
if ((r1 == 0) || (r2 == 0) || (r3 == 0) || (r4 == 0) || (c1 == 0) || (c2 == 0))
|
||||
{
|
||||
fatalerror("filter_biquad_device::opamp_sk_lphp_calc() - no parameters can be 0; parameters were: r1: %f, r2: %f, r3: %f, r4: %f, c1: %f, c2: %f", r1, r2, r3, r4, c1, c2); /* Filter can not be setup. Undefined results. */
|
||||
}
|
||||
r.type = type;
|
||||
r.gain = 1.0 + (r4 / r3); // == (r3 + r4) / r3
|
||||
r.fc = 1.0 / (2 * M_PI * sqrt(r1 * r2 * c1 * c2));
|
||||
if (type == biquad_type::LOWPASS)
|
||||
r.q = sqrt(r1 * r2 * c1 * c2) / ((r1 * c2) + (r2 * c2) + ((r1 * c1) * (1.0 - r.gain)));
|
||||
else if (type == biquad_type::HIGHPASS)
|
||||
r.q = sqrt(r1 * r2 * c1 * c2) / ((r1 * c2) + (r1 * c1) + ((r2 * c2) * (1.0 - r.gain)));
|
||||
else
|
||||
r.q = M_SQRT2/2.0; // we shouldn't get here but fail gracefully if we do.
|
||||
LOGMASKED(LOG_SETUP,"filter_biquad_device::opamp_sk_lphp_calc(%f, %f, %f, %f, %f, %f) yields: fc = %f, Q = %f, gain = %f\n", r1, r2, r3, r4, c1*1000000, c2*1000000, r.fc, r.q, r.gain);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Setup a biquad filter structure based on a single op-amp Sallen-Key low-pass filter circuit.
|
||||
* This is sometimes, incorrectly, called a "Butterworth" filter structure.
|
||||
*
|
||||
* .----------------------------.
|
||||
* | |
|
||||
* --- c1 |
|
||||
* --- |
|
||||
* | |
|
||||
* r1 | r2 |\ |
|
||||
* In >----ZZZZ----+--ZZZZ---+--------+ | \ |
|
||||
* | '--|+ \ |
|
||||
* --- c2 | >--+------> out
|
||||
* --- .--|- / |
|
||||
* | | | / |
|
||||
* gnd | |/ |
|
||||
* | |
|
||||
* | r4 |
|
||||
* +--ZZZZ---'
|
||||
* |
|
||||
* Z
|
||||
* Z r3
|
||||
* Z
|
||||
* |
|
||||
* gnd
|
||||
* ,--------------------------.
|
||||
* | |
|
||||
* --- c1 |
|
||||
* --- |
|
||||
* | |\ |
|
||||
* r1 | r2 | \ |
|
||||
* In >---ZZZZ--+--ZZZZ--+----------|+ \ |
|
||||
* | | >--+---> out
|
||||
* --- c2 ,--|- / |
|
||||
* --- | | / |
|
||||
* | | |/ |
|
||||
* | | |
|
||||
* gnd | r4 |
|
||||
* +--ZZZZ---'
|
||||
* |
|
||||
* Z r3
|
||||
* Z
|
||||
* Z
|
||||
* |
|
||||
* gnd
|
||||
*/
|
||||
filter_biquad_device& filter_biquad_device::opamp_sk_lowpass_setup(double r1, double r2, double r3, double r4, double c1, double c2)
|
||||
{
|
||||
filter_biquad_device::biquad_params p = opamp_sk_lowpass_calc(r1, r2, r3, r4, c1, c2);
|
||||
filter_biquad_device::biquad_params p = opamp_sk_lphp_calc(biquad_type::LOWPASS, r1, r2, r3, r4, c1, c2);
|
||||
return setup(p);
|
||||
}
|
||||
|
||||
void filter_biquad_device::opamp_sk_lowpass_modify(double r1, double r2, double r3, double r4, double c1, double c2)
|
||||
{
|
||||
filter_biquad_device::biquad_params p = opamp_sk_lowpass_calc(r1, r2, r3, r4, c1, c2);
|
||||
filter_biquad_device::biquad_params p = opamp_sk_lphp_calc(biquad_type::LOWPASS, r1, r2, r3, r4, c1, c2);
|
||||
modify(p);
|
||||
}
|
||||
|
||||
filter_biquad_device::biquad_params filter_biquad_device::opamp_sk_lowpass_calc(double r1, double r2, double r3, double r4, double c1, double c2)
|
||||
|
||||
/* Setup a biquad filter structure based on a single op-amp Sallen-Key high-pass filter circuit.
|
||||
*
|
||||
* ,--------------------------.
|
||||
* | |
|
||||
* Z r1 |
|
||||
* Z |
|
||||
* Z |\ |
|
||||
* c1 | c2 | \ |
|
||||
* In >----||---+---||---+----------|+ \ |
|
||||
* | | >--+---> out
|
||||
* Z r2 ,--|- / |
|
||||
* Z | | / |
|
||||
* Z | |/ |
|
||||
* | | |
|
||||
* gnd | r4 |
|
||||
* +--ZZZZ---'
|
||||
* |
|
||||
* Z r3
|
||||
* Z
|
||||
* Z
|
||||
* |
|
||||
* gnd
|
||||
*/
|
||||
filter_biquad_device& filter_biquad_device::opamp_sk_highpass_setup(double r1, double r2, double r3, double r4, double c1, double c2)
|
||||
{
|
||||
filter_biquad_device::biquad_params r;
|
||||
if ((r1 == 0) || (r2 == 0) || (r3 == 0) || (r4 == 0) || (c1 == 0) || (c2 == 0))
|
||||
{
|
||||
fatalerror("filter_biquad_device::opamp_sk_lowpass_calc() - no parameters can be 0; parameters were: r1: %f, r2: %f, r3: %f, r4: %f, c1: %f, c2: %f", r1, r2, r3, r4, c1, c2); /* Filter can not be setup. Undefined results. */
|
||||
}
|
||||
r.type = biquad_type::LOWPASS;
|
||||
r.gain = 1.0 + (r4 / r3); // == (r3 + r4) / r3
|
||||
r.fc = 1.0 / (2 * M_PI * sqrt(r1 * r2 * c1 * c2));
|
||||
r.q = sqrt(r1 * r2 * c1 * c2) / ((r1 * c2) + (r2 * c2) + ((r2 * c1) * (1.0 - r.gain)));
|
||||
LOGMASKED(LOG_SETUP,"filter_biquad_device::opamp_sk_lowpass_calc(%f, %f, %f, %f, %f, %f) yields: fc = %f, Q = %f, gain = %f\n", r1, r2, r3, r4, c1*1000000, c2*1000000, r.fc, r.q, r.gain);
|
||||
return r;
|
||||
filter_biquad_device::biquad_params p = opamp_sk_lphp_calc(biquad_type::HIGHPASS, r1, r2, r3, r4, c1, c2);
|
||||
return setup(p);
|
||||
}
|
||||
|
||||
// TODO when needed: Sallen-Key high-pass filter
|
||||
void filter_biquad_device::opamp_sk_highpass_modify(double r1, double r2, double r3, double r4, double c1, double c2)
|
||||
{
|
||||
filter_biquad_device::biquad_params p = opamp_sk_lphp_calc(biquad_type::HIGHPASS, r1, r2, r3, r4, c1, c2);
|
||||
modify(p);
|
||||
}
|
||||
|
||||
// TODO when needed: Sallen-Key band-pass (there are several versions of this in the 1955 Sallen-Key paper)
|
||||
|
||||
|
||||
// Multiple-Feedback filters
|
||||
@ -210,24 +253,39 @@ filter_biquad_device::biquad_params filter_biquad_device::opamp_sk_lowpass_calc(
|
||||
/* Setup a biquad filter structure based on a single op-amp Multiple-Feedback low-pass filter circuit.
|
||||
* This is sometimes called a "Rauch" filter circuit.
|
||||
* NOTE: There is a well known 'proper' 1st order version of this circuit where
|
||||
* r2 is a dead short, and c1 omitted. As an exception to the usual rule about
|
||||
* missing components, set both c1 and r2 to 0 in this case.
|
||||
* NOTE: There is a variant of this filter with the c1 capacitor left off, and
|
||||
* r2 present. if so, set c1 to 0 and r2 to its expected value.
|
||||
* TODO: make this compatible with the RES_M(999.99) and RES_R(0.001) rules!
|
||||
* r2 is a dead short, and c1 omitted: set r2 to 0 or RES_R(0.001) and c1 to 0
|
||||
* in this case.
|
||||
* NOTE: There is a variant of this filter where r2 is present but c1 is
|
||||
* omitted: set r2 to its expected value, and c1 to 0.
|
||||
*
|
||||
* .--------+---------.
|
||||
* | | |
|
||||
* Z --- c2 |
|
||||
* Z r3 --- |
|
||||
* Z | |
|
||||
* r1 | r2 | |\ |
|
||||
* In >----ZZZZ----+---------+--ZZZZ--+ | \ |
|
||||
* | '--|- \ |
|
||||
* --- c1 | >--+------> out
|
||||
* --- .--|+ /
|
||||
* | | | /
|
||||
* gnd vRef >---' |/
|
||||
* Typical variant: (set c1 to 0 if missing)
|
||||
* ,--------+---------.
|
||||
* | | |
|
||||
* Z r3 --- c2 |
|
||||
* Z --- |
|
||||
* Z | |
|
||||
* r1 | r2 | |\ |
|
||||
* In >---ZZZZ--+-------+--ZZZZ--+ | \ |
|
||||
* | `--|- \ |
|
||||
* --- c1 | >--+---> out
|
||||
* --- ,--|+ /
|
||||
* | | | /
|
||||
* | vRef >---' |/
|
||||
* gnd
|
||||
*
|
||||
* First order variant: (set c1 and r2 to 0)
|
||||
* ,-------+---------.
|
||||
* | | |
|
||||
* Z r3 --- c2 |
|
||||
* Z --- |
|
||||
* Z | |
|
||||
* r1 | | |\ |
|
||||
* In >---ZZZZ--+-------+ | \ |
|
||||
* `--|- \ |
|
||||
* | >--+---> out
|
||||
* ,--|+ /
|
||||
* | | /
|
||||
* vRef >--' |/
|
||||
*
|
||||
*/
|
||||
filter_biquad_device& filter_biquad_device::opamp_mfb_lowpass_setup(double r1, double r2, double r3, double c1, double c2)
|
||||
@ -269,23 +327,21 @@ filter_biquad_device::biquad_params filter_biquad_device::opamp_mfb_lowpass_calc
|
||||
/* Setup a biquad filter structure based on a single op-amp Multiple-Feedback band-pass filter circuit.
|
||||
* This is sometimes called a "modified Deliyannis" or "Deliyannis-friend" filter circuit,
|
||||
* or an "Infinite Gain Multiple-Feedback [band-pass] Filter" aka "IGMF".
|
||||
* TODO: There is a documented modification to this filter which adds a resistor ladder between
|
||||
* ground and the op-amp output, with the 'rung' of the ladder connecting to the + input of
|
||||
* the op-amp, and this allows more control of the filter.
|
||||
* NOTE2: If r2 is not present, then set it to RES_M(999.99), the code will effectively be an Infinite Gain MFB Bandpass.
|
||||
*
|
||||
* .--------+---------.
|
||||
* | | |
|
||||
* --- c1 Z |
|
||||
* --- Z r3 |
|
||||
* | Z |
|
||||
* r1 | c2 | |\ |
|
||||
* In >----ZZZZ----+---------+--||----+ | \ |
|
||||
* Z '--|- \ |
|
||||
* Z r2 | >--+------> out
|
||||
* Z .--|+ /
|
||||
* | | | /
|
||||
* gnd vRef >---' |/
|
||||
* ,--------+---------.
|
||||
* | | |
|
||||
* --- c1 Z r3 |
|
||||
* --- Z |
|
||||
* | Z |
|
||||
* r1 | c2 | |\ |
|
||||
* In >---ZZZZ--+-------+---||---+ | \ |
|
||||
* | `--|- \ |
|
||||
* Z r2 | >--+---> out
|
||||
* Z ,--|+ /
|
||||
* Z | | /
|
||||
* | vRef >---' |/
|
||||
* gnd
|
||||
*
|
||||
*/
|
||||
filter_biquad_device& filter_biquad_device::opamp_mfb_bandpass_setup(double r1, double r2, double r3, double c1, double c2)
|
||||
@ -305,18 +361,18 @@ filter_biquad_device& filter_biquad_device::opamp_mfb_bandpass_setup(double r1,
|
||||
|
||||
/* Setup a biquad filter structure based on a single op-amp Multiple-Feedback high-pass filter circuit.
|
||||
*
|
||||
* .--------+---------.
|
||||
* | | |
|
||||
* --- c3 Z |
|
||||
* --- Z r2 |
|
||||
* | Z |
|
||||
* c1 | c2 | |\ |
|
||||
* In >-----||-----+---------+---||---+ | \ |
|
||||
* Z '--|- \ |
|
||||
* Z r1 | >--+------> out
|
||||
* Z .--|+ /
|
||||
* | | | /
|
||||
* gnd vRef >---' |/
|
||||
* ,--------+---------.
|
||||
* | | |
|
||||
* --- c3 Z |
|
||||
* --- Z r2 |
|
||||
* | Z |
|
||||
* c1 | c2 | |\ |
|
||||
* In >---||----+-------+---||---+ | \ |
|
||||
* Z `--|- \ |
|
||||
* Z r1 | >--+---> out
|
||||
* Z ,--|+ /
|
||||
* | | | /
|
||||
* gnd vRef >---' |/
|
||||
*
|
||||
*/
|
||||
filter_biquad_device& filter_biquad_device::opamp_mfb_highpass_setup(double r1, double r2, double c1, double c2, double c3)
|
||||
@ -333,23 +389,26 @@ filter_biquad_device& filter_biquad_device::opamp_mfb_highpass_setup(double r1,
|
||||
return setup(biquad_type::HIGHPASS, fc, q, gain);
|
||||
}
|
||||
|
||||
|
||||
// Other filters:
|
||||
|
||||
// Differentiator Filter
|
||||
|
||||
/* Setup a biquad filter structure based on a single op-amp Differentiator band-pass filter circuit.
|
||||
* This circuit is sometimes called an "Inverting Band Pass Filter Circuit"
|
||||
*
|
||||
* .--------+---------.
|
||||
* | | |
|
||||
* --- c2 Z |
|
||||
* --- Z r2 |
|
||||
* | Z |
|
||||
* r1 c1 | | |\ |
|
||||
* In >----ZZZZ-----||-----+--------+ | \ |
|
||||
* '--|- \ |
|
||||
* | >--+------> out
|
||||
* .--|+ /
|
||||
* | | /
|
||||
* vRef >---' |/
|
||||
* ,--------+---------.
|
||||
* | | |
|
||||
* --- c2 Z r2 |
|
||||
* --- Z |
|
||||
* | Z |
|
||||
* r1 c1 | | |\ |
|
||||
* In >---ZZZZ-----||---+--------+ | \ |
|
||||
* `--|- \ |
|
||||
* | >--+---> out
|
||||
* ,--|+ /
|
||||
* | | /
|
||||
* vRef >---' |/
|
||||
*
|
||||
*/
|
||||
filter_biquad_device& filter_biquad_device::opamp_diff_bandpass_setup(double r1, double r2, double c1, double c2)
|
||||
|
@ -52,16 +52,18 @@ public:
|
||||
// Helper setup functions to create common filters representable by biquad filters:
|
||||
// (and, as needed, modify/update/recalc helpers)
|
||||
|
||||
// universal calculator for both Sallen-Key low-pass and high-pass
|
||||
biquad_params opamp_sk_lphp_calc(biquad_type type, double r1, double r2, double r3, double r4, double c1, double c2);
|
||||
|
||||
// Sallen-Key low-pass
|
||||
filter_biquad_device& opamp_sk_lowpass_setup(double r1, double r2, double r3, double r4, double c1, double c2);
|
||||
void opamp_sk_lowpass_modify(double r1, double r2, double r3, double r4, double c1, double c2);
|
||||
biquad_params opamp_sk_lowpass_calc(double r1, double r2, double r3, double r4, double c1, double c2);
|
||||
|
||||
// TODO when needed: Sallen-Key band-pass
|
||||
// Sallen-Key high-pass
|
||||
filter_biquad_device& opamp_sk_highpass_setup(double r1, double r2, double r3, double r4, double c1, double c2);
|
||||
void opamp_sk_highpass_modify(double r1, double r2, double r3, double r4, double c1, double c2);
|
||||
|
||||
// TODO when needed: Sallen-Key band-reject
|
||||
|
||||
// TODO when needed: Sallen-Key high-pass
|
||||
// TODO when needed: Sallen-Key band-pass (there are several versions of this in the 1955 Sallen-Key paper)
|
||||
|
||||
// Multiple-Feedback low-pass
|
||||
filter_biquad_device& opamp_mfb_lowpass_setup(double r1, double r2, double r3, double c1, double c2);
|
||||
|
599
src/devices/sound/upd931.cpp
Normal file
599
src/devices/sound/upd931.cpp
Normal file
@ -0,0 +1,599 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Devin Acker
|
||||
|
||||
/***************************************************************************
|
||||
NEC/Casio uPD931 synthesis chip
|
||||
|
||||
Many details of this implementation are based on research and notes by Robin Whittle:
|
||||
https://www.firstpr.com.au/rwi/casio/Casio-931-2006-06-17.txt
|
||||
Any references to MT-65 behavior are based on this document.
|
||||
|
||||
TODO:
|
||||
- implement vibrato register (CT-8000 doesn't use it)
|
||||
- a few other unknown/unclear bits in the flags shift register
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "upd931.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
DEFINE_DEVICE_TYPE(UPD931, upd931_device, "upd931", "NEC uPD931")
|
||||
|
||||
upd931_device::upd931_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, UPD931, tag, owner, clock)
|
||||
, device_sound_interface(mconfig, *this)
|
||||
, device_memory_interface(mconfig, *this)
|
||||
, m_io_config("io", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(upd931_device::io_map), this))
|
||||
, m_retrig_timer(nullptr)
|
||||
, m_filter_cb(*this)
|
||||
, m_sync_cb(*this)
|
||||
, m_master(true)
|
||||
{
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
device_memory_interface::space_config_vector upd931_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector{std::make_pair(AS_IO, &m_io_config)};
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::io_map(address_map &map)
|
||||
{
|
||||
map(0x20, 0x27).w(FUNC(upd931_device::note_w));
|
||||
map(0x30, 0x37).w(FUNC(upd931_device::octave_w));
|
||||
// waveform write position: ct8000 uses 40, mt65 uses 60
|
||||
map(0x40, 0x40).mirror(0x20).w(FUNC(upd931_device::wave_pos_w));
|
||||
map(0xa7, 0xa7).w(FUNC(upd931_device::wave_data_w));
|
||||
map(0xb0, 0xb7).w(FUNC(upd931_device::flags_w)); // lower address bits are ignored
|
||||
map(0xb8, 0xbf).w(FUNC(upd931_device::status_latch_w));
|
||||
// vibrato/sustain: ct8000 uses c0-c7, mt65 uses d0-d7 (lower two bits are also ignored)
|
||||
map(0xc0, 0xc3).mirror(0x10).w(FUNC(upd931_device::vibrato_w));
|
||||
map(0xc4, 0xc7).mirror(0x10).w(FUNC(upd931_device::sustain_w));
|
||||
map(0xe0, 0xe7).w(FUNC(upd931_device::note_on_w));
|
||||
map(0xf4, 0xf4).lw8(NAME([this] (offs_t offset, u8 data) { m_filter_cb(data); }));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::device_start()
|
||||
{
|
||||
space(AS_IO).specific(m_io);
|
||||
|
||||
m_stream = stream_alloc(0, 1, clock() / CLOCKS_PER_SAMPLE);
|
||||
|
||||
if (m_master)
|
||||
{
|
||||
m_retrig_timer = timer_alloc(FUNC(upd931_device::timer_tick), this);
|
||||
reset_timer();
|
||||
}
|
||||
m_last_clock = clock();
|
||||
|
||||
m_db = 0xf;
|
||||
m_i1 = m_i2 = m_i3 = 1;
|
||||
m_status = 0xf;
|
||||
|
||||
// generate note frequencies based on CT-8000 crystal frequency (probably not entirely accurate)
|
||||
const unsigned sample_rate = 4'946'864 / CLOCKS_PER_SAMPLE;
|
||||
for (int i = 0; i < 73; i++)
|
||||
{
|
||||
// A4 is note 33, 442 Hz
|
||||
const double freq = 442.0 * pow(2, (i - 33) / 12.0);
|
||||
m_pitch[i] = (1 << PITCH_SHIFT) * (freq * 16 / sample_rate);
|
||||
}
|
||||
|
||||
save_item(NAME(m_db));
|
||||
save_item(NAME(m_i1));
|
||||
save_item(NAME(m_i2));
|
||||
save_item(NAME(m_i3));
|
||||
|
||||
save_item(NAME(m_addr));
|
||||
save_item(NAME(m_data));
|
||||
save_item(NAME(m_status));
|
||||
|
||||
save_item(NAME(m_wave));
|
||||
save_item(NAME(m_wave_pos));
|
||||
save_item(NAME(m_vibrato));
|
||||
save_item(NAME(m_sustain));
|
||||
save_item(NAME(m_reverb));
|
||||
|
||||
save_item(NAME(m_flags));
|
||||
save_item(NAME(m_last_clock));
|
||||
|
||||
save_item(STRUCT_MEMBER(m_voice, m_note));
|
||||
save_item(STRUCT_MEMBER(m_voice, m_octave));
|
||||
save_item(STRUCT_MEMBER(m_voice, m_pitch));
|
||||
save_item(STRUCT_MEMBER(m_voice, m_pitch_counter));
|
||||
save_item(STRUCT_MEMBER(m_voice, m_timbre_shift));
|
||||
|
||||
save_item(STRUCT_MEMBER(m_voice, m_wave_pos));
|
||||
save_item(STRUCT_MEMBER(m_voice, m_wave_out));
|
||||
|
||||
save_item(STRUCT_MEMBER(m_voice, m_env_state));
|
||||
save_item(STRUCT_MEMBER(m_voice, m_env_counter));
|
||||
save_item(STRUCT_MEMBER(m_voice, m_env_level));
|
||||
save_item(STRUCT_MEMBER(m_voice, m_force_release));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
TIMER_CALLBACK_MEMBER(upd931_device::timer_tick)
|
||||
{
|
||||
m_sync_cb(1);
|
||||
sync_w(1);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::device_reset()
|
||||
{
|
||||
std::fill(std::begin(m_wave[0]), std::end(m_wave[0]), 0);
|
||||
std::fill(std::begin(m_wave[1]), std::end(m_wave[1]), 0);
|
||||
m_wave_pos = 0;
|
||||
m_vibrato = 0;
|
||||
m_sustain = 0;
|
||||
m_reverb = 0;
|
||||
|
||||
m_flags = 0;
|
||||
|
||||
std::fill(m_voice.begin(), m_voice.end(), voice_t());
|
||||
|
||||
m_filter_cb(0);
|
||||
m_sync_cb(0);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::device_clock_changed()
|
||||
{
|
||||
m_stream->set_sample_rate(clock() / CLOCKS_PER_SAMPLE);
|
||||
|
||||
if (m_retrig_timer)
|
||||
{
|
||||
const u64 ticks_left = m_retrig_timer->remaining().as_ticks(m_last_clock);
|
||||
const attotime remaining = attotime::from_ticks(ticks_left, clock());
|
||||
const attotime period = attotime::from_ticks(RETRIG_RATE, clock());
|
||||
|
||||
m_retrig_timer->adjust(remaining, 0, period);
|
||||
}
|
||||
|
||||
m_last_clock = clock();
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
|
||||
{
|
||||
for (int i = 0; i < outputs[0].samples(); i++)
|
||||
{
|
||||
s32 sample = 0;
|
||||
for (voice_t &voice : m_voice)
|
||||
{
|
||||
update_env(voice);
|
||||
update_wave(voice);
|
||||
|
||||
sample += voice.m_wave_out[0] * (voice.m_env_level[0] >> VOLUME_SHIFT);
|
||||
sample += voice.m_wave_out[1] * (voice.m_env_level[1] >> VOLUME_SHIFT);
|
||||
}
|
||||
outputs[0].put_int_clamp(i, sample, 1 << 16);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::i1_w(int state)
|
||||
{
|
||||
if (!m_i3 && m_i1 && !state)
|
||||
{
|
||||
// address high nibble on I1 falling edge
|
||||
m_addr &= 0x0f;
|
||||
m_addr |= (m_db << 4);
|
||||
}
|
||||
|
||||
m_i1 = state;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::i2_w(int state)
|
||||
{
|
||||
if (!m_i3)
|
||||
{
|
||||
if (!m_i2 && state)
|
||||
{
|
||||
// address low nibble on I2 rising edge
|
||||
m_addr &= 0xf0;
|
||||
m_addr |= (m_db & 0xf);
|
||||
|
||||
// apply register write
|
||||
m_stream->update();
|
||||
m_io.write_byte(m_addr, m_data & 0xf);
|
||||
}
|
||||
else if (m_i2 && !state)
|
||||
{
|
||||
// data on I2 falling edge
|
||||
m_data = m_db;
|
||||
}
|
||||
}
|
||||
|
||||
m_i2 = state;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::i3_w(int state)
|
||||
{
|
||||
m_i3 = state;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::db_w(u8 data)
|
||||
{
|
||||
m_db = data;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
u8 upd931_device::db_r()
|
||||
{
|
||||
if (m_i1 && m_i2 && !m_i3)
|
||||
return m_status;
|
||||
return 0xf;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::sync_w(int state)
|
||||
{
|
||||
if (BIT(m_flags, FLAG_RETRIGGER))
|
||||
{
|
||||
m_stream->update();
|
||||
|
||||
for (voice_t &voice : m_voice)
|
||||
{
|
||||
if (voice.m_env_state == ENV_DECAY1 || voice.m_env_state == ENV_DECAY2)
|
||||
{
|
||||
voice.m_env_state = ENV_ATTACK1;
|
||||
voice.m_env_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::note_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_voice[offset].m_note = data;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::octave_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_voice[offset].m_octave = m_data;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::wave_pos_w(u8 data)
|
||||
{
|
||||
m_wave_pos = data;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::wave_data_w(u8 data)
|
||||
{
|
||||
const u8 sel = BIT(m_flags, FLAG_WAVE_SEL);
|
||||
m_wave[sel][m_wave_pos & 0xf] = data;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::flags_w(u8 data)
|
||||
{
|
||||
m_flags >>= 1;
|
||||
m_flags |= ((data & 1) << FLAG_WAVE_SEL);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::status_latch_w(offs_t offset, u8 data)
|
||||
{
|
||||
// TODO: more details. ct8000 only checks if bits 1-3 are all zero or not
|
||||
if (m_voice[offset].m_env_state == ENV_IDLE)
|
||||
m_status = 0xf;
|
||||
else
|
||||
m_status = 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::vibrato_w(u8 data)
|
||||
{
|
||||
// TODO: implement this. ct8000 always writes 0 since it uses the external VCO vibrato instead
|
||||
m_vibrato = data & 3;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::sustain_w(u8 data)
|
||||
{
|
||||
m_sustain = data & 3;
|
||||
m_reverb = BIT(data, 1, 2) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::note_on_w(offs_t offset, u8 data)
|
||||
{
|
||||
voice_t &voice = m_voice[offset];
|
||||
if (BIT(data, 0))
|
||||
note_on(voice);
|
||||
else
|
||||
voice.m_env_state = ENV_RELEASE;
|
||||
|
||||
// mt65 turns off sustain and reverb when changing tones, ct8000 does this instead
|
||||
// (and also when playing a new note that is already playing)
|
||||
voice.m_force_release = BIT(data, 3);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::note_on(voice_t &voice)
|
||||
{
|
||||
if (voice.m_note >= 0x2 && voice.m_note <= 0xe)
|
||||
{
|
||||
const u8 note = voice.m_note - 2;
|
||||
u8 octave = voice.m_octave & 7;
|
||||
|
||||
if (octave >= 2)
|
||||
octave -= 2; // octave values 0-1 are the same as 2-3
|
||||
|
||||
/*
|
||||
setting bit 3 of the octave reduces the duty cycle of individual notes, which is
|
||||
implemented here by changing which part of the phase counter to use as the sample address.
|
||||
ct8000 uses this for a few of its presets to produce a simple key-scaling effect.
|
||||
*/
|
||||
if (BIT(voice.m_octave, 3))
|
||||
voice.m_timbre_shift = 3 - octave;
|
||||
else
|
||||
voice.m_timbre_shift = 0;
|
||||
|
||||
voice.m_pitch = m_pitch[octave * 12 + note];
|
||||
}
|
||||
else
|
||||
{
|
||||
voice.m_pitch = 0;
|
||||
}
|
||||
|
||||
voice.m_pitch_counter = 0;
|
||||
voice.m_wave_pos = 0xff;
|
||||
voice.m_wave_out[0] = voice.m_wave_out[1] = 0;
|
||||
voice.m_env_state = ENV_ATTACK1;
|
||||
voice.m_env_counter = 0;
|
||||
|
||||
if (m_master)
|
||||
reset_timer();
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::reset_timer()
|
||||
{
|
||||
const attotime period = attotime::from_ticks(RETRIG_RATE, clock());
|
||||
m_retrig_timer->adjust(period, 0, period);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::update_env(voice_t &voice)
|
||||
{
|
||||
const unsigned shift = BIT(m_flags, FLAG_ENV_SHIFT, 2);
|
||||
|
||||
switch (voice.m_env_state)
|
||||
{
|
||||
case ENV_IDLE:
|
||||
return;
|
||||
|
||||
case ENV_ATTACK1:
|
||||
{
|
||||
static const u16 rates[] =
|
||||
{
|
||||
0, 2048, 512, 256, 160, 80, 32, 8
|
||||
};
|
||||
|
||||
const u8 val = BIT(m_flags, FLAG_ATTACK1, 3);
|
||||
u32 rate;
|
||||
|
||||
if (val == 0)
|
||||
rate = VOLUME_MAX; // value 0 = instant
|
||||
else if (val < 4 && voice.m_env_counter >= (0xe0 << VOLUME_SHIFT))
|
||||
rate = 160 << shift; // values 1-3 slow down at 7/8 of max volume
|
||||
else
|
||||
rate = rates[val] << shift;
|
||||
voice.m_env_counter = std::min(voice.m_env_counter + rate, VOLUME_MAX);
|
||||
|
||||
// only increase wave A level if it isn't set to rise during attack2 instead
|
||||
if (BIT(m_flags, FLAG_ATTACK2_A))
|
||||
voice.m_env_level[0] = 0;
|
||||
else
|
||||
voice.m_env_level[0] = voice.m_env_counter;
|
||||
voice.m_env_level[1] = voice.m_env_counter;
|
||||
|
||||
if (voice.m_env_counter >= VOLUME_MAX)
|
||||
{
|
||||
voice.m_env_counter = 0;
|
||||
voice.m_env_state = ENV_ATTACK2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ENV_ATTACK2:
|
||||
{
|
||||
static const u32 rates[] =
|
||||
{
|
||||
0, 2048, 256, 128, 64, 32, 16, 8
|
||||
};
|
||||
|
||||
const u8 val = BIT(m_flags, FLAG_ATTACK2, 3);
|
||||
u32 rate;
|
||||
|
||||
if (val == 0)
|
||||
rate = VOLUME_MAX;
|
||||
else
|
||||
rate = rates[val] << shift;
|
||||
voice.m_env_counter = std::min(voice.m_env_counter + rate, VOLUME_MAX);
|
||||
|
||||
// fade wave A in, if specified
|
||||
if (BIT(m_flags, FLAG_ATTACK2_A))
|
||||
voice.m_env_level[0] = voice.m_env_counter;
|
||||
|
||||
// fade wave B out, if specified
|
||||
if (BIT(m_flags, FLAG_ATTACK2_B))
|
||||
voice.m_env_level[1] = VOLUME_MAX - voice.m_env_counter;
|
||||
|
||||
if (voice.m_env_counter >= VOLUME_MAX)
|
||||
voice.m_env_state = ENV_DECAY1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ENV_DECAY1:
|
||||
{
|
||||
static const u32 rates[] =
|
||||
{
|
||||
2048, 640, 160, 32, 16, 8, 2, 0
|
||||
};
|
||||
|
||||
const u8 val = BIT(m_flags, FLAG_DECAY1, 3);
|
||||
const u32 rate = rates[val] << shift;
|
||||
|
||||
if (voice.m_env_counter < rate)
|
||||
{
|
||||
voice.m_env_counter = 0;
|
||||
voice.m_env_state = ENV_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
voice.m_env_counter -= rate;
|
||||
}
|
||||
|
||||
voice.m_env_level[0] = voice.m_env_counter;
|
||||
// only fade wave B if it didn't already fade out during attack2
|
||||
if (voice.m_env_level[1])
|
||||
voice.m_env_level[1] = voice.m_env_counter;
|
||||
|
||||
if (!BIT(m_flags, FLAG_DECAY2_DISABLE))
|
||||
{
|
||||
// transition to decay2 at 1/2 or 1/4 of max volume, if enabled
|
||||
const u8 decay2_level = BIT(m_flags, FLAG_DECAY2_LEVEL) ? 0x40 : 0x80;
|
||||
if (voice.m_env_counter < (decay2_level << VOLUME_SHIFT))
|
||||
voice.m_env_state = ENV_DECAY2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ENV_DECAY2:
|
||||
{
|
||||
// apply reverb rate (below 1/8 max volume) or decay2 rate
|
||||
u16 rate;
|
||||
|
||||
if (m_reverb && voice.m_env_counter < (0x20 << VOLUME_SHIFT))
|
||||
rate = 1 << shift;
|
||||
else if (BIT(m_flags, FLAG_DECAY2))
|
||||
rate = 3 << shift;
|
||||
else
|
||||
rate = 6 << shift;
|
||||
|
||||
if (voice.m_env_counter < rate)
|
||||
{
|
||||
voice.m_env_counter = 0;
|
||||
voice.m_env_state = ENV_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
voice.m_env_counter -= rate;
|
||||
}
|
||||
|
||||
voice.m_env_level[0] = voice.m_env_counter;
|
||||
if (voice.m_env_level[1])
|
||||
voice.m_env_level[1] = voice.m_env_counter;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ENV_RELEASE:
|
||||
{
|
||||
// apply reverb rate (below 1/8 max volume), sustain rate (if enabled) or default release rate
|
||||
u16 rate = 512 << shift;
|
||||
|
||||
if (!voice.m_force_release)
|
||||
{
|
||||
if (m_reverb && voice.m_env_counter < (0x20 << VOLUME_SHIFT))
|
||||
rate = 1 << shift;
|
||||
else if (m_sustain == 1)
|
||||
rate = 16 << shift;
|
||||
else if (m_sustain == 2)
|
||||
rate = 12 << shift;
|
||||
}
|
||||
|
||||
if (voice.m_env_counter < rate)
|
||||
{
|
||||
voice.m_env_counter = 0;
|
||||
voice.m_env_state = ENV_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
voice.m_env_counter -= rate;
|
||||
}
|
||||
|
||||
// fade each wave individually because if keyed off during attack, they may be different from each other
|
||||
voice.m_env_level[0] = std::min(voice.m_env_level[0], voice.m_env_counter);
|
||||
voice.m_env_level[1] = std::min(voice.m_env_level[1], voice.m_env_counter);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void upd931_device::update_wave(voice_t &voice)
|
||||
{
|
||||
voice.m_pitch_counter += voice.m_pitch;
|
||||
|
||||
const u8 cycle = BIT(voice.m_pitch_counter, PITCH_SHIFT + 4, 2);
|
||||
/*
|
||||
the part of the counter which is treated as the sample address depends on if key scaling is active.
|
||||
if it is active, then the voice alternates between a narrowed waveform and silence, which alters
|
||||
the timbre without affecting pitch
|
||||
*/
|
||||
u8 pos = BIT(voice.m_pitch_counter, PITCH_SHIFT - voice.m_timbre_shift, 4 + voice.m_timbre_shift);
|
||||
if (pos == voice.m_wave_pos || pos >= 0x10)
|
||||
return;
|
||||
|
||||
voice.m_wave_pos = pos;
|
||||
|
||||
// play every other cycle backwards, if enabled
|
||||
if (BIT(m_flags, FLAG_MIRROR) && BIT(cycle, 0))
|
||||
pos ^= 0xf;
|
||||
|
||||
// flag bits determine which of 4 consecutive cycles to apply waveforms A and B
|
||||
const unsigned cycle_mode[] =
|
||||
{
|
||||
BIT(m_flags, FLAG_MODE_A, 2),
|
||||
BIT(m_flags, FLAG_MODE_B, 2)
|
||||
};
|
||||
|
||||
static const u8 cycle_mask[] =
|
||||
{
|
||||
0xf, // always on
|
||||
0x5, // on, off, on, off
|
||||
0x1, // on 1x, off 3x
|
||||
0x3 // on 2x, off 2x
|
||||
};
|
||||
|
||||
static const s8 steps[] =
|
||||
{
|
||||
0, 1, 2, 2, 4, 4, 8, 8,
|
||||
0, -1, -2, -2, -4, -4, -8, -8
|
||||
};
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
// check if this waveform is enabled for this cycle
|
||||
if (!BIT(cycle_mask[cycle_mode[i]], cycle))
|
||||
continue;
|
||||
|
||||
s8 step = steps[m_wave[i][pos] & 0xf];
|
||||
// invert waveform on every other cycle, if enabled
|
||||
if (BIT(m_flags, FLAG_INVERT) && BIT(cycle, 0))
|
||||
step = -step;
|
||||
|
||||
voice.m_wave_out[i] += step;
|
||||
voice.m_wave_out[i] = util::sext(voice.m_wave_out[i] & 0x3f, 6);
|
||||
}
|
||||
}
|
153
src/devices/sound/upd931.h
Normal file
153
src/devices/sound/upd931.h
Normal file
@ -0,0 +1,153 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Devin Acker
|
||||
|
||||
/***************************************************************************
|
||||
NEC/Casio uPD931 synthesis chip
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_SOUND_UPD931_H
|
||||
#define MAME_SOUND_UPD931_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
class upd931_device : public device_t, public device_sound_interface, public device_memory_interface
|
||||
{
|
||||
public:
|
||||
static constexpr feature_type imperfect_features() { return feature::SOUND; }
|
||||
|
||||
upd931_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
|
||||
|
||||
auto &set_master(bool master) { m_master = master; return *this; }
|
||||
|
||||
auto filter_cb() { return m_filter_cb.bind(); }
|
||||
auto sync_cb() { return m_sync_cb.bind(); }
|
||||
|
||||
void i1_w(int state);
|
||||
void i2_w(int state);
|
||||
void i3_w(int state);
|
||||
|
||||
void db_w(u8 data);
|
||||
u8 db_r();
|
||||
|
||||
void sync_w(int state);
|
||||
|
||||
protected:
|
||||
device_memory_interface::space_config_vector memory_space_config() const override ATTR_COLD;
|
||||
|
||||
virtual void device_start() override ATTR_COLD;
|
||||
virtual void device_reset() override ATTR_COLD;
|
||||
virtual void device_clock_changed() override;
|
||||
|
||||
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
|
||||
|
||||
private:
|
||||
static constexpr unsigned PITCH_SHIFT = 15;
|
||||
static constexpr unsigned VOLUME_SHIFT = 15;
|
||||
static constexpr unsigned VOLUME_MAX = (0xff << VOLUME_SHIFT);
|
||||
|
||||
static constexpr unsigned CLOCKS_PER_SAMPLE = 8;
|
||||
static constexpr unsigned RETRIG_RATE = 0x60000;
|
||||
|
||||
enum
|
||||
{
|
||||
FLAG_DECAY1 = 0, // bits 0-2 = decay1 rate
|
||||
FLAG_ATTACK2 = 3, // bits 3-5 = attack2 rate
|
||||
FLAG_ATTACK1 = 6, // bits 6-8 = attack1 rate
|
||||
FLAG_DECAY2_LEVEL = 9, // bit 9 = decay1->decay2 transition point
|
||||
FLAG_DECAY2 = 10, // bit 10 = decay2 rate
|
||||
FLAG_RETRIGGER = 11, // bit 11 = retrigger note during decay (mandolin effect)
|
||||
FLAG_ENV_SPLIT = 12, // bit 12 = wave A envelope split(?)
|
||||
FLAG_ATTACK2_B = 13, // bit 13 = wave B fades out during attack2
|
||||
FLAG_ATTACK2_A = 14, // bit 14 = wave A fades in during attack2
|
||||
FLAG_DECAY2_DISABLE = 15, // bit 15 = disable decay2
|
||||
FLAG_ENV_SHIFT = 16, // bit 16-17 = envelope/vibrato rate shift
|
||||
FLAG_MIRROR = 19, // bit 19 = mirror waveform on alternate cycles
|
||||
FLAG_INVERT = 20, // bit 20 = invert waveform on alternate cycles
|
||||
FLAG_MODE_B = 21, // bit 21-22 = wave B output mode
|
||||
FLAG_MODE_A = 23, // bit 23-24 = wave A output mode
|
||||
FLAG_WAVE_SEL = 25, // bit 25 = wave data input select
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ENV_IDLE,
|
||||
ENV_ATTACK1,
|
||||
ENV_ATTACK2,
|
||||
ENV_DECAY1,
|
||||
ENV_DECAY2,
|
||||
ENV_RELEASE
|
||||
};
|
||||
|
||||
struct voice_t
|
||||
{
|
||||
u8 m_note = 0;
|
||||
u8 m_octave = 0;
|
||||
u16 m_pitch = 0;
|
||||
u32 m_pitch_counter = 0;
|
||||
s8 m_timbre_shift = 0;
|
||||
|
||||
u8 m_wave_pos = 0;
|
||||
s8 m_wave_out[2] = {0};
|
||||
|
||||
u8 m_env_state = ENV_IDLE;
|
||||
u32 m_env_counter = 0;
|
||||
u32 m_env_level[2] = {0};
|
||||
u8 m_force_release = 0;
|
||||
};
|
||||
|
||||
void io_map(address_map &map) ATTR_COLD;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(timer_tick);
|
||||
|
||||
void note_w(offs_t offset, u8 data);
|
||||
void octave_w(offs_t offset, u8 data);
|
||||
void wave_pos_w(u8 data);
|
||||
void wave_data_w(u8 data);
|
||||
void flags_w(u8 data);
|
||||
void status_latch_w(offs_t offset, u8 data);
|
||||
void vibrato_w(u8 data);
|
||||
void sustain_w(u8 data);
|
||||
void note_on_w(offs_t offset, u8 data);
|
||||
|
||||
void note_on(voice_t &voice);
|
||||
void reset_timer();
|
||||
void update_env(voice_t &voice);
|
||||
void update_wave(voice_t &voice);
|
||||
|
||||
address_space_config m_io_config;
|
||||
memory_access<8, 0, 0, ENDIANNESS_LITTLE>::specific m_io;
|
||||
|
||||
sound_stream *m_stream;
|
||||
emu_timer *m_retrig_timer;
|
||||
|
||||
devcb_write8 m_filter_cb;
|
||||
devcb_write_line m_sync_cb;
|
||||
|
||||
bool m_master;
|
||||
|
||||
u16 m_pitch[12*6 + 1]; // valid note range = C1 to C7
|
||||
|
||||
u8 m_db;
|
||||
u8 m_i1, m_i2, m_i3;
|
||||
|
||||
u8 m_addr, m_data;
|
||||
u8 m_status;
|
||||
|
||||
// data global to all voices
|
||||
u8 m_wave[2][16];
|
||||
u8 m_wave_pos;
|
||||
u8 m_vibrato;
|
||||
u8 m_sustain;
|
||||
u8 m_reverb;
|
||||
|
||||
u32 m_flags;
|
||||
u32 m_last_clock;
|
||||
|
||||
std::array<voice_t, 8> m_voice;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(UPD931, upd931_device)
|
||||
|
||||
#endif // MAME_SOUND_UPD931_H
|
@ -119,6 +119,7 @@ const double XTAL::known_xtals[] = {
|
||||
4'433'619, // 4.433619_MHz_XTAL PAL color subcarrier (technically 4.43361875mhz)
|
||||
4'608'000, // 4.608_MHz_XTAL Luxor ABC-77 keyboard (Keytronic custom part #48-300-107 is equivalent)
|
||||
4'915'200, // 4.9152_MHz_XTAL -
|
||||
4'946'864, // 4.946864_MHz_XTAL Casiotone 8000
|
||||
4'952'000, // 4.952_MHz_XTAL IGS M036 based mahjong games, for TT5665 sound chip
|
||||
5'000'000, // 5_MHz_XTAL Mutant Night
|
||||
5'068'800, // 5.0688_MHz_XTAL Usually used as MC2661 or COM8116 baud rate clock
|
||||
|
857
src/mame/casio/ct8000.cpp
Normal file
857
src/mame/casio/ct8000.cpp
Normal file
@ -0,0 +1,857 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Devin Acker
|
||||
// thanks-to:BCM
|
||||
|
||||
/***************************************************************************
|
||||
Casiotone 8000 / "Symphonytron" system
|
||||
|
||||
The Symphonytron was a modular electronic organ produced by Casio in 1983.
|
||||
The full system consists of:
|
||||
|
||||
- up to two Casiotone 8000 keyboards (8049 CPU, 2x uPD931 "vowel-consonant synthesis")
|
||||
- RC-1 accompaniment unit (uPD7801 CPU, uPD930 rhythm generator, analog percussion)
|
||||
- MB-1 memory unit (8049 CPU, 2x uPD931, RAM cartridge slot)
|
||||
- FK-1 pedal keyboard (8049 CPU, single uPD931)
|
||||
- CS-100 or CS-200 keyboard stand with built-in mixer
|
||||
|
||||
The keyboards and memory unit all connect to the RC-1 via 14-pin DIN connectors.
|
||||
Although the RAM cart slot is located on the MB-1, all actual access to the cart is controlled
|
||||
remotely by the RC-1, which uses the cart to record and play back both rhythm/chord and melody
|
||||
data. The MB-1's sound hardware is then used to play back recorded melody data independently of
|
||||
the keyboards. The RC-1 also has a "tone mix" feature, where note data received from one keyboard
|
||||
is automatically forwarded to the other.
|
||||
|
||||
The individual units can also be used on their own; the MB-1 will also respond to notes and tone
|
||||
selection commands via the DIN connector, but it needs the RC-1 present to do much else.
|
||||
It's marked as "not working" for this reason.
|
||||
|
||||
This driver also features MIDI in/thru support via an "adapter" device which translates a subset
|
||||
of MIDI messages into the protocol used with the original connectors.
|
||||
|
||||
TODO:
|
||||
- volume/expression pedal (for all systems)
|
||||
- fix aliasing in BBD output for some presets
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "ct8000_midi.h"
|
||||
#include "bus/midi/midiinport.h"
|
||||
#include "bus/midi/midioutport.h"
|
||||
#include "cpu/mcs48/mcs48.h"
|
||||
#include "machine/i8243.h"
|
||||
#include "machine/rescap.h"
|
||||
#include "sound/bbd.h"
|
||||
#include "sound/flt_biquad.h"
|
||||
#include "sound/flt_rc.h"
|
||||
#include "sound/flt_vol.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/upd931.h"
|
||||
|
||||
#include "speaker.h"
|
||||
|
||||
#define LOG_VCO (1<<1)
|
||||
|
||||
// #define VERBOSE (LOG_GENERAL | LOG_VCO)
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#include "ct8000.lh"
|
||||
#include "ctfk1.lh"
|
||||
|
||||
namespace {
|
||||
|
||||
class ct8000_state : public driver_device
|
||||
{
|
||||
public:
|
||||
ct8000_state(machine_config const &mconfig, device_type type, char const *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_io(*this, "ioport%c", 'a')
|
||||
, m_midi(*this, "midi")
|
||||
, m_931a(*this, "upd931a")
|
||||
, m_931b(*this, "upd931b")
|
||||
, m_mixer(*this, "mixer")
|
||||
, m_filter_rc(*this, "filter_rc%u", 0)
|
||||
, m_filter_bq(*this, "filter_bq%u", 0)
|
||||
, m_bbd(*this, "bbd")
|
||||
, m_bank(*this, "bank")
|
||||
, m_inputs(*this, "KC%X", 0) // schematic uses KC0-9, A-C
|
||||
{
|
||||
}
|
||||
|
||||
void config_base(machine_config &config) ATTR_COLD;
|
||||
void ctmb1(machine_config &config) ATTR_COLD;
|
||||
void ct8000(machine_config &config) ATTR_COLD;
|
||||
void ctfk1(machine_config &config) ATTR_COLD;
|
||||
|
||||
ioport_value switch_r() { return m_switch; }
|
||||
DECLARE_INPUT_CHANGED_MEMBER(switch_w);
|
||||
DECLARE_INPUT_CHANGED_MEMBER(switch_clear_w);
|
||||
|
||||
protected:
|
||||
void ct8000_map(address_map &map) ATTR_COLD;
|
||||
void ct8000_io_map(address_map &map) ATTR_COLD;
|
||||
|
||||
virtual void driver_start() override ATTR_COLD;
|
||||
|
||||
void p1_w(u8 data);
|
||||
u8 p1_r();
|
||||
void p2_w(u8 data);
|
||||
u8 p2_r();
|
||||
|
||||
void p4a_w(u8 data);
|
||||
void p5a_w(u8 data);
|
||||
void p6a_w(u8 data);
|
||||
void p7a_w(u8 data);
|
||||
|
||||
void p4b_w(u8 data);
|
||||
void p7b_w(u8 data);
|
||||
|
||||
u8 keys_r();
|
||||
|
||||
void filter_main_w(u8 data);
|
||||
void filter_sub_w(u8 data);
|
||||
void filter_bass_w(u8 data);
|
||||
|
||||
void pll_w(offs_t offset, u8 data);
|
||||
virtual void update_clocks();
|
||||
|
||||
attoseconds_t chorus_cv(attotime const &curtime);
|
||||
|
||||
required_device<i8049_device> m_maincpu;
|
||||
required_device_array<i8243_device, 2> m_io;
|
||||
|
||||
required_device<ct8000_midi_device> m_midi;
|
||||
|
||||
required_device<upd931_device> m_931a;
|
||||
optional_device<upd931_device> m_931b;
|
||||
required_device<mixer_device> m_mixer;
|
||||
optional_device_array<filter_rc_device, 3> m_filter_rc;
|
||||
optional_device_array<filter_biquad_device, 3> m_filter_bq;
|
||||
optional_device<mn3207_device> m_bbd;
|
||||
|
||||
required_memory_bank m_bank;
|
||||
|
||||
optional_ioport_array<13> m_inputs;
|
||||
|
||||
u16 m_key_select;
|
||||
u8 m_key_enable;
|
||||
|
||||
ioport_value m_switch;
|
||||
|
||||
u16 m_pll_counter[2];
|
||||
u16 m_pll_ref[2];
|
||||
|
||||
u8 m_clock_select;
|
||||
u8 m_clock_div;
|
||||
};
|
||||
|
||||
void ct8000_state::ct8000_map(address_map &map)
|
||||
{
|
||||
map(0x800, 0xfff).bankr("bank");
|
||||
}
|
||||
|
||||
void ct8000_state::ct8000_io_map(address_map &map)
|
||||
{
|
||||
map(0x00, 0xff).rw(FUNC(ct8000_state::keys_r), FUNC(ct8000_state::pll_w));
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::config_base(machine_config &config)
|
||||
{
|
||||
I8049(config, m_maincpu, 4.946864_MHz_XTAL);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &ct8000_state::ct8000_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &ct8000_state::ct8000_io_map);
|
||||
m_maincpu->p1_out_cb().set(FUNC(ct8000_state::p1_w));
|
||||
m_maincpu->p1_in_cb().set(FUNC(ct8000_state::p1_r));
|
||||
m_maincpu->p2_out_cb().set(FUNC(ct8000_state::p2_w));
|
||||
m_maincpu->p2_in_cb().set(FUNC(ct8000_state::p2_r));
|
||||
|
||||
CT8000_MIDI(config, m_midi);
|
||||
m_midi->int_cb().set_inputline(m_maincpu, MCS48_INPUT_IRQ);
|
||||
m_maincpu->t0_in_cb().set(m_midi, FUNC(ct8000_midi_device::ack_r));
|
||||
|
||||
midi_port_device &mdin(MIDI_PORT(config, "mdin", midiin_slot, "midiin"));
|
||||
mdin.rxd_handler().set(m_midi, FUNC(ct8000_midi_device::rx_w));
|
||||
|
||||
MIDI_PORT(config, "mdthru", midiout_slot, "midiout");
|
||||
mdin.rxd_handler().append("mdthru", FUNC(midi_port_device::write_txd));
|
||||
|
||||
I8243(config, m_io[0]);
|
||||
m_maincpu->prog_out_cb().set(m_io[0], FUNC(i8243_device::prog_w));
|
||||
m_io[0]->p4_out_cb().set(FUNC(ct8000_state::p4a_w));
|
||||
m_io[0]->p5_out_cb().set(FUNC(ct8000_state::p5a_w));
|
||||
m_io[0]->p6_out_cb().set(FUNC(ct8000_state::p6a_w));
|
||||
m_io[0]->p7_out_cb().set(FUNC(ct8000_state::p7a_w));
|
||||
|
||||
I8243(config, m_io[1]);
|
||||
m_maincpu->prog_out_cb().append(m_io[1], FUNC(i8243_device::prog_w));
|
||||
m_io[1]->p4_out_cb().set(FUNC(ct8000_state::p4b_w));
|
||||
m_io[1]->p5_in_cb().set(m_midi, FUNC(ct8000_midi_device::data_r));
|
||||
m_io[1]->p5_out_cb().set_nop();
|
||||
m_io[1]->p6_out_cb().set(m_midi, FUNC(ct8000_midi_device::data_w));
|
||||
m_io[1]->p7_out_cb().set(FUNC(ct8000_state::p7b_w));
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::ctmb1(machine_config &config)
|
||||
{
|
||||
config_base(config);
|
||||
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
|
||||
MIXER(config, m_mixer);
|
||||
m_mixer->add_route(0, "lspeaker", 1.0);
|
||||
m_mixer->add_route(0, "rspeaker", 1.0);
|
||||
|
||||
// 931 A - sub (consonant) waveform
|
||||
UPD931(config, m_931a, m_maincpu->clock());
|
||||
m_931a->set_master(false);
|
||||
m_931a->filter_cb().set(FUNC(ct8000_state::filter_sub_w));
|
||||
/*
|
||||
Both of the uPD931s have a fairly large amount of headroom in their outputs,
|
||||
which is partly compensated for via adjustable gain (see filter_main_w and filter_sub_w),
|
||||
but the base output gain should be boosted as well to provide a decent volume.
|
||||
*/
|
||||
m_931a->add_route(0, m_filter_rc[0], 2.0);
|
||||
|
||||
// sub HPF
|
||||
FILTER_RC(config, m_filter_rc[0]).add_route(0, m_filter_bq[0], 1.0);
|
||||
FILTER_BIQUAD(config, m_filter_bq[0]).add_route(0, m_filter_rc[1], 1.0);
|
||||
|
||||
// sub LPF
|
||||
FILTER_RC(config, m_filter_rc[1]).add_route(0, m_filter_bq[1], 1.0);
|
||||
FILTER_BIQUAD(config, m_filter_bq[1]).add_route(0, "filter_ac0", 1.0);
|
||||
|
||||
FILTER_RC(config, "filter_ac0").set_ac().add_route(0, m_mixer, 1.0);
|
||||
|
||||
// 931 B - main (vowel) waveform
|
||||
UPD931(config, m_931b, m_maincpu->clock());
|
||||
m_931b->sync_cb().set(m_931a, FUNC(upd931_device::sync_w));
|
||||
m_931b->filter_cb().set(FUNC(ct8000_state::filter_main_w));
|
||||
m_931b->add_route(0, m_filter_rc[2], 2.0);
|
||||
|
||||
// main LPF
|
||||
FILTER_RC(config, m_filter_rc[2]).add_route(0, m_filter_bq[2], 1.0);
|
||||
FILTER_BIQUAD(config, m_filter_bq[2]).add_route(0, "filter_ac1", 1.0);
|
||||
|
||||
FILTER_RC(config, "filter_ac1").set_ac().add_route(0, m_mixer, 1.0);
|
||||
|
||||
MN3207(config, m_bbd).set_cv_handler(FUNC(ct8000_state::chorus_cv));
|
||||
m_mixer->add_route(0, m_bbd, 1.0);
|
||||
m_bbd->add_route(ALL_OUTPUTS, "chorus", 0.5);
|
||||
|
||||
auto &bbd_mixer = MIXER(config, "chorus");
|
||||
bbd_mixer.add_route(0, "lspeaker", 0.4);
|
||||
bbd_mixer.add_route(0, "rspeaker", -0.4);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::ct8000(machine_config &config)
|
||||
{
|
||||
ctmb1(config);
|
||||
config.set_default_layout(layout_ct8000);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::ctfk1(machine_config &config)
|
||||
{
|
||||
config_base(config);
|
||||
m_io[0]->p4_out_cb().set_nop(); // no switchable clock
|
||||
|
||||
// valid program/patch numbers on FK-1 start at 1 instead of 0 for some reason
|
||||
m_midi->set_base_program(1);
|
||||
|
||||
SPEAKER(config, "speaker").front_center();
|
||||
|
||||
MIXER(config, m_mixer).add_route(0, "speaker", 1.0);
|
||||
|
||||
UPD931(config, m_931a, m_maincpu->clock());
|
||||
m_931a->filter_cb().set(FUNC(ct8000_state::filter_bass_w));
|
||||
m_931a->add_route(0, m_filter_rc[0], 4.0); // boost volume even more since the FK-1 is monophonic
|
||||
|
||||
FILTER_RC(config, m_filter_rc[0]).add_route(0, m_filter_bq[0], 1.0);
|
||||
FILTER_BIQUAD(config, m_filter_bq[0]).add_route(0, "filter_ac", 1.0);
|
||||
|
||||
FILTER_RC(config, "filter_ac").set_ac().add_route(0, m_mixer, 1.0);
|
||||
|
||||
config.set_default_layout(layout_ctfk1);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::driver_start()
|
||||
{
|
||||
m_bank->configure_entries(0, 2, memregion("bankrom")->base(), 0x800);
|
||||
|
||||
m_key_select = 0xffff;
|
||||
m_key_enable = 0;
|
||||
m_switch = 0;
|
||||
|
||||
m_pll_counter[0] = m_pll_counter[1] = 0;
|
||||
m_pll_ref[0] = m_pll_ref[1] = 0;
|
||||
|
||||
m_clock_select = m_clock_div = 0;
|
||||
|
||||
save_item(NAME(m_key_select));
|
||||
save_item(NAME(m_key_enable));
|
||||
save_item(NAME(m_switch));
|
||||
|
||||
save_item(NAME(m_pll_counter));
|
||||
save_item(NAME(m_pll_ref));
|
||||
|
||||
save_item(NAME(m_clock_select));
|
||||
save_item(NAME(m_clock_div));
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::p1_w(u8 data)
|
||||
{
|
||||
// bit 0-3: 931 data
|
||||
// bit 4: 931 strobe 1 (I1)
|
||||
// bit 5: 931 strobe 2 (I2)
|
||||
// bit 6: 931 B select (ct8000) / 931 select (fk1)
|
||||
// bit 7: 931 A select (ct8000) / unused (fk1)
|
||||
m_931a->db_w(data & 0xf);
|
||||
m_931a->i1_w(BIT(data, 4));
|
||||
m_931a->i2_w(BIT(data, 5));
|
||||
|
||||
if (m_931b)
|
||||
{
|
||||
m_931b->db_w(data & 0xf);
|
||||
m_931b->i1_w(BIT(data, 4));
|
||||
m_931b->i2_w(BIT(data, 5));
|
||||
m_931b->i3_w(BIT(data, 6));
|
||||
m_931a->i3_w(BIT(data, 7));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_931a->i3_w(BIT(data, 6));
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
u8 ct8000_state::p1_r()
|
||||
{
|
||||
u8 status = m_931a->db_r();
|
||||
if (m_931b)
|
||||
status &= m_931b->db_r();
|
||||
|
||||
return 0xf0 | status;
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::p2_w(u8 data)
|
||||
{
|
||||
m_io[0]->p2_w(data & 0xf);
|
||||
m_io[1]->p2_w(data & 0xf);
|
||||
m_io[0]->cs_w(BIT(data, 4));
|
||||
m_io[1]->cs_w(BIT(data, 6));
|
||||
m_bank->set_entry(BIT(data, 7));
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
u8 ct8000_state::p2_r()
|
||||
{
|
||||
return 0xf0 | (m_io[0]->p2_r() & m_io[1]->p2_r());
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::p4a_w(u8 data)
|
||||
{
|
||||
// bit 0: master 931 clock select (1 = master VCO, 0 = slave VCO)
|
||||
// bit 1-2: master 931 clock divider (3, 6, 12, 4)
|
||||
// bit 3: 931 reset
|
||||
m_clock_select = BIT(~data, 0);
|
||||
m_clock_div = BIT(data, 1, 2);
|
||||
|
||||
update_clocks();
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::p5a_w(u8 data)
|
||||
{
|
||||
// key matrix out bits 4-7
|
||||
m_key_select &= 0xff0f;
|
||||
m_key_select |= (data << 4);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::p6a_w(u8 data)
|
||||
{
|
||||
// bit 0: unused
|
||||
// bit 1: key matrix in enable (active low)
|
||||
// bit 2-3: key matrix out bits 8-9
|
||||
m_key_enable = BIT(~data, 1);
|
||||
m_key_select &= 0xfcff;
|
||||
m_key_select |= (BIT(data, 2, 2) << 8);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::p7a_w(u8 data)
|
||||
{
|
||||
// key matrix out bits 0-3
|
||||
m_key_select &= 0xfff0;
|
||||
m_key_select |= data;
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::p4b_w(u8 data)
|
||||
{
|
||||
// bit 0: data out strobe to RC-1
|
||||
// bit 1: data in ack to RC-1 (active low)
|
||||
// bit 2: stereo chorus enable (active low)
|
||||
// bit 3: stereo chorus enable for line in (active low)
|
||||
m_midi->strobe_w(BIT(data, 0));
|
||||
m_midi->ack_w(BIT(data, 1));
|
||||
|
||||
if (m_bbd)
|
||||
m_bbd->set_input_gain(0, BIT(data, 2) ? 0 : 1.0);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::p7b_w(u8 data)
|
||||
{
|
||||
// bit 0-2: key matrix out bits 10-12
|
||||
// bit 3: mute
|
||||
m_key_select &= 0xe3ff;
|
||||
m_key_select |= ((data & 0x7) << 10);
|
||||
|
||||
// mute is applied to mixed/filtered 931 output before the stereo chorus
|
||||
const double gain = BIT(data, 3) ? 1.0 : 0.0;
|
||||
m_mixer->set_input_gain(0, gain);
|
||||
m_mixer->set_input_gain(1, gain);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
u8 ct8000_state::keys_r()
|
||||
{
|
||||
u8 data = 0xff;
|
||||
|
||||
if (m_key_enable)
|
||||
{
|
||||
for (int i = 0; i < m_inputs.size(); i++)
|
||||
if (!BIT(m_key_select, i))
|
||||
data &= m_inputs[i].read_safe(0xff);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
INPUT_CHANGED_MEMBER(ct8000_state::switch_w)
|
||||
{
|
||||
if (!oldval && newval)
|
||||
m_switch |= param;
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
INPUT_CHANGED_MEMBER(ct8000_state::switch_clear_w)
|
||||
{
|
||||
if (!oldval && newval)
|
||||
m_switch = 0;
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::filter_main_w(u8 data)
|
||||
{
|
||||
// bit 0-1 = main LPF cutoff
|
||||
// bit 2-3 = absolute gain
|
||||
double r, c;
|
||||
if (BIT(data, 1))
|
||||
{
|
||||
r = RES_K(68);
|
||||
c = CAP_P(470) + BIT(data, 0) ? CAP_P(330) : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = RES_K(43);
|
||||
c = CAP_P(390);
|
||||
}
|
||||
|
||||
m_filter_rc[2]->filter_rc_set_RC(filter_rc_device::LOWPASS, r, 0, 0, CAP_N(2.2));
|
||||
m_filter_bq[2]->opamp_sk_lowpass_modify(r, r, RES_M(999.99), RES_R(0.001), CAP_N(5.6), c);
|
||||
|
||||
static const double gain[] = { 3.79, 2.82, 1.94, 1 };
|
||||
m_mixer->set_output_gain(0, gain[BIT(data, 2, 2)]);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::filter_sub_w(u8 data)
|
||||
{
|
||||
// bit 0 = sub HPF enable
|
||||
// bit 1 = sub LPF cutoff
|
||||
// bit 2 = sub LPF disable
|
||||
// bit 3 = consonant gain
|
||||
if (BIT(data, 0))
|
||||
{
|
||||
const double c = CAP_N(2.2);
|
||||
m_filter_rc[0]->filter_rc_set_RC(filter_rc_device::HIGHPASS, RES_K(18), 0, 0, c);
|
||||
m_filter_bq[0]->opamp_sk_highpass_modify(RES_K(6.8), RES_K(220), RES_M(999.99), RES_R(0.001), c, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filter_rc[0]->filter_rc_set_RC(filter_rc_device::HIGHPASS, 0, 0, 0, 0);
|
||||
m_filter_bq[0]->modify_raw(0, 0, 1, 0, 0);
|
||||
}
|
||||
|
||||
if (BIT(data, 2))
|
||||
{
|
||||
m_filter_rc[1]->filter_rc_set_RC(filter_rc_device::LOWPASS, 0, 0, 0, 0);
|
||||
m_filter_bq[1]->modify_raw(0, 0, 1, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const double r = BIT(data, 1) ? RES_K(22) : RES_K(56);
|
||||
const double c = BIT(data, 1) ? CAP_P(430) : CAP_P(330);
|
||||
|
||||
m_filter_rc[1]->filter_rc_set_RC(filter_rc_device::LOWPASS, r, 0, 0, CAP_N(2.2));
|
||||
m_filter_bq[1]->opamp_sk_lowpass_modify(r, r, RES_M(999.99), RES_R(0.001), CAP_N(5.6), c);
|
||||
}
|
||||
|
||||
m_filter_bq[1]->set_output_gain(0, BIT(data, 3) ? 0.468 : 1);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::filter_bass_w(u8 data)
|
||||
{
|
||||
// bit 0 = LPF cutoff
|
||||
// bit 1 = LPF enable (seems to be incorrectly inverted in the schematic)
|
||||
// bit 2-3 = gain
|
||||
|
||||
if (BIT(data, 1))
|
||||
{
|
||||
const double r = RES_K(12);
|
||||
const double c = CAP_N(3.3) + BIT(data, 0) ? CAP_N(10) : 0;
|
||||
|
||||
m_filter_rc[0]->filter_rc_set_RC(filter_rc_device::LOWPASS, r, 0, 0, CAP_N(22));
|
||||
m_filter_bq[0]->opamp_sk_lowpass_modify(r, r, RES_M(999.99), RES_R(0.001), CAP_N(56), c);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filter_rc[0]->filter_rc_set_RC(filter_rc_device::LOWPASS, 0, 0, 0, 0);
|
||||
m_filter_bq[0]->modify_raw(0, 0, 1, 0, 0);
|
||||
}
|
||||
|
||||
static const double gain[] = { 3.79, 2.82, 1.94, 1 };
|
||||
m_mixer->set_output_gain(ALL_OUTPUTS, gain[BIT(data, 2, 2)]);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::pll_w(offs_t offset, u8 data)
|
||||
{
|
||||
data &= 0xf;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (!BIT(offset, 3 + i))
|
||||
{
|
||||
switch (offset & 7)
|
||||
{
|
||||
case 0:
|
||||
m_pll_counter[i] &= 0x3ff0;
|
||||
m_pll_counter[i] |= data;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_pll_counter[i] &= 0x3f0f;
|
||||
m_pll_counter[i] |= (data << 4);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_pll_counter[i] &= 0x30ff;
|
||||
m_pll_counter[i] |= (data << 8);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_pll_counter[i] &= 0x0fff;
|
||||
m_pll_counter[i] |= ((data & 3) << 12);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_pll_ref[i] &= 0xff0;
|
||||
m_pll_ref[i] |= data;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
m_pll_ref[i] &= 0xf0f;
|
||||
m_pll_ref[i] |= (data << 4);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
m_pll_ref[i] &= 0x0ff;
|
||||
m_pll_ref[i] |= (data << 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_clocks();
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
void ct8000_state::update_clocks()
|
||||
{
|
||||
double clock_scale[2] = { 1.0, 1.0 };
|
||||
|
||||
// master VCO freq (controls 931 B)
|
||||
const int sel = m_clock_select & 1;
|
||||
if (m_931b && m_pll_counter[sel] && m_pll_ref[sel])
|
||||
{
|
||||
// PLLs are tuned so that increasing/decreasing the counter by 1 raises or lowers pitch by ~1.5 cents
|
||||
clock_scale[0] = (2.0 * m_pll_counter[sel]) / m_pll_ref[sel];
|
||||
|
||||
switch (m_clock_div & 3)
|
||||
{
|
||||
case 0: clock_scale[0] /= 3; break;
|
||||
case 1: clock_scale[0] /= 6; break;
|
||||
case 2: clock_scale[0] /= 12; break;
|
||||
case 3: clock_scale[0] /= 4; break;
|
||||
}
|
||||
|
||||
m_931b->set_clock_scale(clock_scale[0]);
|
||||
}
|
||||
|
||||
// slave VCO freq (controls 931 A and CPU)
|
||||
if (m_pll_counter[1] && m_pll_ref[1])
|
||||
{
|
||||
clock_scale[1] = (2.0 * m_pll_counter[1]) / (3 * m_pll_ref[1]);
|
||||
|
||||
m_maincpu->set_clock_scale(clock_scale[1]);
|
||||
m_931a->set_clock_scale(clock_scale[1]);
|
||||
}
|
||||
|
||||
LOGMASKED(LOG_VCO, "VCO #1 %.3f MHz, #2 %.3f MHz\n",
|
||||
clock_scale[0] * m_maincpu->unscaled_clock() / 1'000'000,
|
||||
clock_scale[1] * m_maincpu->unscaled_clock() / 1'000'000);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
attoseconds_t ct8000_state::chorus_cv(attotime const &cvtime)
|
||||
{
|
||||
// 62.5 to 80 kHz, varies at 0.6666... Hz
|
||||
double pos = cvtime.as_double() / 1.5;
|
||||
pos -= std::floor(pos);
|
||||
pos = (pos < 0.5) ? (2 * pos) : 2 * (1.0 - pos);
|
||||
const double bbd_freq = 62500 + (80000 - 62500) * pos;
|
||||
|
||||
return HZ_TO_ATTOSECONDS(bbd_freq);
|
||||
}
|
||||
|
||||
|
||||
INPUT_PORTS_START(ct8000)
|
||||
PORT_START("KC0")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C2")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C#2")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D2")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D#2")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("E2")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F2")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC1")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F#2")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("G2")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("G#2")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("A2")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("A#2")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("B2")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC2")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C3")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C#3")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D3")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D#3")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("E3")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F3")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC3")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F#3")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("G3")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("G#3")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("A3")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("A#3")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("B3")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC4")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C4")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C#4")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D4")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D#4")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("E4")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F4")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC5")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F#4")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("G4")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("G#4")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("A4")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("A#4")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("B4")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC6")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C5")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C#5")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D5")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D#5")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("E5")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F5")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC7")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F#5")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("G5")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("G#5")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("A5")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("A#5")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("B5")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC8")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C6")
|
||||
PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC9")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Sustain Pedal")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tune Up")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tune Down")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Stereo Chorus") PORT_TOGGLE
|
||||
PORT_BIT(0xf0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KCA")
|
||||
PORT_BIT(0x07, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(ct8000_state::switch_r))
|
||||
PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KCB")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tone Memory 1")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tone Memory 2")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tone Memory 3")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tone Memory 4")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tone Set") PORT_TOGGLE
|
||||
PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KCC")
|
||||
PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Vibrato") PORT_TOGGLE
|
||||
PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("SWITCH")
|
||||
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Effect Cancel") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ct8000_state::switch_clear_w), 0)
|
||||
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Sustain") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ct8000_state::switch_w), 0x1)
|
||||
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Reverb") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ct8000_state::switch_w), 0x4)
|
||||
INPUT_PORTS_END
|
||||
|
||||
INPUT_PORTS_START(ctfk1)
|
||||
PORT_START("KC0")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C1")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C#1")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D1")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D#1")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("E1")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F1")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC1")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F#1")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("G1")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("G#1")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("A1")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("A#1")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("B1")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC2")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C2")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("C#2")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D2")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("D#2")
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("E2")
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("F2")
|
||||
PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC9")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tune Up")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tune Down")
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Bass Select") PORT_TOGGLE
|
||||
PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KCA")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Sustain") PORT_TOGGLE
|
||||
PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KCB")
|
||||
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED) // KI0->KCB diode
|
||||
PORT_BIT(0x0e, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tone Set") PORT_TOGGLE
|
||||
PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
INPUT_PORTS_END
|
||||
|
||||
INPUT_PORTS_START(ctmb1)
|
||||
PORT_START("KC0")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Reverse")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Play")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Forward")
|
||||
PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC1")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keyboard Synchro")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Record")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Reset")
|
||||
PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC2")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Pause")
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Demonstration")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Number Select")
|
||||
PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("KC9")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tune Up")
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tune Down")
|
||||
PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
ROM_START(ct8000)
|
||||
ROM_REGION(0x800, "maincpu", 0)
|
||||
ROM_LOAD("upd8049c-364.bin", 0x000, 0x800, CRC(8c9b3f40) SHA1(5507117671300fe350df39b4ca70239079a1b0e7))
|
||||
|
||||
ROM_REGION(0x1000, "bankrom", 0)
|
||||
ROM_LOAD("ct8000_2732.bin", 0x0000, 0x1000, CRC(e6f1f3f9) SHA1(637a9d2b6be2f12240724c8aa5744c5f28ac4af0))
|
||||
ROM_END
|
||||
|
||||
ROM_START(ctfk1)
|
||||
ROM_REGION(0x800, "maincpu", 0)
|
||||
ROM_LOAD("upd8049c-364.bin", 0x000, 0x800, CRC(8c9b3f40) SHA1(5507117671300fe350df39b4ca70239079a1b0e7))
|
||||
|
||||
ROM_REGION(0x1000, "bankrom", 0)
|
||||
ROM_LOAD("fk1_2732.bin", 0x0000, 0x1000, CRC(f7416356) SHA1(6d92aa5f377769327451334324f1f32b52951968))
|
||||
ROM_END
|
||||
|
||||
ROM_START(ctmb1)
|
||||
ROM_REGION(0x800, "maincpu", 0)
|
||||
ROM_LOAD("upd8049c-364.bin", 0x000, 0x800, CRC(8c9b3f40) SHA1(5507117671300fe350df39b4ca70239079a1b0e7))
|
||||
|
||||
ROM_REGION(0x1000, "bankrom", 0)
|
||||
ROM_LOAD("mb1_2732.bin", 0x0000, 0x1000, CRC(fc128110) SHA1(8ff31fdccb8200836cf414bc709d5b9a68279205))
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
SYST( 1983, ct8000, 0, 0, ct8000, ct8000, ct8000_state, empty_init, "Casio", "Casiotone 8000", MACHINE_SUPPORTS_SAVE )
|
||||
SYST( 1983, ctfk1, 0, 0, ctfk1, ctfk1, ct8000_state, empty_init, "Casio", "Casiotone FK-1", MACHINE_SUPPORTS_SAVE )
|
||||
SYST( 1983, ctmb1, 0, 0, ctmb1, ctmb1, ct8000_state, empty_init, "Casio", "Casiotone MB-1", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
|
409
src/mame/casio/ct8000_midi.cpp
Normal file
409
src/mame/casio/ct8000_midi.cpp
Normal file
@ -0,0 +1,409 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Devin Acker
|
||||
|
||||
/***************************************************************************
|
||||
Casiotone 8000 / Symphonytron MIDI interface
|
||||
|
||||
Translates MIDI messages into the 4-bit parallel protocol used by the Symphonytron.
|
||||
Aside from Note Off/On and Program Change messages, this also handles:
|
||||
- CC #1 (vibrato)
|
||||
- CC #64 (sustain pedal)
|
||||
- CC #69 (sustain switch)
|
||||
- CC #91 (reverb)
|
||||
- CC #93 (chorus)
|
||||
- CC #120 (all sound off)
|
||||
- CC #121 (reset controllers)
|
||||
- CC #123 (all notes off)
|
||||
- CC #124-127 (equivalent to 123, otherwise no effect)
|
||||
- MIDI reset (status 0xFF)
|
||||
|
||||
Vibrato, reverb, and chorus CCs all behave as switches, where 64-127 is "on".
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Summary of 4-bit Symphonytron messages
|
||||
|
||||
Messages are sent in 4-bit increments over the DIN connector, in the following order:
|
||||
- high nibble of command
|
||||
- number of following nibbles (normally 1 or 3)
|
||||
- low nibble of command
|
||||
- high nibble of data (if any)
|
||||
- low nibble of data (if any)
|
||||
|
||||
The exception is the reset command, which is a single 0xF nibble.
|
||||
|
||||
The CT-8000 recognizes these messages:
|
||||
10 xx - set effects
|
||||
11 xx - lock effects (corresponding buttons/pedal do nothing while set)
|
||||
12 xx - ??? effects
|
||||
^^ bit 0 = reverb
|
||||
bit 1 = vibrato
|
||||
bit 2 = sustain pedal (only affects the local keyboard)
|
||||
bit 3 = stereo chorus
|
||||
bit 4 = sustain switch
|
||||
|
||||
20 xx - set lowest possible note to send (default is none)
|
||||
21 xx - set highest possible note to send (default is none)
|
||||
22 xx - set lowest possible note to receive/play (default is 0x21 = C2)
|
||||
23 xx - set highest possible note to receive/play (default is 0x61 = C6)
|
||||
24 - stop all notes
|
||||
28 xx - note on or off
|
||||
^^ bit 7 = note on, bits 6-4 = octave, bits 3-0 = note from 0x1 (C) to 0xC (B)
|
||||
|
||||
C0 xx - set tuning (signed, 1.5 cent increments, 0x32 = quarter tone up)
|
||||
|
||||
E1 xx - set patch number
|
||||
|
||||
F - reset instrument
|
||||
|
||||
The MB-1 recognizes all of the above, plus:
|
||||
A0 xx - ???
|
||||
A1 xx - ???
|
||||
A2 xx - ???
|
||||
A3 xx - ???
|
||||
A4 - clear values from A0-A3
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "ct8000_midi.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
DEFINE_DEVICE_TYPE(CT8000_MIDI, ct8000_midi_device, "ct8000_midi", "Casiotone 8000 MIDI adapter")
|
||||
|
||||
namespace {
|
||||
|
||||
INPUT_PORTS_START(ct8000_midi)
|
||||
PORT_START("CHANNEL")
|
||||
PORT_CONFNAME(0xff, 0x00, "MIDI channel")
|
||||
PORT_CONFSETTING( 0x00, "1")
|
||||
PORT_CONFSETTING( 0x01, "2")
|
||||
PORT_CONFSETTING( 0x02, "3")
|
||||
PORT_CONFSETTING( 0x03, "4")
|
||||
PORT_CONFSETTING( 0x04, "5")
|
||||
PORT_CONFSETTING( 0x05, "6")
|
||||
PORT_CONFSETTING( 0x06, "7")
|
||||
PORT_CONFSETTING( 0x07, "8")
|
||||
PORT_CONFSETTING( 0x08, "9")
|
||||
PORT_CONFSETTING( 0x09, "10")
|
||||
PORT_CONFSETTING( 0x0a, "11")
|
||||
PORT_CONFSETTING( 0x0b, "12")
|
||||
PORT_CONFSETTING( 0x0c, "13")
|
||||
PORT_CONFSETTING( 0x0d, "14")
|
||||
PORT_CONFSETTING( 0x0e, "15")
|
||||
PORT_CONFSETTING( 0x0f, "16")
|
||||
INPUT_PORTS_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
ct8000_midi_device::ct8000_midi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, CT8000_MIDI, tag, owner, clock)
|
||||
, device_serial_interface(mconfig, *this)
|
||||
, m_channel(*this, "CHANNEL")
|
||||
, m_int_cb(*this)
|
||||
, m_base_program(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
ioport_constructor ct8000_midi_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(ct8000_midi);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::device_start()
|
||||
{
|
||||
m_midi_data[0] = m_midi_data[1] = 0;
|
||||
|
||||
m_ack = 1;
|
||||
std::fill(std::begin(m_out_data), std::end(m_out_data), 0);
|
||||
|
||||
m_in_data = 0xf;
|
||||
m_in_strobe = 0;
|
||||
|
||||
set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
|
||||
set_rcv_rate(31250);
|
||||
set_tra_rate(0);
|
||||
|
||||
save_item(NAME(m_status));
|
||||
save_item(NAME(m_midi_data));
|
||||
save_item(NAME(m_midi_data_pos));
|
||||
save_item(NAME(m_midi_data_size));
|
||||
save_item(NAME(m_midi_notes_on));
|
||||
save_item(NAME(m_sustain));
|
||||
|
||||
save_item(NAME(m_ack));
|
||||
save_item(NAME(m_int));
|
||||
save_item(NAME(m_out_data));
|
||||
save_item(NAME(m_out_data_read));
|
||||
save_item(NAME(m_out_data_write));
|
||||
save_item(NAME(m_out_data_space));
|
||||
save_item(NAME(m_out_data_controls));
|
||||
|
||||
save_item(NAME(m_in_data));
|
||||
save_item(NAME(m_in_strobe));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::device_reset()
|
||||
{
|
||||
m_status = 0;
|
||||
m_midi_data_pos = m_midi_data_size = 0;
|
||||
m_out_data_space = sizeof(m_out_data);
|
||||
m_sustain = 0;
|
||||
|
||||
std::fill(std::begin(m_midi_notes_on), std::begin(m_midi_notes_on), 0);
|
||||
|
||||
m_out_data_read = m_out_data_write = 0;
|
||||
m_out_data_controls = 0;
|
||||
|
||||
m_int_cb(m_int = 0);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::rcv_complete()
|
||||
{
|
||||
receive_register_extract();
|
||||
|
||||
if (is_receive_framing_error())
|
||||
{
|
||||
m_status = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const u8 data = get_received_char();
|
||||
if (data < 0x80)
|
||||
{
|
||||
if (m_status >= 0x80)
|
||||
{
|
||||
m_midi_data[m_midi_data_pos++] = data;
|
||||
if (m_midi_data_pos == m_midi_data_size)
|
||||
{
|
||||
midi_message();
|
||||
m_midi_data_pos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (data < 0xf0)
|
||||
{
|
||||
m_status = data;
|
||||
|
||||
if (data >= 0xc0 && data <= 0xdf)
|
||||
m_midi_data_size = 1;
|
||||
else
|
||||
m_midi_data_size = 2;
|
||||
m_midi_data_pos = 0;
|
||||
}
|
||||
else if (data < 0xf8)
|
||||
{
|
||||
m_status = 0;
|
||||
}
|
||||
else if (data == 0xff)
|
||||
{
|
||||
reset();
|
||||
send_nibble(0xf);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
u8 ct8000_midi_device::data_r()
|
||||
{
|
||||
return m_out_data[m_out_data_read];
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::ack_w(int state)
|
||||
{
|
||||
if (m_ack && !state)
|
||||
{
|
||||
m_int_cb(m_int = 0);
|
||||
m_out_data_read++;
|
||||
m_out_data_space++;
|
||||
m_out_data_read %= sizeof(m_out_data);
|
||||
}
|
||||
else if (!m_ack && state)
|
||||
{
|
||||
if (m_out_data_read != m_out_data_write)
|
||||
m_int_cb(m_int = 1);
|
||||
}
|
||||
|
||||
m_ack = state;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::strobe_w(int state)
|
||||
{
|
||||
if (!m_in_strobe && state)
|
||||
logerror("data write: %x\n", m_in_data);
|
||||
|
||||
m_in_strobe = state;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::midi_message()
|
||||
{
|
||||
if ((m_status & 0xf) != m_channel->read())
|
||||
return;
|
||||
|
||||
switch (m_status >> 4)
|
||||
{
|
||||
case 0x8: // note off
|
||||
m_midi_data[1] = 0;
|
||||
[[fallthrough]];
|
||||
case 0x9: // note on
|
||||
if (m_midi_data[0] >= NOTE_MIN && m_midi_data[0] <= NOTE_MAX)
|
||||
send_note(m_midi_data[0] - NOTE_MIN, m_midi_data[1]);
|
||||
break;
|
||||
|
||||
case 0xb: // controller
|
||||
switch (m_midi_data[0])
|
||||
{
|
||||
case 1: // mod wheel / vibrato
|
||||
update_control(FX_VIBRATO);
|
||||
break;
|
||||
|
||||
case 64: // sustain pedal
|
||||
update_sustain(m_midi_data[1]);
|
||||
break;
|
||||
|
||||
case 69: // hold 2 / sustain switch
|
||||
update_control(FX_SUSTAIN);
|
||||
break;
|
||||
|
||||
case 91: // reverb
|
||||
update_control(FX_REVERB);
|
||||
break;
|
||||
|
||||
case 93: // chorus
|
||||
update_control(FX_CHORUS);
|
||||
break;
|
||||
|
||||
case 120: // all sound off
|
||||
send_cmd(CMD_STOP);
|
||||
break;
|
||||
|
||||
case 121: // reset controllers
|
||||
m_out_data_controls = 0;
|
||||
send_cmd(CMD_EFFECTS, 0);
|
||||
update_sustain(0);
|
||||
break;
|
||||
|
||||
case 123: // all notes off
|
||||
case 124: // omni off
|
||||
case 125: // omni on
|
||||
case 126: // mono mode
|
||||
case 127: // poly mode
|
||||
for (unsigned i = 0; i < sizeof(m_midi_notes_on); i++)
|
||||
{
|
||||
if (m_midi_notes_on[i])
|
||||
send_note(i, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xc: // program change
|
||||
send_cmd(CMD_TONE, m_midi_data[0] + m_base_program);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::send_nibble(u8 data)
|
||||
{
|
||||
m_out_data[m_out_data_write++] = data;
|
||||
m_out_data_write %= sizeof(m_out_data);
|
||||
m_out_data_space--;
|
||||
|
||||
if (m_ack && !m_int)
|
||||
m_int_cb(m_int = 1);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::send_cmd(u8 cmd)
|
||||
{
|
||||
if (m_out_data_space >= 3)
|
||||
{
|
||||
send_nibble(cmd >> 4);
|
||||
send_nibble(1); // number of following nibbles
|
||||
send_nibble(cmd & 0xf);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::send_cmd(u8 cmd, u8 data)
|
||||
{
|
||||
if (m_out_data_space >= 5)
|
||||
{
|
||||
send_nibble(cmd >> 4);
|
||||
send_nibble(3); // number of following nibbles
|
||||
send_nibble(cmd & 0xf);
|
||||
send_nibble(data >> 4);
|
||||
send_nibble(data & 0xf);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::send_note(u8 note, u8 on)
|
||||
{
|
||||
if (!on && m_sustain)
|
||||
{
|
||||
m_midi_notes_on[note] = 0x80;
|
||||
return;
|
||||
}
|
||||
|
||||
u8 out_note = ((note / 12) << 4) + (note % 12) + 1;
|
||||
|
||||
if (on && m_midi_notes_on[note])
|
||||
{
|
||||
// force existing note off even if sustained
|
||||
send_cmd(CMD_NOTE, out_note);
|
||||
}
|
||||
|
||||
if (on)
|
||||
out_note |= 0x80;
|
||||
|
||||
send_cmd(CMD_NOTE, out_note);
|
||||
m_midi_notes_on[note] = on;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::update_control(u8 control)
|
||||
{
|
||||
if (m_midi_data[1] >= 0x40)
|
||||
{
|
||||
if (m_out_data_controls & control)
|
||||
return;
|
||||
|
||||
m_out_data_controls |= control;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(m_out_data_controls & control))
|
||||
return;
|
||||
|
||||
m_out_data_controls &= ~control;
|
||||
}
|
||||
|
||||
send_cmd(CMD_EFFECTS, m_out_data_controls);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void ct8000_midi_device::update_sustain(u8 value)
|
||||
{
|
||||
if (value >= 0x40)
|
||||
{
|
||||
m_sustain = 1;
|
||||
}
|
||||
else if (m_sustain)
|
||||
{
|
||||
m_sustain = 0;
|
||||
for (unsigned i = 0; i < sizeof(m_midi_notes_on); i++)
|
||||
{
|
||||
if (BIT(m_midi_notes_on[i], 7))
|
||||
send_note(i, 0);
|
||||
}
|
||||
}
|
||||
}
|
89
src/mame/casio/ct8000_midi.h
Normal file
89
src/mame/casio/ct8000_midi.h
Normal file
@ -0,0 +1,89 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Devin Acker
|
||||
|
||||
#ifndef MAME_CASIO_CT8000_MIDI_H
|
||||
#define MAME_CASIO_CT8000_MIDI_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "diserial.h"
|
||||
|
||||
class ct8000_midi_device : public device_t, public device_serial_interface
|
||||
{
|
||||
public:
|
||||
ct8000_midi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
auto &set_base_program(u8 base) { m_base_program = base; return *this; }
|
||||
|
||||
auto int_cb() { return m_int_cb.bind(); }
|
||||
|
||||
u8 data_r();
|
||||
void data_w(u8 data) { m_in_data = data; }
|
||||
|
||||
int ack_r() { return m_in_strobe; }
|
||||
void ack_w(int state);
|
||||
|
||||
void strobe_w(int state);
|
||||
|
||||
protected:
|
||||
virtual ioport_constructor device_input_ports() const override ATTR_COLD;
|
||||
virtual void device_start() override ATTR_COLD;
|
||||
virtual void device_reset() override ATTR_COLD;
|
||||
|
||||
virtual void rcv_complete() override;
|
||||
|
||||
private:
|
||||
static constexpr unsigned NOTE_MIN = 12; // C0
|
||||
static constexpr unsigned NOTE_MAX = 107; // B7
|
||||
|
||||
enum
|
||||
{
|
||||
CMD_EFFECTS = 0x10,
|
||||
CMD_STOP = 0x24,
|
||||
CMD_NOTE = 0x28,
|
||||
CMD_TONE = 0xe1,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FX_REVERB = 0x01,
|
||||
FX_VIBRATO = 0x02,
|
||||
FX_PEDAL = 0x04, // only affects the local keyboard, so unused here
|
||||
FX_CHORUS = 0x08,
|
||||
FX_SUSTAIN = 0x10
|
||||
};
|
||||
|
||||
void midi_message();
|
||||
|
||||
void send_nibble(u8 data);
|
||||
void send_cmd(u8 cmd);
|
||||
void send_cmd(u8 cmd, u8 data);
|
||||
void send_note(u8 note, u8 on);
|
||||
void update_control(u8 control);
|
||||
void update_sustain(u8 value);
|
||||
|
||||
required_ioport m_channel;
|
||||
devcb_write_line m_int_cb;
|
||||
|
||||
u8 m_base_program;
|
||||
|
||||
u8 m_status;
|
||||
u8 m_midi_data[2];
|
||||
u8 m_midi_data_pos, m_midi_data_size;
|
||||
u8 m_midi_notes_on[NOTE_MAX - NOTE_MIN + 1];
|
||||
u8 m_sustain;
|
||||
|
||||
u8 m_ack;
|
||||
u8 m_int;
|
||||
u8 m_out_data[0x1000];
|
||||
u16 m_out_data_read, m_out_data_write;
|
||||
u16 m_out_data_space;
|
||||
u8 m_out_data_controls;
|
||||
|
||||
u8 m_in_data;
|
||||
u8 m_in_strobe;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(CT8000_MIDI, ct8000_midi_device)
|
||||
|
||||
#endif // MAME_CASIO_CT8000_MIDI_H
|
423
src/mame/layout/ct8000.lay
Normal file
423
src/mame/layout/ct8000.lay
Normal file
@ -0,0 +1,423 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
license:CC0-1.0
|
||||
-->
|
||||
|
||||
<mamelayout version="2">
|
||||
<element name="bg"><rect><color red="0.75" green="0.75" blue="0.775" /></rect></element>
|
||||
<element name="line"><rect><color red="0.55" green="0.55" blue="0.575" /></rect></element>
|
||||
<element name="line_white"><rect><color red="1" green="1" blue="0.95" /></rect></element>
|
||||
<element name="line_black"><rect><color red="0" green="0" blue="0" /></rect></element>
|
||||
|
||||
<element name="button_back">
|
||||
<rect><bounds x="0" y="0" width="1" height="20" /><color red="0.55" green="0.55" blue="0.575" /></rect>
|
||||
<rect><bounds x="0" y="1" width="1" height="18" /><color red="0.65" green="0.65" blue="0.675" /></rect>
|
||||
</element>
|
||||
<element name="panel_back"><rect><color red="0.7" green="0.7" blue="0.725" /></rect></element>
|
||||
|
||||
<!-- text elements -->
|
||||
<element name="cancel"><text string="CANCEL"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="sustain"><text string="SUSTAIN"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="reverb"><text string="REVERB"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="vibrato"><text string="VIBRATO"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="stereo"><text string="STEREO"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="chorus"><text string="CHORUS"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="effect"><text string="EFFECT"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone_memory"><text string="TONE MEMORY"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="num1"><text string="1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="num2"><text string="2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="num3"><text string="3"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="num4"><text string="4"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="mode"><text string="MODE"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="set"><text string="SET"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="play"><text string="PLAY"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tune"><text string="TUNE"><color red="0" blue="0" green="0" /></text></element>
|
||||
|
||||
<element name="tone1"><text string="PIANO 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone2"><text string="PIPE ORGAN 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone3"><text string="PIANO 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone4"><text string="PIPE ORGAN 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone5"><text string="PIANO 3"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone6"><text string="PIANO 4"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone7"><text string="PIPE ORGAN 3"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone8"><text string="HONKY TONK"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone8b"><text string="PIANO"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone9"><text string="PIPE ORGAN 4"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone10"><text string="ZIMBALON"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone11"><text string="PIPE ORGAN 5"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone12"><text string="SYNTH"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone12b"><text string="SOUND"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone13"><text string="HARPSI-"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone13b"><text string="CHORD 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone14"><text string="ACCORDION"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone15"><text string="HARPSI-"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone15b"><text string="CHORD 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone16"><text string="BAGPIPE"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone17"><text string="CELESTA 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone18"><text string="CELESTA 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone19"><text string="OBOE"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone20"><text string="MARIMBA"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone21"><text string="CLARINET"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone22"><text string="HARP 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone23"><text string="FLUTE"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone24"><text string="HARP 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone25"><text string="HARP 3"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone26"><text string="SHAKUHACHI"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone27"><text string="KOTO 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone28"><text string="WA-WA"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone29"><text string="KOTO 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone30"><text string="TAISHO"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone30b"><text string="KOTO"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone31"><text string="HORN"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone32"><text string="BANJO"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone33"><text string="FLUEGELHORN"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone34"><text string="MANDOLIN"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone35"><text string="TRUMPET"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone36"><text string="GUITAR 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone37"><text string="GUITAR 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone38"><text string="BRASS ENSEMBLE"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone39"><text string="GUITAR 3"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone40"><text string="STRING ENSEMBLE"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone41"><text string="ELEC."><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone41b"><text string="GUITAR 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone42"><text string="ELEC."><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone42b"><text string="GUITAR 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone43"><text string="VIOLIN"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone44"><text string="ELEC."><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone44b"><text string="GUITAR 3"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone45"><text string="CELLO"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone46"><text string="ELEC."><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone46b"><text string="GUITAR 4"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone47"><text string="DOUBLE BASS"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone48"><text string="ELEC."><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone48b"><text string="GUITAR 5"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone49"><text string="ELEC. BASS"><color red="0" blue="0" green="0" /></text></element>
|
||||
|
||||
<!-- button primitives -->
|
||||
<element name="button_light" defstate="0">
|
||||
<rect><color red="0.1" green="0.1" blue="0.1" /><bounds x="0" y="0" width="5" height="10" /></rect>
|
||||
<rect state="0"><color red="0.8" green="0.8" blue="0.8" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
<rect state="1"><color red="0.5" green="0.5" blue="0.5" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
</element>
|
||||
|
||||
<element name="button_dark" defstate="0">
|
||||
<rect><color red="0.1" green="0.1" blue="0.1" /><bounds x="0" y="0" width="5" height="10" /></rect>
|
||||
<rect state="0"><color red="0.3" green="0.3" blue="0.3" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
<rect state="1"><color red="0.15" green="0.15" blue="0.15" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
</element>
|
||||
|
||||
<element name="button_down" defstate="0">
|
||||
<rect><color red="0.1" green="0.1" blue="0.1" /><bounds x="0" y="0" width="5" height="10" /></rect>
|
||||
<rect state="0"><color red="0.3" green="0.3" blue="0.3" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
<rect state="1"><color red="0.15" green="0.15" blue="0.15" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
<image>
|
||||
<bounds xc="2.5" yc="5" width="3" height="6" />
|
||||
<data><![CDATA[
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" version="1.1">
|
||||
<polygon points="2,2 5,8 8,2" fill="white" stroke="white" stroke-width="0.4" />
|
||||
</svg>
|
||||
]]></data>
|
||||
</image>
|
||||
</element>
|
||||
|
||||
<element name="button_up" defstate="0">
|
||||
<rect><color red="0.1" green="0.1" blue="0.1" /><bounds x="0" y="0" width="5" height="10" /></rect>
|
||||
<rect state="0"><color red="0.3" green="0.3" blue="0.3" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
<rect state="1"><color red="0.15" green="0.15" blue="0.15" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
<image>
|
||||
<bounds xc="2.5" yc="5" width="3" height="6" />
|
||||
<data><![CDATA[
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" version="1.1">
|
||||
<polygon points="2,8 5,2 8,8" fill="white" stroke="white" stroke-width="0.4" />
|
||||
</svg>
|
||||
]]></data>
|
||||
</image>
|
||||
</element>
|
||||
|
||||
<element name="button_set" defstate="0">
|
||||
<rect><color red="0.1" green="0.1" blue="0.1" /><bounds x="0" y="0" width="10" height="10" /></rect>
|
||||
<rect state="0"><color red="1.0" green="0.45" blue="0.0" /><bounds xc="5" yc="5" width="9" height="9" /></rect>
|
||||
<rect state="1"><color red="0.8" green="0.25" blue="0" /><bounds xc="5" yc="5" width="9" height="9" /></rect>
|
||||
</element>
|
||||
|
||||
<element name="button_icon_up">
|
||||
<rect><color red="0.7" green="0.7" blue="0.725" /><bounds x="0" y="0" width="5" height="5" /></rect>
|
||||
|
||||
<rect><color red="0" green="0" blue="0" /><bounds xc="2.5" y="4" width="5" height="1" /></rect>
|
||||
<rect><color red="0" green="0" blue="0" /><bounds xc="2.5" y="1" width="3.5" height="4" /></rect>
|
||||
</element>
|
||||
|
||||
<element name="button_icon_down">
|
||||
<rect><color red="0.7" green="0.7" blue="0.725" /><bounds x="0" y="0" width="5" height="5" /></rect>
|
||||
|
||||
<rect><color red="0" green="0" blue="0" /><bounds xc="2.5" y="4" width="5" height="1" /></rect>
|
||||
<rect><color red="0" green="0" blue="0" /><bounds xc="2.5" y="3" width="3.5" height="2" /></rect>
|
||||
</element>
|
||||
|
||||
<!-- keyboard primitives -->
|
||||
<element name="keyfill"><rect><color red="0.2" green="0.2" blue="0.2" /></rect></element>
|
||||
<element name="whitekey" defstate="0">
|
||||
<rect state="0"><bounds x="0" y="0" width="45" height="504" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="1"><bounds x="0" y="0" width="45" height="504" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
</element>
|
||||
<element name="whitekey-l" defstate="0">
|
||||
<rect state="0"><bounds x="0" y="0" width="45" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="1"><bounds x="0" y="0" width="45" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
</element>
|
||||
<element name="whitekey-m" defstate="0">
|
||||
<rect state="0"><bounds x="13" y="0" width="53" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="1"><bounds x="13" y="0" width="53" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
</element>
|
||||
<element name="whitekey-lm" defstate="0">
|
||||
<rect state="0"><bounds x="10" y="0" width="44" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="1"><bounds x="10" y="0" width="44" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
</element>
|
||||
<element name="whitekey-rm" defstate="0">
|
||||
<rect state="0"><bounds x="22" y="0" width="44" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="1"><bounds x="22" y="0" width="44" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
</element>
|
||||
<element name="whitekey-r" defstate="0">
|
||||
<rect state="0"><bounds x="34" y="0" width="45" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
|
||||
<rect state="1"><bounds x="34" y="0" width="45" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
|
||||
</element>
|
||||
<element name="blackkey" defstate="0">
|
||||
<rect state="0"><bounds x="0" y="0" width="44" height="324" /><color red="0.0" green="0.0" blue="0.0" /></rect>
|
||||
<rect state="0"><bounds x="4" y="0" width="36" height="320" /><color red="0.1" green="0.1" blue="0.1" /></rect>
|
||||
<rect state="1"><bounds x="0" y="0" width="44" height="324" /><color red="0.1" green="0.1" blue="0.1" /></rect>
|
||||
<rect state="1"><bounds x="4" y="0" width="36" height="320" /><color red="0.1" green="0.1" blue="0.1" /></rect>
|
||||
</element>
|
||||
|
||||
<!-- left button group -->
|
||||
<group name="left">
|
||||
<bounds x="0" y="0" width="80" height="120" />
|
||||
<element ref="panel_back"><bounds x="0" y="0" width="80" height="120" /></element>
|
||||
|
||||
<element ref="line_black"><bounds xc="26" y="25" width="28" height="4" /></element>
|
||||
<element ref="panel_back"><bounds xc="19.25" y="26" width="12.5" height="4" /></element>
|
||||
<element ref="panel_back"><bounds xc="32.75" y="26" width="12.5" height="4" /></element>
|
||||
|
||||
<element ref="button_back"><bounds x="0" y="35" width="80" height="20" /></element>
|
||||
<element ref="cancel"><bounds xc="12" y="30" width="15" height="4" /></element>
|
||||
<element ref="button_dark" inputtag="SWITCH" inputmask="0x01"><bounds xc="12" yc="45" width="9" height="18" /></element>
|
||||
<element ref="sustain"><bounds xc="26" y="30" width="15" height="4" /></element>
|
||||
<element ref="button_back" inputtag="SWITCH" inputmask="0x02"><bounds xc="26" yc="45" width="9" height="18" /></element>
|
||||
<element ref="button_dark" inputtag="KCA" inputmask="0x01"><bounds xc="26" yc="45" width="9" height="18" /></element>
|
||||
<element ref="reverb"><bounds xc="40" y="30" width="15" height="4" /></element>
|
||||
<element ref="button_back" inputtag="SWITCH" inputmask="0x04"><bounds xc="40" yc="45" width="9" height="18" /></element>
|
||||
<element ref="button_dark" inputtag="KCA" inputmask="0x04"><bounds xc="40" yc="45" width="9" height="18" /></element>
|
||||
<element ref="vibrato"><bounds xc="54" y="30" width="15" height="4" /></element>
|
||||
<element ref="button_dark" inputtag="KCC" inputmask="0x10"><bounds xc="54" yc="45" width="9" height="18" /></element>
|
||||
<element ref="stereo"><bounds xc="68" y="26" width="15" height="4" /></element>
|
||||
<element ref="chorus"><bounds xc="68" y="30" width="15" height="4" /></element>
|
||||
<element ref="button_dark" inputtag="KC9" inputmask="0x08"><bounds xc="68" yc="45" width="9" height="18" /></element>
|
||||
<element ref="effect"><bounds xc="40" y="55" width="80" height="4" /></element>
|
||||
|
||||
<element ref="tone_memory"><bounds xc="40" y="62" width="80" height="4" /></element>
|
||||
<element ref="button_back"><bounds x="0" y="70" width="80" height="20" /></element>
|
||||
<element ref="num1"><bounds xc="19" y="66" width="15" height="4" /></element>
|
||||
<element ref="button_light" inputtag="KCB" inputmask="0x01"><bounds xc="19" yc="80" width="9" height="16" /></element>
|
||||
<element ref="num2"><bounds xc="33" y="66" width="15" height="4" /></element>
|
||||
<element ref="button_light" inputtag="KCB" inputmask="0x02"><bounds xc="33" yc="80" width="9" height="16" /></element>
|
||||
<element ref="num3"><bounds xc="47" y="66" width="15" height="4" /></element>
|
||||
<element ref="button_light" inputtag="KCB" inputmask="0x04"><bounds xc="47" yc="80" width="9" height="16" /></element>
|
||||
<element ref="num4"><bounds xc="61" y="66" width="15" height="4" /></element>
|
||||
<element ref="button_light" inputtag="KCB" inputmask="0x08"><bounds xc="61" yc="80" width="9" height="16" /></element>
|
||||
|
||||
<element ref="mode"><bounds xc="61" y="92" width="15" height="4" /></element>
|
||||
<element ref="button_set" inputtag="KCB" inputmask="0x10"><bounds xc="61" yc="106" width="16" height="16" /></element>
|
||||
<!-- these are supposed to be to the right of the button but here they are on the left for better readability -->
|
||||
<element ref="button_icon_down"><bounds xc="38" yc="102" width="3" height="3" /></element>
|
||||
<element ref="set"><bounds xc="46" yc="102" width="15" height="4" /></element>
|
||||
<element ref="button_icon_up"><bounds xc="38" yc="110" width="3" height="3" /></element>
|
||||
<element ref="play"><bounds xc="46" yc="110" width="15" height="4" /></element>
|
||||
</group>
|
||||
|
||||
<!-- right button group -->
|
||||
<group name="right">
|
||||
<element ref="panel_back"><bounds x="0" y="0" width="40" height="120" /></element>
|
||||
<element ref="tune"><bounds xc="20" y="15" width="40" height="4" /></element>
|
||||
<element ref="button_back"><bounds x="0" y="20" width="40" height="20" /></element>
|
||||
<element ref="button_down" inputtag="KC9" inputmask="0x04"><bounds xc="13" yc="30" width="9" height="18" /></element>
|
||||
<element ref="button_up" inputtag="KC9" inputmask="0x02"><bounds xc="27" yc="30" width="9" height="18" /></element>
|
||||
</group>
|
||||
|
||||
<!-- keyboard group -->
|
||||
<group name="keyboard">
|
||||
<element ref="keyfill"><bounds x="72" y="0" width="2396" height="524" /></element>
|
||||
|
||||
<!-- octave 1 -->
|
||||
<element ref="blackkey" inputtag="KC0" inputmask="0x02"><bounds x="130" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC0" inputmask="0x08"><bounds x="233" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC1" inputmask="0x01"><bounds x="373" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC1" inputmask="0x04"><bounds x="467" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC1" inputmask="0x10"><bounds x="561" y="10" width="44" height="324" /></element>
|
||||
<element ref="whitekey-l" inputtag="KC0" inputmask="0x01"><bounds x="82" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-m" inputtag="KC0" inputmask="0x04"><bounds x="164" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-r" inputtag="KC0" inputmask="0x10"><bounds x="246" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-l" inputtag="KC0" inputmask="0x20"><bounds x="328" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-lm" inputtag="KC1" inputmask="0x02"><bounds x="410" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-rm" inputtag="KC1" inputmask="0x08"><bounds x="492" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-r" inputtag="KC1" inputmask="0x20"><bounds x="574" y="10" width="79" height="504" /></element>
|
||||
|
||||
<!-- octave 2 -->
|
||||
<element ref="blackkey" inputtag="KC2" inputmask="0x02"><bounds x="704" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC2" inputmask="0x08"><bounds x="807" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC3" inputmask="0x01"><bounds x="947" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC3" inputmask="0x04"><bounds x="1041" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC3" inputmask="0x10"><bounds x="1135" y="10" width="44" height="324" /></element>
|
||||
<element ref="whitekey-l" inputtag="KC2" inputmask="0x01"><bounds x="656" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-m" inputtag="KC2" inputmask="0x04"><bounds x="738" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-r" inputtag="KC2" inputmask="0x10"><bounds x="820" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-l" inputtag="KC2" inputmask="0x20"><bounds x="902" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-lm" inputtag="KC3" inputmask="0x02"><bounds x="984" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-rm" inputtag="KC3" inputmask="0x08"><bounds x="1066" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-r" inputtag="KC3" inputmask="0x20"><bounds x="1148" y="10" width="79" height="504" /></element>
|
||||
|
||||
<!-- octave 3 -->
|
||||
<element ref="blackkey" inputtag="KC4" inputmask="0x02"><bounds x="1278" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC4" inputmask="0x08"><bounds x="1381" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC5" inputmask="0x01"><bounds x="1521" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC5" inputmask="0x04"><bounds x="1615" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC5" inputmask="0x10"><bounds x="1709" y="10" width="44" height="324" /></element>
|
||||
<element ref="whitekey-l" inputtag="KC4" inputmask="0x01"><bounds x="1230" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-m" inputtag="KC4" inputmask="0x04"><bounds x="1312" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-r" inputtag="KC4" inputmask="0x10"><bounds x="1394" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-l" inputtag="KC4" inputmask="0x20"><bounds x="1476" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-lm" inputtag="KC5" inputmask="0x02"><bounds x="1558" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-rm" inputtag="KC5" inputmask="0x08"><bounds x="1640" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-r" inputtag="KC5" inputmask="0x20"><bounds x="1722" y="10" width="79" height="504" /></element>
|
||||
|
||||
<!-- octave 4 -->
|
||||
<element ref="blackkey" inputtag="KC6" inputmask="0x02"><bounds x="1852" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC6" inputmask="0x08"><bounds x="1955" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC7" inputmask="0x01"><bounds x="2095" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC7" inputmask="0x04"><bounds x="2189" y="10" width="44" height="324" /></element>
|
||||
<element ref="blackkey" inputtag="KC7" inputmask="0x10"><bounds x="2283" y="10" width="44" height="324" /></element>
|
||||
<element ref="whitekey-l" inputtag="KC6" inputmask="0x01"><bounds x="1804" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-m" inputtag="KC6" inputmask="0x04"><bounds x="1886" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-r" inputtag="KC6" inputmask="0x10"><bounds x="1968" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-l" inputtag="KC6" inputmask="0x20"><bounds x="2050" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-lm" inputtag="KC7" inputmask="0x02"><bounds x="2132" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-rm" inputtag="KC7" inputmask="0x08"><bounds x="2214" y="10" width="79" height="504" /></element>
|
||||
<element ref="whitekey-r" inputtag="KC7" inputmask="0x20"><bounds x="2296" y="10" width="79" height="504" /></element>
|
||||
|
||||
<!-- final key -->
|
||||
<element ref="whitekey" inputtag="KC8" inputmask="0x01"><bounds x="2378" y="10" width="79" height="504" /></element>
|
||||
</group>
|
||||
|
||||
<group name="key_labels">
|
||||
<bounds x="0" y="0" width="580" height="20" />
|
||||
|
||||
<element ref="tone2"><bounds xc="18" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="18" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone4"><bounds xc="43" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="43" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone7"><bounds xc="77" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="77" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone9"><bounds xc="100" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="100" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone11"><bounds xc="123" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="123" y="7" width="0.75" height="13" /></element>
|
||||
|
||||
<element ref="tone1"><bounds x="-1" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone3"><bounds x="20" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone5"><bounds x="41" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone6"><bounds x="59" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone8"><bounds x="79" y="11" width="20" height="4" /></element>
|
||||
<element ref="tone8b"><bounds x="79" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone10"><bounds x="101" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone12"><bounds x="121" y="11" width="20" height="4" /></element>
|
||||
<element ref="tone12b"><bounds x="121" y="15" width="20" height="4" /></element>
|
||||
|
||||
<element ref="tone14"><bounds xc="158" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="158" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone16"><bounds xc="183" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="183" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone19"><bounds xc="217" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="217" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone21"><bounds xc="240" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="240" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone23"><bounds xc="263" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="263" y="7" width="0.75" height="13" /></element>
|
||||
|
||||
<element ref="tone13"><bounds x="140" y="11" width="20" height="4" /></element>
|
||||
<element ref="tone13b"><bounds x="140" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone15"><bounds x="160" y="11" width="20" height="4" /></element>
|
||||
<element ref="tone15b"><bounds x="160" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone17"><bounds x="182" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone18"><bounds x="199" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone20"><bounds x="220" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone22"><bounds x="240" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone24"><bounds x="261" y="15" width="20" height="4" /></element>
|
||||
|
||||
<element ref="tone26"><bounds xc="298" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="298" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone28"><bounds xc="323" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="323" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone31"><bounds xc="357" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="357" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone33"><bounds xc="380" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="380" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone35"><bounds xc="403" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="403" y="7" width="0.75" height="13" /></element>
|
||||
|
||||
<element ref="tone25"><bounds x="280" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone27"><bounds x="300" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone29"><bounds x="321" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone30"><bounds x="339" y="11" width="20" height="4" /></element>
|
||||
<element ref="tone30b"><bounds x="339" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone32"><bounds x="360" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone34"><bounds x="380" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone36"><bounds x="401" y="15" width="20" height="4" /></element>
|
||||
|
||||
<element ref="tone38"><bounds xc="432" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="438" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone40"><bounds xc="466" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="463" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone43"><bounds xc="497" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="497" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone45"><bounds xc="520" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="520" y="7" width="0.75" height="13" /></element>
|
||||
<element ref="tone47"><bounds xc="543" y="2" width="30" height="4" /></element>
|
||||
<element ref="line_white"><bounds xc="543" y="7" width="0.75" height="13" /></element>
|
||||
|
||||
<element ref="tone37"><bounds x="419" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone39"><bounds x="440" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone41"><bounds x="461" y="11" width="20" height="4" /></element>
|
||||
<element ref="tone41b"><bounds x="461" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone42"><bounds x="479" y="11" width="20" height="4" /></element>
|
||||
<element ref="tone42b"><bounds x="479" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone44"><bounds x="500" y="11" width="20" height="4" /></element>
|
||||
<element ref="tone44b"><bounds x="500" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone46"><bounds x="520" y="11" width="20" height="4" /></element>
|
||||
<element ref="tone46b"><bounds x="520" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone48"><bounds x="541" y="11" width="20" height="4" /></element>
|
||||
<element ref="tone48b"><bounds x="541" y="15" width="20" height="4" /></element>
|
||||
<element ref="tone49"><bounds x="560" y="15" width="20" height="4" /></element>
|
||||
|
||||
</group>
|
||||
|
||||
<view name="Keyboard">
|
||||
<element ref="bg"><bounds x="0" y="0" width="704" height="170" /></element>
|
||||
|
||||
<element ref="line"><bounds x="80" y="0" width="1" height="50" /></element>
|
||||
<element ref="line"><bounds x="663" y="0" width="1" height="50" /></element>
|
||||
<group ref="left"><bounds x="0" y="50" width="80" height="120" /></group>
|
||||
<group ref="right"><bounds x="664" y="50" width="40" height="120" /></group>
|
||||
<element ref="line"><bounds x="0" y="50" width="704" height="1" /></element>
|
||||
<group ref="key_labels"><bounds x="82" y="30" width="580" height="20" /></group>
|
||||
<group ref="keyboard"><bounds x="80" y="50" width="584" height="120" /></group>
|
||||
</view>
|
||||
</mamelayout>
|
241
src/mame/layout/ctfk1.lay
Normal file
241
src/mame/layout/ctfk1.lay
Normal file
@ -0,0 +1,241 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
license:CC0-1.0
|
||||
-->
|
||||
|
||||
<mamelayout version="2">
|
||||
<element name="bg"><rect><color red="0.75" green="0.75" blue="0.775" /></rect></element>
|
||||
<element name="brown"><rect><color red="0.365" green="0.263" blue="0.17" /></rect></element>
|
||||
<element name="line"><rect><color red="0.55" green="0.55" blue="0.575" /></rect></element>
|
||||
<element name="line_white"><rect><color red="1" green="1" blue="0.95" /></rect></element>
|
||||
|
||||
<element name="button_back">
|
||||
<rect><bounds x="0" y="0" width="1" height="20" /><color red="0.25" green="0.25" blue="0.275" /></rect>
|
||||
<rect><bounds x="0" y="1" width="1" height="18" /><color red="0.3" green="0.3" blue="0.325" /></rect>
|
||||
</element>
|
||||
<element name="panel_back"><rect><color red="0.7" green="0.7" blue="0.725" /></rect></element>
|
||||
|
||||
<element name="top_back">
|
||||
<disk><bounds x="0" y="0" width="10" height="10" /><color red="0.1" green="0.1" blue="0.1" /></disk>
|
||||
<disk><bounds x="270" y="0" width="10" height="10" /><color red="0.1" green="0.1" blue="0.1" /></disk>
|
||||
<disk><bounds x="0" y="35" width="10" height="10" /><color red="0.1" green="0.1" blue="0.1" /></disk>
|
||||
<disk><bounds x="270" y="35" width="10" height="10" /><color red="0.1" green="0.1" blue="0.1" /></disk>
|
||||
<rect><bounds x="5" y="0" width="270" height="45" /><color red="0.1" green="0.1" blue="0.1" /></rect>
|
||||
<rect><bounds x="0" y="5" width="280" height="35" /><color red="0.1" green="0.1" blue="0.1" /></rect>
|
||||
</element>
|
||||
|
||||
<!-- text elements -->
|
||||
<element name="select"><text string="BASS SELECT"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="foot"><text string="FOOT" align="1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="auto"><text string="AUTO" align="1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="mode"><text string="MODE"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="set"><text string="SET" align="1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="play"><text string="PLAY" align="1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="sustain"><text string="SUSTAIN"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="on"><text string="ON" align="1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="off"><text string="OFF" align="1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tune"><text string="TUNE" /></element>
|
||||
|
||||
<element name="tone1"><text string="ORGAN 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone2"><text string="ORGAN 4"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone3"><text string="ORGAN 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone4"><text string="TUBA 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone5"><text string="ORGAN 3"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone6"><text string="TUBA 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone7"><text string="BASSOON 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone8"><text string="BASSOON 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone9"><text string="WOOD BASS"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone9b"><text string="(ARCO 2)"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone10"><text string="WOOD BASS"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone10b"><text string="(ARCO 1)"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone11"><text string="WOOD BASS"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone11b"><text string="(PIZZ 2)"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone12"><text string="WOOD BASS"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone12b"><text string="(PIZZ 1)"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone13"><text string="ELEC. BASS 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone14"><text string="ELEC. BASS 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone15"><text string="HARPSICHORD 1"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone16"><text string="HARPSICHORD 2"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone17"><text string="PIANO"><color red="0" blue="0" green="0" /></text></element>
|
||||
<element name="tone18"><text string="SYNTH CHIME"><color red="0" blue="0" green="0" /></text></element>
|
||||
|
||||
<!-- button primitives -->
|
||||
<element name="button_down" defstate="0">
|
||||
<rect><color red="0.1" green="0.1" blue="0.1" /><bounds x="0" y="0" width="5" height="10" /></rect>
|
||||
<rect state="0"><color red="0.8" green="0.8" blue="0.8" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
<rect state="1"><color red="0.5" green="0.5" blue="0.5" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
<image>
|
||||
<bounds xc="2.5" yc="5" width="2" height="5" />
|
||||
<data><![CDATA[
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" version="1.1">
|
||||
<polygon points="2,2 5,8 8,2" fill="white" stroke="white" stroke-width="0.4" />
|
||||
</svg>
|
||||
]]></data>
|
||||
</image>
|
||||
</element>
|
||||
|
||||
<element name="button_up" defstate="0">
|
||||
<rect><color red="0.1" green="0.1" blue="0.1" /><bounds x="0" y="0" width="5" height="10" /></rect>
|
||||
<rect state="0"><color red="0.8" green="0.8" blue="0.8" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
<rect state="1"><color red="0.5" green="0.5" blue="0.5" /><bounds xc="2.5" yc="5" width="4" height="9" /></rect>
|
||||
<image>
|
||||
<bounds xc="2.5" yc="5" width="2" height="5" />
|
||||
<data><![CDATA[
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" version="1.1">
|
||||
<polygon points="2,8 5,2 8,8" fill="white" stroke="white" stroke-width="0.4" />
|
||||
</svg>
|
||||
]]></data>
|
||||
</image>
|
||||
</element>
|
||||
|
||||
<element name="button" defstate="0">
|
||||
<disk><color red="0.1" green="0.1" blue="0.1" /><bounds x="0" y="0" width="20" height="20" /></disk>
|
||||
<rect><color red="0.1" green="0.1" blue="0.1" /><bounds x="0" y="10" width="20" height="42" /></rect>
|
||||
<disk state="0"><color red="0.3" green="0.3" blue="0.3" /><bounds xc="10" y="1" width="18" height="18" /></disk>
|
||||
<rect state="0"><color red="0.3" green="0.3" blue="0.3" /><bounds xc="10" y="10" width="18" height="40" /></rect>
|
||||
<disk state="1"><color red="0.15" green="0.15" blue="0.15" /><bounds xc="10" y="1" width="18" height="18" /></disk>
|
||||
<rect state="1"><color red="0.15" green="0.15" blue="0.15" /><bounds xc="10" y="10" width="18" height="40" /></rect>
|
||||
</element>
|
||||
|
||||
<element name="button_icon_up">
|
||||
<rect><color red="0.75" green="0.75" blue="0.775" /><bounds x="0" y="0" width="5" height="5" /></rect>
|
||||
|
||||
<rect><color red="0" green="0" blue="0" /><bounds xc="2.5" y="4" width="5" height="1" /></rect>
|
||||
<rect><color red="0" green="0" blue="0" /><bounds xc="2.5" y="1" width="3.5" height="4" /></rect>
|
||||
</element>
|
||||
|
||||
<element name="button_icon_down">
|
||||
<rect><color red="0.75" green="0.75" blue="0.775" /><bounds x="0" y="0" width="5" height="5" /></rect>
|
||||
|
||||
<rect><color red="0" green="0" blue="0" /><bounds xc="2.5" y="4" width="5" height="1" /></rect>
|
||||
<rect><color red="0" green="0" blue="0" /><bounds xc="2.5" y="3" width="3.5" height="2" /></rect>
|
||||
</element>
|
||||
|
||||
<!-- keyboard primitives -->
|
||||
<element name="keyfill"><rect><color red="0.08" green="0.08" blue="0.08" /></rect></element>
|
||||
<element name="whitekey" defstate="0">
|
||||
<rect><bounds xc="0" y="0" width="5" height="47.5" /><color red="0" green="0" blue="0" /></rect>
|
||||
<disk><bounds xc="0" yc="47.5" width="5" height="5" /><color red="0" green="0" blue="0" /></disk>
|
||||
<rect state="0"><bounds xc="0" y="0" width="4.25" height="47.5" /><color red="1" green="1" blue="1" /></rect>
|
||||
<disk state="0"><bounds xc="0" yc="47.5" width="4.25" height="4.25" /><color red="1" green="1" blue="1" /></disk>
|
||||
<rect state="1"><bounds xc="0" y="0" width="4.25" height="47.5" /><color red="0.8" green="0.8" blue="0.8" /></rect>
|
||||
<disk state="1"><bounds xc="0" yc="47.5" width="4.25" height="4.25" /><color red="0.8" green="0.8" blue="0.8" /></disk>
|
||||
</element>
|
||||
<element name="blackkey" defstate="0">
|
||||
<rect><bounds xc="0" y="0" width="5" height="25" /><color red="0" green="0" blue="0" /></rect>
|
||||
<disk><bounds xc="0" yc="25" width="5" height="5" /><color red="0" green="0" blue="0" /></disk>
|
||||
<rect state="0"><bounds xc="0" y="0" width="4.25" height="25" /><color red="0.25" green="0.25" blue="0.25" /></rect>
|
||||
<disk state="0"><bounds xc="0" yc="25" width="4.25" height="4.25" /><color red="0.25" green="0.25" blue="0.25" /></disk>
|
||||
<rect state="1"><bounds xc="0" y="0" width="4.25" height="25" /><color red="0.2" green="0.2" blue="0.2" /></rect>
|
||||
<disk state="1"><bounds xc="0" yc="25" width="4.25" height="4.25" /><color red="0.2" green="0.2" blue="0.2" /></disk>
|
||||
</element>
|
||||
|
||||
<!-- button group -->
|
||||
<group name="buttons">
|
||||
<element ref="bg"><bounds x="0" y="0" width="660" height="180" /></element>
|
||||
<element ref="top_back"><bounds x="25" y="25" width="280" height="45" /></element>
|
||||
<element ref="tune"><bounds xc="270" y="30" width="40" height="9" /></element>
|
||||
<element ref="button_down" inputtag="KC9" inputmask="0x04"><bounds xc="260" y="42" width="10" height="20" /></element>
|
||||
<element ref="button_up" inputtag="KC9" inputmask="0x02"><bounds xc="280" y="42" width="10" height="20" /></element>
|
||||
|
||||
<element ref="select"><bounds xc="90" y="75" width="60" height="11" /></element>
|
||||
<element ref="button_icon_down"><bounds x="73" y="87" width="9" height="9" /></element>
|
||||
<element ref="foot"><bounds x="85" y="87" width="60" height="11" /></element>
|
||||
<element ref="button_icon_up"><bounds x="73" y="99" width="9" height="9" /></element>
|
||||
<element ref="auto"><bounds x="85" y="99" width="60" height="11" /></element>
|
||||
<element ref="button" inputtag="KC9" inputmask="0x10"><bounds xc="90" y="115" width="20" height="52" /></element>
|
||||
|
||||
<element ref="mode"><bounds xc="180" y="75" width="60" height="11" /></element>
|
||||
<element ref="button_icon_down"><bounds x="163" y="87" width="9" height="9" /></element>
|
||||
<element ref="set"><bounds x="175" y="87" width="60" height="11" /></element>
|
||||
<element ref="button_icon_up"><bounds x="163" y="99" width="9" height="9" /></element>
|
||||
<element ref="play"><bounds x="175" y="99" width="60" height="11" /></element>
|
||||
<element ref="button" inputtag="KCB" inputmask="0x10"><bounds xc="180" y="115" width="20" height="52" /></element>
|
||||
|
||||
<element ref="sustain"><bounds xc="270" y="75" width="60" height="11" /></element>
|
||||
<element ref="button_icon_down"><bounds x="253" y="87" width="9" height="9" /></element>
|
||||
<element ref="on"><bounds x="265" y="87" width="60" height="11" /></element>
|
||||
<element ref="button_icon_up"><bounds x="253" y="99" width="9" height="9" /></element>
|
||||
<element ref="off"><bounds x="265" y="99" width="60" height="11" /></element>
|
||||
<element ref="button" inputtag="KCA" inputmask="0x01"><bounds xc="270" y="115" width="20" height="52" /></element>
|
||||
</group>
|
||||
|
||||
<!-- keyboard group -->
|
||||
<group name="keyboard">
|
||||
<element ref="keyfill"><bounds x="0" y="0" width="660" height="300" /></element>
|
||||
|
||||
<element ref="button_back"><bounds x="0" y="100" width="660" height="30" /></element>
|
||||
<element ref="button_back"><bounds x="0" y="200" width="660" height="30" /></element>
|
||||
|
||||
<element ref="whitekey" inputtag="KC0" inputmask="0x01"><bounds xc="30" y="0" width="25" height="245" /></element>
|
||||
<element ref="blackkey" inputtag="KC0" inputmask="0x02"><bounds xc="60" y="0" width="25" height="125" /></element>
|
||||
<element ref="whitekey" inputtag="KC0" inputmask="0x04"><bounds xc="90" y="0" width="25" height="245" /></element>
|
||||
<element ref="blackkey" inputtag="KC0" inputmask="0x08"><bounds xc="120" y="0" width="25" height="125" /></element>
|
||||
<element ref="whitekey" inputtag="KC0" inputmask="0x10"><bounds xc="150" y="0" width="25" height="245" /></element>
|
||||
|
||||
<element ref="whitekey" inputtag="KC0" inputmask="0x20"><bounds xc="210" y="0" width="25" height="245" /></element>
|
||||
<element ref="blackkey" inputtag="KC1" inputmask="0x01"><bounds xc="240" y="0" width="25" height="125" /></element>
|
||||
<element ref="whitekey" inputtag="KC1" inputmask="0x02"><bounds xc="270" y="0" width="25" height="245" /></element>
|
||||
<element ref="blackkey" inputtag="KC1" inputmask="0x04"><bounds xc="300" y="0" width="25" height="125" /></element>
|
||||
<element ref="whitekey" inputtag="KC1" inputmask="0x08"><bounds xc="330" y="0" width="25" height="245" /></element>
|
||||
<element ref="blackkey" inputtag="KC1" inputmask="0x10"><bounds xc="360" y="0" width="25" height="125" /></element>
|
||||
<element ref="whitekey" inputtag="KC1" inputmask="0x20"><bounds xc="390" y="0" width="25" height="245" /></element>
|
||||
|
||||
<element ref="whitekey" inputtag="KC2" inputmask="0x01"><bounds xc="450" y="0" width="25" height="245" /></element>
|
||||
<element ref="blackkey" inputtag="KC2" inputmask="0x02"><bounds xc="480" y="0" width="25" height="125" /></element>
|
||||
<element ref="whitekey" inputtag="KC2" inputmask="0x04"><bounds xc="510" y="0" width="25" height="245" /></element>
|
||||
<element ref="blackkey" inputtag="KC2" inputmask="0x08"><bounds xc="540" y="0" width="25" height="125" /></element>
|
||||
<element ref="whitekey" inputtag="KC2" inputmask="0x10"><bounds xc="570" y="0" width="25" height="245" /></element>
|
||||
|
||||
<element ref="whitekey" inputtag="KC2" inputmask="0x20"><bounds xc="630" y="0" width="25" height="245" /></element>
|
||||
</group>
|
||||
|
||||
<group name="key_labels">
|
||||
<bounds x="0" y="0" width="660" height="40" />
|
||||
|
||||
<element ref="tone2"><bounds xc="60" y="11" width="60" height="9" /></element>
|
||||
<element ref="line_white"><bounds xc="60" y="20" width="1.5" height="20" /></element>
|
||||
<element ref="tone4"><bounds xc="120" y="11" width="60" height="9" /></element>
|
||||
<element ref="line_white"><bounds xc="120" y="20" width="1.5" height="20" /></element>
|
||||
<element ref="tone7"><bounds xc="240" y="11" width="60" height="9" /></element>
|
||||
<element ref="line_white"><bounds xc="240" y="20" width="1.5" height="20" /></element>
|
||||
<element ref="tone9"><bounds xc="300" y="3" width="55" height="9" /></element>
|
||||
<element ref="tone9b"><bounds xc="300" y="11" width="55" height="9" /></element>
|
||||
<element ref="line_white"><bounds xc="300" y="20" width="1.5" height="20" /></element>
|
||||
<element ref="tone11"><bounds xc="360" y="3" width="55" height="9" /></element>
|
||||
<element ref="tone11b"><bounds xc="360" y="11" width="55" height="9" /></element>
|
||||
<element ref="line_white"><bounds xc="360" y="20" width="1.5" height="20" /></element>
|
||||
|
||||
<element ref="tone1"><bounds xc="30" y="30" width="60" height="9" /></element>
|
||||
<element ref="tone3"><bounds xc="90" y="30" width="60" height="9" /></element>
|
||||
<element ref="tone5"><bounds xc="150" y="30" width="60" height="9" /></element>
|
||||
<element ref="tone6"><bounds xc="210" y="30" width="60" height="9" /></element>
|
||||
<element ref="tone8"><bounds xc="270" y="30" width="60" height="9" /></element>
|
||||
<element ref="tone10"><bounds xc="330" y="22" width="55" height="9" /></element>
|
||||
<element ref="tone10b"><bounds xc="330" y="30" width="55" height="9" /></element>
|
||||
<element ref="tone12"><bounds xc="390" y="22" width="55" height="9" /></element>
|
||||
<element ref="tone12b"><bounds xc="390" y="30" width="55" height="9" /></element>
|
||||
|
||||
<element ref="tone14"><bounds xc="480" y="11" width="60" height="9" /></element>
|
||||
<element ref="line_white"><bounds xc="480" y="20" width="1.5" height="20" /></element>
|
||||
<element ref="tone16"><bounds xc="540" y="11" width="60" height="9" /></element>
|
||||
<element ref="line_white"><bounds xc="540" y="20" width="1.5" height="20" /></element>
|
||||
|
||||
<element ref="tone13"><bounds xc="450" y="30" width="60" height="9" /></element>
|
||||
<element ref="tone15"><bounds xc="510" y="30" width="60" height="9" /></element>
|
||||
<element ref="tone17"><bounds xc="570" y="30" width="60" height="9" /></element>
|
||||
<element ref="tone18"><bounds xc="630" y="30" width="60" height="9" /></element>
|
||||
</group>
|
||||
|
||||
<view name="Keyboard">
|
||||
<element ref="brown"><bounds x="0" y="0" width="690" height="520" /></element>
|
||||
<group ref="buttons"><bounds xc="345" y="0" width="660" height="180" /></group>
|
||||
<element ref="panel_back"><bounds xc="345" y="180" width="660" height="40" /></element>
|
||||
<element ref="line"><bounds xc="345" y="180" width="660" height="3" /></element>
|
||||
|
||||
<group ref="key_labels"><bounds xc="345" y="180" width="660" height="40" /></group>
|
||||
<group ref="keyboard"><bounds xc="345" y="220" width="660" height="300" /></group>
|
||||
</view>
|
||||
</mamelayout>
|
@ -16155,6 +16155,11 @@ casloopy //
|
||||
cfx9850 // Casio CFX-9850
|
||||
cfx9850gb // Casio CFX-9850GB Plus
|
||||
|
||||
@source:casio/ct8000.cpp
|
||||
ct8000 //
|
||||
ctfk1 //
|
||||
ctmb1 //
|
||||
|
||||
@source:casio/ctk2000.cpp
|
||||
ctk2100 //
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user