<NME> LIBCD.C
<BEF> #include "LIBCD.H"

#include "EMULATOR_SETUP.H"
#include "EMULATOR.H"

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

int CD_Debug = 0;

FILE* openFile = NULL;

enum ReadMode readMode = RM_DATA;

int CD_Debug = 0;

FILE* openFile = NULL;

typedef struct commandQueue
{
	unsigned int mode;
	unsigned char* p;
	unsigned int processed;
	unsigned int count;
}commandQueue_s, *commandQueue_p;
int currentSector = 0;
int sectorSize = 0;
int currentTrack = 0;
int CD_com = 0;

#pragma pack(push, 1)
int sectorSize = 0;
int currentTrack = 0;
int numFrames = 0;
int CD_com = 0;

#pragma pack(push, 1)
struct TOC
{
	unsigned char tocEntryLength;
	unsigned char extEntryLength;
	unsigned int sectorPosition[2];
	unsigned int fileSize[2];
	unsigned char date[7];
	unsigned char flags;
	unsigned char fileUnitSize;
	unsigned char interleaveGapSize;
	unsigned short volSeqNum[2];
	unsigned char nameLength;
};

struct Sector
	unsigned char	edc[4];		/// Error-detection code (CRC32 of data area)
	unsigned char	ecc[276];	/// Error-correction code (uses Reed-Solomon ECC algorithm)
};
#pragma pack(pop)

CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
#pragma pack(pop)

CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
{
	memset(fp, 0, sizeof(CdlFILE));

	if (name[0] == '\\')
	{
		name++;
	}

	if (openFile != NULL)
	{
		fseek(openFile, 22 * sectorSize, SEEK_SET);

		int tocLocalOffset = 0;
        struct Sector sector;
		fread(&sector, sizeof(struct Sector), 1, openFile);
        struct TOC* toc = (struct TOC*)&sector.data[0];
		while (toc->tocEntryLength != 0)
		{
			if (strcmp((char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], name) == 0)
			{
				memcpy(&fp->name[0], (char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], strlen(name));
				fp->size = toc->fileSize[0];
				fseek(openFile, toc->sectorPosition[0] * sectorSize, SEEK_SET);
				fread(&sector, sizeof(struct Sector), 1, openFile);
				fp->pos.minute = sector.addr[0];
				fp->pos.second = sector.addr[1];
				fp->pos.sector = sector.addr[2];


#if _DEBUG
				eprintf("Found %s\n", name);
#endif
				return fp;
			}
			tocLocalOffset += toc->tocEntryLength;
			toc = (struct TOC*)&sector.data[tocLocalOffset];
		}
	}

	return NULL;
}

CdlLOC* CdIntToPos(int i, CdlLOC* p)
{
	i += 150;
	p->sector = ENCODE_BCD(i % 75);
	int rem = i / 75;
	p->second = ENCODE_BCD(rem % 60);
	p->minute = ENCODE_BCD(rem / 60);
	return p;
}

int CdControl(u_char com, u_char * param, u_char * result)
{
	CdlLOC* cd = (CdlLOC*)param;

	CD_com = com;

	if (openFile == NULL)
	{
		return 0;
	}

		CdlLOC currentLoc;
		CdIntToPos(filePos, &currentLoc);
		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
		if (cd->sector != currentLoc.sector)
		{
			return 1;
		unsigned int filePos = ftell(openFile);
		CdlLOC currentLoc;
		CdIntToPos(filePos, &currentLoc);
		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
		currentSector = CdPosToInt(cd);
		if (cd->sector != currentLoc.sector)
		{
			return 1;
		}
		break;
	}
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}
	{
		CdlLOC* cd = (CdlLOC*)param;
		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
		break;
	}
	case CdlSetfilter:
	case CdlSetloc:
	{
		CdlLOC* cd = (CdlLOC*)param;
		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
		readMode = RM_DATA;
		break;
	}
	case CdlSetfilter:
	{
		CdlFILTER* cdf = (CdlFILTER*)param;
		//TODO Set channel
		break;
	}
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdControlF(u_char com, u_char * param)
{
	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
		//TODO Set channel
		break;
	}
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
		break;
	}
	case CdlGetlocP:
		readMode = RM_XA_AUDIO;
		break;
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

	{
		if (comQueue[i].processed == 1)
		{
			comQueue[i].mode = CdlReadS;
			comQueue[i].p = (unsigned char*)buf;
			comQueue[i].processed = 0;
			comQueue[i].count = sectors;
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		if (comQueue[i].processed == 1)
		{
			comQueue[i].mode = CdlReadS;///@TODO really mode
			comQueue[i].p = (unsigned char*)buf;
			comQueue[i].processed = 0;
			comQueue[i].count = sectors;
			break;
	{
		if (comQueue[i].processed == 0)
		{
            struct Sector sector;
			fread(&sector, sizeof(struct Sector), 1, openFile);

			memcpy(comQueue[i].p, &sector.data[0], 2048);
			comQueue[i].p += 2048;

			if (--comQueue[i].count == 0)
			{
			}
			else
			{
				assert(FALSE);
			}

			if (--comQueue[i].count == 0)
			{
				comQueue[i].processed = 1;
				break;
			}

			return 1;
		}
	}
	return 0;
}

int CdSetDebug(int level)
{
	int lastLevel = CD_Debug;
	CD_Debug = level;
	return lastLevel;
}

int CdSync(int mode, u_char * result)
{
	CdlLOC* loc = (CdlLOC*)result;
	switch (mode)
		{
		case CdlGetlocP:
			CdlLOC locP;
			unsigned int filePos = ftell(openFile) / sectorSize;
			CdIntToPos(filePos, &locP);
			result[2] = locP.minute;
			result[3] = locP.second;
			result[4] = locP.sector;

			break;
		}
				CdReadSync(CdlReadS, NULL);

				//Sector should be read now
				xaAudioData[0] = 0;
			}

			break;
		}
		return CdlComplete;
		break;
	}

	return 0;
}

