pcecd: some additions
This commit is contained in:
9
menu.cpp
9
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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user