CM-32P: support PCM cards, add U-110 card softlist

This commit is contained in:
Valley Bell 2021-04-17 16:27:23 +02:00
parent 94f4c477bc
commit 6f57613198
2 changed files with 288 additions and 15 deletions

199
hash/u110_card.xml Normal file
View File

@ -0,0 +1,199 @@
<?xml version="1.0"?>
<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
<!--
license:CC0
Undumped cards:
- all Rhodes SN-U01-xxR cards
- Roland SN-SPLA-01/03
- Musitronics 2 Voices (U-22)
- Musitronics 5 Eldek (U-21)
- Musitronics 6 Analog Synthesizer (U-20)
-> see https://www.playkeyboardnow.com/Roland_D70_Soundbanks/page63/index.html
Release dates were taken from http://www.rolandmuseum.de/z_syn_wc.php
-->
<softwarelist name="u110_card" description="Roland U-110 PCM memory cards">
<software name="mus1-akk">
<description>Musitronics 1 Akkordeon (U-25)</description>
<year>199x</year>
<publisher>musitronics GmbH</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<!-- Note: The current dump is an overdump due to how address scrambling works. The internal ROM appears to be only 64K. -->
<rom name="musitronics_akkordeon.bin" size="0x20000" crc="69e41a1b" sha1="2931181ad60372461e82491a014cb118c68605d8"/>
</dataarea>
</part>
</software>
<software name="sn-mv30-01">
<description>SN-MV30-01 Rhythm Section (U-31)</description>
<year>1991</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-mv30-01.bin" size="0x80000" crc="9b571919" sha1="873afbac7b1fcd45128952152dc090de48b765c6"/>
</dataarea>
</part>
</software>
<software name="sn-mv30-02">
<description>SN-MV30-02 Orchestral (U-30)</description>
<year>1991</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-mv30-02.bin" size="0x80000" crc="596254dc" sha1="1081973aad7ad5941329d3ab8a20db654c063a2e"/>
</dataarea>
</part>
</software>
<software name="sn-u110-01">
<description>SN-U110-01 Pipe Organ &amp; Harpsichord</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-01.bin" size="0x80000" crc="71fec2e0" sha1="42440bcf0e025dad9182de0a3231f0e00c3a149d"/>
</dataarea>
</part>
</software>
<software name="sn-u110-02">
<description>SN-U110-02 Latin &amp; F.X. Percussions</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-02.bin" size="0x80000" crc="335a67cb" sha1="3e1c2fd64c59474426aa8717eb03240bb8b69730"/>
</dataarea>
</part>
</software>
<software name="sn-u110-03">
<description>SN-U110-03 Ethnic</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-03.bin" size="0x80000" crc="20a010db" sha1="2d33603fe3217d44d28aec284216581e581a9981"/>
</dataarea>
</part>
</software>
<software name="sn-u110-04">
<description>SN-U110-04 Electric Grand &amp; Clavi</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-04.bin" size="0x80000" crc="2653ac2b" sha1="e856625e9efac8ee4026696f46aad4015fb3c097"/>
</dataarea>
</part>
</software>
<software name="sn-u110-05">
<description>SN-U110-05 Orchestral Strings</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-05.bin" size="0x80000" crc="712aa669" sha1="9d67bd73848c1b6c4a9543b8f4abb5794ac2f951"/>
</dataarea>
</part>
</software>
<software name="sn-u110-06">
<description>SN-U110-06 Orchestral Winds</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-06.bin" size="0x80000" crc="5725360d" sha1="d5a8beece04b6da27c6a6b3bddc808c757168a28"/>
</dataarea>
</part>
</software>
<software name="sn-u110-07">
<description>SN-U110-07 Electric Guitar</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-07.bin" size="0x80000" crc="7a6319c2" sha1="fdcb923b986805e3671fb0962804315d8287cba5"/>
</dataarea>
</part>
</software>
<software name="sn-u110-08">
<description>SN-U110-08 Synthesizer</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-08.bin" size="0x80000" crc="fef365d2" sha1="ad3ea185cac7d938a9f7fe17d80cab32881e05d7"/>
</dataarea>
</part>
</software>
<software name="sn-u110-09">
<description>SN-U110-09 Guitar &amp; Keyboards</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-09.bin" size="0x80000" crc="28b03851" sha1="54d07e1b49eedd0f5339999dc0f4690134849f31"/>
</dataarea>
</part>
</software>
<software name="sn-u110-10">
<description>SN-U110-10 Rock Drums</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-10.bin" size="0x80000" crc="7611196a" sha1="056344e4908c2fbde98f77b4d1f5c198c62333e7"/>
</dataarea>
</part>
</software>
<software name="sn-u110-11">
<description>SN-U110-11 Sound Effects</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-11.bin" size="0x80000" crc="57e50aa1" sha1="c15071da567204c84d1a0ae35961caa84ebfa2fc"/>
</dataarea>
</part>
</software>
<software name="sn-u110-12">
<description>SN-U110-12 Sax &amp; Trombone</description>
<year>1989</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-12.bin" size="0x80000" crc="4f925426" sha1="c36fb83e720c3bd55d21959927fa616c92105bbc"/>
</dataarea>
</part>
</software>
<software name="sn-u110-13">
<description>SN-U110-13 Super Strings</description>
<year>1992</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-13.bin" size="0x80000" crc="b26fd0b4" sha1="e332d1dd5f0ebf5284501540fdbcc1488e8ef828"/>
</dataarea>
</part>
</software>
<software name="sn-u110-14">
<description>SN-U110-14 Super Ac Guitar</description>
<year>1992</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-14.bin" size="0x80000" crc="7143045d" sha1="b540bd0db7eb2c0914c7cfb5e98ac8c85bd868aa"/>
</dataarea>
</part>
</software>
<software name="sn-u110-15">
<description>SN-U110-15 Super Brass</description>
<year>1992</year>
<publisher>Roland</publisher>
<part name="card" interface="u110_card">
<dataarea name="rom" size="0x80000">
<rom name="sn-u110-15.bin" size="0x80000" crc="4e215a4d" sha1="10ad202551632118c5e3bdfb06e6613079217ce9"/>
</dataarea>
</part>
</software>
</softwarelist>