int ParseCueSheet()
{
	char* binFileName = NULL;
	openFile = fopen(DISC_IMAGE_FILENAME, "rb");

	if (openFile == NULL)
	{
		eprinterr("Failed to open disc image file! %s\n", DISC_IMAGE_FILENAME);
		return 0;
	}

	fseek(openFile, 0, SEEK_END);
	unsigned int cueSheetFileLength = ftell(openFile);
	char* cueSheet = (char*)malloc(cueSheetFileLength);
	fseek(openFile, 0, SEEK_SET);
	fread(cueSheet, cueSheetFileLength, 1, openFile);

	//Null terminated
	char* string = &cueSheet[0];
	if (!strncmp(string, "FILE", 4))
	{
		//Read the binary name since it's a file
		string += 5;
		if (isspace(string[0]))
		{
			string++;
		}

		//Get file name length
		char* afterFileName = string;
		char fileNameLength = 0;
		//While
		while (!isspace(afterFileName[0]))
		{
			afterFileName++;
			fileNameLength++;
		}

		if (string[0] == '"')
		{
			string[fileNameLength - 1] = 0;
			string++;
		}

		binFileName = string;
		string = afterFileName;

		if (isspace(string[0]))
			string++;

		/* Get Type of BIN file */
		assert(!strncmp(string, "BINARY", 6));
		string += 6;

		while (isspace(string[0]))
			string++;

		/* Get Track of BIN file */
		assert(!strncmp(string, "TRACK", 5));
		string += 5;

		while (isspace(string[0]))
			string++;

		currentTrack = atoi(string);

		string += 2;

		while (isspace(string[0]))
		sectorSize = atoi(string);

		assert(sectorSize == 2352);
	}

	fclose(openFile);
	openFile = fopen(binFileName, "rb");
	free(cueSheet);

	return 1;
}
		numFrames = binFileLength / sectorSize;
		assert(numFrames != 0);
		fseek(openFile, 0, SEEK_SET);
		free(cueSheet);
	}

	return 1;
}

int CdInit(void)
{
	currentSector = 0;

	//Read the cue sheet and obtain properties from it.
	if (!ParseCueSheet())
	{
		eprinterr("Failed to read cue sheet!");
		return 0;
	}

	memset(&comQueue, 0, sizeof(comQueue));
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		comQueue[i].processed = 1;
	}

	return 1;
}

int CdLastCom(void)
{
	return CD_com;
}

<MSG> [Emu]: Update to v1.97.

Add XA Read Mode and Data Read Mode.

<DFF> @@ -9,6 +9,14 @@
 #include <stdlib.h>
 #include <ctype.h>
 
+enum ReadMode
+{
+	RM_DATA,
+	RM_XA_AUDIO
+};
+
+enum ReadMode readMode = RM_DATA;
+
 int CD_Debug = 0;
 
 FILE* openFile = NULL;
@@ -29,6 +37,7 @@ int comQueueCount = 0;
 int currentSector = 0;
 int sectorSize = 0;
 int currentTrack = 0;
+int numFrames = 0;
 int CD_com = 0;
 
 #pragma pack(push, 1)
@@ -56,6 +65,17 @@ struct Sector
 	unsigned char	edc[4];		/// Error-detection code (CRC32 of data area)
 	unsigned char	ecc[276];	/// Error-correction code (uses Reed-Solomon ECC algorithm)
 };
+
+struct AudioSector
+{
+	unsigned char	sync[12];	/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)
+	unsigned char	addr[3];	/// Sector address (see below for encoding details)
+	unsigned char	mode;		/// Mode (usually 2 for Mode 2 Form 1/2 sectors)
+	unsigned char	subHead[8];	/// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors)
+	unsigned char	data[2304];	/// Data (form 1)
+	unsigned char	edc[4];		/// Error-detection code (CRC32 of data area)
+	unsigned char	ecc[276];	/// Error-correction code (uses Reed-Solomon ECC algorithm)
+};
 #pragma pack(pop)
 
 CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
@@ -128,6 +148,7 @@ int CdControl(u_char com, u_char * param, u_char * result)
 		CdlLOC currentLoc;
 		CdIntToPos(filePos, &currentLoc);
 		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
+		currentSector = CdPosToInt(cd);
 		if (cd->sector != currentLoc.sector)
 		{
 			return 1;
@@ -152,6 +173,7 @@ int CdControlB(u_char com, u_char* param, u_char* result)
 	{
 		CdlLOC* cd = (CdlLOC*)param;
 		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
+		readMode = RM_DATA;
 		break;
 	}
 	case CdlSetfilter:
@@ -186,6 +208,9 @@ int CdControlF(u_char com, u_char * param)
 		//TODO Set channel
 		break;
 	}
