Take out CDUtility namespace and some other cleanups

This commit is contained in:
twinaphex 2015-07-28 22:35:18 +02:00
parent 1114032411
commit 5681b1a43a
20 changed files with 832 additions and 1111 deletions

View File

@ -972,7 +972,7 @@ static bool TestMagic(const char *name, MDFNFILE *fp)
static bool TestMagicCD(std::vector<CDIF *> *CDInterfaces)
{
uint8_t buf[2048];
CDUtility::TOC toc;
TOC toc;
int dt;
(*CDInterfaces)[0]->ReadTOC(&toc);
@ -1012,7 +1012,7 @@ static const char *CalcDiscSCEx_BySYSTEMCNF(CDIF *c, unsigned *rr)
{
const char *ret = NULL;
Stream *fp = NULL;
CDUtility::TOC toc;
TOC toc;
//(*CDInterfaces)[disc]->ReadTOC(&toc);
@ -2329,7 +2329,7 @@ void retro_init(void)
log_cb = NULL;
#ifdef NEED_CD
CDUtility::CDUtility_Init();
CDUtility_Init();
#endif
eject_state = false;
@ -2353,10 +2353,10 @@ void retro_init(void)
log_cb(RETRO_LOG_WARN, "System directory is not defined. Fallback on using same dir as ROM for system directory later ...\n");
failed_init = true;
}
if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &dir) && dir)
{
// If save directory is defined use it, otherwise use system directory
// If save directory is defined use it, otherwise use system directory
retro_save_directory = *dir ? dir : retro_base_directory;
// Make sure that we don't have any lingering slashes, etc, as they break Windows.
size_t last = retro_save_directory.find_last_not_of("/\\");
@ -2370,7 +2370,7 @@ void retro_init(void)
/* TODO: Add proper fallback */
if (log_cb)
log_cb(RETRO_LOG_WARN, "Save directory is not defined. Fallback on using SYSTEM directory ...\n");
retro_save_directory = retro_base_directory;
retro_save_directory = retro_base_directory;
}
#if defined(WANT_16BPP) && defined(FRONTEND_SUPPORTS_RGB565)
@ -2734,7 +2734,7 @@ MDFNGI *MDFNI_LoadCD(const char *force_module, const char *devicename)
// Print out a track list for all discs. //
for(unsigned i = 0; i < CDInterfaces.size(); i++)
{
CDUtility::TOC toc;
TOC toc;
CDInterfaces[i]->ReadTOC(&toc);

View File

@ -45,16 +45,16 @@ MemoryStream::MemoryStream(Stream *stream) : data_buffer(NULL), data_buffer_size
delete stream;
}
MemoryStream::MemoryStream(const MemoryStream &zs)
MemoryStream::MemoryStream(const MemoryStream *zs)
{
data_buffer_size = zs.data_buffer_size;
data_buffer_alloced = zs.data_buffer_alloced;
data_buffer_size = zs->data_buffer_size;
data_buffer_alloced = zs->data_buffer_alloced;
if(!(data_buffer = (uint8*)malloc((size_t)data_buffer_alloced)))
throw MDFN_Error(ErrnoHolder(errno));
memcpy(data_buffer, zs.data_buffer, (size_t)data_buffer_size);
memcpy(data_buffer, zs->data_buffer, (size_t)data_buffer_size);
position = zs.position;
position = zs->position;
}
MemoryStream::~MemoryStream()

View File

@ -32,8 +32,8 @@ class MemoryStream : public Stream
// Will only work if stream->tell() == 0, or if "stream" is seekable.
// stream will be deleted even if this constructor throws.
MemoryStream(const MemoryStream &zs);
MemoryStream & operator=(const MemoryStream &zs);
MemoryStream(const MemoryStream *zs);
MemoryStream & operator=(const MemoryStream *zs);
virtual ~MemoryStream();

View File

