Add CHD support for ao486 CD-ROM

This commit is contained in:
Zakk
2020-12-27 16:39:44 -05:00
parent f2fa248eba
commit 26a2d8ee27
11 changed files with 209 additions and 36 deletions

4
cd.h
View File

@@ -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;

View File

@@ -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

View File

@@ -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));

View File

@@ -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;

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;