diff options
-rw-r--r-- | scripts/src/bus.lua | 4 | ||||
-rw-r--r-- | scripts/src/sound.lua | 13 | ||||
-rw-r--r-- | src/devices/bus/ata/atapicdr.cpp | 6 | ||||
-rw-r--r-- | src/devices/bus/ata/atapicdr.h | 2 | ||||
-rw-r--r-- | src/devices/bus/ata/atapihle.cpp | 11 | ||||
-rw-r--r-- | src/devices/bus/ata/atapihle.h | 5 | ||||
-rw-r--r-- | src/devices/machine/intelfsh.cpp | 39 | ||||
-rw-r--r-- | src/devices/machine/intelfsh.h | 9 | ||||
-rw-r--r-- | src/devices/sound/stt_sa1.cpp | 190 | ||||
-rw-r--r-- | src/devices/sound/stt_sa1.h | 57 | ||||
-rw-r--r-- | src/mame/mame.lst | 6 | ||||
-rw-r--r-- | src/mame/misc/shambros.cpp | 110 | ||||
-rw-r--r-- | src/mame/misc/sttechno.cpp | 622 |
13 files changed, 948 insertions, 126 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 13d50f2e0e2..cb9463a2afc 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -506,10 +506,10 @@ if (BUSES["ATA"]~=null) then MAME_DIR .. "src/devices/bus/ata/cp2024.h", MAME_DIR .. "src/devices/bus/ata/cr589.cpp", MAME_DIR .. "src/devices/bus/ata/cr589.h", - MAME_DIR .. "src/devices/bus/ata/hdd.cpp", - MAME_DIR .. "src/devices/bus/ata/hdd.h", MAME_DIR .. "src/devices/bus/ata/gdrom.cpp", MAME_DIR .. "src/devices/bus/ata/gdrom.h", + MAME_DIR .. "src/devices/bus/ata/hdd.cpp", + MAME_DIR .. "src/devices/bus/ata/hdd.h", MAME_DIR .. "src/devices/bus/ata/px320a.cpp", MAME_DIR .. "src/devices/bus/ata/px320a.h", MAME_DIR .. "src/devices/bus/ata/zip100.cpp", diff --git a/scripts/src/sound.lua b/scripts/src/sound.lua index ed9652835b2..fe1b86137cd 100644 --- a/scripts/src/sound.lua +++ b/scripts/src/sound.lua @@ -969,6 +969,19 @@ end --------------------------------------------------- +-- ST-Techno custom sound chip +--@src/devices/sound/stt_sa1.h,SOUNDS["STT_SA1"] = true +--------------------------------------------------- + +if (SOUNDS["STT_SA1"]~=null) then + files { + MAME_DIR .. "src/devices/sound/stt_sa1.cpp", + MAME_DIR .. "src/devices/sound/stt_sa1.h", + } +end + + +--------------------------------------------------- -- S14001A speech synthesizer --@src/devices/sound/s14001a.h,SOUNDS["S14001A"] = true --------------------------------------------------- diff --git a/src/devices/bus/ata/atapicdr.cpp b/src/devices/bus/ata/atapicdr.cpp index 9d2be8d51c5..61a55bca4c2 100644 --- a/src/devices/bus/ata/atapicdr.cpp +++ b/src/devices/bus/ata/atapicdr.cpp @@ -22,7 +22,7 @@ atapi_cdrom_device::atapi_cdrom_device(const machine_config &mconfig, const char atapi_cdrom_device::atapi_cdrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : atapi_hle_device(mconfig, type, tag, owner, clock), device_ata_interface(mconfig, *this), - ultra_dma_mode(0) + m_ultra_dma_mode(0) { } @@ -98,14 +98,14 @@ void atapi_cdrom_device::device_start() m_identify_buffer[ 49 ] = 0x0600; // Word 49=Capabilities, IORDY may be disabled (bit_10), LBA Supported mandatory (bit_9) - m_identify_buffer[ 88 ] = ultra_dma_mode; + m_identify_buffer[ 88 ] = m_ultra_dma_mode; atapi_hle_device::device_start(); } void atapi_cdrom_device::set_ultra_dma_mode(uint16_t mode) { - ultra_dma_mode = mode; + m_ultra_dma_mode = mode; } void atapi_cdrom_device::device_reset() diff --git a/src/devices/bus/ata/atapicdr.h b/src/devices/bus/ata/atapicdr.h index a967fc52bf5..16c4a171517 100644 --- a/src/devices/bus/ata/atapicdr.h +++ b/src/devices/bus/ata/atapicdr.h @@ -56,7 +56,7 @@ protected: virtual void ExecCommand() override; u32 m_sequence_counter; bool m_media_change; - uint16_t ultra_dma_mode; + uint16_t m_ultra_dma_mode; private: // ata_hle_device_base implementation diff --git a/src/devices/bus/ata/atapihle.cpp b/src/devices/bus/ata/atapihle.cpp index 8b2f3fd0548..cb5712f69b3 100644 --- a/src/devices/bus/ata/atapihle.cpp +++ b/src/devices/bus/ata/atapihle.cpp @@ -6,7 +6,8 @@ atapi_hle_device::atapi_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : ata_hle_device_base(mconfig, type, tag, owner, clock), m_packet(0), - m_data_size(0) + m_data_size(0), + m_is_ready(false) { } @@ -22,6 +23,14 @@ void atapi_hle_device::device_reset() ata_hle_device_base::device_reset(); } +void atapi_hle_device::set_is_ready(bool state) +{ + if (has_running_machine() && (machine().phase() >= machine_phase::RESET)) + throw emu_fatalerror("Static ready state should only be set during configuration"); + + m_is_ready = state; +} + void atapi_hle_device::process_buffer() { if (m_packet) diff --git a/src/devices/bus/ata/atapihle.h b/src/devices/bus/ata/atapihle.h index 80a194afa62..8cfe47710f5 100644 --- a/src/devices/bus/ata/atapihle.h +++ b/src/devices/bus/ata/atapihle.h @@ -46,6 +46,8 @@ public: PACKET_COMMAND_RESPONSE_DRQ_50US }; + void set_is_ready(bool state); + protected: atapi_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -55,7 +57,7 @@ protected: virtual int sector_length() override { return ATAPI_BUFFER_LENGTH; } virtual void process_buffer() override; virtual void fill_buffer() override; - virtual bool is_ready() override { return false; } + virtual bool is_ready() override { return m_is_ready; } virtual void signature() override; virtual void process_command() override; virtual void finished_command() override; @@ -70,6 +72,7 @@ private: int m_packet; int m_data_size; + bool m_is_ready; static constexpr int ATAPI_BUFFER_LENGTH = 0xf800; }; diff --git a/src/devices/machine/intelfsh.cpp b/src/devices/machine/intelfsh.cpp index 4ec5315b47b..f0376b80d71 100644 --- a/src/devices/machine/intelfsh.cpp +++ b/src/devices/machine/intelfsh.cpp @@ -41,6 +41,7 @@ enum FM_WRITEPAGEATMEL, FM_WRITEBUFFER1, // part 1 of write to buffer sequence FM_WRITEBUFFER2, // part 2 of write to buffer sequence + FM_FAST_RESET, }; @@ -93,6 +94,7 @@ DEFINE_DEVICE_TYPE(AMD_29F800T, amd_29f800t_device, "amd_29f DEFINE_DEVICE_TYPE(AMD_29F800B_16BIT, amd_29f800b_16bit_device, "amd_29f800b_16bit", "AMD 29F800B Flash (16-bit)") DEFINE_DEVICE_TYPE(AMD_29LV200T, amd_29lv200t_device, "amd_29lv200t", "AMD 29LV200T Flash") DEFINE_DEVICE_TYPE(FUJITSU_29F160TE, fujitsu_29f160te_device, "mbm29f160te", "Fujitsu MBM29F160TE Flash") +DEFINE_DEVICE_TYPE(FUJITSU_29F160TE_16BIT,fujitsu_29f160te_16bit_device,"mbm29f160te_16bit", "Fujitsu MBM29F160TE Flash (16-bit)") DEFINE_DEVICE_TYPE(FUJITSU_29F016A, fujitsu_29f016a_device, "mbm29f016a", "Fujitsu MBM29F016A Flash") DEFINE_DEVICE_TYPE(FUJITSU_29DL164BD, fujitsu_29dl164bd_device, "mbm29dl164bd", "Fujitsu MBM29DL164BD Flash") DEFINE_DEVICE_TYPE(FUJITSU_29LV002TC, fujitsu_29lv002tc_device, "mbm29lv002tc", "Fujitsu MBM29LV002TC Flash") @@ -157,7 +159,8 @@ intelfsh_device::intelfsh_device(const machine_config &mconfig, device_type type m_flash_mode(FM_NORMAL), m_flash_master_lock(false), m_timer(nullptr), - m_bank(0) + m_bank(0), + m_fast_mode(false) { assert(bits == 8 || bits == 16); assert(size != 0); @@ -176,6 +179,9 @@ intel_28f016s5_device::intel_28f016s5_device(const machine_config &mconfig, cons fujitsu_29f160te_device::fujitsu_29f160te_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : intelfsh8_device(mconfig, FUJITSU_29F160TE, tag, owner, clock, 0x200000, MFG_FUJITSU, 0xd2) { m_top_boot_sector = true; } +fujitsu_29f160te_16bit_device::fujitsu_29f160te_16bit_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : intelfsh16_device(mconfig, FUJITSU_29F160TE_16BIT, tag, owner, clock, 0x200000, MFG_FUJITSU, 0xd2) { m_top_boot_sector = true; m_sector_is_4k = true; } + fujitsu_29f016a_device::fujitsu_29f016a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : intelfsh8_device(mconfig, FUJITSU_29F016A, tag, owner, clock, 0x200000, MFG_FUJITSU, 0xad) { } @@ -314,6 +320,7 @@ void intelfsh_device::device_start() save_item( NAME(m_status) ); save_item( NAME(m_flash_mode) ); save_item( NAME(m_flash_master_lock) ); + save_item( NAME(m_fast_mode) ); save_pointer( &m_data[0], "m_data", m_size); } @@ -548,8 +555,11 @@ void intelfsh_device::write_full(uint32_t address, uint32_t data) case 0xff: // reset chip mode m_flash_mode = FM_NORMAL; break; - case 0x90: // read ID - m_flash_mode = FM_READID; + case 0x90: + if ( m_fast_mode && m_maker_id == MFG_FUJITSU ) // reset from fast mode (when fast mode is enabled) + m_flash_mode = FM_FAST_RESET; + else // read ID + m_flash_mode = FM_READID; break; case 0x40: case 0x10: // program @@ -576,6 +586,12 @@ void intelfsh_device::write_full(uint32_t address, uint32_t data) case 0x70: // read status m_flash_mode = FM_READSTATUS; break; + case 0xa0: // fast program (fast mode must be enabled) + if ( m_fast_mode && m_maker_id == MFG_FUJITSU ) + m_flash_mode = FM_BYTEPROGRAM; + else + logerror( "%s: Unknown flash mode byte %x\n", machine().describe_context(), data & 0xff ); + break; case 0xaa: // AMD ID select part 1 if( ( address & 0xfff ) == 0x555 ) { @@ -591,10 +607,10 @@ void intelfsh_device::write_full(uint32_t address, uint32_t data) if ( m_maker_id == MFG_INTEL && m_device_id >= 0x14 && m_device_id <= 0x16 ) m_flash_mode = FM_WRITEBUFFER1; else - logerror( "Unknown flash mode byte %x\n", data & 0xff ); + logerror( "%s: Unknown flash mode byte %x\n", machine().describe_context(), data & 0xff ); break; default: - logerror( "Unknown flash mode byte %x\n", data & 0xff ); + logerror( "%s: Unknown flash mode byte %x\n", machine().describe_context(), data & 0xff ); break; } break; @@ -701,6 +717,12 @@ void intelfsh_device::write_full(uint32_t address, uint32_t data) { m_flash_mode = FM_NORMAL; } + // Fast mode + else if( ( ( address & 0xfff ) == 0xaaa || ( address & 0xfff ) == 0x555 ) && ( data & 0xff ) == 0x20 ) + { + m_flash_mode = FM_NORMAL; + m_fast_mode = true; + } else { logerror( "unexpected %08x=%02x in FM_READAMDID2\n", address, data & 0xff ); @@ -1075,5 +1097,12 @@ void intelfsh_device::write_full(uint32_t address, uint32_t data) m_bank = data & 0xff; m_flash_mode = FM_NORMAL; break; + case FM_FAST_RESET: + if ( ( data & 0xff ) == 0xf0 || ( data & 0xff ) == 0 ) { + m_fast_mode = false; + m_flash_mode = FM_NORMAL; + } else + logerror( "unexpected %08x=%02x in FM_FAST_RESET:\n", address, data & 0xff ); + break; } } diff --git a/src/devices/machine/intelfsh.h b/src/devices/machine/intelfsh.h index 711523bebe4..168b5e7baa0 100644 --- a/src/devices/machine/intelfsh.h +++ b/src/devices/machine/intelfsh.h @@ -62,6 +62,8 @@ protected: uint8_t m_write_buffer[32]; uint32_t m_write_buffer_start_address; uint32_t m_write_buffer_count; + + bool m_fast_mode; }; @@ -267,6 +269,12 @@ public: }; // 16-bit variants +class fujitsu_29f160te_16bit_device : public intelfsh16_device +{ +public: + fujitsu_29f160te_16bit_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); +}; + class sharp_lh28f400_device : public intelfsh16_device { public: @@ -365,6 +373,7 @@ DECLARE_DEVICE_TYPE(AMD_29F800T, amd_29f800t_device) DECLARE_DEVICE_TYPE(AMD_29F800B_16BIT, amd_29f800b_16bit_device) DECLARE_DEVICE_TYPE(AMD_29LV200T, amd_29lv200t_device) DECLARE_DEVICE_TYPE(FUJITSU_29F160TE, fujitsu_29f160te_device) +DECLARE_DEVICE_TYPE(FUJITSU_29F160TE_16BIT,fujitsu_29f160te_16bit_device) DECLARE_DEVICE_TYPE(FUJITSU_29F016A, fujitsu_29f016a_device) DECLARE_DEVICE_TYPE(FUJITSU_29DL164BD, fujitsu_29dl164bd_device) DECLARE_DEVICE_TYPE(FUJITSU_29LV002TC, fujitsu_29lv002tc_device) diff --git a/src/devices/sound/stt_sa1.cpp b/src/devices/sound/stt_sa1.cpp new file mode 100644 index 00000000000..efd9e49e163 --- /dev/null +++ b/src/devices/sound/stt_sa1.cpp @@ -0,0 +1,190 @@ +// license:BSD-3-Clause +// copyright-holders:windyfairy +/* + ST-Techno STT-SA1 PCM sound chip + Originally implemented in an FPGA +*/ +#include "emu.h" +#include "stt_sa1.h" + +// #define VERBOSE (LOG_GENERAL) +// #define LOG_OUTPUT_STREAM std::cout +#include "logmacro.h" + + +DEFINE_DEVICE_TYPE(STT_SA1, stt_sa1_device, "stt_sa1", "ST-Techno STT-SA1 Sound") + +stt_sa1_device::stt_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, STT_SA1, tag, owner, clock) + , device_sound_interface(mconfig, *this) + , device_rom_interface(mconfig, *this) + , m_stream(nullptr) +{ +} + +void stt_sa1_device::enable_w(uint16_t data) +{ + m_enabled = data != 0; +} + +uint16_t stt_sa1_device::read(offs_t offset, uint16_t mem_mask) +{ + offset &= 0x7f; + + return m_regs[offset]; // TODO: Should this return addr_cur for regs 1 and 2 instead? +} + +void stt_sa1_device::write(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + offset &= 0x7f; + const int v = offset >> 4; + const int reg = offset & 0xf; + + m_regs[offset] = data; + + switch (reg) { + case 1: + m_voice[v].addr_start = m_voice[v].addr_cur = (m_voice[v].addr_cur & 0xffff0000000) | (uint64_t(data) << 12); + LOG("voice %d: start = %08llx\n", v, m_voice[v].addr_cur >> 12); + break; + case 2: + m_voice[v].addr_start = m_voice[v].addr_cur = (m_voice[v].addr_cur & 0x0000ffff000) | (uint64_t(data & 0x7fff) << 28); + m_voice[v].is_looped = BIT(data, 15) != 0; + LOG("voice %d: start = %08llx, is_looped = %d\n", v, m_voice[v].addr_cur >> 12, m_voice[v].is_looped); + break; + + case 3: + m_voice[v].freq = data; + LOG("voice %d: step = %08x\n", v, m_voice[v].freq); + break; + + case 4: + m_voice[v].addr_start = (m_voice[v].addr_start & 0xffff0000000) | (uint64_t(data) << 12); + LOG("voice %d: addr_start = %08llx\n", v, m_voice[v].addr_start >> 12); + break; + case 5: + m_voice[v].addr_start = (m_voice[v].addr_start & 0x0000ffff000) | (uint64_t(data) << 28); + LOG("voice %d: addr_start = %08llx\n", v, m_voice[v].addr_start >> 12); + break; + + case 6: + m_voice[v].addr_end = (m_voice[v].addr_end & 0xffff0000000) | (uint64_t(data) << 12); + LOG("voice %d: addr_end = %08llx\n", v, m_voice[v].addr_end >> 12); + break; + case 7: + m_voice[v].addr_end = (m_voice[v].addr_end & 0x0000ffff000) | (uint64_t(data) << 28); + LOG("voice %d: addr_end = %08llx\n", v, m_voice[v].addr_end >> 12); + break; + + case 0x0b: + m_voice[v].vol_l = data; + LOG("voice %d: vol_l = %08x\n", v, m_voice[v].vol_l); + break; + case 0x0c: + m_voice[v].vol_r = data; + LOG("voice %d: vol_r = %08x\n", v, m_voice[v].vol_r); + break; + + default: + LOG("Unknown register usage: voice %d, register %x, data %04x\n", v, reg, data); + break; + } +} + +uint16_t stt_sa1_device::key_r() +{ + if (!m_enabled) + return 0; + + if (!machine().side_effects_disabled()) + m_stream->update(); + + return m_keyctrl; +} + +void stt_sa1_device::key_w(uint16_t data) +{ + if (!m_enabled) + return; + + const u16 prev = m_keyctrl; + + m_stream->update(); + + m_keyctrl = data; + + for (int v = 0; v < 8; v++) { + if (BIT(m_keyctrl, v) && !BIT(prev, v)) { + // keyon + m_voice[v].enabled = true; + m_voice[v].addr_cur = m_voice[v].addr_start; + } else if (!BIT(m_keyctrl, v) && BIT(prev, v)) { + // keyoff + m_voice[v].enabled = false; + } + } +} + +void stt_sa1_device::device_start() +{ + m_stream = stream_alloc(0, 2, clock() / 448); + + save_item(STRUCT_MEMBER(m_voice, addr_start)); + save_item(STRUCT_MEMBER(m_voice, addr_cur)); + save_item(STRUCT_MEMBER(m_voice, addr_end)); + save_item(STRUCT_MEMBER(m_voice, vol_l)); + save_item(STRUCT_MEMBER(m_voice, vol_r)); + save_item(STRUCT_MEMBER(m_voice, freq)); + save_item(STRUCT_MEMBER(m_voice, is_looped)); + save_item(STRUCT_MEMBER(m_voice, enabled)); + save_item(NAME(m_keyctrl)); + save_item(NAME(m_regs)); + save_item(NAME(m_enabled)); +} + +void stt_sa1_device::device_reset() +{ + m_enabled = false; + + std::fill(std::begin(m_regs), std::end(m_regs), 0); + + for (int i = 0; i < 8; i++) { + m_voice[i].addr_start = 0; + m_voice[i].addr_cur = 0; + m_voice[i].addr_end = 0; + m_voice[i].vol_l = 0; + m_voice[i].vol_r = 0; + m_voice[i].freq = 0; + m_voice[i].is_looped = false; + m_voice[i].enabled = false; + } +} + +void stt_sa1_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) +{ + outputs[0].fill(0); + outputs[1].fill(0); + + for (int v = 0; v < 8; v++) { + voice_t &voice = m_voice[v]; + + for (int i = 0; i < outputs[0].samples() && voice.enabled; i++) { + const offs_t offset = voice.addr_cur >> 12; + const int sample = s8(read_byte(offset)) << 8; + + voice.addr_cur += voice.freq; + + outputs[0].add_int(i, (sample * voice.vol_l) >> 16, 32768 * 8); + outputs[1].add_int(i, (sample * voice.vol_r) >> 16, 32768 * 8); + + if (voice.addr_cur >= voice.addr_end) { + if (!voice.is_looped) { + voice.enabled = false; + m_keyctrl &= ~(1 << v); + } else { + voice.addr_cur = voice.addr_start; + } + } + } + } +} diff --git a/src/devices/sound/stt_sa1.h b/src/devices/sound/stt_sa1.h new file mode 100644 index 00000000000..8436c2f7f6c --- /dev/null +++ b/src/devices/sound/stt_sa1.h @@ -0,0 +1,57 @@ +// license:BSD-3-Clause +// copyright-holders:windyfairy +#ifndef MAME_SOUND_STT_SA1_H +#define MAME_SOUND_STT_SA1_H + +#pragma once + +#include "dirom.h" + +class stt_sa1_device : public device_t, + public device_sound_interface, + public device_rom_interface<24, 1, 0, ENDIANNESS_LITTLE> +{ +public: + static constexpr feature_type imperfect_features() { return feature::SOUND; } // unemulated and/or unverified effects and envelopes + + stt_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void enable_w(uint16_t data); + + uint16_t read(offs_t offset, uint16_t mem_mask = ~0); + void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + + uint16_t key_r(); + void key_w(uint16_t data); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; + +private: + struct voice_t { + uint64_t addr_start; + uint64_t addr_end; + uint64_t addr_cur; + uint16_t vol_l; + uint16_t vol_r; + uint16_t freq; + bool is_looped; + bool enabled; + }; + + sound_stream *m_stream; + + voice_t m_voice[8]; + uint16_t m_keyctrl; // Key on/off control bit + + uint16_t m_regs[128]; + + bool m_enabled; +}; + +DECLARE_DEVICE_TYPE(STT_SA1, stt_sa1_device) + +#endif // MAME_SOUND_STT_SA1_H diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 25c16ce3d40..c7603355ee9 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -31684,9 +31684,6 @@ version4v // (c) 2006 Amcoe version4v2 // (c) 2006 Amcoe version4v3 // (c) 2006 Amcoe -@source:misc/shambros.cpp -shambros - @source:misc/shangkid.cpp chinhero // (c) 1984 Taiyo chinhero2 // (c) 1984 Taiyo @@ -31834,6 +31831,9 @@ stop @source:misc/strkzn.cpp strkzn // (c) 1994 Purple Star +@source:misc/sttechno.cpp +shambros + @source:misc/stuntair.cpp stuntair // (c) 1983 Nuova Videotron diff --git a/src/mame/misc/shambros.cpp b/src/mame/misc/shambros.cpp deleted file mode 100644 index 3370380c066..00000000000 --- a/src/mame/misc/shambros.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders: - -/* -Kato's STV01 MainPCB Rev. C - - -Only known game: Shamisen Brothers Vol 1 (2003) -The game was also ported for Namco System 10 - -The dumper only had the CD-ROM. -A low quality picture of the PCB found on the internet shows: -- M68K-based processor -- program ROM -- multiple flash chips -- 3 FPGAs -- Mitsumi CD drive - -TODO: only a placeholder for the CD dump for now -*/ - -#include "emu.h" - -#include "cpu/m68000/m68000.h" - -#include "emupal.h" -#include "screen.h" -#include "speaker.h" - - -namespace { - -class shambros_state : public driver_device -{ -public: - shambros_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - {} - - void shambros(machine_config &config) ATTR_COLD; - -private: - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); -}; - - -uint32_t shambros_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - return 0; -} - - -static INPUT_PORTS_START( shambros ) - PORT_START("IN0") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) - - PORT_START("IN1") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) - - // no dips on PCB -INPUT_PORTS_END - - -void shambros_state::shambros(machine_config &config) -{ - M68000(config, "maincpu", 12'000'000); // exact type not known, XTAL unreadable - - // all wrong - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); - screen.set_size(64*8, 32*8); - screen.set_visarea_full(); - screen.set_screen_update(FUNC(shambros_state::screen_update)); - screen.set_palette("palette"); - - PALETTE(config, "palette").set_entries(0x100); // wrong - - SPEAKER(config, "mono").front_center(); -} - - -ROM_START( shambros ) - ROM_REGION(0x20000, "maincpu", 0) - ROM_LOAD( "g112 v1.01.prg", 0x00000, 0x20000, NO_DUMP ) // actual size unknown - - // numerous undumped flash ROMs - - DISK_REGION( "cdrom" ) - DISK_IMAGE( "sb01-100", 0, SHA1(abd1d61871bcb4635acc691e35ec386823763ba2) ) -ROM_END - -} // anonymous namespace - - -GAME( 2003, shambros, 0, shambros, shambros, shambros_state, empty_init, ROT0, "Kato's", "Shamisen Brothers Vol 1", MACHINE_IS_SKELETON ) diff --git a/src/mame/misc/sttechno.cpp b/src/mame/misc/sttechno.cpp new file mode 100644 index 00000000000..ce82454e008 --- /dev/null +++ b/src/mame/misc/sttechno.cpp @@ -0,0 +1,622 @@ +// license:BSD-3-Clause +// copyright-holders:windyfairy + +/* +Only known game: Shamisen Brothers Vol 1 (2003) +The game was also ported for Namco System 10 + +Kato's STV01 MainPCB Rev. C +ST-Techno PCB +------------------------------------------------------------------------------------------ +| | +| ------------- | +| U18 U47 U45 U40 U39 U37 U31 | | | +| | U6 | U30 | +| U48 U44 U41 U38 U33 U32 | STT-SA1 | | +| U19 | | | +| U4 ------------- | +| U27 U3 --------- U35 | +| U5 U14 X2 | U36 | | +| U13 | | U42 | +| VR1 U16 ------------ --------- | +| --------- | | ----------------------- | +| | U29 | U17 | U15 | | U46 PRG ROM | | +| | | | STT-GA1 | ----------------------- | +| | | | | C | +| | | ------------ -------- N | +| | | U11 X1 | U34 | 1 | +| | | U2 | GLU | | +| | | | | | +| --------- -------- | +| | +| U61 U1 U60 U43 U49 | +| RESET | +| |-----| (EDGE) |--| EDGE |------| CN3 CN2 | +------| |--------| |------------------------------------| |--------------------- + +X1: 33.3333 MHz +X2: 42.95454 MHz + +U1 (TD62083F): Toshiba TD62083AF, 8ch high current darlington sink driver +U2, U3, U4 (AM29F160): Fujitsu MBM29F160TE-70, 16 Megabit (2 M x 8-Bit/1 M x 16-Bit) +U5 (BU9480): 9480F, 16-bit stereo D/A converter +U6: STT-SA1, markings scratched off but patterns are similar to an Actel FPGA and is also 208 pins. Sound chip +U11 (CXD1178Q): Sony CXD1178Q, 8-bit RGB 3-channel D/A converter +U13, U14: Taiwan Memory Technology T14M256A, 32k x 8 high speed CMOS SRAM +U15: STT-GA1 (custom chip? has heatsink), likely an FPGA, 240 pin. Graphics chip +U16, U17 (T224160B): Taiwan Memory Technology T224160B, 256k x 16 DRAM +U18, U19, U27 (NJM2904): 2904 2148B JRC, single-supply dual operational amplifier +U29 (TA8210): Under large heatsink, sound amplifier? +U30 (TA48M025F): 48M025F, three-terminal low dropout voltage regulator +U31, U32, U33, U37, U38, U39, U40, U41, U44, U45, U47, U48 (HY628400): Toshiba TC554001, 512k x 8 SRAM +U34 (GLU): Actel A54SX08A, 208 pin +U35, U42 (HY628100): Hyundai HY628100B 0045A LT1-70, 128k x 8 CMOS SRAM +U36 (68HC000): Toshiba TMP68HC000F-16 +U43 (PST594C): Mitsumi PST594C, system reset monolithic IC +U45 (PRG ROM): MX A9630 27C4100DC-12 MR38674-1, labeled G112 V1.01 +U49: 74HC14A +U60 (ST232ABD): MAX232A CSE 0107 +U61: Toshiba TD62064AF, 4ch high current darlington sink driver + +CN1: 40 pin IDE connector for CD-ROM +CN2: 3 pin header, unused +CN3: USB connector (JVS?) + +VR1: Sound pot + +CD-ROM: Mitsumi FX5400W ATAPI CD-ROM drive + +EDGE: EDGE28P x2side (56P) P=3.96mm connector. Not JAMMA. + Solder Side | Parts Side + GND - A | | 1 - GND + GND - B | | 2 - GND + +5V - C | | 3 - +5V + +5V - D | | 4 - +5V + +12V - E | | 5 - +12V + KEY - F | | 6 - KEY + METER2 - H | | 7 - METER1 + LOCKOUT2 - J | | 8 - LOCKOUT1 + COIN SW2 - K | | 9 - COIN SW1 + 1P BG(-) - L | | 10 - 1P BG(+) + 2P BG(-) - M | | 11 - 2P BG(+) + VIDEO G - N | | 12 - VIDEO R +VIDEO SYNC - P | | 13 - VIDEO B +SERVICE SW - R | | 14 - VIDEO GND + EXT. IN - S | | 15 - TEST SW + 2P START - T | | 16 - 1P START + 2P UP - U | | 17 - 1P UP + 2P MID - V | | 18 - 1P MID + 2P LOW - W | | 19 - 1P LOW + 2P SHOT - X | | 20 - 1P SHOT + 2P DETECT - Y | | 21 - 1P DETECT + UP LAMP - Z | | 22 - SEL UP + DOWN LAMP - a | | 23 - SEL DOWN +DECI. LAMP - b | | 24 - SEL DECI. + EXT. OUT0 - c | | 25 - COIN LAMP1 + EXT. OUT1 - d | | 26 - COIN LAMP2 + GND - e | | 27 - GND + GND - f | | 28 - GND + + +Notes: +- V1.00K is on the CD (pgx.bin) so it's known to exist +- Unknown exactly where RS232 is connected. Likely candidates are JVS, EXT IN/OUT (unused according to manual), or CN2 +- You must send the command "4g63" before the terminal debugger will respond to any commands. Send "h" to see list of most commands. +*/ + +#include "emu.h" + +#include "bus/ata/ataintf.h" +#include "bus/ata/atapicdr.h" +#include "bus/rs232/null_modem.h" +#include "bus/rs232/pty.h" +#include "bus/rs232/rs232.h" +#include "bus/rs232/terminal.h" +#include "cpu/m68000/m68000.h" +#include "machine/i8251.h" +#include "machine/intelfsh.h" +#include "machine/timer.h" +#include "sound/stt_sa1.h" + +#include "emupal.h" +#include "screen.h" +#include "speaker.h" + +#define LOG_VIDEO_DISPLAY (1U << 1) +#define LOG_UART (1U << 2) + +// #define VERBOSE (LOG_GENERAL | LOG_UART) +// #define LOG_OUTPUT_STREAM std::cout + +#include "logmacro.h" + +namespace { + +class sttechno_state : public driver_device, public device_serial_interface +{ +public: + sttechno_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , device_serial_interface(mconfig, *this) + , m_maincpu(*this, "maincpu") + , m_ata(*this, "ata") + , m_flash(*this, "flash%u", 1) + , m_video_flash(*this, "video_flash") + , m_sound(*this, "pcm_sound") + , m_rs232(*this, "rs232") + , m_sttga1_ram_obj(*this, "sttga1_ram_obj") + , m_sttga1_ram_pal(*this, "sttga1_ram_pal") + , m_sound_ram(*this, "sound_ram") + { + } + + void shambros(machine_config &config) ATTR_COLD; + +protected: + virtual void machine_start() override ATTR_COLD; + virtual void machine_reset() override ATTR_COLD; + + virtual void tra_callback() override; + virtual void rcv_complete() override; + +private: + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + void cpu_map(address_map &map) ATTR_COLD; + void sound_map(address_map &map) ATTR_COLD; + + void bank_w(uint16_t data); + void bank_write_enable_w(uint16_t data); + + void data_w(offs_t offset, uint16_t data); + uint16_t data_r(offs_t offset); + + void uart_data_w(uint16_t data); + uint16_t uart_data_r(); + + uint16_t uart_txrdy_r(); + + void uart_config_w(uint16_t data); + + void ata_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t ata_cs0_r(offs_t offset, uint16_t mem_mask = ~0); + + void ata_control_w(uint16_t data); + + uint16_t video_unk_r(); + void sttga1_video_flash_w(offs_t offset, uint16_t data); + uint16_t sttga1_video_flash_r(offs_t offset); + void sttga1_video_flash_write_enable_w(offs_t offset, uint16_t data); + void sttga1_enabled_w(offs_t offset, uint16_t data); + + void sound_device_enable_w(offs_t offset, uint16_t data); + + TIMER_DEVICE_CALLBACK_MEMBER(irq6_timer); + + required_device<cpu_device> m_maincpu; + required_device<ata_interface_device> m_ata; + required_device_array<intelfsh16_device, 2> m_flash; + required_device<intelfsh16_device> m_video_flash; + required_device<stt_sa1_device> m_sound; + required_device<rs232_port_device> m_rs232; + + required_shared_ptr<uint16_t> m_sttga1_ram_obj; + required_shared_ptr<uint16_t> m_sttga1_ram_pal; + required_shared_ptr<uint16_t> m_sound_ram; + + uint16_t m_bank; + uint16_t m_flash_write_enabled; + + bool m_sttga1_video_flash_write_enable; + bool m_sttga1_enabled; + + uint8_t m_uart_rx; + bool m_uart_rx_busy; + + bool m_ata_enabled; +}; + +void sttechno_state::machine_start() +{ + save_item(NAME(m_bank)); + save_item(NAME(m_flash_write_enabled)); + save_item(NAME(m_sttga1_video_flash_write_enable)); + save_item(NAME(m_sttga1_enabled)); + save_item(NAME(m_uart_rx)); + save_item(NAME(m_uart_rx_busy)); + save_item(NAME(m_ata_enabled)); + + // TODO: Exact parameters for the UART are unknown + set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1); + set_rate(115200); +} + +void sttechno_state::machine_reset() +{ + receive_register_reset(); + transmit_register_reset(); + + m_bank = 0; + m_flash_write_enabled = 0; + + m_sttga1_video_flash_write_enable = false; + m_sttga1_enabled = false; + + m_uart_rx = 0; + m_uart_rx_busy = false; + + m_ata_enabled = false; +} + +uint32_t sttechno_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + bitmap.fill(0, cliprect); + + if (!m_sttga1_enabled) + return 0; + + // Use second half of OBJ RAM as the list to be rendered + for (int offset = 0x2000; offset < 0x4000; offset += 4) { + const uint16_t x = m_sttga1_ram_obj[offset] & 0x1ff; + const uint16_t y = m_sttga1_ram_obj[offset+1] & 0x1ff; + const uint16_t transparency = (BIT(m_sttga1_ram_obj[offset+1], 10, 5) / 31.0) * 255; + + const uint8_t palidx = BIT(m_sttga1_ram_obj[offset+2], 0, 6); + const uint8_t unk = BIT(m_sttga1_ram_obj[offset+2], 6, 2); + const uint8_t tiles_w = BIT(m_sttga1_ram_obj[offset+2], 8, 3) + 1; + const uint8_t xflip = BIT(m_sttga1_ram_obj[offset+2], 11); // these aren't confirmed and don't seem to actually be used, but I think they are flipped bit flags based on the code + const uint8_t tiles_h = BIT(m_sttga1_ram_obj[offset+2], 12, 3) + 1; + const uint8_t yflip = BIT(m_sttga1_ram_obj[offset+2], 15); + + const uint32_t char_offset_base = BIT(m_sttga1_ram_obj[offset+3], 0, 14) * 0x100; + const bool is_transparent = BIT(m_sttga1_ram_obj[offset+3], 14) && transparency != 255; + const bool is_last = BIT(m_sttga1_ram_obj[offset+3], 15); + + LOGMASKED(LOG_VIDEO_DISPLAY, "%04x: x[%04x] y[%04x] unk[%x] pal[%02x] w[%02x] h[%02x] xflip[%d] yflip[%d] char_offset_base[%08x] trans[%d %04x] is_last[%d] | obj[%04x]\n", offset, x, y, unk, palidx, tiles_w, tiles_h, xflip, yflip, char_offset_base, is_transparent, transparency, is_last, m_sttga1_ram_obj[offset+2]); + + if (is_last) { + LOGMASKED(LOG_VIDEO_DISPLAY, "end of list\n"); + break; + } + + for (int tile_x = 0; tile_x < tiles_h; tile_x++) { + for (int tile_y = 0; tile_y < tiles_w; tile_y++) { + for (int pix_y = 0; pix_y < 16; pix_y++) { + for (int pix_x = 0; pix_x < 16; pix_x++) { + const int ty = (y + tile_x * 16 + pix_y) % 512; // 512x512 framebuffer size, must be wrapped + const int tx = (x + (tile_y * 16) + pix_x) % 512; + + if (!cliprect.contains(tx, ty)) + continue; + + uint16_t *const pix = &bitmap.pix(ty, tx); + const uint32_t char_offset = char_offset_base + (tile_x * (0x100 * tiles_w)) + (tile_y * 0x100) + (pix_y * 16) + pix_x; + const uint16_t char_data = m_video_flash->read_raw(char_offset / 2); + const int colidx = BIT(char_data, 8 * (1 - (char_offset & 1)), 8); + uint16_t color = m_sttga1_ram_pal[palidx * 0x100 + colidx]; + + if (colidx == 0) + continue; + + pix[0] = is_transparent ? alpha_blend_r16(pix[0], color, transparency) : color; + } + } + } + } + } + + return 0; +} + +TIMER_DEVICE_CALLBACK_MEMBER(sttechno_state::irq6_timer) +{ + // IRQ 6 is responsible for incrementing the in-game song sync timer + // If the IRQ is too fast or too slow then it affects a lot of gameplay-related things: the measure markers, the note placements, the timing judgements + // The animation during the gameplay where the character on the right side jumps up and down is also based on this IRQ + m_maincpu->set_input_line(6, HOLD_LINE); +} + +void sttechno_state::bank_w(uint16_t data) +{ + m_bank = data; +} + +void sttechno_state::bank_write_enable_w(uint16_t data) +{ + // Only appears to be used for banks 3 and 4 + // For bank 3 it'll write 1, for bank 4 it'll write 2 + // The game typically enables write, writes data, then immediately clears the write flag + m_flash_write_enabled = data; +} + +void sttechno_state::data_w(offs_t offset, uint16_t data) +{ + if (m_bank >= 0 && m_bank <= 2) { + const offs_t offs = offset + (0x100000 * m_bank); + if (offs < 0x100 / 2) + m_sound->write(offs, data); + else + m_sound_ram[offs] = swapendian_int16(data); + } else if (m_bank == 3) { + if (BIT(m_flash_write_enabled, 0)) + m_flash[0]->write(offset, data); + } else if (m_bank == 4) { + if (BIT(m_flash_write_enabled, 1)) + m_flash[1]->write(offset, data); + } +} + +uint16_t sttechno_state::data_r( offs_t offset) +{ + if (m_bank >= 0 && m_bank <= 2) { + const offs_t offs = offset + (0x100000 * m_bank); + if (offs < 0x100 / 2) + return m_sound->read(offs); + else + return swapendian_int16(m_sound_ram[offs]); + } else if (m_bank == 3) { + return m_flash[0]->read(offset); + } else if (m_bank == 4) { + return m_flash[1]->read(offset); + } + + return 0; +} + +void sttechno_state::uart_data_w(uint16_t data) +{ + LOGMASKED(LOG_UART, "uart_data_w %04x\n", data); + transmit_register_setup(data & 0xff); +} + +uint16_t sttechno_state::uart_data_r() +{ + uint16_t r = m_uart_rx; + + if (!machine().side_effects_disabled()) { + m_uart_rx = 0; + m_maincpu->set_input_line(4, CLEAR_LINE); + m_uart_rx_busy = false; + } + + return r; +} + +void sttechno_state::tra_callback() +{ + m_rs232->write_txd(transmit_register_get_data_bit()); +} + +void sttechno_state::rcv_complete() +{ + receive_register_extract(); + m_uart_rx = get_received_char(); + m_uart_rx_busy = true; + + m_maincpu->set_input_line(4, ASSERT_LINE); +} + +uint16_t sttechno_state::uart_txrdy_r() +{ + // Polled before writing to uart_data_w + return !m_uart_rx_busy && is_transmit_register_empty() && !is_receive_register_full(); +} + +void sttechno_state::uart_config_w(uint16_t data) +{ + // 0x49 is written here + LOGMASKED(LOG_UART, "uart_config_w %04x\n", data); +} + +void sttechno_state::ata_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (!m_ata_enabled) + return; + + m_ata->cs0_w(offset, data, mem_mask); +} + +uint16_t sttechno_state::ata_cs0_r(offs_t offset, uint16_t mem_mask) +{ + if (!m_ata_enabled) + return 0; + + return m_ata->cs0_r(offset, mem_mask); +} + +void sttechno_state::ata_control_w(uint16_t data) +{ + if (data & 0x8000) { + // TODO: CD-ROM hardware reset + return; + } + + m_ata_enabled = (data & 3) != 0; +} + +uint16_t sttechno_state::video_unk_r() +{ + // This gets called at two points: + // - Every time before the OBJ RAM gets updated + // - Every time before setting FM_BYTEPROGRAM for the flash + + if (m_sttga1_video_flash_write_enable) + return 0; + + // HACK: Copy the OBJ data into the unused second half of the OBJ RAM for rendering + // This helps fix some small graphical glitches (sound test menu's text flicker, flickering during initial installation when programming the video flash) + if (!machine().side_effects_disabled()) + std::copy_n(std::begin(m_sttga1_ram_obj), 0x2000, std::begin(m_sttga1_ram_obj) + 0x2000); + + return 0; +} + +void sttechno_state::sttga1_video_flash_w(offs_t offset, uint16_t data) +{ + if (!m_sttga1_video_flash_write_enable) + return; + + m_video_flash->write(offset, data); +} + +uint16_t sttechno_state::sttga1_video_flash_r(offs_t offset) +{ + return m_video_flash->read(offset); +} + +void sttechno_state::sttga1_video_flash_write_enable_w(offs_t offset, uint16_t data) +{ + // If it's set to 1 then 0xa00000 addresses flash, and if it's 0 then it addresses RAM? + m_sttga1_video_flash_write_enable = data != 0; +} + +void sttechno_state::sttga1_enabled_w(offs_t offset, uint16_t data) +{ + // Set to either 0 or 3 based on enabled status + m_sttga1_enabled = data != 0; +} + +void sttechno_state::cpu_map(address_map &map) +{ + map(0x000000, 0x07ffff).rom().nopw(); // unchecked null pointer makes the game spam a ton of writes to 0x00000c-0x00000e sometimes + map(0x200000, 0x3fffff).ram(); + + map(0x400000, 0x400001).r(FUNC(sttechno_state::video_unk_r)); + + map(0x500000, 0x500001).portr("IN1"); + map(0x500002, 0x500003).portr("IN2"); + map(0x500004, 0x500005).portw("OUT1"); + map(0x500006, 0x500007).portw("OUT2"); + map(0x500020, 0x500021).rw(m_sound, FUNC(stt_sa1_device::key_r), FUNC(stt_sa1_device::key_w)); + map(0x500022, 0x500023).w(m_sound, FUNC(stt_sa1_device::enable_w)); + map(0x500024, 0x500025).w(FUNC(sttechno_state::bank_w)); + map(0x500026, 0x500027).w(FUNC(sttechno_state::bank_write_enable_w)); + + map(0x600000, 0x600001).rw(FUNC(sttechno_state::uart_data_r), FUNC(sttechno_state::uart_data_w)); + map(0x600002, 0x600003).r(FUNC(sttechno_state::uart_txrdy_r)); + map(0x600004, 0x600005).w(FUNC(sttechno_state::uart_config_w)); + + map(0x70000c, 0x70000d).nopw(); // 2 is written here before CD-ROM commands are sent? + map(0x700010, 0x70001f).rw(FUNC(sttechno_state::ata_cs0_r), FUNC(sttechno_state::ata_cs0_w)); + map(0x700020, 0x700021).w(FUNC(sttechno_state::ata_control_w)); + + // Additionally, 0x100000 bytes for other RAM (framebuffer etc?) + map(0x800000, 0x807fff).ram().share(m_sttga1_ram_obj); // OBJ RAM + map(0x808000, 0x80ffff).ram().share(m_sttga1_ram_pal); // Palette RAM, 0x200 per palette + // 810000-81001f region contains some other registers which look like video display configuration registers but I'm not sure how to read it + map(0x810016, 0x810017).w(FUNC(sttechno_state::sttga1_enabled_w)); + map(0x810018, 0x810019).w(FUNC(sttechno_state::sttga1_video_flash_write_enable_w)); + + map(0xa00000, 0xbfffff).rw(FUNC(sttechno_state::sttga1_video_flash_r), FUNC(sttechno_state::sttga1_video_flash_w)); + + map(0xc00000, 0xdfffff).rw(FUNC(sttechno_state::data_r), FUNC(sttechno_state::data_w)); +} + +void sttechno_state::sound_map(address_map &map) +{ + map(0x000000, 0x5fffff).ram().share(m_sound_ram); + map(0x600000, 0x7fffff).r(m_flash[0], FUNC(intelfsh16_device::read_raw)); + map(0x800000, 0x9fffff).r(m_flash[1], FUNC(intelfsh16_device::read_raw)); +} + + +static INPUT_PORTS_START( shambros ) + PORT_START("IN1") + PORT_BIT( 0x3f00, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("Neck Upper") // 1P UP + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("Neck Center") // 1P MID + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("Neck Lower") // 1P LOW + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("Bachi") // 1P SHOT + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("Neck Upper") // 2P UP + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(2) PORT_NAME("Neck Center") // 2P MID + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON9 ) PORT_PLAYER(2) PORT_NAME("Neck Lower") // 2P LOW + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON10 ) PORT_PLAYER(2) PORT_NAME("Bachi") // 2P SHOT + PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_CUSTOM ) // 1P DETECT + PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_CUSTOM ) // 2P DETECT + + PORT_START("IN2") + PORT_BIT( 0xfe43, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) // Select up + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) // Select down + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_START ) // Enter + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_COIN1 ) // Coin + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_SERVICE1 ) // Service button + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_SERVICE ) // Test menu button + + PORT_START( "OUT1" ) + PORT_BIT( 0xfffa, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_OUTPUT ) // Coin meter + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_OUTPUT ) // Coin lockout + + PORT_START( "OUT2" ) + PORT_BIT( 0xfff8, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_OUTPUT ) // SEL UP + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_OUTPUT ) // SEL DOWN + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_OUTPUT ) // SEL DECI. +INPUT_PORTS_END + +static DEVICE_INPUT_DEFAULTS_START(debug_terminal) + DEVICE_INPUT_DEFAULTS("RS232_TXBAUD", 0xff, RS232_BAUD_115200) + DEVICE_INPUT_DEFAULTS("RS232_RXBAUD", 0xff, RS232_BAUD_115200) + DEVICE_INPUT_DEFAULTS("RS232_DATABITS", 0xff, RS232_DATABITS_8) + DEVICE_INPUT_DEFAULTS("RS232_PARITY", 0xff, RS232_PARITY_NONE) + DEVICE_INPUT_DEFAULTS("RS232_STOPBITS", 0xff, RS232_STOPBITS_1) +DEVICE_INPUT_DEFAULTS_END + + +static void sttechno_debug_serial_devices(device_slot_interface &device) +{ + device.option_add("null_modem", NULL_MODEM); + device.option_add("pty", PSEUDO_TERMINAL); + device.option_add("terminal", SERIAL_TERMINAL); +} + +void sttechno_state::shambros(machine_config &config) +{ + M68000(config, m_maincpu, XTAL(42'954'545) / 2); // divisor guessed, anything slower and the game stops functioning (timer flickers, CD-ROM reads are too slow) + m_maincpu->set_addrmap(AS_PROGRAM, &sttechno_state::cpu_map); + + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_raw(XTAL(42'954'545) / 6, 456, 0, 336, 262, 0, 240); // guessed + screen.set_screen_update(FUNC(sttechno_state::screen_update)); + screen.screen_vblank().set_inputline(m_maincpu, M68K_IRQ_2); + screen.set_palette("palette"); + + PALETTE(config, "palette", palette_device::BGR_555); + + ATA_INTERFACE(config, m_ata).options(ata_devices, "cdrom", nullptr, true); + m_ata->slot(0).set_option_machine_config("cdrom", [] (device_t *device) { downcast<atapi_cdrom_device &>(*device).set_is_ready(true); }); + + FUJITSU_29F160TE_16BIT(config, m_flash[0]); + FUJITSU_29F160TE_16BIT(config, m_flash[1]); + FUJITSU_29F160TE_16BIT(config, m_video_flash); + + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + STT_SA1(config, m_sound, XTAL(42'954'545) / 3); + m_sound->set_addrmap(0, &sttechno_state::sound_map); + m_sound->add_route(0, "lspeaker", 1.0); + m_sound->add_route(1, "rspeaker", 1.0); + TIMER(config, "irq6_timer").configure_periodic(FUNC(sttechno_state::irq6_timer), attotime::from_hz(XTAL(42'954'545) / 3 / 448 / 128)); // probably some interrupt? + + RS232_PORT(config, m_rs232, sttechno_debug_serial_devices, nullptr); + m_rs232->set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(debug_terminal)); + m_rs232->set_option_device_input_defaults("pty", DEVICE_INPUT_DEFAULTS_NAME(debug_terminal)); + m_rs232->set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(debug_terminal)); + m_rs232->rxd_handler().set(FUNC(sttechno_state::rx_w)); +} + + +ROM_START( shambros ) + ROM_REGION(0x80000, "maincpu", 0) + ROM_LOAD16_WORD_SWAP( "g112 v1.01.u46", 0x00000, 0x80000, CRC(6e13bcde) SHA1(189b0052083717030ca868b95b9d43e1faaf9695) ) + + DISK_REGION( "ata:0:cdrom" ) + DISK_IMAGE( "sb01-100", 0, SHA1(abd1d61871bcb4635acc691e35ec386823763ba2) ) +ROM_END + +} // anonymous namespace + + +GAME( 2003, shambros, 0, shambros, shambros, sttechno_state, empty_init, ROT0, "Kato's", "Shamisen Brothers Vol 1 (V1.01K)", MACHINE_IMPERFECT_TIMING ) |