diff options
| author | 2025-10-25 22:41:58 +0200 | |
|---|---|---|
| committer | 2025-10-25 22:42:09 +0200 | |
| commit | bff55111780d7cadc7fccd0618c99847a2944e3a (patch) | |
| tree | de5646ca68421f590fb09a05aaa4158fd64e8cf7 | |
| parent | 3a0cd99a8e3c678a01f35ac842636eb15325dc18 (diff) | |
bus/pc8801/pc8801_31.cpp: fix SCSI hookup, translate PCE CD implementation in NSCSI device as PC8801-30
| -rw-r--r-- | scripts/src/bus.lua | 2 | ||||
| -rw-r--r-- | src/devices/bus/nscsi/pc8801_30.cpp | 433 | ||||
| -rw-r--r-- | src/devices/bus/nscsi/pc8801_30.h | 54 | ||||
| -rw-r--r-- | src/devices/bus/pc8801/pc8801_31.cpp | 129 | ||||
| -rw-r--r-- | src/devices/bus/pc8801/pc8801_31.h | 16 |
5 files changed, 584 insertions, 50 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 6658d68f9e3..1a8a700e78b 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -3343,6 +3343,8 @@ if (BUSES["NSCSI"]~=null) then MAME_DIR .. "src/devices/bus/nscsi/devices.h", MAME_DIR .. "src/devices/bus/nscsi/hd.cpp", MAME_DIR .. "src/devices/bus/nscsi/hd.h", + MAME_DIR .. "src/devices/bus/nscsi/pc8801_30.cpp", + MAME_DIR .. "src/devices/bus/nscsi/pc8801_30.h", MAME_DIR .. "src/devices/bus/nscsi/s1410.cpp", MAME_DIR .. "src/devices/bus/nscsi/s1410.h", MAME_DIR .. "src/devices/bus/nscsi/smoc501.cpp", diff --git a/src/devices/bus/nscsi/pc8801_30.cpp b/src/devices/bus/nscsi/pc8801_30.cpp new file mode 100644 index 00000000000..6e58d688c12 --- /dev/null +++ b/src/devices/bus/nscsi/pc8801_30.cpp @@ -0,0 +1,433 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese + +#include "emu.h" +#include "pc8801_30.h" + +#include "coreutil.h" +#include "multibyte.h" + +#define LOG_CMD (1U << 1) +#define LOG_CDDA (1U << 2) + +#define VERBOSE (LOG_GENERAL | LOG_CMD) +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + +#define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__) +#define LOGCDDA(...) LOGMASKED(LOG_CDDA, __VA_ARGS__) + +DEFINE_DEVICE_TYPE(NSCSI_CDROM_PC8801_30, nscsi_cdrom_pc8801_30_device, "scsi_pc8801_30", "SCSI NEC PC8801-30 CD-ROM") + +nscsi_cdrom_pc8801_30_device::nscsi_cdrom_pc8801_30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + nscsi_cdrom_device(mconfig, NSCSI_CDROM_PC8801_30, tag, owner, clock) +{ +} + +void nscsi_cdrom_pc8801_30_device::device_reset() +{ + nscsi_cdrom_device::device_reset(); + m_cdda_status = PCE_CD_CDDA_OFF; + cdda->stop_audio(); +} + + +bool nscsi_cdrom_pc8801_30_device::scsi_command_done(uint8_t command, uint8_t length) +{ + switch (command) + { + case 0xd8: + case 0xd9: + case 0xda: + case 0xdd: + case 0xde: + return length == 10; + + default: + return nscsi_cdrom_device::scsi_command_done(command, length); + } +} + +void nscsi_cdrom_pc8801_30_device::nec_set_audio_start_position() +{ + uint32_t frame = 0; + const uint8_t mode = scsi_cmdbuf[9] & 0xc0; + + LOGCMD("0xd8 SET AUDIO PLAYBACK START POSITION (NEC): mode %02x\n", mode); + if (!image->exists()) + { + return_no_cd(); + return; + } + + const cdrom_file::toc &toc = image->get_toc(); + + switch (mode) + { + case 0x00: + popmessage("CD-DA set start mode 0x00"); + frame = (scsi_cmdbuf[3] << 16) | (scsi_cmdbuf[4] << 8) | scsi_cmdbuf[5]; + break; + case 0x40: + { + const u8 m = bcd_2_dec(scsi_cmdbuf[2]); + const u8 s = bcd_2_dec(scsi_cmdbuf[3]); + const u8 f = bcd_2_dec(scsi_cmdbuf[4]); + frame = f + 75 * (s + m * 60); + + + const u32 pregap = toc.tracks[image->get_track(frame)].pregap; + + LOGCMD("MSF=%d %02d:%02d:%02d (pregap = %d)\n", frame, m, s, f, pregap); + // PCE tries to be clever here and set (start of track + track pregap size) to skip the pregap + // default to 2 secs if that isn't provided + // cfr. draculax in-game, fzone2 / fzone2j / ddragon2 intro etc. + // TODO: is this a global issue and INDEX 01 with no explicit pregap is always 2 seconds in INDEX 00 like in the aforementioned examples? + frame -= std::max(pregap, (u32)150); + break; + } + case 0x80: + { + const u8 track_number = bcd_2_dec(scsi_cmdbuf[2]); + const u32 pregap = toc.tracks[image->get_track(track_number - 1)].pregap; + LOGCMD("TRACK=%d (pregap = %d)\n", track_number, pregap); + frame = toc.tracks[ track_number - 1 ].logframeofs; + // Not right for emeraldd, breaks intro lip sync + //frame -= std::max(pregap, (u32)150); + break; + } + default: + popmessage("CD-DA set start mode 0xc0"); + //assert(nullptr == nec_set_audio_start_position); + break; + } + + m_current_frame = frame; + + m_cdda_status = PCE_CD_CDDA_PAUSED; + + const u8 play_mode = scsi_cmdbuf[1] & 0x03; + LOGCMD("Play mode = %d\n", play_mode); + if (play_mode) + { + // Required by audio CD player + // (will keep skipping tracks over and over, never sends an audio end command) + m_cdda_status = PCE_CD_CDDA_PLAYING; + m_end_frame = m_last_frame; + + LOGCDDA("Audio start (end of CD) current %d end %d\n", m_current_frame, m_end_frame); + + cdda->start_audio(m_current_frame, m_end_frame - m_current_frame); + m_cdda_play_mode = (play_mode & 0x02) ? 2 : 3; // mode 2 sets IRQ at end + m_end_mark = (play_mode & 0x02) ? 1 : 0; + } + else + { + //m_cdda_status = PCE_CD_CDDA_PLAYING; + m_end_frame = toc.tracks[ image->get_track(m_current_frame) ].logframeofs + + toc.tracks[ image->get_track(m_current_frame) ].logframes; + + LOGCDDA("Audio start (end of track) current %d end %d\n", m_current_frame, m_end_frame); + // Several places definitely don't want this to start redbook, + // it's done later with 0xd9 command. + // - fzone2 / fzone2j + // - draculax (stage 2' pre-boss) + // - manhole (fires this during Sunsoft logo but expects playback on successive + // credit sequence instead) + //if (m_end_frame > m_current_frame) + // m_cdda->start_audio(m_current_frame, m_end_frame - m_current_frame); + + // These ones additionally wants a CDDA pause issued: + // - audio CD player ("fade out" button trigger, otherwise will playback the + // very next track at the end of the sequence) + // - ppersia (picking up sword in stage 1, cancels then restarts redbook BGM) + cdda->pause_audio(1); + m_cdda_play_mode = 3; + m_end_mark = 0; + + // snatcher requires that the irq is sent here + // otherwise it will hang on title screen + // set_irq_line(PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE); + } + + scsi_data_in(SBUF_MAIN, 0); + scsi_status_complete(SS_GOOD); + // Definitely not here, breaks jleagt94, iganin, macr2036 "press RUN button" prompt + // (expects to fire an irq at the end of redbook playback thru end_mark = 2 for proper attract mode) + //set_irq_line(PCE_CD_IRQ_TRANSFER_DONE, ASSERT_LINE); +} + +void nscsi_cdrom_pc8801_30_device::nec_set_audio_stop_position() +{ + uint32_t frame = 0; + const uint8_t mode = scsi_cmdbuf[9] & 0xc0; + LOGCMD("0xd9 SET AUDIO PLAYBACK END POSITION (NEC): mode %02x\n", mode); + + if (!image->exists()) + { + return_no_cd(); + return; + } + + const cdrom_file::toc &toc = image->get_toc(); + + switch (mode) + { + case 0x00: + // tadaima + popmessage("CD-DA set end mode 0x00"); + frame = (scsi_cmdbuf[3] << 16) | (scsi_cmdbuf[4] << 8) | scsi_cmdbuf[5]; + break; + case 0x40: + { + const u8 m = bcd_2_dec(scsi_cmdbuf[2]); + const u8 s = bcd_2_dec(scsi_cmdbuf[3]); + const u8 f = bcd_2_dec(scsi_cmdbuf[4]); + const u32 pregap = toc.tracks[image->get_track(frame)].pregap; + + frame = f + 75 * (s + m * 60); + LOGCMD("MSF=%d %02d:%02d:%02d (pregap = %d)\n", frame, m, s, f, pregap); + frame -= std::max(pregap, (u32)150); + break; + } + case 0x80: + { + const u8 track_number = bcd_2_dec(scsi_cmdbuf[2]); + const u32 pregap = toc.tracks[image->get_track(track_number - 1)].pregap; + // NB: crazyhos uses this command with track = 1 on pre-title screen intro. + // It's not supposed to playback anything according to real HW refs. + frame = toc.tracks[ track_number - 1 ].logframeofs; + + LOGCMD("TRACK=%d (raw %02x pregap = %d frame = %d)\n" + , track_number + , scsi_cmdbuf[2] + , pregap + , frame + ); + //frame -= std::max(pregap, (u32)150); + break; + } + default: + popmessage("CD-DA set end mode 0xc0"); + //assert(nullptr == nec_set_audio_start_position); + break; + } + + m_end_frame = frame; + m_cdda_play_mode = scsi_cmdbuf[1] & 0x03; + LOGCMD("Play mode = %d\n", m_cdda_play_mode); + + if (m_cdda_play_mode) + { + if (m_cdda_status == PCE_CD_CDDA_PAUSED) + { + LOGCDDA("Audio unpause\n"); + cdda->pause_audio(0); + } + + LOGCDDA("Audio end current %d end %d\n", m_current_frame, m_end_frame); + //printf("%08x %08x\n",m_current_frame,m_end_frame - m_current_frame); + cdda->start_audio(m_current_frame, m_end_frame - m_current_frame); + m_end_mark = 1; + m_cdda_status = PCE_CD_CDDA_PLAYING; + } + else + { + LOGCDDA("Audio stop\n"); + m_cdda_status = PCE_CD_CDDA_OFF; + cdda->stop_audio(); + m_end_frame = m_last_frame; + m_end_mark = 0; +// assert(nullptr == nec_set_audio_stop_position); + } + + scsi_data_in(SBUF_MAIN, 0); + scsi_status_complete(SS_GOOD); +} + + +void nscsi_cdrom_pc8801_30_device::nec_pause() +{ + if (!image->exists()) + { + return_no_cd(); + return; + } + + LOGCMD("0xda PAUSE (NEC)\n"); + + /* If there was no cdda playing, throw an error */ + if (m_cdda_status == PCE_CD_CDDA_OFF) + { + // TODO: sense key/ASC/ASCQ + LOG("Issued SCSI_CHECK_CONDITION in 0xda!\n"); + scsi_status_complete(SS_CHECK_CONDITION); + return; + } + + m_cdda_status = PCE_CD_CDDA_PAUSED; + m_current_frame = cdda->get_audio_lba(); + LOGCDDA("Audio pause on %d LBA\n", m_current_frame); + cdda->pause_audio(1); + + scsi_data_in(SBUF_MAIN, 0); + scsi_status_complete(SS_GOOD); +} + +void nscsi_cdrom_pc8801_30_device::nec_get_subq() +{ + /* WP - I do not have access to chds with subchannel information yet, so I'm faking something here */ + uint32_t msf_abs, msf_rel, track, frame; + //LOGCMD("0xdd READ SUBCHANNEL Q (NEC) %d\n", m_cdda_status); + + if (!image->exists()) + { + return_no_cd(); + return; + } + + frame = m_current_frame; + + switch (m_cdda_status) + { + case PCE_CD_CDDA_PAUSED: + scsi_cmdbuf[0] = 2; + frame = cdda->get_audio_lba(); + break; + case PCE_CD_CDDA_PLAYING: + scsi_cmdbuf[0] = 0; + frame = cdda->get_audio_lba(); + break; + default: + scsi_cmdbuf[0] = 3; + break; + } + + msf_abs = cdrom_file::lba_to_msf_alt(frame); + track = image->get_track(frame); + msf_rel = cdrom_file::lba_to_msf_alt(frame - image->get_track_start(track)); + + scsi_cmdbuf[1] = 0x01 | ((image->get_track_type(image->get_track(track+1)) == cdrom_file::CD_TRACK_AUDIO) ? 0x00 : 0x40); + // track + scsi_cmdbuf[2] = dec_2_bcd(track+1); + // index + scsi_cmdbuf[3] = 1; + // MSF (relative) + scsi_cmdbuf[4] = dec_2_bcd((msf_rel >> 16) & 0xFF); + scsi_cmdbuf[5] = dec_2_bcd((msf_rel >> 8) & 0xFF); + scsi_cmdbuf[6] = dec_2_bcd(msf_rel & 0xFF); + // MSF (absolute) + scsi_cmdbuf[7] = dec_2_bcd((msf_abs >> 16) & 0xFF); + scsi_cmdbuf[8] = dec_2_bcd((msf_abs >> 8) & 0xFF); + scsi_cmdbuf[9] = dec_2_bcd(msf_abs & 0xFF); + //if(LIVE_SUBQ_VIEW) + //{ + // const std::vector<std::string> status_types = {"standby", "play", "pause"}; + // popmessage("SUBQ - status %s type %02x|track %d index %d| MSF rel %06x MSF abs %06x\n" + // , status_types[m_cdda_status] + // , m_data_buffer[1] + // , track + 1 + // , 1 + // , msf_rel + // , msf_abs + // ); + //} + + scsi_data_in(SBUF_MAIN, 10); + scsi_status_complete(SS_GOOD); +} + + +void nscsi_cdrom_pc8801_30_device::nec_get_dir_info() +{ + LOGCMD("0xde GET DIR INFO (NEC)\n"); + + if (!image->exists()) + { + return_no_cd(); + return; + } + + // NOTE: PC8801-30 CD player wants 4 bytes back vs. PC Engine + switch(scsi_cmdbuf[1]) + { + case 0x00: + scsi_cmdbuf[0] = dec_2_bcd(1); + scsi_cmdbuf[1] = dec_2_bcd(image->get_last_track()); + scsi_cmdbuf[2] = 0; + scsi_cmdbuf[3] = 0; + LOGCMD("Get first and last track numbers => 1-%02x\n", scsi_cmdbuf[1]); + + scsi_data_in(SBUF_MAIN, 4); + scsi_status_complete(SS_GOOD); + break; + case 0x01: + { + const uint32_t start_lba = image->get_track_start(0xaa); + const uint32_t start_frame = to_msf(start_lba); + LOGCMD("Get total disk size in MSF format => %06x\n", start_frame); + + //scsi_cmdbuf[0] = image->get_adr_control(image->get_last_track()); + scsi_cmdbuf[0] = dec_2_bcd(BIT(start_frame, 16, 8)); // minutes + scsi_cmdbuf[1] = dec_2_bcd(BIT(start_frame, 8, 8)); // seconds + scsi_cmdbuf[2] = dec_2_bcd(BIT(start_frame, 0, 8)); // frames + scsi_cmdbuf[3] = 0; + + scsi_data_in(SBUF_MAIN, 4); + scsi_status_complete(SS_GOOD); + break; + } + case 0x02: + { + uint32_t frame; + uint8_t track_type; + if (scsi_cmdbuf[2] == 0xaa) + { + const uint32_t start_lba = image->get_track_start(image->get_last_track()); + frame = to_msf(start_lba); + LOGCMD("Get lead-out => %06x\n", frame); + // TODO: correct? + track_type = 0x04; + } + else + { + const u8 track = std::max(bcd_2_dec(scsi_cmdbuf[2]), 1U); + const uint32_t start_lba = image->get_track_start(track); + frame = to_msf(start_lba); + LOGCMD("Get track info track = %d, frame = %d\n", track, frame); + + track_type = image->get_track_type(track) == cdrom_file::CD_TRACK_AUDIO ? 0x00 : 0x04; + } + + scsi_cmdbuf[0] = dec_2_bcd(BIT(frame, 16, 8)); // minutes + scsi_cmdbuf[1] = dec_2_bcd(BIT(frame, 8, 8)); // seconds + scsi_cmdbuf[2] = dec_2_bcd(BIT(frame, 0, 8)); // frames + scsi_cmdbuf[3] = track_type; + + scsi_data_in(SBUF_MAIN, 4); + scsi_status_complete(SS_GOOD); + + break; + } + } +} + +void nscsi_cdrom_pc8801_30_device::scsi_command() +{ + switch (scsi_cmdbuf[0]) + { + case 0xd8: nec_set_audio_start_position(); break; + case 0xd9: nec_set_audio_stop_position(); break; + case 0xda: nec_pause(); break; + case 0xdd: nec_get_subq(); break; + case 0xde: nec_get_dir_info(); break; + + default: + if (scsi_cmdbuf[0] != 0) + LOGCMD("Not yet emulated command %02x\n", scsi_cmdbuf[0]); + // TODO: purge commands that don't exist on this implementation + nscsi_cdrom_device::scsi_command(); + break; + } +} + diff --git a/src/devices/bus/nscsi/pc8801_30.h b/src/devices/bus/nscsi/pc8801_30.h new file mode 100644 index 00000000000..47ea42e144f --- /dev/null +++ b/src/devices/bus/nscsi/pc8801_30.h @@ -0,0 +1,54 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese + +#ifndef MAME_BUS_NSCSI_PC8801_30_H +#define MAME_BUS_NSCSI_PC8801_30_H + +#pragma once + +#include "bus/nscsi/cd.h" + +#include "imagedev/cdromimg.h" +#include "machine/nscsi_bus.h" +#include "sound/cdda.h" + +#include "cdrom.h" + +class nscsi_cdrom_pc8801_30_device : public nscsi_cdrom_device +{ +public: + nscsi_cdrom_pc8801_30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + +protected: + virtual void device_reset() override ATTR_COLD; + + virtual void scsi_command() override; + virtual bool scsi_command_done(uint8_t command, uint8_t length) override; +private: + void nec_set_audio_start_position(); + void nec_set_audio_stop_position(); + void nec_pause(); + void nec_get_subq(); + void nec_get_dir_info(); + + enum { + PCE_CD_CDDA_OFF = 0, + PCE_CD_CDDA_PLAYING, + PCE_CD_CDDA_PAUSED + }; + + uint32_t m_current_frame = 0; + uint32_t m_end_frame = 0; + uint32_t m_last_frame = 0; + uint8_t m_cdda_status = 0; + uint8_t m_cdda_play_mode = 0; + + uint8_t m_end_mark = 0; + +}; + +DECLARE_DEVICE_TYPE(NSCSI_CDROM_PC8801_30, nscsi_cdrom_pc8801_30_device) + + +#endif // MAME_BUS_NSCSI_PC8801_30_H + diff --git a/src/devices/bus/pc8801/pc8801_31.cpp b/src/devices/bus/pc8801/pc8801_31.cpp index d125b9c9ad6..7291378b229 100644 --- a/src/devices/bus/pc8801/pc8801_31.cpp +++ b/src/devices/bus/pc8801/pc8801_31.cpp @@ -13,6 +13,9 @@ #include "emu.h" #include "pc8801_31.h" +#include "bus/nscsi/pc8801_30.h" + +#include "speaker.h" //************************************************************************** // GLOBAL VARIABLES @@ -35,7 +38,8 @@ DEFINE_DEVICE_TYPE(PC8801_31, pc8801_31_device, "pc8801_31", "NEC PC8801-31 CD-R pc8801_31_device::pc8801_31_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, PC8801_31, tag, owner, clock) - , m_scsibus(*this, "scsi") + , m_sasibus(*this, "sasi") + , m_sasi(*this, "sasi:7:sasicb") , m_rom_bank_cb(*this) , m_sel_off_timer(nullptr) { @@ -49,22 +53,33 @@ pc8801_31_device::pc8801_31_device(const machine_config &mconfig, const char *ta static void pc8801_scsi_devices(device_slot_interface &device) { - // TODO: PC8801-30 - device.option_add("cdrom", NSCSI_CDROM); + device.option_add("cdrom", NSCSI_CDROM_PC8801_30); // TODO: at very least HxC Floppy emulator option } void pc8801_31_device::device_add_mconfig(machine_config &config) { - NSCSI_BUS(config, m_scsibus); - NSCSI_CONNECTOR(config, "scsi:0", pc8801_scsi_devices, "cdrom"); - NSCSI_CONNECTOR(config, "scsi:1", pc8801_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsi:2", pc8801_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsi:3", pc8801_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsi:4", pc8801_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsi:5", pc8801_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsi:6", pc8801_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsi:7", pc8801_scsi_devices, nullptr); + SPEAKER(config, "speaker", 2).front_center(); + + NSCSI_BUS(config, m_sasibus); + NSCSI_CONNECTOR(config, "sasi:0").option_set("cdrom", NSCSI_CDROM_PC8801_30).machine_config( + [](device_t *device) + { + device->subdevice<cdda_device>("cdda")->add_route(0, "^^speaker", 0.5, 0); + device->subdevice<cdda_device>("cdda")->add_route(1, "^^speaker", 0.5, 1); + }); + NSCSI_CONNECTOR(config, "sasi:1", pc8801_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "sasi:2", pc8801_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "sasi:3", pc8801_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "sasi:4", pc8801_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "sasi:5", pc8801_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "sasi:6", pc8801_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "sasi:7", default_scsi_devices, "sasicb", true) + .option_add_internal("sasicb", NSCSI_CB) + .machine_config([this](device_t* device) { + downcast<nscsi_callback_device&>(*device).sel_callback().set(*this, FUNC(pc8801_31_device::sasi_sel_w)); + }); + SOFTWARE_LIST(config, "cd_list").set_original("pc8801_cdrom"); } @@ -76,7 +91,7 @@ void pc8801_31_device::device_add_mconfig(machine_config &config) void pc8801_31_device::device_start() { - m_sel_off_timer = timer_alloc(FUNC(pc8801_31_device::select_off), this); + m_sel_off_timer = timer_alloc(FUNC(pc8801_31_device::select_off_cb), this); save_item(NAME(m_clock_hb)); save_item(NAME(m_cddrive_enable)); @@ -96,9 +111,9 @@ void pc8801_31_device::device_reset() m_sel_off_timer->adjust(attotime::never); } -TIMER_CALLBACK_MEMBER(pc8801_31_device::select_off) +TIMER_CALLBACK_MEMBER(pc8801_31_device::select_off_cb) { - m_scsibus->ctrl_w(0, 0, nscsi_device::S_SEL); + m_sasi->sel_w(0); } @@ -110,10 +125,27 @@ TIMER_CALLBACK_MEMBER(pc8801_31_device::select_off) void pc8801_31_device::amap(address_map &map) { - map(0x00, 0x00).rw(FUNC(pc8801_31_device::scsi_status_r), FUNC(pc8801_31_device::scsi_sel_w)); + map(0x00, 0x00).rw(FUNC(pc8801_31_device::status_r), FUNC(pc8801_31_device::select_w)); map(0x01, 0x01).lrw8( - NAME([this]() { return m_scsibus->data_r(); }), - NAME([this](u8 data) { m_scsibus->data_w(0, data); }) + NAME([this]() { + u8 res = m_sasi->read(); + if ((m_sasi->req_r()) && (m_sasi->io_r())) + { + m_sasi->ack_w(1); + m_sasi->ack_w(0); + } + return res; + }), + NAME([this](u8 data) { + m_sasi->write(data); + + if (m_sasi->req_r()) + { + m_sasi->ack_w(1); + //m_sasi->write(0); + m_sasi->ack_w(0); + } + }) ); map(0x04, 0x04).w(FUNC(pc8801_31_device::scsi_reset_w)); map(0x08, 0x08).rw(FUNC(pc8801_31_device::clock_r), FUNC(pc8801_31_device::volume_control_w)); @@ -139,31 +171,35 @@ void pc8801_31_device::amap(address_map &map) * It eventually moves on floppy/BASIC fallback if this check fails. * */ -u8 pc8801_31_device::scsi_status_r() -{ - u32 ctrl = m_scsibus->ctrl_r(); - return ( - (ctrl & nscsi_device::S_BSY ? 0x80 : 0x00) | - (ctrl & nscsi_device::S_REQ ? 0x40 : 0x00) | - (ctrl & nscsi_device::S_MSG ? 0x20 : 0x00) | - (ctrl & nscsi_device::S_CTL ? 0x10 : 0x00) | - (ctrl & nscsi_device::S_INP ? 0x08 : 0x00) | - m_cddrive_enable - ); +u8 pc8801_31_device::status_r() +{ + u8 res = (m_sasi->bsy_r() << 7 | + m_sasi->req_r() << 6 | + m_sasi->msg_r() << 5 | + m_sasi->cd_r() << 4 | + m_sasi->io_r() << 3 | + m_cddrive_enable); + + if (m_sasi_sel) + res &= ~0xb8; + + return res; } -void pc8801_31_device::scsi_sel_w(u8 data) +void pc8801_31_device::select_w(u8 data) { - bool sel_on = bool(BIT(data, 0)); - m_scsibus->ctrl_w( - 0, - sel_on ? nscsi_device::S_SEL : 0, - nscsi_device::S_SEL - ); - - // TODO: timing - if (sel_on) - m_sel_off_timer->adjust(attotime::from_usec(10)); + if (BIT(data, 0)) + { + if (m_cddrive_enable) + { + m_sasi->sel_w(1); + + // TODO: timing + m_sel_off_timer->adjust(attotime::from_usec(5000)); + } + } + else + m_sasi->sel_w(0); } /* @@ -203,11 +239,8 @@ void pc8801_31_device::volume_control_w(u8 data) */ void pc8801_31_device::scsi_reset_w(u8 data) { - m_scsibus->ctrl_w( - 0, - BIT(data, 7) ? nscsi_device::S_RST : 0, - nscsi_device::S_RST - ); + if (BIT(data, 7)) + m_sasibus->reset(); } u8 pc8801_31_device::id_r() @@ -249,3 +282,9 @@ u8 pc8801_31_device::volume_meter_r() { return 0; } + +void pc8801_31_device::sasi_sel_w(int state) +{ + //m_sasi->req_w(state); + m_sasi_sel = state; +} diff --git a/src/devices/bus/pc8801/pc8801_31.h b/src/devices/bus/pc8801/pc8801_31.h index cc68677ca6d..ce697b546be 100644 --- a/src/devices/bus/pc8801/pc8801_31.h +++ b/src/devices/bus/pc8801/pc8801_31.h @@ -11,8 +11,10 @@ #pragma once -#include "machine/nscsi_bus.h" #include "bus/nscsi/cd.h" +#include "bus/nscsi/devices.h" +#include "machine/nscsi_bus.h" +#include "machine/nscsi_cb.h" //************************************************************************** // TYPE DEFINITIONS @@ -37,17 +39,18 @@ protected: virtual void device_start() override ATTR_COLD; virtual void device_reset() override ATTR_COLD; - TIMER_CALLBACK_MEMBER(select_off); + TIMER_CALLBACK_MEMBER(select_off_cb); private: - required_device<nscsi_bus_device> m_scsibus; + required_device<nscsi_bus_device> m_sasibus; + required_device<nscsi_callback_device> m_sasi; devcb_write_line m_rom_bank_cb; emu_timer *m_sel_off_timer; - u8 scsi_status_r(); - void scsi_sel_w(u8 data); + u8 status_r(); + void select_w(u8 data); void scsi_reset_w(u8 data); u8 clock_r(); void volume_control_w(u8 data); @@ -57,6 +60,9 @@ private: bool m_clock_hb; bool m_cddrive_enable; + int m_sasi_sel; + + void sasi_sel_w(int line); }; |
