summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Dirk Best <mail@dirk-best.de>2022-09-28 20:17:23 +0200
committer Dirk Best <mail@dirk-best.de>2022-09-28 20:17:23 +0200
commit6394b12986f59426597899461c09795679b7dbda (patch)
treeb3901013267d1808109a028460fa7fe5ee351c86 /src
parentf9870d6f020b55991aa1838bca70fd5379b0cefc (diff)
rz1: Improve emulation
- Add MT (magnetic tape) support to load and save rythm and sample data. Supports raw .wav files as well as .cas files (same format as TRS-80 Model 3). - Add a line-in port to support sampling. Currently uses a cassette drive: You can sample .wav files. - Add NVRAM for data and samples - Improve layout and add support for the sampling LED - Add software list for audio (the official RZ-1 Sound Collection tape) and data tapes (homebrew files) - Update notes and small cleanups
Diffstat (limited to 'src')
-rw-r--r--src/mame/casio/rz1.cpp238
-rw-r--r--src/mame/layout/rz1.lay45
2 files changed, 205 insertions, 78 deletions
diff --git a/src/mame/casio/rz1.cpp b/src/mame/casio/rz1.cpp
index 2bd594b568b..0f0a50d0b82 100644
--- a/src/mame/casio/rz1.cpp
+++ b/src/mame/casio/rz1.cpp
@@ -6,38 +6,46 @@
Sampling drum machine
- Sound ROM info:
-
- Each ROM chip holds 1.49s of sounds and can be opened as raw
- PCM data: signed 8-bit, mono, 20,000 Hz.
-
- * Sound A: Toms 1~3, Kick, Snare, Rimshot, Closed Hi-Hat, Open Hi-Hat,
- and Metronome Click (in that order).
-
- * Sound B: Clap, Ride, Cowbell, and Crash (in that order).
-
- Note: Holding EDIT/RECORD, DELETE, INSERT/AUTO-COMPENSATE and
- CHAIN/BEAT at startup causes the system to go into a RAM test.
+ Hardware:
+ - uPD7811G-120
+ - HN4872128G25 (program rom)
+ - uPD4364C (data ram, battery backed)
+ - 2x uPD934G (percussion generator)
+ - 2x HN613256P (sample rom)
+ - 2x uPD4364C-15L (sample ram, battery backed)
+ - EXK-F19Z2064 (10-bit DAC)
+
+ Notes:
+ - Each sample ROM holds 1.49s of sounds in the following format:
+ PCM data, signed 8-bit, mono, 20,000 Hz
+ - Holding EDIT/RECORD, DELETE, INSERT/AUTO-COMPENSATE and
+ CHAIN/BEAT at startup causes the system to go into a RAM test.
TODO:
- Metronome
- MIDI
- - Cassette
- - Audio input
+ - Make audio input generic (core support needed)
***************************************************************************/
#include "emu.h"
-#include "emupal.h"
-#include "screen.h"
#include "cpu/upd7810/upd7811.h"
-#include "video/hd44780.h"
+#include "formats/trs_cas.h"
+#include "imagedev/cassette.h"
+#include "machine/nvram.h"
#include "sound/upd934g.h"
+#include "video/hd44780.h"
+#include "emupal.h"
+#include "screen.h"
+#include "softlist_dev.h"
#include "speaker.h"
#include "rz1.lh"
+namespace {
+
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -50,8 +58,11 @@ public:
m_maincpu(*this, "maincpu"),
m_hd44780(*this, "hd44780"),
m_pg{ {*this, "upd934g_c"}, {*this, "upd934g_b"} },
+ m_cassette(*this, "cassette"),
+ m_linein(*this, "linein"),
m_samples{ {*this, "samples_a"}, {*this, "samples_b"} },
m_keys(*this, "kc%u", 0),
+ m_led_sampling(*this, "led_sampling"),
m_led_song(*this, "led_song"),
m_led_pattern(*this, "led_pattern"),
m_led_startstop(*this, "led_startstop"),
@@ -61,9 +72,6 @@ public:
void rz1(machine_config &config);
- void rz1_palette(palette_device &palette) const;
- HD44780_PIXEL_UPDATE(lcd_pixel_update);
-
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
@@ -72,27 +80,35 @@ private:
required_device<upd7811_device> m_maincpu;
required_device<hd44780_device> m_hd44780;
required_device<upd934g_device> m_pg[2];
+ required_device<cassette_image_device> m_cassette;
+ required_device<cassette_image_device> m_linein;
required_memory_region m_samples[2];
required_ioport_array<8> m_keys;
+ output_finder<> m_led_sampling;
output_finder<> m_led_song;
output_finder<> m_led_pattern;
output_finder<> m_led_startstop;
void map(address_map &map);
- uint8_t port_a_r();
- void port_a_w(uint8_t data);
- void port_b_w(uint8_t data);
- uint8_t port_c_r();
- void port_c_w(uint8_t data);
+ uint8_t key_r();
+
+ void rz1_palette(palette_device &palette) const;
+ HD44780_PIXEL_UPDATE(lcd_pixel_update);
+ void leds_w(uint8_t data);
uint8_t upd934g_c_data_r(offs_t offset);
void upd934g_c_w(offs_t offset, uint8_t data);
uint8_t upd934g_b_data_r(offs_t offset);
void upd934g_b_w(offs_t offset, uint8_t data);
- uint8_t key_r();
- void leds_w(uint8_t data);
+ uint8_t analog_r();
+
+ uint8_t port_a_r();
+ void port_a_w(uint8_t data);
+ void port_b_w(uint8_t data);
+ uint8_t port_c_r();
+ void port_c_w(uint8_t data);
uint8_t m_port_a;
uint8_t m_port_b;
@@ -106,12 +122,12 @@ private:
void rz1_state::map(address_map &map)
{
// map(0x0000, 0x0fff).rom().region("maincpu", 0);
- map(0x2000, 0x3fff).ram();
+ map(0x2000, 0x3fff).ram().share("dataram");
map(0x4000, 0x7fff).rom().region("program", 0);
map(0x8000, 0x8fff).w(FUNC(rz1_state::upd934g_c_w));
map(0x9000, 0x9fff).rw(FUNC(rz1_state::key_r), FUNC(rz1_state::upd934g_b_w));
- map(0xa000, 0xbfff).ram(); // sample ram 1
- map(0xc000, 0xdfff).ram(); // sample ram 2
+ map(0xa000, 0xbfff).ram().share("sample1");
+ map(0xc000, 0xdfff).ram().share("sample2");
map(0xe000, 0xe001).w(FUNC(rz1_state::leds_w));
}
@@ -196,8 +212,31 @@ INPUT_PORTS_END
//**************************************************************************
-// MACHINE EMULATION
+// KEYBOARD
+//**************************************************************************
+
+uint8_t rz1_state::key_r()
+{
+ uint8_t data = 0;
+
+ for (int i = 0; i < 8; i++)
+ if (BIT(m_port_a, i) == 0)
+ data |= m_keys[i]->read();
+
+ return data;
+}
+
+
//**************************************************************************
+// VIDEO EMULATION
+//**************************************************************************
+
+void rz1_state::rz1_palette(palette_device &palette) const
+{
+ palette.set_pen_color(0, rgb_t(138, 146, 148)); // background
+ palette.set_pen_color(1, rgb_t(92, 83, 88)); // lcd pixel on
+ palette.set_pen_color(2, rgb_t(131, 136, 139)); // lcd pixel off
+}
HD44780_PIXEL_UPDATE( rz1_state::lcd_pixel_update )
{
@@ -209,6 +248,27 @@ HD44780_PIXEL_UPDATE( rz1_state::lcd_pixel_update )
bitmap.pix(1 + y, 1 + line*8*6 + pos*6 + x) = state ? 1 : 2;
}
+void rz1_state::leds_w(uint8_t data)
+{
+ // 76------ unknown
+ // --5----- sampling led
+ // ---4---- start/stop led
+ // ----3--- pattern led red
+ // -----2-- pattern led green
+ // ------1- song led red
+ // -------0 song led green
+
+ m_led_song = BIT(~data, 0, 2);
+ m_led_pattern = BIT(~data, 2, 2);
+ m_led_startstop = BIT(~data, 4);
+ m_led_sampling = BIT(~data, 5);
+}
+
+
+//**************************************************************************
+// AUDIO EMULATION
+//**************************************************************************
+
uint8_t rz1_state::upd934g_c_data_r(offs_t offset)
{
if (offset < 0x8000)
@@ -240,6 +300,16 @@ void rz1_state::upd934g_b_w(offs_t offset, uint8_t data)
m_pg[1]->write(offset >> 8, data);
}
+uint8_t rz1_state::analog_r()
+{
+ return uint8_t(int8_t(m_linein->input() * 127.0) + 127);
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
uint8_t rz1_state::port_a_r()
{
if ((BIT(m_port_b, 7) == 0) && (BIT(m_port_b, 6) == 1))
@@ -260,68 +330,53 @@ void rz1_state::port_a_w(uint8_t data)
m_hd44780->write(BIT(m_port_b, 5), data);
}
-// 7------- lcd e
-// -6------ lcd rw
-// --5----- lcd rs
-// ---4---- percussion generator reset
-// ----3--- metronome trigger
-// -----2-- power-on mute for line-out
-// ------1- change-over signal tom3/bd
-// -------0 change-over signal tom1/tom2
-
void rz1_state::port_b_w(uint8_t data)
{
+ // 7------- lcd e
+ // -6------ lcd rw
+ // --5----- lcd rs
+ // ---4---- percussion generator reset
+ // ----3--- metronome trigger
+ // -----2-- power-on mute for line-out
+ // ------1- change-over signal tom3/bd
+ // -------0 change-over signal tom1/tom2
+
if (0)
logerror("port_b_w: %02x\n", data);
m_port_b = data;
}
-// 7------- foot-sustain input
-// -6------ cassette data out
-// --5----- cassette remote control
-// ---4---- change-over signal for sampling ram
-// ----3--- cassette data in
-// -----2-- control signal for percussion generator c
-// ------1- midi in
-// -------0 midi out
-
uint8_t rz1_state::port_c_r()
{
- return 0;
-}
-
-void rz1_state::port_c_w(uint8_t data)
-{
- logerror("port_c_w: %02x\n", data);
-}
+ // 7------- foot-sustain input
+ // -6------ cassette data out
+ // --5----- cassette remote control
+ // ---4---- change-over signal for sampling ram
+ // ----3--- cassette data in
+ // -----2-- control signal for percussion generator c
+ // ------1- midi in
+ // -------0 midi out
-uint8_t rz1_state::key_r()
-{
uint8_t data = 0;
- if (BIT(m_port_a, 0) == 0) data |= m_keys[0]->read();
- if (BIT(m_port_a, 1) == 0) data |= m_keys[1]->read();
- if (BIT(m_port_a, 2) == 0) data |= m_keys[2]->read();
- if (BIT(m_port_a, 3) == 0) data |= m_keys[3]->read();
- if (BIT(m_port_a, 4) == 0) data |= m_keys[4]->read();
- if (BIT(m_port_a, 5) == 0) data |= m_keys[5]->read();
- if (BIT(m_port_a, 6) == 0) data |= m_keys[6]->read();
- if (BIT(m_port_a, 7) == 0) data |= m_keys[7]->read();
+ data |= (m_cassette->input() > 0 ? 0 : 1) << 3;
return data;
}
-void rz1_state::leds_w(uint8_t data)
+void rz1_state::port_c_w(uint8_t data)
{
- m_led_song = BIT(data, 0) == 0 ? 1 : BIT(data, 1) == 0 ? 2 : 0;
- m_led_pattern = BIT(data, 2) == 0 ? 1 : BIT(data, 3) == 0 ? 2 : 0;
- m_led_startstop = BIT(data, 4) == 0 ? 1 : 0;
+ m_cassette->change_state(BIT(data, 5) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
+ m_cassette->output(BIT(data, 6) ? -1.0 : 1.0);
+
+ logerror("port_c_w: %02x\n", data);
}
void rz1_state::machine_start()
{
// resolve output finders
+ m_led_sampling.resolve();
m_led_song.resolve();
m_led_pattern.resolve();
m_led_startstop.resolve();
@@ -335,12 +390,6 @@ void rz1_state::machine_reset()
{
}
-void rz1_state::rz1_palette(palette_device &palette) const
-{
- palette.set_pen_color(0, rgb_t(138, 146, 148)); // background
- palette.set_pen_color(1, rgb_t(92, 83, 88)); // lcd pixel on
- palette.set_pen_color(2, rgb_t(131, 136, 139)); // lcd pixel off
-}
//**************************************************************************
// MACHINE DEFINTIONS
@@ -355,6 +404,18 @@ void rz1_state::rz1(machine_config &config)
m_maincpu->pb_out_cb().set(FUNC(rz1_state::port_b_w));
m_maincpu->pc_in_cb().set(FUNC(rz1_state::port_c_r));
m_maincpu->pc_out_cb().set(FUNC(rz1_state::port_c_w));
+ m_maincpu->an0_func().set(FUNC(rz1_state::analog_r));
+ m_maincpu->an1_func().set(FUNC(rz1_state::analog_r));
+ m_maincpu->an2_func().set(FUNC(rz1_state::analog_r));
+ m_maincpu->an3_func().set(FUNC(rz1_state::analog_r));
+ m_maincpu->an4_func().set(FUNC(rz1_state::analog_r));
+ m_maincpu->an5_func().set(FUNC(rz1_state::analog_r));
+ m_maincpu->an6_func().set(FUNC(rz1_state::analog_r));
+ m_maincpu->an7_func().set(FUNC(rz1_state::analog_r));
+
+ NVRAM(config, "dataram", nvram_device::DEFAULT_NONE);
+ NVRAM(config, "sample1", nvram_device::DEFAULT_NONE);
+ NVRAM(config, "sample2", nvram_device::DEFAULT_NONE);
// video hardware
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
@@ -373,6 +434,7 @@ void rz1_state::rz1(machine_config &config)
config.set_default_layout(layout_rz1);
+ // audio hardware
SPEAKER(config, "speaker").front_center();
UPD934G(config, m_pg[0], 1333000);
m_pg[0]->data_callback().set(FUNC(rz1_state::upd934g_c_data_r));
@@ -380,6 +442,21 @@ void rz1_state::rz1(machine_config &config)
UPD934G(config, m_pg[1], 1280000);
m_pg[1]->data_callback().set(FUNC(rz1_state::upd934g_b_data_r));
m_pg[1]->add_route(ALL_OUTPUTS, "speaker", 1.0);
+
+ // mt (magnetic tape)
+ CASSETTE(config, m_cassette);
+ m_cassette->set_formats(trs80l2_cassette_formats);
+ m_cassette->set_default_state(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_ENABLED);
+ m_cassette->set_interface("rz1_cass");
+ m_cassette->add_route(ALL_OUTPUTS, "speaker", 0.05);
+
+ // should be a generic audio input port, using cassette for now
+ CASSETTE(config, m_linein);
+ m_linein->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
+ m_linein->set_interface("audio_cass");
+ m_linein->add_route(ALL_OUTPUTS, "speaker", 0.05);
+
+ SOFTWARE_LIST(config, "cass_list").set_original("rz1_cass");
}
@@ -394,14 +471,19 @@ ROM_START( rz1 )
ROM_REGION(0x4000, "program", 0)
ROM_LOAD("program.bin", 0x0000, 0x4000, CRC(b44b2652) SHA1(b77f8daece9adb177b6ce1ef518fc3238b8c0a9c))
+ // Toms 1~3, Kick, Snare, Rimshot, Closed Hi-Hat, Open Hi-Hat and Metronome Click
ROM_REGION(0x8000, "samples_a", 0)
- ROM_LOAD("sound_a.cm5", 0x0000, 0x8000, CRC(c643ff24) SHA1(e886314d22a9a5473bfa2cb237ecafcf0daedfc1)) // HN613256P
+ ROM_LOAD("sound_a.cm5", 0x0000, 0x8000, CRC(c643ff24) SHA1(e886314d22a9a5473bfa2cb237ecafcf0daedfc1))
+ // Clap, Ride, Cowbell and Crash
ROM_REGION(0x8000, "samples_b", 0)
- ROM_LOAD("sound_b.cm6", 0x0000, 0x8000, CRC(ee5b703e) SHA1(cbf2e92c68901f236678d704e9e695a5c84ff49e)) // HN613256P
+ ROM_LOAD("sound_b.cm6", 0x0000, 0x8000, CRC(ee5b703e) SHA1(cbf2e92c68901f236678d704e9e695a5c84ff49e))
ROM_END
+} // anonymous namespace
+
+
//**************************************************************************
// SYSTEM DRIVERS
//**************************************************************************
diff --git a/src/mame/layout/rz1.lay b/src/mame/layout/rz1.lay
index eefbc3697a4..56066e281c8 100644
--- a/src/mame/layout/rz1.lay
+++ b/src/mame/layout/rz1.lay
@@ -50,6 +50,15 @@ Casio RZ-1 layout
</rect>
</element>
+ <element name="led_red" defstate="0">
+ <rect state="0">
+ <color red="0.05" green="0.05" blue="0.05" />
+ </rect>
+ <rect state="1">
+ <color red="0.8" green="0.05" blue="0.05" />
+ </rect>
+ </element>
+
<element name="text_0"><text string="0"><color red="0.15" green="0.11" blue="0.11" /></text></element>
<element name="text_1"><text string="1"><color red="0.15" green="0.11" blue="0.11" /></text></element>
<element name="text_2"><text string="2"><color red="0.15" green="0.11" blue="0.11" /></text></element>
@@ -64,6 +73,10 @@ Casio RZ-1 layout
<element name="text_casio"><text string="CASIO"><color red="0.98" green="0.95" blue="0.89" /></text></element>
<element name="text_desc"><text string="DIGITAL SAMPLING RHYTHM COMPOSER"><color red="0.29" green="0.74" blue="0.68" /></text></element>
<element name="text_rz1"><text string="RZ-1"><color red="0.29" green="0.74" blue="0.68" /></text></element>
+ <element name="text_instrument_level"><text string="INSTRUMENT LEVEL"><color red="0.98" green="0.95" blue="0.89" /></text></element>
+ <element name="text_sampling_white"><text string="SAMPLING"><color red="0.98" green="0.95" blue="0.89" /></text></element>
+ <element name="text_level"><text string="LEVEL"><color red="0.98" green="0.95" blue="0.89" /></text></element>
+ <element name="text_volume"><text string="VOLUME"><color red="0.98" green="0.95" blue="0.89" /></text></element>
<element name="text_song"><text string="SONG"><color red="0.98" green="0.95" blue="0.89" /></text></element>
<element name="text_pattern"><text string="PATTERN"><color red="0.98" green="0.95" blue="0.89" /></text></element>
<element name="text_edit"><text string="EDIT"><color red="0.98" green="0.95" blue="0.89" /></text></element>
@@ -224,6 +237,13 @@ Casio RZ-1 layout
</screen>
<collection name="Controls">
+
+ <!-- sampling led -->
+
+ <element name="led_sampling" ref="led_red">
+ <bounds x="526" y="35" width="9" height="4" />
+ </element>
+
<!-- logo and text top right -->
<element ref="text_casio">
@@ -236,6 +256,31 @@ Casio RZ-1 layout
<bounds x="665" y="134" width="59" height="24" />
</element>
+ <!-- dial labels -->
+
+ <element ref="text_instrument_level">
+ <bounds x="53" y="168" width="378" height="7" />
+ </element>
+ <element ref="teal">
+ <bounds x="53" y="177" width="378" height="1" />
+ </element>
+
+ <element ref="text_sampling_white">
+ <bounds x="502" y="160" width="56" height="7" />
+ </element>
+ <element ref="text_level">
+ <bounds x="502" y="168" width="56" height="7" />
+ </element>
+ <element ref="teal">
+ <bounds x="502" y="177" width="56" height="1" />
+ </element>
+ <element ref="text_volume">
+ <bounds x="560" y="168" width="56" height="7" />
+ </element>
+ <element ref="teal">
+ <bounds x="560" y="177" width="56" height="1" />
+ </element>
+
<!-- separator -->
<element name="sep1a" ref="darkgray">