diff options
Diffstat (limited to 'src/devices/bus/rs232/xvd701.cpp')
-rw-r--r-- | src/devices/bus/rs232/xvd701.cpp | 253 |
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); + } } } |