diff --git a/menu.cpp b/menu.cpp index b430edc..aea6de8 100644 --- a/menu.cpp +++ b/menu.cpp @@ -1697,6 +1697,15 @@ void HandleUI(void) mask = 1; } } + if (is_pce()) + { + /*if (mask == 1) pcecd_set_image(0, ""); + if (mask == 2) + {*/ + pcecd_reset(); + /*mask = 1; + }*/ + } uint32_t status = user_io_8bit_set_status(0, 0, ex); diff --git a/support/pcecd/pcecd.cpp b/support/pcecd/pcecd.cpp index 0df4987..c0a68a8 100644 --- a/support/pcecd/pcecd.cpp +++ b/support/pcecd/pcecd.cpp @@ -17,7 +17,7 @@ static uint8_t has_command = 0; void pcecd_poll() { static uint32_t poll_timer = 0; - static uint8_t last_req = 255; + static uint8_t last_req = 0; static uint8_t adj = 0; if (!poll_timer || CheckTimer(poll_timer)) @@ -31,12 +31,23 @@ void pcecd_poll() spi_uio_cmd_cont(UIO_CD_SET); spi_w(s); + spi_w(0); DisableIO(); pcecdd.has_status = 0; printf("\x1b[32mPCECD: Send status = %02X, message = %02X\n\x1b[0m", s&0xFF, s >> 8); } + else if (pcecdd.data_req) { + spi_uio_cmd_cont(UIO_CD_SET); + spi_w(0); + spi_w(1); + DisableIO(); + + pcecdd.data_req = false; + + printf("\x1b[32mPCECD: Data request for MODESELECT6\n\x1b[0m"); + } pcecdd.Update(); } @@ -48,26 +59,34 @@ void pcecd_poll() last_req = req; uint16_t data_in[6]; + uint16_t data_mode; data_in[0] = spi_w(0); data_in[1] = spi_w(0); data_in[2] = spi_w(0); data_in[3] = spi_w(0); data_in[4] = spi_w(0); data_in[5] = spi_w(0); + data_mode = spi_w(0); DisableIO(); - if (need_reset) { - need_reset = 0; - pcecdd.Reset(); - } - - if (!((uint8_t*)data_in)[11]) { + + switch (data_mode & 0xFF) + { + case 0: pcecdd.SetCommand((uint8_t*)data_in); pcecdd.CommandExec(); has_command = 1; - } - else { + break; + + case 1: + //TODO: process data + pcecdd.SendStatus(0, 0); + printf("\x1b[32mPCECD: Command MODESELECT6, received data\n\x1b[0m"); + break; + + default: pcecdd.can_read_next = true; + break; } @@ -75,6 +94,13 @@ void pcecd_poll() } else DisableIO(); + + if (need_reset) { + need_reset = 0; + pcecdd.Reset(); + printf("\x1b[32mPCECD: Reset\n\x1b[0m"); + } + } void pcecd_reset() { @@ -99,13 +125,13 @@ void pcecd_set_image(int num, const char *filename) (void)num; pcecdd.Unload(); - pcecdd.status = CD_STAT_OPEN; + pcecdd.state = PCECD_STATE_NODISC; if (strlen(filename)) { static char path[1024]; if (pcecdd.Load(filename) > 0) { - pcecdd.status = pcecdd.loaded ? CD_STAT_STOP : CD_STAT_NO_DISC; + pcecdd.state = pcecdd.loaded ? PCECD_STATE_IDLE : PCECD_STATE_NODISC; pcecdd.latency = 10; pcecdd.SendData = pcecd_send_data; @@ -116,14 +142,14 @@ void pcecd_set_image(int num, const char *filename) } else { notify_mount(0); - pcecdd.status = CD_STAT_NO_DISC; + pcecdd.state = PCECD_STATE_NODISC; } } else { pcecdd.Unload(); notify_mount(0); - pcecdd.status = CD_STAT_NO_DISC; + pcecdd.state = PCECD_STATE_NODISC; } } diff --git a/support/pcecd/pcecd.h b/support/pcecd/pcecd.h index 08326af..2d34d81 100644 --- a/support/pcecd/pcecd.h +++ b/support/pcecd/pcecd.h @@ -1,28 +1,11 @@ #ifndef PCECD_H #define PCECD_H - -// CDD status -#define CD_STAT_STOP 0x00 -#define CD_STAT_PLAY 0x01 -#define CD_STAT_SEEK 0x02 -#define CD_STAT_SCAN 0x03 -#define CD_STAT_PAUSE 0x04 -#define CD_STAT_OPEN 0x05 -#define CD_STAT_NO_VALID_CHK 0x06 -#define CD_STAT_NO_VALID_CMD 0x07 -#define CD_STAT_ERROR 0x08 -#define CD_STAT_TOC 0x09 -#define CD_STAT_TRACK_MOVE 0x0A -#define CD_STAT_NO_DISC 0x0B -#define CD_STAT_END 0x0C -#define CD_STAT_TRAY 0x0E -#define CD_STAT_TEST 0x0F - // CDD command #define PCECD_COMM_TESTUNIT 0x00 #define PCECD_COMM_REQUESTSENSE 0x03 #define PCECD_COMM_READ6 0x08 +#define PCECD_COMM_MODESELECT6 0x15 #define PCECD_COMM_SAPSP 0xD8 #define PCECD_COMM_SAPEP 0xD9 #define PCECD_COMM_PAUSE 0xDA @@ -30,23 +13,60 @@ #define PCECD_COMM_GETDIRINFO 0xDE #define PCECD_STATE_IDLE 0 -#define PCECD_STATE_READ 1 -#define PCECD_STATE_PLAY 2 -#define PCECD_STATE_PAUSE 3 +#define PCECD_STATE_NODISC 1 +#define PCECD_STATE_READ 2 +#define PCECD_STATE_PLAY 3 +#define PCECD_STATE_PAUSE 4 + +#define PCECD_STATUS_GOOD 0 +#define PCECD_STATUS_CHECK_COND 1 +#define PCECD_STATUS_CONDITION_MET 2 +#define PCECD_STATUS_BUSY 4 +#define PCECD_STATUS_INTERMEDIATE 8 + +#define SENSEKEY_NO_SENSE 0x0 +#define SENSEKEY_NOT_READY 0x2 +#define SENSEKEY_MEDIUM_ERROR 0x3 +#define SENSEKEY_HARDWARE_ERROR 0x4 +#define SENSEKEY_ILLEGAL_REQUEST 0x5 +#define SENSEKEY_UNIT_ATTENTION 0x6 +#define SENSEKEY_ABORTED_COMMAND 0xB + +#define NSE_NO_DISC 0x0B +#define NSE_TRAY_OPEN 0x0D +#define NSE_SEEK_ERROR 0x15 +#define NSE_HEADER_READ_ERROR 0x16 +#define NSE_NOT_AUDIO_TRACK 0x1C +#define NSE_NOT_DATA_TRACK 0x1D +#define NSE_INVALID_COMMAND 0x20 +#define NSE_INVALID_ADDRESS 0x21 +#define NSE_INVALID_PARAMETER 0x22 +#define NSE_END_OF_VOLUME 0x25 +#define NSE_INVALID_REQUEST_IN_CDB 0x27 +#define NSE_DISC_CHANGED 0x28 +#define NSE_AUDIO_NOT_PLAYING 0x2C #include "../../cd.h" +typedef struct +{ + uint8_t key; + uint8_t asc; + uint8_t ascq; + uint8_t fru; +} sense_t; class pcecdd_t { public: uint32_t latency; - uint8_t status; + uint8_t state; uint8_t isData; int loaded; SendDataFunc SendData; int has_status; + bool data_req; bool can_read_next; pcecdd_t(); @@ -57,6 +77,7 @@ public: void CommandExec(); int GetStatus(uint8_t* buf); int SetCommand(uint8_t* buf); + void SendStatus(uint8_t status, uint8_t message); private: toc_t toc; @@ -67,9 +88,10 @@ private: int scanOffset; int audioLength; int audioOffset; - uint8_t state; + //uint8_t state; int CDDAStart; int CDDAEnd; + sense_t sense; uint8_t stat[2]; uint8_t comm[12]; @@ -85,6 +107,7 @@ private: void MSFToLBA(int* lba, msf_t* msf); void MSFToLBA(int* lba, uint8_t m, uint8_t s, uint8_t f); int GetTrackByLBA(int lba, toc_t* toc); + void CommandError(uint8_t key, uint8_t asc, uint8_t ascq, uint8_t fru); }; #define BCD(v) ((uint8_t)((((v)/10) << 4) | ((v)%10))) diff --git a/support/pcecd/pcecdd.cpp b/support/pcecd/pcecdd.cpp index a564b4a..fa9c341 100644 --- a/support/pcecd/pcecdd.cpp +++ b/support/pcecd/pcecdd.cpp @@ -19,16 +19,17 @@ pcecdd_t::pcecdd_t() { lba = 0; scanOffset = 0; isData = 1; - status = CD_STAT_NO_DISC; + state = PCECD_STATE_NODISC; audioLength = 0; audioOffset = 0; SendData = NULL; has_status = 0; + data_req = false; + can_read_next = false; CDDAStart = 0; CDDAEnd = 0; - state = PCECD_STATE_IDLE; - stat[0] = 0xB; + stat[0] = 0x0; stat[1] = 0x0; } @@ -323,38 +324,21 @@ void pcecdd_t::Reset() { lba = 0; scanOffset = 0; isData = 1; - status = loaded ? CD_STAT_STOP : CD_STAT_NO_DISC; + state = loaded ? PCECD_STATE_IDLE : PCECD_STATE_NODISC; audioLength = 0; audioOffset = 0; has_status = 0; + data_req = false; + can_read_next = false; CDDAStart = 0; CDDAEnd = 0; - state = PCECD_STATE_IDLE; - stat[0] = 0xB; + stat[0] = 0x0; stat[1] = 0x0; } void pcecdd_t::Update() { - /*if (this->status == CD_STAT_STOP || this->status == CD_STAT_TRAY || this->status == CD_STAT_OPEN) - { - if (this->latency > 0) - { - this->latency--; - return; - } - this->status = this->loaded ? CD_STAT_TOC : CD_STAT_NO_DISC; - } - else if (this->status == CD_STAT_SEEK) - { - if (this->latency > 0) - { - this->latency--; - return; - } - this->status = CD_STAT_PAUSE; - } - else*/ if (this->state == PCECD_STATE_READ) + if (this->state == PCECD_STATE_READ) { if (this->latency > 0) { @@ -457,68 +441,48 @@ void pcecdd_t::Update() { } } - //else if (this->status == CD_STAT_SCAN) - //{ - // this->lba += this->scanOffset; - - // if (this->lba >= this->toc.tracks[this->index].end) - // { - // this->index++; - // if (this->index < this->toc.last) - // { - // this->lba = this->toc.tracks[this->index].start; - // } - // else - // { - // this->lba = this->toc.end; - // this->status = CD_STAT_END; - // this->isData = 0x01; - // return; - // } - // } - // else if (this->lba < this->toc.tracks[this->index].start) - // { - // if (this->index > 0) - // { - // this->index--; - // this->lba = this->toc.tracks[this->index].end; - // } - // else - // { - // this->lba = 0; - // } - // } - - // this->isData = this->toc.tracks[this->index].type; - - // //if (this->toc.sub) fseek(this->toc.sub, this->lba * 96, SEEK_SET); - - // if (this->toc.tracks[this->index].type) - // { - // // DATA track - // FileSeek(&this->toc.tracks[0].f, this->lba * this->sectorSize, SEEK_SET); - // } - // else if (this->toc.tracks[this->index].f.opened()) - // { - // // AUDIO track - // FileSeek(&this->toc.tracks[this->index].f, (this->lba * 2352) - this->toc.tracks[this->index].offset, SEEK_SET); - // } - //} } void pcecdd_t::CommandExec() { msf_t msf; int lba_ = 0; - uint8_t buf[16]; + static uint8_t buf[32]; - memset(buf, 0, 16); + memset(buf, 0, 32); switch (comm[0]) { case PCECD_COMM_TESTUNIT: - stat[0] = 0; - stat[1] = 0; - has_status = 1; - printf("\x1b[32mPCECD: Command TESTUNIT\n\x1b[0m"); + if (state == PCECD_STATE_NODISC) { + CommandError(SENSEKEY_NOT_READY, NSE_NO_DISC, 0, 0); + SendStatus(PCECD_STATUS_CHECK_COND, 0); + } + else { + SendStatus(PCECD_STATUS_GOOD, 0); + } + + printf("\x1b[32mPCECD: Command TESTUNIT, state = %u\n\x1b[0m", state); + break; + + case PCECD_COMM_REQUESTSENSE: + buf[0] = 18; + buf[1] = 0 | 0x80; + + buf[2] = 0x70; + buf[4] = sense.key; + buf[9] = 0x0A; + buf[14] = sense.asc; + buf[15] = sense.ascq; + buf[16] = sense.fru; + + sense.key = sense.asc = sense.ascq = sense.fru = 0; + + SendStatus(PCECD_STATUS_GOOD, 0); + + printf("\x1b[32mPCECD: Command REQUESTSENSE, key = %02X, asc = %02X, ascq = %02X, fru = %02X\n\x1b[0m", sense.key, sense.asc, sense.ascq, sense.fru); + + if (SendData) + SendData(buf, 18+2, PCECD_DATA_IO_INDEX); + break; case PCECD_COMM_GETDIRINFO: { @@ -561,9 +525,7 @@ void pcecdd_t::CommandExec() { break; } - stat[0] = 0; - stat[1] = 0; - has_status = 1; + SendStatus(PCECD_STATUS_GOOD, 0); printf("\x1b[32mPCECD: Command GETDIRINFO, [1] = %02X, [2] = %02X\n\x1b[0m", comm[1], comm[2]); @@ -610,6 +572,18 @@ void pcecdd_t::CommandExec() { } break; + case PCECD_COMM_MODESELECT6: + if (comm[4]) { + data_req = true; + } + else { + SendStatus(PCECD_STATUS_GOOD, 0); + } + + printf("\x1b[32mPCECD: Command MODESELECT6, cnt = %u\n\x1b[0m", comm[4]); + + break; + case PCECD_COMM_SAPSP: { int lba_ = 0; switch (comm[9] & 0xc0) @@ -662,9 +636,7 @@ void pcecdd_t::CommandExec() { this->lba++; - stat[0] = 0; - stat[1] = 0; - has_status = 1; + SendStatus(PCECD_STATUS_GOOD, 0); } printf("\x1b[32mPCECD: Command SAPSP, start = %i, [9] = %02X\n\x1b[0m", this->CDDAStart, comm[9]); break; @@ -697,9 +669,7 @@ void pcecdd_t::CommandExec() { this->CDDAEnd = lba_; - stat[0] = 0; - stat[1] = 0; - has_status = 1; + SendStatus(PCECD_STATUS_GOOD, 0); } printf("\x1b[32mPCECD: Command SAPEP, end = %i, [9] = %02X\n\x1b[0m", this->CDDAEnd, comm[9]); break; @@ -707,9 +677,7 @@ void pcecdd_t::CommandExec() { case PCECD_COMM_PAUSE: { this->state = PCECD_STATE_PAUSE; - stat[0] = 0; - stat[1] = 0; - has_status = 1; + SendStatus(PCECD_STATUS_GOOD, 0); } printf("\x1b[32mPCECD: Command PAUSE, current lba = %i\n\x1b[0m", this->lba); break; @@ -735,9 +703,7 @@ void pcecdd_t::CommandExec() { buf[10] = BCD(msf.s); buf[11] = BCD(msf.f); - stat[0] = 0; - stat[1] = 0; - has_status = 1; + SendStatus(PCECD_STATUS_GOOD, 0); printf("\x1b[32mPCECD: Command READSUBQ, [1] = %02X, track = %i, index = %i, lba_rel = %i, lba_abs = %i\n\x1b[0m", comm[1], this->index + 1, this->index, lba_rel, lba_); @@ -752,14 +718,6 @@ void pcecdd_t::CommandExec() { printf("\x1b[32mPCECD: Command undefined, [0] = %02X, [1] = %02X, [2] = %02X, [3] = %02X, [4] = %02X, [5] = %02X\n\x1b[0m", comm[0], comm[1], comm[2], comm[3], comm[4], comm[5]); break; } - - /*if (buf[0] || buf[1]) { - int len = ((int)buf[1] * 256) + buf[0] + 2; - if (SendData) - SendData(buf, len, PCECD_DATA_IO_INDEX); - - printf("\x1b[32mPCECD: Send data, len = %u, [2] = %02X, [3] = %02X, [4] = %02X, [5] = %02X\n\x1b[0m", len, buf[2], buf[3], buf[4], buf[5]); - }*/ } int pcecdd_t::GetStatus(uint8_t* buf) { @@ -772,6 +730,12 @@ int pcecdd_t::SetCommand(uint8_t* buf) { return 0; } +void pcecdd_t::SendStatus(uint8_t status, uint8_t message) { + stat[0] = status; + stat[1] = message; + has_status = 1; +} + void pcecdd_t::LBAToMSF(int lba, msf_t* msf) { msf->m = (lba / 75) / 60; msf->s = (lba / 75) % 60; @@ -865,7 +829,12 @@ int pcecdd_t::SectorSend(uint8_t* header) return 0; } - +void pcecdd_t::CommandError(uint8_t key, uint8_t asc, uint8_t ascq, uint8_t fru) { + sense.key = key; + sense.asc = asc; + sense.ascq = ascq; + sense.fru = fru; +}