diff options
author | 2022-09-28 20:17:23 +0200 | |
---|---|---|
committer | 2022-09-28 20:17:23 +0200 | |
commit | 6394b12986f59426597899461c09795679b7dbda (patch) | |
tree | b3901013267d1808109a028460fa7fe5ee351c86 /src/mame | |
parent | f9870d6f020b55991aa1838bca70fd5379b0cefc (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/mame')
-rw-r--r-- | src/mame/casio/rz1.cpp | 238 | ||||
-rw-r--r-- | src/mame/layout/rz1.lay | 45 |
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"> |