summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author angelosa <lordkale4@gmail.com>2025-10-25 22:41:58 +0200
committer angelosa <lordkale4@gmail.com>2025-10-25 22:42:09 +0200
commitbff55111780d7cadc7fccd0618c99847a2944e3a (patch)
treede5646ca68421f590fb09a05aaa4158fd64e8cf7
parent3a0cd99a8e3c678a01f35ac842636eb15325dc18 (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.lua2
-rw-r--r--src/devices/bus/nscsi/pc8801_30.cpp433
-rw-r--r--src/devices/bus/nscsi/pc8801_30.h54
-rw-r--r--src/devices/bus/pc8801/pc8801_31.cpp129
-rw-r--r--src/devices/bus/pc8801/pc8801_31.h16
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);
};