- [Psy-X] added PsyX_CDFS_Init for direct CD image initialization

This commit is contained in:
Ilya Shurumov 2021-04-09 15:44:16 +06:00
parent 3153a9b3e7
commit f2b58ba72d
3 changed files with 133 additions and 81 deletions

View File

@ -110,4 +110,9 @@ extern void PsyX_WaitForTimestep(int count);
/* Changes swap interval state */
extern void PsyX_EnableSwapInterval(int enable);
//----------------------------------------------------------------------
/* Initializes CD filesystem */
extern void PsyX_CDFS_Init(const char* imageFileName, int track = 0, int sectorSize = 0);
#endif

View File

@ -38,16 +38,21 @@ typedef struct commandQueue
u_int count;
}commandQueue_s, *commandQueue_p;
#define COMMAND_QUEUE_SIZE 128
struct commandQueue comQueue[COMMAND_QUEUE_SIZE];
int comQueueIndex = 0;
int comQueueCount = 0;
int currentSector = 0;
int g_sectorSize = 0;
int currentTrack = 0;
int numFrames = 0;
int CD_com = 0;
struct commandQueue g_cdComQueue[COMMAND_QUEUE_SIZE];
int g_cdComQueueIndex = 0;
int g_cdComQueueCount = 0;
int g_cdCurrentSector = 0;
int g_cdSectorSize = CD_SECTOR_SIZE_MODE2; // default
int g_cdCurrentTrack = 1; // default
int g_cdNumFrames = 0;
int g_CD_com = 0;
char g_cdImageBinaryFileName[2048] = { 0 };
int g_UseCDImage = 0;
#pragma pack(push, 1)
struct TOC
@ -84,6 +89,18 @@ struct AudioSector
};
#pragma pack(pop)
void PsyX_CDFS_Init(const char* imageFileName, int track = 0, int sectorSize = 0)
{
g_UseCDImage = 1;
strcpy(g_cdImageBinaryFileName, imageFileName);
if (track > 0)
g_cdCurrentTrack = track;
if (sectorSize > 0)
g_cdSectorSize = sectorSize;
}
// utility function
int GetCurrentDirName(char* dest, char* src)
@ -146,7 +163,7 @@ CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
dirLevel = 0;
// go to sector 22
fseek(g_imageFp, CD_ROOT_DIRECTORY_SECTOR * g_sectorSize, SEEK_SET);
fseek(g_imageFp, CD_ROOT_DIRECTORY_SECTOR * g_cdSectorSize, SEEK_SET);
fread(&sector, sizeof(Sector), 1, g_imageFp);
toc = (TOC*)&sector.data[0];
@ -179,7 +196,7 @@ CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
// read the needed sector with directory contents
dirLevel++;
fseek(g_imageFp, toc->sectorPosition[0] * g_sectorSize, SEEK_SET);
fseek(g_imageFp, toc->sectorPosition[0] * g_cdSectorSize, SEEK_SET);
fread(&sector, sizeof(Sector), 1, g_imageFp);
tocLocalOffset = 0;;
@ -191,7 +208,7 @@ CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
fp->size = toc->fileSize[0];
fseek(g_imageFp, toc->sectorPosition[0] * g_sectorSize, SEEK_SET);
fseek(g_imageFp, toc->sectorPosition[0] * g_cdSectorSize, SEEK_SET);
fread(&sector, sizeof(struct Sector), 1, g_imageFp);
fp->pos.minute = sector.addr[0];
@ -246,7 +263,7 @@ int CdControl(u_char com, u_char * param, u_char * result)
{
CdlLOC* cd = (CdlLOC*)param;
CD_com = com;
g_CD_com = com;
if (g_imageFp == NULL)
return 0;
@ -254,7 +271,7 @@ int CdControl(u_char com, u_char * param, u_char * result)
switch (com)
{
case CdlSetloc:
fseek(g_imageFp, CdPosToInt(cd)*g_sectorSize, SEEK_SET);
fseek(g_imageFp, CdPosToInt(cd)*g_cdSectorSize, SEEK_SET);
break;
case CdlReadS:
{
@ -263,9 +280,9 @@ int CdControl(u_char com, u_char * param, u_char * result)
CdlLOC currentLoc;
CdIntToPos(filePos, &currentLoc);
fseek(g_imageFp, CdPosToInt(cd) * g_sectorSize, SEEK_SET);
fseek(g_imageFp, CdPosToInt(cd) * g_cdSectorSize, SEEK_SET);
currentSector = CdPosToInt(cd);
g_cdCurrentSector = CdPosToInt(cd);
if (cd->sector != currentLoc.sector)
return 1;
@ -291,7 +308,7 @@ int CdControlB(u_char com, u_char* param, u_char* result)
case CdlSetloc:
{
CdlLOC* cd = (CdlLOC*)param;
fseek(g_imageFp, CdPosToInt(cd) * g_sectorSize, SEEK_SET);
fseek(g_imageFp, CdPosToInt(cd) * g_cdSectorSize, SEEK_SET);
readMode = RM_DATA;
ret = 1;
break;
@ -317,7 +334,7 @@ int CdControlB(u_char com, u_char* param, u_char* result)
}
if(ret)
CD_com = com;
g_CD_com = com;
return ret;
}
@ -326,14 +343,14 @@ int CdControlF(u_char com, u_char * param)
{
// TODO: CdControlF() waits for the previous command to complete execution before issuing the new command
CD_com = com;
g_CD_com = com;
switch (com)
{
case CdlSetloc:
{
CdlLOC* cd = (CdlLOC*)param;
fseek(g_imageFp, CdPosToInt(cd) * g_sectorSize, SEEK_SET);
fseek(g_imageFp, CdPosToInt(cd) * g_cdSectorSize, SEEK_SET);
break;
}
case CdlSetfilter:
@ -386,12 +403,12 @@ int CdRead(int sectors, u_long* buf, int mode)
for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
{
if (comQueue[i].processed == 1)
if (g_cdComQueue[i].processed == 1)
{
comQueue[i].mode = mode; // CdlMode*
comQueue[i].p = (unsigned char*)buf;
comQueue[i].processed = 0;
comQueue[i].count = sectors;
g_cdComQueue[i].mode = mode; // CdlMode*
g_cdComQueue[i].p = (unsigned char*)buf;
g_cdComQueue[i].processed = 0;
g_cdComQueue[i].count = sectors;
ret = 1;
break;
@ -410,7 +427,7 @@ int CdReadSync(int mode, u_char* result)
for (i = 0; i < COMMAND_QUEUE_SIZE; i++)
{
if (comQueue[i].processed == 0)
if (g_cdComQueue[i].processed == 0)
{
do
{
@ -420,8 +437,8 @@ int CdReadSync(int mode, u_char* result)
fread(&sector, sizeof(Sector), 1, g_imageFp);
memcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));
comQueue[i].p += sizeof(sector.data);
memcpy(g_cdComQueue[i].p, &sector.data[0], sizeof(sector.data));
g_cdComQueue[i].p += sizeof(sector.data);
}
else if (readMode == RM_XA_AUDIO)
{
@ -429,26 +446,26 @@ int CdReadSync(int mode, u_char* result)
fread(&sector, sizeof(AudioSector), 1, g_imageFp);
memcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));
comQueue[i].p += sizeof(sector.data);
memcpy(g_cdComQueue[i].p, &sector.data[0], sizeof(sector.data));
g_cdComQueue[i].p += sizeof(sector.data);
}
else
{
assert(0);
}
if (--comQueue[i].count == 0)
comQueue[i].processed = 1;
if (--g_cdComQueue[i].count == 0)
g_cdComQueue[i].processed = 1;
// in mode 1 it doesn't wait until read is completed
if (mode == 1)
break;
} while (comQueue[i].count > 0);
} while (g_cdComQueue[i].count > 0);
// returns number of sectors remaining
// on mode == 0 it's always greater than 0
return comQueue[i].count;
return g_cdComQueue[i].count;
}
}
@ -477,15 +494,15 @@ int CdSync(int mode, u_char * result)
{
case CdlGetlocP:
CdlLOC locP;
CdIntToPos(currentSector+=20, &locP);
result[0] = currentTrack;
CdIntToPos(g_cdCurrentSector+=20, &locP);
result[0] = g_cdCurrentTrack;
result[1] = 1;//index, usually 1
result[2] = locP.minute;
result[3] = locP.second;
result[4] = locP.sector;
result[5] = locP.minute + ENCODE_BCD(numFrames);
result[6] = locP.second + ENCODE_BCD(numFrames);
result[7] = locP.sector + ENCODE_BCD(numFrames);
result[5] = locP.minute + ENCODE_BCD(g_cdNumFrames);
result[6] = locP.second + ENCODE_BCD(g_cdNumFrames);
result[7] = locP.sector + ENCODE_BCD(g_cdNumFrames);
//Dirty, for now read the audio data
if (readMode == RM_XA_AUDIO)
@ -507,28 +524,63 @@ int CdSync(int mode, u_char * result)
return 0;
}
// TODO: don't rely on cue sheet
// use this https://gist.github.com/ceritium/139577 to detect Mode 1 or Mode 2
int ParseCueSheet()
int OpenBinaryImageFile()
{
int cdMode;
char* binFileName = NULL;
g_imageFp = fopen(DISC_IMAGE_FILENAME, "rb");
// already open?
// TODO: it has to be closed
// FIXME: what if Psy-X users want to swap CDs?
if (g_imageFp != NULL)
return 0;
if (g_imageFp == NULL)
// open Binary
g_imageFp = fopen(g_cdImageBinaryFileName, "rb");
if (!g_imageFp)
{
eprinterr("%s not found.\n", DISC_IMAGE_FILENAME);
eprinterr("CD image '%s' not found.\n", g_cdImageBinaryFileName);
return 0;
}
fseek(g_imageFp, 0, SEEK_END);
unsigned int binFileLength = ftell(g_imageFp);
g_cdNumFrames = binFileLength / g_cdSectorSize;
unsigned int cueSheetFileLength = ftell(g_imageFp);
assert(g_cdNumFrames != 0);
fseek(g_imageFp, 0, SEEK_SET);
eprintinfo("Using '%s' image, sector size: %d, frames: %d\n", g_cdImageBinaryFileName, g_cdSectorSize, g_cdNumFrames);
return 1;
}
// TODO: don't just rely on cue sheet
// use this https://gist.github.com/ceritium/139577 to detect Mode 1 or Mode 2
int ParseCueSheet()
{
if(strlen(g_cdImageBinaryFileName))
{
OpenBinaryImageFile();
return 1;
}
int cdMode;
char* binFileName = NULL;
FILE* cueFp = fopen(DISC_CUE_FILENAME, "rb");
if (cueFp == NULL)
{
eprinterr("%s not found.\n", DISC_CUE_FILENAME);
return 0;
}
fseek(cueFp, 0, SEEK_END);
unsigned int cueSheetFileLength = ftell(cueFp);
char* cueSheet = (char*)malloc(cueSheetFileLength);
fseek(g_imageFp, 0, SEEK_SET);
fread(cueSheet, cueSheetFileLength, 1, g_imageFp);
fseek(cueFp, 0, SEEK_SET);
fread(cueSheet, cueSheetFileLength, 1, cueFp);
//Null terminated
char* string = &cueSheet[0];
@ -577,7 +629,7 @@ int ParseCueSheet()
while (isspace(string[0]))
string++;
currentTrack = atoi(string);
g_cdCurrentTrack = atoi(string);
string += 2;
@ -593,30 +645,20 @@ int ParseCueSheet()
assert(string[0] == '/');
string++;
g_sectorSize = atoi(string);
g_cdSectorSize = atoi(string);
assert(g_sectorSize == CD_SECTOR_SIZE_MODE2);
assert(g_cdSectorSize == CD_SECTOR_SIZE_MODE2);
fclose(g_imageFp);
g_imageFp = fopen(binFileName, "rb");
fclose(cueFp);
eprintinfo("CUE: '%s' is Mode %d image\n", binFileName, cdMode);
if (!g_imageFp)
{
eprinterr("%s not found.\n", binFileName);
free(cueSheet);
return 0;
}
fseek(g_imageFp, 0, SEEK_END);
unsigned int binFileLength = ftell(g_imageFp);
numFrames = binFileLength / g_sectorSize;
// copy file name
strcpy(g_cdImageBinaryFileName, binFileName);
assert(numFrames != 0);
fseek(g_imageFp, 0, SEEK_SET);
free(cueSheet);
eprintinfo("CUE: '%s' is Mode %d image\n", g_cdImageBinaryFileName, cdMode);
OpenBinaryImageFile();
}
return 1;
@ -624,24 +666,29 @@ int ParseCueSheet()
int CdInit(void)
{
currentSector = 0;
g_cdCurrentSector = 0;
//Read the cue sheet and obtain properties from it.
if (!ParseCueSheet())
return 0;
memset(&comQueue, 0, sizeof(comQueue));
for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
if(g_UseCDImage)
{
comQueue[i].processed = 1;
//Read the cue sheet and obtain properties from it.
if (!ParseCueSheet())
return 0;
}
else
{
// TODO: explicitly PC FS or CD DRIVE?
}
memset(&g_cdComQueue, 0, sizeof(g_cdComQueue));
for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
g_cdComQueue[i].processed = 1;
return 1;
}
int CdLastCom(void)
{
return CD_com;
return g_CD_com;
}
int CdGetSector(void *madr, int size)
@ -750,7 +797,7 @@ int _eCdSpoolerThreadFunc(void* data)
eprintinfo("CD: 'CdlReadS' at %d\n", sector);
// seek
fseek(g_imageFp, sector * g_sectorSize, SEEK_SET);
fseek(g_imageFp, sector * g_cdSectorSize, SEEK_SET);
g_cdSpoolerSeekCmd = 0;
}
}

View File

@ -4,6 +4,6 @@
#include "PLATFORM_SETUP.H"
//Disc image filename to load for disc image builds
#define DISC_IMAGE_FILENAME "IMAGE.CUE"
#define DISC_CUE_FILENAME "IMAGE.CUE"
#endif