Add CHD support for ao486 CD-ROM
This commit is contained in:
4
cd.h
4
cd.h
@@ -12,7 +12,7 @@ typedef struct
|
||||
int end;
|
||||
int type;
|
||||
int sector_size;
|
||||
} track_t;
|
||||
} cd_track_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -20,7 +20,7 @@ typedef struct
|
||||
int last;
|
||||
int sectorSize;
|
||||
chd_file *chd_f;
|
||||
track_t tracks[100];
|
||||
cd_track_t tracks[100];
|
||||
// fileTYPE sub;
|
||||
} toc_t;
|
||||
|
||||
|
||||
@@ -418,6 +418,7 @@ CHD_EXPORT chd_error chd_codec_config(chd_file *chd, int param, void *config);
|
||||
/* return a string description of a codec */
|
||||
CHD_EXPORT const char *chd_get_codec_name(UINT32 codec);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
9
menu.cpp
9
menu.cpp
@@ -1973,15 +1973,14 @@ void HandleUI(void)
|
||||
memcpy(Selected_tmp, Selected_S[(int)ioctl_index], sizeof(Selected_tmp));
|
||||
if (is_x86()) strcpy(Selected_tmp, x86_get_image_path(ioctl_index));
|
||||
|
||||
if (is_pce() || is_megacd())
|
||||
if (is_pce() || is_megacd() || is_x86())
|
||||
{
|
||||
if (!strncasecmp(fs_pFileExt, "CUE", 3))
|
||||
{
|
||||
//if (!strncasecmp(fs_pFileExt, "CUE", 3))
|
||||
//{
|
||||
//look for CHD too
|
||||
printf("LOOK FOR CHD\n");
|
||||
strcat(fs_pFileExt, "CHD");
|
||||
strcat(ext, "CHD");
|
||||
}
|
||||
//}
|
||||
int num = ScanDirectory(Selected_tmp, SCANF_INIT, fs_pFileExt, 0);
|
||||
memcpy(Selected_tmp, Selected_S[(int)ioctl_index], sizeof(Selected_tmp));
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ chd_error mister_load_chd(const char *filename, toc_t *cd_toc)
|
||||
return CHDERR_NO_INTERFACE; //I'm not sure this error condition is possible, so just use whatever
|
||||
}
|
||||
|
||||
mister_chd_log("hunkbytes %d unitbytes %d logical length %d\n", chd_header->hunkbytes, chd_header->unitbytes, chd_header->logicalbytes);
|
||||
mister_chd_log("hunkbytes %d unitbytes %d logical length %llu\n", chd_header->hunkbytes, chd_header->unitbytes, chd_header->logicalbytes);
|
||||
//Load track info
|
||||
|
||||
int sector_cnt = 0;
|
||||
@@ -75,13 +75,19 @@ chd_error mister_load_chd(const char *filename, toc_t *cd_toc)
|
||||
cd_toc->tracks[cd_toc->last].start = 0;
|
||||
}
|
||||
|
||||
if (!strcmp(track_type, "MODE1_RAW") || !strcmp(track_type, "MODE2_RAW"))
|
||||
if (!strcmp(track_type, "MODE1_RAW"))
|
||||
{
|
||||
cd_toc->tracks[cd_toc->last].sector_size = 2352;
|
||||
cd_toc->tracks[cd_toc->last].type = 1;
|
||||
} else if (!strcmp(track_type, "MODE2_RAW")) {
|
||||
cd_toc->tracks[cd_toc->last].sector_size = 2352;
|
||||
cd_toc->tracks[cd_toc->last].type = 2;
|
||||
} else if (!strcmp(track_type, "MODE1")) {
|
||||
cd_toc->tracks[cd_toc->last].sector_size = 2048;
|
||||
cd_toc->tracks[cd_toc->last].type = 1;
|
||||
} else if (!strcmp(track_type, "MODE2")) {
|
||||
cd_toc->tracks[cd_toc->last].sector_size = 2336;
|
||||
cd_toc->tracks[cd_toc->last].type = 2;
|
||||
} else if (!strcmp(track_type, "AUDIO")) {
|
||||
cd_toc->tracks[cd_toc->last].sector_size = 2352;
|
||||
cd_toc->tracks[cd_toc->last].type = 0;
|
||||
@@ -105,7 +111,7 @@ chd_error mister_load_chd(const char *filename, toc_t *cd_toc)
|
||||
}
|
||||
|
||||
|
||||
chd_error mister_chd_read_sector(chd_file *chd_f, int lba, uint8_t d_offset, uint8_t s_offset, int length, uint8_t *destbuf, uint8_t *hunkbuf, int *hunknum)
|
||||
chd_error mister_chd_read_sector(chd_file *chd_f, int lba, uint32_t d_offset, uint32_t s_offset, int length, uint8_t *destbuf, uint8_t *hunkbuf, int *hunknum)
|
||||
{
|
||||
|
||||
int tmphnum = 0;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <libchdr/cdrom.h>
|
||||
#include "../../cd.h"
|
||||
|
||||
chd_error mister_chd_read_sector(chd_file *chd_f, int lba, uint8_t d_offset, uint8_t s_offset, int length, uint8_t *destbuf, uint8_t *hunkbuf, int *hunknum);
|
||||
chd_error mister_chd_read_sector(chd_file *chd_f, int lba, uint32_t d_offset, uint32_t s_offset, int length, uint8_t *destbuf, uint8_t *hunkbuf, int *hunknum);
|
||||
chd_error mister_load_chd(const char *filename, toc_t *cd_toc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -244,13 +244,13 @@ int cdd_t::Load(const char *filename)
|
||||
|
||||
Unload();
|
||||
|
||||
const char *ext = filename+strlen(filename)-3;
|
||||
if (!strncasecmp("CUE", ext, 3))
|
||||
const char *ext = filename+strlen(filename)-4;
|
||||
if (!strncasecmp(".cue", ext, 4))
|
||||
{
|
||||
if (LoadCUE(filename)) {
|
||||
return (-1);
|
||||
}
|
||||
} else if (!strncasecmp("CHD", ext, 3)) {
|
||||
} else if (!strncasecmp(".chd", ext, 4)) {
|
||||
chd_error err = mister_load_chd(filename, &this->toc);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
|
||||
@@ -251,11 +251,11 @@ int pcecdd_t::Load(const char *filename)
|
||||
{
|
||||
Unload();
|
||||
|
||||
const char *ext = filename+strlen(filename)-3;
|
||||
if (!strncasecmp("CUE", ext, 3))
|
||||
const char *ext = filename+strlen(filename)-4;
|
||||
if (!strncasecmp(".cue", ext, 4))
|
||||
{
|
||||
if (LoadCUE(filename)) return -1;
|
||||
} else if (!strncasecmp("CHD", ext, 3)) {
|
||||
} else if (!strncasecmp(".chd", ext, 4)) {
|
||||
mister_load_chd(filename, &this->toc);
|
||||
if (this->chd_hunkbuf)
|
||||
{
|
||||
|
||||
@@ -245,11 +245,18 @@ static int img_mount(fileTYPE *f, const char *name, int rw)
|
||||
FileClose(f);
|
||||
int writable = 0, ret = 0;
|
||||
|
||||
if (strlen(name))
|
||||
int len = strlen(name);
|
||||
if (len)
|
||||
{
|
||||
writable = rw && FileCanWrite(name);
|
||||
ret = FileOpenEx(f, name, writable ? (O_RDWR | O_SYNC) : O_RDONLY);
|
||||
if (!ret) printf("Failed to open file %s\n", name);
|
||||
const char *ext = name+len-4;
|
||||
if (!strncasecmp(".chd", ext, 4))
|
||||
{
|
||||
ret = 1;
|
||||
} else {
|
||||
writable = rw && FileCanWrite(name);
|
||||
ret = FileOpenEx(f, name, writable ? (O_RDWR | O_SYNC) : O_RDONLY);
|
||||
if (!ret) printf("Failed to open file %s\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
#include "../../user_io.h"
|
||||
#include "../../file_io.h"
|
||||
#include "../../hardware.h"
|
||||
#include "../../cd.h"
|
||||
#include "../../lib/libchdr/include/libchdr/chd.h"
|
||||
#include "x86.h"
|
||||
#include "x86_ide.h"
|
||||
#include "x86_cdrom.h"
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
#define dbg_printf printf
|
||||
#define dbg_print_regs ide_print_regs
|
||||
#define dbg_hexdump hexdump
|
||||
@@ -47,6 +49,7 @@
|
||||
|
||||
#define CD_ERR_NO_DISK ((2 << 4) | ATA_ERR_ABRT)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char min;
|
||||
@@ -240,6 +243,87 @@ static int add_track(drive_t *drv, track_t *curr, uint32_t &shift, const int32_t
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char* load_chd_file(drive_t *drv, const char *chdfile)
|
||||
{
|
||||
|
||||
//Borrow the cd.h "toc_t" and mister_chd* parse function. Then translate the toc_t to drive_t+track_t.
|
||||
//TODO: abstract all the bin/cue+chd+iso parsing and reading into a shared class
|
||||
//
|
||||
|
||||
const char *ext = chdfile+strlen(chdfile)-4;
|
||||
uint32_t total_sector_size = 0;
|
||||
|
||||
|
||||
if (strncasecmp(".chd", ext, 4))
|
||||
{
|
||||
//Not a CHD
|
||||
return 0;
|
||||
}
|
||||
toc_t tmpTOC = { };
|
||||
memset(drv->track, 0, sizeof(drv->track));
|
||||
drv->track_cnt = 0;
|
||||
chd_error err = mister_load_chd(chdfile, &tmpTOC);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (drv->chd_hunkbuf)
|
||||
{
|
||||
free(drv->chd_hunkbuf);
|
||||
}
|
||||
|
||||
drv->chd_hunkbuf = (uint8_t *)malloc(CD_FRAME_SIZE * CD_FRAMES_PER_HUNK);
|
||||
drv->chd_hunknum = -1;
|
||||
drv->chd_f = tmpTOC.chd_f;
|
||||
|
||||
//don't use add_track, just do it ourselves...
|
||||
for(int i = 0; i <= tmpTOC.last; i++)
|
||||
{
|
||||
cd_track_t *chd_track = &tmpTOC.tracks[i];
|
||||
track_t *trk = &drv->track[i];
|
||||
trk->number = i+1;
|
||||
trk->sectorSize = chd_track->sector_size;
|
||||
if (chd_track->type)
|
||||
{
|
||||
trk->attr = 0x40;
|
||||
if (chd_track->type == 2)
|
||||
{
|
||||
trk->mode2 = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
trk->chd_offset = chd_track->offset;
|
||||
trk->start = chd_track->start;
|
||||
trk->length = chd_track->end - chd_track->start;
|
||||
drv->track_cnt++;
|
||||
total_sector_size += trk->length * trk->sectorSize;
|
||||
}
|
||||
|
||||
//Add the lead-out track
|
||||
|
||||
track_t *lead_out = &drv->track[drv->track_cnt];
|
||||
lead_out->number = drv->track_cnt+1;
|
||||
lead_out->attr = 0;
|
||||
lead_out->start = tmpTOC.tracks[tmpTOC.last].end;
|
||||
lead_out->length = 0;
|
||||
|
||||
drv->total_sectors = total_sector_size / 512;
|
||||
drv->chd_total_size = total_sector_size;
|
||||
|
||||
for(uint8_t i = 0; i < drv->track_cnt; i++)
|
||||
{
|
||||
if (drv->track[i].attr == 0x40)
|
||||
{
|
||||
drv->data_num = i;
|
||||
}
|
||||
}
|
||||
|
||||
return chdfile;
|
||||
}
|
||||
|
||||
|
||||
static const char* load_cue_file(drive_t *drv, const char *cuefile)
|
||||
{
|
||||
memset(drv->track, 0, sizeof(drv->track));
|
||||
@@ -881,6 +965,8 @@ static void read_cd_sectors(ide_config *ide, int cnt)
|
||||
void cdrom_read(ide_config *ide)
|
||||
{
|
||||
uint32_t cnt = ide->regs.pkt_cnt;
|
||||
drive_t *drive = &ide->drive[ide->regs.drv];
|
||||
|
||||
if ((cnt * 4) > ide_io_max_size) cnt = ide_io_max_size / 4;
|
||||
|
||||
while ((cnt * 2048) > ide->regs.pkt_size_limit)
|
||||
@@ -889,12 +975,13 @@ void cdrom_read(ide_config *ide)
|
||||
cnt--;
|
||||
}
|
||||
|
||||
|
||||
if (cnt != ide->regs.pkt_cnt)
|
||||
{
|
||||
dbg_printf("** partial CD read\n");
|
||||
}
|
||||
|
||||
if (ide->state == IDE_STATE_INIT_RW)
|
||||
if (ide->state == IDE_STATE_INIT_RW && !drive->chd_f)
|
||||
{
|
||||
uint32_t pos = ide->regs.pkt_lba * ide->drive[ide->regs.drv].track[ide->drive[ide->regs.drv].data_num].sectorSize;
|
||||
|
||||
@@ -902,7 +989,32 @@ void cdrom_read(ide_config *ide)
|
||||
ide->null = (FileSeek(ide->drive[ide->regs.drv].f, pos, SEEK_SET) < 0);
|
||||
}
|
||||
|
||||
read_cd_sectors(ide, cnt);
|
||||
|
||||
if (drive->chd_f) {
|
||||
|
||||
uint32_t hdr = drive->track[drive->data_num].mode2 ? 24 : 16;
|
||||
if (drive->track[drive->data_num].sectorSize == 2048)
|
||||
{
|
||||
hdr = 0;
|
||||
}
|
||||
uint32_t d_offset = 0;
|
||||
|
||||
if (ide->state == IDE_STATE_INIT_RW)
|
||||
{
|
||||
drive->chd_last_partial_lba = ide->regs.pkt_lba;
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < cnt; i++)
|
||||
{
|
||||
|
||||
mister_chd_read_sector(drive->chd_f, drive->chd_last_partial_lba + drive->track[drive->data_num].chd_offset, d_offset, hdr, 2048, ide_buf, drive->chd_hunkbuf, &drive->chd_hunknum);
|
||||
d_offset += 2048;
|
||||
drive->chd_last_partial_lba++;
|
||||
}
|
||||
|
||||
} else {
|
||||
read_cd_sectors(ide, cnt);
|
||||
}
|
||||
|
||||
dbg_printf("\nsector:\n");
|
||||
dbg_hexdump(ide_buf, 512, 0);
|
||||
@@ -1093,10 +1205,17 @@ void cdrom_handle_pkt(ide_config *ide)
|
||||
break;
|
||||
|
||||
case 0x25: // read capacity
|
||||
//printf("** Read Capacity\n");
|
||||
dbg_printf("** Read Capacity\n");
|
||||
if (!drv->load_state)
|
||||
{
|
||||
uint32_t tmp = drv->f->size / 2048;;
|
||||
uint32_t tmp = 0;
|
||||
|
||||
if (drv->chd_f)
|
||||
{
|
||||
tmp = drv->chd_total_size / 2048;
|
||||
} else {
|
||||
tmp = drv->f->size / 2048;
|
||||
}
|
||||
ide_buf[0] = tmp >> 24;
|
||||
ide_buf[1] = tmp >> 16;
|
||||
ide_buf[2] = tmp >> 8;
|
||||
@@ -1114,39 +1233,45 @@ void cdrom_handle_pkt(ide_config *ide)
|
||||
break;
|
||||
|
||||
case 0x2B: // seek
|
||||
|
||||
dbg_printf("** Seek\n");
|
||||
drv->playing = 0;
|
||||
drv->paused = 0;
|
||||
cdrom_reply(ide, 0);
|
||||
break;
|
||||
|
||||
case 0x1E: // lock the cd door - doing nothing.
|
||||
dbg_printf("** Lock Door\n");
|
||||
cdrom_reply(ide, 0);
|
||||
break;
|
||||
|
||||
case 0x5A: // mode sense
|
||||
dbg_printf("** Mode Sense\n");
|
||||
pkt_send(ide, ide_buf, mode_sense(cmdbuf[2]));
|
||||
break;
|
||||
|
||||
case 0x42: // read sub
|
||||
dbg_printf("read sub:\n");
|
||||
dbg_printf("** read sub:\n");
|
||||
pkt_send(ide, ide_buf, read_subchannel(drv, cmdbuf));
|
||||
break;
|
||||
|
||||
case 0x43: // read TOC
|
||||
dbg_printf("** Read TOC\n");
|
||||
pkt_send(ide, ide_buf, read_toc(drv, cmdbuf));
|
||||
break;
|
||||
|
||||
case 0x12: // inquiry
|
||||
dbg_printf("** Inquiry\n");
|
||||
pkt_send(ide, ide_buf, cd_inquiry(cmdbuf[4]));
|
||||
break;
|
||||
|
||||
case 0x03: // mode sense
|
||||
dbg_printf("get sense:\n");
|
||||
dbg_printf("** get sense:\n");
|
||||
pkt_send(ide, ide_buf, get_sense(drv));
|
||||
break;
|
||||
|
||||
case 0x55: // mode select
|
||||
printf("mode select\n");
|
||||
dbg_printf("** mode select\n");
|
||||
ide->regs.cylinder = (cmdbuf[7] << 8) | cmdbuf[8];
|
||||
if (ide->regs.cylinder > 512) ide->regs.cylinder = 512;
|
||||
ide->regs.pkt_io_size = (ide->regs.cylinder + 1) / 2;
|
||||
@@ -1157,24 +1282,25 @@ void cdrom_handle_pkt(ide_config *ide)
|
||||
break;
|
||||
|
||||
case 0x00: // test unit ready
|
||||
dbg_printf("** Test Unit Ready\n");
|
||||
if (!drv->load_state) cdrom_reply(ide, 0);
|
||||
else cdrom_nodisk(ide);
|
||||
break;
|
||||
|
||||
case 0x45: // play lba
|
||||
printf("CD PLAY AUDIO(10)\n");
|
||||
dbg_printf("** CD PLAY AUDIO(10)\n");
|
||||
play_audio10(drv, cmdbuf);
|
||||
cdrom_reply(ide, 0);
|
||||
break;
|
||||
|
||||
case 0x47: // play msf
|
||||
printf("CD PLAY AUDIO MSF\n");
|
||||
dbg_printf("** CD PLAY AUDIO MSF\n");
|
||||
play_audio_msf(drv, cmdbuf);
|
||||
cdrom_reply(ide, 0);
|
||||
break;
|
||||
|
||||
case 0x4B: // pause/resume
|
||||
printf("CD PAUSE/RESUME\n");
|
||||
dbg_printf("** CD PAUSE/RESUME\n");
|
||||
pause_resume(drv, cmdbuf);
|
||||
cdrom_reply(ide, 0);
|
||||
break;
|
||||
@@ -1294,6 +1420,23 @@ void cdrom_reply(ide_config *ide, uint8_t error)
|
||||
ide_set_regs(ide);
|
||||
}
|
||||
|
||||
void cdrom_close_chd(drive_t *drv)
|
||||
{
|
||||
|
||||
if (drv->chd_f)
|
||||
{
|
||||
chd_close(drv->chd_f);
|
||||
drv->chd_f = NULL;
|
||||
}
|
||||
|
||||
if (drv->chd_hunkbuf)
|
||||
{
|
||||
free(drv->chd_hunkbuf);
|
||||
drv->chd_hunkbuf = NULL;
|
||||
}
|
||||
drv->chd_hunknum = -1;
|
||||
}
|
||||
|
||||
const char* cdrom_parse(uint32_t num, const char *filename)
|
||||
{
|
||||
const char *res = 0;
|
||||
@@ -1303,7 +1446,9 @@ const char* cdrom_parse(uint32_t num, const char *filename)
|
||||
const char *path = getFullPath(filename);
|
||||
int drv = num & 1;
|
||||
num >>= 1;
|
||||
res = load_cue_file(&ide_inst[num].drive[drv], path);
|
||||
cdrom_close_chd(&ide_inst[num].drive[drv]);
|
||||
res = load_chd_file(&ide_inst[num].drive[drv], path);
|
||||
if (!res) res = load_cue_file(&ide_inst[num].drive[drv], path);
|
||||
if (!res) res = load_iso_file(&ide_inst[num].drive[drv], path);
|
||||
}
|
||||
return res;
|
||||
|
||||
@@ -115,7 +115,7 @@ void x86_ide_set(uint32_t num, uint32_t baseaddr, fileTYPE *f, int ver, int cd)
|
||||
drive->cylinders = 0;
|
||||
drive->heads = 0;
|
||||
drive->spt = 0;
|
||||
drive->total_sectors = 0;
|
||||
//drive->total_sectors = 0;
|
||||
|
||||
drive->present = f ? 1 : 0;
|
||||
ide_inst[num].state = IDE_STATE_RESET;
|
||||
@@ -145,7 +145,12 @@ void x86_ide_set(uint32_t num, uint32_t baseaddr, fileTYPE *f, int ver, int cd)
|
||||
return;
|
||||
}
|
||||
|
||||
if(drive->f) drive->total_sectors = (drive->f->size / 512);
|
||||
if(drive->f)
|
||||
{
|
||||
if (!drive->chd_f) drive->total_sectors = (drive->f->size / 512);
|
||||
} else {
|
||||
drive->total_sectors = 0;
|
||||
}
|
||||
|
||||
if (!drive->cd)
|
||||
{
|
||||
@@ -355,7 +360,7 @@ void x86_ide_set(uint32_t num, uint32_t baseaddr, fileTYPE *f, int ver, int cd)
|
||||
};
|
||||
|
||||
for (int i = 0; i < 256; i++) drive->id[i] = identify[i];
|
||||
drive->load_state = drive->f ? 1 : 3;
|
||||
drive->load_state = (drive->f || drive->chd_f) ? 1 : 3;
|
||||
}
|
||||
|
||||
if (ide_inst[num].drive[drv].present)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef X86_IDE_H
|
||||
#define X86_IDE_H
|
||||
|
||||
#include "../chd/mister_chd.h"
|
||||
|
||||
#define ATA_STATUS_BSY 0x80 // busy
|
||||
#define ATA_STATUS_RDY 0x40 // ready
|
||||
#define ATA_STATUS_DF 0x20 // device fault
|
||||
@@ -66,11 +68,13 @@ typedef struct
|
||||
uint8_t attr;
|
||||
uint8_t mode2;
|
||||
uint8_t number;
|
||||
int chd_offset;
|
||||
} track_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fileTYPE *f;
|
||||
|
||||
uint8_t present;
|
||||
uint8_t drvnum;
|
||||
|
||||
@@ -93,6 +97,12 @@ typedef struct
|
||||
uint32_t play_start_lba;
|
||||
uint32_t play_end_lba;
|
||||
|
||||
chd_file *chd_f;
|
||||
int chd_hunknum;
|
||||
uint8_t *chd_hunkbuf;
|
||||
uint32_t chd_total_size;
|
||||
uint32_t chd_last_partial_lba;
|
||||
|
||||
uint16_t id[256];
|
||||
} drive_t;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user