@ -29,8 +29,6 @@
#include "CDAccess_Image.h"
#include "CDAccess_CCD.h"
using namespace CDUtility;
CDAccess::CDAccess()
{

View File

@ -14,7 +14,7 @@ class CDAccess
virtual void Read_Raw_Sector(uint8 *buf, int32 lba) = 0;
virtual void Read_TOC(CDUtility::TOC *toc) = 0;
virtual void Read_TOC(TOC *toc) = 0;
virtual void Eject(bool eject_status) = 0; // Eject a disc if it's physical, otherwise NOP. Returns true on success(or NOP), false on error

View File

@ -25,358 +25,252 @@
#include <limits.h>
#include <map>
using namespace CDUtility;
typedef std::map<std::string, std::string> CCD_Section;
template<typename T>
static T CCD_ReadInt(CCD_Section &s, const std::string &propname, const bool have_defval = false, const int defval = 0)
{
CCD_Section::iterator zit = s.find(propname);
CCD_Section::iterator zit = s.find(propname);
if(zit == s.end())
{
if(have_defval)
return defval;
else
throw MDFN_Error(0, _("Missing property: %s"), propname.c_str());
}
if(zit == s.end())
{
if(have_defval)
return defval;
throw MDFN_Error(0, _("Missing property: %s"), propname.c_str());
}
const std::string &v = zit->second;
int scan_base = 10;
size_t scan_offset = 0;
long ret = 0;
if(v.length() >= 3 && v[0] == '0' && v[1] == 'x')
{
scan_base = 16;
scan_offset = 2;
}
const std::string &v = zit->second;
int scan_base = 10;
size_t scan_offset = 0;
long ret = 0;
const char *vp = v.c_str() + scan_offset;
char *ep = NULL;
if(v.length() >= 3 && v[0] == '0' && v[1] == 'x')
{
scan_base = 16;
scan_offset = 2;
}
if(std::numeric_limits<T>::is_signed)
ret = strtol(vp, &ep, scan_base);
else
ret = strtoul(vp, &ep, scan_base);
const char *vp = v.c_str() + scan_offset;
char *ep = NULL;
if(!vp[0] || ep[0])
{
throw MDFN_Error(0, _("Property %s: Malformed integer: %s"), propname.c_str(), v.c_str());
}
if(std::numeric_limits<T>::is_signed)
ret = strtol(vp, &ep, scan_base);
else
ret = strtoul(vp, &ep, scan_base);
//if(ret < minv || ret > maxv)
//{
// throw MDFN_Error(0, _("Property %s: Integer %ld out of range(accepted: %d through %d)."), propname.c_str(), ret, minv, maxv);
//}
if(!vp[0] || ep[0])
throw MDFN_Error(0, _("Property %s: Malformed integer: %s"), propname.c_str(), v.c_str());
return ret;
//if(ret < minv || ret > maxv)
//{
// throw MDFN_Error(0, _("Property %s: Integer %ld out of range(accepted: %d through %d)."), propname.c_str(), ret, minv, maxv);
//}
return ret;
}
CDAccess_CCD::CDAccess_CCD(const char *path, bool image_memcache) : img_stream(NULL), sub_stream(NULL), img_numsectors(0)
{
try
{
Load(path, image_memcache);
}
catch(...)
{
Cleanup();
throw;
}
try
{
Load(path, image_memcache);
}
catch(...)
{
Cleanup();
throw;
}
}
void CDAccess_CCD::Load(const char *path, bool image_memcache)
{
FileStream cf(path, FileStream::MODE_READ);
std::map<std::string, CCD_Section> Sections;
std::string linebuf;
std::string cur_section_name;
std::string dir_path, file_base, file_ext;
char img_extsd[4] = { 'i', 'm', 'g', 0 };
char sub_extsd[4] = { 's', 'u', 'b', 0 };
FileStream cf(path, FileStream::MODE_READ);
std::map<std::string, CCD_Section> Sections;
std::string linebuf;
std::string cur_section_name;
std::string dir_path, file_base, file_ext;
char img_extsd[4] = { 'i', 'm', 'g', 0 };
char sub_extsd[4] = { 's', 'u', 'b', 0 };
MDFN_GetFilePathComponents(path, &dir_path, &file_base, &file_ext);
MDFN_GetFilePathComponents(path, &dir_path, &file_base, &file_ext);
if(file_ext.length() == 4 && file_ext[0] == '.')
{
signed char extupt[3] = { -1, -1, -1 };
for(int i = 1; i < 4; i++)
{
if(file_ext[i] >= 'A' && file_ext[i] <= 'Z')
extupt[i - 1] = 'A' - 'a';
else if(file_ext[i] >= 'a' && file_ext[i] <= 'z')
extupt[i - 1] = 0;
}
signed char av = -1;
for(int i = 0; i < 3; i++)
{
if(extupt[i] != -1)
av = extupt[i];
else
extupt[i] = av;
}
if(av == -1)
av = 0;
for(int i = 0; i < 3; i++)
{
if(extupt[i] == -1)
extupt[i] = av;
}
for(int i = 0; i < 3; i++)
{
img_extsd[i] += extupt[i];
sub_extsd[i] += extupt[i];
}
}
//printf("%s %d %d %d\n", file_ext.c_str(), extupt[0], extupt[1], extupt[2]);
linebuf.reserve(256);
while(cf.get_line(linebuf) >= 0)
{
MDFN_trim(linebuf);
if(linebuf.length() == 0) // Skip blank lines.
continue;
if(linebuf[0] == '[')
{
if(linebuf.length() < 3 || linebuf[linebuf.length() - 1] != ']')
throw MDFN_Error(0, _("Malformed section specifier: %s"), linebuf.c_str());
cur_section_name = linebuf.substr(1, linebuf.length() - 2);
MDFN_strtoupper(cur_section_name);
}
else
{
const size_t feqpos = linebuf.find('=');
const size_t leqpos = linebuf.rfind('=');
std::string k, v;
if(feqpos == std::string::npos || feqpos != leqpos)
throw MDFN_Error(0, _("Malformed value pair specifier: %s"), linebuf.c_str());
k = linebuf.substr(0, feqpos);
v = linebuf.substr(feqpos + 1);
MDFN_trim(k);
MDFN_trim(v);
MDFN_strtoupper(k);
Sections[cur_section_name][k] = v;
}
}
{
CCD_Section& ds = Sections["DISC"];
unsigned toc_entries = CCD_ReadInt<unsigned>(ds, "TOCENTRIES");
unsigned num_sessions = CCD_ReadInt<unsigned>(ds, "SESSIONS");
bool data_tracks_scrambled = CCD_ReadInt<unsigned>(ds, "DATATRACKSSCRAMBLED");
if(num_sessions != 1)
throw MDFN_Error(0, _("Unsupported number of sessions: %u"), num_sessions);
if(data_tracks_scrambled)
throw MDFN_Error(0, _("Scrambled CCD data tracks currently not supported."));
//printf("MOO: %d\n", toc_entries);
for(unsigned te = 0; te < toc_entries; te++)
{
char tmpbuf[64];
snprintf(tmpbuf, sizeof(tmpbuf), "ENTRY %u", te);
CCD_Section& ts = Sections[std::string(tmpbuf)];
unsigned session = CCD_ReadInt<unsigned>(ts, "SESSION");
uint8 point = CCD_ReadInt<uint8>(ts, "POINT");
uint8 adr = CCD_ReadInt<uint8>(ts, "ADR");
uint8 control = CCD_ReadInt<uint8>(ts, "CONTROL");
uint8 pmin = CCD_ReadInt<uint8>(ts, "PMIN");
uint8 psec = CCD_ReadInt<uint8>(ts, "PSEC");
uint8 pframe = CCD_ReadInt<uint8>(ts, "PFRAME");
signed plba = CCD_ReadInt<signed>(ts, "PLBA");
if(session != 1)
throw MDFN_Error(0, "Unsupported TOC entry Session value: %u", session);
// Reference: ECMA-394, page 5-14
switch(point)
if(file_ext.length() == 4 && file_ext[0] == '.')
{
default:
throw MDFN_Error(0, "Unsupported TOC entry Point value: %u", point);
signed char extupt[3] = { -1, -1, -1 };
case 0xA0:
tocd.first_track = pmin;
tocd.disc_type = psec;
break;
for(int i = 1; i < 4; i++)
{
if(file_ext[i] >= 'A' && file_ext[i] <= 'Z')
extupt[i - 1] = 'A' - 'a';
else if(file_ext[i] >= 'a' && file_ext[i] <= 'z')
extupt[i - 1] = 0;
}
case 0xA1:
tocd.last_track = pmin;
break;
signed char av = -1;
for(int i = 0; i < 3; i++)
{
if(extupt[i] != -1)
av = extupt[i];
else
extupt[i] = av;
}
case 0xA2:
tocd.tracks[100].adr = adr;
tocd.tracks[100].control = control;
tocd.tracks[100].lba = plba;
break;
if(av == -1)
av = 0;
case 99:
case 98:
case 97:
case 96:
case 95:
case 94:
case 93:
case 92:
case 91:
case 90:
case 89:
case 88:
case 87:
case 86:
case 85:
case 84:
case 83:
case 82:
case 81:
case 80:
case 79:
case 78:
case 77:
case 76:
case 75:
case 74:
case 73:
case 72:
case 71:
case 70:
case 69:
case 68:
case 67:
case 66:
case 65:
case 64:
case 63:
case 62:
case 61:
case 60:
case 59:
case 58:
case 57:
case 56:
case 55:
case 54:
case 53:
case 52:
case 51:
case 50:
case 49:
case 48:
case 47:
case 46:
case 45:
case 44:
case 43:
case 42:
case 41:
case 40:
case 39:
case 38:
case 37:
case 36:
case 35:
case 34:
case 33:
case 32:
case 31:
case 30:
case 29:
case 28:
case 27:
case 26:
case 25:
case 24:
case 23:
case 22:
case 21:
case 20:
case 19:
case 18:
case 17:
case 16:
case 15:
case 14:
case 13:
case 12:
case 11:
case 10:
case 9:
case 8:
case 7:
case 6:
case 5:
case 4:
case 3:
case 2:
case 1:
tocd.tracks[point].adr = adr;
tocd.tracks[point].control = control;
tocd.tracks[point].lba = plba;
break;
for(int i = 0; i < 3; i++)
{
if(extupt[i] == -1)
extupt[i] = av;
}
for(int i = 0; i < 3; i++)
{
img_extsd[i] += extupt[i];
sub_extsd[i] += extupt[i];
}
}
}
}
// Convenience leadout track duplication.
if(tocd.last_track < 99)
tocd.tracks[tocd.last_track + 1] = tocd.tracks[100];
//printf("%s %d %d %d\n", file_ext.c_str(), extupt[0], extupt[1], extupt[2]);
//
// Open image stream.
{
std::string image_path = MDFN_EvalFIP(dir_path, file_base + std::string(".") + std::string(img_extsd), true);
linebuf.reserve(256);
if(image_memcache)
{
img_stream = new MemoryStream(new FileStream(image_path.c_str(), FileStream::MODE_READ));
}
else
{
img_stream = new FileStream(image_path.c_str(), FileStream::MODE_READ);
}
while(cf.get_line(linebuf) >= 0)
{
MDFN_trim(linebuf);
int64 ss = img_stream->size();
if(linebuf.length() == 0) // Skip blank lines.
continue;
if(ss % 2352)
throw MDFN_Error(0, _("CCD image size is not evenly divisible by 2352."));
if(linebuf[0] == '[')
{
if(linebuf.length() < 3 || linebuf[linebuf.length() - 1] != ']')
throw MDFN_Error(0, _("Malformed section specifier: %s"), linebuf.c_str());
img_numsectors = ss / 2352;
}
cur_section_name = linebuf.substr(1, linebuf.length() - 2);
MDFN_strtoupper(cur_section_name);
}
else
{
const size_t feqpos = linebuf.find('=');
const size_t leqpos = linebuf.rfind('=');
std::string k, v;
//
// Open subchannel stream
{
std::string sub_path = MDFN_EvalFIP(dir_path, file_base + std::string(".") + std::string(sub_extsd), true);
if(feqpos == std::string::npos || feqpos != leqpos)
throw MDFN_Error(0, _("Malformed value pair specifier: %s"), linebuf.c_str());
if(image_memcache)
sub_stream = new MemoryStream(new FileStream(sub_path.c_str(), FileStream::MODE_READ));
else
sub_stream = new FileStream(sub_path.c_str(), FileStream::MODE_READ);
k = linebuf.substr(0, feqpos);
v = linebuf.substr(feqpos + 1);
if(sub_stream->size() != (int64)img_numsectors * 96)
throw MDFN_Error(0, _("CCD SUB file size mismatch."));
}
MDFN_trim(k);
MDFN_trim(v);
CheckSubQSanity();
MDFN_strtoupper(k);
Sections[cur_section_name][k] = v;
}
}
{
CCD_Section& ds = Sections["DISC"];
unsigned toc_entries = CCD_ReadInt<unsigned>(ds, "TOCENTRIES");
unsigned num_sessions = CCD_ReadInt<unsigned>(ds, "SESSIONS");
bool data_tracks_scrambled = CCD_ReadInt<unsigned>(ds, "DATATRACKSSCRAMBLED");
if(num_sessions != 1)
throw MDFN_Error(0, _("Unsupported number of sessions: %u"), num_sessions);
if(data_tracks_scrambled)
throw MDFN_Error(0, _("Scrambled CCD data tracks currently not supported."));
//printf("MOO: %d\n", toc_entries);
for(unsigned te = 0; te < toc_entries; te++)
{
char tmpbuf[64];
snprintf(tmpbuf, sizeof(tmpbuf), "ENTRY %u", te);
CCD_Section& ts = Sections[std::string(tmpbuf)];
unsigned session = CCD_ReadInt<unsigned>(ts, "SESSION");
uint8 point = CCD_ReadInt<uint8>(ts, "POINT");
uint8 adr = CCD_ReadInt<uint8>(ts, "ADR");
uint8 control = CCD_ReadInt<uint8>(ts, "CONTROL");
uint8 pmin = CCD_ReadInt<uint8>(ts, "PMIN");
uint8 psec = CCD_ReadInt<uint8>(ts, "PSEC");
uint8 pframe = CCD_ReadInt<uint8>(ts, "PFRAME");
signed plba = CCD_ReadInt<signed>(ts, "PLBA");
if(session != 1)
throw MDFN_Error(0, "Unsupported TOC entry Session value: %u", session);
// Reference: ECMA-394, page 5-14
if (point >= 1 && point <= 99)
{
tocd.tracks[point].adr = adr;
tocd.tracks[point].control = control;
tocd.tracks[point].lba = plba;
}
else
switch(point)
{
default:
throw MDFN_Error(0, "Unsupported TOC entry Point value: %u", point);
case 0xA0:
tocd.first_track = pmin;
tocd.disc_type = psec;
break;
case 0xA1:
tocd.last_track = pmin;
break;
case 0xA2:
tocd.tracks[100].adr = adr;
tocd.tracks[100].control = control;
tocd.tracks[100].lba = plba;
break;
}
}
}
// Convenience leadout track duplication.
if(tocd.last_track < 99)
tocd.tracks[tocd.last_track + 1] = tocd.tracks[100];
//
// Open image stream.
{
std::string image_path = MDFN_EvalFIP(dir_path, file_base + std::string(".") + std::string(img_extsd), true);
FileStream *str = new FileStream(image_path.c_str(), FileStream::MODE_READ);
if(image_memcache)
img_stream = new MemoryStream(str);
else
img_stream = str;
int64 ss = img_stream->size();
if(ss % 2352)
throw MDFN_Error(0, _("CCD image size is not evenly divisible by 2352."));
img_numsectors = ss / 2352;
}
{
// Open subchannel stream
std::string sub_path = MDFN_EvalFIP(dir_path, file_base + std::string(".") + std::string(sub_extsd), true);
if(image_memcache)
sub_stream = new MemoryStream(new FileStream(sub_path.c_str(), FileStream::MODE_READ));
else
sub_stream = new FileStream(sub_path.c_str(), FileStream::MODE_READ);
if(sub_stream->size() != (int64)img_numsectors * 96)
throw MDFN_Error(0, _("CCD SUB file size mismatch."));
}
CheckSubQSanity();
}
//
@ -389,113 +283,112 @@ case 1:
//
void CDAccess_CCD::CheckSubQSanity(void)
{
size_t checksum_pass_counter = 0;
int prev_lba = INT_MAX;
uint8 prev_track = 0;
size_t checksum_pass_counter = 0;
int prev_lba = INT_MAX;
uint8 prev_track = 0;
for(size_t s = 0; s < img_numsectors; s++)
{
union
{
uint8 full[96];
struct
for(size_t s = 0; s < img_numsectors; s++)
{
uint8 pbuf[12];
uint8 qbuf[12];
};
} buf;
union
{
uint8 full[96];
struct
{
uint8 pbuf[12];
uint8 qbuf[12];
};
} buf;
sub_stream->seek(s * 96, SEEK_SET);
sub_stream->read(buf.full, 96);
sub_stream->seek(s * 96, SEEK_SET);
sub_stream->read(buf.full, 96);
if(subq_check_checksum(buf.qbuf))
{
uint8 adr = buf.qbuf[0] & 0xF;
if(subq_check_checksum(buf.qbuf))
{
uint8 adr = buf.qbuf[0] & 0xF;
if(adr == 0x01)
{
uint8 track_bcd = buf.qbuf[1];
uint8 index_bcd = buf.qbuf[2];
uint8 rm_bcd = buf.qbuf[3];
uint8 rs_bcd = buf.qbuf[4];
uint8 rf_bcd = buf.qbuf[5];
uint8 am_bcd = buf.qbuf[7];
uint8 as_bcd = buf.qbuf[8];
uint8 af_bcd = buf.qbuf[9];
if(adr == 0x01)
{
uint8 track_bcd = buf.qbuf[1];
uint8 index_bcd = buf.qbuf[2];
uint8 rm_bcd = buf.qbuf[3];
uint8 rs_bcd = buf.qbuf[4];
uint8 rf_bcd = buf.qbuf[5];
uint8 am_bcd = buf.qbuf[7];
uint8 as_bcd = buf.qbuf[8];
uint8 af_bcd = buf.qbuf[9];
//printf("%2x %2x %2x\n", am_bcd, as_bcd, af_bcd);
//printf("%2x %2x %2x\n", am_bcd, as_bcd, af_bcd);
if(!BCD_is_valid(track_bcd) || !BCD_is_valid(index_bcd) || !BCD_is_valid(rm_bcd) || !BCD_is_valid(rs_bcd) || !BCD_is_valid(rf_bcd) ||
!BCD_is_valid(am_bcd) || !BCD_is_valid(as_bcd) || !BCD_is_valid(af_bcd) ||
rs_bcd > 0x59 || rf_bcd > 0x74 || as_bcd > 0x59 || af_bcd > 0x74)
{
throw MDFN_Error(0, _("Garbage subchannel Q data detected(bad BCD/out of range): %02x:%02x:%02x %02x:%02x:%02x"), rm_bcd, rs_bcd, rf_bcd, am_bcd, as_bcd, af_bcd);
}
else
{
int lba = ((BCD_to_U8(am_bcd) * 60 + BCD_to_U8(as_bcd)) * 75 + BCD_to_U8(af_bcd)) - 150;
uint8 track = BCD_to_U8(track_bcd);
if(!BCD_is_valid(track_bcd) || !BCD_is_valid(index_bcd) || !BCD_is_valid(rm_bcd) || !BCD_is_valid(rs_bcd) || !BCD_is_valid(rf_bcd) ||
!BCD_is_valid(am_bcd) || !BCD_is_valid(as_bcd) || !BCD_is_valid(af_bcd) ||
rs_bcd > 0x59 || rf_bcd > 0x74 || as_bcd > 0x59 || af_bcd > 0x74)
{
throw MDFN_Error(0, _("Garbage subchannel Q data detected(bad BCD/out of range): %02x:%02x:%02x %02x:%02x:%02x"), rm_bcd, rs_bcd, rf_bcd, am_bcd, as_bcd, af_bcd);
}
else
{
int lba = ((BCD_to_U8(am_bcd) * 60 + BCD_to_U8(as_bcd)) * 75 + BCD_to_U8(af_bcd)) - 150;
uint8 track = BCD_to_U8(track_bcd);
prev_lba = lba;
prev_lba = lba;
if(track < prev_track)
throw MDFN_Error(0, _("Garbage subchannel Q data detected(bad track number)"));
//else if(prev_track && track - pre
if(track < prev_track)
throw MDFN_Error(0, _("Garbage subchannel Q data detected(bad track number)"));
//else if(prev_track && track - pre
prev_track = track;
}
checksum_pass_counter++;
prev_track = track;
}
checksum_pass_counter++;
}
}
}
}
}
//printf("%u/%u\n", checksum_pass_counter, img_numsectors);
//printf("%u/%u\n", checksum_pass_counter, img_numsectors);
}
void CDAccess_CCD::Cleanup(void)
{
if(img_stream)
{
delete img_stream;
img_stream = NULL;
}
if(img_stream)
{
delete img_stream;
img_stream = NULL;
}
if(sub_stream)
{
delete sub_stream;
sub_stream = NULL;
}
if(sub_stream)
{
delete sub_stream;
sub_stream = NULL;
}
}
CDAccess_CCD::~CDAccess_CCD()
{
Cleanup();
Cleanup();
}
void CDAccess_CCD::Read_Raw_Sector(uint8 *buf, int32 lba)
{
if(lba < 0 || (size_t)lba >= img_numsectors)
throw(MDFN_Error(0, _("LBA out of range.")));
if(lba < 0 || (size_t)lba >= img_numsectors)
throw(MDFN_Error(0, _("LBA out of range.")));
uint8 sub_buf[96];
uint8 sub_buf[96];
img_stream->seek(lba * 2352, SEEK_SET);
img_stream->read(buf, 2352);
img_stream->seek(lba * 2352, SEEK_SET);
img_stream->read(buf, 2352);
sub_stream->seek(lba * 96, SEEK_SET);
sub_stream->read(sub_buf, 96);
sub_stream->seek(lba * 96, SEEK_SET);
sub_stream->read(sub_buf, 96);
subpw_interleave(sub_buf, buf + 2352);
subpw_interleave(sub_buf, buf + 2352);
}
void CDAccess_CCD::Read_TOC(CDUtility::TOC *toc)
void CDAccess_CCD::Read_TOC(TOC *toc)
{
*toc = tocd;
*toc = tocd;
}
void CDAccess_CCD::Eject(bool eject_status)
{
}

View File

@ -33,7 +33,7 @@ class CDAccess_CCD : public CDAccess
virtual void Read_Raw_Sector(uint8 *buf, int32 lba);
virtual void Read_TOC(CDUtility::TOC *toc);
virtual void Read_TOC(TOC *toc);
virtual void Eject(bool eject_status);
@ -47,7 +47,7 @@ class CDAccess_CCD : public CDAccess
Stream* img_stream;
Stream* sub_stream;
size_t img_numsectors;
CDUtility::TOC tocd;
TOC tocd;
};
#endif