+	case CdlGetlocP:
+		readMode = RM_XA_AUDIO;
+		break;
 	default:
 		eprinterr("Unhandled command 0x%02X!\n", com);
 		break;
@@ -205,7 +230,7 @@ int CdRead(int sectors, u_long* buf, int mode)
 	{
 		if (comQueue[i].processed == 1)
 		{
-			comQueue[i].mode = CdlReadS;
+			comQueue[i].mode = CdlReadS;///@TODO really mode
 			comQueue[i].p = (unsigned char*)buf;
 			comQueue[i].processed = 0;
 			comQueue[i].count = sectors;
@@ -221,11 +246,26 @@ int CdReadSync(int mode, u_char* result)
 	{
 		if (comQueue[i].processed == 0)
 		{
-            struct Sector sector;
-			fread(&sector, sizeof(struct Sector), 1, openFile);
+			if (readMode == RM_DATA)
+			{
+				struct Sector sector;
+				fread(&sector, sizeof(struct Sector), 1, openFile);
 
-			memcpy(comQueue[i].p, &sector.data[0], 2048);
-			comQueue[i].p += 2048;
+				memcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));
+				comQueue[i].p += sizeof(sector.data);
+			}
+			else if (readMode == RM_XA_AUDIO)
+			{
+				struct AudioSector sector;
+				fread(&sector, sizeof(struct AudioSector), 1, openFile);
+
+				memcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));
+				comQueue[i].p += sizeof(sector.data);
+			}
+			else
+			{
+				assert(FALSE);
+			}
 
 			if (--comQueue[i].count == 0)
 			{
@@ -261,11 +301,26 @@ int CdSync(int mode, u_char * result)
 		{
 		case CdlGetlocP:
 			CdlLOC locP;
-			unsigned int filePos = ftell(openFile) / sectorSize;
-			CdIntToPos(filePos, &locP);
+			CdIntToPos(currentSector+=20, &locP);
+			result[0] = currentTrack;
+			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);
+			
+			//Dirty, for now read the audio data
+			if (readMode == RM_XA_AUDIO)
+			{
+				char xaAudioData[2304];
+				CdRead(1, (unsigned long*)&xaAudioData[0], CdlReadS);
+				CdReadSync(CdlReadS, NULL);
+
+				//Sector should be read now
+				xaAudioData[0] = 0;
+			}
 
 			break;
 		}
@@ -356,11 +411,16 @@ int ParseCueSheet()
 		sectorSize = atoi(string);
 
 		assert(sectorSize == 2352);
-	}
 
-	fclose(openFile);
-	openFile = fopen(binFileName, "rb");
-	free(cueSheet);
+		fclose(openFile);
+		openFile = fopen(binFileName, "rb");
+		fseek(openFile, 0, SEEK_END);
+		unsigned int binFileLength = ftell(openFile);
+		numFrames = binFileLength / sectorSize;
+		assert(numFrames != 0);
+		fseek(openFile, 0, SEEK_SET);
+		free(cueSheet);
+	}
 
 	return 1;
 }

