ao486: support CUE CD format.

This commit is contained in:
sorgelig
2020-09-21 14:02:36 +08:00
parent 2784264e8f
commit 715a313764
3 changed files with 472 additions and 100 deletions

View File

@@ -239,7 +239,7 @@ static fileTYPE fdd1_image = {};
static fileTYPE ide_image[4] = {};
static bool boot_from_floppy = 1;
static int img_mount(fileTYPE *f, char *name)
static int img_mount(fileTYPE *f, const char *name)
{
FileClose(f);
int writable = 0, ret = 0;
@@ -417,8 +417,22 @@ static void hdd_set(int num, char* filename)
{
if (!v3 && num > 1) return;
uint32_t base = newcore ? ((num & (v3 ? 2 : 1)) ? HDD1_BASE_NEW : HDD0_BASE_NEW) : (num ? HDD1_BASE_OLD : HDD0_BASE_OLD);
int present = img_mount(&ide_image[num], filename);
x86_ide_set(num, base, present ? &ide_image[num] : 0, v3 ? 3 : newcore ? 2 : 0);
int present = 0;
int cd = 0;
int len = strlen(filename);
int vhd = (len > 4 && !strcasecmp(filename + len - 4, ".vhd"));
if (num > 1 && !vhd)
{
const char *img_name = x86_ide_parse_cd(num, filename);
if (img_name) present = img_mount(&ide_image[num], img_name);
if (present) cd = 1;
}
if(!present && vhd) present = img_mount(&ide_image[num], filename);
x86_ide_set(num, base, present ? &ide_image[num] : 0, v3 ? 3 : newcore ? 2 : 0, cd);
}
static uint8_t bin2bcd(unsigned val)

View File

@@ -6,6 +6,12 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <ios>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <sys/stat.h>
#include "../../spi.h"
#include "../../user_io.h"
@@ -97,42 +103,49 @@ typedef struct
uint8_t status;
} regs_t;
typedef struct
{
char filename[1024];
uint32_t start;
uint32_t length;
uint32_t skip;
uint16_t sectorSize;
uint8_t attr;
uint8_t mode2;
uint8_t number;
} track_t;
typedef struct
{
fileTYPE *f;
uint32_t hd_cylinders;
uint32_t hd_heads;
uint32_t hd_spt;
uint32_t hd_total_sectors;
uint8_t present;
uint8_t placeholder;
uint8_t allow_placeholder;
uint8_t cd;
uint8_t load_state;
uint8_t playing;
uint8_t paused;
uint8_t track_cnt;
uint8_t data_num;
track_t track[50];
uint16_t id[256];
} drive_t;
typedef struct
{
uint32_t base;
struct
{
fileTYPE *f;
uint32_t hd_cylinders;
uint32_t hd_heads;
uint32_t hd_spt;
uint32_t hd_total_sectors;
uint8_t present;
uint8_t placeholder;
uint8_t allow_placeholder;
uint8_t cd;
uint8_t playing;
uint8_t paused;
struct
{
uint32_t start;
uint32_t length;
uint32_t skip;
uint16_t sectorSize;
uint8_t attr;
uint8_t mode2;
}
tracks[2];
uint8_t load_state;
uint16_t id[256];
} drive[2];
uint32_t state;
uint32_t null;
uint32_t prepcnt;
regs_t regs;
drive_t drive[2];
} ide_config;
static ide_config ide_inst[2] = {};
@@ -262,40 +275,375 @@ static int x86_check_iso_file(fileTYPE *f, uint8_t *mode2, uint16_t *sectorSize)
return 0;
}
static void ParseIsoFile(ide_config *ide, int drv)
static const char * LoadIsoFile(drive_t *drv, const char* filename)
{
memset(ide->drive[drv].tracks, 0, sizeof(ide->drive[drv].tracks));
ide->drive[drv].tracks[0].attr = 0x40; //data track
if (!ide->drive[drv].f)
fileTYPE f;
memset(drv->track, 0, sizeof(drv->track));
drv->track_cnt = 0;
strcpy(drv->track[0].filename, filename);
if (!FileOpen(&f, filename))
{
printf("No CD!\n");
return;
return 0;
}
if(!x86_check_iso_file(ide->drive[drv].f, &ide->drive[drv].tracks[0].mode2, &ide->drive[drv].tracks[0].sectorSize))
if(!x86_check_iso_file(&f, &drv->track[0].mode2, &drv->track[0].sectorSize))
{
printf("Fail to parse ISO!\n");
return;
FileClose(&f);
return 0;
}
ide->drive[drv].tracks[0].length = ide->drive[drv].f->size / ide->drive[drv].tracks[0].sectorSize;
drv->track[0].attr = 0x40; //data track
drv->track[0].length = f.size / drv->track[0].sectorSize;
drv->track[0].number = 1;
FileClose(&f);
// lead-out track (track 2)
ide->drive[drv].tracks[1].start = ide->drive[drv].tracks[0].length;
drv->track[1].start = drv->track[0].length;
drv->track[2].number = 2;
printf("ISO: mode2 = %d, sectorSize = %d, sectors = %d\n", ide->drive[drv].tracks[0].mode2, ide->drive[drv].tracks[0].sectorSize, ide->drive[drv].tracks[0].length);
printf("ISO: mode2 = %d, sectorSize = %d, sectors = %d\n", drv->track[0].mode2, drv->track[0].sectorSize, drv->track[0].length);
drv->track_cnt = 2;
drv->data_num = 0;
return drv->track[0].filename;
}
typedef struct SMSF
#define CD_FPS 75
#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F))
typedef struct
{
//! \brief Time, minutes field
unsigned char min;
//! \brief Time, seconds field
unsigned char sec;
//! \brief Time, frame field
unsigned char fr;
} TMSF;
static int GetCueKeyword(std::string &keyword, std::istream &in)
{
in >> keyword;
for (uint32_t i = 0; i < keyword.size(); i++)
{
keyword[i] = static_cast<char>(toupper(keyword[i]));
}
return 1;
}
static int GetCueFrame(uint32_t &frames, std::istream &in)
{
std::string msf;
in >> msf;
TMSF tmp = { 0, 0, 0 };
int success = sscanf(msf.c_str(), "%hhu:%hhu:%hhu", &tmp.min, &tmp.sec, &tmp.fr) == 3;
frames = (int)MSF_TO_FRAMES(tmp.min, tmp.sec, tmp.fr);
return success;
}
static int GetCueString(std::string &str, std::istream &in)
{
int pos = (int)in.tellg();
in >> str;
if (str[0] == '\"') {
if (str[str.size() - 1] == '\"')
{
str.assign(str, 1, str.size() - 2);
}
else
{
in.seekg(pos, std::ios::beg);
static char buffer[1024];
in.getline(buffer, 1024, '\"'); // skip
in.getline(buffer, 1024, '\"');
str = buffer;
}
}
return 1;
}
static int AddTrack(drive_t *drv, track_t *curr, uint32_t &shift, const int32_t prestart, uint32_t &totalPregap, uint32_t currPregap)
{
uint32_t skip = 0;
if (drv->track_cnt >= sizeof(drv->track) / sizeof(drv->track[0]))
{
printf("CDROM: too many tracks(%d)\n", drv->track_cnt);
return 0;
}
// frames between index 0(prestart) and 1(curr.start) must be skipped
if (prestart >= 0)
{
if (prestart > static_cast<int>(curr->start))
{
printf("CDROM: AddTrack => prestart %d cannot be > curr.start %u\n", prestart, curr->start);
return 0;
}
skip = static_cast<uint32_t>(static_cast<int>(curr->start) - prestart);
}
// Add the first track, if our vector is empty
if (!drv->track_cnt)
{
//assertm(curr.number == 1, "The first track must be labelled number 1 [BUG!]");
curr->skip = skip * curr->sectorSize;
curr->start += currPregap;
totalPregap = currPregap;
memcpy(&drv->track[drv->track_cnt], curr, sizeof(track_t));
drv->track_cnt++;
return 1;
}
// Guard against undefined behavior in subsequent tracks.back() call
//assert(!tracks.empty());
track_t *prev = &drv->track[drv->track_cnt - 1];
// current track consumes data from the same file as the previous
if (!strcmp(prev->filename, curr->filename))
{
curr->start += shift;
if (!prev->length)
{
prev->length = curr->start + totalPregap - prev->start - skip;
}
curr->skip += prev->skip + prev->length * prev->sectorSize + skip * curr->sectorSize;
totalPregap += currPregap;
curr->start += totalPregap;
// current track uses a different file as the previous track
}
else
{
uint32_t size = FileLoad(prev->filename, 0, 0);
const uint32_t tmp = size - prev->skip;
prev->length = tmp / prev->sectorSize;
if (tmp % prev->sectorSize != 0) prev->length++; // padding
curr->start += prev->start + prev->length + currPregap;
curr->skip = skip * curr->sectorSize;
shift += prev->start + prev->length;
totalPregap = currPregap;
}
// error checks
if (curr->number <= 1
|| prev->number + 1 != curr->number
|| curr->start < prev->start + prev->length) {
printf("AddTrack: failed consistency checks\n"
"\tcurr.number (%d) <= 1\n"
"\tprev.number (%d) + 1 != curr.number (%d)\n"
"\tcurr.start (%d) < prev.start (%d) + prev.length (%d)\n",
curr->number, prev->number, curr->number,
curr->start, prev->start, prev->length);
return 0;
}
memcpy(&drv->track[drv->track_cnt], curr, sizeof(track_t));
drv->track_cnt++;
return 1;
}
static std::string dirname(char * file)
{
char * sep = strrchr(file, '/');
if (!sep) return "";
int len = (int)(sep - file);
static char tmp[1024];
strncpy(tmp, file, len + 1);
tmp[len + 1] = 0;
return tmp;
}
static int GetRealFileName(std::string &filename, std::string &pathname)
{
// check if file exists
struct stat test;
if (stat(filename.c_str(), &test) == 0)
{
return 1;
}
// check if file with path relative to cue file exists
std::string tmpstr(pathname + "/" + filename);
if (stat(tmpstr.c_str(), &test) == 0)
{
filename = tmpstr;
return 1;
}
return 0;
}
static const char * LoadCueSheet(drive_t *drv, const char *cuefile)
{
printf("LoadCueSheet(%s)\n", cuefile);
memset(drv->track, 0, sizeof(drv->track));
drv->track_cnt = 0;
track_t track = {};
uint32_t shift = 0;
uint32_t currPregap = 0;
uint32_t totalPregap = 0;
int32_t prestart = -1;
int track_number;
int success;
int canAddTrack = 0;
static char tmp[1024];
strcpy(tmp, cuefile);
std::string pathname(dirname(tmp));
std::ifstream in;
in.open(cuefile, std::ios::in);
if (in.fail()) return 0;
while (!in.eof())
{
// get next line
char buf[256];
in.getline(buf, sizeof(buf));
if (in.fail() && !in.eof())
{
return 0; // probably a binary file
}
std::istringstream line(buf);
std::string command;
GetCueKeyword(command, line);
//printf("command: %s\n", command.c_str());
if (command == "TRACK")
{
if (canAddTrack) success = AddTrack(drv, &track, shift, prestart, totalPregap, currPregap);
else success = 1;
track.start = 0;
track.skip = 0;
currPregap = 0;
prestart = -1;
line >> track_number; // (cin) read into a true int first
track.number = static_cast<uint8_t>(track_number);
std::string type;
GetCueKeyword(type, line);
//printf(" type: %s\n", type.c_str());
if (type == "AUDIO")
{
track.sectorSize = BYTES_PER_RAW_REDBOOK_FRAME;
track.attr = 0;
track.mode2 = false;
}
else if (type == "MODE1/2048")
{
track.sectorSize = BYTES_PER_COOKED_REDBOOK_FRAME;
track.attr = 0x40;
track.mode2 = false;
}
else if (type == "MODE1/2352")
{
track.sectorSize = BYTES_PER_RAW_REDBOOK_FRAME;
track.attr = 0x40;
track.mode2 = false;
}
else if (type == "MODE2/2336")
{
track.sectorSize = 2336;
track.attr = 0x40;
track.mode2 = true;
}
else if (type == "MODE2/2352")
{
track.sectorSize = BYTES_PER_RAW_REDBOOK_FRAME;
track.attr = 0x40;
track.mode2 = true;
}
else success = 0;
canAddTrack = true;
}
else if (command == "INDEX")
{
int index;
line >> index;
uint32_t frame;
success = GetCueFrame(frame, line);
if (index == 1) track.start = frame;
else if (index == 0) prestart = static_cast<int32_t>(frame);
// ignore other indices
}
else if (command == "FILE")
{
if (canAddTrack) success = AddTrack(drv, &track, shift, prestart, totalPregap, currPregap);
else success = 1;
canAddTrack = 0;
std::string filename;
GetCueString(filename, line);
GetRealFileName(filename, pathname);
std::string type;
GetCueKeyword(type, line);
strcpy(track.filename, filename.c_str());
}
else if (command == "PREGAP") success = GetCueFrame(currPregap, line);
// ignored commands
else if (command == "CATALOG" || command == "CDTEXTFILE" || command == "FLAGS" || command == "ISRC" ||
command == "PERFORMER" || command == "POSTGAP" || command == "REM" ||
command == "SONGWRITER" || command == "TITLE" || command.empty())
{
success = 1;
}
// failure
else
{
success = 0;
}
if (!success)
{
return 0;
}
}
// add last track
if (!AddTrack(drv, &track, shift, prestart, totalPregap, currPregap))
{
return 0;
}
// add lead-out track
track.number++;
track.attr = 0;//sync with load iso
track.start = 0;
track.length = 0;
if (!AddTrack(drv, &track, shift, -1, totalPregap, 0))
{
return 0;
}
for (uint8_t i = 0; i < drv->track_cnt; i++)
{
if (drv->track[i].attr == 0x40)
{
drv->data_num = i;
return drv->track[i].filename;
}
}
return 0;
}
inline TMSF frames_to_msf(uint32_t frames)
{
TMSF msf = { 0, 0, 0 };
@@ -307,31 +655,29 @@ inline TMSF frames_to_msf(uint32_t frames)
return msf;
}
static int GetCDTracks(ide_config *ide, int& start_track_num, int& end_track_num, TMSF& lead_out_msf)
static int GetCDTracks(drive_t *drv, int& start_track_num, int& end_track_num, TMSF& lead_out_msf)
{
if (!ide->drive[ide->regs.drv].tracks[0].length) return 0;
if (drv->track_cnt < 2 || !drv->track[0].length) return 0;
start_track_num = 1;
end_track_num = 1;
lead_out_msf = frames_to_msf(ide->drive[ide->regs.drv].tracks[1].start + REDBOOK_FRAME_PADDING);
start_track_num = drv->track[0].number;
end_track_num = drv->track[drv->track_cnt - 2].number;
lead_out_msf = frames_to_msf(drv->track[drv->track_cnt - 1].start + REDBOOK_FRAME_PADDING);
return 1;
}
static int GetCDTrackInfo(ide_config *ide, int requested_track_num, TMSF& start_msf, unsigned char& attr)
static int GetCDTrackInfo(drive_t *drv, int requested_track_num, TMSF& start_msf, unsigned char& attr)
{
if (!ide->drive[ide->regs.drv].tracks[0].length
|| requested_track_num < 1
|| (unsigned int)requested_track_num >= (sizeof(ide->drive[ide->regs.drv].tracks)/sizeof(ide->drive[ide->regs.drv].tracks[0])))
if (drv->track_cnt < 2 || requested_track_num < 1 || requested_track_num >= drv->track_cnt)
{
return 0;
}
start_msf = frames_to_msf(ide->drive[ide->regs.drv].tracks[requested_track_num - 1].start + REDBOOK_FRAME_PADDING);
attr = ide->drive[ide->regs.drv].tracks[requested_track_num - 1].attr;
start_msf = frames_to_msf(drv->track[requested_track_num - 1].start + REDBOOK_FRAME_PADDING);
attr = drv->track[requested_track_num - 1].attr;
return 1;
}
static int read_toc(ide_config *ide, uint8_t *cmdbuf)
static int read_toc(drive_t *drv, uint8_t *cmdbuf)
{
/* NTS: The SCSI MMC standards say we're allowed to indicate the return data
* is longer than it's allocation length. But here's the thing: some MS-DOS
@@ -353,7 +699,7 @@ static int read_toc(ide_config *ide, uint8_t *cmdbuf)
memset(buf, 0, 8);
if (!GetCDTracks(ide, first, last, leadOut))
if (!GetCDTracks(drv, first, last, leadOut))
{
printf("WARNING: ATAPI READ TOC failed to get track info\n");
return 8;
@@ -370,7 +716,7 @@ static int read_toc(ide_config *ide, uint8_t *cmdbuf)
*write++ = (unsigned char)1; /* @+2 first complete session */
*write++ = (unsigned char)1; /* @+3 last complete session */
if (!GetCDTrackInfo(ide, first, start, attr))
if (!GetCDTrackInfo(drv, first, start, attr))
{
printf("WARNING: ATAPI READ TOC unable to read track %u information\n", first);
attr = 0x41; /* ADR=1 CONTROL=4 */
@@ -413,7 +759,7 @@ static int read_toc(ide_config *ide, uint8_t *cmdbuf)
unsigned char attr;
TMSF start;
if (!GetCDTrackInfo(ide, track, start, attr))
if (!GetCDTrackInfo(drv, track, start, attr))
{
printf("WARNING: ATAPI READ TOC unable to read track %u information\n", track);
attr = 0x41; /* ADR=1 CONTROL=4 */
@@ -620,9 +966,9 @@ static uint16_t mode_sense(int page)
return x + 2;
}
static int GetCDSub(ide_config *ide, unsigned char& attr, unsigned char& track_num, unsigned char& index, TMSF& relative_msf, TMSF& absolute_msf)
static int GetCDSub(drive_t *drv, unsigned char& attr, unsigned char& track_num, unsigned char& index, TMSF& relative_msf, TMSF& absolute_msf)
{
attr = ide->drive[ide->regs.drv].tracks[0].attr;
attr = drv->track[0].attr;
track_num = 1;
index = 1;
relative_msf.min = relative_msf.fr = 0; relative_msf.sec = 2;
@@ -630,7 +976,7 @@ static int GetCDSub(ide_config *ide, unsigned char& attr, unsigned char& track_n
return 1;
}
static int read_subchannel(ide_config *ide, uint8_t* cmdbuf)
static int read_subchannel(drive_t *drv, uint8_t* cmdbuf)
{
unsigned char paramList = cmdbuf[3];
unsigned char attr, track, index;
@@ -638,7 +984,7 @@ static int read_subchannel(ide_config *ide, uint8_t* cmdbuf)
bool TIME = !!(cmdbuf[1] & 2);
unsigned char *write;
unsigned char astat;
bool playing = ide->drive[ide->regs.drv].playing, pause = ide->drive[ide->regs.drv].paused;
bool playing = drv->playing, pause = drv->paused;
TMSF rel, abs;
if (paramList == 0 || paramList > 3)
@@ -660,7 +1006,7 @@ static int read_subchannel(ide_config *ide, uint8_t* cmdbuf)
}
/* get current subchannel position */
if (!GetCDSub(ide, attr, track, index, rel, abs))
if (!GetCDSub(drv, attr, track, index, rel, abs))
{
printf("ATAPI READ SUBCHANNEL unable to read current pos\n");
memset(buf, 0, 8);
@@ -721,7 +1067,20 @@ static int read_subchannel(ide_config *ide, uint8_t* cmdbuf)
return write - buf;
}
void x86_ide_set(uint32_t num, uint32_t baseaddr, fileTYPE *f, int ver)
const char * x86_ide_parse_cd(uint32_t num, const char *filename)
{
int drv = num & 1;
num >>= 1;
const char *path = getFullPath(filename);
const char *res = LoadCueSheet(&ide_inst[num].drive[drv], path);
if(!res) res = LoadIsoFile(&ide_inst[num].drive[drv], path);
return res;
}
void x86_ide_set(uint32_t num, uint32_t baseaddr, fileTYPE *f, int ver, int cd)
{
int drv = (ver == 3) ? (num & 1) : 0;
if (ver == 3) num >>= 1;
@@ -737,8 +1096,7 @@ void x86_ide_set(uint32_t num, uint32_t baseaddr, fileTYPE *f, int ver)
ide_inst[num].drive[drv].present = f ? 1 : 0;
ide_inst[num].state = IDE_STATE_RESET;
ide_inst[num].drive[drv].cd = ide_inst[num].drive[drv].present && (ver == 3) && num && x86_check_iso_file(f, 0, 0);
if (ide_inst[num].drive[drv].cd) printf("Image recognized as ISO file\n");
ide_inst[num].drive[drv].cd = ide_inst[num].drive[drv].present && (ver == 3) && num && cd;
if (ver == 3)
{
@@ -971,7 +1329,6 @@ void x86_ide_set(uint32_t num, uint32_t baseaddr, fileTYPE *f, int ver)
for (int i = 0; i < 256; i++) ide_inst[num].drive[drv].id[i] = (uint16_t)identify[i];
ParseIsoFile(&ide_inst[num], drv);
ide_inst[num].drive[drv].load_state = ide_inst[num].drive[drv].f ? 1 : 3;
}
@@ -1159,7 +1516,7 @@ static void pkt_send(ide_config *ide, void *data, uint16_t size)
static void read_cd_sectors(ide_config *ide, int cnt)
{
uint32_t sz = ide->drive[ide->regs.drv].tracks[0].sectorSize;
uint32_t sz = ide->drive[ide->regs.drv].track[0].sectorSize;
fileTYPE *f = ide->drive[ide->regs.drv].f;
if (sz == 2048)
@@ -1169,7 +1526,7 @@ static void read_cd_sectors(ide_config *ide, int cnt)
return;
}
uint32_t pre = ide->drive[ide->regs.drv].tracks[0].mode2 ? 24 : 16;
uint32_t pre = ide->drive[ide->regs.drv].track[0].mode2 ? 24 : 16;
uint32_t post = sz - pre - 2048;
uint32_t off = 0;
@@ -1201,7 +1558,7 @@ static void process_cd_read(ide_config *ide)
if (ide->state == IDE_STATE_INIT_RW)
{
uint32_t pos = ide->regs.pkt_lba * ide->drive[ide->regs.drv].tracks[0].sectorSize;
uint32_t pos = ide->regs.pkt_lba * ide->drive[ide->regs.drv].track[0].sectorSize;
//printf("Read from pos: %d\n", pos);
ide->null = (FileSeek(ide->drive[ide->regs.drv].f, pos, SEEK_SET) < 0);
@@ -1260,9 +1617,9 @@ static void set_sense(uint8_t SK, uint8_t ASC = 0, uint8_t ASCQ = 0)
buf[13] = ASCQ;
}
static int get_sense(ide_config *ide)
static int get_sense(drive_t *drv)
{
switch (ide->drive[ide->regs.drv].load_state)
switch (drv->load_state)
{
case 3:
set_sense(2, 0x3A);
@@ -1270,12 +1627,12 @@ static int get_sense(ide_config *ide)
case 2:
set_sense(2, 4, 1);
ide->drive[ide->regs.drv].load_state--;
drv->load_state--;
break;
case 1:
set_sense(2, 28, 0);
ide->drive[ide->regs.drv].load_state--;
drv->load_state--;
break;
default:
@@ -1288,13 +1645,13 @@ static int get_sense(ide_config *ide)
}
void pause_resume(ide_config *ide, uint8_t *cmdbuf)
static void pause_resume(drive_t *drv, uint8_t *cmdbuf)
{
bool resume = !!(cmdbuf[8] & 1);
if(ide->drive[ide->regs.drv].playing) ide->drive[ide->regs.drv].paused = !resume;
if(drv->playing) drv->paused = !resume;
}
void play_audio_msf(ide_config *ide, uint8_t *cmdbuf)
static void play_audio_msf(drive_t *drv, uint8_t *cmdbuf)
{
uint32_t start_lba, end_lba;
@@ -1323,25 +1680,25 @@ void play_audio_msf(ide_config *ide, uint8_t *cmdbuf)
if (start_lba == end_lba)
{
ide->drive[ide->regs.drv].playing = 0;
ide->drive[ide->regs.drv].paused = 0;
drv->playing = 0;
drv->paused = 0;
return;
}
/* LBA 0xFFFFFFFF means start playing wherever the optics of the CD sit */
if (start_lba != 0xFFFFFFFF)
{
ide->drive[ide->regs.drv].playing = 1;
ide->drive[ide->regs.drv].paused = 0;
drv->playing = 1;
drv->paused = 0;
}
else
{
ide->drive[ide->regs.drv].playing = 0;
ide->drive[ide->regs.drv].paused = 1;
drv->playing = 0;
drv->paused = 1;
}
}
void play_audio10(ide_config *ide, uint8_t *cmdbuf)
void play_audio10(drive_t *drv, uint8_t *cmdbuf)
{
uint16_t play_length;
uint32_t start_lba;
@@ -1351,21 +1708,21 @@ void play_audio10(ide_config *ide, uint8_t *cmdbuf)
if (play_length == 0)
{
ide->drive[ide->regs.drv].playing = 0;
ide->drive[ide->regs.drv].paused = 0;
drv->playing = 0;
drv->paused = 0;
return;
}
/* LBA 0xFFFFFFFF means start playing wherever the optics of the CD sit */
if (start_lba != 0xFFFFFFFF)
{
ide->drive[ide->regs.drv].playing = 1;
ide->drive[ide->regs.drv].paused = 0;
drv->playing = 1;
drv->paused = 0;
}
else
{
ide->drive[ide->regs.drv].playing = 0;
ide->drive[ide->regs.drv].paused = 1;
drv->playing = 0;
drv->paused = 1;
}
}
@@ -1436,11 +1793,11 @@ static void process_pkt_cmd(ide_config *ide)
case 0x42: // read sub
cddbg_printf("read sub:\n");
pkt_send(ide, buf, read_subchannel(ide, cmdbuf));
pkt_send(ide, buf, read_subchannel(&ide->drive[ide->regs.drv], cmdbuf));
break;
case 0x43: // read TOC
pkt_send(ide, buf, read_toc(ide, cmdbuf));
pkt_send(ide, buf, read_toc(&ide->drive[ide->regs.drv], cmdbuf));
break;
case 0x12: // inquiry
@@ -1449,7 +1806,7 @@ static void process_pkt_cmd(ide_config *ide)
case 0x03: // mode sense
cddbg_printf("get sense:\n");
pkt_send(ide, buf, get_sense(ide));
pkt_send(ide, buf, get_sense(&ide->drive[ide->regs.drv]));
break;
case 0x55: // mode select
@@ -1470,19 +1827,19 @@ static void process_pkt_cmd(ide_config *ide)
case 0x45: // play lba
printf("CD PLAY AUDIO(10)\n");
play_audio10(ide, cmdbuf);
play_audio10(&ide->drive[ide->regs.drv], cmdbuf);
cd_reply(ide, 0);
break;
case 0x47: // play msf
printf("CD PLAY AUDIO MSF\n");
play_audio_msf(ide, cmdbuf);
play_audio_msf(&ide->drive[ide->regs.drv], cmdbuf);
cd_reply(ide, 0);
break;
case 0x4B: // pause/resume
printf("CD PAUSE/RESUME\n");
pause_resume(ide, cmdbuf);
pause_resume(&ide->drive[ide->regs.drv], cmdbuf);
cd_reply(ide, 0);
break;

View File

@@ -3,7 +3,8 @@
#include "x86.h"
void x86_ide_set(uint32_t num, uint32_t baseaddr, fileTYPE *f, int ver);
const char * x86_ide_parse_cd(uint32_t num, const char *filename);
void x86_ide_set(uint32_t num, uint32_t baseaddr, fileTYPE *f, int ver, int cd);
void x86_ide_io(int num, int req);
int x86_ide_is_placeholder(int num);
void x86_ide_reset(uint8_t hotswap);