View File

@ -54,8 +54,6 @@ extern retro_log_printf_t log_cb;
#include <map>
using namespace CDUtility;
enum
{
CDRF_SUBM_NONE = 0,

View File

@ -31,33 +31,6 @@ struct CDRFILE_TRACK_INFO
AudioReader *AReader;
};
#if 0
struct Medium_Chunk
{
int64 Offset; // Offset in [..TODO..]
uint32 DIFormat;
FILE *fp;
bool FirstFileInstance;
bool RawAudioMSBFirst;
unsigned int SubchannelMode;
uint32 LastSamplePos;
AudioReader *AReader;
};
struct CD_Chunk
{
int32 LBA;
int32 Track;
int32 Index;
bool DataType;
Medium_Chunk Medium;
};
static std::vector<CD_Chunk> Chunks;
#endif
class CDAccess_Image : public CDAccess
{
@ -68,7 +41,7 @@ class CDAccess_Image : public CDAccess
virtual void Read_Raw_Sector(uint8 *buf, int32 lba);
virtual void Read_TOC(CDUtility::TOC *toc);
virtual void Read_TOC(TOC *toc);
virtual void Eject(bool eject_status);
private:

View File

@ -23,44 +23,39 @@
#include "lec.h"
#include <assert.h>
// Kill_LEC_Correct();
namespace CDUtility
{
// lookup table for crc calculation
static uint16 subq_crctab[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108,
0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210,
0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B,
0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401,
0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE,
0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6,
0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D,
0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5,
0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC,
0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4,
0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD,
0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13,
0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A,
0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E,
0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1,
0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB,
0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0,
0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8,
0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657,
0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9,
0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882,
0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E,
0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07,
0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D,
0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74,
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108,
0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210,
0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B,
0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401,
0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE,
0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6,
0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D,
0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5,
0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC,
0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4,
0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD,
0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13,
0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A,
0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E,
0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1,
0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB,
0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0,
0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8,
0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657,
0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9,
0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882,
0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E,
0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07,
0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D,
0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74,
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
@ -70,163 +65,159 @@ static bool CDUtility_Inited = false;
static void InitScrambleTable(void)
{
unsigned cv = 1;
unsigned cv = 1;
for(unsigned i = 12; i < 2352; i++)
{
unsigned char z = 0;
for(unsigned i = 12; i < 2352; i++)
{
unsigned char z = 0;
for(int b = 0; b < 8; b++)
{
z |= (cv & 1) << b;
for(int b = 0; b < 8; b++)
{
z |= (cv & 1) << b;
int feedback = ((cv >> 1) & 1) ^ (cv & 1);
cv = (cv >> 1) | (feedback << 14);
}
int feedback = ((cv >> 1) & 1) ^ (cv & 1);
cv = (cv >> 1) | (feedback << 14);
}
scramble_table[i - 12] = z;
}
scramble_table[i - 12] = z;
}
//for(int i = 0; i < 2352 - 12; i++)
// printf("0x%02x, ", scramble_table[i]);
//for(int i = 0; i < 2352 - 12; i++)
// printf("0x%02x, ", scramble_table[i]);
}
void CDUtility_Init(void)
{
if(!CDUtility_Inited)
{
Init_LEC_Correct();
if(!CDUtility_Inited)
{
Init_LEC_Correct();
InitScrambleTable();
InitScrambleTable();
CDUtility_Inited = true;
}
CDUtility_Inited = true;
}
}
void encode_mode0_sector(uint32 aba, uint8 *sector_data)
{
CDUtility_Init();
CDUtility_Init();
lec_encode_mode0_sector(aba, sector_data);
lec_encode_mode0_sector(aba, sector_data);
}
void encode_mode1_sector(uint32 aba, uint8 *sector_data)
{
CDUtility_Init();
CDUtility_Init();
lec_encode_mode1_sector(aba, sector_data);
lec_encode_mode1_sector(aba, sector_data);
}
void encode_mode2_sector(uint32 aba, uint8 *sector_data)
{
CDUtility_Init();
CDUtility_Init();
lec_encode_mode2_sector(aba, sector_data);
lec_encode_mode2_sector(aba, sector_data);
}
void encode_mode2_form1_sector(uint32 aba, uint8 *sector_data)
{
CDUtility_Init();
CDUtility_Init();
lec_encode_mode2_form1_sector(aba, sector_data);
lec_encode_mode2_form1_sector(aba, sector_data);
}
void encode_mode2_form2_sector(uint32 aba, uint8 *sector_data)
{
CDUtility_Init();
CDUtility_Init();
lec_encode_mode2_form2_sector(aba, sector_data);
lec_encode_mode2_form2_sector(aba, sector_data);
}
bool edc_check(const uint8 *sector_data, bool xa)
{
CDUtility_Init();
CDUtility_Init();
return(CheckEDC(sector_data, xa));
return(CheckEDC(sector_data, xa));
}
bool edc_lec_check_and_correct(uint8 *sector_data, bool xa)
{
CDUtility_Init();
CDUtility_Init();
return(ValidateRawSector(sector_data, xa));
return(ValidateRawSector(sector_data, xa));
}
bool subq_check_checksum(const uint8 *SubQBuf)
{
uint16 crc = 0;
uint16 stored_crc = 0;
uint16 crc = 0;
uint16 stored_crc = 0;
stored_crc = SubQBuf[0xA] << 8;
stored_crc |= SubQBuf[0xB];
stored_crc = SubQBuf[0xA] << 8;
stored_crc |= SubQBuf[0xB];
for(int i = 0; i < 0xA; i++)
crc = subq_crctab[(crc >> 8) ^ SubQBuf[i]] ^ (crc << 8);
for(int i = 0; i < 0xA; i++)
crc = subq_crctab[(crc >> 8) ^ SubQBuf[i]] ^ (crc << 8);
crc = ~crc;
crc = ~crc;
return(crc == stored_crc);
return(crc == stored_crc);
}
void subq_generate_checksum(uint8 *buf)
{
uint16 crc = 0;
uint16 crc = 0;
for(int i = 0; i < 0xA; i++)
crc = subq_crctab[(crc >> 8) ^ buf[i]] ^ (crc << 8);
for(int i = 0; i < 0xA; i++)
crc = subq_crctab[(crc >> 8) ^ buf[i]] ^ (crc << 8);
// Checksum
buf[0xa] = ~(crc >> 8);
buf[0xb] = ~(crc);
// Checksum
buf[0xa] = ~(crc >> 8);
buf[0xb] = ~(crc);
}
void subq_deinterleave(const uint8 *SubPWBuf, uint8 *qbuf)
{
memset(qbuf, 0, 0xC);
memset(qbuf, 0, 0xC);
for(int i = 0; i < 96; i++)
{
qbuf[i >> 3] |= ((SubPWBuf[i] >> 6) & 0x1) << (7 - (i & 0x7));
}
for(int i = 0; i < 96; i++)
qbuf[i >> 3] |= ((SubPWBuf[i] >> 6) & 0x1) << (7 - (i & 0x7));
}
// Deinterleaves 96 bytes of subchannel P-W data from 96 bytes of interleaved subchannel PW data.
void subpw_deinterleave(const uint8 *in_buf, uint8 *out_buf)
{
assert(in_buf != out_buf);
assert(in_buf != out_buf);
memset(out_buf, 0, 96);
memset(out_buf, 0, 96);
for(unsigned ch = 0; ch < 8; ch++)
{
for(unsigned i = 0; i < 96; i++)
{
out_buf[(ch * 12) + (i >> 3)] |= ((in_buf[i] >> (7 - ch)) & 0x1) << (7 - (i & 0x7));
}
}
for(unsigned ch = 0; ch < 8; ch++)
{
for(unsigned i = 0; i < 96; i++)
out_buf[(ch * 12) + (i >> 3)] |= ((in_buf[i] >> (7 - ch)) & 0x1) << (7 - (i & 0x7));
}
}
// Interleaves 96 bytes of subchannel P-W data from 96 bytes of uninterleaved subchannel PW data.
void subpw_interleave(const uint8 *in_buf, uint8 *out_buf)
{
assert(in_buf != out_buf);
assert(in_buf != out_buf);
for(unsigned d = 0; d < 12; d++)
{
for(unsigned bitpoodle = 0; bitpoodle < 8; bitpoodle++)
{
uint8 rawb = 0;
for(unsigned ch = 0; ch < 8; ch++)
for(unsigned d = 0; d < 12; d++)
{
rawb |= ((in_buf[ch * 12 + d] >> (7 - bitpoodle)) & 1) << (7 - ch);
for(unsigned bitpoodle = 0; bitpoodle < 8; bitpoodle++)
{
uint8 rawb = 0;
for(unsigned ch = 0; ch < 8; ch++)
{
rawb |= ((in_buf[ch * 12 + d] >> (7 - bitpoodle)) & 1) << (7 - ch);
}
out_buf[(d << 3) + bitpoodle] = rawb;
}
}
out_buf[(d << 3) + bitpoodle] = rawb;
}
}
}
// NOTES ON LEADOUT AREA SYNTHESIS
@ -237,99 +228,85 @@ void subpw_interleave(const uint8 *in_buf, uint8 *out_buf)
//
void subpw_synth_leadout_lba(const TOC& toc, const int32 lba, uint8* SubPWBuf)
{
uint8 buf[0xC];
uint32 lba_relative;
uint32 ma, sa, fa;
uint32 m, s, f;
uint8 buf[0xC];
uint32 lba_relative;
uint32 ma, sa, fa;
uint32 m, s, f;
lba_relative = lba - toc.tracks[100].lba;
lba_relative = lba - toc.tracks[100].lba;
f = (lba_relative % 75);
s = ((lba_relative / 75) % 60);
m = (lba_relative / 75 / 60);
f = (lba_relative % 75);
s = ((lba_relative / 75) % 60);
m = (lba_relative / 75 / 60);
fa = (lba + 150) % 75;
sa = ((lba + 150) / 75) % 60;
ma = ((lba + 150) / 75 / 60);
fa = (lba + 150) % 75;
sa = ((lba + 150) / 75) % 60;
ma = ((lba + 150) / 75 / 60);
uint8 adr = 0x1; // Q channel data encodes position
uint8 control = (toc.tracks[toc.last_track].control & 0x4) | toc.tracks[100].control;
uint8 adr = 0x1; // Q channel data encodes position
uint8 control = (toc.tracks[toc.last_track].control & 0x4) | toc.tracks[100].control;
memset(buf, 0, 0xC);
buf[0] = (adr << 0) | (control << 4);
buf[1] = 0xAA;
buf[2] = 0x01;
memset(buf, 0, 0xC);
buf[0] = (adr << 0) | (control << 4);
buf[1] = 0xAA;
buf[2] = 0x01;
// Track relative MSF address
buf[3] = U8_to_BCD(m);
buf[4] = U8_to_BCD(s);
buf[5] = U8_to_BCD(f);
// Track relative MSF address
buf[3] = U8_to_BCD(m);
buf[4] = U8_to_BCD(s);
buf[5] = U8_to_BCD(f);
buf[6] = 0; // Zerroooo
buf[6] = 0; // Zerroooo
// Absolute MSF address
buf[7] = U8_to_BCD(ma);
buf[8] = U8_to_BCD(sa);
buf[9] = U8_to_BCD(fa);
// Absolute MSF address
buf[7] = U8_to_BCD(ma);
buf[8] = U8_to_BCD(sa);
buf[9] = U8_to_BCD(fa);
subq_generate_checksum(buf);
subq_generate_checksum(buf);
for(int i = 0; i < 96; i++)
SubPWBuf[i] = (((buf[i >> 3] >> (7 - (i & 0x7))) & 1) ? 0x40 : 0x00) | 0x80;
for(int i = 0; i < 96; i++)
SubPWBuf[i] = (((buf[i >> 3] >> (7 - (i & 0x7))) & 1) ? 0x40 : 0x00) | 0x80;
}
void synth_leadout_sector_lba(const uint8 mode, const TOC& toc, const int32 lba, uint8* out_buf)
{
memset(out_buf, 0, 2352 + 96);
subpw_synth_leadout_lba(toc, lba, out_buf + 2352);
memset(out_buf, 0, 2352 + 96);
subpw_synth_leadout_lba(toc, lba, out_buf + 2352);
if((toc.tracks[toc.last_track].control | toc.tracks[100].control) & 0x4)
{
switch(mode)
{
default:
encode_mode0_sector(LBA_to_ABA(lba), out_buf);
break;
if((toc.tracks[toc.last_track].control | toc.tracks[100].control) & 0x4)
{
switch(mode)
{
default:
encode_mode0_sector(LBA_to_ABA(lba), out_buf);
break;
case 0x01:
encode_mode1_sector(LBA_to_ABA(lba), out_buf);
break;
case 0x01:
encode_mode1_sector(LBA_to_ABA(lba), out_buf);
break;
case 0x02:
out_buf[18] = 0x20;
encode_mode2_form2_sector(LBA_to_ABA(lba), out_buf);
break;
}
}
case 0x02:
out_buf[18] = 0x20;
encode_mode2_form2_sector(LBA_to_ABA(lba), out_buf);
break;
}
}
}
#if 0
bool subq_extrapolate(const uint8 *subq_input, int32 position_delta, uint8 *subq_output)
{
assert(subq_check_checksum(subq_input));
subq_generate_checksum(subq_output);
}
#endif
void scrambleize_data_sector(uint8 *sector_data)
{
for(unsigned i = 12; i < 2352; i++)
sector_data[i] ^= scramble_table[i - 12];
}
for(unsigned i = 12; i < 2352; i++)
sector_data[i] ^= scramble_table[i - 12];
}
void MDFN_strtoupper(char *str)
{
for(size_t x = 0; str[x]; x++)
{
if(str[x] >= 'a' && str[x] <= 'z')
{
str[x] = str[x] - 'a' + 'A';
}
}
for(size_t x = 0; str[x]; x++)
{
if(str[x] >= 'a' && str[x] <= 'z')
str[x] = str[x] - 'a' + 'A';
}
}
void MDFN_strtoupper(std::string &str)
@ -339,8 +316,6 @@ void MDFN_strtoupper(std::string &str)
for(size_t x = 0; x < len; x++)
{
if(str[x] >= 'a' && str[x] <= 'z')
{
str[x] = str[x] - 'a' + 'A';
}
}
}

View File

@ -1,227 +1,224 @@
#ifndef __MDFN_CDROM_CDUTILITY_H
#define __MDFN_CDROM_CDUTILITY_H
namespace CDUtility
// Call once at app startup before creating any threads that could potentially cause re-entrancy to these functions.
// It will also be called automatically if needed for the first time a function in this namespace that requires
// the initialization function to be called is called, for potential
// usage in constructors of statically-declared objects.
void CDUtility_Init(void);
// Quick definitions here:
//
// ABA - Absolute block address, synonymous to absolute MSF
// aba = (m_a * 60 * 75) + (s_a * 75) + f_a
//
// LBA - Logical block address(related: data CDs are required to have a pregap of 2 seconds, IE 150 frames/sectors)
// lba = aba - 150
enum
{
// Call once at app startup before creating any threads that could potentially cause re-entrancy to these functions.
// It will also be called automatically if needed for the first time a function in this namespace that requires
// the initialization function to be called is called, for potential
// usage in constructors of statically-declared objects.
void CDUtility_Init(void);
// Quick definitions here:
//
// ABA - Absolute block address, synonymous to absolute MSF
// aba = (m_a * 60 * 75) + (s_a * 75) + f_a
//
// LBA - Logical block address(related: data CDs are required to have a pregap of 2 seconds, IE 150 frames/sectors)
// lba = aba - 150
ADR_NOQINFO = 0x00,
ADR_CURPOS = 0x01,
ADR_MCN = 0x02,
ADR_ISRC = 0x03
};
enum
{
ADR_NOQINFO = 0x00,
ADR_CURPOS = 0x01,
ADR_MCN = 0x02,
ADR_ISRC = 0x03
};
struct TOC_Track
{
uint8 adr;
uint8 control;
uint32 lba;
};
// SubQ control field flags.
enum
{
SUBQ_CTRLF_PRE = 0x01, // With 50/15us pre-emphasis.
SUBQ_CTRLF_DCP = 0x02, // Digital copy permitted.
SUBQ_CTRLF_DATA = 0x04, // Data track.
SUBQ_CTRLF_4CH = 0x08, // 4-channel CD-DA.
};
struct TOC_Track
{
uint8 adr;
uint8 control;
uint32 lba;
};
enum
{
DISC_TYPE_CDDA_OR_M1 = 0x00,
DISC_TYPE_CD_I = 0x10,
DISC_TYPE_CD_XA = 0x20
};
// SubQ control field flags.
enum
{
SUBQ_CTRLF_PRE = 0x01, // With 50/15us pre-emphasis.
SUBQ_CTRLF_DCP = 0x02, // Digital copy permitted.
SUBQ_CTRLF_DATA = 0x04, // Data track.
SUBQ_CTRLF_4CH = 0x08, // 4-channel CD-DA.
};
enum
{
DISC_TYPE_CDDA_OR_M1 = 0x00,
DISC_TYPE_CD_I = 0x10,
DISC_TYPE_CD_XA = 0x20
};
struct TOC
{
INLINE TOC()
{
Clear();
}
INLINE void Clear(void)
{
first_track = last_track = 0;
disc_type = 0;
memset(tracks, 0, sizeof(tracks)); // FIXME if we change TOC_Track to non-POD type.
}
INLINE int FindTrackByLBA(uint32 LBA)
{
for(int32 track = first_track; track <= (last_track + 1); track++)
struct TOC
{
INLINE TOC()
{
if(track == (last_track + 1))
{
if(LBA < tracks[100].lba)
return(track - 1);
}
else
{
if(LBA < tracks[track].lba)
return(track - 1);
}
Clear();
}
return(0);
}
uint8 first_track;
uint8 last_track;
uint8 disc_type;
TOC_Track tracks[100 + 1]; // [0] is unused, [100] is for the leadout track.
// Also, for convenience, tracks[last_track + 1] will always refer
// to the leadout track(even if last_track < 99, IE the leadout track details are duplicated).
};
INLINE void Clear(void)
{
first_track = last_track = 0;
disc_type = 0;
//
// Address conversion functions.
//
static INLINE uint32 AMSF_to_ABA(int32 m_a, int32 s_a, int32 f_a)
{
return(f_a + 75 * s_a + 75 * 60 * m_a);
}
memset(tracks, 0, sizeof(tracks)); // FIXME if we change TOC_Track to non-POD type.
}
static INLINE void ABA_to_AMSF(uint32 aba, uint8 *m_a, uint8 *s_a, uint8 *f_a)
{
*m_a = aba / 75 / 60;
*s_a = (aba - *m_a * 75 * 60) / 75;
*f_a = aba - (*m_a * 75 * 60) - (*s_a * 75);
}
INLINE int FindTrackByLBA(uint32 LBA)
{
for(int32 track = first_track; track <= (last_track + 1); track++)
{
if(track == (last_track + 1))
{
if(LBA < tracks[100].lba)
return(track - 1);
}
else
{
if(LBA < tracks[track].lba)
return(track - 1);
}
}
return(0);
}
static INLINE int32 ABA_to_LBA(uint32 aba)
{
return(aba - 150);
}
uint8 first_track;
uint8 last_track;
uint8 disc_type;
TOC_Track tracks[100 + 1]; // [0] is unused, [100] is for the leadout track.
// Also, for convenience, tracks[last_track + 1] will always refer
// to the leadout track(even if last_track < 99, IE the leadout track details are duplicated).
};
static INLINE uint32 LBA_to_ABA(int32 lba)
{
return(lba + 150);
}
static INLINE int32 AMSF_to_LBA(uint8 m_a, uint8 s_a, uint8 f_a)
{
return(ABA_to_LBA(AMSF_to_ABA(m_a, s_a, f_a)));
}
static INLINE void LBA_to_AMSF(int32 lba, uint8 *m_a, uint8 *s_a, uint8 *f_a)
{
ABA_to_AMSF(LBA_to_ABA(lba), m_a, s_a, f_a);
}
//
// BCD conversion functions
//
static INLINE bool BCD_is_valid(uint8 bcd_number)
{
if((bcd_number & 0xF0) >= 0xA0)
return(false);
if((bcd_number & 0x0F) >= 0x0A)
return(false);
return(true);
}
static INLINE uint8 BCD_to_U8(uint8 bcd_number)
{
return( ((bcd_number >> 4) * 10) + (bcd_number & 0x0F) );
}
static INLINE uint8 U8_to_BCD(uint8 num)
{
return( ((num / 10) << 4) + (num % 10) );
}
// should always perform the conversion, even if the bcd number is invalid.
static INLINE bool BCD_to_U8_check(uint8 bcd_number, uint8 *out_number)
{
*out_number = BCD_to_U8(bcd_number);
if(!BCD_is_valid(bcd_number))
return(false);
return(true);
}
//
// Sector data encoding functions(to full 2352 bytes raw sector).
//
// sector_data must be able to contain at least 2352 bytes.
void encode_mode0_sector(uint32 aba, uint8 *sector_data);
void encode_mode1_sector(uint32 aba, uint8 *sector_data); // 2048 bytes of user data at offset 16
void encode_mode2_sector(uint32 aba, uint8 *sector_data); // 2336 bytes of user data at offset 16
void encode_mode2_form1_sector(uint32 aba, uint8 *sector_data); // 2048+8 bytes of user data at offset 16
void encode_mode2_form2_sector(uint32 aba, uint8 *sector_data); // 2324+8 bytes of user data at offset 16
// out_buf must be able to contain 2352+96 bytes.
// "mode" is only used if(toc.tracks[100].control & 0x4)
void synth_leadout_sector_lba(const uint8 mode, const TOC& toc, const int32 lba, uint8* out_buf);
//
// User data error detection and correction
//
// Check EDC of a mode 1 or mode 2 form 1 sector.
// Returns "true" if checksum is ok(matches).
// Returns "false" if checksum mismatch.
// sector_data should contain 2352 bytes of raw sector data.
bool edc_check(const uint8 *sector_data, bool xa);
// Check EDC and L-EC data of a mode 1 or mode 2 form 1 sector, and correct bit errors if any exist.
// Returns "true" if errors weren't detected, or they were corrected succesfully.
// Returns "false" if errors couldn't be corrected.
// sector_data should contain 2352 bytes of raw sector data.
bool edc_lec_check_and_correct(uint8 *sector_data, bool xa);
//
// Subchannel(Q in particular) functions
//
// Returns false on checksum mismatch, true on match.
bool subq_check_checksum(const uint8 *subq_buf);
// Calculates the checksum of Q subchannel data(not including the checksum bytes of course ;)) from subq_buf, and stores it into the appropriate position
// in subq_buf.
void subq_generate_checksum(uint8 *subq_buf);
// Deinterleaves 12 bytes of subchannel Q data from 96 bytes of interleaved subchannel PW data.
void subq_deinterleave(const uint8 *subpw_buf, uint8 *subq_buf);
// Deinterleaves 96 bytes of subchannel P-W data from 96 bytes of interleaved subchannel PW data.
void subpw_deinterleave(const uint8 *in_buf, uint8 *out_buf);
// Interleaves 96 bytes of subchannel P-W data from 96 bytes of uninterleaved subchannel PW data.
void subpw_interleave(const uint8 *in_buf, uint8 *out_buf);
// Extrapolates Q subchannel current position data from subq_input, with frame/sector delta position_delta, and writes to subq_output.
// Only valid for ADR_CURPOS.
// subq_input must pass subq_check_checksum().
// TODO
//void subq_extrapolate(const uint8 *subq_input, int32 position_delta, uint8 *subq_output);
// (De)Scrambles data sector.
void scrambleize_data_sector(uint8 *sector_data);
//
// Address conversion functions.
//
static INLINE uint32 AMSF_to_ABA(int32 m_a, int32 s_a, int32 f_a)
{
return(f_a + 75 * s_a + 75 * 60 * m_a);
}
static INLINE void ABA_to_AMSF(uint32 aba, uint8 *m_a, uint8 *s_a, uint8 *f_a)
{
*m_a = aba / 75 / 60;
*s_a = (aba - *m_a * 75 * 60) / 75;
*f_a = aba - (*m_a * 75 * 60) - (*s_a * 75);
}
static INLINE int32 ABA_to_LBA(uint32 aba)
{
return(aba - 150);
}
static INLINE uint32 LBA_to_ABA(int32 lba)
{
return(lba + 150);
}
static INLINE int32 AMSF_to_LBA(uint8 m_a, uint8 s_a, uint8 f_a)
{
return(ABA_to_LBA(AMSF_to_ABA(m_a, s_a, f_a)));
}
static INLINE void LBA_to_AMSF(int32 lba, uint8 *m_a, uint8 *s_a, uint8 *f_a)
{
ABA_to_AMSF(LBA_to_ABA(lba), m_a, s_a, f_a);
}
//
// BCD conversion functions
//
static INLINE bool BCD_is_valid(uint8 bcd_number)
{
if((bcd_number & 0xF0) >= 0xA0)
return(false);
if((bcd_number & 0x0F) >= 0x0A)
return(false);
return(true);
}
static INLINE uint8 BCD_to_U8(uint8 bcd_number)
{
return( ((bcd_number >> 4) * 10) + (bcd_number & 0x0F) );
}
static INLINE uint8 U8_to_BCD(uint8 num)
{
return( ((num / 10) << 4) + (num % 10) );
}
// should always perform the conversion, even if the bcd number is invalid.
static INLINE bool BCD_to_U8_check(uint8 bcd_number, uint8 *out_number)
{
*out_number = BCD_to_U8(bcd_number);
if(!BCD_is_valid(bcd_number))
return(false);
return(true);
}
//
// Sector data encoding functions(to full 2352 bytes raw sector).
//
// sector_data must be able to contain at least 2352 bytes.
void encode_mode0_sector(uint32 aba, uint8 *sector_data);
void encode_mode1_sector(uint32 aba, uint8 *sector_data); // 2048 bytes of user data at offset 16
void encode_mode2_sector(uint32 aba, uint8 *sector_data); // 2336 bytes of user data at offset 16
void encode_mode2_form1_sector(uint32 aba, uint8 *sector_data); // 2048+8 bytes of user data at offset 16
void encode_mode2_form2_sector(uint32 aba, uint8 *sector_data); // 2324+8 bytes of user data at offset 16
// out_buf must be able to contain 2352+96 bytes.
// "mode" is only used if(toc.tracks[100].control & 0x4)
void synth_leadout_sector_lba(const uint8 mode, const TOC& toc, const int32 lba, uint8* out_buf);
//
// User data error detection and correction
//
// Check EDC of a mode 1 or mode 2 form 1 sector.
// Returns "true" if checksum is ok(matches).
// Returns "false" if checksum mismatch.
// sector_data should contain 2352 bytes of raw sector data.
bool edc_check(const uint8 *sector_data, bool xa);
// Check EDC and L-EC data of a mode 1 or mode 2 form 1 sector, and correct bit errors if any exist.
// Returns "true" if errors weren't detected, or they were corrected succesfully.
// Returns "false" if errors couldn't be corrected.
// sector_data should contain 2352 bytes of raw sector data.
bool edc_lec_check_and_correct(uint8 *sector_data, bool xa);
//
// Subchannel(Q in particular) functions
//
// Returns false on checksum mismatch, true on match.
bool subq_check_checksum(const uint8 *subq_buf);
// Calculates the checksum of Q subchannel data(not including the checksum bytes of course ;)) from subq_buf, and stores it into the appropriate position
// in subq_buf.
void subq_generate_checksum(uint8 *subq_buf);
// Deinterleaves 12 bytes of subchannel Q data from 96 bytes of interleaved subchannel PW data.
void subq_deinterleave(const uint8 *subpw_buf, uint8 *subq_buf);
// Deinterleaves 96 bytes of subchannel P-W data from 96 bytes of interleaved subchannel PW data.
void subpw_deinterleave(const uint8 *in_buf, uint8 *out_buf);
// Interleaves 96 bytes of subchannel P-W data from 96 bytes of uninterleaved subchannel PW data.
void subpw_interleave(const uint8 *in_buf, uint8 *out_buf);
// Extrapolates Q subchannel current position data from subq_input, with frame/sector delta position_delta, and writes to subq_output.
// Only valid for ADR_CURPOS.
// subq_input must pass subq_check_checksum().
// TODO
//void subq_extrapolate(const uint8 *subq_input, int32 position_delta, uint8 *subq_output);
// (De)Scrambles data sector.
void scrambleize_data_sector(uint8 *sector_data);
void MDFN_strtoupper(std::string &str);
void MDFN_strtoupper(char *str);

View File

@ -27,8 +27,6 @@
extern retro_log_printf_t log_cb;
using namespace CDUtility;
enum
{
// Status/Error messages

View File

@ -23,7 +23,7 @@
#include <queue>
typedef CDUtility::TOC CD_TOC;
typedef TOC CD_TOC;
class CDIF
{
@ -32,7 +32,7 @@ class CDIF
CDIF();
virtual ~CDIF();
inline void ReadTOC(CDUtility::TOC *read_target)
inline void ReadTOC(TOC *read_target)
{
*read_target = disc_toc;
}
@ -61,7 +61,7 @@ class CDIF
protected:
bool UnrecoverableError;
bool is_phys_cache;
CDUtility::TOC disc_toc;
TOC disc_toc;
bool DiscEjected;
};

View File

@ -33,13 +33,13 @@
static inline int mod_fieldmax(int x)
{
while (x >= GF_FIELDMAX)
{
x -= GF_FIELDMAX;
x = (x >> GF_SYMBOLSIZE) + (x & GF_FIELDMAX);
}
while (x >= GF_FIELDMAX)
{
x -= GF_FIELDMAX;
x = (x >> GF_SYMBOLSIZE) + (x & GF_FIELDMAX);
}
return x;
return x;
}
#endif

View File

@ -36,11 +36,10 @@
/* Initialize the Galois field tables */
GaloisTables* CreateGaloisTables(int32 gf_generator)
{
GaloisTables *gt = (GaloisTables *)calloc(1, sizeof(GaloisTables));
{
int32 b,log;
GaloisTables *gt = (GaloisTables *)calloc(1, sizeof(GaloisTables));
/* Allocate the tables.
The encoder uses a special version of alpha_to which has the mod_fieldmax()
@ -51,7 +50,7 @@ GaloisTables* CreateGaloisTables(int32 gf_generator)
gt->indexOf = (int32 *)calloc(GF_FIELDSIZE, sizeof(int32));
gt->alphaTo = (int32 *)calloc(GF_FIELDSIZE, sizeof(int32));
gt->encAlphaTo = (int32 *)calloc(2*GF_FIELDSIZE, sizeof(int32));
/* create the log/ilog values */
for(b=1, log=0; log<GF_FIELDMAX; log++)
@ -59,13 +58,13 @@ GaloisTables* CreateGaloisTables(int32 gf_generator)
gt->alphaTo[log] = b;
b = b << 1;
if(b & GF_FIELDSIZE)
b = b ^ gf_generator;
b = b ^ gf_generator;
}
if(b!=1)
{
printf("Failed to create the Galois field log tables!\n");
exit(1);
printf("Failed to create the Galois field log tables!\n");
exit(1);
}
/* we're even closed using infinity (makes things easier) */
@ -74,18 +73,21 @@ GaloisTables* CreateGaloisTables(int32 gf_generator)
gt->alphaTo[GF_ALPHA0] = 0; /* and the other way around */
for(b=0; b<2*GF_FIELDSIZE; b++)
gt->encAlphaTo[b] = gt->alphaTo[mod_fieldmax(b)];
gt->encAlphaTo[b] = gt->alphaTo[mod_fieldmax(b)];
return gt;
}
void FreeGaloisTables(GaloisTables *gt)
{
if(gt->indexOf) free(gt->indexOf);
if(gt->alphaTo) free(gt->alphaTo);
if(gt->encAlphaTo) free(gt->encAlphaTo);
if(gt->indexOf)
free(gt->indexOf);
if(gt->alphaTo)
free(gt->alphaTo);
if(gt->encAlphaTo)
free(gt->encAlphaTo);
free(gt);
free(gt);
}
/***
@ -94,10 +96,11 @@ void FreeGaloisTables(GaloisTables *gt)
*/
ReedSolomonTables *CreateReedSolomonTables(GaloisTables *gt,
int32 first_consecutive_root,
int32 prim_elem,
int nroots_in)
{ ReedSolomonTables *rt = (ReedSolomonTables *)calloc(1, sizeof(ReedSolomonTables));
int32 first_consecutive_root,
int32 prim_elem,
int nroots_in)
{
ReedSolomonTables *rt = (ReedSolomonTables *)calloc(1, sizeof(ReedSolomonTables));
int32 i,j,root;
rt->gfTables = gt;
@ -115,42 +118,31 @@ ReedSolomonTables *CreateReedSolomonTables(GaloisTables *gt,
for(i=0, root=first_consecutive_root*prim_elem; i<rt->nroots; i++, root+=prim_elem)
{ rt->gpoly[i+1] = 1;
/* Multiply gpoly by alpha**(root+x) */
/* Multiply gpoly by alpha**(root+x) */
for(j=i; j>0; j--)
{
if(rt->gpoly[j] != 0)
rt->gpoly[j] = rt->gpoly[j-1] ^ gt->alphaTo[mod_fieldmax(gt->indexOf[rt->gpoly[j]] + root)];
else
rt->gpoly[j] = rt->gpoly[j-1];
}
for(j=i; j>0; j--)
{
if(rt->gpoly[j] != 0)
rt->gpoly[j] = rt->gpoly[j-1] ^ gt->alphaTo[mod_fieldmax(gt->indexOf[rt->gpoly[j]] + root)];
else
rt->gpoly[j] = rt->gpoly[j-1];
}
rt->gpoly[0] = gt->alphaTo[mod_fieldmax(gt->indexOf[rt->gpoly[0]] + root)];
rt->gpoly[0] = gt->alphaTo[mod_fieldmax(gt->indexOf[rt->gpoly[0]] + root)];
}
/* Store the polynomials index for faster encoding */
for(i=0; i<=rt->nroots; i++)
rt->gpoly[i] = gt->indexOf[rt->gpoly[i]];
#if 0
/* for the precalculated unrolled loops only */
for(i=gt->nroots-1; i>0; i--)
PrintCLI(
" par_idx[((++spk)&%d)] ^= enc_alpha_to[feedback + %3d];\n",
nroots-1,gt->gpoly[i]);
PrintCLI(" par_idx[sp] = enc_alpha_to[feedback + %3d];\n",
gt->gpoly[0]);
#endif
rt->gpoly[i] = gt->indexOf[rt->gpoly[i]];
return rt;
}
void FreeReedSolomonTables(ReedSolomonTables *rt)
{
if(rt->gpoly) free(rt->gpoly);
if(rt->gpoly)
free(rt->gpoly);
free(rt);
free(rt);
}

View File

@ -243,18 +243,18 @@ int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
int corrected = 0;
int i,j,k;
int r,el;
/*** Form the syndromes: Evaluate data(x) at roots of g(x) */
for(i=0; i<NROOTS; i++)
syndrome[i] = data[0];
syndrome[i] = data[0];
for(j=1; j<shortened_size; j++)
for(i=0; i<NROOTS; i++)
if(syndrome[i] == 0)
syndrome[i] = data[j];
else syndrome[i] = data[j] ^ gt->alphaTo[mod_fieldmax(gt->indexOf[syndrome[i]]
+ (LEC_FIRST_ROOT+i)*LEC_PRIM_ELEM)];
for(i=0; i<NROOTS; i++)
if(syndrome[i] == 0)
syndrome[i] = data[j];
else syndrome[i] = data[j] ^ gt->alphaTo[mod_fieldmax(gt->indexOf[syndrome[i]]
+ (LEC_FIRST_ROOT+i)*LEC_PRIM_ELEM)];
/*** Convert syndrome to index form, check for nonzero condition. */
@ -267,7 +267,7 @@ int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
/*** If the syndrome is zero, everything is fine. */
if(!syn_error)
return 0;
return 0;
/*** Initialize lambda to be the erasure locator polynomial */
@ -278,7 +278,7 @@ int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
erasure_list[1] += padding;
if(erasure_count > 2) /* sanity check */
erasure_count = 0;
erasure_count = 0;
if(erasure_count > 0)
{ lambda[1] = gt->alphaTo[mod_fieldmax(LEC_PRIM_ELEM*(GF_FIELDMAX-1-erasure_list[0]))];
@ -287,17 +287,17 @@ int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
{ int u = mod_fieldmax(LEC_PRIM_ELEM*(GF_FIELDMAX-1-erasure_list[i]));
for(j=i+1; j>0; j--)
{ int tmp = gt->indexOf[lambda[j-1]];
{ int tmp = gt->indexOf[lambda[j-1]];
if(tmp != GF_ALPHA0)
lambda[j] ^= gt->alphaTo[mod_fieldmax(u + tmp)];
}
lambda[j] ^= gt->alphaTo[mod_fieldmax(u + tmp)];
}
}
}
for(i=0; i<NROOTS+1; i++)
b[i] = gt->indexOf[lambda[i]];
b[i] = gt->indexOf[lambda[i]];
/*** Berlekamp-Massey algorithm to determine error+erasure locator polynomial */
r = erasure_count; /* r is the step number */
@ -309,42 +309,42 @@ int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
{ int discr_r = 0;
for(i=0; i<r; i++)
if((lambda[i] != 0) && (syndrome[r-i-1] != GF_ALPHA0))
discr_r ^= gt->alphaTo[mod_fieldmax(gt->indexOf[lambda[i]] + syndrome[r-i-1])];
if((lambda[i] != 0) && (syndrome[r-i-1] != GF_ALPHA0))
discr_r ^= gt->alphaTo[mod_fieldmax(gt->indexOf[lambda[i]] + syndrome[r-i-1])];
discr_r = gt->indexOf[discr_r];
if(discr_r == GF_ALPHA0)
{ /* B(x) = x*B(x) */
memmove(b+1, b, NROOTS*sizeof(b[0]));
b[0] = GF_ALPHA0;
memmove(b+1, b, NROOTS*sizeof(b[0]));
b[0] = GF_ALPHA0;
}
else
{ int t[NROOTS+1];
/* T(x) = lambda(x) - discr_r*x*b(x) */
t[0] = lambda[0];
for(i=0; i<NROOTS; i++)
{ if(b[i] != GF_ALPHA0)
t[i+1] = lambda[i+1] ^ gt->alphaTo[mod_fieldmax(discr_r + b[i])];
else t[i+1] = lambda[i+1];
}
/* T(x) = lambda(x) - discr_r*x*b(x) */
t[0] = lambda[0];
for(i=0; i<NROOTS; i++)
{ if(b[i] != GF_ALPHA0)
t[i+1] = lambda[i+1] ^ gt->alphaTo[mod_fieldmax(discr_r + b[i])];
else t[i+1] = lambda[i+1];
}
if(2*el <= r+erasure_count-1)
{ el = r + erasure_count - el;
if(2*el <= r+erasure_count-1)
{ el = r + erasure_count - el;
/* B(x) <-- inv(discr_r) * lambda(x) */
for(i=0; i<=NROOTS; i++)
b[i] = (lambda[i] == 0) ? GF_ALPHA0
: mod_fieldmax(gt->indexOf[lambda[i]] - discr_r + GF_FIELDMAX);
}
else
{ /* 2 lines below: B(x) <-- x*B(x) */
memmove(b+1, b, NROOTS*sizeof(b[0]));
b[0] = GF_ALPHA0;
}
/* B(x) <-- inv(discr_r) * lambda(x) */
for(i=0; i<=NROOTS; i++)
b[i] = (lambda[i] == 0) ? GF_ALPHA0
: mod_fieldmax(gt->indexOf[lambda[i]] - discr_r + GF_FIELDMAX);
}
else
{ /* 2 lines below: B(x) <-- x*B(x) */
memmove(b+1, b, NROOTS*sizeof(b[0]));
b[0] = GF_ALPHA0;
}
memcpy(lambda, t, (NROOTS+1)*sizeof(t[0]));
memcpy(lambda, t, (NROOTS+1)*sizeof(t[0]));
}
}
@ -354,7 +354,7 @@ int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
for(i=0; i<NROOTS+1; i++)
{ lambda[i] = gt->indexOf[lambda[i]];
if(lambda[i] != GF_ALPHA0)
deg_lambda = i;
deg_lambda = i;
}
/*** Find roots of the error+erasure locator polynomial by Chien search */
@ -367,9 +367,9 @@ int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
for(j=deg_lambda; j>0; j--)
{ if(reg[j] != GF_ALPHA0)
{ reg[j] = mod_fieldmax(reg[j] + j);
q ^= gt->alphaTo[reg[j]];
}
{ reg[j] = mod_fieldmax(reg[j] + j);
q ^= gt->alphaTo[reg[j]];
}
}
if(q != 0) continue; /* Not a root */
@ -401,7 +401,7 @@ int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
for(j=i; j>=0; j--)
{ if((syndrome[i - j] != GF_ALPHA0) && (lambda[j] != GF_ALPHA0))
tmp ^= gt->alphaTo[mod_fieldmax(syndrome[i - j] + lambda[j])];
tmp ^= gt->alphaTo[mod_fieldmax(syndrome[i - j] + lambda[j])];
}
omega[i] = gt->indexOf[tmp];
@ -420,59 +420,54 @@ int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding,
for(i=deg_omega; i>=0; i--)
{ if(omega[i] != GF_ALPHA0)
num1 ^= gt->alphaTo[mod_fieldmax(omega[i] + i * root[j])];
num1 ^= gt->alphaTo[mod_fieldmax(omega[i] + i * root[j])];
}
num2 = gt->alphaTo[mod_fieldmax(root[j] * (LEC_FIRST_ROOT - 1) + GF_FIELDMAX)];
den = 0;
/* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
for(i=MIN(deg_lambda, NROOTS-1) & ~1; i>=0; i-=2)
{ if(lambda[i+1] != GF_ALPHA0)
den ^= gt->alphaTo[mod_fieldmax(lambda[i+1] + i * root[j])];
den ^= gt->alphaTo[mod_fieldmax(lambda[i+1] + i * root[j])];
}
/* Apply error to data */
if(num1 != 0 && location >= padding)
{
corrected++;
data[location-padding] ^= gt->alphaTo[mod_fieldmax(gt->indexOf[num1] + gt->indexOf[num2]
+ GF_FIELDMAX - gt->indexOf[den])];
corrected++;
data[location-padding] ^= gt->alphaTo[mod_fieldmax(gt->indexOf[num1] + gt->indexOf[num2]
+ GF_FIELDMAX - gt->indexOf[den])];
/* If no erasures were given, at most one error was corrected.
Return its position in erasure_list[0]. */
/* If no erasures were given, at most one error was corrected.
Return its position in erasure_list[0]. */
if(!erasure_count)
erasure_list[0] = location-padding;
if(!erasure_count)
erasure_list[0] = location-padding;
}
#if 1
else return -3;
#endif
else
return -3;
}
/*** Form the syndromes: Evaluate data(x) at roots of g(x) */
for(i=0; i<NROOTS; i++)
syndrome[i] = data[0];
syndrome[i] = data[0];
for(j=1; j<shortened_size; j++)
for(i=0; i<NROOTS; i++)
{ if(syndrome[i] == 0)
syndrome[i] = data[j];
else syndrome[i] = data[j] ^ gt->alphaTo[mod_fieldmax(gt->indexOf[syndrome[i]]
+ (LEC_FIRST_ROOT+i)*LEC_PRIM_ELEM)];
}
for(i=0; i<NROOTS; i++)
{ if(syndrome[i] == 0)
syndrome[i] = data[j];
else syndrome[i] = data[j] ^ gt->alphaTo[mod_fieldmax(gt->indexOf[syndrome[i]]
+ (LEC_FIRST_ROOT+i)*LEC_PRIM_ELEM)];
}
/*** Convert syndrome to index form, check for nonzero condition. */
#if 1
for(i=0; i<NROOTS; i++)
if(syndrome[i])
return -2;
#endif
if(syndrome[i])
return -2;
return corrected;
}

View File

@ -575,117 +575,25 @@ void lec_encode_mode2_form2_sector(u_int32_t adr, u_int8_t *sector)
*/
void lec_scramble(u_int8_t *sector)
{
u_int16_t i;
const u_int8_t *stable = SCRAMBLE_TABLE;
u_int8_t *p = sector;
u_int8_t tmp;
u_int16_t i;
const u_int8_t *stable = SCRAMBLE_TABLE;
u_int8_t *p = sector;
u_int8_t tmp;
for (i = 0; i < 6; i++) {
for (i = 0; i < 6; i++)
{
/* just swap bytes of sector sync */
tmp = *p;
*p = *(p + 1);
p++;
*p++ = tmp;
}
for (;i < (2352 / 2); i++) {
}
for (;i < (2352 / 2); i++) {
/* scramble and swap bytes */
tmp = *p ^ *stable++;
*p = *(p + 1) ^ *stable++;
p++;
*p++ = tmp;
}
}
}
#if 0
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char **argv)
{
char *infile;
char *outfile;
int fd_in, fd_out;
u_int8_t buffer1[2352];
u_int8_t buffer2[2352];
u_int32_t lba;
int i;
#if 0
for (i = 0; i < 2048; i++)
buffer1[i + 16] = 234;
lba = 150;
for (i = 0; i < 100000; i++) {
lec_encode_mode1_sector(lba, buffer1);
lec_scramble(buffer2);
lba++;
}
#else
if (argc != 3)
return 1;
infile = argv[1];
outfile = argv[2];
if ((fd_in = open(infile, O_RDONLY)) < 0) {
perror("Cannot open input file");
return 1;
}
if ((fd_out = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) {
perror("Cannot open output file");
return 1;
}
lba = 150;
do {
if (read(fd_in, buffer1, 2352) != 2352)
break;
switch (*(buffer1 + 12 + 3)) {
case 1:
memcpy(buffer2 + 16, buffer1 + 16, 2048);
lec_encode_mode1_sector(lba, buffer2);
break;
case 2:
if ((*(buffer1 + 12 + 4 + 2) & 0x20) != 0) {
/* form 2 sector */
memcpy(buffer2 + 16, buffer1 + 16, 2324 + 8);
lec_encode_mode2_form2_sector(lba, buffer2);
}
else {
/* form 1 sector */
memcpy(buffer2 + 16, buffer1 + 16, 2048 + 8);
lec_encode_mode2_form1_sector(lba, buffer2);
}
break;
}
if (memcmp(buffer1, buffer2, 2352) != 0) {
printf("Verify error at lba %ld\n", lba);
}
lec_scramble(buffer2);
write(fd_out, buffer2, 2352);
lba++;
} while (1);
close(fd_in);
close(fd_out);
#endif
return 0;
}
#endif

View File

@ -49,26 +49,24 @@ void Kill_LEC_Correct(void)
int CheckEDC(const unsigned char *cd_frame, bool xa_mode)
{
unsigned int expected_crc, real_crc;
unsigned int crc_base = xa_mode ? 2072 : 2064;
unsigned int expected_crc, real_crc;
unsigned int crc_base = xa_mode ? 2072 : 2064;
expected_crc = cd_frame[crc_base + 0] << 0;
expected_crc |= cd_frame[crc_base + 1] << 8;
expected_crc |= cd_frame[crc_base + 2] << 16;
expected_crc |= cd_frame[crc_base + 3] << 24;
expected_crc = cd_frame[crc_base + 0] << 0;
expected_crc |= cd_frame[crc_base + 1] << 8;
expected_crc |= cd_frame[crc_base + 2] << 16;
expected_crc |= cd_frame[crc_base + 3] << 24;
if(xa_mode)
real_crc = EDCCrc32(cd_frame+16, 2056);
else
real_crc = EDCCrc32(cd_frame, 2064);
if(xa_mode)
real_crc = EDCCrc32(cd_frame+16, 2056);
else
real_crc = EDCCrc32(cd_frame, 2064);
if(expected_crc == real_crc)
return(1);
else
{
//printf("Bad EDC CRC: Calculated: %08x, Recorded: %08x\n", real_crc, expected_crc);
return(0);
}
if(expected_crc == real_crc)
return(1);
//printf("Bad EDC CRC: Calculated: %08x, Recorded: %08x\n", real_crc, expected_crc);
return(0);
}
/***
@ -101,31 +99,34 @@ static int simple_lec(unsigned char *frame)
/* Perform Q-Parity error correction */
for(q=0; q<N_Q_VECTORS; q++)
{ int err;
{
int err;
/* We have no erasure information for Q vectors */
GetQVector(frame, q_vector, q);
err = DecodePQ(rt, q_vector, Q_PADDING, ignore, 0);
GetQVector(frame, q_vector, q);
err = DecodePQ(rt, q_vector, Q_PADDING, ignore, 0);
/* See what we've got */
/* See what we've got */
if(err < 0) /* Uncorrectable. Mark bytes are erasure. */
{ q_failures++;
FillQVector(byte_state, 1, q);
}
else /* Correctable */
{ if(err == 1 || err == 2) /* Store back corrected vector */
{ SetQVector(frame, q_vector, q);
q_corrected++;
}
}
if(err < 0) /* Uncorrectable. Mark bytes are erasure. */
{ q_failures++;
FillQVector(byte_state, 1, q);
}
else /* Correctable */
{
if(err == 1 || err == 2) /* Store back corrected vector */
{
SetQVector(frame, q_vector, q);
q_corrected++;
}
}
}
/* Perform P-Parity error correction */
for(p=0; p<N_P_VECTORS; p++)
{ int err,i;
{
int err,i;
/* Try error correction without erasure information */
@ -133,41 +134,41 @@ static int simple_lec(unsigned char *frame)
err = DecodePQ(rt, p_vector, P_PADDING, ignore, 0);
/* If unsuccessful, try again using erasures.
Erasure information is uncertain, so try this last. */
Erasure information is uncertain, so try this last. */
if(err < 0 || err > 2)
{ GetPVector(byte_state, p_state, p);
erasure_count = 0;
{
GetPVector(byte_state, p_state, p);
erasure_count = 0;
for(i=0; i<P_VECTOR_SIZE; i++)
if(p_state[i])
erasures[erasure_count++] = i;
for(i=0; i<P_VECTOR_SIZE; i++)
if(p_state[i])
erasures[erasure_count++] = i;
if(erasure_count > 0 && erasure_count <= 2)
{ GetPVector(frame, p_vector, p);
err = DecodePQ(rt, p_vector, P_PADDING, erasures, erasure_count);
}
if(erasure_count > 0 && erasure_count <= 2)
{
GetPVector(frame, p_vector, p);
err = DecodePQ(rt, p_vector, P_PADDING, erasures, erasure_count);
}
}
/* See what we've got */
if(err < 0) /* Uncorrectable. */
{ p_failures++;
}
p_failures++;
else /* Correctable. */
{ if(err == 1 || err == 2) /* Store back corrected vector */
{ SetPVector(frame, p_vector, p);
p_corrected++;
}
{
if(err == 1 || err == 2) /* Store back corrected vector */
{ SetPVector(frame, p_vector, p);
p_corrected++;
}
}
}
/* Sum up */
if(q_failures || p_failures || q_corrected || p_corrected)
{
return 1;
}
return 1;
return 0;
}
@ -178,26 +179,21 @@ static int simple_lec(unsigned char *frame)
int ValidateRawSector(unsigned char *frame, bool xaMode)
{
int lec_did_sth = FALSE;
int lec_did_sth = FALSE;
/* Do simple L-EC.
It seems that drives stop their internal L-EC as soon as the
EDC is okay, so we may see uncorrected errors in the parity bytes.
Since we are also interested in the user data only and doing the
L-EC is expensive, we skip our L-EC as well when the EDC is fine. */
/* Do simple L-EC.
It seems that drives stop their internal L-EC as soon as the
EDC is okay, so we may see uncorrected errors in the parity bytes.
Since we are also interested in the user data only and doing the
L-EC is expensive, we skip our L-EC as well when the EDC is fine. */
if(!CheckEDC(frame, xaMode))
{
lec_did_sth = simple_lec(frame);
}
/* Test internal sector checksum again */
if(!CheckEDC(frame, xaMode))
lec_did_sth = simple_lec(frame);
/* Test internal sector checksum again */
if(!CheckEDC(frame, xaMode))
{
/* EDC failure in RAW sector */
return FALSE;
}
if(!CheckEDC(frame, xaMode))
return FALSE;
return TRUE;
return TRUE;
}

View File

@ -52,8 +52,6 @@
#include "cdc.h"
#include "spu.h"
using namespace CDUtility;
PS_CDC::PS_CDC() : DMABuffer(4096)
{
IsPSXDisc = false;

View File

@ -181,7 +181,7 @@ class PS_CDC
int32_t lastts;
CDUtility::TOC toc;
TOC toc;
bool IsPSXDisc;
uint8 DiscID[4];