summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Felipe CorrĂȘa da Silva Sanches <juca@members.fsf.org>2025-08-29 03:04:35 -0300
committer GitHub <noreply@github.com>2025-08-29 16:04:35 +1000
commitc41bc7a44cc542231edda5fb533e7ac0d9691aec (patch)
treed5df1fdd9ca06cbc4c5317558c4eb956a5965035
parent5ab1a10950311af888990d6eff42b14947b84337 (diff)
ensoniq/esq1.cpp: Adding internal interactive artwork for the Ensoniq ESQ-1. (#14049)
ensoniq/esqvfd.cpp: Added support for underline segments.
-rw-r--r--src/mame/ensoniq/esq1.cpp287
-rw-r--r--src/mame/ensoniq/esqlcd.cpp2
-rw-r--r--src/mame/ensoniq/esqlcd.h2
-rw-r--r--src/mame/ensoniq/esqvfd.cpp29
-rw-r--r--src/mame/ensoniq/esqvfd.h10
-rw-r--r--src/mame/layout/esq1.lay810
-rw-r--r--src/mame/layout/esq2by40.lay18
7 files changed, 1077 insertions, 81 deletions
diff --git a/src/mame/ensoniq/esq1.cpp b/src/mame/ensoniq/esq1.cpp
index 26dc705a379..c0a59f34db5 100644
--- a/src/mame/ensoniq/esq1.cpp
+++ b/src/mame/ensoniq/esq1.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont, Olivier Galibert
/***************************************************************************
- drivers/esq1.c
+ ensoniq/esq1.cpp
Ensoniq ESQ-1 Digital Wave Synthesizer
Ensoniq ESQ-M (rack-mount ESQ-1)
@@ -53,10 +53,9 @@ IRQ sources are the DUART and the DRQ line from the FDC (SQ-80 only).
NMI is from the IRQ line on the FDC (again, SQ-80 only).
TODO:
- - VFD display
- Keyboard
-] - Analog filters and VCA on the back end of the 5503 (inaccurate)
- - duart seems to keep interrupting even after MIDI xmit buffer becomes empty
+ - Analog filters and VCA on the back end of the 5503 (inaccurate)
+ - DUART seems to keep interrupting even after MIDI xmit buffer becomes empty
NOTES:
Commands from KPC are all 2 bytes
@@ -181,15 +180,23 @@ NOTES:
***************************************************************************/
#include "emu.h"
+
+#include "esqpanel.h"
+
#include "bus/midi/midi.h"
#include "cpu/m6809/m6809.h"
#include "machine/input_merger.h"
#include "machine/mc68681.h"
#include "machine/wd_fdc.h"
-#include "esqpanel.h"
#include "sound/es5503.h"
+
#include "speaker.h"
+//#define VERBOSE 1
+#include "logmacro.h"
+
+#include "esq1.lh"
+
#define WD1772_TAG "wd1772"
@@ -397,6 +404,10 @@ public:
m_filters(*this, "filters"),
m_fdc(*this, WD1772_TAG),
m_panel(*this, "panel"),
+ m_volume_slider(*this, "volume_slider"),
+ m_data_entry_slider(*this, "data_entry_slider"),
+ m_pitch_wheel(*this, "pitch_wheel"),
+ m_mod_wheel(*this, "mod_wheel"),
m_mdout(*this, "mdout"),
m_es5503(*this, "es5503"),
m_es5503_rom(*this, "es5503")
@@ -407,6 +418,7 @@ public:
void esq1(machine_config &config);
DECLARE_INPUT_CHANGED_MEMBER(key_stroke);
+ DECLARE_INPUT_CHANGED_MEMBER(internal_kbd_key_stroke);
private:
required_device<cpu_device> m_maincpu;
@@ -414,6 +426,10 @@ private:
required_device<esq1_filters> m_filters;
optional_device<wd1772_device> m_fdc;
optional_device<esqpanel2x40_device> m_panel;
+ required_ioport m_volume_slider;
+ required_ioport m_data_entry_slider;
+ required_ioport m_pitch_wheel;
+ required_ioport m_mod_wheel;
optional_device<midi_port_device> m_mdout;
required_device<es5503_device> m_es5503;
required_region_ptr<uint8_t> m_es5503_rom;
@@ -443,8 +459,7 @@ private:
void sq80_es5503_map(address_map &map) ATTR_COLD;
bool kpc_calibrated = false; // sq80 requires keyboard calibration acknowledgement
- int m_adc_target = 0; // adc poll target (index into the table below)
- uint8_t m_adc_value[6] = { 0,0,128,0,0,0 }; // VALV,PEDV,PITV,MODV,FILV,BATV
+ int m_adc_poll_target = 0;
};
uint8_t esq1_state::es5503_sample_r(offs_t offset)
@@ -459,13 +474,37 @@ void esq1_state::sq80_es5503_map(address_map &map)
uint8_t esq1_state::esq1_adc_read()
{
- return m_adc_value[m_adc_target];
+ uint8_t value;
+ switch(m_adc_poll_target) {
+ case 0: // VALV
+ value = m_data_entry_slider->read();
+ break;
+
+ case 1: // PEDV - Expression Pedal / CV input
+ value = 0;
+ break;
+
+ case 2: // PITV
+ value = m_pitch_wheel->read();
+ break;
+
+ case 3: // MODV
+ value = m_mod_wheel->read();
+ break;
+
+ case 4: // FILV
+ case 5: // BATV
+ default:
+ value = 0;
+ break;
+ }
+ return value * 255.0/100;
}
void esq1_state::machine_reset()
{
// set default OSROM banking
- membank("osbank")->set_base(memregion("osrom")->base() );
+ membank("osbank")->set_base(memregion("osrom")->base());
m_mapper_state = 1;
m_seq_bank = 0;
@@ -486,7 +525,7 @@ void esq1_state::mapper_w(uint8_t data)
{
m_mapper_state = (data & 1);
-// printf("mapper_state = %d\n", data ^ 1);
+ LOG("mapper_state = %d\n", data ^ 1);
}
void esq1_state::analog_w(offs_t offset, uint8_t data)
@@ -503,24 +542,18 @@ void esq1_state::analog_w(offs_t offset, uint8_t data)
uint8_t esq1_state::seqdosram_r(offs_t offset)
{
- if (m_mapper_state)
- {
+ if (m_mapper_state) {
return m_dosram[offset];
- }
- else
- {
+ } else {
return m_seqram[offset + m_seq_bank];
}
}
void esq1_state::seqdosram_w(offs_t offset, uint8_t data)
{
- if (m_mapper_state)
- {
+ if (m_mapper_state) {
m_dosram[offset] = data;
- }
- else
- {
+ } else {
m_seqram[offset + m_seq_bank] = data;
}
}
@@ -566,14 +599,14 @@ void esq1_state::sq80_map(address_map &map)
void esq1_state::duart_output(uint8_t data)
{
- int bank = m_adc_target = ((data >> 1) & 0x7);
-// printf("DP [%02x]: %d mlo %d mhi %d tape %d\n", data, data&1, (data>>4)&1, (data>>5)&1, (data>>6)&3);
-// printf("%s [%02x] bank %d => offset %x\n", machine().describe_context().c_str(), data, bank, bank * 0x1000);
+ int bank = m_adc_poll_target = ((data >> 1) & 0x7);
+ LOG("DP [%02x]: %d mlo %d mhi %d tape %d\n", data, data&1, (data>>4)&1, (data>>5)&1, (data>>6)&3);
+ LOG("%s [%02x] bank %d => offset %x\n", machine().describe_context().c_str(), data, bank, bank * 0x1000);
membank("osbank")->set_base(memregion("osrom")->base() + (bank * 0x1000) );
m_seq_bank = (data & 0x8) ? 0x8000 : 0x0000;
m_seq_bank += ((data>>1) & 3) * 0x2000;
-// printf("seqram_bank = %x\n", state->m_seq_bank);
+ LOG("seqram_bank = %x\n", state->m_seq_bank);
}
void esq1_state::send_through_panel(uint8_t data)
@@ -584,28 +617,36 @@ void esq1_state::send_through_panel(uint8_t data)
INPUT_CHANGED_MEMBER(esq1_state::key_stroke)
{
u8 offset = 0;
- if (strncmp(machine().basename().c_str(), "sq80", 4) == 0)
- {
- if (!kpc_calibrated)
- { // ack SQ80 keyboard calibration
+ // FIXME: get rid of short name checks
+ if(strncmp(machine().basename().c_str(), "sq80", 4) == 0) {
+ if (!kpc_calibrated) {
+ // ack SQ80 keyboard calibration
send_through_panel((u8)0xff);
kpc_calibrated = true;
}
offset = 2; // SQ80 keycodes are offset by -2
}
- if (oldval == 0 && newval == 1)
- {
+ if(oldval == 0 && newval == 1) {
send_through_panel((u8)param - offset);
send_through_panel((u8)0x00);
- }
- else if (oldval == 1 && newval == 0)
- {
+ } else if(oldval == 1 && newval == 0) {
send_through_panel(((u8)param - offset)&0x7f);
send_through_panel((u8)0x00);
}
}
+INPUT_CHANGED_MEMBER(esq1_state::internal_kbd_key_stroke)
+{
+ if(oldval == 0 && newval == 1) {
+ send_through_panel((u8)param);
+ send_through_panel((u8)0x01);
+ } else if(oldval == 1 && newval == 0) {
+ send_through_panel(((u8)param)&0x7f);
+ send_through_panel((u8)0x01);
+ }
+}
+
void esq1_state::esq1(machine_config &config)
{
MC6809E(config, m_maincpu, 8_MHz_XTAL / 4);
@@ -649,11 +690,14 @@ void esq1_state::esq1(machine_config &config)
m_es5503->add_route(5, "filters", 1.0, 5);
m_es5503->add_route(6, "filters", 1.0, 6);
m_es5503->add_route(7, "filters", 1.0, 7);
+
+ config.set_default_layout(layout_esq1);
}
void esq1_state::sq80(machine_config &config)
{
esq1(config);
+
m_maincpu->set_addrmap(AS_PROGRAM, &esq1_state::sq80_map);
m_es5503->set_addrmap(0, &esq1_state::sq80_es5503_map);
@@ -665,32 +709,157 @@ void esq1_state::sq80(machine_config &config)
}
static INPUT_PORTS_START( esq1 )
- PORT_START("KEY0")
- PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x84) PORT_NAME("SEQ")
- PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x85) PORT_NAME("CART A")
- PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x86) PORT_NAME("CART B")
- PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x87) PORT_NAME("INT")
- PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x88) PORT_NAME("1 / SEQ 1")
- PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x89) PORT_NAME("2 / SEQ 2")
- PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8a) PORT_NAME("3 / SEQ 3")
- PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8b) PORT_NAME("4 / SONG")
- PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('Z') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8c) PORT_NAME("COMPARE")
- PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8e) PORT_NAME("DATA DOWN")
- PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8d) PORT_NAME("DATA UP")
- PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR('\r') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8f) PORT_NAME("WRITE")
-
- PORT_START("KEY1")
- PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x90) PORT_NAME("UPPER 1")
- PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x91) PORT_NAME("UPPER 2")
- PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x92) PORT_NAME("UPPER 3")
- PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x93) PORT_NAME("UPPER 4")
- PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x99) PORT_NAME("UPPER 5")
- PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x94) PORT_NAME("LOWER 1")
- PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x95) PORT_NAME("LOWER 2")
- PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x96) PORT_NAME("LOWER 3")
- PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x97) PORT_NAME("LOWER 4")
- PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x98) PORT_NAME("LOWER 5")
-
+ PORT_START("volume_slider")
+ PORT_ADJUSTER(255, "Volume")
+
+ PORT_START("data_entry_slider")
+ PORT_ADJUSTER(255, "Data Entry")
+
+ PORT_START("pitch_wheel")
+ PORT_ADJUSTER(255, "Pitch Wheel")
+
+ PORT_START("mod_wheel")
+ PORT_ADJUSTER(255, "Mod Wheel")
+
+ PORT_START("COL0")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x84) PORT_NAME("SEQ")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x85) PORT_NAME("CART A")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x86) PORT_NAME("CART B")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x87) PORT_NAME("INT")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x88) PORT_NAME("1 / SEQ 1")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x89) PORT_NAME("2 / SEQ 2")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8a) PORT_NAME("3 / SEQ 3")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8b) PORT_NAME("4 / SONG")
+
+ PORT_START("COL1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('Z') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8c) PORT_NAME("COMPARE")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8d) PORT_NAME("DATA UP")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8e) PORT_NAME("DATA DOWN")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR('\r') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x8f) PORT_NAME("WRITE")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x90) PORT_NAME("UPPER 1")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x91) PORT_NAME("UPPER 2")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x92) PORT_NAME("UPPER 3")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x93) PORT_NAME("UPPER 4")
+
+ PORT_START("COL2")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x94) PORT_NAME("LOWER 1")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x95) PORT_NAME("LOWER 2")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x96) PORT_NAME("LOWER 3")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x97) PORT_NAME("LOWER 4")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x98) PORT_NAME("LOWER 5")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x99) PORT_NAME("UPPER 5")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x9a) PORT_NAME("LFO 1")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x9b) PORT_NAME("ENV 2")
+
+ PORT_START("COL3")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x9c) PORT_NAME("Master")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x9d) PORT_NAME("Create/Erase")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x9e) PORT_NAME("Tracks: Select")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0x9f) PORT_NAME("Record")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xa0) PORT_NAME("Storage")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xa1) PORT_NAME("Edit")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xa2) PORT_NAME("Mix")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xa3) PORT_NAME("Stop")
+
+ PORT_START("COL4")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xa4) PORT_NAME("MIDI")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xa5) PORT_NAME("Control")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xa6) PORT_NAME("Locate")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xa7) PORT_NAME("Play")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xa8) PORT_NAME("OSC 1")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xa9) PORT_NAME("OSC 2")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xaa) PORT_NAME("OSC 3")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xab) PORT_NAME("ENV 1")
+
+ PORT_START("COL5")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xac) PORT_NAME("DCA 1")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xad) PORT_NAME("DCA 2")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xae) PORT_NAME("DCA 3")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xaf) PORT_NAME("LFO 2")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xb0) PORT_NAME("LFO 3")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xb1) PORT_NAME("Filter")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xb2) PORT_NAME("ENV 4")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xb3) PORT_NAME("ENV 3")
+
+ PORT_START("COL6")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xb4) PORT_NAME("DCA 4")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xb5) PORT_NAME("Modes")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::key_stroke), 0xb6) PORT_NAME("Split")
+ PORT_BIT(0xf8, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("INTERNAL_KBD1")
+ PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0x98) PORT_GM_C1
+ PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0x99) PORT_GM_CS1
+ PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0x9a) PORT_GM_D1
+ PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0x9b) PORT_GM_DS1
+ PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0x9c) PORT_GM_E1
+ PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0x9d) PORT_GM_F1
+ PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0x9e) PORT_GM_FS1
+ PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0x9f) PORT_GM_G1
+ PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xa0) PORT_GM_GS1
+ PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xa1) PORT_GM_A1
+ PORT_BIT(0x400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xa2) PORT_GM_AS1
+ PORT_BIT(0x800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xa3) PORT_GM_B1
+
+ PORT_START("INTERNAL_KBD2")
+ PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xa4) PORT_GM_C2
+ PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xa5) PORT_GM_CS2
+ PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xa6) PORT_GM_D2
+ PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xa7) PORT_GM_DS2
+ PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xa8) PORT_GM_E2
+ PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xa9) PORT_GM_F2
+ PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xaa) PORT_GM_FS2
+ PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xab) PORT_GM_G2
+ PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xac) PORT_GM_GS2
+ PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xad) PORT_GM_A2
+ PORT_BIT(0x400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xae) PORT_GM_AS2
+ PORT_BIT(0x800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xaf) PORT_GM_B2
+
+ PORT_START("INTERNAL_KBD3")
+ PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xb0) PORT_GM_C3
+ PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xb1) PORT_GM_CS3
+ PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xb2) PORT_GM_D3
+ PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xb3) PORT_GM_DS3
+ PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xb4) PORT_GM_E3
+ PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xb5) PORT_GM_F3
+ PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xb6) PORT_GM_FS3
+ PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xb7) PORT_GM_G3
+ PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xb8) PORT_GM_GS3
+ PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xb9) PORT_GM_A3
+ PORT_BIT(0x400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xba) PORT_GM_AS3
+ PORT_BIT(0x800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xbb) PORT_GM_B3
+
+ PORT_START("INTERNAL_KBD4")
+ PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xbc) PORT_GM_C4
+ PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xbd) PORT_GM_CS4
+ PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xbe) PORT_GM_D4
+ PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xbf) PORT_GM_DS4
+ PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xc0) PORT_GM_E4
+ PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xc1) PORT_GM_F4
+ PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xc2) PORT_GM_FS4
+ PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xc3) PORT_GM_G4
+ PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xc4) PORT_GM_GS4
+ PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xc5) PORT_GM_A4
+ PORT_BIT(0x400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xc6) PORT_GM_AS4
+ PORT_BIT(0x800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xc7) PORT_GM_B4
+
+ PORT_START("INTERNAL_KBD5")
+ PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xc8) PORT_GM_C5
+ PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xc9) PORT_GM_CS5
+ PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xca) PORT_GM_D5
+ PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xcb) PORT_GM_DS5
+ PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xcc) PORT_GM_E5
+ PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xcd) PORT_GM_F5
+ PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xce) PORT_GM_FS5
+ PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xcf) PORT_GM_G5
+ PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xd0) PORT_GM_GS5
+ PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xd1) PORT_GM_A5
+ PORT_BIT(0x400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xd2) PORT_GM_AS5
+ PORT_BIT(0x800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xd3) PORT_GM_B5
+
+ PORT_START("INTERNAL_KBD6")
+ PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(esq1_state::internal_kbd_key_stroke), 0xd4) PORT_GM_C6
+ PORT_BIT(0xffe, IP_ACTIVE_HIGH, IPT_UNUSED)
INPUT_PORTS_END
diff --git a/src/mame/ensoniq/esqlcd.cpp b/src/mame/ensoniq/esqlcd.cpp
index a9348a5bde2..e1a26cd1ac7 100644
--- a/src/mame/ensoniq/esqlcd.cpp
+++ b/src/mame/ensoniq/esqlcd.cpp
@@ -168,7 +168,7 @@ void esq2x16_sq1_device::device_add_mconfig(machine_config &config)
}
//--------------------------------------------------------------------------------------------------------------------------------------------
-void esq2x16_sq1_device::write_char(int data)
+void esq2x16_sq1_device::write_char(uint8_t data)
{
int DisplayCode = data;
int LedState;
diff --git a/src/mame/ensoniq/esqlcd.h b/src/mame/ensoniq/esqlcd.h
index 29632c7cec2..ac6bdbe5c50 100644
--- a/src/mame/ensoniq/esqlcd.h
+++ b/src/mame/ensoniq/esqlcd.h
@@ -14,7 +14,7 @@ class esq2x16_sq1_device : public esqvfd_device {
public:
esq2x16_sq1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual void write_char(int data) override;
+ virtual void write_char(uint8_t data) override;
virtual void update_display() override;
protected:
diff --git a/src/mame/ensoniq/esqvfd.cpp b/src/mame/ensoniq/esqvfd.cpp
index 68b913f9c22..f8aa3435f56 100644
--- a/src/mame/ensoniq/esqvfd.cpp
+++ b/src/mame/ensoniq/esqvfd.cpp
@@ -151,12 +151,12 @@ void esqvfd_device::update_display()
{
uint32_t segdata = conv_segments(font[m_chars[row][col]]);
- // force bottom bar on all underlined chars
- if (m_attrs[row][col] & AT_UNDERLINE)
- segdata |= 0x0008;
-
+ // digits:
m_vfds->set((row * m_cols) + col, segdata);
+ // underlines:
+ m_vfds->set((row * m_cols) + col + (m_rows * m_cols), (m_attrs[row][col] & AT_UNDERLINE) ? 1 : 0);
+
m_dirty[row][col] = 0;
}
}
@@ -170,17 +170,22 @@ void esq2x40_device::device_add_mconfig(machine_config &config)
config.set_default_layout(layout_esq2by40);
}
-void esq2x40_device::write_char(int data)
+void esq2x40_device::write_char(uint8_t data)
{
// ESQ-1 sends (cursor move) 0xfa 0xYY to mark YY characters as underlined at the current cursor location
if (m_lastchar == 0xfa)
{
- if ((m_cursx + data) > m_rows)
- data = m_rows - m_cursx;
- for (int i = 0; i < data; i++)
+ for (uint8_t j = 0; j < m_rows; j++)
{
- m_attrs[m_cursy][m_cursx + i] |= AT_UNDERLINE;
- m_dirty[m_cursy][m_cursx + i] = 1;
+ for (uint8_t i = 0; i < m_cols; i++)
+ {
+ if (m_cursy == j && i >= m_cursx && i < m_cursx + data)
+ m_attrs[j][i] |= AT_UNDERLINE;
+ else
+ m_attrs[j][i] &= ~AT_UNDERLINE;
+
+ m_dirty[j][i] = 1;
+ }
}
m_lastchar = 0;
@@ -305,7 +310,7 @@ void esq1x22_device::device_add_mconfig(machine_config &config)
}
-void esq1x22_device::write_char(int data)
+void esq1x22_device::write_char(uint8_t data)
{
if (data >= 0x60)
{
@@ -352,7 +357,7 @@ void esq2x40_sq1_device::device_add_mconfig(machine_config &config)
config.set_default_layout(layout_esq2by40); // we use the normal 2x40 layout
}
-void esq2x40_sq1_device::write_char(int data)
+void esq2x40_sq1_device::write_char(uint8_t data)
{
if (data == 0x09) // musical note
{
diff --git a/src/mame/ensoniq/esqvfd.h b/src/mame/ensoniq/esqvfd.h
index d976ef22841..bbbe2ea7cc7 100644
--- a/src/mame/ensoniq/esqvfd.h
+++ b/src/mame/ensoniq/esqvfd.h
@@ -11,7 +11,7 @@ class esqvfd_device : public device_t {
public:
void write(uint8_t data) { write_char(data); }
- virtual void write_char(int data) = 0;
+ virtual void write_char(uint8_t data) = 0;
virtual void update_display();
virtual bool write_contents(std::ostream &o) { return false; }
@@ -36,7 +36,7 @@ protected:
typedef std::tuple<output_helper::ptr, int, int> dimensions_param;
- template <int R, int C> static dimensions_param make_dimensions(device_t &device) { return dimensions_param(std::make_unique<output_helper_impl<R * C> >(device), R, C); }
+ template <int R, int C> static dimensions_param make_dimensions(device_t &device) { return dimensions_param(std::make_unique<output_helper_impl<2 * R * C> >(device), R, C); }
esqvfd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, dimensions_param &&dimensions);
@@ -64,7 +64,7 @@ class esq1x22_device : public esqvfd_device {
public:
esq1x22_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual void write_char(int data) override;
+ virtual void write_char(uint8_t data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
@@ -76,7 +76,7 @@ class esq2x40_device : public esqvfd_device {
public:
esq2x40_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual void write_char(int data) override;
+ virtual void write_char(uint8_t data) override;
virtual bool write_contents(std::ostream &o) override;
protected:
@@ -87,7 +87,7 @@ class esq2x40_sq1_device : public esqvfd_device {
public:
esq2x40_sq1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual void write_char(int data) override;
+ virtual void write_char(uint8_t data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
diff --git a/src/mame/layout/esq1.lay b/src/mame/layout/esq1.lay
new file mode 100644
index 00000000000..1ce6e521a3f
--- /dev/null
+++ b/src/mame/layout/esq1.lay
@@ -0,0 +1,810 @@
+<?xml version="1.0"?>
+<!--
+license:CC0-1.0
+-->
+<!-- 2012-05-26: Initial version - Only VFDs. [R. Belmont / VFDGen 0.1] -->
+<!-- 2025-08-08: Full control panel with buttons, sliders, LEDs and keybed. [F. Sanches] -->
+<mamelayout version="2">
+
+<!-- define elements -->
+
+ <element name="down_arrow">
+ <image><data><![CDATA[
+ <svg width="9" height="5">
+ <path fill="#d4dad3" d="M 0,0 l 4.5,5 4.5,-5 z" />
+ </svg>
+ ]]></data></image>
+ </element>
+
+ <element name="oscillators_diagram">
+ <image><data><![CDATA[
+ <svg width="285" height="58">
+ <!-- Arrows -->
+ <path fill="#fecb24"
+ d="
+ M 0,9 l 3,5 3,-5 -3,1 z
+ M 53,8 l 1.5,6 -5.5,-2 3,-1 z
+ " />
+
+ <!-- Lines -->
+ <path fill="none" stroke="#fecb24" stroke-width="1"
+ d="
+ M 30,3 h 14 l 23,23 h 10
+ m 52,6 h -9 l -25,25 h -65
+ m 156,-25 h 99
+ m 0,-24 h -57 l -18,18 h -24
+ m -57,0 h -9 l -25,-25 h -92 l 0,28 h 176
+ " />
+ </svg>
+ ]]></data></image>
+ </element>
+
+ <element name="envelope_diagram">
+ <image><data><![CDATA[
+ <svg width="87" height="62">
+ <path fill="none" stroke="#d4dad3" stroke-width="1"
+ d="
+ M 5,31 L 21,1 38,40 51,22 H 72 L 78,31
+ M 87,31 H 0
+ M 0,1 H 3 M 0,7 H 3 M 0,13 H 3 M 0,19 H 3 M 0,25 H 3
+ M 0,37 H 3 M 0,43 H 3 M 0,49 H 3 M 0,55 H 3 M 0,61 H 3
+ " />
+ </svg>
+ ]]></data></image>
+ </element>
+
+ <element name="white_key">
+ <rect state="0"><color red="0.95" green="0.95" blue="0.9"/></rect>
+ <rect state="1"><color red="0.3" green="0.6" blue="0.8"/></rect>
+ </element>
+
+ <element name="black_key">
+ <rect state="0"><color red="0.08" green="0.08" blue="0.08"/></rect>
+ <rect state="1"><color red="0.3" green="0.3" blue="0.6"/></rect>
+ </element>
+
+ <element name="grey_button">
+ <rect state="0"><color red="0.08" green="0.08" blue="0.08"/></rect>
+ <rect state="1"><color red="0.3" green="0.3" blue="0.3"/></rect>
+ </element>
+
+ <element name="yellow_button">
+ <rect state="0"><color red="0.99" green="0.79" blue="0.14"/></rect>
+ <rect state="1"><color red="0.5" green="0.4" blue="0.07"/></rect>
+ </element>
+
+ <element name="white_button">
+ <rect state="0"><color red="0.83" green="0.86" blue="0.83"/></rect>
+ <rect state="1"><color red="0.41" green="0.43" blue="0.41"/></rect>
+ </element>
+
+ <element name="white_rect">
+ <rect><color red="0.83" green="0.86" blue="0.83" /></rect>
+ </element>
+
+ <element name="grey_rect">
+ <rect><color red="0.2" green="0.2" blue="0.2" /></rect>
+ </element>
+
+ <element name="dark_grey_rect">
+ <rect><color red="0.13" green="0.13" blue="0.15" /></rect>
+ </element>
+
+ <element name="wheel-body">
+ <rect><color red="0.1" green="0.1" blue="0.1" /></rect>
+ </element>
+
+ <element name="panel_sheet">
+ <rect><color red="0.17" green="0.17" blue="0.18"/></rect>
+ </element>
+
+ <element name="screen_border">
+ <rect><color red="0.05" green="0.05" blue="0.05"/></rect>
+ </element>
+
+ <element name="invisible-rect">
+ <rect><color red="0" green="0" blue="0" alpha="0"/></rect>
+ </element>
+
+ <element name="black-rect">
+ <rect><color red="0.0" green="0.0" blue="0.0"/></rect>
+ </element>
+
+ <element name="wheel-knob">
+ <rect>
+ <color red="0" green="0" blue="0"/>
+ </rect>
+ </element>
+
+ <element name="slider-knob">
+ <rect>
+ <bounds x="0" y="0" width="35" height="35"/>
+ <color red="0.17" green="0.21" blue="0.19"/>
+ </rect>
+ <rect>
+ <bounds x="1" y="16" width="33" height="3"/>
+ <color red="0.97" green="0.97" blue="0.96"/>
+ </rect>
+ </element>
+
+ <element name="slider_ticks">
+ <image><data><![CDATA[
+ <svg width="46" height="93">
+ <path fill="none" stroke="#d4dad3" stroke-width="1"
+ d="
+ M 0,18 h 9 m 28,0 h 9
+ m -46,9 h 9 m 28,0 h 9
+ m -46,9 h 9 m 28,0 h 9
+ m -46,9 h 9 m 28,0 h 9
+ m -46,9 h 9 m 28,0 h 9
+ m -46,9 h 9 m 28,0 h 9
+ m -46,9 h 9 m 28,0 h 9
+ " />
+ </svg>
+ ]]></data></image>
+ </element>
+
+ <group name="slider">
+ <element ref="black-rect"> <!-- slider channel -->
+ <bounds x="12" y="0" width="23" height="94"/>
+ </element>
+ <element ref="dark_grey_rect"> <!-- slider rail -->
+ <bounds x="20" y="10" width="7" height="77"/>
+ </element>
+ <element id="slider_~slider_id~" ref="invisible-rect">
+ <bounds x="12" y="10" width="23" height="77"/>
+ </element>
+ <element ref="slider_ticks"><bounds x="0" y="0" width="46" height="94"/></element>
+ <element id="slider_knob_~slider_id~" ref="slider-knob">
+ <animate inputtag="~port_name~" inputmask="0x7f"/>
+ <bounds state="100" x="9" y="11" width="29" height="16"/>
+ <bounds state="0" x="9" y="66" width="29" height="16"/>
+ </element>
+ </group>
+
+ <group name="wheel">
+ <element ref="wheel-body">
+ <bounds x="12" y="0" width="23" height="94"/>
+ </element>
+ <element id="slider_~slider_id~" ref="invisible-rect">
+ <bounds x="12" y="10" width="23" height="77"/>
+ </element>
+ <element id="slider_knob_~slider_id~" ref="wheel-knob">
+ <animate inputtag="~port_name~" inputmask="0x7f"/>
+ <bounds state="100" x="12" y="11" width="23" height="16"/>
+ <bounds state="0" x="12" y="66" width="23" height="16"/>
+ </element>
+ </group>
+
+ <element name="screw_head"><disk><color red="0.25" green="0.25" blue="0.25" /></disk></element>
+
+ <element name="power_text"><text string="POWER"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="line_text"><text string="LINE"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="fuse_text"><text string="FUSE"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="sustain_text"><text string="SUSTAIN"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="ft_sw_text"><text string="FT. SW."><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="sequencer_text"><text string="SEQUENCER"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="tape_out_text"><text string="TAPE OUT"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="tape_in_text"><text string="TAPE IN"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="midi_in_text"><text string="MIDI IN"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="midi_out_text"><text string="MIDI OUT"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="pedal_cv_text"><text string="PEDAL/CV"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="left_mono_rear_text"><text string="LEFT/MONO"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="right_rear_text"><text string="RIGHT"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="audio_out_text"><text string="AUDIO OUT"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+
+ <!--<element name="ensoniq_logo"><text string="ensoniq"><color red="0.83" green="0.86" blue="0.83" /></text></element>-->
+ <element name="esq1_logo"><text string="ESQ-1"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="dwsynth_title"><text string="Digital Wave Synthesizer"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="cartridge_text"><text string="Program Cartridge"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="pitch_text"><text string="PITCH"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="mod_text"><text string="MOD"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="volume_title"><text string="VOLUME"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="banks_title"><text string="BANKS"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="data_entry_title"><text string="DATA ENTRY"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="programmer_title"><text string="PROGRAMMER"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="sequencer_title"><text string="SEQUENCER"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="voice_title"><text string="VOICE"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="seq_text"><text string="SEQ"><color red="0.99" green="0.79" blue="0.14"/></text></element>
+ <element name="seq_1_text"><text string="SEQ 1"><color red="0.99" green="0.79" blue="0.14"/></text></element>
+ <element name="seq_2_text"><text string="SEQ 2"><color red="0.99" green="0.79" blue="0.14"/></text></element>
+ <element name="seq_3_text"><text string="SEQ 3"><color red="0.99" green="0.79" blue="0.14"/></text></element>
+ <element name="song_text"><text string="Song"><color red="0.99" green="0.79" blue="0.14"/></text></element>
+
+ <element name="cart_a_text"><text string="Cart A"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="cart_b_text"><text string="Cart B"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="internal_text"><text string="Internal"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="1_text"><text string="1"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="2_text"><text string="2"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="3_text"><text string="3"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="4_text"><text string="4"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="compare_text"><text string="Compare"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="write_text"><text string="Write"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="master_text"><text string="Master"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="storage_text"><text string="Storage"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="midi_text"><text string="MIDI"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="create_erase_text1"><text string="Create/"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="create_erase_text2"><text string="Erase"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="edit_text"><text string="Edit"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="control_text"><text string="Control"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="tracks_text"><text string="Tracks"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="select_text"><text string="Select"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="mix_midi_text"><text string="Mix/MIDI"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="locate_text"><text string="Locate"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="record_text"><text string="Record"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="stop_cont_text"><text string="Stop/Cont"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="play_text"><text string="Play"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+
+ <element name="digital_waveform_mem_text1"><text string="DIGITAL"><color red="0.17" green="0.17" blue="0.18" /></text></element>
+ <element name="digital_waveform_mem_text2"><text string="WAVEFORM"><color red="0.17" green="0.17" blue="0.18" /></text></element>
+ <element name="digital_waveform_mem_text3"><text string="MEMORY"><color red="0.17" green="0.17" blue="0.18" /></text></element>
+
+ <element name="osc1_text"><text string="OSC 1"><color red="0.17" green="0.17" blue="0.18" /></text></element>
+ <element name="osc2_text"><text string="OSC 2"><color red="0.17" green="0.17" blue="0.18" /></text></element>
+ <element name="osc3_text"><text string="OSC 3"><color red="0.17" green="0.17" blue="0.18" /></text></element>
+
+ <element name="dca1_text"><text string="DCA 1"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="dca2_text"><text string="DCA 2"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="dca3_text"><text string="DCA 3"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="dca4_text"><text string="DCA 4"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="lfo1_text"><text string="LFO 1"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="lfo2_text"><text string="LFO 2"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="lfo3_text"><text string="LFO 3"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="env1_text"><text string="ENV 1"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="env2_text"><text string="ENV 2"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="env3_text"><text string="ENV 3"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="env4_text"><text string="ENV 4"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+
+ <element name="sync_text"><text string="Sync"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="am_text"><text string="AM"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="left_mono_text"><text string="Left/Mono"><color red="0.99" green="0.79" blue="0.14"/></text></element>
+ <element name="right_text"><text string="Right"><color red="0.99" green="0.79" blue="0.14"/></text></element>
+ <element name="filter_text"><text string="Filter"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="modes_text"><text string="Modes"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="split_layer_text1"><text string="Split/"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="split_layer_text2"><text string="Layer"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+
+ <element name="p63_text"><text string="+63"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="0_text"><text string="0"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="m63_text"><text string="-63"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="t1_text"><text string="T1"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="l1_text"><text string="L1"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="t2_text"><text string="T2"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="l2_text"><text string="L2"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="t3_text"><text string="T3"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="l3_text"><text string="L3"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="t4_text"><text string="T4"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+ <element name="envelope_parameters_text"><text string="Envelope Parameters"><color red="0.83" green="0.86" blue="0.83" /></text></element>
+
+ <element name="vfd" defstate="0">
+ <led14segsc>
+ <color red="0.45" green="1.0" blue="0.95" />
+ </led14segsc>
+ </element>
+
+ <element name="underline" defstate="0">
+ <rect state="0"><color red="0.06" green="0.12" blue="0.10" /></rect>
+ <rect state="1"><color red="0.45" green="1.00" blue="0.95" /></rect>
+ </element>
+
+<!-- build layout -->
+
+ <group name="full">
+ <bounds x="-495" y="-100" width="1843" height="640"/>
+
+ <element ref="dark_grey_rect"><bounds x="-460" y="-87" width="1777" height="85"/></element> <!-- rear -->
+ <element ref="panel_sheet"><bounds x="-460" y="0" width="1777" height="188"/></element> <!-- main portion of control panel -->
+ <element ref="dark_grey_rect"><bounds x="-460" y="190" width="1777" height="55"/></element> <!-- middle -->
+ <!-- <element ref="grey_rect"><bounds x="-227" y="257" width="1507" height="263"/></element> --> <!-- under the keybed -->
+ <element ref="panel_sheet"><bounds x="-460" y="257" width="297" height="246"/></element> <!-- pitch & mod side-panel -->
+ <element ref="dark_grey_rect"><bounds x="-490" y="-95" width="27" height="620"/></element> <!-- left border -->
+ <element ref="dark_grey_rect"><bounds x="1320" y="-95" width="27" height="620"/></element> <!-- right border -->
+
+<!-- PITCH WHEEL: -->
+ <param name="slider_id" value="pitch_wheel"/>
+ <param name="port_name" value="pitch_wheel"/>
+ <group ref="wheel">
+ <bounds x="-390" y="310" width="24" height="145"/>
+ </group>
+
+<!-- MOD WHEEL: -->
+ <param name="slider_id" value="mod_wheel"/>
+ <param name="port_name" value="mod_wheel"/>
+ <group ref="wheel">
+ <bounds x="-315" y="310" width="24" height="145"/>
+ </group>
+
+ <element ref="oscillators_diagram"><bounds x="966" y="29" width="285" height="58"/></element>
+ <element ref="sync_text"><bounds x="951" y="45" width="14" height="6"/></element>
+ <element ref="am_text"><bounds x="1025" y="39" width="9" height="6"/></element>
+ <element ref="left_mono_text"><bounds x="1252" y="34" width="28" height="7"/></element>
+ <element ref="right_text"><bounds x="1253" y="59" width="15" height="7"/></element>
+
+ <element ref="envelope_diagram"><bounds x="1181" y="90" width="87" height="62"/></element>
+ <element ref="p63_text"><bounds x="1173" y="89" width="7" height="4"/></element>
+ <element ref="0_text"><bounds x="1178" y="118" width="2" height="4"/></element>
+ <element ref="m63_text"><bounds x="1174" y="146" width="6" height="4"/></element>
+ <element ref="t1_text"><bounds x="1190" y="100" width="5" height="4"/></element>
+ <element ref="l1_text"><bounds x="1200" y="87" width="4" height="4"/></element>
+ <element ref="t2_text"><bounds x="1208" y="100" width="5" height="4"/></element>
+ <element ref="l2_text"><bounds x="1217" y="130" width="4" height="4"/></element>
+ <element ref="t3_text"><bounds x="1223" y="113" width="5" height="4"/></element>
+ <element ref="l3_text"><bounds x="1241" y="108" width="4" height="4"/></element>
+ <element ref="t4_text"><bounds x="1257" y="113" width="5" height="4"/></element>
+ <element ref="envelope_parameters_text"><bounds x="1220" y="145" width="46" height="6"/></element>
+
+<!-- VFDs -->
+ <element ref="screen_border"><bounds x="266" y="56" width="421" height="60"/></element>
+ <repeat count="2">
+ <param name="s" start="0" increment="40" />
+ <param name="su" start="80" increment="40" />
+ <param name="y" start="70" increment="20" />
+ <param name="yu" start="83" increment="20" />
+ <repeat count="40">
+ <param name="n" start="~s~" increment="1" />
+ <param name="u" start="~su~" increment="1" />
+ <param name="x" start="277" increment="10" />
+ <param name="xu" start="278" increment="10" />
+ <element name="vfd~n~" ref="vfd">
+ <bounds x="~x~" y="~y~" width="9" height="12" />
+ </element>
+ <element name="vfd~u~" ref="underline">
+ <bounds x="~xu~" y="~yu~" width="7" height="1" />
+ </element>
+ </repeat>
+ </repeat>
+
+
+<!-- Program Cartridge: -->
+ <element ref="dark_grey_rect"><bounds x="-226" y="55" width="100" height="30"/></element>
+
+
+<!-- VOLUME SLIDER: -->
+ <param name="slider_id" value="volume"/>
+ <param name="port_name" value="volume_slider"/>
+ <group ref="slider">
+ <bounds x="-60" y="53" width="47" height="93"/>
+ </group>
+
+<!-- BANKS: -->
+ <element ref="yellow_button" inputtag="COL0" inputmask="0x01"><!-- SEQ --><bounds x="20" y="26" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL0" inputmask="0x02"><!-- CART A --><bounds x="20" y="63" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL0" inputmask="0x04"><!-- CART B --><bounds x="20" y="100" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL0" inputmask="0x08"><!-- INT --><bounds x="20" y="137" width="20" height="9"/></element>
+
+ <element ref="grey_button" inputtag="COL0" inputmask="0x10"><!-- 1 / SEQ 1 --><bounds x="58" y="26" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL0" inputmask="0x20"><!-- 2 / SEQ 2 --><bounds x="58" y="63" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL0" inputmask="0x40"><!-- 3 / SEQ 3 --><bounds x="58" y="100" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL0" inputmask="0x80"><!-- 4 / Song --><bounds x="58" y="137" width="20" height="9"/></element>
+
+<!-- DATA ENTRY: -->
+ <element ref="grey_button" inputtag="COL1" inputmask="0x01"><!-- Compare --><bounds x="115" y="26" width="20" height="9"/></element>
+ <element ref="white_button" inputtag="COL1" inputmask="0x08"><!-- Write --><bounds x="160" y="26" width="20" height="9"/></element>
+
+ <element ref="white_button" inputtag="COL1" inputmask="0x02"><!-- Data Up --><bounds x="115" y="100" width="20" height="9"/></element>
+ <element ref="white_button" inputtag="COL1" inputmask="0x04"><!-- Data Down --><bounds x="115" y="137" width="20" height="9"/></element>
+
+<!-- DATA ENTRY SLIDER: -->
+ <param name="slider_id" value="data_entry"/>
+ <param name="port_name" value="data_entry_slider"/>
+ <group ref="slider">
+ <bounds x="160" y="53" width="47" height="93"/>
+ </group>
+
+<!-- PROGRAMMER: -->
+ <element ref="grey_button" inputtag="COL1" inputmask="0x10"><!-- UPPER 1 --><bounds x="350" y="26" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL1" inputmask="0x20"><!-- UPPER 2 --><bounds x="422" y="26" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL1" inputmask="0x40"><!-- UPPER 3 --><bounds x="494" y="26" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL1" inputmask="0x80"><!-- UPPER 4 --><bounds x="566" y="26" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL2" inputmask="0x20"><!-- UPPER 5 --><bounds x="638" y="26" width="20" height="9"/></element>
+
+ <element ref="grey_button" inputtag="COL2" inputmask="0x01"><!-- LOWER 1 --><bounds x="350" y="137" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL2" inputmask="0x02"><!-- LOWER 2 --><bounds x="422" y="137" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL2" inputmask="0x04"><!-- LOWER 3 --><bounds x="494" y="137" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL2" inputmask="0x08"><!-- LOWER 4 --><bounds x="566" y="137" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL2" inputmask="0x10"><!-- LOWER 5 --><bounds x="638" y="137" width="20" height="9"/></element>
+
+<!-- SEQUENCER: -->
+ <element ref="grey_button" inputtag="COL3" inputmask="0x01"><!-- Master --><bounds x="824" y="26" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL3" inputmask="0x10"><!-- Storage --><bounds x="869" y="26" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL4" inputmask="0x01"><!-- MIDI --><bounds x="914" y="26" width="20" height="9"/></element>
+
+ <element ref="yellow_button" inputtag="COL3" inputmask="0x02"><!-- Create/Erase --><bounds x="824" y="81" width="20" height="9"/></element>
+ <element ref="yellow_button" inputtag="COL3" inputmask="0x20"><!-- Edit --><bounds x="869" y="81" width="20" height="9"/></element>
+ <element ref="yellow_button" inputtag="COL4" inputmask="0x02"><!-- Control --><bounds x="914" y="81" width="20" height="9"/></element>
+
+ <element ref="yellow_button" inputtag="COL3" inputmask="0x04"><!-- Tracks: Select --><bounds x="824" y="109" width="20" height="9"/></element>
+ <element ref="yellow_button" inputtag="COL3" inputmask="0x40"><!-- Tracks: Mix/MIDI --><bounds x="869" y="109" width="20" height="9"/></element>
+ <element ref="yellow_button" inputtag="COL4" inputmask="0x04"><!-- Locate --><bounds x="914" y="109" width="20" height="9"/></element>
+
+ <element ref="yellow_button" inputtag="COL3" inputmask="0x08"><!-- Record --><bounds x="824" y="137" width="20" height="9"/></element>
+ <element ref="yellow_button" inputtag="COL3" inputmask="0x80"><!-- Stop/Cont --><bounds x="869" y="137" width="20" height="9"/></element>
+ <element ref="yellow_button" inputtag="COL4" inputmask="0x08"><!-- Play --><bounds x="914" y="137" width="20" height="9"/></element>
+
+<!-- VOICE: -->
+ <element ref="white_rect"><bounds x="980" y="5" width="26" height="13"/></element>
+ <element ref="white_rect"><bounds x="980" y="20" width="26" height="78"/></element>
+ <element ref="grey_button" inputtag="COL4" inputmask="0x10"><!-- OSC 1 --><bounds x="983" y="26" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL5" inputmask="0x01"><!-- DCA 1 --><bounds x="1036" y="26" width="20" height="9"/></element>
+
+ <element ref="grey_button" inputtag="COL4" inputmask="0x20"><!-- OSC 2 --><bounds x="983" y="54" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL5" inputmask="0x02"><!-- DCA 2 --><bounds x="1036" y="54" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL5" inputmask="0x20"><!-- Filter --><bounds x="1089" y="54" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL6" inputmask="0x01"><!-- DCA 4 --><bounds x="1132" y="54" width="20" height="9"/></element>
+
+ <element ref="grey_button" inputtag="COL4" inputmask="0x40"><!-- OSC 3 --><bounds x="983" y="82" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL5" inputmask="0x04"><!-- DCA 3 --><bounds x="1036" y="82" width="20" height="9"/></element>
+
+ <element ref="grey_button" inputtag="COL2" inputmask="0x40"><!-- LFO 1 --><bounds x="1000" y="109" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL5" inputmask="0x08"><!-- LFO 2 --><bounds x="1036" y="109" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL5" inputmask="0x10"><!-- LFO 3 --><bounds x="1072" y="109" width="20" height="9"/></element>
+
+ <element ref="grey_button" inputtag="COL4" inputmask="0x80"><!-- ENV 1 --><bounds x="982" y="137" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL2" inputmask="0x80"><!-- ENV 2 --><bounds x="1018" y="137" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL5" inputmask="0x80"><!-- ENV 3 --><bounds x="1054" y="137" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL5" inputmask="0x40"><!-- ENV 4 --><bounds x="1090" y="137" width="20" height="9"/></element>
+
+ <element ref="grey_button" inputtag="COL6" inputmask="0x02"><!-- Modes --><bounds x="1132" y="109" width="20" height="9"/></element>
+ <element ref="grey_button" inputtag="COL6" inputmask="0x04"><!-- Split/Layer --><bounds x="1132" y="137" width="20" height="9"/></element>
+
+ <repeat count="5">
+ <param name="n" start="1" increment="1" />
+ <param name="c" start="-227" increment="301" />
+ <param name="cs" start="-201" increment="301" />
+ <param name="d" start="-184" increment="301" />
+ <param name="ds" start="-158" increment="301" />
+ <param name="e" start="-141" increment="301" />
+ <param name="f" start="-98" increment="301" />
+ <param name="fs" start="-72" increment="301" />
+ <param name="g" start="-55" increment="301" />
+ <param name="gs" start="-29" increment="301" />
+ <param name="a" start="-12" increment="301" />
+ <param name="as" start="14" increment="301" />
+ <param name="b" start="31" increment="301" />
+
+ <element ref="black_key" inputtag="INTERNAL_KBD~n~" inputmask="0x002"><!-- C# / Db key --><bounds x="~cs~" y="257" width="27" height="158"/></element>
+ <element ref="black_key" inputtag="INTERNAL_KBD~n~" inputmask="0x008"><!-- D# / Eb key --><bounds x="~ds~" y="257" width="27" height="158"/></element>
+ <element ref="black_key" inputtag="INTERNAL_KBD~n~" inputmask="0x040"><!-- F# / Gb key --><bounds x="~fs~" y="257" width="27" height="158"/></element>
+ <element ref="black_key" inputtag="INTERNAL_KBD~n~" inputmask="0x100"><!-- G# / Ab key --><bounds x="~gs~" y="257" width="27" height="158"/></element>
+ <element ref="black_key" inputtag="INTERNAL_KBD~n~" inputmask="0x400"><!-- A# / Bb key --><bounds x="~as~" y="257" width="27" height="158"/></element>
+
+ <element ref="white_key" inputtag="INTERNAL_KBD~n~" inputmask="0x001"><!-- C key --><bounds x="~c~" y="257" width="39" height="250"/></element>
+ <element ref="white_key" inputtag="INTERNAL_KBD~n~" inputmask="0x004"><!-- D key --><bounds x="~d~" y="257" width="39" height="250"/></element>
+ <element ref="white_key" inputtag="INTERNAL_KBD~n~" inputmask="0x010"><!-- E key --><bounds x="~e~" y="257" width="39" height="250"/></element>
+ <element ref="white_key" inputtag="INTERNAL_KBD~n~" inputmask="0x020"><!-- F key --><bounds x="~f~" y="257" width="39" height="250"/></element>
+ <element ref="white_key" inputtag="INTERNAL_KBD~n~" inputmask="0x080"><!-- G key --><bounds x="~g~" y="257" width="39" height="250"/></element>
+ <element ref="white_key" inputtag="INTERNAL_KBD~n~" inputmask="0x200"><!-- A key --><bounds x="~a~" y="257" width="39" height="250"/></element>
+ <element ref="white_key" inputtag="INTERNAL_KBD~n~" inputmask="0x800"><!-- B key --><bounds x="~b~" y="257" width="39" height="250"/></element>
+
+
+ <!-- Declaring the black keys AGAIN here is a hack!
+ I need to find a better way to let the black keys have precedence over the white ones. -->
+ <element ref="black_key" inputtag="INTERNAL_KBD~n~" inputmask="0x002"><!-- C# / Db key --><bounds x="~cs~" y="257" width="27" height="158"/></element>
+ <element ref="black_key" inputtag="INTERNAL_KBD~n~" inputmask="0x008"><!-- D# / Eb key --><bounds x="~ds~" y="257" width="27" height="158"/></element>
+ <element ref="black_key" inputtag="INTERNAL_KBD~n~" inputmask="0x040"><!-- F# / Gb key --><bounds x="~fs~" y="257" width="27" height="158"/></element>
+ <element ref="black_key" inputtag="INTERNAL_KBD~n~" inputmask="0x100"><!-- G# / Ab key --><bounds x="~gs~" y="257" width="27" height="158"/></element>
+ <element ref="black_key" inputtag="INTERNAL_KBD~n~" inputmask="0x400"><!-- A# / Bb key --><bounds x="~as~" y="257" width="27" height="158"/></element>
+ </repeat>
+
+ <element ref="white_key" inputtag="INTERNAL_KBD6" inputmask="0x001"><!-- C6 key --><bounds x="1278" y="257" width="39" height="250"/></element>
+
+
+<!-- Separators: -->
+ <element ref="white_rect"><bounds x="822" y="59" width="114" height="2"/></element>
+
+ <element ref="white_rect"><bounds x="822" y="101" width="69" height="1"/></element>
+
+
+ <element ref="white_rect"><bounds x="-460" y="162" width="1777" height="3"/></element>
+ <element ref="white_rect"><bounds x="-64" y="163" width="32" height="4"/></element>
+ <element ref="white_rect"><bounds x="22" y="163" width="55" height="4"/></element>
+ <element ref="white_rect"><bounds x="115" y="163" width="70" height="4"/></element>
+ <element ref="white_rect"><bounds x="265" y="163" width="422" height="4"/></element>
+ <element ref="white_rect"><bounds x="822" y="163" width="114" height="4"/></element>
+ <element ref="white_rect"><bounds x="982" y="163" width="170" height="4"/></element>
+ <element ref="white_rect"><bounds x="-460" y="480" width="226" height="3"/></element>
+
+<!-- A few screws: -->
+ <element ref="screw_head"><bounds x="-456" y="-65" width="10" height="10"/></element>
+ <element ref="screw_head"><bounds x="-456" y="200" width="10" height="10"/></element>
+ <element ref="screw_head"><bounds x="1303" y="-65" width="10" height="10"/></element>
+ <element ref="screw_head"><bounds x="1303" y="200" width="10" height="10"/></element>
+ <element ref="screw_head"><bounds x="-454" y="273" width="10" height="10"/></element>
+ <element ref="screw_head"><bounds x="-454" y="476" width="10" height="10"/></element>
+
+
+<!-- Text labels: -->
+
+<!-- Top / rear connection labels: -->
+ <element ref="power_text"><bounds x="-434" y="-73" width="21" height="6"/></element>
+ <element ref="line_text"><bounds x="-352" y="-73" width="12" height="6"/></element>
+ <element ref="fuse_text"><bounds x="-270" y="-73" width="14" height="6"/></element>
+
+ <element ref="sustain_text"><bounds x="340" y="-80" width="24" height="6"/></element>
+ <element ref="ft_sw_text"><bounds x="343" y="-73" width="20" height="6"/></element>
+ <element ref="sequencer_text"><bounds x="380" y="-80" width="36" height="6"/></element>
+ <element ref="ft_sw_text"><bounds x="390" y="-73" width="20" height="6"/></element>
+ <element ref="tape_out_text"><bounds x="431" y="-73" width="29" height="6"/></element>
+ <element ref="tape_in_text"><bounds x="481" y="-73" width="22" height="6"/></element>
+
+ <element ref="midi_in_text"><bounds x="551" y="-73" width="20" height="6"/></element>
+ <element ref="midi_out_text"><bounds x="614" y="-73" width="27" height="6"/></element>
+
+ <element ref="pedal_cv_text"><bounds x="797" y="-73" width="29" height="6"/></element>
+ <element ref="left_mono_rear_text"><bounds x="844" y="-73" width="34" height="6"/></element>
+ <element ref="right_rear_text"><bounds x="898" y="-73" width="18" height="6"/></element>
+ <element ref="white_rect"><bounds x="843" y="-65" width="74" height="1"/></element>
+ <element ref="audio_out_text"><bounds x="863" y="-62" width="34" height="6"/></element>
+
+ <!--<element ref="ensoniq_logo"><bounds x="1089" y="-65" width="129" height="26"/></element>-->
+
+<!-- Left side of the panel: -->
+ <element ref="cartridge_text"><bounds x="-195" y="88" width="67" height="8"/></element>
+
+ <element ref="pitch_text"><bounds x="-388" y="290" width="19" height="8"/></element>
+ <element ref="mod_text"><bounds x="-311" y="290" width="15" height="8"/></element>
+
+<!-- BANKS: -->
+ <element ref="seq_text"><bounds x="24" y="19" width="12" height="6"/></element>
+ <element ref="1_text"><bounds x="66" y="19" width="3" height="6"/></element>
+ <element ref="seq_1_text"><bounds x="59" y="37" width="18" height="6"/></element>
+
+ <element ref="cart_a_text"><bounds x="21" y="56" width="18" height="6"/></element>
+ <element ref="2_text"><bounds x="66" y="56" width="3" height="6"/></element>
+ <element ref="seq_2_text"><bounds x="59" y="74" width="18" height="6"/></element>
+
+ <element ref="cart_b_text"><bounds x="21" y="93" width="18" height="6"/></element>
+ <element ref="3_text"><bounds x="66" y="93" width="3" height="6"/></element>
+ <element ref="seq_3_text"><bounds x="59" y="111" width="18" height="6"/></element>
+
+ <element ref="internal_text"><bounds x="20" y="130" width="21" height="6"/></element>
+ <element ref="4_text"><bounds x="65" y="130" width="4" height="6"/></element>
+ <element ref="song_text"><bounds x="60" y="148" width="15" height="6"/></element>
+
+<!-- DATA ENTRY: -->
+ <element ref="compare_text"><bounds x="113" y="19" width="24" height="6"/></element>
+ <element ref="write_text"><bounds x="162" y="19" width="16" height="6"/></element>
+
+ <!-- up -->
+ <element ref="down_arrow"><orientation rotate="180"/><bounds x="121" y="92" width="9" height="5"/></element>
+ <!-- down -->
+ <element ref="down_arrow"><bounds x="121" y="130" width="9" height="5"/></element>
+
+<!-- SEQUENCER: -->
+ <element ref="master_text"><bounds x="824" y="20" width="19" height="6"/></element>
+ <element ref="storage_text"><bounds x="869" y="20" width="19" height="6"/></element>
+ <element ref="midi_text"><bounds x="918" y="20" width="12" height="6"/></element>
+
+ <element ref="create_erase_text1"><bounds x="823" y="69" width="23" height="6"/></element>
+ <element ref="create_erase_text2"><bounds x="826" y="75" width="16" height="6"/></element>
+ <element ref="edit_text"><bounds x="873" y="75" width="12" height="6"/></element>
+ <element ref="control_text"><bounds x="913" y="75" width="22" height="6"/></element>
+
+ <element ref="tracks_text"><bounds x="846" y="95" width="19" height="6"/></element>
+ <element ref="select_text"><bounds x="825" y="103" width="18" height="6"/></element>
+ <element ref="mix_midi_text"><bounds x="867" y="103" width="24" height="6"/></element>
+ <element ref="locate_text"><bounds x="914" y="103" width="20" height="6"/></element>
+
+ <element ref="record_text"><bounds x="824" y="131" width="20" height="6"/></element>
+ <element ref="stop_cont_text"><bounds x="865" y="131" width="28" height="6"/></element>
+ <element ref="play_text"><bounds x="918" y="131" width="12" height="6"/></element>
+
+<!-- VOICE: -->
+ <element ref="digital_waveform_mem_text1"><bounds x="986" y="5" width="14" height="5"/></element>
+ <element ref="digital_waveform_mem_text2"><bounds x="982" y="9" width="22" height="5"/></element>
+ <element ref="digital_waveform_mem_text3"><bounds x="985" y="13" width="16" height="5"/></element>
+
+ <element ref="osc1_text"><bounds x="984" y="20" width="18" height="6"/></element>
+ <element ref="osc2_text"><bounds x="984" y="48" width="18" height="6"/></element>
+ <element ref="osc3_text"><bounds x="984" y="76" width="18" height="6"/></element>
+
+ <element ref="dca1_text"><bounds x="1037" y="19" width="18" height="6"/></element>
+ <element ref="dca2_text"><bounds x="1037" y="47" width="18" height="6"/></element>
+ <element ref="dca3_text"><bounds x="1037" y="75" width="18" height="6"/></element>
+ <element ref="filter_text"><bounds x="1090" y="47" width="18" height="6"/></element>
+ <element ref="dca4_text"><bounds x="1133" y="47" width="18" height="6"/></element>
+
+ <element ref="lfo1_text"><bounds x="1001" y="102" width="18" height="6"/></element>
+ <element ref="lfo2_text"><bounds x="1037" y="102" width="18" height="6"/></element>
+ <element ref="lfo3_text"><bounds x="1073" y="102" width="18" height="6"/></element>
+
+ <element ref="env1_text"><bounds x="983" y="130" width="18" height="6"/></element>
+ <element ref="env2_text"><bounds x="1019" y="130" width="18" height="6"/></element>
+ <element ref="env3_text"><bounds x="1055" y="130" width="18" height="6"/></element>
+ <element ref="env4_text"><bounds x="1091" y="130" width="18" height="6"/></element>
+
+ <element ref="modes_text"><bounds x="1133" y="102" width="18" height="6"/></element>
+
+ <element ref="split_layer_text1"><bounds x="1133" y="124" width="18" height="6"/></element>
+ <element ref="split_layer_text2"><bounds x="1133" y="130" width="18" height="6"/></element>
+
+ <element ref="esq1_logo"><bounds x="-410" y="119" width="153" height="40"/></element>
+ <element ref="dwsynth_title"><bounds x="-412" y="169" width="154" height="16"/></element>
+ <element ref="volume_title"><bounds x="-62" y="169" width="28" height="8"/></element>
+ <element ref="banks_title"><bounds x="38" y="169" width="22" height="8"/></element>
+ <element ref="data_entry_title"><bounds x="130" y="169" width="41" height="8"/></element>
+ <element ref="programmer_title"><bounds x="453" y="169" width="48" height="8"/></element>
+ <element ref="sequencer_title"><bounds x="859" y="169" width="42" height="9"/></element>
+ <element ref="voice_title"><bounds x="1057" y="169" width="23" height="8"/></element>
+ </group>
+
+ <view name="Default Layout">
+ <bounds left="0" right="1280" y="-100" height="640"/>
+
+ <group ref="full"><bounds x="-495" y="-100" width="1843" height="640"/></group>
+ </view>
+
+ <view name="Full Unit">
+ <group ref="full"><bounds x="-495" y="-100" width="1843" height="640"/></group>
+ </view>
+
+ <view name="VFD close-up">
+ <bounds x="0" y="-100" width="700" height="400"/>
+
+ <group ref="full"><bounds x="-495" y="-100" width="1843" height="640"/></group>
+ </view>
+
+ <view name="Sequencer and Voice">
+ <bounds x="780" y="-100" width="520" height="400"/>
+
+ <group ref="full"><bounds x="-495" y="-100" width="1843" height="640"/></group>
+ </view>
+
+ <script><![CDATA[
+ file:set_resolve_tags_callback(
+ function()
+ for view_name, view in pairs(file.views) do
+ install_slider_callbacks(view)
+
+ add_vertical_slider(view, "slider_volume", "slider_knob_volume", "volume_slider")
+ add_vertical_slider(view, "slider_data_entry", "slider_knob_data_entry", "data_entry_slider")
+ add_vertical_slider(view, "slider_pitch_wheel", "slider_knob_pitch_wheel", "pitch_wheel")
+ add_vertical_slider(view, "slider_mod_wheel", "slider_knob_mod_wheel", "mod_wheel")
+
+ -- TODO: Display a warning about how to enable sliders
+ -- view.items["warning"]:set_state(0)
+ end
+ end)
+
+ -----------------------------------------------------------------------
+ -- Slider library starts.
+ -- Can be copied as-is to other layouts.
+ -----------------------------------------------------------------------
+ local sliders = {} -- Stores slider information.
+ local pointers = {} -- Tracks pointer state.
+
+ -- The knob's Y position must be animated using <animate inputtag="{port_name}">.
+ -- The click area's vertical size must exactly span the range of the
+ -- knob's movement.
+ function add_vertical_slider(view, clickarea_id, knob_id, port_name)
+ local slider = {}
+
+ slider.clickarea = view.items[clickarea_id]
+ if slider.clickarea == nil then
+ emu.print_error("Slider element: '" .. clickarea_id .. "' not found.")
+ return
+ end
+
+ slider.knob = view.items[knob_id]
+ if slider.knob == nil then
+ emu.print_error("Slider knob element: '" .. knob_id .. "' not found.")
+ return
+ end
+
+ local port = file.device:ioport(port_name)
+ if port == nil then
+ emu.print_error("Port: '" .. port_name .. "' not found.")
+ return
+ end
+
+ slider.field = nil
+ for k, val in pairs(port.fields) do
+ slider.field = val
+ break
+ end
+ if slider.field == nil then
+ emu.print_error("Port: '" .. port_name .."' does not seem to be an IPT_ADJUSTER.")
+ return
+ end
+
+ table.insert(sliders, slider)
+ end
+
+ local function pointer_updated(type, id, dev, x, y, btn, dn, up, cnt)
+ -- If a button is not pressed, reset the state of the current pointer.
+ if btn & 1 == 0 then
+ pointers[id] = nil
+ return
+ end
+
+ -- If a button was just pressed, find the affected slider, if any.
+ if dn & 1 ~= 0 then
+ for i = 1, #sliders do
+ if sliders[i].knob.bounds:includes(x, y) then
+ pointers[id] = {
+ selected_slider = i,
+ relative = true,
+ start_y = y,
+ start_value = sliders[i].field.user_value }
+ break
+ elseif sliders[i].clickarea.bounds:includes(x, y) then
+ pointers[id] = {
+ selected_slider = i,
+ relative = false }
+ break
+ end
+ end
+ end
+
+ -- If there is no slider selected by the current pointer, we are done.
+ if pointers[id] == nil then
+ return
+ end
+
+ -- A slider is selected. Update state and, indirectly, slider knob position,
+ -- based on the pointer's Y position. It is assumed the attached IO field is
+ -- an IPT_ADJUSTER with a range of 0-100 (the default).
+
+ local pointer = pointers[id]
+ local slider = sliders[pointer.selected_slider]
+
+ local knob_half_height = slider.knob.bounds.height / 2
+ local min_y = slider.clickarea.bounds.y0 + knob_half_height
+ local max_y = slider.clickarea.bounds.y1 - knob_half_height
+
+ local new_value = 0
+ if pointer.relative then
+ -- User clicked on the knob. The new value will depend on how much the
+ -- knob was dragged.
+ new_value = pointer.start_value - 100 * (y - pointer.start_y) / (max_y - min_y)
+ else
+ -- User clicked elsewhere on the slider. The new value will depend on
+ -- the absolute position of the click.
+ new_value = 100 - 100 * (y - min_y) / (max_y - min_y)
+ end
+
+ new_value = math.floor(new_value + 0.5)
+ if new_value < 0 then new_value = 0 end
+ if new_value > 100 then new_value = 100 end
+ slider.field.user_value = new_value
+ end
+
+ local function pointer_left(type, id, dev, x, y, up, cnt)
+ pointers[id] = nil
+ end
+
+ local function pointer_aborted(type, id, dev, x, y, up, cnt)
+ pointers[id] = nil
+ end
+
+ local function forget_pointers()
+ pointers = {}
+ end
+
+ function install_slider_callbacks(view)
+ view:set_pointer_updated_callback(pointer_updated)
+ view:set_pointer_left_callback(pointer_left)
+ view:set_pointer_aborted_callback(pointer_aborted)
+ view:set_forget_pointers_callback(forget_pointers)
+ end
+ -----------------------------------------------------------------------
+ -- Slider library ends.
+ -----------------------------------------------------------------------
+ ]]></script>
+
+</mamelayout>
diff --git a/src/mame/layout/esq2by40.lay b/src/mame/layout/esq2by40.lay
index 2c6b664731c..0dabaa910fa 100644
--- a/src/mame/layout/esq2by40.lay
+++ b/src/mame/layout/esq2by40.lay
@@ -6,24 +6,36 @@ license:CC0-1.0
<mamelayout version="2">
- <element name="vfd0" defstate="0">
+ <element name="vfd" defstate="0">
<led14segsc>
<color red="0.45" green="1.0" blue="0.95" />
</led14segsc>
</element>
+ <element name="underline" defstate="0">
+ <rect state="0"><color red="0.06" green="0.12" blue="0.10" /></rect>
+ <rect state="1"><color red="0.45" green="1.00" blue="0.95" /></rect>
+ </element>
+
<view name="Default Layout">
<!-- VFDs -->
<repeat count="2">
<param name="s" start="0" increment="40" />
- <param name="y" start="0" increment="24" />
+ <param name="su" start="80" increment="40" />
+ <param name="y" start="0" increment="34" />
+ <param name="yu" start="26" increment="34" />
<repeat count="40">
<param name="n" start="~s~" increment="1" />
+ <param name="u" start="~su~" increment="1" />
<param name="x" start="0" increment="19" />
- <element name="vfd~n~" ref="vfd0">
+ <param name="xu" start="2" increment="19" />
+ <element name="vfd~n~" ref="vfd">
<bounds x="~x~" y="~y~" width="18" height="23" />
</element>
+ <element name="vfd~u~" ref="underline">
+ <bounds x="~xu~" y="~yu~" width="14" height="2" />
+ </element>
</repeat>
</repeat>
</view>