summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/rs232/xvd701.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/rs232/xvd701.cpp')
-rw-r--r--src/devices/bus/rs232/xvd701.cpp253
1 files changed, 204 insertions, 49 deletions
diff --git a/src/devices/bus/rs232/xvd701.cpp b/src/devices/bus/rs232/xvd701.cpp
index b2635d21c02..3b1c3843f96 100644
--- a/src/devices/bus/rs232/xvd701.cpp
+++ b/src/devices/bus/rs232/xvd701.cpp
@@ -1,12 +1,23 @@
// license:BSD-3-Clause
-// copyright-holders:smf
+// copyright-holders:smf, DragonMinded, windyfairy
+
#include "emu.h"
#include "xvd701.h"
+#define LOG_COMMAND (1U << 1)
+// #define VERBOSE (LOG_COMMAND)
+// #define LOG_OUTPUT_STREAM std::cout
+
+#include "logmacro.h"
+
+#define LOGCMD(...) LOGMASKED(LOG_COMMAND, __VA_ARGS__)
+
+
jvc_xvd701_device::jvc_xvd701_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, JVC_XVD701, tag, owner, clock),
device_serial_interface(mconfig, *this),
device_rs232_port_interface(mconfig, *this),
+ m_media_type(JVC_MEDIA_VCD), // TODO: This should be changed based on the type of disc inserted or else seeking won't work properly
m_response_index(0),
m_timer_response(nullptr)
{
@@ -47,7 +58,7 @@ void jvc_xvd701_device::device_start()
output_ri(0);
output_cts(0);
- m_timer_response = timer_alloc(TIMER_RESPONSE);
+ m_timer_response = timer_alloc(FUNC(jvc_xvd701_device::send_response), this);
}
void jvc_xvd701_device::device_reset()
@@ -55,19 +66,11 @@ void jvc_xvd701_device::device_reset()
memset(m_command, 0, sizeof(m_command));
m_response_index = sizeof(m_response);
-}
-void jvc_xvd701_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_RESPONSE:
- send_response();
- break;
-
- default:
- break;
- }
+ m_jlip_id = 33; // Twinkle default
+ m_is_powered = false;
+ m_chapter = 0;
+ m_playback_status = STATUS_STOP;
}
void jvc_xvd701_device::tra_callback()
@@ -82,15 +85,28 @@ void jvc_xvd701_device::tra_complete()
unsigned char jvc_xvd701_device::sum(unsigned char *buffer, int length)
{
- int sum = 0;
+ int sum = 0x80;
for (int i = 0; i < length; i++)
- sum += buffer[i];
+ sum -= buffer[i] & 0x7f;
return sum & 0x7f;
}
-void jvc_xvd701_device::send_response()
+void jvc_xvd701_device::create_packet(unsigned char status, const unsigned char response[6])
+{
+ m_response[0] = 0xfc;
+ m_response[1] = 0xff;
+ m_response[2] = m_jlip_id;
+ m_response[3] = status;
+ memcpy(&m_response[4], response, 6);
+ m_response[10] = sum(m_response, sizeof(m_response) - 1);
+
+ m_response_index = 0;
+ m_timer_response->adjust(attotime::from_msec(100));
+}
+
+TIMER_CALLBACK_MEMBER(jvc_xvd701_device::send_response)
{
if (m_response_index < sizeof(m_response) && is_transmit_register_empty())
{
@@ -99,6 +115,22 @@ void jvc_xvd701_device::send_response()
}
}
+bool jvc_xvd701_device::seek_chapter(int chapter)
+{
+ if (chapter <= 0)
+ {
+ // Chapters are from 1 and up
+ return false;
+ }
+
+ m_chapter = chapter;
+
+ if (m_playback_status != STATUS_PAUSE)
+ m_playback_status = STATUS_PLAYING;
+
+ return true;
+}
+
void jvc_xvd701_device::rcv_complete()
{
receive_register_extract();
@@ -110,39 +142,162 @@ void jvc_xvd701_device::rcv_complete()
if (m_command[0] == 0xff &&
m_command[1] == 0xff &&
- m_command[2] == 0x21 &&
- sum(m_command, sizeof(m_command)) == 0)
+ m_command[10] == sum(m_command, sizeof(m_command) - 1))
{
- // printf("xvd701");
-
- //for (int i = 0; i < sizeof(m_command); i++)
- // printf(" %02x", m_command[i]);
-
- //printf("\n");
-
- // FF FF 21 3E 40 70 00 00 00 00 73 DEVICE ON
- // FF FF 21 3E 40 60 00 00 00 00 03 DEVICE OFF
- // FF FF 21 0C 44 60 00 00 00 00 31 STOP
- // FF FF 21 0C 43 75 00 00 00 00 1D PLAY
- // FF FF 21 0C 43 6D 00 00 00 00 25 PAUSE
- // FF FF 21 0C 50 20 00 00 00 00 63 SEEK TO SPECIFIC CHAPTER
- // FF FF 21 0C 50 73 00 00 00 00 12 FF (SEEK TO NEXT CHAPTER)
- // FF FF 21 0C 50 61 00 00 00 00 24 PREV (SEEK TO PREVIOUS CHAPTER)
-
- m_response[0] = 0xff;
- m_response[1] = 0xfe;
- m_response[2] = 0x7f;
- m_response[3] = 0x7e;
- m_response[4] = 0x7d;
- m_response[5] = 0x7c;
- m_response[6] = 0x7b;
- m_response[7] = 0x7a;
- m_response[8] = 0x79;
- m_response[9] = 0x78;
- m_response[10] = 0x77;
- m_response_index = 0;
-
- m_timer_response->adjust(attotime::from_msec(100));
+ if (m_command[3] == 0x0c && m_command[4] == 0x43 && m_command[5] == 0x6d)
+ {
+ // FF FF 21 0C 43 6D 00 00 00 00 25 PAUSE
+ LOGCMD("xvd701: Playback PAUSE\n");
+ m_playback_status = STATUS_PAUSE;
+ create_packet(STATUS_OK, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x0c && m_command[4] == 0x43 && m_command[5] == 0x75)
+ {
+ // FF FF 21 0C 43 75 00 00 00 00 1D PLAY
+ LOGCMD("xvd701: Playback PLAY\n");
+
+ auto status = STATUS_OK;
+ if (m_playback_status == STATUS_STOP)
+ {
+ // Force video to load again if the video was stopped then started again
+ if (!seek_chapter(m_chapter))
+ status = STATUS_ERROR;
+ }
+
+ if (status == STATUS_OK)
+ m_playback_status = STATUS_PLAYING;
+
+ create_packet(status, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x0c && m_command[4] == 0x44 && m_command[5] == 0x60)
+ {
+ // FF FF 21 0C 44 60 00 00 00 00 31 STOP
+ LOGCMD("xvd701: Playback STOP\n");
+
+ m_playback_status = STATUS_STOP;
+ create_packet(STATUS_OK, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x0c && m_command[4] == 0x50 && m_command[5] == 0x20)
+ {
+ // FF FF 21 0C 50 20 00 00 00 00 63 SEEK TO SPECIFIC CHAPTER
+ auto chapter = ((m_command[6] % 10) * 100) + ((m_command[7] % 10) * 10) + (m_command[8] % 10);
+
+ if (m_media_type == JVC_MEDIA_VCD)
+ {
+ // VCD can only go to 99, so it sticks the data in the first two spots
+ chapter /= 10;
+ }
+
+ auto status = seek_chapter(chapter);
+ LOGCMD("xvd701: Seek chapter %d -> %d\n", chapter, status);
+ create_packet(status ? STATUS_OK : STATUS_ERROR, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x0c && m_command[4] == 0x50 && m_command[5] == 0x61)
+ {
+ // FF FF 21 0C 50 61 00 00 00 00 24 PREV (SEEK TO PREVIOUS CHAPTER)
+ auto chapter = m_chapter - 1;
+ if (m_playback_status != STATUS_PLAYING && chapter == 0)
+ chapter = 1;
+
+ auto status = seek_chapter(chapter);
+ LOGCMD("xvd701: Seek prev -> %d\n", status);
+ create_packet(status ? STATUS_OK : STATUS_ERROR, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x0c && m_command[4] == 0x50 && m_command[5] == 0x73)
+ {
+ // FF FF 21 0C 50 73 00 00 00 00 12 FF (SEEK TO NEXT CHAPTER)
+ auto status = seek_chapter(m_chapter + 1);
+ LOGCMD("xvd701: Seek FF -> %d\n", status);
+ create_packet(status ? STATUS_OK : STATUS_ERROR, NO_RESPONSE);
+ }
+
+ else if (m_command[3] == 0x3e && m_command[4] == 0x40 && m_command[5] == 0x60)
+ {
+ // FF FF 21 3E 40 60 00 00 00 00 03 DEVICE OFF
+ LOGCMD("xvd701: Device OFF\n");
+
+ auto status = m_is_powered ? STATUS_OK : STATUS_ERROR;
+ if (m_is_powered)
+ m_is_powered = false;
+
+ create_packet(status, NO_RESPONSE);
+
+ }
+ else if (m_command[3] == 0x3e && m_command[4] == 0x40 && m_command[5] == 0x70)
+ {
+ // FF FF 21 3E 40 70 00 00 00 00 73 DEVICE ON
+ LOGCMD("xvd701: Device ON\n");
+
+ auto status = !m_is_powered ? STATUS_OK : STATUS_ERROR;
+ if (!m_is_powered)
+ m_is_powered = true;
+
+ create_packet(status, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x3e && m_command[4] == 0x4e && m_command[5] == 0x20)
+ {
+ LOGCMD("xvd701: Device power status request\n");
+ const unsigned char response[6] = { m_is_powered, 0x20, 0, 0, 0, 0 };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x41)
+ {
+ auto new_id = m_command[5];
+ LOGCMD("xvd701: Change JLIP ID to %02x\n", new_id);
+
+ if (new_id > 0 && new_id < 64)
+ {
+ m_jlip_id = new_id;
+ create_packet(STATUS_OK, NO_RESPONSE);
+ }
+ else
+ {
+ create_packet(STATUS_ERROR, NO_RESPONSE);
+ }
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x45 && m_command[5] == 0x00)
+ {
+ LOGCMD("xvd701: Machine code request\n");
+
+ const unsigned char response[6] = { 0x00, 0x01, 0x03, 0x00, 0x03, 0x01 };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x48 && m_command[5] == 0x20)
+ {
+ LOGCMD("xvd701: Baud rate request\n");
+
+ // Hardcoded to 9600 baud
+ const unsigned char response[6] = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x49 && m_command[5] == 0x00)
+ {
+ LOGCMD("xvd701: Device code request\n");
+
+ const unsigned char response[6] = { 0x03, 0x0C, 0x7F, 0x7F, 0x7F, 0x7F };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x4c && m_command[5] == 0x00)
+ {
+ LOGCMD("xvd701: Device name first half request\n");
+
+ const unsigned char response[6] = { 'D', 'V', 'D', ' ', 'P', 'L' };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x4d && m_command[5] == 0x00)
+ {
+ LOGCMD("xvd701: Device name last half request\n");
+
+ const unsigned char response[6] = { 'A', 'Y', 'E', 'R', 0x7F, 0x7F };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x4e && m_command[5] == 0x20)
+ {
+ LOGCMD("xvd701: NOP request\n");
+
+ const unsigned char response[6] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ create_packet(STATUS_OK, response);
+ }
}
}