NP2kai/fdd/sxsicd.c
2019-03-21 20:48:05 +09:00

536 lines
11 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "compiler.h"
#include "strres.h"
#include "textfile.h"
#include "dosio.h"
#include "sysmng.h"
#include "sxsi.h"
#ifdef SUPPORT_PHYSICAL_CDDRV
#include <winioctl.h>
#include <api/ntddcdrm.h>
#endif
#ifdef SUPPORT_KAI_IMAGES
#include "diskimage/cddfile.h"
#include "diskimage/cd/cdd_iso.h"
#include "diskimage/cd/cdd_cue.h"
#include "diskimage/cd/cdd_ccd.h"
#include "diskimage/cd/cdd_mds.h"
#include "diskimage/cd/cdd_nrg.h"
BRESULT sxsicd_open(SXSIDEV sxsi, const OEMCHAR *fname) {
const OEMCHAR *ext;
#ifdef SUPPORT_PHYSICAL_CDDRV
// XXX: 手抜き判定注意実CDドライブ
if(_tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0){
return(openrealcdd(sxsi, fname));
}
#endif
// とりあえず拡張子で判断
ext = file_getext(fname);
if (!file_cmpname(ext, str_cue)) { // CUEシート(*.cue)
return(opencue(sxsi, fname));
}
else if (!file_cmpname(ext, str_ccd)) { // CloneCD(*.ccd)に対応
return(openccd(sxsi, fname));
}
else if (!file_cmpname(ext, str_cdm)) { // CD Manipulator(*.cdm)に対応(読み方はCloneCDと一緒)
return(openccd(sxsi, fname));
// return(opencdm(sxsi, fname));
}
else if (!file_cmpname(ext, str_mds)) { // Media Descriptor(*.mds)に対応
return(openmds(sxsi, fname));
}
else if (!file_cmpname(ext, str_nrg)) { // Nero(*.nrg)に対応
return(opennrg(sxsi, fname));
}
return(openiso(sxsi, fname)); // 知らない拡張子なら、とりあえずISOとして開いてみる
}
CDTRK sxsicd_gettrk(SXSIDEV sxsi, UINT *tracks) {
CDINFO cdinfo;
cdinfo = (CDINFO)sxsi->hdl;
if (tracks) {
*tracks = cdinfo->trks;
}
return(cdinfo->trk);
}
BRESULT sxsicd_readraw(SXSIDEV sxsi, FILEPOS pos, void *buf) {
CDINFO cdinfo;
FILEH fh;
FILEPOS fpos;
UINT16 secsize;
UINT i;
UINT32 secs;
// UINT64 trk_offset;
int isPhysicalCD = 0;
// 範囲外は失敗
if ((pos < 0) || (sxsi->totals < pos)) {
return(FAILURE);
}
cdinfo = (CDINFO)sxsi->hdl;
#ifdef SUPPORT_PHYSICAL_CDDRV
// XXX: 事前に判定して記録しておくべき・・・
isPhysicalCD = (cdinfo->path[0] == '\\' && cdinfo->path[1] == '\\' && cdinfo->path[2] == '.' && cdinfo->path[3] == '\\');
#endif
// pos位置のセクタサイズを取得
for (i = cdinfo->trks - 1; i >= 0; i--) {
if (cdinfo->trk[i].pos <= (UINT32)pos) {
secsize = cdinfo->trk[i].sector_size;
break;
}
}
if (secsize == 2048 && !isPhysicalCD) {
return(FAILURE);
}
if (sxsi_prepare(sxsi) != SUCCESS) {
return(FAILURE);
}
fh = ((CDINFO)sxsi->hdl)->fh;
fpos = 0;
secs = 0;
for (i = 0; i < cdinfo->trks; i++) {
if (cdinfo->trk[i].str_sec <= (UINT32)pos && (UINT32)pos <= cdinfo->trk[i].end_sec) {
fpos += (pos - secs) * cdinfo->trk[i].sector_size;
break;
}
fpos += cdinfo->trk[i].sectors * cdinfo->trk[i].sector_size;
secs += cdinfo->trk[i].sectors;
}
fpos += (FILEPOS)(cdinfo->trk[0].start_offset);
#ifdef SUPPORT_PHYSICAL_CDDRV
if(isPhysicalCD){
DWORD BytesReturned;
RAW_READ_INFO rawReadInfo;
rawReadInfo.TrackMode = CDDA;
rawReadInfo.SectorCount = 1;
rawReadInfo.DiskOffset.QuadPart = fpos;
if (!DeviceIoControl(fh,IOCTL_CDROM_RAW_READ,&rawReadInfo,sizeof(RAW_READ_INFO), buf, 2352, &BytesReturned,0)) {
return(FAILURE);
}
if (BytesReturned != 2352) {
return(FAILURE);
}
}else{
#endif
if ((file_seek(fh, fpos, FSEEK_SET) != fpos) ||
(file_read(fh, buf, 2352) != 2352)) {
return(FAILURE);
}
#ifdef SUPPORT_PHYSICAL_CDDRV
}
#endif
return(SUCCESS);
}
#else /* SUPPORT_KAI_IMAGES */
// 旧処理もとりあえず残しておく
#include "cpucore.h"
#include "pccore.h"
static const UINT8 cd001[7] = {0x01,'C','D','0','0','1',0x01};
typedef struct {
FILEH fh;
UINT type;
UINT trks;
_CDTRK trk[100];
OEMCHAR path[MAX_PATH];
} _CDINFO, *CDINFO;
// ---- セクタ2048
static int issec2048(FILEH fh) {
FILEPOS fpos;
UINT8 buf[2048];
UINT secsize;
UINT fsize;
fpos = 16 * 2048;
if (file_seek(fh, fpos, FSEEK_SET) != fpos) {
goto sec2048_err;
}
if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) {
goto sec2048_err;
}
if (memcmp(buf, cd001, 7) != 0) {
goto sec2048_err;
}
secsize = LOADINTELWORD(buf + 128);
if (secsize != 2048) {
goto sec2048_err;
}
fsize = file_getsize(fh);
if ((fsize % 2048) != 0) {
goto sec2048_err;
}
return(fsize / 2048);
sec2048_err:
return(-1);
}
static REG8 sec2048_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) {
FILEH fh;
UINT rsize;
if (sxsi_prepare(sxsi) != SUCCESS) {
return(0x60);
}
if ((pos < 0) || (pos >= sxsi->totals)) {
return(0x40);
}
pos = pos * 2048;
fh = ((CDINFO)sxsi->hdl)->fh;
if (file_seek(fh, pos, FSEEK_SET) != pos) {
return(0xd0);
}
while(size) {
rsize = np2min(size, 2048);
CPU_REMCLOCK -= rsize;
if (file_read(fh, buf, rsize) != rsize) {
return(0xd0);
}
buf += rsize;
size -= rsize;
}
return(0x00);
}
// ---- セクタ2352
static int issec2352(FILEH fh) {
FILEPOS fpos;
UINT8 buf[2048];
UINT secsize;
UINT fsize;
fpos = (16 * 2352) + 16;
if (file_seek(fh, fpos, FSEEK_SET) != fpos) {
goto sec2352_err;
}
if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) {
goto sec2352_err;
}
if (memcmp(buf, cd001, 7) != 0) {
goto sec2352_err;
}
secsize = LOADINTELWORD(buf + 128);
if (secsize != 2048) {
goto sec2352_err;
}
fsize = file_getsize(fh);
if ((fsize % 2352) != 0) {
goto sec2352_err;
}
return(fsize / 2352);
sec2352_err:
return(-1);
}
static REG8 sec2352_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) {
FILEH fh;
FILEPOS fpos;
UINT rsize;
if (sxsi_prepare(sxsi) != SUCCESS) {
return(0x60);
}
if ((pos < 0) || (pos >= sxsi->totals)) {
return(0x40);
}
fh = ((CDINFO)sxsi->hdl)->fh;
while(size) {
fpos = (pos * 2352) + 16;
if (file_seek(fh, fpos, FSEEK_SET) != fpos) {
return(0xd0);
}
rsize = np2min(size, 2048);
CPU_REMCLOCK -= rsize;
if (file_read(fh, buf, rsize) != rsize) {
return(0xd0);
}
buf += rsize;
size -= rsize;
pos++;
}
return(0x00);
}
// ----
static BRESULT cd_reopen(SXSIDEV sxsi) {
CDINFO cdinfo;
FILEH fh;
cdinfo = (CDINFO)sxsi->hdl;
fh = file_open_rb(cdinfo->path);
if (fh != FILEH_INVALID) {
cdinfo->fh = fh;
return(SUCCESS);
}
else {
return(FAILURE);
}
}
static void cd_close(SXSIDEV sxsi) {
CDINFO cdinfo;
cdinfo = (CDINFO)sxsi->hdl;
file_close(cdinfo->fh);
}
static void cd_destroy(SXSIDEV sxsi) {
_MFREE((CDINFO)sxsi->hdl);
}
// ----
static const OEMCHAR str_cue[] = OEMTEXT("cue");
static const OEMCHAR str_file[] = OEMTEXT("FILE");
static const OEMCHAR str_track[] = OEMTEXT("TRACK");
static const OEMCHAR str_mode1[] = OEMTEXT("MODE1/2352");
static const OEMCHAR str_index[] = OEMTEXT("INDEX");
static const OEMCHAR str_audio[] = OEMTEXT("AUDIO");
static BRESULT openimg(SXSIDEV sxsi, const OEMCHAR *path,
const _CDTRK *trk, UINT trks) {
FILEH fh;
UINT type;
FILEPOS totals;
CDINFO cdinfo;
UINT mediatype;
UINT i;
fh = file_open_rb(path);
if (fh == FILEH_INVALID) {
goto sxsiope_err1;
}
type = 2048;
totals = issec2048(fh);
if (totals < 0) {
type = 2352;
totals = issec2352(fh);
}
if (totals < 0) {
goto sxsiope_err2;
}
cdinfo = (CDINFO)_MALLOC(sizeof(_CDINFO), path);
if (cdinfo == NULL) {
goto sxsiope_err2;
}
ZeroMemory(cdinfo, sizeof(_CDINFO));
cdinfo->fh = fh;
cdinfo->type = type;
if ((trk != NULL) && (trks != 0)) {
trks = np2min(trks, NELEMENTS(cdinfo->trk) - 1);
CopyMemory(cdinfo->trk, trk, trks * sizeof(_CDTRK));
}
else {
cdinfo->trk[0].type = 0x14;
cdinfo->trk[0].track = 1;
// cdinfo->trk[0].pos = 0;
trks = 1;
}
mediatype = 0;
for (i=0; i<trks; i++) {
if (cdinfo->trk[i].type == 0x14) {
mediatype |= SXSIMEDIA_DATA;
}
else if (cdinfo->trk[i].type == 0x10) {
mediatype |= SXSIMEDIA_AUDIO;
}
}
cdinfo->trk[trks].type = 0x10;
cdinfo->trk[trks].track = 0xaa;
cdinfo->trk[trks].pos = totals;
cdinfo->trks = trks;
file_cpyname(cdinfo->path, path, NELEMENTS(cdinfo->path));
sxsi->reopen = cd_reopen;
if (type == 2048) {
sxsi->read = sec2048_read;
}
else {
sxsi->read = sec2352_read;
}
sxsi->close = cd_close;
sxsi->destroy = cd_destroy;
sxsi->hdl = (INTPTR)cdinfo;
sxsi->totals = totals;
sxsi->cylinders = 0;
sxsi->size = 2048;
sxsi->sectors = 1;
sxsi->surfaces = 1;
sxsi->headersize = 0;
sxsi->mediatype = mediatype;
return(SUCCESS);
sxsiope_err2:
file_close(fh);
sxsiope_err1:
return(FAILURE);
}
static BRESULT getint2(const OEMCHAR *str, UINT *val) {
if ((str[0] < '0') || (str[0] > '9') ||
(str[1] < '0') || (str[1] > '9')) {
return(FAILURE);
}
if (val) {
*val = ((str[0] - '0') * 10) + (str[1] - '0');
}
return(SUCCESS);
}
static UINT32 getpos(const OEMCHAR *str) {
UINT m;
UINT s;
UINT f;
if ((getint2(str + 0, &m) != SUCCESS) || (str[2] != ':') ||
(getint2(str + 3, &s) != SUCCESS) || (str[5] != ':') ||
(getint2(str + 6, &f) != SUCCESS)) {
return(0);
}
return((((m * 60) + s) * 75) + f);
}
static BRESULT opencue(SXSIDEV sxsi, const OEMCHAR *fname) {
_CDTRK trk[99];
OEMCHAR path[MAX_PATH];
UINT idx;
UINT8 curtrk;
UINT curtype;
TEXTFILEH tfh;
OEMCHAR buf[512];
OEMCHAR *argv[8];
int argc;
ZeroMemory(trk, sizeof(trk));
path[0] = '\0';
idx = 0;
curtrk = 1;
curtype = 0x14;
tfh = textfile_open(fname, 0x800);
if (tfh == NULL) {
return(FAILURE);
}
while(textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) {
argc = milstr_getarg(buf, argv, NELEMENTS(argv));
if ((argc >= 3) && (!milstr_cmp(argv[0], str_file))) {
file_cpyname(path, fname, NELEMENTS(path));
file_cutname(path);
file_catname(path, argv[1], NELEMENTS(path));
}
else if ((argc >= 3) && (!milstr_cmp(argv[0], str_track))) {
curtrk = (UINT8)milstr_solveINT(argv[1]);
if (!milstr_cmp(argv[2], str_mode1)) {
curtype = 0x14;
}
else if (!milstr_cmp(argv[2], str_audio)) {
curtype = 0x10;
}
}
else if ((argc >= 3) && (!milstr_cmp(argv[0], str_index))) {
if (idx < NELEMENTS(trk)) {
trk[idx].type = curtype;
trk[idx].track = curtrk;
trk[idx].pos = getpos(argv[2]);
idx++;
}
}
}
textfile_close(tfh);
return(openimg(sxsi, path, trk, idx));
}
BRESULT sxsicd_open(SXSIDEV sxsi, const OEMCHAR *fname) {
const OEMCHAR *ext;
ext = file_getext(fname);
if (!file_cmpname(ext, str_cue)) {
return(opencue(sxsi, fname));
}
return(openimg(sxsi, fname, NULL, 0));
}
CDTRK sxsicd_gettrk(SXSIDEV sxsi, UINT *tracks) {
CDINFO cdinfo;
cdinfo = (CDINFO)sxsi->hdl;
if (tracks) {
*tracks = cdinfo->trks;
}
return(cdinfo->trk);
}
BRESULT sxsicd_readraw(SXSIDEV sxsi, FILEPOS pos, void *buf) {
CDINFO cdinfo;
FILEH fh;
FILEPOS fpos;
cdinfo = (CDINFO)sxsi->hdl;
if (cdinfo->type != 2352) {
return(FAILURE);
}
if (sxsi_prepare(sxsi) != SUCCESS) {
return(FAILURE);
}
if ((pos < 0) || (pos >= sxsi->totals)) {
return(FAILURE);
}
fh = ((CDINFO)sxsi->hdl)->fh;
fpos = pos * 2352;
if ((file_seek(fh, fpos, FSEEK_SET) != fpos) ||
(file_read(fh, buf, 2352) != 2352)) {
return(FAILURE);
}
return(SUCCESS);
}
#endif /* SUPPORT_KAI_IMAGES */