{'commit': 'diff --git a/EMULATOR/EMULATOR_VERSION.H b/EMULATOR/EMULATOR_VERSION.H\nindex 8290099a..3e2f7bc9 100644\n--- a/EMULATOR/EMULATOR_VERSION.H\n+++ b/EMULATOR/EMULATOR_VERSION.H\n@@ -6,7 +6,7 @@\n \n /* Emulator version */\n #define EMULATOR_MAJOR_VERSION (1)\n-#define EMULATOR_MINOR_VERSION (96)\n+#define EMULATOR_MINOR_VERSION (97)\n \n /* Compile date and time */\n #define EMULATOR_COMPILE_DATE (__DATE__)\ndiff --git a/EMULATOR/LIBCD.C b/EMULATOR/LIBCD.C\nindex ceb73f3c..adcb3117 100644\n--- a/EMULATOR/LIBCD.C\n+++ b/EMULATOR/LIBCD.C\n@@ -9,6 +9,14 @@\n #include <stdlib.h>\n #include <ctype.h>\n \n+enum ReadMode\n+{\n+\tRM_DATA,\n+\tRM_XA_AUDIO\n+};\n+\n+enum ReadMode readMode = RM_DATA;\n+\n int CD_Debug = 0;\n \n FILE* openFile = NULL;\n@@ -29,6 +37,7 @@ int comQueueCount = 0;\n int currentSector = 0;\n int sectorSize = 0;\n int currentTrack = 0;\n+int numFrames = 0;\n int CD_com = 0;\n \n #pragma pack(push, 1)\n@@ -56,6 +65,17 @@ struct Sector\n \tunsigned char\tedc[4];\t\t/// Error-detection code (CRC32 of data area)\n \tunsigned char\tecc[276];\t/// Error-correction code (uses Reed-Solomon ECC algorithm)\n };\n+\n+struct AudioSector\n+{\n+\tunsigned char\tsync[12];\t/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)\n+\tunsigned char\taddr[3];\t/// Sector address (see below for encoding details)\n+\tunsigned char\tmode;\t\t/// Mode (usually 2 for Mode 2 Form 1/2 sectors)\n+\tunsigned char\tsubHead[8];\t/// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors)\n+\tunsigned char\tdata[2304];\t/// Data (form 1)\n+\tunsigned char\tedc[4];\t\t/// Error-detection code (CRC32 of data area)\n+\tunsigned char\tecc[276];\t/// Error-correction code (uses Reed-Solomon ECC algorithm)\n+};\n #pragma pack(pop)\n \n CdlFILE* CdSearchFile(CdlFILE* fp, char* name)\n@@ -128,6 +148,7 @@ int CdControl(u_char com, u_char * param, u_char * result)\n \t\tCdlLOC currentLoc;\n \t\tCdIntToPos(filePos, &currentLoc);\n \t\tfseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);\n+\t\tcurrentSector = CdPosToInt(cd);\n \t\tif (cd->sector != currentLoc.sector)\n \t\t{\n \t\t\treturn 1;\n@@ -152,6 +173,7 @@ int CdControlB(u_char com, u_char* param, u_char* result)\n \t{\n \t\tCdlLOC* cd = (CdlLOC*)param;\n \t\tfseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);\n+\t\treadMode = RM_DATA;\n \t\tbreak;\n \t}\n \tcase CdlSetfilter:\n@@ -186,6 +208,9 @@ int CdControlF(u_char com, u_char * param)\n \t\t//TODO Set channel\n \t\tbreak;\n \t}\n+\tcase CdlGetlocP:\n+\t\treadMode = RM_XA_AUDIO;\n+\t\tbreak;\n \tdefault:\n \t\teprinterr("Unhandled command 0x%02X!\\n", com);\n \t\tbreak;\n@@ -205,7 +230,7 @@ int CdRead(int sectors, u_long* buf, int mode)\n \t{\n \t\tif (comQueue[i].processed == 1)\n \t\t{\n-\t\t\tcomQueue[i].mode = CdlReadS;\n+\t\t\tcomQueue[i].mode = CdlReadS;///@TODO really mode\n \t\t\tcomQueue[i].p = (unsigned char*)buf;\n \t\t\tcomQueue[i].processed = 0;\n \t\t\tcomQueue[i].count = sectors;\n@@ -221,11 +246,26 @@ int CdReadSync(int mode, u_char* result)\n \t{\n \t\tif (comQueue[i].processed == 0)\n \t\t{\n-            struct Sector sector;\n-\t\t\tfread(&sector, sizeof(struct Sector), 1, openFile);\n+\t\t\tif (readMode == RM_DATA)\n+\t\t\t{\n+\t\t\t\tstruct Sector sector;\n+\t\t\t\tfread(&sector, sizeof(struct Sector), 1, openFile);\n \n-\t\t\tmemcpy(comQueue[i].p, &sector.data[0], 2048);\n-\t\t\tcomQueue[i].p += 2048;\n+\t\t\t\tmemcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));\n+\t\t\t\tcomQueue[i].p += sizeof(sector.data);\n+\t\t\t}\n+\t\t\telse if (readMode == RM_XA_AUDIO)\n+\t\t\t{\n+\t\t\t\tstruct AudioSector sector;\n+\t\t\t\tfread(&sector, sizeof(struct AudioSector), 1, openFile);\n+\n+\t\t\t\tmemcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));\n+\t\t\t\tcomQueue[i].p += sizeof(sector.data);\n+\t\t\t}\n+\t\t\telse\n+\t\t\t{\n+\t\t\t\tassert(FALSE);\n+\t\t\t}\n \n \t\t\tif (--comQueue[i].count == 0)\n \t\t\t{\n@@ -261,11 +301,26 @@ int CdSync(int mode, u_char * result)\n \t\t{\n \t\tcase CdlGetlocP:\n \t\t\tCdlLOC locP;\n-\t\t\tunsigned int filePos = ftell(openFile) / sectorSize;\n-\t\t\tCdIntToPos(filePos, &locP);\n+\t\t\tCdIntToPos(currentSector+=20, &locP);\n+\t\t\tresult[0] = currentTrack;\n+\t\t\tresult[1] = 1;//index, usually 1\n \t\t\tresult[2] = locP.minute;\n \t\t\tresult[3] = locP.second;\n \t\t\tresult[4] = locP.sector;\n+\t\t\tresult[5] = locP.minute + ENCODE_BCD(numFrames);\n+\t\t\tresult[6] = locP.second + ENCODE_BCD(numFrames);\n+\t\t\tresult[7] = locP.sector + ENCODE_BCD(numFrames);\n+\t\t\t\n+\t\t\t//Dirty, for now read the audio data\n+\t\t\tif (readMode == RM_XA_AUDIO)\n+\t\t\t{\n+\t\t\t\tchar xaAudioData[2304];\n+\t\t\t\tCdRead(1, (unsigned long*)&xaAudioData[0], CdlReadS);\n+\t\t\t\tCdReadSync(CdlReadS, NULL);\n+\n+\t\t\t\t//Sector should be read now\n+\t\t\t\txaAudioData[0] = 0;\n+\t\t\t}\n \n \t\t\tbreak;\n \t\t}\n@@ -356,11 +411,16 @@ int ParseCueSheet()\n \t\tsectorSize = atoi(string);\n \n \t\tassert(sectorSize == 2352);\n-\t}\n \n-\tfclose(openFile);\n-\topenFile = fopen(binFileName, "rb");\n-\tfree(cueSheet);\n+\t\tfclose(openFile);\n+\t\topenFile = fopen(binFileName, "rb");\n+\t\tfseek(openFile, 0, SEEK_END);\n+\t\tunsigned int binFileLength = ftell(openFile);\n+\t\tnumFrames = binFileLength / sectorSize;\n+\t\tassert(numFrames != 0);\n+\t\tfseek(openFile, 0, SEEK_SET);\n+\t\tfree(cueSheet);\n+\t}\n \n \treturn 1;\n }\n', 'commit_subject': '[Emu]: Update to v1.97.', 'repo_name': 'TOMB5/TOMB5', 'committer': {'name': 'Gh0stBlade', 'email': '19ffcc48b5297ad4998e7ea4f40eaa34eefb03dd@users.noreply.github.com', 'time_sec': '1585756705', 'tz_offset': '60', 'date': {'seconds': '1585756705'}}, 'commit_tree': 'f3d9c0622b043438d670c7bba501edd8aaa663dd', 'commit_message': '[Emu]: Update to v1.97.\n\nAdd XA Read Mode and Data Read Mode.\n', 'language_name': 'C++', 'license': 'mit', 'hunks': '@@ -9,6 +9,14 @@\n #include <stdlib.h>\n #include <ctype.h>\n \n+enum ReadMode\n+{\n+\tRM_DATA,\n+\tRM_XA_AUDIO\n+};\n+\n+enum ReadMode readMode = RM_DATA;\n+\n int CD_Debug = 0;\n \n FILE* openFile = NULL;\n@@ -29,6 +37,7 @@ int comQueueCount = 0;\n int currentSector = 0;\n int sectorSize = 0;\n int currentTrack = 0;\n+int numFrames = 0;\n int CD_com = 0;\n \n #pragma pack(push, 1)\n@@ -56,6 +65,17 @@ struct Sector\n \tunsigned char\tedc[4];\t\t/// Error-detection code (CRC32 of data area)\n \tunsigned char\tecc[276];\t/// Error-correction code (uses Reed-Solomon ECC algorithm)\n };\n+\n+struct AudioSector\n+{\n+\tunsigned char\tsync[12];\t/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)\n+\tunsigned char\taddr[3];\t/// Sector address (see below for encoding details)\n+\tunsigned char\tmode;\t\t/// Mode (usually 2 for Mode 2 Form 1/2 sectors)\n+\tunsigned char\tsubHead[8];\t/// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors)\n+\tunsigned char\tdata[2304];\t/// Data (form 1)\n+\tunsigned char\tedc[4];\t\t/// Error-detection code (CRC32 of data area)\n+\tunsigned char\tecc[276];\t/// Error-correction code (uses Reed-Solomon ECC algorithm)\n+};\n #pragma pack(pop)\n \n CdlFILE* CdSearchFile(CdlFILE* fp, char* name)\n@@ -128,6 +148,7 @@ int CdControl(u_char com, u_char * param, u_char * result)\n \t\tCdlLOC currentLoc;\n \t\tCdIntToPos(filePos, &currentLoc);\n \t\tfseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);\n+\t\tcurrentSector = CdPosToInt(cd);\n \t\tif (cd->sector != currentLoc.sector)\n \t\t{\n \t\t\treturn 1;\n@@ -152,6 +173,7 @@ int CdControlB(u_char com, u_char* param, u_char* result)\n \t{\n \t\tCdlLOC* cd = (CdlLOC*)param;\n \t\tfseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);\n+\t\treadMode = RM_DATA;\n \t\tbreak;\n \t}\n \tcase CdlSetfilter:\n@@ -186,6 +208,9 @@ int CdControlF(u_char com, u_char * param)\n \t\t//TODO Set channel\n \t\tbreak;\n \t}\n+\tcase CdlGetlocP:\n+\t\treadMode = RM_XA_AUDIO;\n+\t\tbreak;\n \tdefault:\n \t\teprinterr("Unhandled command 0x%02X!\\n", com);\n \t\tbreak;\n@@ -205,7 +230,7 @@ int CdRead(int sectors, u_long* buf, int mode)\n \t{\n \t\tif (comQueue[i].processed == 1)\n \t\t{\n-\t\t\tcomQueue[i].mode = CdlReadS;\n+\t\t\tcomQueue[i].mode = CdlReadS;///@TODO really mode\n \t\t\tcomQueue[i].p = (unsigned char*)buf;\n \t\t\tcomQueue[i].processed = 0;\n \t\t\tcomQueue[i].count = sectors;\n@@ -221,11 +246,26 @@ int CdReadSync(int mode, u_char* result)\n \t{\n \t\tif (comQueue[i].processed == 0)\n \t\t{\n-            struct Sector sector;\n-\t\t\tfread(&sector, sizeof(struct Sector), 1, openFile);\n+\t\t\tif (readMode == RM_DATA)\n+\t\t\t{\n+\t\t\t\tstruct Sector sector;\n+\t\t\t\tfread(&sector, sizeof(struct Sector), 1, openFile);\n \n-\t\t\tmemcpy(comQueue[i].p, &sector.data[0], 2048);\n-\t\t\tcomQueue[i].p += 2048;\n+\t\t\t\tmemcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));\n+\t\t\t\tcomQueue[i].p += sizeof(sector.data);\n+\t\t\t}\n+\t\t\telse if (readMode == RM_XA_AUDIO)\n+\t\t\t{\n+\t\t\t\tstruct AudioSector sector;\n+\t\t\t\tfread(&sector, sizeof(struct AudioSector), 1, openFile);\n+\n+\t\t\t\tmemcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));\n+\t\t\t\tcomQueue[i].p += sizeof(sector.data);\n+\t\t\t}\n+\t\t\telse\n+\t\t\t{\n+\t\t\t\tassert(FALSE);\n+\t\t\t}\n \n \t\t\tif (--comQueue[i].count == 0)\n \t\t\t{\n@@ -261,11 +301,26 @@ int CdSync(int mode, u_char * result)\n \t\t{\n \t\tcase CdlGetlocP:\n \t\t\tCdlLOC locP;\n-\t\t\tunsigned int filePos = ftell(openFile) / sectorSize;\n-\t\t\tCdIntToPos(filePos, &locP);\n+\t\t\tCdIntToPos(currentSector+=20, &locP);\n+\t\t\tresult[0] = currentTrack;\n+\t\t\tresult[1] = 1;//index, usually 1\n \t\t\tresult[2] = locP.minute;\n \t\t\tresult[3] = locP.second;\n \t\t\tresult[4] = locP.sector;\n+\t\t\tresult[5] = locP.minute + ENCODE_BCD(numFrames);\n+\t\t\tresult[6] = locP.second + ENCODE_BCD(numFrames);\n+\t\t\tresult[7] = locP.sector + ENCODE_BCD(numFrames);\n+\t\t\t\n+\t\t\t//Dirty, for now read the audio data\n+\t\t\tif (readMode == RM_XA_AUDIO)\n+\t\t\t{\n+\t\t\t\tchar xaAudioData[2304];\n+\t\t\t\tCdRead(1, (unsigned long*)&xaAudioData[0], CdlReadS);\n+\t\t\t\tCdReadSync(CdlReadS, NULL);\n+\n+\t\t\t\t//Sector should be read now\n+\t\t\t\txaAudioData[0] = 0;\n+\t\t\t}\n \n \t\t\tbreak;\n \t\t}\n@@ -356,11 +411,16 @@ int ParseCueSheet()\n \t\tsectorSize = atoi(string);\n \n \t\tassert(sectorSize == 2352);\n-\t}\n \n-\tfclose(openFile);\n-\topenFile = fopen(binFileName, "rb");\n-\tfree(cueSheet);\n+\t\tfclose(openFile);\n+\t\topenFile = fopen(binFileName, "rb");\n+\t\tfseek(openFile, 0, SEEK_END);\n+\t\tunsigned int binFileLength = ftell(openFile);\n+\t\tnumFrames = binFileLength / sectorSize;\n+\t\tassert(numFrames != 0);\n+\t\tfseek(openFile, 0, SEEK_SET);\n+\t\tfree(cueSheet);\n+\t}\n \n \treturn 1;\n }\n', 'addition_count': 71, 'deletion_count': 11, 'src_file': 'a/EMULATOR/LIBCD.C', 'tgt_file': 'b/EMULATOR/LIBCD.C', 'file_extension': '.C', 'before_file': '#include "LIBCD.H"\n\n#include "EMULATOR_SETUP.H"\n#include "EMULATOR.H"\n\n#include <assert.h>\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <ctype.h>\n\nint CD_Debug = 0;\n\nFILE* openFile = NULL;\n\nenum ReadMode readMode = RM_DATA;\n\nint CD_Debug = 0;\n\nFILE* openFile = NULL;\n\ntypedef struct commandQueue\n{\n\tunsigned int mode;\n\tunsigned char* p;\n\tunsigned int processed;\n\tunsigned int count;\n}commandQueue_s, *commandQueue_p;\nint currentSector = 0;\nint sectorSize = 0;\nint currentTrack = 0;\nint CD_com = 0;\n\n#pragma pack(push, 1)\nint sectorSize = 0;\nint currentTrack = 0;\nint numFrames = 0;\nint CD_com = 0;\n\n#pragma pack(push, 1)\nstruct TOC\n{\n\tunsigned char tocEntryLength;\n\tunsigned char extEntryLength;\n\tunsigned int sectorPosition[2];\n\tunsigned int fileSize[2];\n\tunsigned char date[7];\n\tunsigned char flags;\n\tunsigned char fileUnitSize;\n\tunsigned char interleaveGapSize;\n\tunsigned short volSeqNum[2];\n\tunsigned char nameLength;\n};\n\nstruct Sector\n\tunsigned char\tedc[4];\t\t/// Error-detection code (CRC32 of data area)\n\tunsigned char\tecc[276];\t/// Error-correction code (uses Reed-Solomon ECC algorithm)\n};\n#pragma pack(pop)\n\nCdlFILE* CdSearchFile(CdlFILE* fp, char* name)\n#pragma pack(pop)\n\nCdlFILE* CdSearchFile(CdlFILE* fp, char* name)\n{\n\tmemset(fp, 0, sizeof(CdlFILE));\n\n\tif (name[0] == \'\\\\\')\n\t{\n\t\tname++;\n\t}\n\n\tif (openFile != NULL)\n\t{\n\t\tfseek(openFile, 22 * sectorSize, SEEK_SET);\n\n\t\tint tocLocalOffset = 0;\n        struct Sector sector;\n\t\tfread(&sector, sizeof(struct Sector), 1, openFile);\n        struct TOC* toc = (struct TOC*)&sector.data[0];\n\t\twhile (toc->tocEntryLength != 0)\n\t\t{\n\t\t\tif (strcmp((char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], name) == 0)\n\t\t\t{\n\t\t\t\tmemcpy(&fp->name[0], (char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], strlen(name));\n\t\t\t\tfp->size = toc->fileSize[0];\n\t\t\t\tfseek(openFile, toc->sectorPosition[0] * sectorSize, SEEK_SET);\n\t\t\t\tfread(&sector, sizeof(struct Sector), 1, openFile);\n\t\t\t\tfp->pos.minute = sector.addr[0];\n\t\t\t\tfp->pos.second = sector.addr[1];\n\t\t\t\tfp->pos.sector = sector.addr[2];\n\n\n#if _DEBUG\n\t\t\t\teprintf("Found %s\\n", name);\n#endif\n\t\t\t\treturn fp;\n\t\t\t}\n\t\t\ttocLocalOffset += toc->tocEntryLength;\n\t\t\ttoc = (struct TOC*)&sector.data[tocLocalOffset];\n\t\t}\n\t}\n\n\treturn NULL;\n}\n\nCdlLOC* CdIntToPos(int i, CdlLOC* p)\n{\n\ti += 150;\n\tp->sector = ENCODE_BCD(i % 75);\n\tint rem = i / 75;\n\tp->second = ENCODE_BCD(rem % 60);\n\tp->minute = ENCODE_BCD(rem / 60);\n\treturn p;\n}\n\nint CdControl(u_char com, u_char * param, u_char * result)\n{\n\tCdlLOC* cd = (CdlLOC*)param;\n\n\tCD_com = com;\n\n\tif (openFile == NULL)\n\t{\n\t\treturn 0;\n\t}\n\n\t\tCdlLOC currentLoc;\n\t\tCdIntToPos(filePos, &currentLoc);\n\t\tfseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);\n\t\tif (cd->sector != currentLoc.sector)\n\t\t{\n\t\t\treturn 1;\n\t\tunsigned int filePos = ftell(openFile);\n\t\tCdlLOC currentLoc;\n\t\tCdIntToPos(filePos, &currentLoc);\n\t\tfseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);\n\t\tcurrentSector = CdPosToInt(cd);\n\t\tif (cd->sector != currentLoc.sector)\n\t\t{\n\t\t\treturn 1;\n\t\t}\n\t\tbreak;\n\t}\n\tdefault:\n\t\teprinterr("Unhandled command 0x%02X!\\n", com);\n\t\tbreak;\n\t}\n\n\treturn 0;\n}\n\t{\n\t\tCdlLOC* cd = (CdlLOC*)param;\n\t\tfseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);\n\t\tbreak;\n\t}\n\tcase CdlSetfilter:\n\tcase CdlSetloc:\n\t{\n\t\tCdlLOC* cd = (CdlLOC*)param;\n\t\tfseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);\n\t\treadMode = RM_DATA;\n\t\tbreak;\n\t}\n\tcase CdlSetfilter:\n\t{\n\t\tCdlFILTER* cdf = (CdlFILTER*)param;\n\t\t//TODO Set channel\n\t\tbreak;\n\t}\n\tdefault:\n\t\teprinterr("Unhandled command 0x%02X!\\n", com);\n\t\tbreak;\n\t}\n\n\treturn 0;\n}\n\nint CdControlF(u_char com, u_char * param)\n{\n\tCD_com = com;\n\n\tswitch (com)\n\t{\n\tcase CdlSetloc:\n\t\t//TODO Set channel\n\t\tbreak;\n\t}\n\tdefault:\n\t\teprinterr("Unhandled command 0x%02X!\\n", com);\n\t\tbreak;\n\t\tbreak;\n\t}\n\tcase CdlGetlocP:\n\t\treadMode = RM_XA_AUDIO;\n\t\tbreak;\n\tdefault:\n\t\teprinterr("Unhandled command 0x%02X!\\n", com);\n\t\tbreak;\n\t}\n\n\treturn 0;\n}\n\n\t{\n\t\tif (comQueue[i].processed == 1)\n\t\t{\n\t\t\tcomQueue[i].mode = CdlReadS;\n\t\t\tcomQueue[i].p = (unsigned char*)buf;\n\t\t\tcomQueue[i].processed = 0;\n\t\t\tcomQueue[i].count = sectors;\n\tfor (int i = 0; i < COMMAND_QUEUE_SIZE; i++)\n\t{\n\t\tif (comQueue[i].processed == 1)\n\t\t{\n\t\t\tcomQueue[i].mode = CdlReadS;///@TODO really mode\n\t\t\tcomQueue[i].p = (unsigned char*)buf;\n\t\t\tcomQueue[i].processed = 0;\n\t\t\tcomQueue[i].count = sectors;\n\t\t\tbreak;\n\t{\n\t\tif (comQueue[i].processed == 0)\n\t\t{\n            struct Sector sector;\n\t\t\tfread(&sector, sizeof(struct Sector), 1, openFile);\n\n\t\t\tmemcpy(comQueue[i].p, &sector.data[0], 2048);\n\t\t\tcomQueue[i].p += 2048;\n\n\t\t\tif (--comQueue[i].count == 0)\n\t\t\t{\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tassert(FALSE);\n\t\t\t}\n\n\t\t\tif (--comQueue[i].count == 0)\n\t\t\t{\n\t\t\t\tcomQueue[i].processed = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn 1;\n\t\t}\n\t}\n\treturn 0;\n}\n\nint CdSetDebug(int level)\n{\n\tint lastLevel = CD_Debug;\n\tCD_Debug = level;\n\treturn lastLevel;\n}\n\nint CdSync(int mode, u_char * result)\n{\n\tCdlLOC* loc = (CdlLOC*)result;\n\tswitch (mode)\n\t\t{\n\t\tcase CdlGetlocP:\n\t\t\tCdlLOC locP;\n\t\t\tunsigned int filePos = ftell(openFile) / sectorSize;\n\t\t\tCdIntToPos(filePos, &locP);\n\t\t\tresult[2] = locP.minute;\n\t\t\tresult[3] = locP.second;\n\t\t\tresult[4] = locP.sector;\n\n\t\t\tbreak;\n\t\t}\n\t\t\t\tCdReadSync(CdlReadS, NULL);\n\n\t\t\t\t//Sector should be read now\n\t\t\t\txaAudioData[0] = 0;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\t\treturn CdlComplete;\n\t\tbreak;\n\t}\n\n\treturn 0;\n}\n\nint ParseCueSheet()\n{\n\tchar* binFileName = NULL;\n\topenFile = fopen(DISC_IMAGE_FILENAME, "rb");\n\n\tif (openFile == NULL)\n\t{\n\t\teprinterr("Failed to open disc image file! %s\\n", DISC_IMAGE_FILENAME);\n\t\treturn 0;\n\t}\n\n\tfseek(openFile, 0, SEEK_END);\n\tunsigned int cueSheetFileLength = ftell(openFile);\n\tchar* cueSheet = (char*)malloc(cueSheetFileLength);\n\tfseek(openFile, 0, SEEK_SET);\n\tfread(cueSheet, cueSheetFileLength, 1, openFile);\n\n\t//Null terminated\n\tchar* string = &cueSheet[0];\n\tif (!strncmp(string, "FILE", 4))\n\t{\n\t\t//Read the binary name since it\'s a file\n\t\tstring += 5;\n\t\tif (isspace(string[0]))\n\t\t{\n\t\t\tstring++;\n\t\t}\n\n\t\t//Get file name length\n\t\tchar* afterFileName = string;\n\t\tchar fileNameLength = 0;\n\t\t//While\n\t\twhile (!isspace(afterFileName[0]))\n\t\t{\n\t\t\tafterFileName++;\n\t\t\tfileNameLength++;\n\t\t}\n\n\t\tif (string[0] == \'"\')\n\t\t{\n\t\t\tstring[fileNameLength - 1] = 0;\n\t\t\tstring++;\n\t\t}\n\n\t\tbinFileName = string;\n\t\tstring = afterFileName;\n\n\t\tif (isspace(string[0]))\n\t\t\tstring++;\n\n\t\t/* Get Type of BIN file */\n\t\tassert(!strncmp(string, "BINARY", 6));\n\t\tstring += 6;\n\n\t\twhile (isspace(string[0]))\n\t\t\tstring++;\n\n\t\t/* Get Track of BIN file */\n\t\tassert(!strncmp(string, "TRACK", 5));\n\t\tstring += 5;\n\n\t\twhile (isspace(string[0]))\n\t\t\tstring++;\n\n\t\tcurrentTrack = atoi(string);\n\n\t\tstring += 2;\n\n\t\twhile (isspace(string[0]))\n\t\tsectorSize = atoi(string);\n\n\t\tassert(sectorSize == 2352);\n\t}\n\n\tfclose(openFile);\n\topenFile = fopen(binFileName, "rb");\n\tfree(cueSheet);\n\n\treturn 1;\n}\n\t\tnumFrames = binFileLength / sectorSize;\n\t\tassert(numFrames != 0);\n\t\tfseek(openFile, 0, SEEK_SET);\n\t\tfree(cueSheet);\n\t}\n\n\treturn 1;\n}\n\nint CdInit(void)\n{\n\tcurrentSector = 0;\n\n\t//Read the cue sheet and obtain properties from it.\n\tif (!ParseCueSheet())\n\t{\n\t\teprinterr("Failed to read cue sheet!");\n\t\treturn 0;\n\t}\n\n\tmemset(&comQueue, 0, sizeof(comQueue));\n\tfor (int i = 0; i < COMMAND_QUEUE_SIZE; i++)\n\t{\n\t\tcomQueue[i].processed = 1;\n\t}\n\n\treturn 1;\n}\n\nint CdLastCom(void)\n{\n\treturn CD_com;\n}\n', 'message': '[Emu]: Update to v1.97.\n\nAdd XA Read Mode and Data Read Mode.\n', 'author_name': 'Gh0stBlade', 'lang': 'C'}