View File

@ -39,7 +39,6 @@ Notes:
TODO:
- figure out how "freeing a voice" works - right now the firmware gets stuck when playing the 32th note.
- add PCM card support
PCB Layout
@ -231,18 +230,24 @@ Some routine locations
#include "machine/timer.h"
#include "sound/rolandpcm.h"
#include "video/msm6222b.h"
#include "bus/generic/slot.h"
#include "bus/generic/carts.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
// unscramble address: ROM dump offset -> proper (descrambled) offset
#define UNSCRAMBLE_ADDRESS(_offset) \
#define UNSCRAMBLE_ADDR_INT(_offset) \
bitswap<19>(_offset,18,17,15,14,16,12,11, 7, 9,13,10, 8, 3, 2, 1, 6, 4, 5, 0)
// scramble address: proper offset -> ROM dump offset
#define SCRAMBLE_ADDRESS(_offset) \
#define SCRAMBLE_ADDR_INT(_offset) \
bitswap<19>(_offset,18,17,14,16,15, 9,13,12, 8,10, 7,11, 3, 1, 2, 6, 5, 4, 0)
// PCM cards use a different address line scrambling
#define UNSCRAMBLE_ADDR_EXT(_offset) \
bitswap<19>(_offset,18,17, 8, 9,16,11,12, 7,14,10,13,15, 3, 2, 1, 6, 4, 5, 0)
#define UNSCRAMBLE_DATA(_data) \
bitswap<8>(_data,1,2,7,3,5,0,4,6)
@ -254,7 +259,7 @@ static INPUT_PORTS_START( cm32p )
PORT_START("SERVICE") // connected to Port 0 of the P8098 CPU.
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Test Switch") PORT_TOGGLE PORT_CODE(KEYCODE_F2) // SW A (checked during boot)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Test: Check/Tune") PORT_CODE(KEYCODE_B) // SW B
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("PCM card inserted") PORT_TOGGLE PORT_CODE(KEYCODE_C)
//PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("PCM card inserted") PORT_TOGGLE PORT_CODE(KEYCODE_C)
PORT_START("SW") // test switches, accessed by reading from address 0x1300
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Test: MSB Adj.") PORT_CODE(KEYCODE_1) // SW 1
@ -283,6 +288,7 @@ protected:
private:
required_device<i8x9x_device> cpu;
required_device<mb87419_mb87420_device> pcm;
required_device<generic_slot_device> pcmcard;
required_device<msm6222b_device> lcd;
required_device<timer_device> midi_timer;
required_device<ram_device> some_ram;
@ -309,8 +315,15 @@ private:
TIMER_DEVICE_CALLBACK_MEMBER(midi_timer_cb);
TIMER_DEVICE_CALLBACK_MEMBER(samples_timer_cb);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(card_load);
DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER(card_unload);
void cm32p_map(address_map &map);
void descramble_rom_internal(u8* dst, const u8* src);
void descramble_rom_external(u8* dst, const u8* src);
bool pcmard_loaded;
u8 midi;
int midi_pos;
u8 sound_io_buffer[0x100];
@ -321,6 +334,7 @@ cm32p_state::cm32p_state(const machine_config &mconfig, device_type type, const
: driver_device(mconfig, type, tag)
, cpu(*this, "maincpu")
, pcm(*this, "pcm")
, pcmcard(*this, "cardslot")
, lcd(*this, "lcd")
, midi_timer(*this, "midi_timer")
, some_ram(*this, "some_ram")
@ -379,6 +393,46 @@ void cm32p_state::machine_reset()
midi_pos = 0;
}
DEVICE_IMAGE_LOAD_MEMBER(cm32p_state::card_load)
{
uint32_t size = pcmcard->common_get_size("rom");
if (size > 0x080000)
{
image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only up to 512K is supported");
return image_init_result::FAIL;
}
pcmcard->rom_alloc(0x080000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE); // cards are up to 512K
pcmcard->common_load_rom(pcmcard->get_rom_base(), size, "rom");
u8* base = pcmcard->get_rom_base();
if (size < 0x080000)
{
uint32_t mirror = (1 << (31 - count_leading_zeros(size)));
if (mirror < 0x020000) // due to how address descrambling works, we can currently only do mirroring for 128K pages
mirror = 0x020000;
for (uint32_t ofs = mirror; ofs < 0x080000; ofs += mirror)
memcpy(base + ofs, base, mirror);
}
u8* src = static_cast<u8*>(memregion("pcmorg")->base());
u8* dst = static_cast<u8*>(memregion("pcm")->base());
memcpy(&src[0x080000], base, 0x080000);
// descramble PCM card ROM
descramble_rom_external(&dst[0x080000], &src[0x080000]);
pcmard_loaded = true;
return image_init_result::PASS;
}
DEVICE_IMAGE_UNLOAD_MEMBER(cm32p_state::card_unload)
{
u8* src = static_cast<u8*>(memregion("pcmorg")->base());
u8* dst = static_cast<u8*>(memregion("pcm")->base());
memset(&src[0x080000], 0xFF, 0x080000);
memset(&dst[0x080000], 0xFF, 0x080000);
pcmard_loaded = false;
}
void cm32p_state::lcd_ctrl_w(u8 data)
{
lcd->control_w(data);
@ -414,7 +468,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(cm32p_state::midi_timer_cb)
u16 cm32p_state::port0_r()
{
return service_port->read();
return service_port->read() | (pcmard_loaded ? 0x10 : 0x00);
}
u8 cm32p_state::pcmrom_r(offs_t offset)
@ -565,11 +619,14 @@ void cm32p_state::cm32p(machine_config &config)
screen.set_size(16*6-1, (16*6-1)*3/4);
screen.set_visarea(0, 16*6-2, 0, (16*6-1)*3/4-1);
screen.set_palette("palette");
PALETTE(config, "palette", FUNC(cm32p_state::mt32_palette), 2);
MSM6222B_01(config, lcd, 0);
generic_cartslot_device &cardslot(GENERIC_CARTSLOT(config, "cardslot", generic_romram_plain_slot, "u110_card", "bin"));
cardslot.set_device_load(FUNC(cm32p_state::card_load));
cardslot.set_device_unload(FUNC(cm32p_state::card_unload));
SOFTWARE_LIST(config, "card_list").set_original("u110_card");
TIMER(config, midi_timer).configure_generic(FUNC(cm32p_state::midi_timer_cb));
TIMER(config, "samples_timer").configure_periodic(FUNC(cm32p_state::samples_timer_cb), attotime::from_hz(32000*2));
@ -578,20 +635,37 @@ void cm32p_state::cm32p(machine_config &config)
void cm32p_state::init_cm32p()
{
// Roland did a fair amount of scrambling on the address and data lines.
// Only the first 0x20 bytes of the ROMs are readable text in a raw dump.
// Only the first 0x80 bytes of the ROMs are readable text in a raw dump.
// The CM-32P actually checks some of these header bytes, but it uses post-scrambling variants of offsets/values.
u8* src = static_cast<u8*>(memregion("pcmorg")->base());
u8* dst = static_cast<u8*>(memregion("pcm")->base());
for (offs_t bank_ofs = 0x00; bank_ofs < 0x400000; bank_ofs += 0x080000)
// descramble internal ROMs
descramble_rom_internal(&dst[0x000000], &src[0x000000]);
descramble_rom_internal(&dst[0x100000], &src[0x100000]);
descramble_rom_internal(&dst[0x200000], &src[0x200000]);
// descramble PCM card ROM
descramble_rom_external(&dst[0x080000], &src[0x080000]);
}
void cm32p_state::descramble_rom_internal(u8* dst, const u8* src)
{
for (offs_t srcpos = 0x00; srcpos < 0x80000; srcpos ++)
{
offs_t dstpos;
for (offs_t srcpos = 0x00; srcpos < 0x80000; srcpos ++)
{
dstpos = UNSCRAMBLE_ADDRESS(srcpos);
dst[bank_ofs + dstpos] = UNSCRAMBLE_DATA(src[bank_ofs + srcpos]);
}
offs_t dstpos = UNSCRAMBLE_ADDR_INT(srcpos);
dst[dstpos] = UNSCRAMBLE_DATA(src[srcpos]);
}
}
void cm32p_state::descramble_rom_external(u8* dst, const u8* src)
{
for (offs_t srcpos = 0x00; srcpos < 0x80000; srcpos ++)
{
offs_t dstpos = UNSCRAMBLE_ADDR_EXT(srcpos);
dst[dstpos] = UNSCRAMBLE_DATA(src[srcpos]);
}
}
ROM_START( cm32p )
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "cm-32_p__1.0.0.am27c512.7d.ic9", 0x000000, 0x10000, CRC(6f2f6dfd) SHA1(689f77c1d56f923ef1dab7d993a124c47736bc56) ) // "CM-32 P // 1 0 0 <filled bubbles in red marker>" sticker on an AM27C512-150DC eprom @ IC9